Anand Shukla
6 months ago
2575 changed files with 282312 additions and 0 deletions
@ -0,0 +1,167 @@ |
|||||||
|
{ |
||||||
|
"info": { |
||||||
|
"_postman_id": "7bb9858f-4bd4-4869-b69b-62ba97ad8392", |
||||||
|
"name": "GraphQL Authentications", |
||||||
|
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", |
||||||
|
"_exporter_id": "29186461" |
||||||
|
}, |
||||||
|
"item": [ |
||||||
|
{ |
||||||
|
"name": "Full Read", |
||||||
|
"request": { |
||||||
|
"method": "POST", |
||||||
|
"header": [ |
||||||
|
{ |
||||||
|
"key": "Authorization", |
||||||
|
"value": "Basic YWRtaW46YWRtaW4=" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"key": "Content-Type", |
||||||
|
"value": "application/json" |
||||||
|
} |
||||||
|
], |
||||||
|
"body": { |
||||||
|
"mode": "graphql", |
||||||
|
"graphql": { |
||||||
|
"query": "query MyQuery($offset: Int, $limit: Int, $order: String, $domain: [[Any]]) {\n ResPartner(\n offset: $offset\n limit: $limit\n order: $order\n domain: $domain\n )\n {\n id\n name\n phone\n email\n is_company\n country_id{\n name\n code\n }\n user_id{\n name\n active\n }\n company_id{\n name\n }\n }\n}\n", |
||||||
|
"variables": "{\n \"offset\": 0,\n \"limit\": 5,\n \"order\": \"name,id desc\",\n \"domain\": [[\"is_company\",\"=\",true]]\n}\n" |
||||||
|
} |
||||||
|
}, |
||||||
|
"url": { |
||||||
|
"raw": "http://192.168.1.15:8016/gqlapi", |
||||||
|
"protocol": "http", |
||||||
|
"host": [ |
||||||
|
"192", |
||||||
|
"168", |
||||||
|
"1", |
||||||
|
"15" |
||||||
|
], |
||||||
|
"port": "8016", |
||||||
|
"path": [ |
||||||
|
"gqlapi" |
||||||
|
] |
||||||
|
} |
||||||
|
}, |
||||||
|
"response": [] |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "Auth API Key", |
||||||
|
"request": { |
||||||
|
"method": "POST", |
||||||
|
"header": [ |
||||||
|
{ |
||||||
|
"key": "x-api-key", |
||||||
|
"value": "nZ(xta#/(uh#DN,Ce\"=U`iA(y|5Fd]b&" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"key": "Content-Type", |
||||||
|
"value": "application/json" |
||||||
|
} |
||||||
|
], |
||||||
|
"body": { |
||||||
|
"mode": "graphql", |
||||||
|
"graphql": { |
||||||
|
"query": "query MyQuery($offset: Int, $limit: Int, $order: String, $domain: [[Any]]) {\n ResPartner(\n offset: $offset\n limit: $limit\n order: $order\n domain: $domain\n )\n {\n id\n name\n phone\n email\n is_company\n country_id{\n name\n code\n }\n user_id{\n name\n active\n }\n company_id{\n name\n }\n }\n}\n", |
||||||
|
"variables": "{\n \"offset\": 0,\n \"limit\": 5,\n \"order\": \"name,id desc\",\n \"domain\": [[\"is_company\",\"=\",true]]\n}\n" |
||||||
|
} |
||||||
|
}, |
||||||
|
"url": { |
||||||
|
"raw": "http://192.168.1.15:8016/gqlkey", |
||||||
|
"protocol": "http", |
||||||
|
"host": [ |
||||||
|
"192", |
||||||
|
"168", |
||||||
|
"1", |
||||||
|
"15" |
||||||
|
], |
||||||
|
"port": "8016", |
||||||
|
"path": [ |
||||||
|
"gqlkey" |
||||||
|
] |
||||||
|
} |
||||||
|
}, |
||||||
|
"response": [] |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "Auth User", |
||||||
|
"request": { |
||||||
|
"method": "POST", |
||||||
|
"header": [ |
||||||
|
{ |
||||||
|
"key": "Content-Type", |
||||||
|
"value": "application/json" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"key": "username", |
||||||
|
"value": "admin" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"key": "password", |
||||||
|
"value": "admin", |
||||||
|
"type": "text" |
||||||
|
} |
||||||
|
], |
||||||
|
"body": { |
||||||
|
"mode": "graphql", |
||||||
|
"graphql": { |
||||||
|
"query": "query MyQuery($offset: Int, $limit: Int, $order: String, $domain: [[Any]]) {\n ResPartner(\n offset: $offset\n limit: $limit\n order: $order\n domain: $domain\n )\n {\n id\n name\n phone\n email\n is_company\n country_id{\n name\n code\n }\n user_id{\n name\n active\n }\n company_id{\n name\n }\n }\n}\n", |
||||||
|
"variables": "{\n \"offset\": 0,\n \"limit\": 5,\n \"order\": \"name,id desc\",\n \"domain\": [[\"is_company\",\"=\",true]]\n}\n" |
||||||
|
} |
||||||
|
}, |
||||||
|
"url": { |
||||||
|
"raw": "http://192.168.1.15:8016/gqluser", |
||||||
|
"protocol": "http", |
||||||
|
"host": [ |
||||||
|
"192", |
||||||
|
"168", |
||||||
|
"1", |
||||||
|
"15" |
||||||
|
], |
||||||
|
"port": "8016", |
||||||
|
"path": [ |
||||||
|
"gqluser" |
||||||
|
] |
||||||
|
} |
||||||
|
}, |
||||||
|
"response": [] |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "Auth Basic", |
||||||
|
"request": { |
||||||
|
"method": "POST", |
||||||
|
"header": [ |
||||||
|
{ |
||||||
|
"key": "Authorization", |
||||||
|
"value": "Basic YWRtaW46YWRtaW4=" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"key": "Content-Type", |
||||||
|
"value": "application/json" |
||||||
|
} |
||||||
|
], |
||||||
|
"body": { |
||||||
|
"mode": "graphql", |
||||||
|
"graphql": { |
||||||
|
"query": "query MyQuery($offset: Int, $limit: Int, $order: String, $domain: [[Any]]) {\n ResPartner(\n offset: $offset\n limit: $limit\n order: $order\n domain: $domain\n )\n {\n id\n name\n phone\n email\n is_company\n country_id{\n name\n code\n }\n user_id{\n name\n active\n }\n company_id{\n name\n }\n }\n}\n", |
||||||
|
"variables": "{\n \"offset\": 0,\n \"limit\": 5,\n \"order\": \"name,id desc\",\n \"domain\": [[\"is_company\",\"=\",true]]\n}\n" |
||||||
|
} |
||||||
|
}, |
||||||
|
"url": { |
||||||
|
"raw": "http://192.168.1.15:8016/gqlapi", |
||||||
|
"protocol": "http", |
||||||
|
"host": [ |
||||||
|
"192", |
||||||
|
"168", |
||||||
|
"1", |
||||||
|
"15" |
||||||
|
], |
||||||
|
"port": "8016", |
||||||
|
"path": [ |
||||||
|
"gqlapi" |
||||||
|
] |
||||||
|
} |
||||||
|
}, |
||||||
|
"response": [] |
||||||
|
} |
||||||
|
] |
||||||
|
} |
@ -0,0 +1,34 @@ |
|||||||
|
<!DOCTYPE html> |
||||||
|
<html lang="en"> |
||||||
|
<head> |
||||||
|
<meta charset="UTF-8"> |
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
||||||
|
<title>GraphQL Subscription</title> |
||||||
|
</head> |
||||||
|
<body> |
||||||
|
<h1>GraphQL Subscription Response</h1> |
||||||
|
<div id="response"></div> |
||||||
|
|
||||||
|
<script> |
||||||
|
const ws = new WebSocket(`ws://${location.host}`); |
||||||
|
|
||||||
|
ws.onmessage = (event) => { |
||||||
|
const data = JSON.parse(event.data); |
||||||
|
const responseDiv = document.getElementById('response'); |
||||||
|
responseDiv.innerHTML = JSON.stringify(data, null, 2); |
||||||
|
}; |
||||||
|
|
||||||
|
ws.onopen = () => { |
||||||
|
console.log('WebSocket connection opened'); |
||||||
|
}; |
||||||
|
|
||||||
|
ws.onclose = () => { |
||||||
|
console.log('WebSocket connection closed'); |
||||||
|
}; |
||||||
|
|
||||||
|
ws.onerror = (error) => { |
||||||
|
console.error('WebSocket error:', error); |
||||||
|
}; |
||||||
|
</script> |
||||||
|
</body> |
||||||
|
</html> |
@ -0,0 +1 @@ |
|||||||
|
../mime/cli.js |
@ -0,0 +1,726 @@ |
|||||||
|
{ |
||||||
|
"name": "graphql-express-app", |
||||||
|
"version": "1.0.0", |
||||||
|
"lockfileVersion": 3, |
||||||
|
"requires": true, |
||||||
|
"packages": { |
||||||
|
"node_modules/accepts": { |
||||||
|
"version": "1.3.8", |
||||||
|
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", |
||||||
|
"integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", |
||||||
|
"dependencies": { |
||||||
|
"mime-types": "~2.1.34", |
||||||
|
"negotiator": "0.6.3" |
||||||
|
}, |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.6" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/array-flatten": { |
||||||
|
"version": "1.1.1", |
||||||
|
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", |
||||||
|
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" |
||||||
|
}, |
||||||
|
"node_modules/body-parser": { |
||||||
|
"version": "1.20.2", |
||||||
|
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", |
||||||
|
"integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", |
||||||
|
"dependencies": { |
||||||
|
"bytes": "3.1.2", |
||||||
|
"content-type": "~1.0.5", |
||||||
|
"debug": "2.6.9", |
||||||
|
"depd": "2.0.0", |
||||||
|
"destroy": "1.2.0", |
||||||
|
"http-errors": "2.0.0", |
||||||
|
"iconv-lite": "0.4.24", |
||||||
|
"on-finished": "2.4.1", |
||||||
|
"qs": "6.11.0", |
||||||
|
"raw-body": "2.5.2", |
||||||
|
"type-is": "~1.6.18", |
||||||
|
"unpipe": "1.0.0" |
||||||
|
}, |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.8", |
||||||
|
"npm": "1.2.8000 || >= 1.4.16" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/bytes": { |
||||||
|
"version": "3.1.2", |
||||||
|
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", |
||||||
|
"integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.8" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/call-bind": { |
||||||
|
"version": "1.0.7", |
||||||
|
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", |
||||||
|
"integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", |
||||||
|
"dependencies": { |
||||||
|
"es-define-property": "^1.0.0", |
||||||
|
"es-errors": "^1.3.0", |
||||||
|
"function-bind": "^1.1.2", |
||||||
|
"get-intrinsic": "^1.2.4", |
||||||
|
"set-function-length": "^1.2.1" |
||||||
|
}, |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.4" |
||||||
|
}, |
||||||
|
"funding": { |
||||||
|
"url": "https://github.com/sponsors/ljharb" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/content-disposition": { |
||||||
|
"version": "0.5.4", |
||||||
|
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", |
||||||
|
"integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", |
||||||
|
"dependencies": { |
||||||
|
"safe-buffer": "5.2.1" |
||||||
|
}, |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.6" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/content-type": { |
||||||
|
"version": "1.0.5", |
||||||
|
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", |
||||||
|
"integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.6" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/cookie": { |
||||||
|
"version": "0.6.0", |
||||||
|
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", |
||||||
|
"integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.6" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/cookie-signature": { |
||||||
|
"version": "1.0.6", |
||||||
|
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", |
||||||
|
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" |
||||||
|
}, |
||||||
|
"node_modules/debug": { |
||||||
|
"version": "2.6.9", |
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", |
||||||
|
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", |
||||||
|
"dependencies": { |
||||||
|
"ms": "2.0.0" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/define-data-property": { |
||||||
|
"version": "1.1.4", |
||||||
|
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", |
||||||
|
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", |
||||||
|
"dependencies": { |
||||||
|
"es-define-property": "^1.0.0", |
||||||
|
"es-errors": "^1.3.0", |
||||||
|
"gopd": "^1.0.1" |
||||||
|
}, |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.4" |
||||||
|
}, |
||||||
|
"funding": { |
||||||
|
"url": "https://github.com/sponsors/ljharb" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/depd": { |
||||||
|
"version": "2.0.0", |
||||||
|
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", |
||||||
|
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.8" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/destroy": { |
||||||
|
"version": "1.2.0", |
||||||
|
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", |
||||||
|
"integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.8", |
||||||
|
"npm": "1.2.8000 || >= 1.4.16" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/ee-first": { |
||||||
|
"version": "1.1.1", |
||||||
|
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", |
||||||
|
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" |
||||||
|
}, |
||||||
|
"node_modules/encodeurl": { |
||||||
|
"version": "1.0.2", |
||||||
|
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", |
||||||
|
"integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.8" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/es-define-property": { |
||||||
|
"version": "1.0.0", |
||||||
|
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", |
||||||
|
"integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", |
||||||
|
"dependencies": { |
||||||
|
"get-intrinsic": "^1.2.4" |
||||||
|
}, |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.4" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/es-errors": { |
||||||
|
"version": "1.3.0", |
||||||
|
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", |
||||||
|
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.4" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/escape-html": { |
||||||
|
"version": "1.0.3", |
||||||
|
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", |
||||||
|
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" |
||||||
|
}, |
||||||
|
"node_modules/etag": { |
||||||
|
"version": "1.8.1", |
||||||
|
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", |
||||||
|
"integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.6" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/express": { |
||||||
|
"version": "4.19.2", |
||||||
|
"resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", |
||||||
|
"integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", |
||||||
|
"dependencies": { |
||||||
|
"accepts": "~1.3.8", |
||||||
|
"array-flatten": "1.1.1", |
||||||
|
"body-parser": "1.20.2", |
||||||
|
"content-disposition": "0.5.4", |
||||||
|
"content-type": "~1.0.4", |
||||||
|
"cookie": "0.6.0", |
||||||
|
"cookie-signature": "1.0.6", |
||||||
|
"debug": "2.6.9", |
||||||
|
"depd": "2.0.0", |
||||||
|
"encodeurl": "~1.0.2", |
||||||
|
"escape-html": "~1.0.3", |
||||||
|
"etag": "~1.8.1", |
||||||
|
"finalhandler": "1.2.0", |
||||||
|
"fresh": "0.5.2", |
||||||
|
"http-errors": "2.0.0", |
||||||
|
"merge-descriptors": "1.0.1", |
||||||
|
"methods": "~1.1.2", |
||||||
|
"on-finished": "2.4.1", |
||||||
|
"parseurl": "~1.3.3", |
||||||
|
"path-to-regexp": "0.1.7", |
||||||
|
"proxy-addr": "~2.0.7", |
||||||
|
"qs": "6.11.0", |
||||||
|
"range-parser": "~1.2.1", |
||||||
|
"safe-buffer": "5.2.1", |
||||||
|
"send": "0.18.0", |
||||||
|
"serve-static": "1.15.0", |
||||||
|
"setprototypeof": "1.2.0", |
||||||
|
"statuses": "2.0.1", |
||||||
|
"type-is": "~1.6.18", |
||||||
|
"utils-merge": "1.0.1", |
||||||
|
"vary": "~1.1.2" |
||||||
|
}, |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.10.0" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/finalhandler": { |
||||||
|
"version": "1.2.0", |
||||||
|
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", |
||||||
|
"integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", |
||||||
|
"dependencies": { |
||||||
|
"debug": "2.6.9", |
||||||
|
"encodeurl": "~1.0.2", |
||||||
|
"escape-html": "~1.0.3", |
||||||
|
"on-finished": "2.4.1", |
||||||
|
"parseurl": "~1.3.3", |
||||||
|
"statuses": "2.0.1", |
||||||
|
"unpipe": "~1.0.0" |
||||||
|
}, |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.8" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/forwarded": { |
||||||
|
"version": "0.2.0", |
||||||
|
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", |
||||||
|
"integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.6" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/fresh": { |
||||||
|
"version": "0.5.2", |
||||||
|
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", |
||||||
|
"integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.6" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/function-bind": { |
||||||
|
"version": "1.1.2", |
||||||
|
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", |
||||||
|
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", |
||||||
|
"funding": { |
||||||
|
"url": "https://github.com/sponsors/ljharb" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/get-intrinsic": { |
||||||
|
"version": "1.2.4", |
||||||
|
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", |
||||||
|
"integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", |
||||||
|
"dependencies": { |
||||||
|
"es-errors": "^1.3.0", |
||||||
|
"function-bind": "^1.1.2", |
||||||
|
"has-proto": "^1.0.1", |
||||||
|
"has-symbols": "^1.0.3", |
||||||
|
"hasown": "^2.0.0" |
||||||
|
}, |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.4" |
||||||
|
}, |
||||||
|
"funding": { |
||||||
|
"url": "https://github.com/sponsors/ljharb" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/gopd": { |
||||||
|
"version": "1.0.1", |
||||||
|
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", |
||||||
|
"integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", |
||||||
|
"dependencies": { |
||||||
|
"get-intrinsic": "^1.1.3" |
||||||
|
}, |
||||||
|
"funding": { |
||||||
|
"url": "https://github.com/sponsors/ljharb" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/graphql": { |
||||||
|
"version": "16.8.1", |
||||||
|
"resolved": "https://registry.npmjs.org/graphql/-/graphql-16.8.1.tgz", |
||||||
|
"integrity": "sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==", |
||||||
|
"peer": true, |
||||||
|
"engines": { |
||||||
|
"node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/graphql-ws": { |
||||||
|
"version": "5.16.0", |
||||||
|
"resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.16.0.tgz", |
||||||
|
"integrity": "sha512-Ju2RCU2dQMgSKtArPbEtsK5gNLnsQyTNIo/T7cZNp96niC1x0KdJNZV0TIoilceBPQwfb5itrGl8pkFeOUMl4A==", |
||||||
|
"engines": { |
||||||
|
"node": ">=10" |
||||||
|
}, |
||||||
|
"peerDependencies": { |
||||||
|
"graphql": ">=0.11 <=16" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/has-property-descriptors": { |
||||||
|
"version": "1.0.2", |
||||||
|
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", |
||||||
|
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", |
||||||
|
"dependencies": { |
||||||
|
"es-define-property": "^1.0.0" |
||||||
|
}, |
||||||
|
"funding": { |
||||||
|
"url": "https://github.com/sponsors/ljharb" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/has-proto": { |
||||||
|
"version": "1.0.3", |
||||||
|
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", |
||||||
|
"integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.4" |
||||||
|
}, |
||||||
|
"funding": { |
||||||
|
"url": "https://github.com/sponsors/ljharb" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/has-symbols": { |
||||||
|
"version": "1.0.3", |
||||||
|
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", |
||||||
|
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.4" |
||||||
|
}, |
||||||
|
"funding": { |
||||||
|
"url": "https://github.com/sponsors/ljharb" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/hasown": { |
||||||
|
"version": "2.0.2", |
||||||
|
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", |
||||||
|
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", |
||||||
|
"dependencies": { |
||||||
|
"function-bind": "^1.1.2" |
||||||
|
}, |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.4" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/http-errors": { |
||||||
|
"version": "2.0.0", |
||||||
|
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", |
||||||
|
"integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", |
||||||
|
"dependencies": { |
||||||
|
"depd": "2.0.0", |
||||||
|
"inherits": "2.0.4", |
||||||
|
"setprototypeof": "1.2.0", |
||||||
|
"statuses": "2.0.1", |
||||||
|
"toidentifier": "1.0.1" |
||||||
|
}, |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.8" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/iconv-lite": { |
||||||
|
"version": "0.4.24", |
||||||
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", |
||||||
|
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", |
||||||
|
"dependencies": { |
||||||
|
"safer-buffer": ">= 2.1.2 < 3" |
||||||
|
}, |
||||||
|
"engines": { |
||||||
|
"node": ">=0.10.0" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/inherits": { |
||||||
|
"version": "2.0.4", |
||||||
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", |
||||||
|
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" |
||||||
|
}, |
||||||
|
"node_modules/ipaddr.js": { |
||||||
|
"version": "1.9.1", |
||||||
|
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", |
||||||
|
"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.10" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/media-typer": { |
||||||
|
"version": "0.3.0", |
||||||
|
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", |
||||||
|
"integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.6" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/merge-descriptors": { |
||||||
|
"version": "1.0.1", |
||||||
|
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", |
||||||
|
"integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" |
||||||
|
}, |
||||||
|
"node_modules/methods": { |
||||||
|
"version": "1.1.2", |
||||||
|
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", |
||||||
|
"integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.6" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/mime": { |
||||||
|
"version": "1.6.0", |
||||||
|
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", |
||||||
|
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", |
||||||
|
"bin": { |
||||||
|
"mime": "cli.js" |
||||||
|
}, |
||||||
|
"engines": { |
||||||
|
"node": ">=4" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/mime-db": { |
||||||
|
"version": "1.52.0", |
||||||
|
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", |
||||||
|
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.6" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/mime-types": { |
||||||
|
"version": "2.1.35", |
||||||
|
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", |
||||||
|
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", |
||||||
|
"dependencies": { |
||||||
|
"mime-db": "1.52.0" |
||||||
|
}, |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.6" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/ms": { |
||||||
|
"version": "2.0.0", |
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", |
||||||
|
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" |
||||||
|
}, |
||||||
|
"node_modules/negotiator": { |
||||||
|
"version": "0.6.3", |
||||||
|
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", |
||||||
|
"integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.6" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/object-inspect": { |
||||||
|
"version": "1.13.1", |
||||||
|
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", |
||||||
|
"integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", |
||||||
|
"funding": { |
||||||
|
"url": "https://github.com/sponsors/ljharb" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/on-finished": { |
||||||
|
"version": "2.4.1", |
||||||
|
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", |
||||||
|
"integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", |
||||||
|
"dependencies": { |
||||||
|
"ee-first": "1.1.1" |
||||||
|
}, |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.8" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/parseurl": { |
||||||
|
"version": "1.3.3", |
||||||
|
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", |
||||||
|
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.8" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/path-to-regexp": { |
||||||
|
"version": "0.1.7", |
||||||
|
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", |
||||||
|
"integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" |
||||||
|
}, |
||||||
|
"node_modules/proxy-addr": { |
||||||
|
"version": "2.0.7", |
||||||
|
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", |
||||||
|
"integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", |
||||||
|
"dependencies": { |
||||||
|
"forwarded": "0.2.0", |
||||||
|
"ipaddr.js": "1.9.1" |
||||||
|
}, |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.10" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/qs": { |
||||||
|
"version": "6.11.0", |
||||||
|
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", |
||||||
|
"integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", |
||||||
|
"dependencies": { |
||||||
|
"side-channel": "^1.0.4" |
||||||
|
}, |
||||||
|
"engines": { |
||||||
|
"node": ">=0.6" |
||||||
|
}, |
||||||
|
"funding": { |
||||||
|
"url": "https://github.com/sponsors/ljharb" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/range-parser": { |
||||||
|
"version": "1.2.1", |
||||||
|
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", |
||||||
|
"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.6" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/raw-body": { |
||||||
|
"version": "2.5.2", |
||||||
|
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", |
||||||
|
"integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", |
||||||
|
"dependencies": { |
||||||
|
"bytes": "3.1.2", |
||||||
|
"http-errors": "2.0.0", |
||||||
|
"iconv-lite": "0.4.24", |
||||||
|
"unpipe": "1.0.0" |
||||||
|
}, |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.8" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/safe-buffer": { |
||||||
|
"version": "5.2.1", |
||||||
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", |
||||||
|
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", |
||||||
|
"funding": [ |
||||||
|
{ |
||||||
|
"type": "github", |
||||||
|
"url": "https://github.com/sponsors/feross" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"type": "patreon", |
||||||
|
"url": "https://www.patreon.com/feross" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"type": "consulting", |
||||||
|
"url": "https://feross.org/support" |
||||||
|
} |
||||||
|
] |
||||||
|
}, |
||||||
|
"node_modules/safer-buffer": { |
||||||
|
"version": "2.1.2", |
||||||
|
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", |
||||||
|
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" |
||||||
|
}, |
||||||
|
"node_modules/send": { |
||||||
|
"version": "0.18.0", |
||||||
|
"resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", |
||||||
|
"integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", |
||||||
|
"dependencies": { |
||||||
|
"debug": "2.6.9", |
||||||
|
"depd": "2.0.0", |
||||||
|
"destroy": "1.2.0", |
||||||
|
"encodeurl": "~1.0.2", |
||||||
|
"escape-html": "~1.0.3", |
||||||
|
"etag": "~1.8.1", |
||||||
|
"fresh": "0.5.2", |
||||||
|
"http-errors": "2.0.0", |
||||||
|
"mime": "1.6.0", |
||||||
|
"ms": "2.1.3", |
||||||
|
"on-finished": "2.4.1", |
||||||
|
"range-parser": "~1.2.1", |
||||||
|
"statuses": "2.0.1" |
||||||
|
}, |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.8.0" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/send/node_modules/ms": { |
||||||
|
"version": "2.1.3", |
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", |
||||||
|
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" |
||||||
|
}, |
||||||
|
"node_modules/serve-static": { |
||||||
|
"version": "1.15.0", |
||||||
|
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", |
||||||
|
"integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", |
||||||
|
"dependencies": { |
||||||
|
"encodeurl": "~1.0.2", |
||||||
|
"escape-html": "~1.0.3", |
||||||
|
"parseurl": "~1.3.3", |
||||||
|
"send": "0.18.0" |
||||||
|
}, |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.8.0" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/set-function-length": { |
||||||
|
"version": "1.2.2", |
||||||
|
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", |
||||||
|
"integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", |
||||||
|
"dependencies": { |
||||||
|
"define-data-property": "^1.1.4", |
||||||
|
"es-errors": "^1.3.0", |
||||||
|
"function-bind": "^1.1.2", |
||||||
|
"get-intrinsic": "^1.2.4", |
||||||
|
"gopd": "^1.0.1", |
||||||
|
"has-property-descriptors": "^1.0.2" |
||||||
|
}, |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.4" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/setprototypeof": { |
||||||
|
"version": "1.2.0", |
||||||
|
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", |
||||||
|
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" |
||||||
|
}, |
||||||
|
"node_modules/side-channel": { |
||||||
|
"version": "1.0.6", |
||||||
|
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", |
||||||
|
"integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", |
||||||
|
"dependencies": { |
||||||
|
"call-bind": "^1.0.7", |
||||||
|
"es-errors": "^1.3.0", |
||||||
|
"get-intrinsic": "^1.2.4", |
||||||
|
"object-inspect": "^1.13.1" |
||||||
|
}, |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.4" |
||||||
|
}, |
||||||
|
"funding": { |
||||||
|
"url": "https://github.com/sponsors/ljharb" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/statuses": { |
||||||
|
"version": "2.0.1", |
||||||
|
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", |
||||||
|
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.8" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/toidentifier": { |
||||||
|
"version": "1.0.1", |
||||||
|
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", |
||||||
|
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", |
||||||
|
"engines": { |
||||||
|
"node": ">=0.6" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/type-is": { |
||||||
|
"version": "1.6.18", |
||||||
|
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", |
||||||
|
"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", |
||||||
|
"dependencies": { |
||||||
|
"media-typer": "0.3.0", |
||||||
|
"mime-types": "~2.1.24" |
||||||
|
}, |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.6" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/unpipe": { |
||||||
|
"version": "1.0.0", |
||||||
|
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", |
||||||
|
"integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.8" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/utils-merge": { |
||||||
|
"version": "1.0.1", |
||||||
|
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", |
||||||
|
"integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.4.0" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/vary": { |
||||||
|
"version": "1.1.2", |
||||||
|
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", |
||||||
|
"integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.8" |
||||||
|
} |
||||||
|
}, |
||||||
|
"node_modules/ws": { |
||||||
|
"version": "8.17.0", |
||||||
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.17.0.tgz", |
||||||
|
"integrity": "sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==", |
||||||
|
"engines": { |
||||||
|
"node": ">=10.0.0" |
||||||
|
}, |
||||||
|
"peerDependencies": { |
||||||
|
"bufferutil": "^4.0.1", |
||||||
|
"utf-8-validate": ">=5.0.2" |
||||||
|
}, |
||||||
|
"peerDependenciesMeta": { |
||||||
|
"bufferutil": { |
||||||
|
"optional": true |
||||||
|
}, |
||||||
|
"utf-8-validate": { |
||||||
|
"optional": true |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,243 @@ |
|||||||
|
1.3.8 / 2022-02-02 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: mime-types@~2.1.34 |
||||||
|
- deps: mime-db@~1.51.0 |
||||||
|
* deps: negotiator@0.6.3 |
||||||
|
|
||||||
|
1.3.7 / 2019-04-29 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: negotiator@0.6.2 |
||||||
|
- Fix sorting charset, encoding, and language with extra parameters |
||||||
|
|
||||||
|
1.3.6 / 2019-04-28 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: mime-types@~2.1.24 |
||||||
|
- deps: mime-db@~1.40.0 |
||||||
|
|
||||||
|
1.3.5 / 2018-02-28 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: mime-types@~2.1.18 |
||||||
|
- deps: mime-db@~1.33.0 |
||||||
|
|
||||||
|
1.3.4 / 2017-08-22 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: mime-types@~2.1.16 |
||||||
|
- deps: mime-db@~1.29.0 |
||||||
|
|
||||||
|
1.3.3 / 2016-05-02 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: mime-types@~2.1.11 |
||||||
|
- deps: mime-db@~1.23.0 |
||||||
|
* deps: negotiator@0.6.1 |
||||||
|
- perf: improve `Accept` parsing speed |
||||||
|
- perf: improve `Accept-Charset` parsing speed |
||||||
|
- perf: improve `Accept-Encoding` parsing speed |
||||||
|
- perf: improve `Accept-Language` parsing speed |
||||||
|
|
||||||
|
1.3.2 / 2016-03-08 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: mime-types@~2.1.10 |
||||||
|
- Fix extension of `application/dash+xml` |
||||||
|
- Update primary extension for `audio/mp4` |
||||||
|
- deps: mime-db@~1.22.0 |
||||||
|
|
||||||
|
1.3.1 / 2016-01-19 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: mime-types@~2.1.9 |
||||||
|
- deps: mime-db@~1.21.0 |
||||||
|
|
||||||
|
1.3.0 / 2015-09-29 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: mime-types@~2.1.7 |
||||||
|
- deps: mime-db@~1.19.0 |
||||||
|
* deps: negotiator@0.6.0 |
||||||
|
- Fix including type extensions in parameters in `Accept` parsing |
||||||
|
- Fix parsing `Accept` parameters with quoted equals |
||||||
|
- Fix parsing `Accept` parameters with quoted semicolons |
||||||
|
- Lazy-load modules from main entry point |
||||||
|
- perf: delay type concatenation until needed |
||||||
|
- perf: enable strict mode |
||||||
|
- perf: hoist regular expressions |
||||||
|
- perf: remove closures getting spec properties |
||||||
|
- perf: remove a closure from media type parsing |
||||||
|
- perf: remove property delete from media type parsing |
||||||
|
|
||||||
|
1.2.13 / 2015-09-06 |
||||||
|
=================== |
||||||
|
|
||||||
|
* deps: mime-types@~2.1.6 |
||||||
|
- deps: mime-db@~1.18.0 |
||||||
|
|
||||||
|
1.2.12 / 2015-07-30 |
||||||
|
=================== |
||||||
|
|
||||||
|
* deps: mime-types@~2.1.4 |
||||||
|
- deps: mime-db@~1.16.0 |
||||||
|
|
||||||
|
1.2.11 / 2015-07-16 |
||||||
|
=================== |
||||||
|
|
||||||
|
* deps: mime-types@~2.1.3 |
||||||
|
- deps: mime-db@~1.15.0 |
||||||
|
|
||||||
|
1.2.10 / 2015-07-01 |
||||||
|
=================== |
||||||
|
|
||||||
|
* deps: mime-types@~2.1.2 |
||||||
|
- deps: mime-db@~1.14.0 |
||||||
|
|
||||||
|
1.2.9 / 2015-06-08 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: mime-types@~2.1.1 |
||||||
|
- perf: fix deopt during mapping |
||||||
|
|
||||||
|
1.2.8 / 2015-06-07 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: mime-types@~2.1.0 |
||||||
|
- deps: mime-db@~1.13.0 |
||||||
|
* perf: avoid argument reassignment & argument slice |
||||||
|
* perf: avoid negotiator recursive construction |
||||||
|
* perf: enable strict mode |
||||||
|
* perf: remove unnecessary bitwise operator |
||||||
|
|
||||||
|
1.2.7 / 2015-05-10 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: negotiator@0.5.3 |
||||||
|
- Fix media type parameter matching to be case-insensitive |
||||||
|
|
||||||
|
1.2.6 / 2015-05-07 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: mime-types@~2.0.11 |
||||||
|
- deps: mime-db@~1.9.1 |
||||||
|
* deps: negotiator@0.5.2 |
||||||
|
- Fix comparing media types with quoted values |
||||||
|
- Fix splitting media types with quoted commas |
||||||
|
|
||||||
|
1.2.5 / 2015-03-13 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: mime-types@~2.0.10 |
||||||
|
- deps: mime-db@~1.8.0 |
||||||
|
|
||||||
|
1.2.4 / 2015-02-14 |
||||||
|
================== |
||||||
|
|
||||||
|
* Support Node.js 0.6 |
||||||
|
* deps: mime-types@~2.0.9 |
||||||
|
- deps: mime-db@~1.7.0 |
||||||
|
* deps: negotiator@0.5.1 |
||||||
|
- Fix preference sorting to be stable for long acceptable lists |
||||||
|
|
||||||
|
1.2.3 / 2015-01-31 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: mime-types@~2.0.8 |
||||||
|
- deps: mime-db@~1.6.0 |
||||||
|
|
||||||
|
1.2.2 / 2014-12-30 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: mime-types@~2.0.7 |
||||||
|
- deps: mime-db@~1.5.0 |
||||||
|
|
||||||
|
1.2.1 / 2014-12-30 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: mime-types@~2.0.5 |
||||||
|
- deps: mime-db@~1.3.1 |
||||||
|
|
||||||
|
1.2.0 / 2014-12-19 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: negotiator@0.5.0 |
||||||
|
- Fix list return order when large accepted list |
||||||
|
- Fix missing identity encoding when q=0 exists |
||||||
|
- Remove dynamic building of Negotiator class |
||||||
|
|
||||||
|
1.1.4 / 2014-12-10 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: mime-types@~2.0.4 |
||||||
|
- deps: mime-db@~1.3.0 |
||||||
|
|
||||||
|
1.1.3 / 2014-11-09 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: mime-types@~2.0.3 |
||||||
|
- deps: mime-db@~1.2.0 |
||||||
|
|
||||||
|
1.1.2 / 2014-10-14 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: negotiator@0.4.9 |
||||||
|
- Fix error when media type has invalid parameter |
||||||
|
|
||||||
|
1.1.1 / 2014-09-28 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: mime-types@~2.0.2 |
||||||
|
- deps: mime-db@~1.1.0 |
||||||
|
* deps: negotiator@0.4.8 |
||||||
|
- Fix all negotiations to be case-insensitive |
||||||
|
- Stable sort preferences of same quality according to client order |
||||||
|
|
||||||
|
1.1.0 / 2014-09-02 |
||||||
|
================== |
||||||
|
|
||||||
|
* update `mime-types` |
||||||
|
|
||||||
|
1.0.7 / 2014-07-04 |
||||||
|
================== |
||||||
|
|
||||||
|
* Fix wrong type returned from `type` when match after unknown extension |
||||||
|
|
||||||
|
1.0.6 / 2014-06-24 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: negotiator@0.4.7 |
||||||
|
|
||||||
|
1.0.5 / 2014-06-20 |
||||||
|
================== |
||||||
|
|
||||||
|
* fix crash when unknown extension given |
||||||
|
|
||||||
|
1.0.4 / 2014-06-19 |
||||||
|
================== |
||||||
|
|
||||||
|
* use `mime-types` |
||||||
|
|
||||||
|
1.0.3 / 2014-06-11 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: negotiator@0.4.6 |
||||||
|
- Order by specificity when quality is the same |
||||||
|
|
||||||
|
1.0.2 / 2014-05-29 |
||||||
|
================== |
||||||
|
|
||||||
|
* Fix interpretation when header not in request |
||||||
|
* deps: pin negotiator@0.4.5 |
||||||
|
|
||||||
|
1.0.1 / 2014-01-18 |
||||||
|
================== |
||||||
|
|
||||||
|
* Identity encoding isn't always acceptable |
||||||
|
* deps: negotiator@~0.4.0 |
||||||
|
|
||||||
|
1.0.0 / 2013-12-27 |
||||||
|
================== |
||||||
|
|
||||||
|
* Genesis |
@ -0,0 +1,23 @@ |
|||||||
|
(The MIT License) |
||||||
|
|
||||||
|
Copyright (c) 2014 Jonathan Ong <me@jongleberry.com> |
||||||
|
Copyright (c) 2015 Douglas Christopher Wilson <doug@somethingdoug.com> |
||||||
|
|
||||||
|
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. |
@ -0,0 +1,140 @@ |
|||||||
|
# accepts |
||||||
|
|
||||||
|
[![NPM Version][npm-version-image]][npm-url] |
||||||
|
[![NPM Downloads][npm-downloads-image]][npm-url] |
||||||
|
[![Node.js Version][node-version-image]][node-version-url] |
||||||
|
[![Build Status][github-actions-ci-image]][github-actions-ci-url] |
||||||
|
[![Test Coverage][coveralls-image]][coveralls-url] |
||||||
|
|
||||||
|
Higher level content negotiation based on [negotiator](https://www.npmjs.com/package/negotiator). |
||||||
|
Extracted from [koa](https://www.npmjs.com/package/koa) for general use. |
||||||
|
|
||||||
|
In addition to negotiator, it allows: |
||||||
|
|
||||||
|
- Allows types as an array or arguments list, ie `(['text/html', 'application/json'])` |
||||||
|
as well as `('text/html', 'application/json')`. |
||||||
|
- Allows type shorthands such as `json`. |
||||||
|
- Returns `false` when no types match |
||||||
|
- Treats non-existent headers as `*` |
||||||
|
|
||||||
|
## Installation |
||||||
|
|
||||||
|
This is a [Node.js](https://nodejs.org/en/) module available through the |
||||||
|
[npm registry](https://www.npmjs.com/). Installation is done using the |
||||||
|
[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): |
||||||
|
|
||||||
|
```sh |
||||||
|
$ npm install accepts |
||||||
|
``` |
||||||
|
|
||||||
|
## API |
||||||
|
|
||||||
|
```js |
||||||
|
var accepts = require('accepts') |
||||||
|
``` |
||||||
|
|
||||||
|
### accepts(req) |
||||||
|
|
||||||
|
Create a new `Accepts` object for the given `req`. |
||||||
|
|
||||||
|
#### .charset(charsets) |
||||||
|
|
||||||
|
Return the first accepted charset. If nothing in `charsets` is accepted, |
||||||
|
then `false` is returned. |
||||||
|
|
||||||
|
#### .charsets() |
||||||
|
|
||||||
|
Return the charsets that the request accepts, in the order of the client's |
||||||
|
preference (most preferred first). |
||||||
|
|
||||||
|
#### .encoding(encodings) |
||||||
|
|
||||||
|
Return the first accepted encoding. If nothing in `encodings` is accepted, |
||||||
|
then `false` is returned. |
||||||
|
|
||||||
|
#### .encodings() |
||||||
|
|
||||||
|
Return the encodings that the request accepts, in the order of the client's |
||||||
|
preference (most preferred first). |
||||||
|
|
||||||
|
#### .language(languages) |
||||||
|
|
||||||
|
Return the first accepted language. If nothing in `languages` is accepted, |
||||||
|
then `false` is returned. |
||||||
|
|
||||||
|
#### .languages() |
||||||
|
|
||||||
|
Return the languages that the request accepts, in the order of the client's |
||||||
|
preference (most preferred first). |
||||||
|
|
||||||
|
#### .type(types) |
||||||
|
|
||||||
|
Return the first accepted type (and it is returned as the same text as what |
||||||
|
appears in the `types` array). If nothing in `types` is accepted, then `false` |
||||||
|
is returned. |
||||||
|
|
||||||
|
The `types` array can contain full MIME types or file extensions. Any value |
||||||
|
that is not a full MIME types is passed to `require('mime-types').lookup`. |
||||||
|
|
||||||
|
#### .types() |
||||||
|
|
||||||
|
Return the types that the request accepts, in the order of the client's |
||||||
|
preference (most preferred first). |
||||||
|
|
||||||
|
## Examples |
||||||
|
|
||||||
|
### Simple type negotiation |
||||||
|
|
||||||
|
This simple example shows how to use `accepts` to return a different typed |
||||||
|
respond body based on what the client wants to accept. The server lists it's |
||||||
|
preferences in order and will get back the best match between the client and |
||||||
|
server. |
||||||
|
|
||||||
|
```js |
||||||
|
var accepts = require('accepts') |
||||||
|
var http = require('http') |
||||||
|
|
||||||
|
function app (req, res) { |
||||||
|
var accept = accepts(req) |
||||||
|
|
||||||
|
// the order of this list is significant; should be server preferred order |
||||||
|
switch (accept.type(['json', 'html'])) { |
||||||
|
case 'json': |
||||||
|
res.setHeader('Content-Type', 'application/json') |
||||||
|
res.write('{"hello":"world!"}') |
||||||
|
break |
||||||
|
case 'html': |
||||||
|
res.setHeader('Content-Type', 'text/html') |
||||||
|
res.write('<b>hello, world!</b>') |
||||||
|
break |
||||||
|
default: |
||||||
|
// the fallback is text/plain, so no need to specify it above |
||||||
|
res.setHeader('Content-Type', 'text/plain') |
||||||
|
res.write('hello, world!') |
||||||
|
break |
||||||
|
} |
||||||
|
|
||||||
|
res.end() |
||||||
|
} |
||||||
|
|
||||||
|
http.createServer(app).listen(3000) |
||||||
|
``` |
||||||
|
|
||||||
|
You can test this out with the cURL program: |
||||||
|
```sh |
||||||
|
curl -I -H'Accept: text/html' http://localhost:3000/ |
||||||
|
``` |
||||||
|
|
||||||
|
## License |
||||||
|
|
||||||
|
[MIT](LICENSE) |
||||||
|
|
||||||
|
[coveralls-image]: https://badgen.net/coveralls/c/github/jshttp/accepts/master |
||||||
|
[coveralls-url]: https://coveralls.io/r/jshttp/accepts?branch=master |
||||||
|
[github-actions-ci-image]: https://badgen.net/github/checks/jshttp/accepts/master?label=ci |
||||||
|
[github-actions-ci-url]: https://github.com/jshttp/accepts/actions/workflows/ci.yml |
||||||
|
[node-version-image]: https://badgen.net/npm/node/accepts |
||||||
|
[node-version-url]: https://nodejs.org/en/download |
||||||
|
[npm-downloads-image]: https://badgen.net/npm/dm/accepts |
||||||
|
[npm-url]: https://npmjs.org/package/accepts |
||||||
|
[npm-version-image]: https://badgen.net/npm/v/accepts |
@ -0,0 +1,238 @@ |
|||||||
|
/*! |
||||||
|
* accepts |
||||||
|
* Copyright(c) 2014 Jonathan Ong |
||||||
|
* Copyright(c) 2015 Douglas Christopher Wilson |
||||||
|
* MIT Licensed |
||||||
|
*/ |
||||||
|
|
||||||
|
'use strict' |
||||||
|
|
||||||
|
/** |
||||||
|
* Module dependencies. |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
var Negotiator = require('negotiator') |
||||||
|
var mime = require('mime-types') |
||||||
|
|
||||||
|
/** |
||||||
|
* Module exports. |
||||||
|
* @public |
||||||
|
*/ |
||||||
|
|
||||||
|
module.exports = Accepts |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new Accepts object for the given req. |
||||||
|
* |
||||||
|
* @param {object} req |
||||||
|
* @public |
||||||
|
*/ |
||||||
|
|
||||||
|
function Accepts (req) { |
||||||
|
if (!(this instanceof Accepts)) { |
||||||
|
return new Accepts(req) |
||||||
|
} |
||||||
|
|
||||||
|
this.headers = req.headers |
||||||
|
this.negotiator = new Negotiator(req) |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Check if the given `type(s)` is acceptable, returning |
||||||
|
* the best match when true, otherwise `undefined`, in which |
||||||
|
* case you should respond with 406 "Not Acceptable". |
||||||
|
* |
||||||
|
* The `type` value may be a single mime type string |
||||||
|
* such as "application/json", the extension name |
||||||
|
* such as "json" or an array `["json", "html", "text/plain"]`. When a list |
||||||
|
* or array is given the _best_ match, if any is returned. |
||||||
|
* |
||||||
|
* Examples: |
||||||
|
* |
||||||
|
* // Accept: text/html
|
||||||
|
* this.types('html'); |
||||||
|
* // => "html"
|
||||||
|
* |
||||||
|
* // Accept: text/*, application/json
|
||||||
|
* this.types('html'); |
||||||
|
* // => "html"
|
||||||
|
* this.types('text/html'); |
||||||
|
* // => "text/html"
|
||||||
|
* this.types('json', 'text'); |
||||||
|
* // => "json"
|
||||||
|
* this.types('application/json'); |
||||||
|
* // => "application/json"
|
||||||
|
* |
||||||
|
* // Accept: text/*, application/json
|
||||||
|
* this.types('image/png'); |
||||||
|
* this.types('png'); |
||||||
|
* // => undefined
|
||||||
|
* |
||||||
|
* // Accept: text/*;q=.5, application/json
|
||||||
|
* this.types(['html', 'json']); |
||||||
|
* this.types('html', 'json'); |
||||||
|
* // => "json"
|
||||||
|
* |
||||||
|
* @param {String|Array} types... |
||||||
|
* @return {String|Array|Boolean} |
||||||
|
* @public |
||||||
|
*/ |
||||||
|
|
||||||
|
Accepts.prototype.type = |
||||||
|
Accepts.prototype.types = function (types_) { |
||||||
|
var types = types_ |
||||||
|
|
||||||
|
// support flattened arguments
|
||||||
|
if (types && !Array.isArray(types)) { |
||||||
|
types = new Array(arguments.length) |
||||||
|
for (var i = 0; i < types.length; i++) { |
||||||
|
types[i] = arguments[i] |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// no types, return all requested types
|
||||||
|
if (!types || types.length === 0) { |
||||||
|
return this.negotiator.mediaTypes() |
||||||
|
} |
||||||
|
|
||||||
|
// no accept header, return first given type
|
||||||
|
if (!this.headers.accept) { |
||||||
|
return types[0] |
||||||
|
} |
||||||
|
|
||||||
|
var mimes = types.map(extToMime) |
||||||
|
var accepts = this.negotiator.mediaTypes(mimes.filter(validMime)) |
||||||
|
var first = accepts[0] |
||||||
|
|
||||||
|
return first |
||||||
|
? types[mimes.indexOf(first)] |
||||||
|
: false |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return accepted encodings or best fit based on `encodings`. |
||||||
|
* |
||||||
|
* Given `Accept-Encoding: gzip, deflate` |
||||||
|
* an array sorted by quality is returned: |
||||||
|
* |
||||||
|
* ['gzip', 'deflate'] |
||||||
|
* |
||||||
|
* @param {String|Array} encodings... |
||||||
|
* @return {String|Array} |
||||||
|
* @public |
||||||
|
*/ |
||||||
|
|
||||||
|
Accepts.prototype.encoding = |
||||||
|
Accepts.prototype.encodings = function (encodings_) { |
||||||
|
var encodings = encodings_ |
||||||
|
|
||||||
|
// support flattened arguments
|
||||||
|
if (encodings && !Array.isArray(encodings)) { |
||||||
|
encodings = new Array(arguments.length) |
||||||
|
for (var i = 0; i < encodings.length; i++) { |
||||||
|
encodings[i] = arguments[i] |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// no encodings, return all requested encodings
|
||||||
|
if (!encodings || encodings.length === 0) { |
||||||
|
return this.negotiator.encodings() |
||||||
|
} |
||||||
|
|
||||||
|
return this.negotiator.encodings(encodings)[0] || false |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return accepted charsets or best fit based on `charsets`. |
||||||
|
* |
||||||
|
* Given `Accept-Charset: utf-8, iso-8859-1;q=0.2, utf-7;q=0.5` |
||||||
|
* an array sorted by quality is returned: |
||||||
|
* |
||||||
|
* ['utf-8', 'utf-7', 'iso-8859-1'] |
||||||
|
* |
||||||
|
* @param {String|Array} charsets... |
||||||
|
* @return {String|Array} |
||||||
|
* @public |
||||||
|
*/ |
||||||
|
|
||||||
|
Accepts.prototype.charset = |
||||||
|
Accepts.prototype.charsets = function (charsets_) { |
||||||
|
var charsets = charsets_ |
||||||
|
|
||||||
|
// support flattened arguments
|
||||||
|
if (charsets && !Array.isArray(charsets)) { |
||||||
|
charsets = new Array(arguments.length) |
||||||
|
for (var i = 0; i < charsets.length; i++) { |
||||||
|
charsets[i] = arguments[i] |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// no charsets, return all requested charsets
|
||||||
|
if (!charsets || charsets.length === 0) { |
||||||
|
return this.negotiator.charsets() |
||||||
|
} |
||||||
|
|
||||||
|
return this.negotiator.charsets(charsets)[0] || false |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return accepted languages or best fit based on `langs`. |
||||||
|
* |
||||||
|
* Given `Accept-Language: en;q=0.8, es, pt` |
||||||
|
* an array sorted by quality is returned: |
||||||
|
* |
||||||
|
* ['es', 'pt', 'en'] |
||||||
|
* |
||||||
|
* @param {String|Array} langs... |
||||||
|
* @return {Array|String} |
||||||
|
* @public |
||||||
|
*/ |
||||||
|
|
||||||
|
Accepts.prototype.lang = |
||||||
|
Accepts.prototype.langs = |
||||||
|
Accepts.prototype.language = |
||||||
|
Accepts.prototype.languages = function (languages_) { |
||||||
|
var languages = languages_ |
||||||
|
|
||||||
|
// support flattened arguments
|
||||||
|
if (languages && !Array.isArray(languages)) { |
||||||
|
languages = new Array(arguments.length) |
||||||
|
for (var i = 0; i < languages.length; i++) { |
||||||
|
languages[i] = arguments[i] |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// no languages, return all requested languages
|
||||||
|
if (!languages || languages.length === 0) { |
||||||
|
return this.negotiator.languages() |
||||||
|
} |
||||||
|
|
||||||
|
return this.negotiator.languages(languages)[0] || false |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Convert extnames to mime. |
||||||
|
* |
||||||
|
* @param {String} type |
||||||
|
* @return {String} |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
function extToMime (type) { |
||||||
|
return type.indexOf('/') === -1 |
||||||
|
? mime.lookup(type) |
||||||
|
: type |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Check if mime is valid. |
||||||
|
* |
||||||
|
* @param {String} type |
||||||
|
* @return {String} |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
function validMime (type) { |
||||||
|
return typeof type === 'string' |
||||||
|
} |
@ -0,0 +1,47 @@ |
|||||||
|
{ |
||||||
|
"name": "accepts", |
||||||
|
"description": "Higher-level content negotiation", |
||||||
|
"version": "1.3.8", |
||||||
|
"contributors": [ |
||||||
|
"Douglas Christopher Wilson <doug@somethingdoug.com>", |
||||||
|
"Jonathan Ong <me@jongleberry.com> (http://jongleberry.com)" |
||||||
|
], |
||||||
|
"license": "MIT", |
||||||
|
"repository": "jshttp/accepts", |
||||||
|
"dependencies": { |
||||||
|
"mime-types": "~2.1.34", |
||||||
|
"negotiator": "0.6.3" |
||||||
|
}, |
||||||
|
"devDependencies": { |
||||||
|
"deep-equal": "1.0.1", |
||||||
|
"eslint": "7.32.0", |
||||||
|
"eslint-config-standard": "14.1.1", |
||||||
|
"eslint-plugin-import": "2.25.4", |
||||||
|
"eslint-plugin-markdown": "2.2.1", |
||||||
|
"eslint-plugin-node": "11.1.0", |
||||||
|
"eslint-plugin-promise": "4.3.1", |
||||||
|
"eslint-plugin-standard": "4.1.0", |
||||||
|
"mocha": "9.2.0", |
||||||
|
"nyc": "15.1.0" |
||||||
|
}, |
||||||
|
"files": [ |
||||||
|
"LICENSE", |
||||||
|
"HISTORY.md", |
||||||
|
"index.js" |
||||||
|
], |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.6" |
||||||
|
}, |
||||||
|
"scripts": { |
||||||
|
"lint": "eslint .", |
||||||
|
"test": "mocha --reporter spec --check-leaks --bail test/", |
||||||
|
"test-ci": "nyc --reporter=lcov --reporter=text npm test", |
||||||
|
"test-cov": "nyc --reporter=html --reporter=text npm test" |
||||||
|
}, |
||||||
|
"keywords": [ |
||||||
|
"content", |
||||||
|
"negotiation", |
||||||
|
"accept", |
||||||
|
"accepts" |
||||||
|
] |
||||||
|
} |
@ -0,0 +1,21 @@ |
|||||||
|
The MIT License (MIT) |
||||||
|
|
||||||
|
Copyright (c) 2014 Blake Embrey (hello@blakeembrey.com) |
||||||
|
|
||||||
|
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. |
@ -0,0 +1,43 @@ |
|||||||
|
# Array Flatten |
||||||
|
|
||||||
|
[![NPM version][npm-image]][npm-url] |
||||||
|
[![NPM downloads][downloads-image]][downloads-url] |
||||||
|
[![Build status][travis-image]][travis-url] |
||||||
|
[![Test coverage][coveralls-image]][coveralls-url] |
||||||
|
|
||||||
|
> Flatten an array of nested arrays into a single flat array. Accepts an optional depth. |
||||||
|
|
||||||
|
## Installation |
||||||
|
|
||||||
|
``` |
||||||
|
npm install array-flatten --save |
||||||
|
``` |
||||||
|
|
||||||
|
## Usage |
||||||
|
|
||||||
|
```javascript |
||||||
|
var flatten = require('array-flatten') |
||||||
|
|
||||||
|
flatten([1, [2, [3, [4, [5], 6], 7], 8], 9]) |
||||||
|
//=> [1, 2, 3, 4, 5, 6, 7, 8, 9] |
||||||
|
|
||||||
|
flatten([1, [2, [3, [4, [5], 6], 7], 8], 9], 2) |
||||||
|
//=> [1, 2, 3, [4, [5], 6], 7, 8, 9] |
||||||
|
|
||||||
|
(function () { |
||||||
|
flatten(arguments) //=> [1, 2, 3] |
||||||
|
})(1, [2, 3]) |
||||||
|
``` |
||||||
|
|
||||||
|
## License |
||||||
|
|
||||||
|
MIT |
||||||
|
|
||||||
|
[npm-image]: https://img.shields.io/npm/v/array-flatten.svg?style=flat |
||||||
|
[npm-url]: https://npmjs.org/package/array-flatten |
||||||
|
[downloads-image]: https://img.shields.io/npm/dm/array-flatten.svg?style=flat |
||||||
|
[downloads-url]: https://npmjs.org/package/array-flatten |
||||||
|
[travis-image]: https://img.shields.io/travis/blakeembrey/array-flatten.svg?style=flat |
||||||
|
[travis-url]: https://travis-ci.org/blakeembrey/array-flatten |
||||||
|
[coveralls-image]: https://img.shields.io/coveralls/blakeembrey/array-flatten.svg?style=flat |
||||||
|
[coveralls-url]: https://coveralls.io/r/blakeembrey/array-flatten?branch=master |
@ -0,0 +1,64 @@ |
|||||||
|
'use strict' |
||||||
|
|
||||||
|
/** |
||||||
|
* Expose `arrayFlatten`. |
||||||
|
*/ |
||||||
|
module.exports = arrayFlatten |
||||||
|
|
||||||
|
/** |
||||||
|
* Recursive flatten function with depth. |
||||||
|
* |
||||||
|
* @param {Array} array |
||||||
|
* @param {Array} result |
||||||
|
* @param {Number} depth |
||||||
|
* @return {Array} |
||||||
|
*/ |
||||||
|
function flattenWithDepth (array, result, depth) { |
||||||
|
for (var i = 0; i < array.length; i++) { |
||||||
|
var value = array[i] |
||||||
|
|
||||||
|
if (depth > 0 && Array.isArray(value)) { |
||||||
|
flattenWithDepth(value, result, depth - 1) |
||||||
|
} else { |
||||||
|
result.push(value) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return result |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Recursive flatten function. Omitting depth is slightly faster. |
||||||
|
* |
||||||
|
* @param {Array} array |
||||||
|
* @param {Array} result |
||||||
|
* @return {Array} |
||||||
|
*/ |
||||||
|
function flattenForever (array, result) { |
||||||
|
for (var i = 0; i < array.length; i++) { |
||||||
|
var value = array[i] |
||||||
|
|
||||||
|
if (Array.isArray(value)) { |
||||||
|
flattenForever(value, result) |
||||||
|
} else { |
||||||
|
result.push(value) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return result |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Flatten an array, with the ability to define a depth. |
||||||
|
* |
||||||
|
* @param {Array} array |
||||||
|
* @param {Number} depth |
||||||
|
* @return {Array} |
||||||
|
*/ |
||||||
|
function arrayFlatten (array, depth) { |
||||||
|
if (depth == null) { |
||||||
|
return flattenForever(array, []) |
||||||
|
} |
||||||
|
|
||||||
|
return flattenWithDepth(array, [], depth) |
||||||
|
} |
@ -0,0 +1,39 @@ |
|||||||
|
{ |
||||||
|
"name": "array-flatten", |
||||||
|
"version": "1.1.1", |
||||||
|
"description": "Flatten an array of nested arrays into a single flat array", |
||||||
|
"main": "array-flatten.js", |
||||||
|
"files": [ |
||||||
|
"array-flatten.js", |
||||||
|
"LICENSE" |
||||||
|
], |
||||||
|
"scripts": { |
||||||
|
"test": "istanbul cover _mocha -- -R spec" |
||||||
|
}, |
||||||
|
"repository": { |
||||||
|
"type": "git", |
||||||
|
"url": "git://github.com/blakeembrey/array-flatten.git" |
||||||
|
}, |
||||||
|
"keywords": [ |
||||||
|
"array", |
||||||
|
"flatten", |
||||||
|
"arguments", |
||||||
|
"depth" |
||||||
|
], |
||||||
|
"author": { |
||||||
|
"name": "Blake Embrey", |
||||||
|
"email": "hello@blakeembrey.com", |
||||||
|
"url": "http://blakeembrey.me" |
||||||
|
}, |
||||||
|
"license": "MIT", |
||||||
|
"bugs": { |
||||||
|
"url": "https://github.com/blakeembrey/array-flatten/issues" |
||||||
|
}, |
||||||
|
"homepage": "https://github.com/blakeembrey/array-flatten", |
||||||
|
"devDependencies": { |
||||||
|
"istanbul": "^0.3.13", |
||||||
|
"mocha": "^2.2.4", |
||||||
|
"pre-commit": "^1.0.7", |
||||||
|
"standard": "^3.7.3" |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,665 @@ |
|||||||
|
1.20.2 / 2023-02-21 |
||||||
|
=================== |
||||||
|
|
||||||
|
* Fix strict json error message on Node.js 19+ |
||||||
|
* deps: content-type@~1.0.5 |
||||||
|
- perf: skip value escaping when unnecessary |
||||||
|
* deps: raw-body@2.5.2 |
||||||
|
|
||||||
|
1.20.1 / 2022-10-06 |
||||||
|
=================== |
||||||
|
|
||||||
|
* deps: qs@6.11.0 |
||||||
|
* perf: remove unnecessary object clone |
||||||
|
|
||||||
|
1.20.0 / 2022-04-02 |
||||||
|
=================== |
||||||
|
|
||||||
|
* Fix error message for json parse whitespace in `strict` |
||||||
|
* Fix internal error when inflated body exceeds limit |
||||||
|
* Prevent loss of async hooks context |
||||||
|
* Prevent hanging when request already read |
||||||
|
* deps: depd@2.0.0 |
||||||
|
- Replace internal `eval` usage with `Function` constructor |
||||||
|
- Use instance methods on `process` to check for listeners |
||||||
|
* deps: http-errors@2.0.0 |
||||||
|
- deps: depd@2.0.0 |
||||||
|
- deps: statuses@2.0.1 |
||||||
|
* deps: on-finished@2.4.1 |
||||||
|
* deps: qs@6.10.3 |
||||||
|
* deps: raw-body@2.5.1 |
||||||
|
- deps: http-errors@2.0.0 |
||||||
|
|
||||||
|
1.19.2 / 2022-02-15 |
||||||
|
=================== |
||||||
|
|
||||||
|
* deps: bytes@3.1.2 |
||||||
|
* deps: qs@6.9.7 |
||||||
|
* Fix handling of `__proto__` keys |
||||||
|
* deps: raw-body@2.4.3 |
||||||
|
- deps: bytes@3.1.2 |
||||||
|
|
||||||
|
1.19.1 / 2021-12-10 |
||||||
|
=================== |
||||||
|
|
||||||
|
* deps: bytes@3.1.1 |
||||||
|
* deps: http-errors@1.8.1 |
||||||
|
- deps: inherits@2.0.4 |
||||||
|
- deps: toidentifier@1.0.1 |
||||||
|
- deps: setprototypeof@1.2.0 |
||||||
|
* deps: qs@6.9.6 |
||||||
|
* deps: raw-body@2.4.2 |
||||||
|
- deps: bytes@3.1.1 |
||||||
|
- deps: http-errors@1.8.1 |
||||||
|
* deps: safe-buffer@5.2.1 |
||||||
|
* deps: type-is@~1.6.18 |
||||||
|
|
||||||
|
1.19.0 / 2019-04-25 |
||||||
|
=================== |
||||||
|
|
||||||
|
* deps: bytes@3.1.0 |
||||||
|
- Add petabyte (`pb`) support |
||||||
|
* deps: http-errors@1.7.2 |
||||||
|
- Set constructor name when possible |
||||||
|
- deps: setprototypeof@1.1.1 |
||||||
|
- deps: statuses@'>= 1.5.0 < 2' |
||||||
|
* deps: iconv-lite@0.4.24 |
||||||
|
- Added encoding MIK |
||||||
|
* deps: qs@6.7.0 |
||||||
|
- Fix parsing array brackets after index |
||||||
|
* deps: raw-body@2.4.0 |
||||||
|
- deps: bytes@3.1.0 |
||||||
|
- deps: http-errors@1.7.2 |
||||||
|
- deps: iconv-lite@0.4.24 |
||||||
|
* deps: type-is@~1.6.17 |
||||||
|
- deps: mime-types@~2.1.24 |
||||||
|
- perf: prevent internal `throw` on invalid type |
||||||
|
|
||||||
|
1.18.3 / 2018-05-14 |
||||||
|
=================== |
||||||
|
|
||||||
|
* Fix stack trace for strict json parse error |
||||||
|
* deps: depd@~1.1.2 |
||||||
|
- perf: remove argument reassignment |
||||||
|
* deps: http-errors@~1.6.3 |
||||||
|
- deps: depd@~1.1.2 |
||||||
|
- deps: setprototypeof@1.1.0 |
||||||
|
- deps: statuses@'>= 1.3.1 < 2' |
||||||
|
* deps: iconv-lite@0.4.23 |
||||||
|
- Fix loading encoding with year appended |
||||||
|
- Fix deprecation warnings on Node.js 10+ |
||||||
|
* deps: qs@6.5.2 |
||||||
|
* deps: raw-body@2.3.3 |
||||||
|
- deps: http-errors@1.6.3 |
||||||
|
- deps: iconv-lite@0.4.23 |
||||||
|
* deps: type-is@~1.6.16 |
||||||
|
- deps: mime-types@~2.1.18 |
||||||
|
|
||||||
|
1.18.2 / 2017-09-22 |
||||||
|
=================== |
||||||
|
|
||||||
|
* deps: debug@2.6.9 |
||||||
|
* perf: remove argument reassignment |
||||||
|
|
||||||
|
1.18.1 / 2017-09-12 |
||||||
|
=================== |
||||||
|
|
||||||
|
* deps: content-type@~1.0.4 |
||||||
|
- perf: remove argument reassignment |
||||||
|
- perf: skip parameter parsing when no parameters |
||||||
|
* deps: iconv-lite@0.4.19 |
||||||
|
- Fix ISO-8859-1 regression |
||||||
|
- Update Windows-1255 |
||||||
|
* deps: qs@6.5.1 |
||||||
|
- Fix parsing & compacting very deep objects |
||||||
|
* deps: raw-body@2.3.2 |
||||||
|
- deps: iconv-lite@0.4.19 |
||||||
|
|
||||||
|
1.18.0 / 2017-09-08 |
||||||
|
=================== |
||||||
|
|
||||||
|
* Fix JSON strict violation error to match native parse error |
||||||
|
* Include the `body` property on verify errors |
||||||
|
* Include the `type` property on all generated errors |
||||||
|
* Use `http-errors` to set status code on errors |
||||||
|
* deps: bytes@3.0.0 |
||||||
|
* deps: debug@2.6.8 |
||||||
|
* deps: depd@~1.1.1 |
||||||
|
- Remove unnecessary `Buffer` loading |
||||||
|
* deps: http-errors@~1.6.2 |
||||||
|
- deps: depd@1.1.1 |
||||||
|
* deps: iconv-lite@0.4.18 |
||||||
|
- Add support for React Native |
||||||
|
- Add a warning if not loaded as utf-8 |
||||||
|
- Fix CESU-8 decoding in Node.js 8 |
||||||
|
- Improve speed of ISO-8859-1 encoding |
||||||
|
* deps: qs@6.5.0 |
||||||
|
* deps: raw-body@2.3.1 |
||||||
|
- Use `http-errors` for standard emitted errors |
||||||
|
- deps: bytes@3.0.0 |
||||||
|
- deps: iconv-lite@0.4.18 |
||||||
|
- perf: skip buffer decoding on overage chunk |
||||||
|
* perf: prevent internal `throw` when missing charset |
||||||
|
|
||||||
|
1.17.2 / 2017-05-17 |
||||||
|
=================== |
||||||
|
|
||||||
|
* deps: debug@2.6.7 |
||||||
|
- Fix `DEBUG_MAX_ARRAY_LENGTH` |
||||||
|
- deps: ms@2.0.0 |
||||||
|
* deps: type-is@~1.6.15 |
||||||
|
- deps: mime-types@~2.1.15 |
||||||
|
|
||||||
|
1.17.1 / 2017-03-06 |
||||||
|
=================== |
||||||
|
|
||||||
|
* deps: qs@6.4.0 |
||||||
|
- Fix regression parsing keys starting with `[` |
||||||
|
|
||||||
|
1.17.0 / 2017-03-01 |
||||||
|
=================== |
||||||
|
|
||||||
|
* deps: http-errors@~1.6.1 |
||||||
|
- Make `message` property enumerable for `HttpError`s |
||||||
|
- deps: setprototypeof@1.0.3 |
||||||
|
* deps: qs@6.3.1 |
||||||
|
- Fix compacting nested arrays |
||||||
|
|
||||||
|
1.16.1 / 2017-02-10 |
||||||
|
=================== |
||||||
|
|
||||||
|
* deps: debug@2.6.1 |
||||||
|
- Fix deprecation messages in WebStorm and other editors |
||||||
|
- Undeprecate `DEBUG_FD` set to `1` or `2` |
||||||
|
|
||||||
|
1.16.0 / 2017-01-17 |
||||||
|
=================== |
||||||
|
|
||||||
|
* deps: debug@2.6.0 |
||||||
|
- Allow colors in workers |
||||||
|
- Deprecated `DEBUG_FD` environment variable |
||||||
|
- Fix error when running under React Native |
||||||
|
- Use same color for same namespace |
||||||
|
- deps: ms@0.7.2 |
||||||
|
* deps: http-errors@~1.5.1 |
||||||
|
- deps: inherits@2.0.3 |
||||||
|
- deps: setprototypeof@1.0.2 |
||||||
|
- deps: statuses@'>= 1.3.1 < 2' |
||||||
|
* deps: iconv-lite@0.4.15 |
||||||
|
- Added encoding MS-31J |
||||||
|
- Added encoding MS-932 |
||||||
|
- Added encoding MS-936 |
||||||
|
- Added encoding MS-949 |
||||||
|
- Added encoding MS-950 |
||||||
|
- Fix GBK/GB18030 handling of Euro character |
||||||
|
* deps: qs@6.2.1 |
||||||
|
- Fix array parsing from skipping empty values |
||||||
|
* deps: raw-body@~2.2.0 |
||||||
|
- deps: iconv-lite@0.4.15 |
||||||
|
* deps: type-is@~1.6.14 |
||||||
|
- deps: mime-types@~2.1.13 |
||||||
|
|
||||||
|
1.15.2 / 2016-06-19 |
||||||
|
=================== |
||||||
|
|
||||||
|
* deps: bytes@2.4.0 |
||||||
|
* deps: content-type@~1.0.2 |
||||||
|
- perf: enable strict mode |
||||||
|
* deps: http-errors@~1.5.0 |
||||||
|
- Use `setprototypeof` module to replace `__proto__` setting |
||||||
|
- deps: statuses@'>= 1.3.0 < 2' |
||||||
|
- perf: enable strict mode |
||||||
|
* deps: qs@6.2.0 |
||||||
|
* deps: raw-body@~2.1.7 |
||||||
|
- deps: bytes@2.4.0 |
||||||
|
- perf: remove double-cleanup on happy path |
||||||
|
* deps: type-is@~1.6.13 |
||||||
|
- deps: mime-types@~2.1.11 |
||||||
|
|
||||||
|
1.15.1 / 2016-05-05 |
||||||
|
=================== |
||||||
|
|
||||||
|
* deps: bytes@2.3.0 |
||||||
|
- Drop partial bytes on all parsed units |
||||||
|
- Fix parsing byte string that looks like hex |
||||||
|
* deps: raw-body@~2.1.6 |
||||||
|
- deps: bytes@2.3.0 |
||||||
|
* deps: type-is@~1.6.12 |
||||||
|
- deps: mime-types@~2.1.10 |
||||||
|
|
||||||
|
1.15.0 / 2016-02-10 |
||||||
|
=================== |
||||||
|
|
||||||
|
* deps: http-errors@~1.4.0 |
||||||
|
- Add `HttpError` export, for `err instanceof createError.HttpError` |
||||||
|
- deps: inherits@2.0.1 |
||||||
|
- deps: statuses@'>= 1.2.1 < 2' |
||||||
|
* deps: qs@6.1.0 |
||||||
|
* deps: type-is@~1.6.11 |
||||||
|
- deps: mime-types@~2.1.9 |
||||||
|
|
||||||
|
1.14.2 / 2015-12-16 |
||||||
|
=================== |
||||||
|
|
||||||
|
* deps: bytes@2.2.0 |
||||||
|
* deps: iconv-lite@0.4.13 |
||||||
|
* deps: qs@5.2.0 |
||||||
|
* deps: raw-body@~2.1.5 |
||||||
|
- deps: bytes@2.2.0 |
||||||
|
- deps: iconv-lite@0.4.13 |
||||||
|
* deps: type-is@~1.6.10 |
||||||
|
- deps: mime-types@~2.1.8 |
||||||
|
|
||||||
|
1.14.1 / 2015-09-27 |
||||||
|
=================== |
||||||
|
|
||||||
|
* Fix issue where invalid charset results in 400 when `verify` used |
||||||
|
* deps: iconv-lite@0.4.12 |
||||||
|
- Fix CESU-8 decoding in Node.js 4.x |
||||||
|
* deps: raw-body@~2.1.4 |
||||||
|
- Fix masking critical errors from `iconv-lite` |
||||||
|
- deps: iconv-lite@0.4.12 |
||||||
|
* deps: type-is@~1.6.9 |
||||||
|
- deps: mime-types@~2.1.7 |
||||||
|
|
||||||
|
1.14.0 / 2015-09-16 |
||||||
|
=================== |
||||||
|
|
||||||
|
* Fix JSON strict parse error to match syntax errors |
||||||
|
* Provide static `require` analysis in `urlencoded` parser |
||||||
|
* deps: depd@~1.1.0 |
||||||
|
- Support web browser loading |
||||||
|
* deps: qs@5.1.0 |
||||||
|
* deps: raw-body@~2.1.3 |
||||||
|
- Fix sync callback when attaching data listener causes sync read |
||||||
|
* deps: type-is@~1.6.8 |
||||||
|
- Fix type error when given invalid type to match against |
||||||
|
- deps: mime-types@~2.1.6 |
||||||
|
|
||||||
|
1.13.3 / 2015-07-31 |
||||||
|
=================== |
||||||
|
|
||||||
|
* deps: type-is@~1.6.6 |
||||||
|
- deps: mime-types@~2.1.4 |
||||||
|
|
||||||
|
1.13.2 / 2015-07-05 |
||||||
|
=================== |
||||||
|
|
||||||
|
* deps: iconv-lite@0.4.11 |
||||||
|
* deps: qs@4.0.0 |
||||||
|
- Fix dropping parameters like `hasOwnProperty` |
||||||
|
- Fix user-visible incompatibilities from 3.1.0 |
||||||
|
- Fix various parsing edge cases |
||||||
|
* deps: raw-body@~2.1.2 |
||||||
|
- Fix error stack traces to skip `makeError` |
||||||
|
- deps: iconv-lite@0.4.11 |
||||||
|
* deps: type-is@~1.6.4 |
||||||
|
- deps: mime-types@~2.1.2 |
||||||
|
- perf: enable strict mode |
||||||
|
- perf: remove argument reassignment |
||||||
|
|
||||||
|
1.13.1 / 2015-06-16 |
||||||
|
=================== |
||||||
|
|
||||||
|
* deps: qs@2.4.2 |
||||||
|
- Downgraded from 3.1.0 because of user-visible incompatibilities |
||||||
|
|
||||||
|
1.13.0 / 2015-06-14 |
||||||
|
=================== |
||||||
|
|
||||||
|
* Add `statusCode` property on `Error`s, in addition to `status` |
||||||
|
* Change `type` default to `application/json` for JSON parser |
||||||
|
* Change `type` default to `application/x-www-form-urlencoded` for urlencoded parser |
||||||
|
* Provide static `require` analysis |
||||||
|
* Use the `http-errors` module to generate errors |
||||||
|
* deps: bytes@2.1.0 |
||||||
|
- Slight optimizations |
||||||
|
* deps: iconv-lite@0.4.10 |
||||||
|
- The encoding UTF-16 without BOM now defaults to UTF-16LE when detection fails |
||||||
|
- Leading BOM is now removed when decoding |
||||||
|
* deps: on-finished@~2.3.0 |
||||||
|
- Add defined behavior for HTTP `CONNECT` requests |
||||||
|
- Add defined behavior for HTTP `Upgrade` requests |
||||||
|
- deps: ee-first@1.1.1 |
||||||
|
* deps: qs@3.1.0 |
||||||
|
- Fix dropping parameters like `hasOwnProperty` |
||||||
|
- Fix various parsing edge cases |
||||||
|
- Parsed object now has `null` prototype |
||||||
|
* deps: raw-body@~2.1.1 |
||||||
|
- Use `unpipe` module for unpiping requests |
||||||
|
- deps: iconv-lite@0.4.10 |
||||||
|
* deps: type-is@~1.6.3 |
||||||
|
- deps: mime-types@~2.1.1 |
||||||
|
- perf: reduce try block size |
||||||
|
- perf: remove bitwise operations |
||||||
|
* perf: enable strict mode |
||||||
|
* perf: remove argument reassignment |
||||||
|
* perf: remove delete call |
||||||
|
|
||||||
|
1.12.4 / 2015-05-10 |
||||||
|
=================== |
||||||
|
|
||||||
|
* deps: debug@~2.2.0 |
||||||
|
* deps: qs@2.4.2 |
||||||
|
- Fix allowing parameters like `constructor` |
||||||
|
* deps: on-finished@~2.2.1 |
||||||
|
* deps: raw-body@~2.0.1 |
||||||
|
- Fix a false-positive when unpiping in Node.js 0.8 |
||||||
|
- deps: bytes@2.0.1 |
||||||
|
* deps: type-is@~1.6.2 |
||||||
|
- deps: mime-types@~2.0.11 |
||||||
|
|
||||||
|
1.12.3 / 2015-04-15 |
||||||
|
=================== |
||||||
|
|
||||||
|
* Slight efficiency improvement when not debugging |
||||||
|
* deps: depd@~1.0.1 |
||||||
|
* deps: iconv-lite@0.4.8 |
||||||
|
- Add encoding alias UNICODE-1-1-UTF-7 |
||||||
|
* deps: raw-body@1.3.4 |
||||||
|
- Fix hanging callback if request aborts during read |
||||||
|
- deps: iconv-lite@0.4.8 |
||||||
|
|
||||||
|
1.12.2 / 2015-03-16 |
||||||
|
=================== |
||||||
|
|
||||||
|
* deps: qs@2.4.1 |
||||||
|
- Fix error when parameter `hasOwnProperty` is present |
||||||
|
|
||||||
|
1.12.1 / 2015-03-15 |
||||||
|
=================== |
||||||
|
|
||||||
|
* deps: debug@~2.1.3 |
||||||
|
- Fix high intensity foreground color for bold |
||||||
|
- deps: ms@0.7.0 |
||||||
|
* deps: type-is@~1.6.1 |
||||||
|
- deps: mime-types@~2.0.10 |
||||||
|
|
||||||
|
1.12.0 / 2015-02-13 |
||||||
|
=================== |
||||||
|
|
||||||
|
* add `debug` messages |
||||||
|
* accept a function for the `type` option |
||||||
|
* use `content-type` to parse `Content-Type` headers |
||||||
|
* deps: iconv-lite@0.4.7 |
||||||
|
- Gracefully support enumerables on `Object.prototype` |
||||||
|
* deps: raw-body@1.3.3 |
||||||
|
- deps: iconv-lite@0.4.7 |
||||||
|
* deps: type-is@~1.6.0 |
||||||
|
- fix argument reassignment |
||||||
|
- fix false-positives in `hasBody` `Transfer-Encoding` check |
||||||
|
- support wildcard for both type and subtype (`*/*`) |
||||||
|
- deps: mime-types@~2.0.9 |
||||||
|
|
||||||
|
1.11.0 / 2015-01-30 |
||||||
|
=================== |
||||||
|
|
||||||
|
* make internal `extended: true` depth limit infinity |
||||||
|
* deps: type-is@~1.5.6 |
||||||
|
- deps: mime-types@~2.0.8 |
||||||
|
|
||||||
|
1.10.2 / 2015-01-20 |
||||||
|
=================== |
||||||
|
|
||||||
|
* deps: iconv-lite@0.4.6 |
||||||
|
- Fix rare aliases of single-byte encodings |
||||||
|
* deps: raw-body@1.3.2 |
||||||
|
- deps: iconv-lite@0.4.6 |
||||||
|
|
||||||
|
1.10.1 / 2015-01-01 |
||||||
|
=================== |
||||||
|
|
||||||
|
* deps: on-finished@~2.2.0 |
||||||
|
* deps: type-is@~1.5.5 |
||||||
|
- deps: mime-types@~2.0.7 |
||||||
|
|
||||||
|
1.10.0 / 2014-12-02 |
||||||
|
=================== |
||||||
|
|
||||||
|
* make internal `extended: true` array limit dynamic |
||||||
|
|
||||||
|
1.9.3 / 2014-11-21 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: iconv-lite@0.4.5 |
||||||
|
- Fix Windows-31J and X-SJIS encoding support |
||||||
|
* deps: qs@2.3.3 |
||||||
|
- Fix `arrayLimit` behavior |
||||||
|
* deps: raw-body@1.3.1 |
||||||
|
- deps: iconv-lite@0.4.5 |
||||||
|
* deps: type-is@~1.5.3 |
||||||
|
- deps: mime-types@~2.0.3 |
||||||
|
|
||||||
|
1.9.2 / 2014-10-27 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: qs@2.3.2 |
||||||
|
- Fix parsing of mixed objects and values |
||||||
|
|
||||||
|
1.9.1 / 2014-10-22 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: on-finished@~2.1.1 |
||||||
|
- Fix handling of pipelined requests |
||||||
|
* deps: qs@2.3.0 |
||||||
|
- Fix parsing of mixed implicit and explicit arrays |
||||||
|
* deps: type-is@~1.5.2 |
||||||
|
- deps: mime-types@~2.0.2 |
||||||
|
|
||||||
|
1.9.0 / 2014-09-24 |
||||||
|
================== |
||||||
|
|
||||||
|
* include the charset in "unsupported charset" error message |
||||||
|
* include the encoding in "unsupported content encoding" error message |
||||||
|
* deps: depd@~1.0.0 |
||||||
|
|
||||||
|
1.8.4 / 2014-09-23 |
||||||
|
================== |
||||||
|
|
||||||
|
* fix content encoding to be case-insensitive |
||||||
|
|
||||||
|
1.8.3 / 2014-09-19 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: qs@2.2.4 |
||||||
|
- Fix issue with object keys starting with numbers truncated |
||||||
|
|
||||||
|
1.8.2 / 2014-09-15 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: depd@0.4.5 |
||||||
|
|
||||||
|
1.8.1 / 2014-09-07 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: media-typer@0.3.0 |
||||||
|
* deps: type-is@~1.5.1 |
||||||
|
|
||||||
|
1.8.0 / 2014-09-05 |
||||||
|
================== |
||||||
|
|
||||||
|
* make empty-body-handling consistent between chunked requests |
||||||
|
- empty `json` produces `{}` |
||||||
|
- empty `raw` produces `new Buffer(0)` |
||||||
|
- empty `text` produces `''` |
||||||
|
- empty `urlencoded` produces `{}` |
||||||
|
* deps: qs@2.2.3 |
||||||
|
- Fix issue where first empty value in array is discarded |
||||||
|
* deps: type-is@~1.5.0 |
||||||
|
- fix `hasbody` to be true for `content-length: 0` |
||||||
|
|
||||||
|
1.7.0 / 2014-09-01 |
||||||
|
================== |
||||||
|
|
||||||
|
* add `parameterLimit` option to `urlencoded` parser |
||||||
|
* change `urlencoded` extended array limit to 100 |
||||||
|
* respond with 413 when over `parameterLimit` in `urlencoded` |
||||||
|
|
||||||
|
1.6.7 / 2014-08-29 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: qs@2.2.2 |
||||||
|
- Remove unnecessary cloning |
||||||
|
|
||||||
|
1.6.6 / 2014-08-27 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: qs@2.2.0 |
||||||
|
- Array parsing fix |
||||||
|
- Performance improvements |
||||||
|
|
||||||
|
1.6.5 / 2014-08-16 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: on-finished@2.1.0 |
||||||
|
|
||||||
|
1.6.4 / 2014-08-14 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: qs@1.2.2 |
||||||
|
|
||||||
|
1.6.3 / 2014-08-10 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: qs@1.2.1 |
||||||
|
|
||||||
|
1.6.2 / 2014-08-07 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: qs@1.2.0 |
||||||
|
- Fix parsing array of objects |
||||||
|
|
||||||
|
1.6.1 / 2014-08-06 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: qs@1.1.0 |
||||||
|
- Accept urlencoded square brackets |
||||||
|
- Accept empty values in implicit array notation |
||||||
|
|
||||||
|
1.6.0 / 2014-08-05 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: qs@1.0.2 |
||||||
|
- Complete rewrite |
||||||
|
- Limits array length to 20 |
||||||
|
- Limits object depth to 5 |
||||||
|
- Limits parameters to 1,000 |
||||||
|
|
||||||
|
1.5.2 / 2014-07-27 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: depd@0.4.4 |
||||||
|
- Work-around v8 generating empty stack traces |
||||||
|
|
||||||
|
1.5.1 / 2014-07-26 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: depd@0.4.3 |
||||||
|
- Fix exception when global `Error.stackTraceLimit` is too low |
||||||
|
|
||||||
|
1.5.0 / 2014-07-20 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: depd@0.4.2 |
||||||
|
- Add `TRACE_DEPRECATION` environment variable |
||||||
|
- Remove non-standard grey color from color output |
||||||
|
- Support `--no-deprecation` argument |
||||||
|
- Support `--trace-deprecation` argument |
||||||
|
* deps: iconv-lite@0.4.4 |
||||||
|
- Added encoding UTF-7 |
||||||
|
* deps: raw-body@1.3.0 |
||||||
|
- deps: iconv-lite@0.4.4 |
||||||
|
- Added encoding UTF-7 |
||||||
|
- Fix `Cannot switch to old mode now` error on Node.js 0.10+ |
||||||
|
* deps: type-is@~1.3.2 |
||||||
|
|
||||||
|
1.4.3 / 2014-06-19 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: type-is@1.3.1 |
||||||
|
- fix global variable leak |
||||||
|
|
||||||
|
1.4.2 / 2014-06-19 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: type-is@1.3.0 |
||||||
|
- improve type parsing |
||||||
|
|
||||||
|
1.4.1 / 2014-06-19 |
||||||
|
================== |
||||||
|
|
||||||
|
* fix urlencoded extended deprecation message |
||||||
|
|
||||||
|
1.4.0 / 2014-06-19 |
||||||
|
================== |
||||||
|
|
||||||
|
* add `text` parser |
||||||
|
* add `raw` parser |
||||||
|
* check accepted charset in content-type (accepts utf-8) |
||||||
|
* check accepted encoding in content-encoding (accepts identity) |
||||||
|
* deprecate `bodyParser()` middleware; use `.json()` and `.urlencoded()` as needed |
||||||
|
* deprecate `urlencoded()` without provided `extended` option |
||||||
|
* lazy-load urlencoded parsers |
||||||
|
* parsers split into files for reduced mem usage |
||||||
|
* support gzip and deflate bodies |
||||||
|
- set `inflate: false` to turn off |
||||||
|
* deps: raw-body@1.2.2 |
||||||
|
- Support all encodings from `iconv-lite` |
||||||
|
|
||||||
|
1.3.1 / 2014-06-11 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: type-is@1.2.1 |
||||||
|
- Switch dependency from mime to mime-types@1.0.0 |
||||||
|
|
||||||
|
1.3.0 / 2014-05-31 |
||||||
|
================== |
||||||
|
|
||||||
|
* add `extended` option to urlencoded parser |
||||||
|
|
||||||
|
1.2.2 / 2014-05-27 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: raw-body@1.1.6 |
||||||
|
- assert stream encoding on node.js 0.8 |
||||||
|
- assert stream encoding on node.js < 0.10.6 |
||||||
|
- deps: bytes@1 |
||||||
|
|
||||||
|
1.2.1 / 2014-05-26 |
||||||
|
================== |
||||||
|
|
||||||
|
* invoke `next(err)` after request fully read |
||||||
|
- prevents hung responses and socket hang ups |
||||||
|
|
||||||
|
1.2.0 / 2014-05-11 |
||||||
|
================== |
||||||
|
|
||||||
|
* add `verify` option |
||||||
|
* deps: type-is@1.2.0 |
||||||
|
- support suffix matching |
||||||
|
|
||||||
|
1.1.2 / 2014-05-11 |
||||||
|
================== |
||||||
|
|
||||||
|
* improve json parser speed |
||||||
|
|
||||||
|
1.1.1 / 2014-05-11 |
||||||
|
================== |
||||||
|
|
||||||
|
* fix repeated limit parsing with every request |
||||||
|
|
||||||
|
1.1.0 / 2014-05-10 |
||||||
|
================== |
||||||
|
|
||||||
|
* add `type` option |
||||||
|
* deps: pin for safety and consistency |
||||||
|
|
||||||
|
1.0.2 / 2014-04-14 |
||||||
|
================== |
||||||
|
|
||||||
|
* use `type-is` module |
||||||
|
|
||||||
|
1.0.1 / 2014-03-20 |
||||||
|
================== |
||||||
|
|
||||||
|
* lower default limits to 100kb |
@ -0,0 +1,23 @@ |
|||||||
|
(The MIT License) |
||||||
|
|
||||||
|
Copyright (c) 2014 Jonathan Ong <me@jongleberry.com> |
||||||
|
Copyright (c) 2014-2015 Douglas Christopher Wilson <doug@somethingdoug.com> |
||||||
|
|
||||||
|
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. |
@ -0,0 +1,465 @@ |
|||||||
|
# body-parser |
||||||
|
|
||||||
|
[![NPM Version][npm-version-image]][npm-url] |
||||||
|
[![NPM Downloads][npm-downloads-image]][npm-url] |
||||||
|
[![Build Status][ci-image]][ci-url] |
||||||
|
[![Test Coverage][coveralls-image]][coveralls-url] |
||||||
|
|
||||||
|
Node.js body parsing middleware. |
||||||
|
|
||||||
|
Parse incoming request bodies in a middleware before your handlers, available |
||||||
|
under the `req.body` property. |
||||||
|
|
||||||
|
**Note** As `req.body`'s shape is based on user-controlled input, all |
||||||
|
properties and values in this object are untrusted and should be validated |
||||||
|
before trusting. For example, `req.body.foo.toString()` may fail in multiple |
||||||
|
ways, for example the `foo` property may not be there or may not be a string, |
||||||
|
and `toString` may not be a function and instead a string or other user input. |
||||||
|
|
||||||
|
[Learn about the anatomy of an HTTP transaction in Node.js](https://nodejs.org/en/docs/guides/anatomy-of-an-http-transaction/). |
||||||
|
|
||||||
|
_This does not handle multipart bodies_, due to their complex and typically |
||||||
|
large nature. For multipart bodies, you may be interested in the following |
||||||
|
modules: |
||||||
|
|
||||||
|
* [busboy](https://www.npmjs.org/package/busboy#readme) and |
||||||
|
[connect-busboy](https://www.npmjs.org/package/connect-busboy#readme) |
||||||
|
* [multiparty](https://www.npmjs.org/package/multiparty#readme) and |
||||||
|
[connect-multiparty](https://www.npmjs.org/package/connect-multiparty#readme) |
||||||
|
* [formidable](https://www.npmjs.org/package/formidable#readme) |
||||||
|
* [multer](https://www.npmjs.org/package/multer#readme) |
||||||
|
|
||||||
|
This module provides the following parsers: |
||||||
|
|
||||||
|
* [JSON body parser](#bodyparserjsonoptions) |
||||||
|
* [Raw body parser](#bodyparserrawoptions) |
||||||
|
* [Text body parser](#bodyparsertextoptions) |
||||||
|
* [URL-encoded form body parser](#bodyparserurlencodedoptions) |
||||||
|
|
||||||
|
Other body parsers you might be interested in: |
||||||
|
|
||||||
|
- [body](https://www.npmjs.org/package/body#readme) |
||||||
|
- [co-body](https://www.npmjs.org/package/co-body#readme) |
||||||
|
|
||||||
|
## Installation |
||||||
|
|
||||||
|
```sh |
||||||
|
$ npm install body-parser |
||||||
|
``` |
||||||
|
|
||||||
|
## API |
||||||
|
|
||||||
|
```js |
||||||
|
var bodyParser = require('body-parser') |
||||||
|
``` |
||||||
|
|
||||||
|
The `bodyParser` object exposes various factories to create middlewares. All |
||||||
|
middlewares will populate the `req.body` property with the parsed body when |
||||||
|
the `Content-Type` request header matches the `type` option, or an empty |
||||||
|
object (`{}`) if there was no body to parse, the `Content-Type` was not matched, |
||||||
|
or an error occurred. |
||||||
|
|
||||||
|
The various errors returned by this module are described in the |
||||||
|
[errors section](#errors). |
||||||
|
|
||||||
|
### bodyParser.json([options]) |
||||||
|
|
||||||
|
Returns middleware that only parses `json` and only looks at requests where |
||||||
|
the `Content-Type` header matches the `type` option. This parser accepts any |
||||||
|
Unicode encoding of the body and supports automatic inflation of `gzip` and |
||||||
|
`deflate` encodings. |
||||||
|
|
||||||
|
A new `body` object containing the parsed data is populated on the `request` |
||||||
|
object after the middleware (i.e. `req.body`). |
||||||
|
|
||||||
|
#### Options |
||||||
|
|
||||||
|
The `json` function takes an optional `options` object that may contain any of |
||||||
|
the following keys: |
||||||
|
|
||||||
|
##### inflate |
||||||
|
|
||||||
|
When set to `true`, then deflated (compressed) bodies will be inflated; when |
||||||
|
`false`, deflated bodies are rejected. Defaults to `true`. |
||||||
|
|
||||||
|
##### limit |
||||||
|
|
||||||
|
Controls the maximum request body size. If this is a number, then the value |
||||||
|
specifies the number of bytes; if it is a string, the value is passed to the |
||||||
|
[bytes](https://www.npmjs.com/package/bytes) library for parsing. Defaults |
||||||
|
to `'100kb'`. |
||||||
|
|
||||||
|
##### reviver |
||||||
|
|
||||||
|
The `reviver` option is passed directly to `JSON.parse` as the second |
||||||
|
argument. You can find more information on this argument |
||||||
|
[in the MDN documentation about JSON.parse](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#Example.3A_Using_the_reviver_parameter). |
||||||
|
|
||||||
|
##### strict |
||||||
|
|
||||||
|
When set to `true`, will only accept arrays and objects; when `false` will |
||||||
|
accept anything `JSON.parse` accepts. Defaults to `true`. |
||||||
|
|
||||||
|
##### type |
||||||
|
|
||||||
|
The `type` option is used to determine what media type the middleware will |
||||||
|
parse. This option can be a string, array of strings, or a function. If not a |
||||||
|
function, `type` option is passed directly to the |
||||||
|
[type-is](https://www.npmjs.org/package/type-is#readme) library and this can |
||||||
|
be an extension name (like `json`), a mime type (like `application/json`), or |
||||||
|
a mime type with a wildcard (like `*/*` or `*/json`). If a function, the `type` |
||||||
|
option is called as `fn(req)` and the request is parsed if it returns a truthy |
||||||
|
value. Defaults to `application/json`. |
||||||
|
|
||||||
|
##### verify |
||||||
|
|
||||||
|
The `verify` option, if supplied, is called as `verify(req, res, buf, encoding)`, |
||||||
|
where `buf` is a `Buffer` of the raw request body and `encoding` is the |
||||||
|
encoding of the request. The parsing can be aborted by throwing an error. |
||||||
|
|
||||||
|
### bodyParser.raw([options]) |
||||||
|
|
||||||
|
Returns middleware that parses all bodies as a `Buffer` and only looks at |
||||||
|
requests where the `Content-Type` header matches the `type` option. This |
||||||
|
parser supports automatic inflation of `gzip` and `deflate` encodings. |
||||||
|
|
||||||
|
A new `body` object containing the parsed data is populated on the `request` |
||||||
|
object after the middleware (i.e. `req.body`). This will be a `Buffer` object |
||||||
|
of the body. |
||||||
|
|
||||||
|
#### Options |
||||||
|
|
||||||
|
The `raw` function takes an optional `options` object that may contain any of |
||||||
|
the following keys: |
||||||
|
|
||||||
|
##### inflate |
||||||
|
|
||||||
|
When set to `true`, then deflated (compressed) bodies will be inflated; when |
||||||
|
`false`, deflated bodies are rejected. Defaults to `true`. |
||||||
|
|
||||||
|
##### limit |
||||||
|
|
||||||
|
Controls the maximum request body size. If this is a number, then the value |
||||||
|
specifies the number of bytes; if it is a string, the value is passed to the |
||||||
|
[bytes](https://www.npmjs.com/package/bytes) library for parsing. Defaults |
||||||
|
to `'100kb'`. |
||||||
|
|
||||||
|
##### type |
||||||
|
|
||||||
|
The `type` option is used to determine what media type the middleware will |
||||||
|
parse. This option can be a string, array of strings, or a function. |
||||||
|
If not a function, `type` option is passed directly to the |
||||||
|
[type-is](https://www.npmjs.org/package/type-is#readme) library and this |
||||||
|
can be an extension name (like `bin`), a mime type (like |
||||||
|
`application/octet-stream`), or a mime type with a wildcard (like `*/*` or |
||||||
|
`application/*`). If a function, the `type` option is called as `fn(req)` |
||||||
|
and the request is parsed if it returns a truthy value. Defaults to |
||||||
|
`application/octet-stream`. |
||||||
|
|
||||||
|
##### verify |
||||||
|
|
||||||
|
The `verify` option, if supplied, is called as `verify(req, res, buf, encoding)`, |
||||||
|
where `buf` is a `Buffer` of the raw request body and `encoding` is the |
||||||
|
encoding of the request. The parsing can be aborted by throwing an error. |
||||||
|
|
||||||
|
### bodyParser.text([options]) |
||||||
|
|
||||||
|
Returns middleware that parses all bodies as a string and only looks at |
||||||
|
requests where the `Content-Type` header matches the `type` option. This |
||||||
|
parser supports automatic inflation of `gzip` and `deflate` encodings. |
||||||
|
|
||||||
|
A new `body` string containing the parsed data is populated on the `request` |
||||||
|
object after the middleware (i.e. `req.body`). This will be a string of the |
||||||
|
body. |
||||||
|
|
||||||
|
#### Options |
||||||
|
|
||||||
|
The `text` function takes an optional `options` object that may contain any of |
||||||
|
the following keys: |
||||||
|
|
||||||
|
##### defaultCharset |
||||||
|
|
||||||
|
Specify the default character set for the text content if the charset is not |
||||||
|
specified in the `Content-Type` header of the request. Defaults to `utf-8`. |
||||||
|
|
||||||
|
##### inflate |
||||||
|
|
||||||
|
When set to `true`, then deflated (compressed) bodies will be inflated; when |
||||||
|
`false`, deflated bodies are rejected. Defaults to `true`. |
||||||
|
|
||||||
|
##### limit |
||||||
|
|
||||||
|
Controls the maximum request body size. If this is a number, then the value |
||||||
|
specifies the number of bytes; if it is a string, the value is passed to the |
||||||
|
[bytes](https://www.npmjs.com/package/bytes) library for parsing. Defaults |
||||||
|
to `'100kb'`. |
||||||
|
|
||||||
|
##### type |
||||||
|
|
||||||
|
The `type` option is used to determine what media type the middleware will |
||||||
|
parse. This option can be a string, array of strings, or a function. If not |
||||||
|
a function, `type` option is passed directly to the |
||||||
|
[type-is](https://www.npmjs.org/package/type-is#readme) library and this can |
||||||
|
be an extension name (like `txt`), a mime type (like `text/plain`), or a mime |
||||||
|
type with a wildcard (like `*/*` or `text/*`). If a function, the `type` |
||||||
|
option is called as `fn(req)` and the request is parsed if it returns a |
||||||
|
truthy value. Defaults to `text/plain`. |
||||||
|
|
||||||
|
##### verify |
||||||
|
|
||||||
|
The `verify` option, if supplied, is called as `verify(req, res, buf, encoding)`, |
||||||
|
where `buf` is a `Buffer` of the raw request body and `encoding` is the |
||||||
|
encoding of the request. The parsing can be aborted by throwing an error. |
||||||
|
|
||||||
|
### bodyParser.urlencoded([options]) |
||||||
|
|
||||||
|
Returns middleware that only parses `urlencoded` bodies and only looks at |
||||||
|
requests where the `Content-Type` header matches the `type` option. This |
||||||
|
parser accepts only UTF-8 encoding of the body and supports automatic |
||||||
|
inflation of `gzip` and `deflate` encodings. |
||||||
|
|
||||||
|
A new `body` object containing the parsed data is populated on the `request` |
||||||
|
object after the middleware (i.e. `req.body`). This object will contain |
||||||
|
key-value pairs, where the value can be a string or array (when `extended` is |
||||||
|
`false`), or any type (when `extended` is `true`). |
||||||
|
|
||||||
|
#### Options |
||||||
|
|
||||||
|
The `urlencoded` function takes an optional `options` object that may contain |
||||||
|
any of the following keys: |
||||||
|
|
||||||
|
##### extended |
||||||
|
|
||||||
|
The `extended` option allows to choose between parsing the URL-encoded data |
||||||
|
with the `querystring` library (when `false`) or the `qs` library (when |
||||||
|
`true`). The "extended" syntax allows for rich objects and arrays to be |
||||||
|
encoded into the URL-encoded format, allowing for a JSON-like experience |
||||||
|
with URL-encoded. For more information, please |
||||||
|
[see the qs library](https://www.npmjs.org/package/qs#readme). |
||||||
|
|
||||||
|
Defaults to `true`, but using the default has been deprecated. Please |
||||||
|
research into the difference between `qs` and `querystring` and choose the |
||||||
|
appropriate setting. |
||||||
|
|
||||||
|
##### inflate |
||||||
|
|
||||||
|
When set to `true`, then deflated (compressed) bodies will be inflated; when |
||||||
|
`false`, deflated bodies are rejected. Defaults to `true`. |
||||||
|
|
||||||
|
##### limit |
||||||
|
|
||||||
|
Controls the maximum request body size. If this is a number, then the value |
||||||
|
specifies the number of bytes; if it is a string, the value is passed to the |
||||||
|
[bytes](https://www.npmjs.com/package/bytes) library for parsing. Defaults |
||||||
|
to `'100kb'`. |
||||||
|
|
||||||
|
##### parameterLimit |
||||||
|
|
||||||
|
The `parameterLimit` option controls the maximum number of parameters that |
||||||
|
are allowed in the URL-encoded data. If a request contains more parameters |
||||||
|
than this value, a 413 will be returned to the client. Defaults to `1000`. |
||||||
|
|
||||||
|
##### type |
||||||
|
|
||||||
|
The `type` option is used to determine what media type the middleware will |
||||||
|
parse. This option can be a string, array of strings, or a function. If not |
||||||
|
a function, `type` option is passed directly to the |
||||||
|
[type-is](https://www.npmjs.org/package/type-is#readme) library and this can |
||||||
|
be an extension name (like `urlencoded`), a mime type (like |
||||||
|
`application/x-www-form-urlencoded`), or a mime type with a wildcard (like |
||||||
|
`*/x-www-form-urlencoded`). If a function, the `type` option is called as |
||||||
|
`fn(req)` and the request is parsed if it returns a truthy value. Defaults |
||||||
|
to `application/x-www-form-urlencoded`. |
||||||
|
|
||||||
|
##### verify |
||||||
|
|
||||||
|
The `verify` option, if supplied, is called as `verify(req, res, buf, encoding)`, |
||||||
|
where `buf` is a `Buffer` of the raw request body and `encoding` is the |
||||||
|
encoding of the request. The parsing can be aborted by throwing an error. |
||||||
|
|
||||||
|
## Errors |
||||||
|
|
||||||
|
The middlewares provided by this module create errors using the |
||||||
|
[`http-errors` module](https://www.npmjs.com/package/http-errors). The errors |
||||||
|
will typically have a `status`/`statusCode` property that contains the suggested |
||||||
|
HTTP response code, an `expose` property to determine if the `message` property |
||||||
|
should be displayed to the client, a `type` property to determine the type of |
||||||
|
error without matching against the `message`, and a `body` property containing |
||||||
|
the read body, if available. |
||||||
|
|
||||||
|
The following are the common errors created, though any error can come through |
||||||
|
for various reasons. |
||||||
|
|
||||||
|
### content encoding unsupported |
||||||
|
|
||||||
|
This error will occur when the request had a `Content-Encoding` header that |
||||||
|
contained an encoding but the "inflation" option was set to `false`. The |
||||||
|
`status` property is set to `415`, the `type` property is set to |
||||||
|
`'encoding.unsupported'`, and the `charset` property will be set to the |
||||||
|
encoding that is unsupported. |
||||||
|
|
||||||
|
### entity parse failed |
||||||
|
|
||||||
|
This error will occur when the request contained an entity that could not be |
||||||
|
parsed by the middleware. The `status` property is set to `400`, the `type` |
||||||
|
property is set to `'entity.parse.failed'`, and the `body` property is set to |
||||||
|
the entity value that failed parsing. |
||||||
|
|
||||||
|
### entity verify failed |
||||||
|
|
||||||
|
This error will occur when the request contained an entity that could not be |
||||||
|
failed verification by the defined `verify` option. The `status` property is |
||||||
|
set to `403`, the `type` property is set to `'entity.verify.failed'`, and the |
||||||
|
`body` property is set to the entity value that failed verification. |
||||||
|
|
||||||
|
### request aborted |
||||||
|
|
||||||
|
This error will occur when the request is aborted by the client before reading |
||||||
|
the body has finished. The `received` property will be set to the number of |
||||||
|
bytes received before the request was aborted and the `expected` property is |
||||||
|
set to the number of expected bytes. The `status` property is set to `400` |
||||||
|
and `type` property is set to `'request.aborted'`. |
||||||
|
|
||||||
|
### request entity too large |
||||||
|
|
||||||
|
This error will occur when the request body's size is larger than the "limit" |
||||||
|
option. The `limit` property will be set to the byte limit and the `length` |
||||||
|
property will be set to the request body's length. The `status` property is |
||||||
|
set to `413` and the `type` property is set to `'entity.too.large'`. |
||||||
|
|
||||||
|
### request size did not match content length |
||||||
|
|
||||||
|
This error will occur when the request's length did not match the length from |
||||||
|
the `Content-Length` header. This typically occurs when the request is malformed, |
||||||
|
typically when the `Content-Length` header was calculated based on characters |
||||||
|
instead of bytes. The `status` property is set to `400` and the `type` property |
||||||
|
is set to `'request.size.invalid'`. |
||||||
|
|
||||||
|
### stream encoding should not be set |
||||||
|
|
||||||
|
This error will occur when something called the `req.setEncoding` method prior |
||||||
|
to this middleware. This module operates directly on bytes only and you cannot |
||||||
|
call `req.setEncoding` when using this module. The `status` property is set to |
||||||
|
`500` and the `type` property is set to `'stream.encoding.set'`. |
||||||
|
|
||||||
|
### stream is not readable |
||||||
|
|
||||||
|
This error will occur when the request is no longer readable when this middleware |
||||||
|
attempts to read it. This typically means something other than a middleware from |
||||||
|
this module read the request body already and the middleware was also configured to |
||||||
|
read the same request. The `status` property is set to `500` and the `type` |
||||||
|
property is set to `'stream.not.readable'`. |
||||||
|
|
||||||
|
### too many parameters |
||||||
|
|
||||||
|
This error will occur when the content of the request exceeds the configured |
||||||
|
`parameterLimit` for the `urlencoded` parser. The `status` property is set to |
||||||
|
`413` and the `type` property is set to `'parameters.too.many'`. |
||||||
|
|
||||||
|
### unsupported charset "BOGUS" |
||||||
|
|
||||||
|
This error will occur when the request had a charset parameter in the |
||||||
|
`Content-Type` header, but the `iconv-lite` module does not support it OR the |
||||||
|
parser does not support it. The charset is contained in the message as well |
||||||
|
as in the `charset` property. The `status` property is set to `415`, the |
||||||
|
`type` property is set to `'charset.unsupported'`, and the `charset` property |
||||||
|
is set to the charset that is unsupported. |
||||||
|
|
||||||
|
### unsupported content encoding "bogus" |
||||||
|
|
||||||
|
This error will occur when the request had a `Content-Encoding` header that |
||||||
|
contained an unsupported encoding. The encoding is contained in the message |
||||||
|
as well as in the `encoding` property. The `status` property is set to `415`, |
||||||
|
the `type` property is set to `'encoding.unsupported'`, and the `encoding` |
||||||
|
property is set to the encoding that is unsupported. |
||||||
|
|
||||||
|
## Examples |
||||||
|
|
||||||
|
### Express/Connect top-level generic |
||||||
|
|
||||||
|
This example demonstrates adding a generic JSON and URL-encoded parser as a |
||||||
|
top-level middleware, which will parse the bodies of all incoming requests. |
||||||
|
This is the simplest setup. |
||||||
|
|
||||||
|
```js |
||||||
|
var express = require('express') |
||||||
|
var bodyParser = require('body-parser') |
||||||
|
|
||||||
|
var app = express() |
||||||
|
|
||||||
|
// parse application/x-www-form-urlencoded |
||||||
|
app.use(bodyParser.urlencoded({ extended: false })) |
||||||
|
|
||||||
|
// parse application/json |
||||||
|
app.use(bodyParser.json()) |
||||||
|
|
||||||
|
app.use(function (req, res) { |
||||||
|
res.setHeader('Content-Type', 'text/plain') |
||||||
|
res.write('you posted:\n') |
||||||
|
res.end(JSON.stringify(req.body, null, 2)) |
||||||
|
}) |
||||||
|
``` |
||||||
|
|
||||||
|
### Express route-specific |
||||||
|
|
||||||
|
This example demonstrates adding body parsers specifically to the routes that |
||||||
|
need them. In general, this is the most recommended way to use body-parser with |
||||||
|
Express. |
||||||
|
|
||||||
|
```js |
||||||
|
var express = require('express') |
||||||
|
var bodyParser = require('body-parser') |
||||||
|
|
||||||
|
var app = express() |
||||||
|
|
||||||
|
// create application/json parser |
||||||
|
var jsonParser = bodyParser.json() |
||||||
|
|
||||||
|
// create application/x-www-form-urlencoded parser |
||||||
|
var urlencodedParser = bodyParser.urlencoded({ extended: false }) |
||||||
|
|
||||||
|
// POST /login gets urlencoded bodies |
||||||
|
app.post('/login', urlencodedParser, function (req, res) { |
||||||
|
res.send('welcome, ' + req.body.username) |
||||||
|
}) |
||||||
|
|
||||||
|
// POST /api/users gets JSON bodies |
||||||
|
app.post('/api/users', jsonParser, function (req, res) { |
||||||
|
// create user in req.body |
||||||
|
}) |
||||||
|
``` |
||||||
|
|
||||||
|
### Change accepted type for parsers |
||||||
|
|
||||||
|
All the parsers accept a `type` option which allows you to change the |
||||||
|
`Content-Type` that the middleware will parse. |
||||||
|
|
||||||
|
```js |
||||||
|
var express = require('express') |
||||||
|
var bodyParser = require('body-parser') |
||||||
|
|
||||||
|
var app = express() |
||||||
|
|
||||||
|
// parse various different custom JSON types as JSON |
||||||
|
app.use(bodyParser.json({ type: 'application/*+json' })) |
||||||
|
|
||||||
|
// parse some custom thing into a Buffer |
||||||
|
app.use(bodyParser.raw({ type: 'application/vnd.custom-type' })) |
||||||
|
|
||||||
|
// parse an HTML body into a string |
||||||
|
app.use(bodyParser.text({ type: 'text/html' })) |
||||||
|
``` |
||||||
|
|
||||||
|
## License |
||||||
|
|
||||||
|
[MIT](LICENSE) |
||||||
|
|
||||||
|
[ci-image]: https://badgen.net/github/checks/expressjs/body-parser/master?label=ci |
||||||
|
[ci-url]: https://github.com/expressjs/body-parser/actions/workflows/ci.yml |
||||||
|
[coveralls-image]: https://badgen.net/coveralls/c/github/expressjs/body-parser/master |
||||||
|
[coveralls-url]: https://coveralls.io/r/expressjs/body-parser?branch=master |
||||||
|
[node-version-image]: https://badgen.net/npm/node/body-parser |
||||||
|
[node-version-url]: https://nodejs.org/en/download |
||||||
|
[npm-downloads-image]: https://badgen.net/npm/dm/body-parser |
||||||
|
[npm-url]: https://npmjs.org/package/body-parser |
||||||
|
[npm-version-image]: https://badgen.net/npm/v/body-parser |
@ -0,0 +1,25 @@ |
|||||||
|
# Security Policies and Procedures |
||||||
|
|
||||||
|
## Reporting a Bug |
||||||
|
|
||||||
|
The Express team and community take all security bugs seriously. Thank you |
||||||
|
for improving the security of Express. We appreciate your efforts and |
||||||
|
responsible disclosure and will make every effort to acknowledge your |
||||||
|
contributions. |
||||||
|
|
||||||
|
Report security bugs by emailing the current owner(s) of `body-parser`. This |
||||||
|
information can be found in the npm registry using the command |
||||||
|
`npm owner ls body-parser`. |
||||||
|
If unsure or unable to get the information from the above, open an issue |
||||||
|
in the [project issue tracker](https://github.com/expressjs/body-parser/issues) |
||||||
|
asking for the current contact information. |
||||||
|
|
||||||
|
To ensure the timely response to your report, please ensure that the entirety |
||||||
|
of the report is contained within the email body and not solely behind a web |
||||||
|
link or an attachment. |
||||||
|
|
||||||
|
At least one owner will acknowledge your email within 48 hours, and will send a |
||||||
|
more detailed response within 48 hours indicating the next steps in handling |
||||||
|
your report. After the initial reply to your report, the owners will |
||||||
|
endeavor to keep you informed of the progress towards a fix and full |
||||||
|
announcement, and may ask for additional information or guidance. |
@ -0,0 +1,156 @@ |
|||||||
|
/*! |
||||||
|
* body-parser |
||||||
|
* Copyright(c) 2014-2015 Douglas Christopher Wilson |
||||||
|
* MIT Licensed |
||||||
|
*/ |
||||||
|
|
||||||
|
'use strict' |
||||||
|
|
||||||
|
/** |
||||||
|
* Module dependencies. |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
var deprecate = require('depd')('body-parser') |
||||||
|
|
||||||
|
/** |
||||||
|
* Cache of loaded parsers. |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
var parsers = Object.create(null) |
||||||
|
|
||||||
|
/** |
||||||
|
* @typedef Parsers |
||||||
|
* @type {function} |
||||||
|
* @property {function} json |
||||||
|
* @property {function} raw |
||||||
|
* @property {function} text |
||||||
|
* @property {function} urlencoded |
||||||
|
*/ |
||||||
|
|
||||||
|
/** |
||||||
|
* Module exports. |
||||||
|
* @type {Parsers} |
||||||
|
*/ |
||||||
|
|
||||||
|
exports = module.exports = deprecate.function(bodyParser, |
||||||
|
'bodyParser: use individual json/urlencoded middlewares') |
||||||
|
|
||||||
|
/** |
||||||
|
* JSON parser. |
||||||
|
* @public |
||||||
|
*/ |
||||||
|
|
||||||
|
Object.defineProperty(exports, 'json', { |
||||||
|
configurable: true, |
||||||
|
enumerable: true, |
||||||
|
get: createParserGetter('json') |
||||||
|
}) |
||||||
|
|
||||||
|
/** |
||||||
|
* Raw parser. |
||||||
|
* @public |
||||||
|
*/ |
||||||
|
|
||||||
|
Object.defineProperty(exports, 'raw', { |
||||||
|
configurable: true, |
||||||
|
enumerable: true, |
||||||
|
get: createParserGetter('raw') |
||||||
|
}) |
||||||
|
|
||||||
|
/** |
||||||
|
* Text parser. |
||||||
|
* @public |
||||||
|
*/ |
||||||
|
|
||||||
|
Object.defineProperty(exports, 'text', { |
||||||
|
configurable: true, |
||||||
|
enumerable: true, |
||||||
|
get: createParserGetter('text') |
||||||
|
}) |
||||||
|
|
||||||
|
/** |
||||||
|
* URL-encoded parser. |
||||||
|
* @public |
||||||
|
*/ |
||||||
|
|
||||||
|
Object.defineProperty(exports, 'urlencoded', { |
||||||
|
configurable: true, |
||||||
|
enumerable: true, |
||||||
|
get: createParserGetter('urlencoded') |
||||||
|
}) |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a middleware to parse json and urlencoded bodies. |
||||||
|
* |
||||||
|
* @param {object} [options] |
||||||
|
* @return {function} |
||||||
|
* @deprecated |
||||||
|
* @public |
||||||
|
*/ |
||||||
|
|
||||||
|
function bodyParser (options) { |
||||||
|
// use default type for parsers
|
||||||
|
var opts = Object.create(options || null, { |
||||||
|
type: { |
||||||
|
configurable: true, |
||||||
|
enumerable: true, |
||||||
|
value: undefined, |
||||||
|
writable: true |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
var _urlencoded = exports.urlencoded(opts) |
||||||
|
var _json = exports.json(opts) |
||||||
|
|
||||||
|
return function bodyParser (req, res, next) { |
||||||
|
_json(req, res, function (err) { |
||||||
|
if (err) return next(err) |
||||||
|
_urlencoded(req, res, next) |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a getter for loading a parser. |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
function createParserGetter (name) { |
||||||
|
return function get () { |
||||||
|
return loadParser(name) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Load a parser module. |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
function loadParser (parserName) { |
||||||
|
var parser = parsers[parserName] |
||||||
|
|
||||||
|
if (parser !== undefined) { |
||||||
|
return parser |
||||||
|
} |
||||||
|
|
||||||
|
// this uses a switch for static require analysis
|
||||||
|
switch (parserName) { |
||||||
|
case 'json': |
||||||
|
parser = require('./lib/types/json') |
||||||
|
break |
||||||
|
case 'raw': |
||||||
|
parser = require('./lib/types/raw') |
||||||
|
break |
||||||
|
case 'text': |
||||||
|
parser = require('./lib/types/text') |
||||||
|
break |
||||||
|
case 'urlencoded': |
||||||
|
parser = require('./lib/types/urlencoded') |
||||||
|
break |
||||||
|
} |
||||||
|
|
||||||
|
// store to prevent invoking require()
|
||||||
|
return (parsers[parserName] = parser) |
||||||
|
} |
@ -0,0 +1,205 @@ |
|||||||
|
/*! |
||||||
|
* body-parser |
||||||
|
* Copyright(c) 2014-2015 Douglas Christopher Wilson |
||||||
|
* MIT Licensed |
||||||
|
*/ |
||||||
|
|
||||||
|
'use strict' |
||||||
|
|
||||||
|
/** |
||||||
|
* Module dependencies. |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
var createError = require('http-errors') |
||||||
|
var destroy = require('destroy') |
||||||
|
var getBody = require('raw-body') |
||||||
|
var iconv = require('iconv-lite') |
||||||
|
var onFinished = require('on-finished') |
||||||
|
var unpipe = require('unpipe') |
||||||
|
var zlib = require('zlib') |
||||||
|
|
||||||
|
/** |
||||||
|
* Module exports. |
||||||
|
*/ |
||||||
|
|
||||||
|
module.exports = read |
||||||
|
|
||||||
|
/** |
||||||
|
* Read a request into a buffer and parse. |
||||||
|
* |
||||||
|
* @param {object} req |
||||||
|
* @param {object} res |
||||||
|
* @param {function} next |
||||||
|
* @param {function} parse |
||||||
|
* @param {function} debug |
||||||
|
* @param {object} options |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
function read (req, res, next, parse, debug, options) { |
||||||
|
var length |
||||||
|
var opts = options |
||||||
|
var stream |
||||||
|
|
||||||
|
// flag as parsed
|
||||||
|
req._body = true |
||||||
|
|
||||||
|
// read options
|
||||||
|
var encoding = opts.encoding !== null |
||||||
|
? opts.encoding |
||||||
|
: null |
||||||
|
var verify = opts.verify |
||||||
|
|
||||||
|
try { |
||||||
|
// get the content stream
|
||||||
|
stream = contentstream(req, debug, opts.inflate) |
||||||
|
length = stream.length |
||||||
|
stream.length = undefined |
||||||
|
} catch (err) { |
||||||
|
return next(err) |
||||||
|
} |
||||||
|
|
||||||
|
// set raw-body options
|
||||||
|
opts.length = length |
||||||
|
opts.encoding = verify |
||||||
|
? null |
||||||
|
: encoding |
||||||
|
|
||||||
|
// assert charset is supported
|
||||||
|
if (opts.encoding === null && encoding !== null && !iconv.encodingExists(encoding)) { |
||||||
|
return next(createError(415, 'unsupported charset "' + encoding.toUpperCase() + '"', { |
||||||
|
charset: encoding.toLowerCase(), |
||||||
|
type: 'charset.unsupported' |
||||||
|
})) |
||||||
|
} |
||||||
|
|
||||||
|
// read body
|
||||||
|
debug('read body') |
||||||
|
getBody(stream, opts, function (error, body) { |
||||||
|
if (error) { |
||||||
|
var _error |
||||||
|
|
||||||
|
if (error.type === 'encoding.unsupported') { |
||||||
|
// echo back charset
|
||||||
|
_error = createError(415, 'unsupported charset "' + encoding.toUpperCase() + '"', { |
||||||
|
charset: encoding.toLowerCase(), |
||||||
|
type: 'charset.unsupported' |
||||||
|
}) |
||||||
|
} else { |
||||||
|
// set status code on error
|
||||||
|
_error = createError(400, error) |
||||||
|
} |
||||||
|
|
||||||
|
// unpipe from stream and destroy
|
||||||
|
if (stream !== req) { |
||||||
|
unpipe(req) |
||||||
|
destroy(stream, true) |
||||||
|
} |
||||||
|
|
||||||
|
// read off entire request
|
||||||
|
dump(req, function onfinished () { |
||||||
|
next(createError(400, _error)) |
||||||
|
}) |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
// verify
|
||||||
|
if (verify) { |
||||||
|
try { |
||||||
|
debug('verify body') |
||||||
|
verify(req, res, body, encoding) |
||||||
|
} catch (err) { |
||||||
|
next(createError(403, err, { |
||||||
|
body: body, |
||||||
|
type: err.type || 'entity.verify.failed' |
||||||
|
})) |
||||||
|
return |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// parse
|
||||||
|
var str = body |
||||||
|
try { |
||||||
|
debug('parse body') |
||||||
|
str = typeof body !== 'string' && encoding !== null |
||||||
|
? iconv.decode(body, encoding) |
||||||
|
: body |
||||||
|
req.body = parse(str) |
||||||
|
} catch (err) { |
||||||
|
next(createError(400, err, { |
||||||
|
body: str, |
||||||
|
type: err.type || 'entity.parse.failed' |
||||||
|
})) |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
next() |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get the content stream of the request. |
||||||
|
* |
||||||
|
* @param {object} req |
||||||
|
* @param {function} debug |
||||||
|
* @param {boolean} [inflate=true] |
||||||
|
* @return {object} |
||||||
|
* @api private |
||||||
|
*/ |
||||||
|
|
||||||
|
function contentstream (req, debug, inflate) { |
||||||
|
var encoding = (req.headers['content-encoding'] || 'identity').toLowerCase() |
||||||
|
var length = req.headers['content-length'] |
||||||
|
var stream |
||||||
|
|
||||||
|
debug('content-encoding "%s"', encoding) |
||||||
|
|
||||||
|
if (inflate === false && encoding !== 'identity') { |
||||||
|
throw createError(415, 'content encoding unsupported', { |
||||||
|
encoding: encoding, |
||||||
|
type: 'encoding.unsupported' |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
switch (encoding) { |
||||||
|
case 'deflate': |
||||||
|
stream = zlib.createInflate() |
||||||
|
debug('inflate body') |
||||||
|
req.pipe(stream) |
||||||
|
break |
||||||
|
case 'gzip': |
||||||
|
stream = zlib.createGunzip() |
||||||
|
debug('gunzip body') |
||||||
|
req.pipe(stream) |
||||||
|
break |
||||||
|
case 'identity': |
||||||
|
stream = req |
||||||
|
stream.length = length |
||||||
|
break |
||||||
|
default: |
||||||
|
throw createError(415, 'unsupported content encoding "' + encoding + '"', { |
||||||
|
encoding: encoding, |
||||||
|
type: 'encoding.unsupported' |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
return stream |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Dump the contents of a request. |
||||||
|
* |
||||||
|
* @param {object} req |
||||||
|
* @param {function} callback |
||||||
|
* @api private |
||||||
|
*/ |
||||||
|
|
||||||
|
function dump (req, callback) { |
||||||
|
if (onFinished.isFinished(req)) { |
||||||
|
callback(null) |
||||||
|
} else { |
||||||
|
onFinished(req, callback) |
||||||
|
req.resume() |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,247 @@ |
|||||||
|
/*! |
||||||
|
* body-parser |
||||||
|
* Copyright(c) 2014 Jonathan Ong |
||||||
|
* Copyright(c) 2014-2015 Douglas Christopher Wilson |
||||||
|
* MIT Licensed |
||||||
|
*/ |
||||||
|
|
||||||
|
'use strict' |
||||||
|
|
||||||
|
/** |
||||||
|
* Module dependencies. |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
var bytes = require('bytes') |
||||||
|
var contentType = require('content-type') |
||||||
|
var createError = require('http-errors') |
||||||
|
var debug = require('debug')('body-parser:json') |
||||||
|
var read = require('../read') |
||||||
|
var typeis = require('type-is') |
||||||
|
|
||||||
|
/** |
||||||
|
* Module exports. |
||||||
|
*/ |
||||||
|
|
||||||
|
module.exports = json |
||||||
|
|
||||||
|
/** |
||||||
|
* RegExp to match the first non-space in a string. |
||||||
|
* |
||||||
|
* Allowed whitespace is defined in RFC 7159: |
||||||
|
* |
||||||
|
* ws = *( |
||||||
|
* %x20 / ; Space |
||||||
|
* %x09 / ; Horizontal tab |
||||||
|
* %x0A / ; Line feed or New line |
||||||
|
* %x0D ) ; Carriage return |
||||||
|
*/ |
||||||
|
|
||||||
|
var FIRST_CHAR_REGEXP = /^[\x20\x09\x0a\x0d]*([^\x20\x09\x0a\x0d])/ // eslint-disable-line no-control-regex
|
||||||
|
|
||||||
|
var JSON_SYNTAX_CHAR = '#' |
||||||
|
var JSON_SYNTAX_REGEXP = /#+/g |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a middleware to parse JSON bodies. |
||||||
|
* |
||||||
|
* @param {object} [options] |
||||||
|
* @return {function} |
||||||
|
* @public |
||||||
|
*/ |
||||||
|
|
||||||
|
function json (options) { |
||||||
|
var opts = options || {} |
||||||
|
|
||||||
|
var limit = typeof opts.limit !== 'number' |
||||||
|
? bytes.parse(opts.limit || '100kb') |
||||||
|
: opts.limit |
||||||
|
var inflate = opts.inflate !== false |
||||||
|
var reviver = opts.reviver |
||||||
|
var strict = opts.strict !== false |
||||||
|
var type = opts.type || 'application/json' |
||||||
|
var verify = opts.verify || false |
||||||
|
|
||||||
|
if (verify !== false && typeof verify !== 'function') { |
||||||
|
throw new TypeError('option verify must be function') |
||||||
|
} |
||||||
|
|
||||||
|
// create the appropriate type checking function
|
||||||
|
var shouldParse = typeof type !== 'function' |
||||||
|
? typeChecker(type) |
||||||
|
: type |
||||||
|
|
||||||
|
function parse (body) { |
||||||
|
if (body.length === 0) { |
||||||
|
// special-case empty json body, as it's a common client-side mistake
|
||||||
|
// TODO: maybe make this configurable or part of "strict" option
|
||||||
|
return {} |
||||||
|
} |
||||||
|
|
||||||
|
if (strict) { |
||||||
|
var first = firstchar(body) |
||||||
|
|
||||||
|
if (first !== '{' && first !== '[') { |
||||||
|
debug('strict violation') |
||||||
|
throw createStrictSyntaxError(body, first) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
try { |
||||||
|
debug('parse json') |
||||||
|
return JSON.parse(body, reviver) |
||||||
|
} catch (e) { |
||||||
|
throw normalizeJsonSyntaxError(e, { |
||||||
|
message: e.message, |
||||||
|
stack: e.stack |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return function jsonParser (req, res, next) { |
||||||
|
if (req._body) { |
||||||
|
debug('body already parsed') |
||||||
|
next() |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
req.body = req.body || {} |
||||||
|
|
||||||
|
// skip requests without bodies
|
||||||
|
if (!typeis.hasBody(req)) { |
||||||
|
debug('skip empty body') |
||||||
|
next() |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
debug('content-type %j', req.headers['content-type']) |
||||||
|
|
||||||
|
// determine if request should be parsed
|
||||||
|
if (!shouldParse(req)) { |
||||||
|
debug('skip parsing') |
||||||
|
next() |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
// assert charset per RFC 7159 sec 8.1
|
||||||
|
var charset = getCharset(req) || 'utf-8' |
||||||
|
if (charset.slice(0, 4) !== 'utf-') { |
||||||
|
debug('invalid charset') |
||||||
|
next(createError(415, 'unsupported charset "' + charset.toUpperCase() + '"', { |
||||||
|
charset: charset, |
||||||
|
type: 'charset.unsupported' |
||||||
|
})) |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
// read
|
||||||
|
read(req, res, next, parse, debug, { |
||||||
|
encoding: charset, |
||||||
|
inflate: inflate, |
||||||
|
limit: limit, |
||||||
|
verify: verify |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create strict violation syntax error matching native error. |
||||||
|
* |
||||||
|
* @param {string} str |
||||||
|
* @param {string} char |
||||||
|
* @return {Error} |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
function createStrictSyntaxError (str, char) { |
||||||
|
var index = str.indexOf(char) |
||||||
|
var partial = '' |
||||||
|
|
||||||
|
if (index !== -1) { |
||||||
|
partial = str.substring(0, index) + JSON_SYNTAX_CHAR |
||||||
|
|
||||||
|
for (var i = index + 1; i < str.length; i++) { |
||||||
|
partial += JSON_SYNTAX_CHAR |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
try { |
||||||
|
JSON.parse(partial); /* istanbul ignore next */ throw new SyntaxError('strict violation') |
||||||
|
} catch (e) { |
||||||
|
return normalizeJsonSyntaxError(e, { |
||||||
|
message: e.message.replace(JSON_SYNTAX_REGEXP, function (placeholder) { |
||||||
|
return str.substring(index, index + placeholder.length) |
||||||
|
}), |
||||||
|
stack: e.stack |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get the first non-whitespace character in a string. |
||||||
|
* |
||||||
|
* @param {string} str |
||||||
|
* @return {function} |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
function firstchar (str) { |
||||||
|
var match = FIRST_CHAR_REGEXP.exec(str) |
||||||
|
|
||||||
|
return match |
||||||
|
? match[1] |
||||||
|
: undefined |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get the charset of a request. |
||||||
|
* |
||||||
|
* @param {object} req |
||||||
|
* @api private |
||||||
|
*/ |
||||||
|
|
||||||
|
function getCharset (req) { |
||||||
|
try { |
||||||
|
return (contentType.parse(req).parameters.charset || '').toLowerCase() |
||||||
|
} catch (e) { |
||||||
|
return undefined |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Normalize a SyntaxError for JSON.parse. |
||||||
|
* |
||||||
|
* @param {SyntaxError} error |
||||||
|
* @param {object} obj |
||||||
|
* @return {SyntaxError} |
||||||
|
*/ |
||||||
|
|
||||||
|
function normalizeJsonSyntaxError (error, obj) { |
||||||
|
var keys = Object.getOwnPropertyNames(error) |
||||||
|
|
||||||
|
for (var i = 0; i < keys.length; i++) { |
||||||
|
var key = keys[i] |
||||||
|
if (key !== 'stack' && key !== 'message') { |
||||||
|
delete error[key] |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// replace stack before message for Node.js 0.10 and below
|
||||||
|
error.stack = obj.stack.replace(error.message, obj.message) |
||||||
|
error.message = obj.message |
||||||
|
|
||||||
|
return error |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get the simple type checker. |
||||||
|
* |
||||||
|
* @param {string} type |
||||||
|
* @return {function} |
||||||
|
*/ |
||||||
|
|
||||||
|
function typeChecker (type) { |
||||||
|
return function checkType (req) { |
||||||
|
return Boolean(typeis(req, type)) |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,101 @@ |
|||||||
|
/*! |
||||||
|
* body-parser |
||||||
|
* Copyright(c) 2014-2015 Douglas Christopher Wilson |
||||||
|
* MIT Licensed |
||||||
|
*/ |
||||||
|
|
||||||
|
'use strict' |
||||||
|
|
||||||
|
/** |
||||||
|
* Module dependencies. |
||||||
|
*/ |
||||||
|
|
||||||
|
var bytes = require('bytes') |
||||||
|
var debug = require('debug')('body-parser:raw') |
||||||
|
var read = require('../read') |
||||||
|
var typeis = require('type-is') |
||||||
|
|
||||||
|
/** |
||||||
|
* Module exports. |
||||||
|
*/ |
||||||
|
|
||||||
|
module.exports = raw |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a middleware to parse raw bodies. |
||||||
|
* |
||||||
|
* @param {object} [options] |
||||||
|
* @return {function} |
||||||
|
* @api public |
||||||
|
*/ |
||||||
|
|
||||||
|
function raw (options) { |
||||||
|
var opts = options || {} |
||||||
|
|
||||||
|
var inflate = opts.inflate !== false |
||||||
|
var limit = typeof opts.limit !== 'number' |
||||||
|
? bytes.parse(opts.limit || '100kb') |
||||||
|
: opts.limit |
||||||
|
var type = opts.type || 'application/octet-stream' |
||||||
|
var verify = opts.verify || false |
||||||
|
|
||||||
|
if (verify !== false && typeof verify !== 'function') { |
||||||
|
throw new TypeError('option verify must be function') |
||||||
|
} |
||||||
|
|
||||||
|
// create the appropriate type checking function
|
||||||
|
var shouldParse = typeof type !== 'function' |
||||||
|
? typeChecker(type) |
||||||
|
: type |
||||||
|
|
||||||
|
function parse (buf) { |
||||||
|
return buf |
||||||
|
} |
||||||
|
|
||||||
|
return function rawParser (req, res, next) { |
||||||
|
if (req._body) { |
||||||
|
debug('body already parsed') |
||||||
|
next() |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
req.body = req.body || {} |
||||||
|
|
||||||
|
// skip requests without bodies
|
||||||
|
if (!typeis.hasBody(req)) { |
||||||
|
debug('skip empty body') |
||||||
|
next() |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
debug('content-type %j', req.headers['content-type']) |
||||||
|
|
||||||
|
// determine if request should be parsed
|
||||||
|
if (!shouldParse(req)) { |
||||||
|
debug('skip parsing') |
||||||
|
next() |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
// read
|
||||||
|
read(req, res, next, parse, debug, { |
||||||
|
encoding: null, |
||||||
|
inflate: inflate, |
||||||
|
limit: limit, |
||||||
|
verify: verify |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get the simple type checker. |
||||||
|
* |
||||||
|
* @param {string} type |
||||||
|
* @return {function} |
||||||
|
*/ |
||||||
|
|
||||||
|
function typeChecker (type) { |
||||||
|
return function checkType (req) { |
||||||
|
return Boolean(typeis(req, type)) |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,121 @@ |
|||||||
|
/*! |
||||||
|
* body-parser |
||||||
|
* Copyright(c) 2014-2015 Douglas Christopher Wilson |
||||||
|
* MIT Licensed |
||||||
|
*/ |
||||||
|
|
||||||
|
'use strict' |
||||||
|
|
||||||
|
/** |
||||||
|
* Module dependencies. |
||||||
|
*/ |
||||||
|
|
||||||
|
var bytes = require('bytes') |
||||||
|
var contentType = require('content-type') |
||||||
|
var debug = require('debug')('body-parser:text') |
||||||
|
var read = require('../read') |
||||||
|
var typeis = require('type-is') |
||||||
|
|
||||||
|
/** |
||||||
|
* Module exports. |
||||||
|
*/ |
||||||
|
|
||||||
|
module.exports = text |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a middleware to parse text bodies. |
||||||
|
* |
||||||
|
* @param {object} [options] |
||||||
|
* @return {function} |
||||||
|
* @api public |
||||||
|
*/ |
||||||
|
|
||||||
|
function text (options) { |
||||||
|
var opts = options || {} |
||||||
|
|
||||||
|
var defaultCharset = opts.defaultCharset || 'utf-8' |
||||||
|
var inflate = opts.inflate !== false |
||||||
|
var limit = typeof opts.limit !== 'number' |
||||||
|
? bytes.parse(opts.limit || '100kb') |
||||||
|
: opts.limit |
||||||
|
var type = opts.type || 'text/plain' |
||||||
|
var verify = opts.verify || false |
||||||
|
|
||||||
|
if (verify !== false && typeof verify !== 'function') { |
||||||
|
throw new TypeError('option verify must be function') |
||||||
|
} |
||||||
|
|
||||||
|
// create the appropriate type checking function
|
||||||
|
var shouldParse = typeof type !== 'function' |
||||||
|
? typeChecker(type) |
||||||
|
: type |
||||||
|
|
||||||
|
function parse (buf) { |
||||||
|
return buf |
||||||
|
} |
||||||
|
|
||||||
|
return function textParser (req, res, next) { |
||||||
|
if (req._body) { |
||||||
|
debug('body already parsed') |
||||||
|
next() |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
req.body = req.body || {} |
||||||
|
|
||||||
|
// skip requests without bodies
|
||||||
|
if (!typeis.hasBody(req)) { |
||||||
|
debug('skip empty body') |
||||||
|
next() |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
debug('content-type %j', req.headers['content-type']) |
||||||
|
|
||||||
|
// determine if request should be parsed
|
||||||
|
if (!shouldParse(req)) { |
||||||
|
debug('skip parsing') |
||||||
|
next() |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
// get charset
|
||||||
|
var charset = getCharset(req) || defaultCharset |
||||||
|
|
||||||
|
// read
|
||||||
|
read(req, res, next, parse, debug, { |
||||||
|
encoding: charset, |
||||||
|
inflate: inflate, |
||||||
|
limit: limit, |
||||||
|
verify: verify |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get the charset of a request. |
||||||
|
* |
||||||
|
* @param {object} req |
||||||
|
* @api private |
||||||
|
*/ |
||||||
|
|
||||||
|
function getCharset (req) { |
||||||
|
try { |
||||||
|
return (contentType.parse(req).parameters.charset || '').toLowerCase() |
||||||
|
} catch (e) { |
||||||
|
return undefined |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get the simple type checker. |
||||||
|
* |
||||||
|
* @param {string} type |
||||||
|
* @return {function} |
||||||
|
*/ |
||||||
|
|
||||||
|
function typeChecker (type) { |
||||||
|
return function checkType (req) { |
||||||
|
return Boolean(typeis(req, type)) |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,284 @@ |
|||||||
|
/*! |
||||||
|
* body-parser |
||||||
|
* Copyright(c) 2014 Jonathan Ong |
||||||
|
* Copyright(c) 2014-2015 Douglas Christopher Wilson |
||||||
|
* MIT Licensed |
||||||
|
*/ |
||||||
|
|
||||||
|
'use strict' |
||||||
|
|
||||||
|
/** |
||||||
|
* Module dependencies. |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
var bytes = require('bytes') |
||||||
|
var contentType = require('content-type') |
||||||
|
var createError = require('http-errors') |
||||||
|
var debug = require('debug')('body-parser:urlencoded') |
||||||
|
var deprecate = require('depd')('body-parser') |
||||||
|
var read = require('../read') |
||||||
|
var typeis = require('type-is') |
||||||
|
|
||||||
|
/** |
||||||
|
* Module exports. |
||||||
|
*/ |
||||||
|
|
||||||
|
module.exports = urlencoded |
||||||
|
|
||||||
|
/** |
||||||
|
* Cache of parser modules. |
||||||
|
*/ |
||||||
|
|
||||||
|
var parsers = Object.create(null) |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a middleware to parse urlencoded bodies. |
||||||
|
* |
||||||
|
* @param {object} [options] |
||||||
|
* @return {function} |
||||||
|
* @public |
||||||
|
*/ |
||||||
|
|
||||||
|
function urlencoded (options) { |
||||||
|
var opts = options || {} |
||||||
|
|
||||||
|
// notice because option default will flip in next major
|
||||||
|
if (opts.extended === undefined) { |
||||||
|
deprecate('undefined extended: provide extended option') |
||||||
|
} |
||||||
|
|
||||||
|
var extended = opts.extended !== false |
||||||
|
var inflate = opts.inflate !== false |
||||||
|
var limit = typeof opts.limit !== 'number' |
||||||
|
? bytes.parse(opts.limit || '100kb') |
||||||
|
: opts.limit |
||||||
|
var type = opts.type || 'application/x-www-form-urlencoded' |
||||||
|
var verify = opts.verify || false |
||||||
|
|
||||||
|
if (verify !== false && typeof verify !== 'function') { |
||||||
|
throw new TypeError('option verify must be function') |
||||||
|
} |
||||||
|
|
||||||
|
// create the appropriate query parser
|
||||||
|
var queryparse = extended |
||||||
|
? extendedparser(opts) |
||||||
|
: simpleparser(opts) |
||||||
|
|
||||||
|
// create the appropriate type checking function
|
||||||
|
var shouldParse = typeof type !== 'function' |
||||||
|
? typeChecker(type) |
||||||
|
: type |
||||||
|
|
||||||
|
function parse (body) { |
||||||
|
return body.length |
||||||
|
? queryparse(body) |
||||||
|
: {} |
||||||
|
} |
||||||
|
|
||||||
|
return function urlencodedParser (req, res, next) { |
||||||
|
if (req._body) { |
||||||
|
debug('body already parsed') |
||||||
|
next() |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
req.body = req.body || {} |
||||||
|
|
||||||
|
// skip requests without bodies
|
||||||
|
if (!typeis.hasBody(req)) { |
||||||
|
debug('skip empty body') |
||||||
|
next() |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
debug('content-type %j', req.headers['content-type']) |
||||||
|
|
||||||
|
// determine if request should be parsed
|
||||||
|
if (!shouldParse(req)) { |
||||||
|
debug('skip parsing') |
||||||
|
next() |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
// assert charset
|
||||||
|
var charset = getCharset(req) || 'utf-8' |
||||||
|
if (charset !== 'utf-8') { |
||||||
|
debug('invalid charset') |
||||||
|
next(createError(415, 'unsupported charset "' + charset.toUpperCase() + '"', { |
||||||
|
charset: charset, |
||||||
|
type: 'charset.unsupported' |
||||||
|
})) |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
// read
|
||||||
|
read(req, res, next, parse, debug, { |
||||||
|
debug: debug, |
||||||
|
encoding: charset, |
||||||
|
inflate: inflate, |
||||||
|
limit: limit, |
||||||
|
verify: verify |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get the extended query parser. |
||||||
|
* |
||||||
|
* @param {object} options |
||||||
|
*/ |
||||||
|
|
||||||
|
function extendedparser (options) { |
||||||
|
var parameterLimit = options.parameterLimit !== undefined |
||||||
|
? options.parameterLimit |
||||||
|
: 1000 |
||||||
|
var parse = parser('qs') |
||||||
|
|
||||||
|
if (isNaN(parameterLimit) || parameterLimit < 1) { |
||||||
|
throw new TypeError('option parameterLimit must be a positive number') |
||||||
|
} |
||||||
|
|
||||||
|
if (isFinite(parameterLimit)) { |
||||||
|
parameterLimit = parameterLimit | 0 |
||||||
|
} |
||||||
|
|
||||||
|
return function queryparse (body) { |
||||||
|
var paramCount = parameterCount(body, parameterLimit) |
||||||
|
|
||||||
|
if (paramCount === undefined) { |
||||||
|
debug('too many parameters') |
||||||
|
throw createError(413, 'too many parameters', { |
||||||
|
type: 'parameters.too.many' |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
var arrayLimit = Math.max(100, paramCount) |
||||||
|
|
||||||
|
debug('parse extended urlencoding') |
||||||
|
return parse(body, { |
||||||
|
allowPrototypes: true, |
||||||
|
arrayLimit: arrayLimit, |
||||||
|
depth: Infinity, |
||||||
|
parameterLimit: parameterLimit |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get the charset of a request. |
||||||
|
* |
||||||
|
* @param {object} req |
||||||
|
* @api private |
||||||
|
*/ |
||||||
|
|
||||||
|
function getCharset (req) { |
||||||
|
try { |
||||||
|
return (contentType.parse(req).parameters.charset || '').toLowerCase() |
||||||
|
} catch (e) { |
||||||
|
return undefined |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Count the number of parameters, stopping once limit reached |
||||||
|
* |
||||||
|
* @param {string} body |
||||||
|
* @param {number} limit |
||||||
|
* @api private |
||||||
|
*/ |
||||||
|
|
||||||
|
function parameterCount (body, limit) { |
||||||
|
var count = 0 |
||||||
|
var index = 0 |
||||||
|
|
||||||
|
while ((index = body.indexOf('&', index)) !== -1) { |
||||||
|
count++ |
||||||
|
index++ |
||||||
|
|
||||||
|
if (count === limit) { |
||||||
|
return undefined |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return count |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get parser for module name dynamically. |
||||||
|
* |
||||||
|
* @param {string} name |
||||||
|
* @return {function} |
||||||
|
* @api private |
||||||
|
*/ |
||||||
|
|
||||||
|
function parser (name) { |
||||||
|
var mod = parsers[name] |
||||||
|
|
||||||
|
if (mod !== undefined) { |
||||||
|
return mod.parse |
||||||
|
} |
||||||
|
|
||||||
|
// this uses a switch for static require analysis
|
||||||
|
switch (name) { |
||||||
|
case 'qs': |
||||||
|
mod = require('qs') |
||||||
|
break |
||||||
|
case 'querystring': |
||||||
|
mod = require('querystring') |
||||||
|
break |
||||||
|
} |
||||||
|
|
||||||
|
// store to prevent invoking require()
|
||||||
|
parsers[name] = mod |
||||||
|
|
||||||
|
return mod.parse |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get the simple query parser. |
||||||
|
* |
||||||
|
* @param {object} options |
||||||
|
*/ |
||||||
|
|
||||||
|
function simpleparser (options) { |
||||||
|
var parameterLimit = options.parameterLimit !== undefined |
||||||
|
? options.parameterLimit |
||||||
|
: 1000 |
||||||
|
var parse = parser('querystring') |
||||||
|
|
||||||
|
if (isNaN(parameterLimit) || parameterLimit < 1) { |
||||||
|
throw new TypeError('option parameterLimit must be a positive number') |
||||||
|
} |
||||||
|
|
||||||
|
if (isFinite(parameterLimit)) { |
||||||
|
parameterLimit = parameterLimit | 0 |
||||||
|
} |
||||||
|
|
||||||
|
return function queryparse (body) { |
||||||
|
var paramCount = parameterCount(body, parameterLimit) |
||||||
|
|
||||||
|
if (paramCount === undefined) { |
||||||
|
debug('too many parameters') |
||||||
|
throw createError(413, 'too many parameters', { |
||||||
|
type: 'parameters.too.many' |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
debug('parse urlencoding') |
||||||
|
return parse(body, undefined, undefined, { maxKeys: parameterLimit }) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get the simple type checker. |
||||||
|
* |
||||||
|
* @param {string} type |
||||||
|
* @return {function} |
||||||
|
*/ |
||||||
|
|
||||||
|
function typeChecker (type) { |
||||||
|
return function checkType (req) { |
||||||
|
return Boolean(typeis(req, type)) |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,56 @@ |
|||||||
|
{ |
||||||
|
"name": "body-parser", |
||||||
|
"description": "Node.js body parsing middleware", |
||||||
|
"version": "1.20.2", |
||||||
|
"contributors": [ |
||||||
|
"Douglas Christopher Wilson <doug@somethingdoug.com>", |
||||||
|
"Jonathan Ong <me@jongleberry.com> (http://jongleberry.com)" |
||||||
|
], |
||||||
|
"license": "MIT", |
||||||
|
"repository": "expressjs/body-parser", |
||||||
|
"dependencies": { |
||||||
|
"bytes": "3.1.2", |
||||||
|
"content-type": "~1.0.5", |
||||||
|
"debug": "2.6.9", |
||||||
|
"depd": "2.0.0", |
||||||
|
"destroy": "1.2.0", |
||||||
|
"http-errors": "2.0.0", |
||||||
|
"iconv-lite": "0.4.24", |
||||||
|
"on-finished": "2.4.1", |
||||||
|
"qs": "6.11.0", |
||||||
|
"raw-body": "2.5.2", |
||||||
|
"type-is": "~1.6.18", |
||||||
|
"unpipe": "1.0.0" |
||||||
|
}, |
||||||
|
"devDependencies": { |
||||||
|
"eslint": "8.34.0", |
||||||
|
"eslint-config-standard": "14.1.1", |
||||||
|
"eslint-plugin-import": "2.27.5", |
||||||
|
"eslint-plugin-markdown": "3.0.0", |
||||||
|
"eslint-plugin-node": "11.1.0", |
||||||
|
"eslint-plugin-promise": "6.1.1", |
||||||
|
"eslint-plugin-standard": "4.1.0", |
||||||
|
"methods": "1.1.2", |
||||||
|
"mocha": "10.2.0", |
||||||
|
"nyc": "15.1.0", |
||||||
|
"safe-buffer": "5.2.1", |
||||||
|
"supertest": "6.3.3" |
||||||
|
}, |
||||||
|
"files": [ |
||||||
|
"lib/", |
||||||
|
"LICENSE", |
||||||
|
"HISTORY.md", |
||||||
|
"SECURITY.md", |
||||||
|
"index.js" |
||||||
|
], |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.8", |
||||||
|
"npm": "1.2.8000 || >= 1.4.16" |
||||||
|
}, |
||||||
|
"scripts": { |
||||||
|
"lint": "eslint .", |
||||||
|
"test": "mocha --require test/support/env --reporter spec --check-leaks --bail test/", |
||||||
|
"test-ci": "nyc --reporter=lcov --reporter=text npm test", |
||||||
|
"test-cov": "nyc --reporter=html --reporter=text npm test" |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,97 @@ |
|||||||
|
3.1.2 / 2022-01-27 |
||||||
|
================== |
||||||
|
|
||||||
|
* Fix return value for un-parsable strings |
||||||
|
|
||||||
|
3.1.1 / 2021-11-15 |
||||||
|
================== |
||||||
|
|
||||||
|
* Fix "thousandsSeparator" incorrecting formatting fractional part |
||||||
|
|
||||||
|
3.1.0 / 2019-01-22 |
||||||
|
================== |
||||||
|
|
||||||
|
* Add petabyte (`pb`) support |
||||||
|
|
||||||
|
3.0.0 / 2017-08-31 |
||||||
|
================== |
||||||
|
|
||||||
|
* Change "kB" to "KB" in format output |
||||||
|
* Remove support for Node.js 0.6 |
||||||
|
* Remove support for ComponentJS |
||||||
|
|
||||||
|
2.5.0 / 2017-03-24 |
||||||
|
================== |
||||||
|
|
||||||
|
* Add option "unit" |
||||||
|
|
||||||
|
2.4.0 / 2016-06-01 |
||||||
|
================== |
||||||
|
|
||||||
|
* Add option "unitSeparator" |
||||||
|
|
||||||
|
2.3.0 / 2016-02-15 |
||||||
|
================== |
||||||
|
|
||||||
|
* Drop partial bytes on all parsed units |
||||||
|
* Fix non-finite numbers to `.format` to return `null` |
||||||
|
* Fix parsing byte string that looks like hex |
||||||
|
* perf: hoist regular expressions |
||||||
|
|
||||||
|
2.2.0 / 2015-11-13 |
||||||
|
================== |
||||||
|
|
||||||
|
* add option "decimalPlaces" |
||||||
|
* add option "fixedDecimals" |
||||||
|
|
||||||
|
2.1.0 / 2015-05-21 |
||||||
|
================== |
||||||
|
|
||||||
|
* add `.format` export |
||||||
|
* add `.parse` export |
||||||
|
|
||||||
|
2.0.2 / 2015-05-20 |
||||||
|
================== |
||||||
|
|
||||||
|
* remove map recreation |
||||||
|
* remove unnecessary object construction |
||||||
|
|
||||||
|
2.0.1 / 2015-05-07 |
||||||
|
================== |
||||||
|
|
||||||
|
* fix browserify require |
||||||
|
* remove node.extend dependency |
||||||
|
|
||||||
|
2.0.0 / 2015-04-12 |
||||||
|
================== |
||||||
|
|
||||||
|
* add option "case" |
||||||
|
* add option "thousandsSeparator" |
||||||
|
* return "null" on invalid parse input |
||||||
|
* support proper round-trip: bytes(bytes(num)) === num |
||||||
|
* units no longer case sensitive when parsing |
||||||
|
|
||||||
|
1.0.0 / 2014-05-05 |
||||||
|
================== |
||||||
|
|
||||||
|
* add negative support. fixes #6 |
||||||
|
|
||||||
|
0.3.0 / 2014-03-19 |
||||||
|
================== |
||||||
|
|
||||||
|
* added terabyte support |
||||||
|
|
||||||
|
0.2.1 / 2013-04-01 |
||||||
|
================== |
||||||
|
|
||||||
|
* add .component |
||||||
|
|
||||||
|
0.2.0 / 2012-10-28 |
||||||
|
================== |
||||||
|
|
||||||
|
* bytes(200).should.eql('200b') |
||||||
|
|
||||||
|
0.1.0 / 2012-07-04 |
||||||
|
================== |
||||||
|
|
||||||
|
* add bytes to string conversion [yields] |
@ -0,0 +1,23 @@ |
|||||||
|
(The MIT License) |
||||||
|
|
||||||
|
Copyright (c) 2012-2014 TJ Holowaychuk <tj@vision-media.ca> |
||||||
|
Copyright (c) 2015 Jed Watson <jed.watson@me.com> |
||||||
|
|
||||||
|
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. |
@ -0,0 +1,152 @@ |
|||||||
|
# Bytes utility |
||||||
|
|
||||||
|
[![NPM Version][npm-image]][npm-url] |
||||||
|
[![NPM Downloads][downloads-image]][downloads-url] |
||||||
|
[![Build Status][ci-image]][ci-url] |
||||||
|
[![Test Coverage][coveralls-image]][coveralls-url] |
||||||
|
|
||||||
|
Utility to parse a string bytes (ex: `1TB`) to bytes (`1099511627776`) and vice-versa. |
||||||
|
|
||||||
|
## Installation |
||||||
|
|
||||||
|
This is a [Node.js](https://nodejs.org/en/) module available through the |
||||||
|
[npm registry](https://www.npmjs.com/). Installation is done using the |
||||||
|
[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): |
||||||
|
|
||||||
|
```bash |
||||||
|
$ npm install bytes |
||||||
|
``` |
||||||
|
|
||||||
|
## Usage |
||||||
|
|
||||||
|
```js |
||||||
|
var bytes = require('bytes'); |
||||||
|
``` |
||||||
|
|
||||||
|
#### bytes(number|string value, [options]): number|string|null |
||||||
|
|
||||||
|
Default export function. Delegates to either `bytes.format` or `bytes.parse` based on the type of `value`. |
||||||
|
|
||||||
|
**Arguments** |
||||||
|
|
||||||
|
| Name | Type | Description | |
||||||
|
|---------|----------|--------------------| |
||||||
|
| value | `number`|`string` | Number value to format or string value to parse | |
||||||
|
| options | `Object` | Conversion options for `format` | |
||||||
|
|
||||||
|
**Returns** |
||||||
|
|
||||||
|
| Name | Type | Description | |
||||||
|
|---------|------------------|-------------------------------------------------| |
||||||
|
| results | `string`|`number`|`null` | Return null upon error. Numeric value in bytes, or string value otherwise. | |
||||||
|
|
||||||
|
**Example** |
||||||
|
|
||||||
|
```js |
||||||
|
bytes(1024); |
||||||
|
// output: '1KB' |
||||||
|
|
||||||
|
bytes('1KB'); |
||||||
|
// output: 1024 |
||||||
|
``` |
||||||
|
|
||||||
|
#### bytes.format(number value, [options]): string|null |
||||||
|
|
||||||
|
Format the given value in bytes into a string. If the value is negative, it is kept as such. If it is a float, it is |
||||||
|
rounded. |
||||||
|
|
||||||
|
**Arguments** |
||||||
|
|
||||||
|
| Name | Type | Description | |
||||||
|
|---------|----------|--------------------| |
||||||
|
| value | `number` | Value in bytes | |
||||||
|
| options | `Object` | Conversion options | |
||||||
|
|
||||||
|
**Options** |
||||||
|
|
||||||
|
| Property | Type | Description | |
||||||
|
|-------------------|--------|-----------------------------------------------------------------------------------------| |
||||||
|
| decimalPlaces | `number`|`null` | Maximum number of decimal places to include in output. Default value to `2`. | |
||||||
|
| fixedDecimals | `boolean`|`null` | Whether to always display the maximum number of decimal places. Default value to `false` | |
||||||
|
| thousandsSeparator | `string`|`null` | Example of values: `' '`, `','` and `'.'`... Default value to `''`. | |
||||||
|
| unit | `string`|`null` | The unit in which the result will be returned (B/KB/MB/GB/TB). Default value to `''` (which means auto detect). | |
||||||
|
| unitSeparator | `string`|`null` | Separator to use between number and unit. Default value to `''`. | |
||||||
|
|
||||||
|
**Returns** |
||||||
|
|
||||||
|
| Name | Type | Description | |
||||||
|
|---------|------------------|-------------------------------------------------| |
||||||
|
| results | `string`|`null` | Return null upon error. String value otherwise. | |
||||||
|
|
||||||
|
**Example** |
||||||
|
|
||||||
|
```js |
||||||
|
bytes.format(1024); |
||||||
|
// output: '1KB' |
||||||
|
|
||||||
|
bytes.format(1000); |
||||||
|
// output: '1000B' |
||||||
|
|
||||||
|
bytes.format(1000, {thousandsSeparator: ' '}); |
||||||
|
// output: '1 000B' |
||||||
|
|
||||||
|
bytes.format(1024 * 1.7, {decimalPlaces: 0}); |
||||||
|
// output: '2KB' |
||||||
|
|
||||||
|
bytes.format(1024, {unitSeparator: ' '}); |
||||||
|
// output: '1 KB' |
||||||
|
``` |
||||||
|
|
||||||
|
#### bytes.parse(string|number value): number|null |
||||||
|
|
||||||
|
Parse the string value into an integer in bytes. If no unit is given, or `value` |
||||||
|
is a number, it is assumed the value is in bytes. |
||||||
|
|
||||||
|
Supported units and abbreviations are as follows and are case-insensitive: |
||||||
|
|
||||||
|
* `b` for bytes |
||||||
|
* `kb` for kilobytes |
||||||
|
* `mb` for megabytes |
||||||
|
* `gb` for gigabytes |
||||||
|
* `tb` for terabytes |
||||||
|
* `pb` for petabytes |
||||||
|
|
||||||
|
The units are in powers of two, not ten. This means 1kb = 1024b according to this parser. |
||||||
|
|
||||||
|
**Arguments** |
||||||
|
|
||||||
|
| Name | Type | Description | |
||||||
|
|---------------|--------|--------------------| |
||||||
|
| value | `string`|`number` | String to parse, or number in bytes. | |
||||||
|
|
||||||
|
**Returns** |
||||||
|
|
||||||
|
| Name | Type | Description | |
||||||
|
|---------|-------------|-------------------------| |
||||||
|
| results | `number`|`null` | Return null upon error. Value in bytes otherwise. | |
||||||
|
|
||||||
|
**Example** |
||||||
|
|
||||||
|
```js |
||||||
|
bytes.parse('1KB'); |
||||||
|
// output: 1024 |
||||||
|
|
||||||
|
bytes.parse('1024'); |
||||||
|
// output: 1024 |
||||||
|
|
||||||
|
bytes.parse(1024); |
||||||
|
// output: 1024 |
||||||
|
``` |
||||||
|
|
||||||
|
## License |
||||||
|
|
||||||
|
[MIT](LICENSE) |
||||||
|
|
||||||
|
[ci-image]: https://badgen.net/github/checks/visionmedia/bytes.js/master?label=ci |
||||||
|
[ci-url]: https://github.com/visionmedia/bytes.js/actions?query=workflow%3Aci |
||||||
|
[coveralls-image]: https://badgen.net/coveralls/c/github/visionmedia/bytes.js/master |
||||||
|
[coveralls-url]: https://coveralls.io/r/visionmedia/bytes.js?branch=master |
||||||
|
[downloads-image]: https://badgen.net/npm/dm/bytes |
||||||
|
[downloads-url]: https://npmjs.org/package/bytes |
||||||
|
[npm-image]: https://badgen.net/npm/v/bytes |
||||||
|
[npm-url]: https://npmjs.org/package/bytes |
@ -0,0 +1,170 @@ |
|||||||
|
/*! |
||||||
|
* bytes |
||||||
|
* Copyright(c) 2012-2014 TJ Holowaychuk |
||||||
|
* Copyright(c) 2015 Jed Watson |
||||||
|
* MIT Licensed |
||||||
|
*/ |
||||||
|
|
||||||
|
'use strict'; |
||||||
|
|
||||||
|
/** |
||||||
|
* Module exports. |
||||||
|
* @public |
||||||
|
*/ |
||||||
|
|
||||||
|
module.exports = bytes; |
||||||
|
module.exports.format = format; |
||||||
|
module.exports.parse = parse; |
||||||
|
|
||||||
|
/** |
||||||
|
* Module variables. |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
var formatThousandsRegExp = /\B(?=(\d{3})+(?!\d))/g; |
||||||
|
|
||||||
|
var formatDecimalsRegExp = /(?:\.0*|(\.[^0]+)0+)$/; |
||||||
|
|
||||||
|
var map = { |
||||||
|
b: 1, |
||||||
|
kb: 1 << 10, |
||||||
|
mb: 1 << 20, |
||||||
|
gb: 1 << 30, |
||||||
|
tb: Math.pow(1024, 4), |
||||||
|
pb: Math.pow(1024, 5), |
||||||
|
}; |
||||||
|
|
||||||
|
var parseRegExp = /^((-|\+)?(\d+(?:\.\d+)?)) *(kb|mb|gb|tb|pb)$/i; |
||||||
|
|
||||||
|
/** |
||||||
|
* Convert the given value in bytes into a string or parse to string to an integer in bytes. |
||||||
|
* |
||||||
|
* @param {string|number} value |
||||||
|
* @param {{ |
||||||
|
* case: [string], |
||||||
|
* decimalPlaces: [number] |
||||||
|
* fixedDecimals: [boolean] |
||||||
|
* thousandsSeparator: [string] |
||||||
|
* unitSeparator: [string] |
||||||
|
* }} [options] bytes options. |
||||||
|
* |
||||||
|
* @returns {string|number|null} |
||||||
|
*/ |
||||||
|
|
||||||
|
function bytes(value, options) { |
||||||
|
if (typeof value === 'string') { |
||||||
|
return parse(value); |
||||||
|
} |
||||||
|
|
||||||
|
if (typeof value === 'number') { |
||||||
|
return format(value, options); |
||||||
|
} |
||||||
|
|
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Format the given value in bytes into a string. |
||||||
|
* |
||||||
|
* If the value is negative, it is kept as such. If it is a float, |
||||||
|
* it is rounded. |
||||||
|
* |
||||||
|
* @param {number} value |
||||||
|
* @param {object} [options] |
||||||
|
* @param {number} [options.decimalPlaces=2] |
||||||
|
* @param {number} [options.fixedDecimals=false] |
||||||
|
* @param {string} [options.thousandsSeparator=] |
||||||
|
* @param {string} [options.unit=] |
||||||
|
* @param {string} [options.unitSeparator=] |
||||||
|
* |
||||||
|
* @returns {string|null} |
||||||
|
* @public |
||||||
|
*/ |
||||||
|
|
||||||
|
function format(value, options) { |
||||||
|
if (!Number.isFinite(value)) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
var mag = Math.abs(value); |
||||||
|
var thousandsSeparator = (options && options.thousandsSeparator) || ''; |
||||||
|
var unitSeparator = (options && options.unitSeparator) || ''; |
||||||
|
var decimalPlaces = (options && options.decimalPlaces !== undefined) ? options.decimalPlaces : 2; |
||||||
|
var fixedDecimals = Boolean(options && options.fixedDecimals); |
||||||
|
var unit = (options && options.unit) || ''; |
||||||
|
|
||||||
|
if (!unit || !map[unit.toLowerCase()]) { |
||||||
|
if (mag >= map.pb) { |
||||||
|
unit = 'PB'; |
||||||
|
} else if (mag >= map.tb) { |
||||||
|
unit = 'TB'; |
||||||
|
} else if (mag >= map.gb) { |
||||||
|
unit = 'GB'; |
||||||
|
} else if (mag >= map.mb) { |
||||||
|
unit = 'MB'; |
||||||
|
} else if (mag >= map.kb) { |
||||||
|
unit = 'KB'; |
||||||
|
} else { |
||||||
|
unit = 'B'; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
var val = value / map[unit.toLowerCase()]; |
||||||
|
var str = val.toFixed(decimalPlaces); |
||||||
|
|
||||||
|
if (!fixedDecimals) { |
||||||
|
str = str.replace(formatDecimalsRegExp, '$1'); |
||||||
|
} |
||||||
|
|
||||||
|
if (thousandsSeparator) { |
||||||
|
str = str.split('.').map(function (s, i) { |
||||||
|
return i === 0 |
||||||
|
? s.replace(formatThousandsRegExp, thousandsSeparator) |
||||||
|
: s |
||||||
|
}).join('.'); |
||||||
|
} |
||||||
|
|
||||||
|
return str + unitSeparator + unit; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Parse the string value into an integer in bytes. |
||||||
|
* |
||||||
|
* If no unit is given, it is assumed the value is in bytes. |
||||||
|
* |
||||||
|
* @param {number|string} val |
||||||
|
* |
||||||
|
* @returns {number|null} |
||||||
|
* @public |
||||||
|
*/ |
||||||
|
|
||||||
|
function parse(val) { |
||||||
|
if (typeof val === 'number' && !isNaN(val)) { |
||||||
|
return val; |
||||||
|
} |
||||||
|
|
||||||
|
if (typeof val !== 'string') { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
// Test if the string passed is valid
|
||||||
|
var results = parseRegExp.exec(val); |
||||||
|
var floatValue; |
||||||
|
var unit = 'b'; |
||||||
|
|
||||||
|
if (!results) { |
||||||
|
// Nothing could be extracted from the given string
|
||||||
|
floatValue = parseInt(val, 10); |
||||||
|
unit = 'b' |
||||||
|
} else { |
||||||
|
// Retrieve the value and the unit
|
||||||
|
floatValue = parseFloat(results[1]); |
||||||
|
unit = results[4].toLowerCase(); |
||||||
|
} |
||||||
|
|
||||||
|
if (isNaN(floatValue)) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
return Math.floor(map[unit] * floatValue); |
||||||
|
} |
@ -0,0 +1,42 @@ |
|||||||
|
{ |
||||||
|
"name": "bytes", |
||||||
|
"description": "Utility to parse a string bytes to bytes and vice-versa", |
||||||
|
"version": "3.1.2", |
||||||
|
"author": "TJ Holowaychuk <tj@vision-media.ca> (http://tjholowaychuk.com)", |
||||||
|
"contributors": [ |
||||||
|
"Jed Watson <jed.watson@me.com>", |
||||||
|
"Théo FIDRY <theo.fidry@gmail.com>" |
||||||
|
], |
||||||
|
"license": "MIT", |
||||||
|
"keywords": [ |
||||||
|
"byte", |
||||||
|
"bytes", |
||||||
|
"utility", |
||||||
|
"parse", |
||||||
|
"parser", |
||||||
|
"convert", |
||||||
|
"converter" |
||||||
|
], |
||||||
|
"repository": "visionmedia/bytes.js", |
||||||
|
"devDependencies": { |
||||||
|
"eslint": "7.32.0", |
||||||
|
"eslint-plugin-markdown": "2.2.1", |
||||||
|
"mocha": "9.2.0", |
||||||
|
"nyc": "15.1.0" |
||||||
|
}, |
||||||
|
"files": [ |
||||||
|
"History.md", |
||||||
|
"LICENSE", |
||||||
|
"Readme.md", |
||||||
|
"index.js" |
||||||
|
], |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.8" |
||||||
|
}, |
||||||
|
"scripts": { |
||||||
|
"lint": "eslint .", |
||||||
|
"test": "mocha --check-leaks --reporter spec", |
||||||
|
"test-ci": "nyc --reporter=lcov --reporter=text npm test", |
||||||
|
"test-cov": "nyc --reporter=html --reporter=text npm test" |
||||||
|
} |
||||||
|
} |
@ -0,0 +1 @@ |
|||||||
|
coverage/ |
@ -0,0 +1,16 @@ |
|||||||
|
{ |
||||||
|
"root": true, |
||||||
|
|
||||||
|
"extends": "@ljharb", |
||||||
|
|
||||||
|
"rules": { |
||||||
|
"func-name-matching": 0, |
||||||
|
"id-length": 0, |
||||||
|
"new-cap": [2, { |
||||||
|
"capIsNewExceptions": [ |
||||||
|
"GetIntrinsic", |
||||||
|
], |
||||||
|
}], |
||||||
|
"no-magic-numbers": 0, |
||||||
|
}, |
||||||
|
} |
@ -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/call-bind |
||||||
|
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 up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] |
@ -0,0 +1,9 @@ |
|||||||
|
{ |
||||||
|
"all": true, |
||||||
|
"check-coverage": false, |
||||||
|
"reporter": ["text-summary", "text", "html", "json"], |
||||||
|
"exclude": [ |
||||||
|
"coverage", |
||||||
|
"test" |
||||||
|
] |
||||||
|
} |
@ -0,0 +1,93 @@ |
|||||||
|
# Changelog |
||||||
|
|
||||||
|
All notable changes to this project will be documented in this file. |
||||||
|
|
||||||
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) |
||||||
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). |
||||||
|
|
||||||
|
## [v1.0.7](https://github.com/ljharb/call-bind/compare/v1.0.6...v1.0.7) - 2024-02-12 |
||||||
|
|
||||||
|
### Commits |
||||||
|
|
||||||
|
- [Refactor] use `es-define-property` [`09b76a0`](https://github.com/ljharb/call-bind/commit/09b76a01634440461d44a80c9924ec4b500f3b03) |
||||||
|
- [Deps] update `get-intrinsic`, `set-function-length` [`ad5136d`](https://github.com/ljharb/call-bind/commit/ad5136ddda2a45c590959829ad3dce0c9f4e3590) |
||||||
|
|
||||||
|
## [v1.0.6](https://github.com/ljharb/call-bind/compare/v1.0.5...v1.0.6) - 2024-02-05 |
||||||
|
|
||||||
|
### Commits |
||||||
|
|
||||||
|
- [Dev Deps] update `aud`, `npmignore`, `tape` [`d564d5c`](https://github.com/ljharb/call-bind/commit/d564d5ce3e06a19df4d499c77f8d1a9da44e77aa) |
||||||
|
- [Deps] update `get-intrinsic`, `set-function-length` [`cfc2bdc`](https://github.com/ljharb/call-bind/commit/cfc2bdca7b633df0e0e689e6b637f668f1c6792e) |
||||||
|
- [Refactor] use `es-errors`, so things that only need those do not need `get-intrinsic` [`64cd289`](https://github.com/ljharb/call-bind/commit/64cd289ae5862c250a4ca80aa8d461047c166af5) |
||||||
|
- [meta] add missing `engines.node` [`32a4038`](https://github.com/ljharb/call-bind/commit/32a4038857b62179f7f9b7b3df2c5260036be582) |
||||||
|
|
||||||
|
## [v1.0.5](https://github.com/ljharb/call-bind/compare/v1.0.4...v1.0.5) - 2023-10-19 |
||||||
|
|
||||||
|
### Commits |
||||||
|
|
||||||
|
- [Fix] throw an error on non-functions as early as possible [`f262408`](https://github.com/ljharb/call-bind/commit/f262408f822c840fbc268080f3ad7c429611066d) |
||||||
|
- [Deps] update `set-function-length` [`3fff271`](https://github.com/ljharb/call-bind/commit/3fff27145a1e3a76a5b74f1d7c3c43d0fa3b9871) |
||||||
|
|
||||||
|
## [v1.0.4](https://github.com/ljharb/call-bind/compare/v1.0.3...v1.0.4) - 2023-10-19 |
||||||
|
|
||||||
|
## [v1.0.3](https://github.com/ljharb/call-bind/compare/v1.0.2...v1.0.3) - 2023-10-19 |
||||||
|
|
||||||
|
### Commits |
||||||
|
|
||||||
|
- [actions] reuse common workflows [`a994df6`](https://github.com/ljharb/call-bind/commit/a994df69f401f4bf735a4ccd77029b85d1549453) |
||||||
|
- [meta] use `npmignore` to autogenerate an npmignore file [`eef3ef2`](https://github.com/ljharb/call-bind/commit/eef3ef21e1f002790837fedb8af2679c761fbdf5) |
||||||
|
- [readme] flesh out content [`1845ccf`](https://github.com/ljharb/call-bind/commit/1845ccfd9976a607884cfc7157c93192cc16cf22) |
||||||
|
- [actions] use `node/install` instead of `node/run`; use `codecov` action [`5b47d53`](https://github.com/ljharb/call-bind/commit/5b47d53d2fd74af5ea0a44f1d51e503cd42f7a90) |
||||||
|
- [Refactor] use `set-function-length` [`a0e165c`](https://github.com/ljharb/call-bind/commit/a0e165c5dc61db781cbc919b586b1c2b8da0b150) |
||||||
|
- [Dev Deps] update `@ljharb/eslint-config`, `aud`, `tape` [`9c50103`](https://github.com/ljharb/call-bind/commit/9c50103f44137279a817317cf6cc421a658f85b4) |
||||||
|
- [meta] simplify "exports" [`019c6d0`](https://github.com/ljharb/call-bind/commit/019c6d06b0e1246ceed8e579f57e44441cbbf6d9) |
||||||
|
- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `aud`, `auto-changelog`, `safe-publish-latest`, `tape` [`23bd718`](https://github.com/ljharb/call-bind/commit/23bd718a288d3b03042062b4ef5153b3cea83f11) |
||||||
|
- [actions] update codecov uploader [`62552d7`](https://github.com/ljharb/call-bind/commit/62552d79cc79e05825e99aaba134ae5b37f33da5) |
||||||
|
- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `aud`, `auto-changelog`, `tape` [`ec81665`](https://github.com/ljharb/call-bind/commit/ec81665b300f87eabff597afdc8b8092adfa7afd) |
||||||
|
- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `safe-publish-latest`, `tape` [`35d67fc`](https://github.com/ljharb/call-bind/commit/35d67fcea883e686650f736f61da5ddca2592de8) |
||||||
|
- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `aud`, `tape` [`0266d8d`](https://github.com/ljharb/call-bind/commit/0266d8d2a45086a922db366d0c2932fa463662ff) |
||||||
|
- [Dev Deps] update `@ljharb/eslint-config`, `aud`, `tape` [`43a5b28`](https://github.com/ljharb/call-bind/commit/43a5b28a444e710e1bbf92adb8afb5cf7523a223) |
||||||
|
- [Deps] update `define-data-property`, `function-bind`, `get-intrinsic` [`780eb36`](https://github.com/ljharb/call-bind/commit/780eb36552514f8cc99c70821ce698697c2726a5) |
||||||
|
- [Dev Deps] update `aud`, `tape` [`90d50ad`](https://github.com/ljharb/call-bind/commit/90d50ad03b061e0268b3380b0065fcaec183dc05) |
||||||
|
- [meta] use `prepublishOnly` script for npm 7+ [`44c5433`](https://github.com/ljharb/call-bind/commit/44c5433b7980e02b4870007046407cf6fc543329) |
||||||
|
- [Deps] update `get-intrinsic` [`86bfbfc`](https://github.com/ljharb/call-bind/commit/86bfbfcf34afdc6eabc93ce3d408548d0e27d958) |
||||||
|
- [Deps] update `get-intrinsic` [`5c53354`](https://github.com/ljharb/call-bind/commit/5c5335489be0294c18cd7a8bb6e08226ee019ff5) |
||||||
|
- [actions] update checkout action [`4c393a8`](https://github.com/ljharb/call-bind/commit/4c393a8173b3c8e5b30d5b3297b3b94d48bf87f3) |
||||||
|
- [Deps] update `get-intrinsic` [`4e70bde`](https://github.com/ljharb/call-bind/commit/4e70bdec0626acb11616d66250fc14565e716e91) |
||||||
|
- [Deps] update `get-intrinsic` [`55ae803`](https://github.com/ljharb/call-bind/commit/55ae803a920bd93c369cd798c20de31f91e9fc60) |
||||||
|
|
||||||
|
## [v1.0.2](https://github.com/ljharb/call-bind/compare/v1.0.1...v1.0.2) - 2021-01-11 |
||||||
|
|
||||||
|
### Commits |
||||||
|
|
||||||
|
- [Fix] properly include the receiver in the bound length [`dbae7bc`](https://github.com/ljharb/call-bind/commit/dbae7bc676c079a0d33c0a43e9ef92cb7b01345d) |
||||||
|
|
||||||
|
## [v1.0.1](https://github.com/ljharb/call-bind/compare/v1.0.0...v1.0.1) - 2021-01-08 |
||||||
|
|
||||||
|
### Commits |
||||||
|
|
||||||
|
- [Tests] migrate tests to Github Actions [`b6db284`](https://github.com/ljharb/call-bind/commit/b6db284c36f8ccd195b88a6764fe84b7223a0da1) |
||||||
|
- [meta] do not publish github action workflow files [`ec7fe46`](https://github.com/ljharb/call-bind/commit/ec7fe46e60cfa4764ee943d2755f5e5a366e578e) |
||||||
|
- [Fix] preserve original function’s length when possible [`adbceaa`](https://github.com/ljharb/call-bind/commit/adbceaa3cac4b41ea78bb19d7ccdbaaf7e0bdadb) |
||||||
|
- [Tests] gather coverage data on every job [`d69e23c`](https://github.com/ljharb/call-bind/commit/d69e23cc65f101ba1d4c19bb07fa8eb0ec624be8) |
||||||
|
- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `aud`, `tape` [`2fd3586`](https://github.com/ljharb/call-bind/commit/2fd3586c5d47b335364c14293114c6b625ae1f71) |
||||||
|
- [Deps] update `get-intrinsic` [`f23e931`](https://github.com/ljharb/call-bind/commit/f23e9318cc271c2add8bb38cfded85ee7baf8eee) |
||||||
|
- [Deps] update `get-intrinsic` [`72d9f44`](https://github.com/ljharb/call-bind/commit/72d9f44e184465ba8dd3fb48260bbcff234985f2) |
||||||
|
- [meta] fix FUNDING.yml [`e723573`](https://github.com/ljharb/call-bind/commit/e723573438c5a68dcec31fb5d96ea6b7e4a93be8) |
||||||
|
- [eslint] ignore coverage output [`15e76d2`](https://github.com/ljharb/call-bind/commit/15e76d28a5f43e504696401e5b31ebb78ee1b532) |
||||||
|
- [meta] add Automatic Rebase and Require Allow Edits workflows [`8fa4dab`](https://github.com/ljharb/call-bind/commit/8fa4dabb23ba3dd7bb92c9571c1241c08b56e4b6) |
||||||
|
|
||||||
|
## v1.0.0 - 2020-10-30 |
||||||
|
|
||||||
|
### Commits |
||||||
|
|
||||||
|
- Initial commit [`306cf98`](https://github.com/ljharb/call-bind/commit/306cf98c7ec9e7ef66b653ec152277ac1381eb50) |
||||||
|
- Tests [`e10d0bb`](https://github.com/ljharb/call-bind/commit/e10d0bbdadc7a10ecedc9a1c035112d3e368b8df) |
||||||
|
- Implementation [`43852ed`](https://github.com/ljharb/call-bind/commit/43852eda0f187327b7fad2423ca972149a52bd65) |
||||||
|
- npm init [`408f860`](https://github.com/ljharb/call-bind/commit/408f860b773a2f610805fd3613d0d71bac1b6249) |
||||||
|
- [meta] add Automatic Rebase and Require Allow Edits workflows [`fb349b2`](https://github.com/ljharb/call-bind/commit/fb349b2e48defbec8b5ec8a8395cc8f69f220b13) |
||||||
|
- [meta] add `auto-changelog` [`c4001fc`](https://github.com/ljharb/call-bind/commit/c4001fc43031799ef908211c98d3b0fb2b60fde4) |
||||||
|
- [meta] add "funding"; create `FUNDING.yml` [`d4d6d29`](https://github.com/ljharb/call-bind/commit/d4d6d2974a14bc2e98830468eda7fe6d6a776717) |
||||||
|
- [Tests] add `npm run lint` [`dedfb98`](https://github.com/ljharb/call-bind/commit/dedfb98bd0ecefb08ddb9a94061bd10cde4332af) |
||||||
|
- Only apps should have lockfiles [`54ac776`](https://github.com/ljharb/call-bind/commit/54ac77653db45a7361dc153d2f478e743f110650) |
||||||
|
- [meta] add `safe-publish-latest` [`9ea8e43`](https://github.com/ljharb/call-bind/commit/9ea8e435b950ce9b705559cd651039f9bf40140f) |
@ -0,0 +1,21 @@ |
|||||||
|
MIT License |
||||||
|
|
||||||
|
Copyright (c) 2020 Jordan Harband |
||||||
|
|
||||||
|
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. |
@ -0,0 +1,64 @@ |
|||||||
|
# call-bind <sup>[![Version Badge][npm-version-svg]][package-url]</sup> |
||||||
|
|
||||||
|
[![github actions][actions-image]][actions-url] |
||||||
|
[![coverage][codecov-image]][codecov-url] |
||||||
|
[![dependency status][deps-svg]][deps-url] |
||||||
|
[![dev dependency status][dev-deps-svg]][dev-deps-url] |
||||||
|
[![License][license-image]][license-url] |
||||||
|
[![Downloads][downloads-image]][downloads-url] |
||||||
|
|
||||||
|
[![npm badge][npm-badge-png]][package-url] |
||||||
|
|
||||||
|
Robustly `.call.bind()` a function. |
||||||
|
|
||||||
|
## Getting started |
||||||
|
|
||||||
|
```sh |
||||||
|
npm install --save call-bind |
||||||
|
``` |
||||||
|
|
||||||
|
## Usage/Examples |
||||||
|
|
||||||
|
```js |
||||||
|
const assert = require('assert'); |
||||||
|
const callBind = require('call-bind'); |
||||||
|
const callBound = require('call-bind/callBound'); |
||||||
|
|
||||||
|
function f(a, b) { |
||||||
|
assert.equal(this, 1); |
||||||
|
assert.equal(a, 2); |
||||||
|
assert.equal(b, 3); |
||||||
|
assert.equal(arguments.length, 2); |
||||||
|
} |
||||||
|
|
||||||
|
const fBound = callBind(f); |
||||||
|
|
||||||
|
const slice = callBound('Array.prototype.slice'); |
||||||
|
|
||||||
|
delete Function.prototype.call; |
||||||
|
delete Function.prototype.bind; |
||||||
|
|
||||||
|
fBound(1, 2, 3); |
||||||
|
|
||||||
|
assert.deepEqual(slice([1, 2, 3, 4], 1, -1), [2, 3]); |
||||||
|
``` |
||||||
|
|
||||||
|
## Tests |
||||||
|
|
||||||
|
Clone the repo, `npm install`, and run `npm test` |
||||||
|
|
||||||
|
[package-url]: https://npmjs.org/package/call-bind |
||||||
|
[npm-version-svg]: https://versionbadg.es/ljharb/call-bind.svg |
||||||
|
[deps-svg]: https://david-dm.org/ljharb/call-bind.svg |
||||||
|
[deps-url]: https://david-dm.org/ljharb/call-bind |
||||||
|
[dev-deps-svg]: https://david-dm.org/ljharb/call-bind/dev-status.svg |
||||||
|
[dev-deps-url]: https://david-dm.org/ljharb/call-bind#info=devDependencies |
||||||
|
[npm-badge-png]: https://nodei.co/npm/call-bind.png?downloads=true&stars=true |
||||||
|
[license-image]: https://img.shields.io/npm/l/call-bind.svg |
||||||
|
[license-url]: LICENSE |
||||||
|
[downloads-image]: https://img.shields.io/npm/dm/call-bind.svg |
||||||
|
[downloads-url]: https://npm-stat.com/charts.html?package=call-bind |
||||||
|
[codecov-image]: https://codecov.io/gh/ljharb/call-bind/branch/main/graphs/badge.svg |
||||||
|
[codecov-url]: https://app.codecov.io/gh/ljharb/call-bind/ |
||||||
|
[actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/ljharb/call-bind |
||||||
|
[actions-url]: https://github.com/ljharb/call-bind/actions |
@ -0,0 +1,15 @@ |
|||||||
|
'use strict'; |
||||||
|
|
||||||
|
var GetIntrinsic = require('get-intrinsic'); |
||||||
|
|
||||||
|
var callBind = require('./'); |
||||||
|
|
||||||
|
var $indexOf = callBind(GetIntrinsic('String.prototype.indexOf')); |
||||||
|
|
||||||
|
module.exports = function callBoundIntrinsic(name, allowMissing) { |
||||||
|
var intrinsic = GetIntrinsic(name, !!allowMissing); |
||||||
|
if (typeof intrinsic === 'function' && $indexOf(name, '.prototype.') > -1) { |
||||||
|
return callBind(intrinsic); |
||||||
|
} |
||||||
|
return intrinsic; |
||||||
|
}; |
@ -0,0 +1,35 @@ |
|||||||
|
'use strict'; |
||||||
|
|
||||||
|
var bind = require('function-bind'); |
||||||
|
var GetIntrinsic = require('get-intrinsic'); |
||||||
|
var setFunctionLength = require('set-function-length'); |
||||||
|
|
||||||
|
var $TypeError = require('es-errors/type'); |
||||||
|
var $apply = GetIntrinsic('%Function.prototype.apply%'); |
||||||
|
var $call = GetIntrinsic('%Function.prototype.call%'); |
||||||
|
var $reflectApply = GetIntrinsic('%Reflect.apply%', true) || bind.call($call, $apply); |
||||||
|
|
||||||
|
var $defineProperty = require('es-define-property'); |
||||||
|
var $max = GetIntrinsic('%Math.max%'); |
||||||
|
|
||||||
|
module.exports = function callBind(originalFunction) { |
||||||
|
if (typeof originalFunction !== 'function') { |
||||||
|
throw new $TypeError('a function is required'); |
||||||
|
} |
||||||
|
var func = $reflectApply(bind, $call, arguments); |
||||||
|
return setFunctionLength( |
||||||
|
func, |
||||||
|
1 + $max(0, originalFunction.length - (arguments.length - 1)), |
||||||
|
true |
||||||
|
); |
||||||
|
}; |
||||||
|
|
||||||
|
var applyBind = function applyBind() { |
||||||
|
return $reflectApply(bind, $apply, arguments); |
||||||
|
}; |
||||||
|
|
||||||
|
if ($defineProperty) { |
||||||
|
$defineProperty(module.exports, 'apply', { value: applyBind }); |
||||||
|
} else { |
||||||
|
module.exports.apply = applyBind; |
||||||
|
} |
@ -0,0 +1,95 @@ |
|||||||
|
{ |
||||||
|
"name": "call-bind", |
||||||
|
"version": "1.0.7", |
||||||
|
"description": "Robustly `.call.bind()` a function", |
||||||
|
"main": "index.js", |
||||||
|
"exports": { |
||||||
|
".": "./index.js", |
||||||
|
"./callBound": "./callBound.js", |
||||||
|
"./package.json": "./package.json" |
||||||
|
}, |
||||||
|
"scripts": { |
||||||
|
"prepack": "npmignore --auto --commentLines=auto", |
||||||
|
"prepublish": "not-in-publish || npm run prepublishOnly", |
||||||
|
"prepublishOnly": "safe-publish-latest", |
||||||
|
"lint": "eslint --ext=.js,.mjs .", |
||||||
|
"postlint": "evalmd README.md", |
||||||
|
"pretest": "npm run lint", |
||||||
|
"tests-only": "nyc tape 'test/**/*.js'", |
||||||
|
"test": "npm run tests-only", |
||||||
|
"posttest": "aud --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/call-bind.git" |
||||||
|
}, |
||||||
|
"keywords": [ |
||||||
|
"javascript", |
||||||
|
"ecmascript", |
||||||
|
"es", |
||||||
|
"js", |
||||||
|
"callbind", |
||||||
|
"callbound", |
||||||
|
"call", |
||||||
|
"bind", |
||||||
|
"bound", |
||||||
|
"call-bind", |
||||||
|
"call-bound", |
||||||
|
"function", |
||||||
|
"es-abstract" |
||||||
|
], |
||||||
|
"author": "Jordan Harband <ljharb@gmail.com>", |
||||||
|
"funding": { |
||||||
|
"url": "https://github.com/sponsors/ljharb" |
||||||
|
}, |
||||||
|
"license": "MIT", |
||||||
|
"bugs": { |
||||||
|
"url": "https://github.com/ljharb/call-bind/issues" |
||||||
|
}, |
||||||
|
"homepage": "https://github.com/ljharb/call-bind#readme", |
||||||
|
"devDependencies": { |
||||||
|
"@ljharb/eslint-config": "^21.1.0", |
||||||
|
"aud": "^2.0.4", |
||||||
|
"auto-changelog": "^2.4.0", |
||||||
|
"es-value-fixtures": "^1.4.2", |
||||||
|
"eslint": "=8.8.0", |
||||||
|
"evalmd": "^0.0.19", |
||||||
|
"for-each": "^0.3.3", |
||||||
|
"gopd": "^1.0.1", |
||||||
|
"has-strict-mode": "^1.0.1", |
||||||
|
"in-publish": "^2.0.1", |
||||||
|
"npmignore": "^0.3.1", |
||||||
|
"nyc": "^10.3.2", |
||||||
|
"object-inspect": "^1.13.1", |
||||||
|
"safe-publish-latest": "^2.0.0", |
||||||
|
"tape": "^5.7.4" |
||||||
|
}, |
||||||
|
"dependencies": { |
||||||
|
"es-define-property": "^1.0.0", |
||||||
|
"es-errors": "^1.3.0", |
||||||
|
"function-bind": "^1.1.2", |
||||||
|
"get-intrinsic": "^1.2.4", |
||||||
|
"set-function-length": "^1.2.1" |
||||||
|
}, |
||||||
|
"testling": { |
||||||
|
"files": "test/index.js" |
||||||
|
}, |
||||||
|
"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,54 @@ |
|||||||
|
'use strict'; |
||||||
|
|
||||||
|
var test = require('tape'); |
||||||
|
|
||||||
|
var callBound = require('../callBound'); |
||||||
|
|
||||||
|
test('callBound', function (t) { |
||||||
|
// static primitive
|
||||||
|
t.equal(callBound('Array.length'), Array.length, 'Array.length yields itself'); |
||||||
|
t.equal(callBound('%Array.length%'), Array.length, '%Array.length% yields itself'); |
||||||
|
|
||||||
|
// static non-function object
|
||||||
|
t.equal(callBound('Array.prototype'), Array.prototype, 'Array.prototype yields itself'); |
||||||
|
t.equal(callBound('%Array.prototype%'), Array.prototype, '%Array.prototype% yields itself'); |
||||||
|
t.equal(callBound('Array.constructor'), Array.constructor, 'Array.constructor yields itself'); |
||||||
|
t.equal(callBound('%Array.constructor%'), Array.constructor, '%Array.constructor% yields itself'); |
||||||
|
|
||||||
|
// static function
|
||||||
|
t.equal(callBound('Date.parse'), Date.parse, 'Date.parse yields itself'); |
||||||
|
t.equal(callBound('%Date.parse%'), Date.parse, '%Date.parse% yields itself'); |
||||||
|
|
||||||
|
// prototype primitive
|
||||||
|
t.equal(callBound('Error.prototype.message'), Error.prototype.message, 'Error.prototype.message yields itself'); |
||||||
|
t.equal(callBound('%Error.prototype.message%'), Error.prototype.message, '%Error.prototype.message% yields itself'); |
||||||
|
|
||||||
|
// prototype function
|
||||||
|
t.notEqual(callBound('Object.prototype.toString'), Object.prototype.toString, 'Object.prototype.toString does not yield itself'); |
||||||
|
t.notEqual(callBound('%Object.prototype.toString%'), Object.prototype.toString, '%Object.prototype.toString% does not yield itself'); |
||||||
|
t.equal(callBound('Object.prototype.toString')(true), Object.prototype.toString.call(true), 'call-bound Object.prototype.toString calls into the original'); |
||||||
|
t.equal(callBound('%Object.prototype.toString%')(true), Object.prototype.toString.call(true), 'call-bound %Object.prototype.toString% calls into the original'); |
||||||
|
|
||||||
|
t['throws']( |
||||||
|
function () { callBound('does not exist'); }, |
||||||
|
SyntaxError, |
||||||
|
'nonexistent intrinsic throws' |
||||||
|
); |
||||||
|
t['throws']( |
||||||
|
function () { callBound('does not exist', true); }, |
||||||
|
SyntaxError, |
||||||
|
'allowMissing arg still throws for unknown intrinsic' |
||||||
|
); |
||||||
|
|
||||||
|
t.test('real but absent intrinsic', { skip: typeof WeakRef !== 'undefined' }, function (st) { |
||||||
|
st['throws']( |
||||||
|
function () { callBound('WeakRef'); }, |
||||||
|
TypeError, |
||||||
|
'real but absent intrinsic throws' |
||||||
|
); |
||||||
|
st.equal(callBound('WeakRef', true), undefined, 'allowMissing arg avoids exception'); |
||||||
|
st.end(); |
||||||
|
}); |
||||||
|
|
||||||
|
t.end(); |
||||||
|
}); |
@ -0,0 +1,80 @@ |
|||||||
|
'use strict'; |
||||||
|
|
||||||
|
var callBind = require('../'); |
||||||
|
var bind = require('function-bind'); |
||||||
|
var gOPD = require('gopd'); |
||||||
|
var hasStrictMode = require('has-strict-mode')(); |
||||||
|
var forEach = require('for-each'); |
||||||
|
var inspect = require('object-inspect'); |
||||||
|
var v = require('es-value-fixtures'); |
||||||
|
|
||||||
|
var test = require('tape'); |
||||||
|
|
||||||
|
/* |
||||||
|
* older engines have length nonconfigurable |
||||||
|
* in io.js v3, it is configurable except on bound functions, hence the .bind() |
||||||
|
*/ |
||||||
|
var functionsHaveConfigurableLengths = !!( |
||||||
|
gOPD |
||||||
|
&& Object.getOwnPropertyDescriptor |
||||||
|
&& Object.getOwnPropertyDescriptor(bind.call(function () {}), 'length').configurable |
||||||
|
); |
||||||
|
|
||||||
|
test('callBind', function (t) { |
||||||
|
forEach(v.nonFunctions, function (nonFunction) { |
||||||
|
t['throws']( |
||||||
|
function () { callBind(nonFunction); }, |
||||||
|
TypeError, |
||||||
|
inspect(nonFunction) + ' is not a function' |
||||||
|
); |
||||||
|
}); |
||||||
|
|
||||||
|
var sentinel = { sentinel: true }; |
||||||
|
var func = function (a, b) { |
||||||
|
// eslint-disable-next-line no-invalid-this
|
||||||
|
return [!hasStrictMode && this === global ? undefined : this, a, b]; |
||||||
|
}; |
||||||
|
t.equal(func.length, 2, 'original function length is 2'); |
||||||
|
t.deepEqual(func(), [undefined, undefined, undefined], 'unbound func with too few args'); |
||||||
|
t.deepEqual(func(1, 2), [undefined, 1, 2], 'unbound func with right args'); |
||||||
|
t.deepEqual(func(1, 2, 3), [undefined, 1, 2], 'unbound func with too many args'); |
||||||
|
|
||||||
|
var bound = callBind(func); |
||||||
|
t.equal(bound.length, func.length + 1, 'function length is preserved', { skip: !functionsHaveConfigurableLengths }); |
||||||
|
t.deepEqual(bound(), [undefined, undefined, undefined], 'bound func with too few args'); |
||||||
|
t.deepEqual(bound(1, 2), [hasStrictMode ? 1 : Object(1), 2, undefined], 'bound func with right args'); |
||||||
|
t.deepEqual(bound(1, 2, 3), [hasStrictMode ? 1 : Object(1), 2, 3], 'bound func with too many args'); |
||||||
|
|
||||||
|
var boundR = callBind(func, sentinel); |
||||||
|
t.equal(boundR.length, func.length, 'function length is preserved', { skip: !functionsHaveConfigurableLengths }); |
||||||
|
t.deepEqual(boundR(), [sentinel, undefined, undefined], 'bound func with receiver, with too few args'); |
||||||
|
t.deepEqual(boundR(1, 2), [sentinel, 1, 2], 'bound func with receiver, with right args'); |
||||||
|
t.deepEqual(boundR(1, 2, 3), [sentinel, 1, 2], 'bound func with receiver, with too many args'); |
||||||
|
|
||||||
|
var boundArg = callBind(func, sentinel, 1); |
||||||
|
t.equal(boundArg.length, func.length - 1, 'function length is preserved', { skip: !functionsHaveConfigurableLengths }); |
||||||
|
t.deepEqual(boundArg(), [sentinel, 1, undefined], 'bound func with receiver and arg, with too few args'); |
||||||
|
t.deepEqual(boundArg(2), [sentinel, 1, 2], 'bound func with receiver and arg, with right arg'); |
||||||
|
t.deepEqual(boundArg(2, 3), [sentinel, 1, 2], 'bound func with receiver and arg, with too many args'); |
||||||
|
|
||||||
|
t.test('callBind.apply', function (st) { |
||||||
|
var aBound = callBind.apply(func); |
||||||
|
st.deepEqual(aBound(sentinel), [sentinel, undefined, undefined], 'apply-bound func with no args'); |
||||||
|
st.deepEqual(aBound(sentinel, [1], 4), [sentinel, 1, undefined], 'apply-bound func with too few args'); |
||||||
|
st.deepEqual(aBound(sentinel, [1, 2], 4), [sentinel, 1, 2], 'apply-bound func with right args'); |
||||||
|
|
||||||
|
var aBoundArg = callBind.apply(func); |
||||||
|
st.deepEqual(aBoundArg(sentinel, [1, 2, 3], 4), [sentinel, 1, 2], 'apply-bound func with too many args'); |
||||||
|
st.deepEqual(aBoundArg(sentinel, [1, 2], 4), [sentinel, 1, 2], 'apply-bound func with right args'); |
||||||
|
st.deepEqual(aBoundArg(sentinel, [1], 4), [sentinel, 1, undefined], 'apply-bound func with too few args'); |
||||||
|
|
||||||
|
var aBoundR = callBind.apply(func, sentinel); |
||||||
|
st.deepEqual(aBoundR([1, 2, 3], 4), [sentinel, 1, 2], 'apply-bound func with receiver and too many args'); |
||||||
|
st.deepEqual(aBoundR([1, 2], 4), [sentinel, 1, 2], 'apply-bound func with receiver and right args'); |
||||||
|
st.deepEqual(aBoundR([1], 4), [sentinel, 1, undefined], 'apply-bound func with receiver and too few args'); |
||||||
|
|
||||||
|
st.end(); |
||||||
|
}); |
||||||
|
|
||||||
|
t.end(); |
||||||
|
}); |
@ -0,0 +1,60 @@ |
|||||||
|
0.5.4 / 2021-12-10 |
||||||
|
================== |
||||||
|
|
||||||
|
* deps: safe-buffer@5.2.1 |
||||||
|
|
||||||
|
0.5.3 / 2018-12-17 |
||||||
|
================== |
||||||
|
|
||||||
|
* Use `safe-buffer` for improved Buffer API |
||||||
|
|
||||||
|
0.5.2 / 2016-12-08 |
||||||
|
================== |
||||||
|
|
||||||
|
* Fix `parse` to accept any linear whitespace character |
||||||
|
|
||||||
|
0.5.1 / 2016-01-17 |
||||||
|
================== |
||||||
|
|
||||||
|
* perf: enable strict mode |
||||||
|
|
||||||
|
0.5.0 / 2014-10-11 |
||||||
|
================== |
||||||
|
|
||||||
|
* Add `parse` function |
||||||
|
|
||||||
|
0.4.0 / 2014-09-21 |
||||||
|
================== |
||||||
|
|
||||||
|
* Expand non-Unicode `filename` to the full ISO-8859-1 charset |
||||||
|
|
||||||
|
0.3.0 / 2014-09-20 |
||||||
|
================== |
||||||
|
|
||||||
|
* Add `fallback` option |
||||||
|
* Add `type` option |
||||||
|
|
||||||
|
0.2.0 / 2014-09-19 |
||||||
|
================== |
||||||
|
|
||||||
|
* Reduce ambiguity of file names with hex escape in buggy browsers |
||||||
|
|
||||||
|
0.1.2 / 2014-09-19 |
||||||
|
================== |
||||||
|
|
||||||
|
* Fix periodic invalid Unicode filename header |
||||||
|
|
||||||
|
0.1.1 / 2014-09-19 |
||||||
|
================== |
||||||
|
|
||||||
|
* Fix invalid characters appearing in `filename*` parameter |
||||||
|
|
||||||
|
0.1.0 / 2014-09-18 |
||||||
|
================== |
||||||
|
|
||||||
|
* Make the `filename` argument optional |
||||||
|
|
||||||
|
0.0.0 / 2014-09-18 |
||||||
|
================== |
||||||
|
|
||||||
|
* Initial release |
@ -0,0 +1,22 @@ |
|||||||
|
(The MIT License) |
||||||
|
|
||||||
|
Copyright (c) 2014-2017 Douglas Christopher Wilson |
||||||
|
|
||||||
|
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. |
@ -0,0 +1,142 @@ |
|||||||
|
# content-disposition |
||||||
|
|
||||||
|
[![NPM Version][npm-image]][npm-url] |
||||||
|
[![NPM Downloads][downloads-image]][downloads-url] |
||||||
|
[![Node.js Version][node-version-image]][node-version-url] |
||||||
|
[![Build Status][github-actions-ci-image]][github-actions-ci-url] |
||||||
|
[![Test Coverage][coveralls-image]][coveralls-url] |
||||||
|
|
||||||
|
Create and parse HTTP `Content-Disposition` header |
||||||
|
|
||||||
|
## Installation |
||||||
|
|
||||||
|
```sh |
||||||
|
$ npm install content-disposition |
||||||
|
``` |
||||||
|
|
||||||
|
## API |
||||||
|
|
||||||
|
```js |
||||||
|
var contentDisposition = require('content-disposition') |
||||||
|
``` |
||||||
|
|
||||||
|
### contentDisposition(filename, options) |
||||||
|
|
||||||
|
Create an attachment `Content-Disposition` header value using the given file name, |
||||||
|
if supplied. The `filename` is optional and if no file name is desired, but you |
||||||
|
want to specify `options`, set `filename` to `undefined`. |
||||||
|
|
||||||
|
```js |
||||||
|
res.setHeader('Content-Disposition', contentDisposition('∫ maths.pdf')) |
||||||
|
``` |
||||||
|
|
||||||
|
**note** HTTP headers are of the ISO-8859-1 character set. If you are writing this |
||||||
|
header through a means different from `setHeader` in Node.js, you'll want to specify |
||||||
|
the `'binary'` encoding in Node.js. |
||||||
|
|
||||||
|
#### Options |
||||||
|
|
||||||
|
`contentDisposition` accepts these properties in the options object. |
||||||
|
|
||||||
|
##### fallback |
||||||
|
|
||||||
|
If the `filename` option is outside ISO-8859-1, then the file name is actually |
||||||
|
stored in a supplemental field for clients that support Unicode file names and |
||||||
|
a ISO-8859-1 version of the file name is automatically generated. |
||||||
|
|
||||||
|
This specifies the ISO-8859-1 file name to override the automatic generation or |
||||||
|
disables the generation all together, defaults to `true`. |
||||||
|
|
||||||
|
- A string will specify the ISO-8859-1 file name to use in place of automatic |
||||||
|
generation. |
||||||
|
- `false` will disable including a ISO-8859-1 file name and only include the |
||||||
|
Unicode version (unless the file name is already ISO-8859-1). |
||||||
|
- `true` will enable automatic generation if the file name is outside ISO-8859-1. |
||||||
|
|
||||||
|
If the `filename` option is ISO-8859-1 and this option is specified and has a |
||||||
|
different value, then the `filename` option is encoded in the extended field |
||||||
|
and this set as the fallback field, even though they are both ISO-8859-1. |
||||||
|
|
||||||
|
##### type |
||||||
|
|
||||||
|
Specifies the disposition type, defaults to `"attachment"`. This can also be |
||||||
|
`"inline"`, or any other value (all values except inline are treated like |
||||||
|
`attachment`, but can convey additional information if both parties agree to |
||||||
|
it). The type is normalized to lower-case. |
||||||
|
|
||||||
|
### contentDisposition.parse(string) |
||||||
|
|
||||||
|
```js |
||||||
|
var disposition = contentDisposition.parse('attachment; filename="EURO rates.txt"; filename*=UTF-8\'\'%e2%82%ac%20rates.txt') |
||||||
|
``` |
||||||
|
|
||||||
|
Parse a `Content-Disposition` header string. This automatically handles extended |
||||||
|
("Unicode") parameters by decoding them and providing them under the standard |
||||||
|
parameter name. This will return an object with the following properties (examples |
||||||
|
are shown for the string `'attachment; filename="EURO rates.txt"; filename*=UTF-8\'\'%e2%82%ac%20rates.txt'`): |
||||||
|
|
||||||
|
- `type`: The disposition type (always lower case). Example: `'attachment'` |
||||||
|
|
||||||
|
- `parameters`: An object of the parameters in the disposition (name of parameter |
||||||
|
always lower case and extended versions replace non-extended versions). Example: |
||||||
|
`{filename: "€ rates.txt"}` |
||||||
|
|
||||||
|
## Examples |
||||||
|
|
||||||
|
### Send a file for download |
||||||
|
|
||||||
|
```js |
||||||
|
var contentDisposition = require('content-disposition') |
||||||
|
var destroy = require('destroy') |
||||||
|
var fs = require('fs') |
||||||
|
var http = require('http') |
||||||
|
var onFinished = require('on-finished') |
||||||
|
|
||||||
|
var filePath = '/path/to/public/plans.pdf' |
||||||
|
|
||||||
|
http.createServer(function onRequest (req, res) { |
||||||
|
// set headers |
||||||
|
res.setHeader('Content-Type', 'application/pdf') |
||||||
|
res.setHeader('Content-Disposition', contentDisposition(filePath)) |
||||||
|
|
||||||
|
// send file |
||||||
|
var stream = fs.createReadStream(filePath) |
||||||
|
stream.pipe(res) |
||||||
|
onFinished(res, function () { |
||||||
|
destroy(stream) |
||||||
|
}) |
||||||
|
}) |
||||||
|
``` |
||||||
|
|
||||||
|
## Testing |
||||||
|
|
||||||
|
```sh |
||||||
|
$ npm test |
||||||
|
``` |
||||||
|
|
||||||
|
## References |
||||||
|
|
||||||
|
- [RFC 2616: Hypertext Transfer Protocol -- HTTP/1.1][rfc-2616] |
||||||
|
- [RFC 5987: Character Set and Language Encoding for Hypertext Transfer Protocol (HTTP) Header Field Parameters][rfc-5987] |
||||||
|
- [RFC 6266: Use of the Content-Disposition Header Field in the Hypertext Transfer Protocol (HTTP)][rfc-6266] |
||||||
|
- [Test Cases for HTTP Content-Disposition header field (RFC 6266) and the Encodings defined in RFCs 2047, 2231 and 5987][tc-2231] |
||||||
|
|
||||||
|
[rfc-2616]: https://tools.ietf.org/html/rfc2616 |
||||||
|
[rfc-5987]: https://tools.ietf.org/html/rfc5987 |
||||||
|
[rfc-6266]: https://tools.ietf.org/html/rfc6266 |
||||||
|
[tc-2231]: http://greenbytes.de/tech/tc2231/ |
||||||
|
|
||||||
|
## License |
||||||
|
|
||||||
|
[MIT](LICENSE) |
||||||
|
|
||||||
|
[npm-image]: https://img.shields.io/npm/v/content-disposition.svg |
||||||
|
[npm-url]: https://npmjs.org/package/content-disposition |
||||||
|
[node-version-image]: https://img.shields.io/node/v/content-disposition.svg |
||||||
|
[node-version-url]: https://nodejs.org/en/download |
||||||
|
[coveralls-image]: https://img.shields.io/coveralls/jshttp/content-disposition.svg |
||||||
|
[coveralls-url]: https://coveralls.io/r/jshttp/content-disposition?branch=master |
||||||
|
[downloads-image]: https://img.shields.io/npm/dm/content-disposition.svg |
||||||
|
[downloads-url]: https://npmjs.org/package/content-disposition |
||||||
|
[github-actions-ci-image]: https://img.shields.io/github/workflow/status/jshttp/content-disposition/ci/master?label=ci |
||||||
|
[github-actions-ci-url]: https://github.com/jshttp/content-disposition?query=workflow%3Aci |
@ -0,0 +1,458 @@ |
|||||||
|
/*! |
||||||
|
* content-disposition |
||||||
|
* Copyright(c) 2014-2017 Douglas Christopher Wilson |
||||||
|
* MIT Licensed |
||||||
|
*/ |
||||||
|
|
||||||
|
'use strict' |
||||||
|
|
||||||
|
/** |
||||||
|
* Module exports. |
||||||
|
* @public |
||||||
|
*/ |
||||||
|
|
||||||
|
module.exports = contentDisposition |
||||||
|
module.exports.parse = parse |
||||||
|
|
||||||
|
/** |
||||||
|
* Module dependencies. |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
var basename = require('path').basename |
||||||
|
var Buffer = require('safe-buffer').Buffer |
||||||
|
|
||||||
|
/** |
||||||
|
* RegExp to match non attr-char, *after* encodeURIComponent (i.e. not including "%") |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
var ENCODE_URL_ATTR_CHAR_REGEXP = /[\x00-\x20"'()*,/:;<=>?@[\\\]{}\x7f]/g // eslint-disable-line no-control-regex
|
||||||
|
|
||||||
|
/** |
||||||
|
* RegExp to match percent encoding escape. |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
var HEX_ESCAPE_REGEXP = /%[0-9A-Fa-f]{2}/ |
||||||
|
var HEX_ESCAPE_REPLACE_REGEXP = /%([0-9A-Fa-f]{2})/g |
||||||
|
|
||||||
|
/** |
||||||
|
* RegExp to match non-latin1 characters. |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
var NON_LATIN1_REGEXP = /[^\x20-\x7e\xa0-\xff]/g |
||||||
|
|
||||||
|
/** |
||||||
|
* RegExp to match quoted-pair in RFC 2616 |
||||||
|
* |
||||||
|
* quoted-pair = "\" CHAR |
||||||
|
* CHAR = <any US-ASCII character (octets 0 - 127)> |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
var QESC_REGEXP = /\\([\u0000-\u007f])/g // eslint-disable-line no-control-regex
|
||||||
|
|
||||||
|
/** |
||||||
|
* RegExp to match chars that must be quoted-pair in RFC 2616 |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
var QUOTE_REGEXP = /([\\"])/g |
||||||
|
|
||||||
|
/** |
||||||
|
* RegExp for various RFC 2616 grammar |
||||||
|
* |
||||||
|
* parameter = token "=" ( token | quoted-string ) |
||||||
|
* token = 1*<any CHAR except CTLs or separators> |
||||||
|
* separators = "(" | ")" | "<" | ">" | "@" |
||||||
|
* | "," | ";" | ":" | "\" | <"> |
||||||
|
* | "/" | "[" | "]" | "?" | "=" |
||||||
|
* | "{" | "}" | SP | HT |
||||||
|
* quoted-string = ( <"> *(qdtext | quoted-pair ) <"> ) |
||||||
|
* qdtext = <any TEXT except <">> |
||||||
|
* quoted-pair = "\" CHAR |
||||||
|
* CHAR = <any US-ASCII character (octets 0 - 127)> |
||||||
|
* TEXT = <any OCTET except CTLs, but including LWS> |
||||||
|
* LWS = [CRLF] 1*( SP | HT ) |
||||||
|
* CRLF = CR LF |
||||||
|
* CR = <US-ASCII CR, carriage return (13)> |
||||||
|
* LF = <US-ASCII LF, linefeed (10)> |
||||||
|
* SP = <US-ASCII SP, space (32)> |
||||||
|
* HT = <US-ASCII HT, horizontal-tab (9)> |
||||||
|
* CTL = <any US-ASCII control character (octets 0 - 31) and DEL (127)> |
||||||
|
* OCTET = <any 8-bit sequence of data> |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
var PARAM_REGEXP = /;[\x09\x20]*([!#$%&'*+.0-9A-Z^_`a-z|~-]+)[\x09\x20]*=[\x09\x20]*("(?:[\x20!\x23-\x5b\x5d-\x7e\x80-\xff]|\\[\x20-\x7e])*"|[!#$%&'*+.0-9A-Z^_`a-z|~-]+)[\x09\x20]*/g // eslint-disable-line no-control-regex
|
||||||
|
var TEXT_REGEXP = /^[\x20-\x7e\x80-\xff]+$/ |
||||||
|
var TOKEN_REGEXP = /^[!#$%&'*+.0-9A-Z^_`a-z|~-]+$/ |
||||||
|
|
||||||
|
/** |
||||||
|
* RegExp for various RFC 5987 grammar |
||||||
|
* |
||||||
|
* ext-value = charset "'" [ language ] "'" value-chars |
||||||
|
* charset = "UTF-8" / "ISO-8859-1" / mime-charset |
||||||
|
* mime-charset = 1*mime-charsetc |
||||||
|
* mime-charsetc = ALPHA / DIGIT |
||||||
|
* / "!" / "#" / "$" / "%" / "&" |
||||||
|
* / "+" / "-" / "^" / "_" / "`" |
||||||
|
* / "{" / "}" / "~" |
||||||
|
* language = ( 2*3ALPHA [ extlang ] ) |
||||||
|
* / 4ALPHA |
||||||
|
* / 5*8ALPHA |
||||||
|
* extlang = *3( "-" 3ALPHA ) |
||||||
|
* value-chars = *( pct-encoded / attr-char ) |
||||||
|
* pct-encoded = "%" HEXDIG HEXDIG |
||||||
|
* attr-char = ALPHA / DIGIT |
||||||
|
* / "!" / "#" / "$" / "&" / "+" / "-" / "." |
||||||
|
* / "^" / "_" / "`" / "|" / "~" |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
var EXT_VALUE_REGEXP = /^([A-Za-z0-9!#$%&+\-^_`{}~]+)'(?:[A-Za-z]{2,3}(?:-[A-Za-z]{3}){0,3}|[A-Za-z]{4,8}|)'((?:%[0-9A-Fa-f]{2}|[A-Za-z0-9!#$&+.^_`|~-])+)$/ |
||||||
|
|
||||||
|
/** |
||||||
|
* RegExp for various RFC 6266 grammar |
||||||
|
* |
||||||
|
* disposition-type = "inline" | "attachment" | disp-ext-type |
||||||
|
* disp-ext-type = token |
||||||
|
* disposition-parm = filename-parm | disp-ext-parm |
||||||
|
* filename-parm = "filename" "=" value |
||||||
|
* | "filename*" "=" ext-value |
||||||
|
* disp-ext-parm = token "=" value |
||||||
|
* | ext-token "=" ext-value |
||||||
|
* ext-token = <the characters in token, followed by "*"> |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
var DISPOSITION_TYPE_REGEXP = /^([!#$%&'*+.0-9A-Z^_`a-z|~-]+)[\x09\x20]*(?:$|;)/ // eslint-disable-line no-control-regex
|
||||||
|
|
||||||
|
/** |
||||||
|
* Create an attachment Content-Disposition header. |
||||||
|
* |
||||||
|
* @param {string} [filename] |
||||||
|
* @param {object} [options] |
||||||
|
* @param {string} [options.type=attachment] |
||||||
|
* @param {string|boolean} [options.fallback=true] |
||||||
|
* @return {string} |
||||||
|
* @public |
||||||
|
*/ |
||||||
|
|
||||||
|
function contentDisposition (filename, options) { |
||||||
|
var opts = options || {} |
||||||
|
|
||||||
|
// get type
|
||||||
|
var type = opts.type || 'attachment' |
||||||
|
|
||||||
|
// get parameters
|
||||||
|
var params = createparams(filename, opts.fallback) |
||||||
|
|
||||||
|
// format into string
|
||||||
|
return format(new ContentDisposition(type, params)) |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create parameters object from filename and fallback. |
||||||
|
* |
||||||
|
* @param {string} [filename] |
||||||
|
* @param {string|boolean} [fallback=true] |
||||||
|
* @return {object} |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
function createparams (filename, fallback) { |
||||||
|
if (filename === undefined) { |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
var params = {} |
||||||
|
|
||||||
|
if (typeof filename !== 'string') { |
||||||
|
throw new TypeError('filename must be a string') |
||||||
|
} |
||||||
|
|
||||||
|
// fallback defaults to true
|
||||||
|
if (fallback === undefined) { |
||||||
|
fallback = true |
||||||
|
} |
||||||
|
|
||||||
|
if (typeof fallback !== 'string' && typeof fallback !== 'boolean') { |
||||||
|
throw new TypeError('fallback must be a string or boolean') |
||||||
|
} |
||||||
|
|
||||||
|
if (typeof fallback === 'string' && NON_LATIN1_REGEXP.test(fallback)) { |
||||||
|
throw new TypeError('fallback must be ISO-8859-1 string') |
||||||
|
} |
||||||
|
|
||||||
|
// restrict to file base name
|
||||||
|
var name = basename(filename) |
||||||
|
|
||||||
|
// determine if name is suitable for quoted string
|
||||||
|
var isQuotedString = TEXT_REGEXP.test(name) |
||||||
|
|
||||||
|
// generate fallback name
|
||||||
|
var fallbackName = typeof fallback !== 'string' |
||||||
|
? fallback && getlatin1(name) |
||||||
|
: basename(fallback) |
||||||
|
var hasFallback = typeof fallbackName === 'string' && fallbackName !== name |
||||||
|
|
||||||
|
// set extended filename parameter
|
||||||
|
if (hasFallback || !isQuotedString || HEX_ESCAPE_REGEXP.test(name)) { |
||||||
|
params['filename*'] = name |
||||||
|
} |
||||||
|
|
||||||
|
// set filename parameter
|
||||||
|
if (isQuotedString || hasFallback) { |
||||||
|
params.filename = hasFallback |
||||||
|
? fallbackName |
||||||
|
: name |
||||||
|
} |
||||||
|
|
||||||
|
return params |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Format object to Content-Disposition header. |
||||||
|
* |
||||||
|
* @param {object} obj |
||||||
|
* @param {string} obj.type |
||||||
|
* @param {object} [obj.parameters] |
||||||
|
* @return {string} |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
function format (obj) { |
||||||
|
var parameters = obj.parameters |
||||||
|
var type = obj.type |
||||||
|
|
||||||
|
if (!type || typeof type !== 'string' || !TOKEN_REGEXP.test(type)) { |
||||||
|
throw new TypeError('invalid type') |
||||||
|
} |
||||||
|
|
||||||
|
// start with normalized type
|
||||||
|
var string = String(type).toLowerCase() |
||||||
|
|
||||||
|
// append parameters
|
||||||
|
if (parameters && typeof parameters === 'object') { |
||||||
|
var param |
||||||
|
var params = Object.keys(parameters).sort() |
||||||
|
|
||||||
|
for (var i = 0; i < params.length; i++) { |
||||||
|
param = params[i] |
||||||
|
|
||||||
|
var val = param.substr(-1) === '*' |
||||||
|
? ustring(parameters[param]) |
||||||
|
: qstring(parameters[param]) |
||||||
|
|
||||||
|
string += '; ' + param + '=' + val |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return string |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Decode a RFC 5987 field value (gracefully). |
||||||
|
* |
||||||
|
* @param {string} str |
||||||
|
* @return {string} |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
function decodefield (str) { |
||||||
|
var match = EXT_VALUE_REGEXP.exec(str) |
||||||
|
|
||||||
|
if (!match) { |
||||||
|
throw new TypeError('invalid extended field value') |
||||||
|
} |
||||||
|
|
||||||
|
var charset = match[1].toLowerCase() |
||||||
|
var encoded = match[2] |
||||||
|
var value |
||||||
|
|
||||||
|
// to binary string
|
||||||
|
var binary = encoded.replace(HEX_ESCAPE_REPLACE_REGEXP, pdecode) |
||||||
|
|
||||||
|
switch (charset) { |
||||||
|
case 'iso-8859-1': |
||||||
|
value = getlatin1(binary) |
||||||
|
break |
||||||
|
case 'utf-8': |
||||||
|
value = Buffer.from(binary, 'binary').toString('utf8') |
||||||
|
break |
||||||
|
default: |
||||||
|
throw new TypeError('unsupported charset in extended field') |
||||||
|
} |
||||||
|
|
||||||
|
return value |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get ISO-8859-1 version of string. |
||||||
|
* |
||||||
|
* @param {string} val |
||||||
|
* @return {string} |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
function getlatin1 (val) { |
||||||
|
// simple Unicode -> ISO-8859-1 transformation
|
||||||
|
return String(val).replace(NON_LATIN1_REGEXP, '?') |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Parse Content-Disposition header string. |
||||||
|
* |
||||||
|
* @param {string} string |
||||||
|
* @return {object} |
||||||
|
* @public |
||||||
|
*/ |
||||||
|
|
||||||
|
function parse (string) { |
||||||
|
if (!string || typeof string !== 'string') { |
||||||
|
throw new TypeError('argument string is required') |
||||||
|
} |
||||||
|
|
||||||
|
var match = DISPOSITION_TYPE_REGEXP.exec(string) |
||||||
|
|
||||||
|
if (!match) { |
||||||
|
throw new TypeError('invalid type format') |
||||||
|
} |
||||||
|
|
||||||
|
// normalize type
|
||||||
|
var index = match[0].length |
||||||
|
var type = match[1].toLowerCase() |
||||||
|
|
||||||
|
var key |
||||||
|
var names = [] |
||||||
|
var params = {} |
||||||
|
var value |
||||||
|
|
||||||
|
// calculate index to start at
|
||||||
|
index = PARAM_REGEXP.lastIndex = match[0].substr(-1) === ';' |
||||||
|
? index - 1 |
||||||
|
: index |
||||||
|
|
||||||
|
// match parameters
|
||||||
|
while ((match = PARAM_REGEXP.exec(string))) { |
||||||
|
if (match.index !== index) { |
||||||
|
throw new TypeError('invalid parameter format') |
||||||
|
} |
||||||
|
|
||||||
|
index += match[0].length |
||||||
|
key = match[1].toLowerCase() |
||||||
|
value = match[2] |
||||||
|
|
||||||
|
if (names.indexOf(key) !== -1) { |
||||||
|
throw new TypeError('invalid duplicate parameter') |
||||||
|
} |
||||||
|
|
||||||
|
names.push(key) |
||||||
|
|
||||||
|
if (key.indexOf('*') + 1 === key.length) { |
||||||
|
// decode extended value
|
||||||
|
key = key.slice(0, -1) |
||||||
|
value = decodefield(value) |
||||||
|
|
||||||
|
// overwrite existing value
|
||||||
|
params[key] = value |
||||||
|
continue |
||||||
|
} |
||||||
|
|
||||||
|
if (typeof params[key] === 'string') { |
||||||
|
continue |
||||||
|
} |
||||||
|
|
||||||
|
if (value[0] === '"') { |
||||||
|
// remove quotes and escapes
|
||||||
|
value = value |
||||||
|
.substr(1, value.length - 2) |
||||||
|
.replace(QESC_REGEXP, '$1') |
||||||
|
} |
||||||
|
|
||||||
|
params[key] = value |
||||||
|
} |
||||||
|
|
||||||
|
if (index !== -1 && index !== string.length) { |
||||||
|
throw new TypeError('invalid parameter format') |
||||||
|
} |
||||||
|
|
||||||
|
return new ContentDisposition(type, params) |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Percent decode a single character. |
||||||
|
* |
||||||
|
* @param {string} str |
||||||
|
* @param {string} hex |
||||||
|
* @return {string} |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
function pdecode (str, hex) { |
||||||
|
return String.fromCharCode(parseInt(hex, 16)) |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Percent encode a single character. |
||||||
|
* |
||||||
|
* @param {string} char |
||||||
|
* @return {string} |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
function pencode (char) { |
||||||
|
return '%' + String(char) |
||||||
|
.charCodeAt(0) |
||||||
|
.toString(16) |
||||||
|
.toUpperCase() |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Quote a string for HTTP. |
||||||
|
* |
||||||
|
* @param {string} val |
||||||
|
* @return {string} |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
function qstring (val) { |
||||||
|
var str = String(val) |
||||||
|
|
||||||
|
return '"' + str.replace(QUOTE_REGEXP, '\\$1') + '"' |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Encode a Unicode string for HTTP (RFC 5987). |
||||||
|
* |
||||||
|
* @param {string} val |
||||||
|
* @return {string} |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
function ustring (val) { |
||||||
|
var str = String(val) |
||||||
|
|
||||||
|
// percent encode as UTF-8
|
||||||
|
var encoded = encodeURIComponent(str) |
||||||
|
.replace(ENCODE_URL_ATTR_CHAR_REGEXP, pencode) |
||||||
|
|
||||||
|
return 'UTF-8\'\'' + encoded |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Class for parsed Content-Disposition header for v8 optimization |
||||||
|
* |
||||||
|
* @public |
||||||
|
* @param {string} type |
||||||
|
* @param {object} parameters |
||||||
|
* @constructor |
||||||
|
*/ |
||||||
|
|
||||||
|
function ContentDisposition (type, parameters) { |
||||||
|
this.type = type |
||||||
|
this.parameters = parameters |
||||||
|
} |
@ -0,0 +1,44 @@ |
|||||||
|
{ |
||||||
|
"name": "content-disposition", |
||||||
|
"description": "Create and parse Content-Disposition header", |
||||||
|
"version": "0.5.4", |
||||||
|
"author": "Douglas Christopher Wilson <doug@somethingdoug.com>", |
||||||
|
"license": "MIT", |
||||||
|
"keywords": [ |
||||||
|
"content-disposition", |
||||||
|
"http", |
||||||
|
"rfc6266", |
||||||
|
"res" |
||||||
|
], |
||||||
|
"repository": "jshttp/content-disposition", |
||||||
|
"dependencies": { |
||||||
|
"safe-buffer": "5.2.1" |
||||||
|
}, |
||||||
|
"devDependencies": { |
||||||
|
"deep-equal": "1.0.1", |
||||||
|
"eslint": "7.32.0", |
||||||
|
"eslint-config-standard": "13.0.1", |
||||||
|
"eslint-plugin-import": "2.25.3", |
||||||
|
"eslint-plugin-markdown": "2.2.1", |
||||||
|
"eslint-plugin-node": "11.1.0", |
||||||
|
"eslint-plugin-promise": "5.2.0", |
||||||
|
"eslint-plugin-standard": "4.1.0", |
||||||
|
"istanbul": "0.4.5", |
||||||
|
"mocha": "9.1.3" |
||||||
|
}, |
||||||
|
"files": [ |
||||||
|
"LICENSE", |
||||||
|
"HISTORY.md", |
||||||
|
"README.md", |
||||||
|
"index.js" |
||||||
|
], |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.6" |
||||||
|
}, |
||||||
|
"scripts": { |
||||||
|
"lint": "eslint .", |
||||||
|
"test": "mocha --reporter spec --bail --check-leaks test/", |
||||||
|
"test-ci": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/", |
||||||
|
"test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/" |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,29 @@ |
|||||||
|
1.0.5 / 2023-01-29 |
||||||
|
================== |
||||||
|
|
||||||
|
* perf: skip value escaping when unnecessary |
||||||
|
|
||||||
|
1.0.4 / 2017-09-11 |
||||||
|
================== |
||||||
|
|
||||||
|
* perf: skip parameter parsing when no parameters |
||||||
|
|
||||||
|
1.0.3 / 2017-09-10 |
||||||
|
================== |
||||||
|
|
||||||
|
* perf: remove argument reassignment |
||||||
|
|
||||||
|
1.0.2 / 2016-05-09 |
||||||
|
================== |
||||||
|
|
||||||
|
* perf: enable strict mode |
||||||
|
|
||||||
|
1.0.1 / 2015-02-13 |
||||||
|
================== |
||||||
|
|
||||||
|
* Improve missing `Content-Type` header error message |
||||||
|
|
||||||
|
1.0.0 / 2015-02-01 |
||||||
|
================== |
||||||
|
|
||||||
|
* Initial implementation, derived from `media-typer@0.3.0` |
@ -0,0 +1,22 @@ |
|||||||
|
(The MIT License) |
||||||
|
|
||||||
|
Copyright (c) 2015 Douglas Christopher Wilson |
||||||
|
|
||||||
|
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. |
@ -0,0 +1,94 @@ |
|||||||
|
# content-type |
||||||
|
|
||||||
|
[![NPM Version][npm-version-image]][npm-url] |
||||||
|
[![NPM Downloads][npm-downloads-image]][npm-url] |
||||||
|
[![Node.js Version][node-image]][node-url] |
||||||
|
[![Build Status][ci-image]][ci-url] |
||||||
|
[![Coverage Status][coveralls-image]][coveralls-url] |
||||||
|
|
||||||
|
Create and parse HTTP Content-Type header according to RFC 7231 |
||||||
|
|
||||||
|
## Installation |
||||||
|
|
||||||
|
```sh |
||||||
|
$ npm install content-type |
||||||
|
``` |
||||||
|
|
||||||
|
## API |
||||||
|
|
||||||
|
```js |
||||||
|
var contentType = require('content-type') |
||||||
|
``` |
||||||
|
|
||||||
|
### contentType.parse(string) |
||||||
|
|
||||||
|
```js |
||||||
|
var obj = contentType.parse('image/svg+xml; charset=utf-8') |
||||||
|
``` |
||||||
|
|
||||||
|
Parse a `Content-Type` header. This will return an object with the following |
||||||
|
properties (examples are shown for the string `'image/svg+xml; charset=utf-8'`): |
||||||
|
|
||||||
|
- `type`: The media type (the type and subtype, always lower case). |
||||||
|
Example: `'image/svg+xml'` |
||||||
|
|
||||||
|
- `parameters`: An object of the parameters in the media type (name of parameter |
||||||
|
always lower case). Example: `{charset: 'utf-8'}` |
||||||
|
|
||||||
|
Throws a `TypeError` if the string is missing or invalid. |
||||||
|
|
||||||
|
### contentType.parse(req) |
||||||
|
|
||||||
|
```js |
||||||
|
var obj = contentType.parse(req) |
||||||
|
``` |
||||||
|
|
||||||
|
Parse the `Content-Type` header from the given `req`. Short-cut for |
||||||
|
`contentType.parse(req.headers['content-type'])`. |
||||||
|
|
||||||
|
Throws a `TypeError` if the `Content-Type` header is missing or invalid. |
||||||
|
|
||||||
|
### contentType.parse(res) |
||||||
|
|
||||||
|
```js |
||||||
|
var obj = contentType.parse(res) |
||||||
|
``` |
||||||
|
|
||||||
|
Parse the `Content-Type` header set on the given `res`. Short-cut for |
||||||
|
`contentType.parse(res.getHeader('content-type'))`. |
||||||
|
|
||||||
|
Throws a `TypeError` if the `Content-Type` header is missing or invalid. |
||||||
|
|
||||||
|
### contentType.format(obj) |
||||||
|
|
||||||
|
```js |
||||||
|
var str = contentType.format({ |
||||||
|
type: 'image/svg+xml', |
||||||
|
parameters: { charset: 'utf-8' } |
||||||
|
}) |
||||||
|
``` |
||||||
|
|
||||||
|
Format an object into a `Content-Type` header. This will return a string of the |
||||||
|
content type for the given object with the following properties (examples are |
||||||
|
shown that produce the string `'image/svg+xml; charset=utf-8'`): |
||||||
|
|
||||||
|
- `type`: The media type (will be lower-cased). Example: `'image/svg+xml'` |
||||||
|
|
||||||
|
- `parameters`: An object of the parameters in the media type (name of the |
||||||
|
parameter will be lower-cased). Example: `{charset: 'utf-8'}` |
||||||
|
|
||||||
|
Throws a `TypeError` if the object contains an invalid type or parameter names. |
||||||
|
|
||||||
|
## License |
||||||
|
|
||||||
|
[MIT](LICENSE) |
||||||
|
|
||||||
|
[ci-image]: https://badgen.net/github/checks/jshttp/content-type/master?label=ci |
||||||
|
[ci-url]: https://github.com/jshttp/content-type/actions/workflows/ci.yml |
||||||
|
[coveralls-image]: https://badgen.net/coveralls/c/github/jshttp/content-type/master |
||||||
|
[coveralls-url]: https://coveralls.io/r/jshttp/content-type?branch=master |
||||||
|
[node-image]: https://badgen.net/npm/node/content-type |
||||||
|
[node-url]: https://nodejs.org/en/download |
||||||
|
[npm-downloads-image]: https://badgen.net/npm/dm/content-type |
||||||
|
[npm-url]: https://npmjs.org/package/content-type |
||||||
|
[npm-version-image]: https://badgen.net/npm/v/content-type |
@ -0,0 +1,225 @@ |
|||||||
|
/*! |
||||||
|
* content-type |
||||||
|
* Copyright(c) 2015 Douglas Christopher Wilson |
||||||
|
* MIT Licensed |
||||||
|
*/ |
||||||
|
|
||||||
|
'use strict' |
||||||
|
|
||||||
|
/** |
||||||
|
* RegExp to match *( ";" parameter ) in RFC 7231 sec 3.1.1.1 |
||||||
|
* |
||||||
|
* parameter = token "=" ( token / quoted-string ) |
||||||
|
* token = 1*tchar |
||||||
|
* tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" |
||||||
|
* / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~" |
||||||
|
* / DIGIT / ALPHA |
||||||
|
* ; any VCHAR, except delimiters |
||||||
|
* quoted-string = DQUOTE *( qdtext / quoted-pair ) DQUOTE |
||||||
|
* qdtext = HTAB / SP / %x21 / %x23-5B / %x5D-7E / obs-text |
||||||
|
* obs-text = %x80-FF |
||||||
|
* quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text ) |
||||||
|
*/ |
||||||
|
var PARAM_REGEXP = /; *([!#$%&'*+.^_`|~0-9A-Za-z-]+) *= *("(?:[\u000b\u0020\u0021\u0023-\u005b\u005d-\u007e\u0080-\u00ff]|\\[\u000b\u0020-\u00ff])*"|[!#$%&'*+.^_`|~0-9A-Za-z-]+) */g // eslint-disable-line no-control-regex
|
||||||
|
var TEXT_REGEXP = /^[\u000b\u0020-\u007e\u0080-\u00ff]+$/ // eslint-disable-line no-control-regex
|
||||||
|
var TOKEN_REGEXP = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/ |
||||||
|
|
||||||
|
/** |
||||||
|
* RegExp to match quoted-pair in RFC 7230 sec 3.2.6 |
||||||
|
* |
||||||
|
* quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text ) |
||||||
|
* obs-text = %x80-FF |
||||||
|
*/ |
||||||
|
var QESC_REGEXP = /\\([\u000b\u0020-\u00ff])/g // eslint-disable-line no-control-regex
|
||||||
|
|
||||||
|
/** |
||||||
|
* RegExp to match chars that must be quoted-pair in RFC 7230 sec 3.2.6 |
||||||
|
*/ |
||||||
|
var QUOTE_REGEXP = /([\\"])/g |
||||||
|
|
||||||
|
/** |
||||||
|
* RegExp to match type in RFC 7231 sec 3.1.1.1 |
||||||
|
* |
||||||
|
* media-type = type "/" subtype |
||||||
|
* type = token |
||||||
|
* subtype = token |
||||||
|
*/ |
||||||
|
var TYPE_REGEXP = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+\/[!#$%&'*+.^_`|~0-9A-Za-z-]+$/ |
||||||
|
|
||||||
|
/** |
||||||
|
* Module exports. |
||||||
|
* @public |
||||||
|
*/ |
||||||
|
|
||||||
|
exports.format = format |
||||||
|
exports.parse = parse |
||||||
|
|
||||||
|
/** |
||||||
|
* Format object to media type. |
||||||
|
* |
||||||
|
* @param {object} obj |
||||||
|
* @return {string} |
||||||
|
* @public |
||||||
|
*/ |
||||||
|
|
||||||
|
function format (obj) { |
||||||
|
if (!obj || typeof obj !== 'object') { |
||||||
|
throw new TypeError('argument obj is required') |
||||||
|
} |
||||||
|
|
||||||
|
var parameters = obj.parameters |
||||||
|
var type = obj.type |
||||||
|
|
||||||
|
if (!type || !TYPE_REGEXP.test(type)) { |
||||||
|
throw new TypeError('invalid type') |
||||||
|
} |
||||||
|
|
||||||
|
var string = type |
||||||
|
|
||||||
|
// append parameters
|
||||||
|
if (parameters && typeof parameters === 'object') { |
||||||
|
var param |
||||||
|
var params = Object.keys(parameters).sort() |
||||||
|
|
||||||
|
for (var i = 0; i < params.length; i++) { |
||||||
|
param = params[i] |
||||||
|
|
||||||
|
if (!TOKEN_REGEXP.test(param)) { |
||||||
|
throw new TypeError('invalid parameter name') |
||||||
|
} |
||||||
|
|
||||||
|
string += '; ' + param + '=' + qstring(parameters[param]) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return string |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Parse media type to object. |
||||||
|
* |
||||||
|
* @param {string|object} string |
||||||
|
* @return {Object} |
||||||
|
* @public |
||||||
|
*/ |
||||||
|
|
||||||
|
function parse (string) { |
||||||
|
if (!string) { |
||||||
|
throw new TypeError('argument string is required') |
||||||
|
} |
||||||
|
|
||||||
|
// support req/res-like objects as argument
|
||||||
|
var header = typeof string === 'object' |
||||||
|
? getcontenttype(string) |
||||||
|
: string |
||||||
|
|
||||||
|
if (typeof header !== 'string') { |
||||||
|
throw new TypeError('argument string is required to be a string') |
||||||
|
} |
||||||
|
|
||||||
|
var index = header.indexOf(';') |
||||||
|
var type = index !== -1 |
||||||
|
? header.slice(0, index).trim() |
||||||
|
: header.trim() |
||||||
|
|
||||||
|
if (!TYPE_REGEXP.test(type)) { |
||||||
|
throw new TypeError('invalid media type') |
||||||
|
} |
||||||
|
|
||||||
|
var obj = new ContentType(type.toLowerCase()) |
||||||
|
|
||||||
|
// parse parameters
|
||||||
|
if (index !== -1) { |
||||||
|
var key |
||||||
|
var match |
||||||
|
var value |
||||||
|
|
||||||
|
PARAM_REGEXP.lastIndex = index |
||||||
|
|
||||||
|
while ((match = PARAM_REGEXP.exec(header))) { |
||||||
|
if (match.index !== index) { |
||||||
|
throw new TypeError('invalid parameter format') |
||||||
|
} |
||||||
|
|
||||||
|
index += match[0].length |
||||||
|
key = match[1].toLowerCase() |
||||||
|
value = match[2] |
||||||
|
|
||||||
|
if (value.charCodeAt(0) === 0x22 /* " */) { |
||||||
|
// remove quotes
|
||||||
|
value = value.slice(1, -1) |
||||||
|
|
||||||
|
// remove escapes
|
||||||
|
if (value.indexOf('\\') !== -1) { |
||||||
|
value = value.replace(QESC_REGEXP, '$1') |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
obj.parameters[key] = value |
||||||
|
} |
||||||
|
|
||||||
|
if (index !== header.length) { |
||||||
|
throw new TypeError('invalid parameter format') |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return obj |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get content-type from req/res objects. |
||||||
|
* |
||||||
|
* @param {object} |
||||||
|
* @return {Object} |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
function getcontenttype (obj) { |
||||||
|
var header |
||||||
|
|
||||||
|
if (typeof obj.getHeader === 'function') { |
||||||
|
// res-like
|
||||||
|
header = obj.getHeader('content-type') |
||||||
|
} else if (typeof obj.headers === 'object') { |
||||||
|
// req-like
|
||||||
|
header = obj.headers && obj.headers['content-type'] |
||||||
|
} |
||||||
|
|
||||||
|
if (typeof header !== 'string') { |
||||||
|
throw new TypeError('content-type header is missing from object') |
||||||
|
} |
||||||
|
|
||||||
|
return header |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Quote a string if necessary. |
||||||
|
* |
||||||
|
* @param {string} val |
||||||
|
* @return {string} |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
function qstring (val) { |
||||||
|
var str = String(val) |
||||||
|
|
||||||
|
// no need to quote tokens
|
||||||
|
if (TOKEN_REGEXP.test(str)) { |
||||||
|
return str |
||||||
|
} |
||||||
|
|
||||||
|
if (str.length > 0 && !TEXT_REGEXP.test(str)) { |
||||||
|
throw new TypeError('invalid parameter value') |
||||||
|
} |
||||||
|
|
||||||
|
return '"' + str.replace(QUOTE_REGEXP, '\\$1') + '"' |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Class to represent a content type. |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
function ContentType (type) { |
||||||
|
this.parameters = Object.create(null) |
||||||
|
this.type = type |
||||||
|
} |
@ -0,0 +1,42 @@ |
|||||||
|
{ |
||||||
|
"name": "content-type", |
||||||
|
"description": "Create and parse HTTP Content-Type header", |
||||||
|
"version": "1.0.5", |
||||||
|
"author": "Douglas Christopher Wilson <doug@somethingdoug.com>", |
||||||
|
"license": "MIT", |
||||||
|
"keywords": [ |
||||||
|
"content-type", |
||||||
|
"http", |
||||||
|
"req", |
||||||
|
"res", |
||||||
|
"rfc7231" |
||||||
|
], |
||||||
|
"repository": "jshttp/content-type", |
||||||
|
"devDependencies": { |
||||||
|
"deep-equal": "1.0.1", |
||||||
|
"eslint": "8.32.0", |
||||||
|
"eslint-config-standard": "15.0.1", |
||||||
|
"eslint-plugin-import": "2.27.5", |
||||||
|
"eslint-plugin-node": "11.1.0", |
||||||
|
"eslint-plugin-promise": "6.1.1", |
||||||
|
"eslint-plugin-standard": "4.1.0", |
||||||
|
"mocha": "10.2.0", |
||||||
|
"nyc": "15.1.0" |
||||||
|
}, |
||||||
|
"files": [ |
||||||
|
"LICENSE", |
||||||
|
"HISTORY.md", |
||||||
|
"README.md", |
||||||
|
"index.js" |
||||||
|
], |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.6" |
||||||
|
}, |
||||||
|
"scripts": { |
||||||
|
"lint": "eslint .", |
||||||
|
"test": "mocha --reporter spec --check-leaks --bail test/", |
||||||
|
"test-ci": "nyc --reporter=lcovonly --reporter=text npm test", |
||||||
|
"test-cov": "nyc --reporter=html --reporter=text npm test", |
||||||
|
"version": "node scripts/version-history.js && git add HISTORY.md" |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,4 @@ |
|||||||
|
support |
||||||
|
test |
||||||
|
examples |
||||||
|
*.sock |
@ -0,0 +1,38 @@ |
|||||||
|
1.0.6 / 2015-02-03 |
||||||
|
================== |
||||||
|
|
||||||
|
* use `npm test` instead of `make test` to run tests |
||||||
|
* clearer assertion messages when checking input |
||||||
|
|
||||||
|
|
||||||
|
1.0.5 / 2014-09-05 |
||||||
|
================== |
||||||
|
|
||||||
|
* add license to package.json |
||||||
|
|
||||||
|
1.0.4 / 2014-06-25 |
||||||
|
================== |
||||||
|
|
||||||
|
* corrected avoidance of timing attacks (thanks @tenbits!) |
||||||
|
|
||||||
|
1.0.3 / 2014-01-28 |
||||||
|
================== |
||||||
|
|
||||||
|
* [incorrect] fix for timing attacks |
||||||
|
|
||||||
|
1.0.2 / 2014-01-28 |
||||||
|
================== |
||||||
|
|
||||||
|
* fix missing repository warning |
||||||
|
* fix typo in test |
||||||
|
|
||||||
|
1.0.1 / 2013-04-15 |
||||||
|
================== |
||||||
|
|
||||||
|
* Revert "Changed underlying HMAC algo. to sha512." |
||||||
|
* Revert "Fix for timing attacks on MAC verification." |
||||||
|
|
||||||
|
0.0.1 / 2010-01-03 |
||||||
|
================== |
||||||
|
|
||||||
|
* Initial release |
@ -0,0 +1,42 @@ |
|||||||
|
|
||||||
|
# cookie-signature |
||||||
|
|
||||||
|
Sign and unsign cookies. |
||||||
|
|
||||||
|
## Example |
||||||
|
|
||||||
|
```js |
||||||
|
var cookie = require('cookie-signature'); |
||||||
|
|
||||||
|
var val = cookie.sign('hello', 'tobiiscool'); |
||||||
|
val.should.equal('hello.DGDUkGlIkCzPz+C0B064FNgHdEjox7ch8tOBGslZ5QI'); |
||||||
|
|
||||||
|
var val = cookie.sign('hello', 'tobiiscool'); |
||||||
|
cookie.unsign(val, 'tobiiscool').should.equal('hello'); |
||||||
|
cookie.unsign(val, 'luna').should.be.false; |
||||||
|
``` |
||||||
|
|
||||||
|
## License |
||||||
|
|
||||||
|
(The MIT License) |
||||||
|
|
||||||
|
Copyright (c) 2012 LearnBoost <tj@learnboost.com> |
||||||
|
|
||||||
|
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. |
@ -0,0 +1,51 @@ |
|||||||
|
/** |
||||||
|
* Module dependencies. |
||||||
|
*/ |
||||||
|
|
||||||
|
var crypto = require('crypto'); |
||||||
|
|
||||||
|
/** |
||||||
|
* Sign the given `val` with `secret`. |
||||||
|
* |
||||||
|
* @param {String} val |
||||||
|
* @param {String} secret |
||||||
|
* @return {String} |
||||||
|
* @api private |
||||||
|
*/ |
||||||
|
|
||||||
|
exports.sign = function(val, secret){ |
||||||
|
if ('string' != typeof val) throw new TypeError("Cookie value must be provided as a string."); |
||||||
|
if ('string' != typeof secret) throw new TypeError("Secret string must be provided."); |
||||||
|
return val + '.' + crypto |
||||||
|
.createHmac('sha256', secret) |
||||||
|
.update(val) |
||||||
|
.digest('base64') |
||||||
|
.replace(/\=+$/, ''); |
||||||
|
}; |
||||||
|
|
||||||
|
/** |
||||||
|
* Unsign and decode the given `val` with `secret`, |
||||||
|
* returning `false` if the signature is invalid. |
||||||
|
* |
||||||
|
* @param {String} val |
||||||
|
* @param {String} secret |
||||||
|
* @return {String|Boolean} |
||||||
|
* @api private |
||||||
|
*/ |
||||||
|
|
||||||
|
exports.unsign = function(val, secret){ |
||||||
|
if ('string' != typeof val) throw new TypeError("Signed cookie string must be provided."); |
||||||
|
if ('string' != typeof secret) throw new TypeError("Secret string must be provided."); |
||||||
|
var str = val.slice(0, val.lastIndexOf('.')) |
||||||
|
, mac = exports.sign(str, secret); |
||||||
|
|
||||||
|
return sha1(mac) == sha1(val) ? str : false; |
||||||
|
}; |
||||||
|
|
||||||
|
/** |
||||||
|
* Private |
||||||
|
*/ |
||||||
|
|
||||||
|
function sha1(str){ |
||||||
|
return crypto.createHash('sha1').update(str).digest('hex'); |
||||||
|
} |
@ -0,0 +1,18 @@ |
|||||||
|
{ |
||||||
|
"name": "cookie-signature", |
||||||
|
"version": "1.0.6", |
||||||
|
"description": "Sign and unsign cookies", |
||||||
|
"keywords": ["cookie", "sign", "unsign"], |
||||||
|
"author": "TJ Holowaychuk <tj@learnboost.com>", |
||||||
|
"license": "MIT", |
||||||
|
"repository": { "type": "git", "url": "https://github.com/visionmedia/node-cookie-signature.git"}, |
||||||
|
"dependencies": {}, |
||||||
|
"devDependencies": { |
||||||
|
"mocha": "*", |
||||||
|
"should": "*" |
||||||
|
}, |
||||||
|
"scripts": { |
||||||
|
"test": "mocha --require should --reporter spec" |
||||||
|
}, |
||||||
|
"main": "index" |
||||||
|
} |
@ -0,0 +1,147 @@ |
|||||||
|
0.6.0 / 2023-11-06 |
||||||
|
================== |
||||||
|
|
||||||
|
* Add `partitioned` option |
||||||
|
|
||||||
|
0.5.0 / 2022-04-11 |
||||||
|
================== |
||||||
|
|
||||||
|
* Add `priority` option |
||||||
|
* Fix `expires` option to reject invalid dates |
||||||
|
* perf: improve default decode speed |
||||||
|
* perf: remove slow string split in parse |
||||||
|
|
||||||
|
0.4.2 / 2022-02-02 |
||||||
|
================== |
||||||
|
|
||||||
|
* perf: read value only when assigning in parse |
||||||
|
* perf: remove unnecessary regexp in parse |
||||||
|
|
||||||
|
0.4.1 / 2020-04-21 |
||||||
|
================== |
||||||
|
|
||||||
|
* Fix `maxAge` option to reject invalid values |
||||||
|
|
||||||
|
0.4.0 / 2019-05-15 |
||||||
|
================== |
||||||
|
|
||||||
|
* Add `SameSite=None` support |
||||||
|
|
||||||
|
0.3.1 / 2016-05-26 |
||||||
|
================== |
||||||
|
|
||||||
|
* Fix `sameSite: true` to work with draft-7 clients |
||||||
|
- `true` now sends `SameSite=Strict` instead of `SameSite` |
||||||
|
|
||||||
|
0.3.0 / 2016-05-26 |
||||||
|
================== |
||||||
|
|
||||||
|
* Add `sameSite` option |
||||||
|
- Replaces `firstPartyOnly` option, never implemented by browsers |
||||||
|
* Improve error message when `encode` is not a function |
||||||
|
* Improve error message when `expires` is not a `Date` |
||||||
|
|
||||||
|
0.2.4 / 2016-05-20 |
||||||
|
================== |
||||||
|
|
||||||
|
* perf: enable strict mode |
||||||
|
* perf: use for loop in parse |
||||||
|
* perf: use string concatenation for serialization |
||||||
|
|
||||||
|
0.2.3 / 2015-10-25 |
||||||
|
================== |
||||||
|
|
||||||
|
* Fix cookie `Max-Age` to never be a floating point number |
||||||
|
|
||||||
|
0.2.2 / 2015-09-17 |
||||||
|
================== |
||||||
|
|
||||||
|
* Fix regression when setting empty cookie value |
||||||
|
- Ease the new restriction, which is just basic header-level validation |
||||||
|
* Fix typo in invalid value errors |
||||||
|
|
||||||
|
0.2.1 / 2015-09-17 |
||||||
|
================== |
||||||
|
|
||||||
|
* Throw on invalid values provided to `serialize` |
||||||
|
- Ensures the resulting string is a valid HTTP header value |
||||||
|
|
||||||
|
0.2.0 / 2015-08-13 |
||||||
|
================== |
||||||
|
|
||||||
|
* Add `firstPartyOnly` option |
||||||
|
* Throw better error for invalid argument to parse |
||||||
|
* perf: hoist regular expression |
||||||
|
|
||||||
|
0.1.5 / 2015-09-17 |
||||||
|
================== |
||||||
|
|
||||||
|
* Fix regression when setting empty cookie value |
||||||
|
- Ease the new restriction, which is just basic header-level validation |
||||||
|
* Fix typo in invalid value errors |
||||||
|
|
||||||
|
0.1.4 / 2015-09-17 |
||||||
|
================== |
||||||
|
|
||||||
|
* Throw better error for invalid argument to parse |
||||||
|
* Throw on invalid values provided to `serialize` |
||||||
|
- Ensures the resulting string is a valid HTTP header value |
||||||
|
|
||||||
|
0.1.3 / 2015-05-19 |
||||||
|
================== |
||||||
|
|
||||||
|
* Reduce the scope of try-catch deopt |
||||||
|
* Remove argument reassignments |
||||||
|
|
||||||
|
0.1.2 / 2014-04-16 |
||||||
|
================== |
||||||
|
|
||||||
|
* Remove unnecessary files from npm package |
||||||
|
|
||||||
|
0.1.1 / 2014-02-23 |
||||||
|
================== |
||||||
|
|
||||||
|
* Fix bad parse when cookie value contained a comma |
||||||
|
* Fix support for `maxAge` of `0` |
||||||
|
|
||||||
|
0.1.0 / 2013-05-01 |
||||||
|
================== |
||||||
|
|
||||||
|
* Add `decode` option |
||||||
|
* Add `encode` option |
||||||
|
|
||||||
|
0.0.6 / 2013-04-08 |
||||||
|
================== |
||||||
|
|
||||||
|
* Ignore cookie parts missing `=` |
||||||
|
|
||||||
|
0.0.5 / 2012-10-29 |
||||||
|
================== |
||||||
|
|
||||||
|
* Return raw cookie value if value unescape errors |
||||||
|
|
||||||
|
0.0.4 / 2012-06-21 |
||||||
|
================== |
||||||
|
|
||||||
|
* Use encode/decodeURIComponent for cookie encoding/decoding |
||||||
|
- Improve server/client interoperability |
||||||
|
|
||||||
|
0.0.3 / 2012-06-06 |
||||||
|
================== |
||||||
|
|
||||||
|
* Only escape special characters per the cookie RFC |
||||||
|
|
||||||
|
0.0.2 / 2012-06-01 |
||||||
|
================== |
||||||
|
|
||||||
|
* Fix `maxAge` option to not throw error |
||||||
|
|
||||||
|
0.0.1 / 2012-05-28 |
||||||
|
================== |
||||||
|
|
||||||
|
* Add more tests |
||||||
|
|
||||||
|
0.0.0 / 2012-05-28 |
||||||
|
================== |
||||||
|
|
||||||
|
* Initial release |
@ -0,0 +1,24 @@ |
|||||||
|
(The MIT License) |
||||||
|
|
||||||
|
Copyright (c) 2012-2014 Roman Shtylman <shtylman@gmail.com> |
||||||
|
Copyright (c) 2015 Douglas Christopher Wilson <doug@somethingdoug.com> |
||||||
|
|
||||||
|
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. |
||||||
|
|
@ -0,0 +1,317 @@ |
|||||||
|
# cookie |
||||||
|
|
||||||
|
[![NPM Version][npm-version-image]][npm-url] |
||||||
|
[![NPM Downloads][npm-downloads-image]][npm-url] |
||||||
|
[![Node.js Version][node-image]][node-url] |
||||||
|
[![Build Status][ci-image]][ci-url] |
||||||
|
[![Coverage Status][coveralls-image]][coveralls-url] |
||||||
|
|
||||||
|
Basic HTTP cookie parser and serializer for HTTP servers. |
||||||
|
|
||||||
|
## Installation |
||||||
|
|
||||||
|
This is a [Node.js](https://nodejs.org/en/) module available through the |
||||||
|
[npm registry](https://www.npmjs.com/). Installation is done using the |
||||||
|
[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): |
||||||
|
|
||||||
|
```sh |
||||||
|
$ npm install cookie |
||||||
|
``` |
||||||
|
|
||||||
|
## API |
||||||
|
|
||||||
|
```js |
||||||
|
var cookie = require('cookie'); |
||||||
|
``` |
||||||
|
|
||||||
|
### cookie.parse(str, options) |
||||||
|
|
||||||
|
Parse an HTTP `Cookie` header string and returning an object of all cookie name-value pairs. |
||||||
|
The `str` argument is the string representing a `Cookie` header value and `options` is an |
||||||
|
optional object containing additional parsing options. |
||||||
|
|
||||||
|
```js |
||||||
|
var cookies = cookie.parse('foo=bar; equation=E%3Dmc%5E2'); |
||||||
|
// { foo: 'bar', equation: 'E=mc^2' } |
||||||
|
``` |
||||||
|
|
||||||
|
#### Options |
||||||
|
|
||||||
|
`cookie.parse` accepts these properties in the options object. |
||||||
|
|
||||||
|
##### decode |
||||||
|
|
||||||
|
Specifies a function that will be used to decode a cookie's value. Since the value of a cookie |
||||||
|
has a limited character set (and must be a simple string), this function can be used to decode |
||||||
|
a previously-encoded cookie value into a JavaScript string or other object. |
||||||
|
|
||||||
|
The default function is the global `decodeURIComponent`, which will decode any URL-encoded |
||||||
|
sequences into their byte representations. |
||||||
|
|
||||||
|
**note** if an error is thrown from this function, the original, non-decoded cookie value will |
||||||
|
be returned as the cookie's value. |
||||||
|
|
||||||
|
### cookie.serialize(name, value, options) |
||||||
|
|
||||||
|
Serialize a cookie name-value pair into a `Set-Cookie` header string. The `name` argument is the |
||||||
|
name for the cookie, the `value` argument is the value to set the cookie to, and the `options` |
||||||
|
argument is an optional object containing additional serialization options. |
||||||
|
|
||||||
|
```js |
||||||
|
var setCookie = cookie.serialize('foo', 'bar'); |
||||||
|
// foo=bar |
||||||
|
``` |
||||||
|
|
||||||
|
#### Options |
||||||
|
|
||||||
|
`cookie.serialize` accepts these properties in the options object. |
||||||
|
|
||||||
|
##### domain |
||||||
|
|
||||||
|
Specifies the value for the [`Domain` `Set-Cookie` attribute][rfc-6265-5.2.3]. By default, no |
||||||
|
domain is set, and most clients will consider the cookie to apply to only the current domain. |
||||||
|
|
||||||
|
##### encode |
||||||
|
|
||||||
|
Specifies a function that will be used to encode a cookie's value. Since value of a cookie |
||||||
|
has a limited character set (and must be a simple string), this function can be used to encode |
||||||
|
a value into a string suited for a cookie's value. |
||||||
|
|
||||||
|
The default function is the global `encodeURIComponent`, which will encode a JavaScript string |
||||||
|
into UTF-8 byte sequences and then URL-encode any that fall outside of the cookie range. |
||||||
|
|
||||||
|
##### expires |
||||||
|
|
||||||
|
Specifies the `Date` object to be the value for the [`Expires` `Set-Cookie` attribute][rfc-6265-5.2.1]. |
||||||
|
By default, no expiration is set, and most clients will consider this a "non-persistent cookie" and |
||||||
|
will delete it on a condition like exiting a web browser application. |
||||||
|
|
||||||
|
**note** the [cookie storage model specification][rfc-6265-5.3] states that if both `expires` and |
||||||
|
`maxAge` are set, then `maxAge` takes precedence, but it is possible not all clients by obey this, |
||||||
|
so if both are set, they should point to the same date and time. |
||||||
|
|
||||||
|
##### httpOnly |
||||||
|
|
||||||
|
Specifies the `boolean` value for the [`HttpOnly` `Set-Cookie` attribute][rfc-6265-5.2.6]. When truthy, |
||||||
|
the `HttpOnly` attribute is set, otherwise it is not. By default, the `HttpOnly` attribute is not set. |
||||||
|
|
||||||
|
**note** be careful when setting this to `true`, as compliant clients will not allow client-side |
||||||
|
JavaScript to see the cookie in `document.cookie`. |
||||||
|
|
||||||
|
##### maxAge |
||||||
|
|
||||||
|
Specifies the `number` (in seconds) to be the value for the [`Max-Age` `Set-Cookie` attribute][rfc-6265-5.2.2]. |
||||||
|
The given number will be converted to an integer by rounding down. By default, no maximum age is set. |
||||||
|
|
||||||
|
**note** the [cookie storage model specification][rfc-6265-5.3] states that if both `expires` and |
||||||
|
`maxAge` are set, then `maxAge` takes precedence, but it is possible not all clients by obey this, |
||||||
|
so if both are set, they should point to the same date and time. |
||||||
|
|
||||||
|
##### partitioned |
||||||
|
|
||||||
|
Specifies the `boolean` value for the [`Partitioned` `Set-Cookie`](rfc-cutler-httpbis-partitioned-cookies) |
||||||
|
attribute. When truthy, the `Partitioned` attribute is set, otherwise it is not. By default, the |
||||||
|
`Partitioned` attribute is not set. |
||||||
|
|
||||||
|
**note** This is an attribute that has not yet been fully standardized, and may change in the future. |
||||||
|
This also means many clients may ignore this attribute until they understand it. |
||||||
|
|
||||||
|
More information about can be found in [the proposal](https://github.com/privacycg/CHIPS). |
||||||
|
|
||||||
|
##### path |
||||||
|
|
||||||
|
Specifies the value for the [`Path` `Set-Cookie` attribute][rfc-6265-5.2.4]. By default, the path |
||||||
|
is considered the ["default path"][rfc-6265-5.1.4]. |
||||||
|
|
||||||
|
##### priority |
||||||
|
|
||||||
|
Specifies the `string` to be the value for the [`Priority` `Set-Cookie` attribute][rfc-west-cookie-priority-00-4.1]. |
||||||
|
|
||||||
|
- `'low'` will set the `Priority` attribute to `Low`. |
||||||
|
- `'medium'` will set the `Priority` attribute to `Medium`, the default priority when not set. |
||||||
|
- `'high'` will set the `Priority` attribute to `High`. |
||||||
|
|
||||||
|
More information about the different priority levels can be found in |
||||||
|
[the specification][rfc-west-cookie-priority-00-4.1]. |
||||||
|
|
||||||
|
**note** This is an attribute that has not yet been fully standardized, and may change in the future. |
||||||
|
This also means many clients may ignore this attribute until they understand it. |
||||||
|
|
||||||
|
##### sameSite |
||||||
|
|
||||||
|
Specifies the `boolean` or `string` to be the value for the [`SameSite` `Set-Cookie` attribute][rfc-6265bis-09-5.4.7]. |
||||||
|
|
||||||
|
- `true` will set the `SameSite` attribute to `Strict` for strict same site enforcement. |
||||||
|
- `false` will not set the `SameSite` attribute. |
||||||
|
- `'lax'` will set the `SameSite` attribute to `Lax` for lax same site enforcement. |
||||||
|
- `'none'` will set the `SameSite` attribute to `None` for an explicit cross-site cookie. |
||||||
|
- `'strict'` will set the `SameSite` attribute to `Strict` for strict same site enforcement. |
||||||
|
|
||||||
|
More information about the different enforcement levels can be found in |
||||||
|
[the specification][rfc-6265bis-09-5.4.7]. |
||||||
|
|
||||||
|
**note** This is an attribute that has not yet been fully standardized, and may change in the future. |
||||||
|
This also means many clients may ignore this attribute until they understand it. |
||||||
|
|
||||||
|
##### secure |
||||||
|
|
||||||
|
Specifies the `boolean` value for the [`Secure` `Set-Cookie` attribute][rfc-6265-5.2.5]. When truthy, |
||||||
|
the `Secure` attribute is set, otherwise it is not. By default, the `Secure` attribute is not set. |
||||||
|
|
||||||
|
**note** be careful when setting this to `true`, as compliant clients will not send the cookie back to |
||||||
|
the server in the future if the browser does not have an HTTPS connection. |
||||||
|
|
||||||
|
## Example |
||||||
|
|
||||||
|
The following example uses this module in conjunction with the Node.js core HTTP server |
||||||
|
to prompt a user for their name and display it back on future visits. |
||||||
|
|
||||||
|
```js |
||||||
|
var cookie = require('cookie'); |
||||||
|
var escapeHtml = require('escape-html'); |
||||||
|
var http = require('http'); |
||||||
|
var url = require('url'); |
||||||
|
|
||||||
|
function onRequest(req, res) { |
||||||
|
// Parse the query string |
||||||
|
var query = url.parse(req.url, true, true).query; |
||||||
|
|
||||||
|
if (query && query.name) { |
||||||
|
// Set a new cookie with the name |
||||||
|
res.setHeader('Set-Cookie', cookie.serialize('name', String(query.name), { |
||||||
|
httpOnly: true, |
||||||
|
maxAge: 60 * 60 * 24 * 7 // 1 week |
||||||
|
})); |
||||||
|
|
||||||
|
// Redirect back after setting cookie |
||||||
|
res.statusCode = 302; |
||||||
|
res.setHeader('Location', req.headers.referer || '/'); |
||||||
|
res.end(); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
// Parse the cookies on the request |
||||||
|
var cookies = cookie.parse(req.headers.cookie || ''); |
||||||
|
|
||||||
|
// Get the visitor name set in the cookie |
||||||
|
var name = cookies.name; |
||||||
|
|
||||||
|
res.setHeader('Content-Type', 'text/html; charset=UTF-8'); |
||||||
|
|
||||||
|
if (name) { |
||||||
|
res.write('<p>Welcome back, <b>' + escapeHtml(name) + '</b>!</p>'); |
||||||
|
} else { |
||||||
|
res.write('<p>Hello, new visitor!</p>'); |
||||||
|
} |
||||||
|
|
||||||
|
res.write('<form method="GET">'); |
||||||
|
res.write('<input placeholder="enter your name" name="name"> <input type="submit" value="Set Name">'); |
||||||
|
res.end('</form>'); |
||||||
|
} |
||||||
|
|
||||||
|
http.createServer(onRequest).listen(3000); |
||||||
|
``` |
||||||
|
|
||||||
|
## Testing |
||||||
|
|
||||||
|
```sh |
||||||
|
$ npm test |
||||||
|
``` |
||||||
|
|
||||||
|
## Benchmark |
||||||
|
|
||||||
|
``` |
||||||
|
$ npm run bench |
||||||
|
|
||||||
|
> cookie@0.5.0 bench |
||||||
|
> node benchmark/index.js |
||||||
|
|
||||||
|
node@18.18.2 |
||||||
|
acorn@8.10.0 |
||||||
|
ada@2.6.0 |
||||||
|
ares@1.19.1 |
||||||
|
brotli@1.0.9 |
||||||
|
cldr@43.1 |
||||||
|
icu@73.2 |
||||||
|
llhttp@6.0.11 |
||||||
|
modules@108 |
||||||
|
napi@9 |
||||||
|
nghttp2@1.57.0 |
||||||
|
nghttp3@0.7.0 |
||||||
|
ngtcp2@0.8.1 |
||||||
|
openssl@3.0.10+quic |
||||||
|
simdutf@3.2.14 |
||||||
|
tz@2023c |
||||||
|
undici@5.26.3 |
||||||
|
unicode@15.0 |
||||||
|
uv@1.44.2 |
||||||
|
uvwasi@0.0.18 |
||||||
|
v8@10.2.154.26-node.26 |
||||||
|
zlib@1.2.13.1-motley |
||||||
|
|
||||||
|
> node benchmark/parse-top.js |
||||||
|
|
||||||
|
cookie.parse - top sites |
||||||
|
|
||||||
|
14 tests completed. |
||||||
|
|
||||||
|
parse accounts.google.com x 2,588,913 ops/sec ±0.74% (186 runs sampled) |
||||||
|
parse apple.com x 2,370,002 ops/sec ±0.69% (186 runs sampled) |
||||||
|
parse cloudflare.com x 2,213,102 ops/sec ±0.88% (188 runs sampled) |
||||||
|
parse docs.google.com x 2,194,157 ops/sec ±1.03% (184 runs sampled) |
||||||
|
parse drive.google.com x 2,265,084 ops/sec ±0.79% (187 runs sampled) |
||||||
|
parse en.wikipedia.org x 457,099 ops/sec ±0.81% (186 runs sampled) |
||||||
|
parse linkedin.com x 504,407 ops/sec ±0.89% (186 runs sampled) |
||||||
|
parse maps.google.com x 1,230,959 ops/sec ±0.98% (186 runs sampled) |
||||||
|
parse microsoft.com x 926,294 ops/sec ±0.88% (184 runs sampled) |
||||||
|
parse play.google.com x 2,311,338 ops/sec ±0.83% (185 runs sampled) |
||||||
|
parse support.google.com x 1,508,850 ops/sec ±0.86% (186 runs sampled) |
||||||
|
parse www.google.com x 1,022,582 ops/sec ±1.32% (182 runs sampled) |
||||||
|
parse youtu.be x 332,136 ops/sec ±1.02% (185 runs sampled) |
||||||
|
parse youtube.com x 323,833 ops/sec ±0.77% (183 runs sampled) |
||||||
|
|
||||||
|
> node benchmark/parse.js |
||||||
|
|
||||||
|
cookie.parse - generic |
||||||
|
|
||||||
|
6 tests completed. |
||||||
|
|
||||||
|
simple x 3,214,032 ops/sec ±1.61% (183 runs sampled) |
||||||
|
decode x 587,237 ops/sec ±1.16% (187 runs sampled) |
||||||
|
unquote x 2,954,618 ops/sec ±1.35% (183 runs sampled) |
||||||
|
duplicates x 857,008 ops/sec ±0.89% (187 runs sampled) |
||||||
|
10 cookies x 292,133 ops/sec ±0.89% (187 runs sampled) |
||||||
|
100 cookies x 22,610 ops/sec ±0.68% (187 runs sampled) |
||||||
|
``` |
||||||
|
|
||||||
|
## References |
||||||
|
|
||||||
|
- [RFC 6265: HTTP State Management Mechanism][rfc-6265] |
||||||
|
- [Same-site Cookies][rfc-6265bis-09-5.4.7] |
||||||
|
|
||||||
|
[rfc-cutler-httpbis-partitioned-cookies]: https://tools.ietf.org/html/draft-cutler-httpbis-partitioned-cookies/ |
||||||
|
[rfc-west-cookie-priority-00-4.1]: https://tools.ietf.org/html/draft-west-cookie-priority-00#section-4.1 |
||||||
|
[rfc-6265bis-09-5.4.7]: https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-09#section-5.4.7 |
||||||
|
[rfc-6265]: https://tools.ietf.org/html/rfc6265 |
||||||
|
[rfc-6265-5.1.4]: https://tools.ietf.org/html/rfc6265#section-5.1.4 |
||||||
|
[rfc-6265-5.2.1]: https://tools.ietf.org/html/rfc6265#section-5.2.1 |
||||||
|
[rfc-6265-5.2.2]: https://tools.ietf.org/html/rfc6265#section-5.2.2 |
||||||
|
[rfc-6265-5.2.3]: https://tools.ietf.org/html/rfc6265#section-5.2.3 |
||||||
|
[rfc-6265-5.2.4]: https://tools.ietf.org/html/rfc6265#section-5.2.4 |
||||||
|
[rfc-6265-5.2.5]: https://tools.ietf.org/html/rfc6265#section-5.2.5 |
||||||
|
[rfc-6265-5.2.6]: https://tools.ietf.org/html/rfc6265#section-5.2.6 |
||||||
|
[rfc-6265-5.3]: https://tools.ietf.org/html/rfc6265#section-5.3 |
||||||
|
|
||||||
|
## License |
||||||
|
|
||||||
|
[MIT](LICENSE) |
||||||
|
|
||||||
|
[ci-image]: https://badgen.net/github/checks/jshttp/cookie/master?label=ci |
||||||
|
[ci-url]: https://github.com/jshttp/cookie/actions/workflows/ci.yml |
||||||
|
[coveralls-image]: https://badgen.net/coveralls/c/github/jshttp/cookie/master |
||||||
|
[coveralls-url]: https://coveralls.io/r/jshttp/cookie?branch=master |
||||||
|
[node-image]: https://badgen.net/npm/node/cookie |
||||||
|
[node-url]: https://nodejs.org/en/download |
||||||
|
[npm-downloads-image]: https://badgen.net/npm/dm/cookie |
||||||
|
[npm-url]: https://npmjs.org/package/cookie |
||||||
|
[npm-version-image]: https://badgen.net/npm/v/cookie |
@ -0,0 +1,25 @@ |
|||||||
|
# Security Policies and Procedures |
||||||
|
|
||||||
|
## Reporting a Bug |
||||||
|
|
||||||
|
The `cookie` team and community take all security bugs seriously. Thank |
||||||
|
you for improving the security of the project. We appreciate your efforts and |
||||||
|
responsible disclosure and will make every effort to acknowledge your |
||||||
|
contributions. |
||||||
|
|
||||||
|
Report security bugs by emailing the current owner(s) of `cookie`. This |
||||||
|
information can be found in the npm registry using the command |
||||||
|
`npm owner ls cookie`. |
||||||
|
If unsure or unable to get the information from the above, open an issue |
||||||
|
in the [project issue tracker](https://github.com/jshttp/cookie/issues) |
||||||
|
asking for the current contact information. |
||||||
|
|
||||||
|
To ensure the timely response to your report, please ensure that the entirety |
||||||
|
of the report is contained within the email body and not solely behind a web |
||||||
|
link or an attachment. |
||||||
|
|
||||||
|
At least one owner will acknowledge your email within 48 hours, and will send a |
||||||
|
more detailed response within 48 hours indicating the next steps in handling |
||||||
|
your report. After the initial reply to your report, the owners will |
||||||
|
endeavor to keep you informed of the progress towards a fix and full |
||||||
|
announcement, and may ask for additional information or guidance. |
@ -0,0 +1,274 @@ |
|||||||
|
/*! |
||||||
|
* cookie |
||||||
|
* Copyright(c) 2012-2014 Roman Shtylman |
||||||
|
* Copyright(c) 2015 Douglas Christopher Wilson |
||||||
|
* MIT Licensed |
||||||
|
*/ |
||||||
|
|
||||||
|
'use strict'; |
||||||
|
|
||||||
|
/** |
||||||
|
* Module exports. |
||||||
|
* @public |
||||||
|
*/ |
||||||
|
|
||||||
|
exports.parse = parse; |
||||||
|
exports.serialize = serialize; |
||||||
|
|
||||||
|
/** |
||||||
|
* Module variables. |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
var __toString = Object.prototype.toString |
||||||
|
|
||||||
|
/** |
||||||
|
* RegExp to match field-content in RFC 7230 sec 3.2 |
||||||
|
* |
||||||
|
* field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ] |
||||||
|
* field-vchar = VCHAR / obs-text |
||||||
|
* obs-text = %x80-FF |
||||||
|
*/ |
||||||
|
|
||||||
|
var fieldContentRegExp = /^[\u0009\u0020-\u007e\u0080-\u00ff]+$/; |
||||||
|
|
||||||
|
/** |
||||||
|
* Parse a cookie header. |
||||||
|
* |
||||||
|
* Parse the given cookie header string into an object |
||||||
|
* The object has the various cookies as keys(names) => values |
||||||
|
* |
||||||
|
* @param {string} str |
||||||
|
* @param {object} [options] |
||||||
|
* @return {object} |
||||||
|
* @public |
||||||
|
*/ |
||||||
|
|
||||||
|
function parse(str, options) { |
||||||
|
if (typeof str !== 'string') { |
||||||
|
throw new TypeError('argument str must be a string'); |
||||||
|
} |
||||||
|
|
||||||
|
var obj = {} |
||||||
|
var opt = options || {}; |
||||||
|
var dec = opt.decode || decode; |
||||||
|
|
||||||
|
var index = 0 |
||||||
|
while (index < str.length) { |
||||||
|
var eqIdx = str.indexOf('=', index) |
||||||
|
|
||||||
|
// no more cookie pairs
|
||||||
|
if (eqIdx === -1) { |
||||||
|
break |
||||||
|
} |
||||||
|
|
||||||
|
var endIdx = str.indexOf(';', index) |
||||||
|
|
||||||
|
if (endIdx === -1) { |
||||||
|
endIdx = str.length |
||||||
|
} else if (endIdx < eqIdx) { |
||||||
|
// backtrack on prior semicolon
|
||||||
|
index = str.lastIndexOf(';', eqIdx - 1) + 1 |
||||||
|
continue |
||||||
|
} |
||||||
|
|
||||||
|
var key = str.slice(index, eqIdx).trim() |
||||||
|
|
||||||
|
// only assign once
|
||||||
|
if (undefined === obj[key]) { |
||||||
|
var val = str.slice(eqIdx + 1, endIdx).trim() |
||||||
|
|
||||||
|
// quoted values
|
||||||
|
if (val.charCodeAt(0) === 0x22) { |
||||||
|
val = val.slice(1, -1) |
||||||
|
} |
||||||
|
|
||||||
|
obj[key] = tryDecode(val, dec); |
||||||
|
} |
||||||
|
|
||||||
|
index = endIdx + 1 |
||||||
|
} |
||||||
|
|
||||||
|
return obj; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Serialize data into a cookie header. |
||||||
|
* |
||||||
|
* Serialize the a name value pair into a cookie string suitable for |
||||||
|
* http headers. An optional options object specified cookie parameters. |
||||||
|
* |
||||||
|
* serialize('foo', 'bar', { httpOnly: true }) |
||||||
|
* => "foo=bar; httpOnly" |
||||||
|
* |
||||||
|
* @param {string} name |
||||||
|
* @param {string} val |
||||||
|
* @param {object} [options] |
||||||
|
* @return {string} |
||||||
|
* @public |
||||||
|
*/ |
||||||
|
|
||||||
|
function serialize(name, val, options) { |
||||||
|
var opt = options || {}; |
||||||
|
var enc = opt.encode || encode; |
||||||
|
|
||||||
|
if (typeof enc !== 'function') { |
||||||
|
throw new TypeError('option encode is invalid'); |
||||||
|
} |
||||||
|
|
||||||
|
if (!fieldContentRegExp.test(name)) { |
||||||
|
throw new TypeError('argument name is invalid'); |
||||||
|
} |
||||||
|
|
||||||
|
var value = enc(val); |
||||||
|
|
||||||
|
if (value && !fieldContentRegExp.test(value)) { |
||||||
|
throw new TypeError('argument val is invalid'); |
||||||
|
} |
||||||
|
|
||||||
|
var str = name + '=' + value; |
||||||
|
|
||||||
|
if (null != opt.maxAge) { |
||||||
|
var maxAge = opt.maxAge - 0; |
||||||
|
|
||||||
|
if (isNaN(maxAge) || !isFinite(maxAge)) { |
||||||
|
throw new TypeError('option maxAge is invalid') |
||||||
|
} |
||||||
|
|
||||||
|
str += '; Max-Age=' + Math.floor(maxAge); |
||||||
|
} |
||||||
|
|
||||||
|
if (opt.domain) { |
||||||
|
if (!fieldContentRegExp.test(opt.domain)) { |
||||||
|
throw new TypeError('option domain is invalid'); |
||||||
|
} |
||||||
|
|
||||||
|
str += '; Domain=' + opt.domain; |
||||||
|
} |
||||||
|
|
||||||
|
if (opt.path) { |
||||||
|
if (!fieldContentRegExp.test(opt.path)) { |
||||||
|
throw new TypeError('option path is invalid'); |
||||||
|
} |
||||||
|
|
||||||
|
str += '; Path=' + opt.path; |
||||||
|
} |
||||||
|
|
||||||
|
if (opt.expires) { |
||||||
|
var expires = opt.expires |
||||||
|
|
||||||
|
if (!isDate(expires) || isNaN(expires.valueOf())) { |
||||||
|
throw new TypeError('option expires is invalid'); |
||||||
|
} |
||||||
|
|
||||||
|
str += '; Expires=' + expires.toUTCString() |
||||||
|
} |
||||||
|
|
||||||
|
if (opt.httpOnly) { |
||||||
|
str += '; HttpOnly'; |
||||||
|
} |
||||||
|
|
||||||
|
if (opt.secure) { |
||||||
|
str += '; Secure'; |
||||||
|
} |
||||||
|
|
||||||
|
if (opt.partitioned) { |
||||||
|
str += '; Partitioned' |
||||||
|
} |
||||||
|
|
||||||
|
if (opt.priority) { |
||||||
|
var priority = typeof opt.priority === 'string' |
||||||
|
? opt.priority.toLowerCase() |
||||||
|
: opt.priority |
||||||
|
|
||||||
|
switch (priority) { |
||||||
|
case 'low': |
||||||
|
str += '; Priority=Low' |
||||||
|
break |
||||||
|
case 'medium': |
||||||
|
str += '; Priority=Medium' |
||||||
|
break |
||||||
|
case 'high': |
||||||
|
str += '; Priority=High' |
||||||
|
break |
||||||
|
default: |
||||||
|
throw new TypeError('option priority is invalid') |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (opt.sameSite) { |
||||||
|
var sameSite = typeof opt.sameSite === 'string' |
||||||
|
? opt.sameSite.toLowerCase() : opt.sameSite; |
||||||
|
|
||||||
|
switch (sameSite) { |
||||||
|
case true: |
||||||
|
str += '; SameSite=Strict'; |
||||||
|
break; |
||||||
|
case 'lax': |
||||||
|
str += '; SameSite=Lax'; |
||||||
|
break; |
||||||
|
case 'strict': |
||||||
|
str += '; SameSite=Strict'; |
||||||
|
break; |
||||||
|
case 'none': |
||||||
|
str += '; SameSite=None'; |
||||||
|
break; |
||||||
|
default: |
||||||
|
throw new TypeError('option sameSite is invalid'); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return str; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* URL-decode string value. Optimized to skip native call when no %. |
||||||
|
* |
||||||
|
* @param {string} str |
||||||
|
* @returns {string} |
||||||
|
*/ |
||||||
|
|
||||||
|
function decode (str) { |
||||||
|
return str.indexOf('%') !== -1 |
||||||
|
? decodeURIComponent(str) |
||||||
|
: str |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* URL-encode value. |
||||||
|
* |
||||||
|
* @param {string} val |
||||||
|
* @returns {string} |
||||||
|
*/ |
||||||
|
|
||||||
|
function encode (val) { |
||||||
|
return encodeURIComponent(val) |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Determine if value is a Date. |
||||||
|
* |
||||||
|
* @param {*} val |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
function isDate (val) { |
||||||
|
return __toString.call(val) === '[object Date]' || |
||||||
|
val instanceof Date |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Try decoding a string using a decoding function. |
||||||
|
* |
||||||
|
* @param {string} str |
||||||
|
* @param {function} decode |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
function tryDecode(str, decode) { |
||||||
|
try { |
||||||
|
return decode(str); |
||||||
|
} catch (e) { |
||||||
|
return str; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,44 @@ |
|||||||
|
{ |
||||||
|
"name": "cookie", |
||||||
|
"description": "HTTP server cookie parsing and serialization", |
||||||
|
"version": "0.6.0", |
||||||
|
"author": "Roman Shtylman <shtylman@gmail.com>", |
||||||
|
"contributors": [ |
||||||
|
"Douglas Christopher Wilson <doug@somethingdoug.com>" |
||||||
|
], |
||||||
|
"license": "MIT", |
||||||
|
"keywords": [ |
||||||
|
"cookie", |
||||||
|
"cookies" |
||||||
|
], |
||||||
|
"repository": "jshttp/cookie", |
||||||
|
"devDependencies": { |
||||||
|
"beautify-benchmark": "0.2.4", |
||||||
|
"benchmark": "2.1.4", |
||||||
|
"eslint": "8.53.0", |
||||||
|
"eslint-plugin-markdown": "3.0.1", |
||||||
|
"mocha": "10.2.0", |
||||||
|
"nyc": "15.1.0", |
||||||
|
"safe-buffer": "5.2.1", |
||||||
|
"top-sites": "1.1.194" |
||||||
|
}, |
||||||
|
"files": [ |
||||||
|
"HISTORY.md", |
||||||
|
"LICENSE", |
||||||
|
"README.md", |
||||||
|
"SECURITY.md", |
||||||
|
"index.js" |
||||||
|
], |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.6" |
||||||
|
}, |
||||||
|
"scripts": { |
||||||
|
"bench": "node benchmark/index.js", |
||||||
|
"lint": "eslint .", |
||||||
|
"test": "mocha --reporter spec --bail --check-leaks test/", |
||||||
|
"test-ci": "nyc --reporter=lcov --reporter=text npm test", |
||||||
|
"test-cov": "nyc --reporter=html --reporter=text npm test", |
||||||
|
"update-bench": "node scripts/update-benchmark.js", |
||||||
|
"version": "node scripts/version-history.js && git add HISTORY.md" |
||||||
|
} |
||||||
|
} |
@ -0,0 +1 @@ |
|||||||
|
repo_token: SIAeZjKYlHK74rbcFvNHMUzjRiMpflxve |
@ -0,0 +1,11 @@ |
|||||||
|
{ |
||||||
|
"env": { |
||||||
|
"browser": true, |
||||||
|
"node": true |
||||||
|
}, |
||||||
|
"rules": { |
||||||
|
"no-console": 0, |
||||||
|
"no-empty": [1, { "allowEmptyCatch": true }] |
||||||
|
}, |
||||||
|
"extends": "eslint:recommended" |
||||||
|
} |
@ -0,0 +1,9 @@ |
|||||||
|
support |
||||||
|
test |
||||||
|
examples |
||||||
|
example |
||||||
|
*.sock |
||||||
|
dist |
||||||
|
yarn.lock |
||||||
|
coverage |
||||||
|
bower.json |
@ -0,0 +1,14 @@ |
|||||||
|
|
||||||
|
language: node_js |
||||||
|
node_js: |
||||||
|
- "6" |
||||||
|
- "5" |
||||||
|
- "4" |
||||||
|
|
||||||
|
install: |
||||||
|
- make node_modules |
||||||
|
|
||||||
|
script: |
||||||
|
- make lint |
||||||
|
- make test |
||||||
|
- make coveralls |
@ -0,0 +1,362 @@ |
|||||||
|
|
||||||
|
2.6.9 / 2017-09-22 |
||||||
|
================== |
||||||
|
|
||||||
|
* remove ReDoS regexp in %o formatter (#504) |
||||||
|
|
||||||
|
2.6.8 / 2017-05-18 |
||||||
|
================== |
||||||
|
|
||||||
|
* Fix: Check for undefined on browser globals (#462, @marbemac) |
||||||
|
|
||||||
|
2.6.7 / 2017-05-16 |
||||||
|
================== |
||||||
|
|
||||||
|
* Fix: Update ms to 2.0.0 to fix regular expression denial of service vulnerability (#458, @hubdotcom) |
||||||
|
* Fix: Inline extend function in node implementation (#452, @dougwilson) |
||||||
|
* Docs: Fix typo (#455, @msasad) |
||||||
|
|
||||||
|
2.6.5 / 2017-04-27 |
||||||
|
================== |
||||||
|
|
||||||
|
* Fix: null reference check on window.documentElement.style.WebkitAppearance (#447, @thebigredgeek) |
||||||
|
* Misc: clean up browser reference checks (#447, @thebigredgeek) |
||||||
|
* Misc: add npm-debug.log to .gitignore (@thebigredgeek) |
||||||
|
|
||||||
|
|
||||||
|
2.6.4 / 2017-04-20 |
||||||
|
================== |
||||||
|
|
||||||
|
* Fix: bug that would occure if process.env.DEBUG is a non-string value. (#444, @LucianBuzzo) |
||||||
|
* Chore: ignore bower.json in npm installations. (#437, @joaovieira) |
||||||
|
* Misc: update "ms" to v0.7.3 (@tootallnate) |
||||||
|
|
||||||
|
2.6.3 / 2017-03-13 |
||||||
|
================== |
||||||
|
|
||||||
|
* Fix: Electron reference to `process.env.DEBUG` (#431, @paulcbetts) |
||||||
|
* Docs: Changelog fix (@thebigredgeek) |
||||||
|
|
||||||
|
2.6.2 / 2017-03-10 |
||||||
|
================== |
||||||
|
|
||||||
|
* Fix: DEBUG_MAX_ARRAY_LENGTH (#420, @slavaGanzin) |
||||||
|
* Docs: Add backers and sponsors from Open Collective (#422, @piamancini) |
||||||
|
* Docs: Add Slackin invite badge (@tootallnate) |
||||||
|
|
||||||
|
2.6.1 / 2017-02-10 |
||||||
|
================== |
||||||
|
|
||||||
|
* Fix: Module's `export default` syntax fix for IE8 `Expected identifier` error |
||||||
|
* Fix: Whitelist DEBUG_FD for values 1 and 2 only (#415, @pi0) |
||||||
|
* Fix: IE8 "Expected identifier" error (#414, @vgoma) |
||||||
|
* Fix: Namespaces would not disable once enabled (#409, @musikov) |
||||||
|
|
||||||
|
2.6.0 / 2016-12-28 |
||||||
|
================== |
||||||
|
|
||||||
|
* Fix: added better null pointer checks for browser useColors (@thebigredgeek) |
||||||
|
* Improvement: removed explicit `window.debug` export (#404, @tootallnate) |
||||||
|
* Improvement: deprecated `DEBUG_FD` environment variable (#405, @tootallnate) |
||||||
|
|
||||||
|
2.5.2 / 2016-12-25 |
||||||
|
================== |
||||||
|
|
||||||
|
* Fix: reference error on window within webworkers (#393, @KlausTrainer) |
||||||
|
* Docs: fixed README typo (#391, @lurch) |
||||||
|
* Docs: added notice about v3 api discussion (@thebigredgeek) |
||||||
|
|
||||||
|
2.5.1 / 2016-12-20 |
||||||
|
================== |
||||||
|
|
||||||
|
* Fix: babel-core compatibility |
||||||
|
|
||||||
|
2.5.0 / 2016-12-20 |
||||||
|
================== |
||||||
|
|
||||||
|
* Fix: wrong reference in bower file (@thebigredgeek) |
||||||
|
* Fix: webworker compatibility (@thebigredgeek) |
||||||
|
* Fix: output formatting issue (#388, @kribblo) |
||||||
|
* Fix: babel-loader compatibility (#383, @escwald) |
||||||
|
* Misc: removed built asset from repo and publications (@thebigredgeek) |
||||||
|
* Misc: moved source files to /src (#378, @yamikuronue) |
||||||
|
* Test: added karma integration and replaced babel with browserify for browser tests (#378, @yamikuronue) |
||||||
|
* Test: coveralls integration (#378, @yamikuronue) |
||||||
|
* Docs: simplified language in the opening paragraph (#373, @yamikuronue) |
||||||
|
|
||||||
|
2.4.5 / 2016-12-17 |
||||||
|
================== |
||||||
|
|
||||||
|
* Fix: `navigator` undefined in Rhino (#376, @jochenberger) |
||||||
|
* Fix: custom log function (#379, @hsiliev) |
||||||
|
* Improvement: bit of cleanup + linting fixes (@thebigredgeek) |
||||||
|
* Improvement: rm non-maintainted `dist/` dir (#375, @freewil) |
||||||
|
* Docs: simplified language in the opening paragraph. (#373, @yamikuronue) |
||||||
|
|
||||||
|
2.4.4 / 2016-12-14 |
||||||
|
================== |
||||||
|
|
||||||
|
* Fix: work around debug being loaded in preload scripts for electron (#368, @paulcbetts) |
||||||
|
|
||||||
|
2.4.3 / 2016-12-14 |
||||||
|
================== |
||||||
|
|
||||||
|
* Fix: navigation.userAgent error for react native (#364, @escwald) |
||||||
|
|
||||||
|
2.4.2 / 2016-12-14 |
||||||
|
================== |
||||||
|
|
||||||
|
* Fix: browser colors (#367, @tootallnate) |
||||||
|
* Misc: travis ci integration (@thebigredgeek) |
||||||
|
* Misc: added linting and testing boilerplate with sanity check (@thebigredgeek) |
||||||
|
|
||||||
|
2.4.1 / 2016-12-13 |
||||||
|
================== |
||||||
|
|
||||||
|
* Fix: typo that broke the package (#356) |
||||||
|
|
||||||
|
2.4.0 / 2016-12-13 |
||||||
|
================== |
||||||
|
|
||||||
|
* Fix: bower.json references unbuilt src entry point (#342, @justmatt) |
||||||
|
* Fix: revert "handle regex special characters" (@tootallnate) |
||||||
|
* Feature: configurable util.inspect()`options for NodeJS (#327, @tootallnate) |
||||||
|
* Feature: %O`(big O) pretty-prints objects (#322, @tootallnate) |
||||||
|
* Improvement: allow colors in workers (#335, @botverse) |
||||||
|
* Improvement: use same color for same namespace. (#338, @lchenay) |
||||||
|
|
||||||
|
2.3.3 / 2016-11-09 |
||||||
|
================== |
||||||
|
|
||||||
|
* Fix: Catch `JSON.stringify()` errors (#195, Jovan Alleyne) |
||||||
|
* Fix: Returning `localStorage` saved values (#331, Levi Thomason) |
||||||
|
* Improvement: Don't create an empty object when no `process` (Nathan Rajlich) |
||||||
|
|
||||||
|
2.3.2 / 2016-11-09 |
||||||
|
================== |
||||||
|
|
||||||
|
* Fix: be super-safe in index.js as well (@TooTallNate) |
||||||
|
* Fix: should check whether process exists (Tom Newby) |
||||||
|
|
||||||
|
2.3.1 / 2016-11-09 |
||||||
|
================== |
||||||
|
|
||||||
|
* Fix: Added electron compatibility (#324, @paulcbetts) |
||||||
|
* Improvement: Added performance optimizations (@tootallnate) |
||||||
|
* Readme: Corrected PowerShell environment variable example (#252, @gimre) |
||||||
|
* Misc: Removed yarn lock file from source control (#321, @fengmk2) |
||||||
|
|
||||||
|
2.3.0 / 2016-11-07 |
||||||
|
================== |
||||||
|
|
||||||
|
* Fix: Consistent placement of ms diff at end of output (#215, @gorangajic) |
||||||
|
* Fix: Escaping of regex special characters in namespace strings (#250, @zacronos) |
||||||
|
* Fix: Fixed bug causing crash on react-native (#282, @vkarpov15) |
||||||
|
* Feature: Enabled ES6+ compatible import via default export (#212 @bucaran) |
||||||
|
* Feature: Added %O formatter to reflect Chrome's console.log capability (#279, @oncletom) |
||||||
|
* Package: Update "ms" to 0.7.2 (#315, @DevSide) |
||||||
|
* Package: removed superfluous version property from bower.json (#207 @kkirsche) |
||||||
|
* Readme: fix USE_COLORS to DEBUG_COLORS |
||||||
|
* Readme: Doc fixes for format string sugar (#269, @mlucool) |
||||||
|
* Readme: Updated docs for DEBUG_FD and DEBUG_COLORS environment variables (#232, @mattlyons0) |
||||||
|
* Readme: doc fixes for PowerShell (#271 #243, @exoticknight @unreadable) |
||||||
|
* Readme: better docs for browser support (#224, @matthewmueller) |
||||||
|
* Tooling: Added yarn integration for development (#317, @thebigredgeek) |
||||||
|
* Misc: Renamed History.md to CHANGELOG.md (@thebigredgeek) |
||||||
|
* Misc: Added license file (#226 #274, @CantemoInternal @sdaitzman) |
||||||
|
* Misc: Updated contributors (@thebigredgeek) |
||||||
|
|
||||||
|
2.2.0 / 2015-05-09 |
||||||
|
================== |
||||||
|
|
||||||
|
* package: update "ms" to v0.7.1 (#202, @dougwilson) |
||||||
|
* README: add logging to file example (#193, @DanielOchoa) |
||||||
|
* README: fixed a typo (#191, @amir-s) |
||||||
|
* browser: expose `storage` (#190, @stephenmathieson) |
||||||
|
* Makefile: add a `distclean` target (#189, @stephenmathieson) |
||||||
|
|
||||||
|
2.1.3 / 2015-03-13 |
||||||
|
================== |
||||||
|
|
||||||
|
* Updated stdout/stderr example (#186) |
||||||
|
* Updated example/stdout.js to match debug current behaviour |
||||||
|
* Renamed example/stderr.js to stdout.js |
||||||
|
* Update Readme.md (#184) |
||||||
|
* replace high intensity foreground color for bold (#182, #183) |
||||||
|
|
||||||
|
2.1.2 / 2015-03-01 |
||||||
|
================== |
||||||
|
|
||||||
|
* dist: recompile |
||||||
|
* update "ms" to v0.7.0 |
||||||
|
* package: update "browserify" to v9.0.3 |
||||||
|
* component: fix "ms.js" repo location |
||||||
|
* changed bower package name |
||||||
|
* updated documentation about using debug in a browser |
||||||
|
* fix: security error on safari (#167, #168, @yields) |
||||||
|
|
||||||
|
2.1.1 / 2014-12-29 |
||||||
|
================== |
||||||
|
|
||||||
|
* browser: use `typeof` to check for `console` existence |
||||||
|
* browser: check for `console.log` truthiness (fix IE 8/9) |
||||||
|
* browser: add support for Chrome apps |
||||||
|
* Readme: added Windows usage remarks |
||||||
|
* Add `bower.json` to properly support bower install |
||||||
|
|
||||||
|
2.1.0 / 2014-10-15 |
||||||
|
================== |
||||||
|
|
||||||
|
* node: implement `DEBUG_FD` env variable support |
||||||
|
* package: update "browserify" to v6.1.0 |
||||||
|
* package: add "license" field to package.json (#135, @panuhorsmalahti) |
||||||
|
|
||||||
|
2.0.0 / 2014-09-01 |
||||||
|
================== |
||||||
|
|
||||||
|
* package: update "browserify" to v5.11.0 |
||||||
|
* node: use stderr rather than stdout for logging (#29, @stephenmathieson) |
||||||
|
|
||||||
|
1.0.4 / 2014-07-15 |
||||||
|
================== |
||||||
|
|
||||||
|
* dist: recompile |
||||||
|
* example: remove `console.info()` log usage |
||||||
|
* example: add "Content-Type" UTF-8 header to browser example |
||||||
|
* browser: place %c marker after the space character |
||||||
|
* browser: reset the "content" color via `color: inherit` |
||||||
|
* browser: add colors support for Firefox >= v31 |
||||||
|
* debug: prefer an instance `log()` function over the global one (#119) |
||||||
|
* Readme: update documentation about styled console logs for FF v31 (#116, @wryk) |
||||||
|
|
||||||
|
1.0.3 / 2014-07-09 |
||||||
|
================== |
||||||
|
|
||||||
|
* Add support for multiple wildcards in namespaces (#122, @seegno) |
||||||
|
* browser: fix lint |
||||||
|
|
||||||
|
1.0.2 / 2014-06-10 |
||||||
|
================== |
||||||
|
|
||||||
|
* browser: update color palette (#113, @gscottolson) |
||||||
|
* common: make console logging function configurable (#108, @timoxley) |
||||||
|
* node: fix %o colors on old node <= 0.8.x |
||||||
|
* Makefile: find node path using shell/which (#109, @timoxley) |
||||||
|
|
||||||
|
1.0.1 / 2014-06-06 |
||||||
|
================== |
||||||
|
|
||||||
|
* browser: use `removeItem()` to clear localStorage |
||||||
|
* browser, node: don't set DEBUG if namespaces is undefined (#107, @leedm777) |
||||||
|
* package: add "contributors" section |
||||||
|
* node: fix comment typo |
||||||
|
* README: list authors |
||||||
|
|
||||||
|
1.0.0 / 2014-06-04 |
||||||
|
================== |
||||||
|
|
||||||
|
* make ms diff be global, not be scope |
||||||
|
* debug: ignore empty strings in enable() |
||||||
|
* node: make DEBUG_COLORS able to disable coloring |
||||||
|
* *: export the `colors` array |
||||||
|
* npmignore: don't publish the `dist` dir |
||||||
|
* Makefile: refactor to use browserify |
||||||
|
* package: add "browserify" as a dev dependency |
||||||
|
* Readme: add Web Inspector Colors section |
||||||
|
* node: reset terminal color for the debug content |
||||||
|
* node: map "%o" to `util.inspect()` |
||||||
|
* browser: map "%j" to `JSON.stringify()` |
||||||
|
* debug: add custom "formatters" |
||||||
|
* debug: use "ms" module for humanizing the diff |
||||||
|
* Readme: add "bash" syntax highlighting |
||||||
|
* browser: add Firebug color support |
||||||
|
* browser: add colors for WebKit browsers |
||||||
|
* node: apply log to `console` |
||||||
|
* rewrite: abstract common logic for Node & browsers |
||||||
|
* add .jshintrc file |
||||||
|
|
||||||
|
0.8.1 / 2014-04-14 |
||||||
|
================== |
||||||
|
|
||||||
|
* package: re-add the "component" section |
||||||
|
|
||||||
|
0.8.0 / 2014-03-30 |
||||||
|
================== |
||||||
|
|
||||||
|
* add `enable()` method for nodejs. Closes #27 |
||||||
|
* change from stderr to stdout |
||||||
|
* remove unnecessary index.js file |
||||||
|
|
||||||
|
0.7.4 / 2013-11-13 |
||||||
|
================== |
||||||
|
|
||||||
|
* remove "browserify" key from package.json (fixes something in browserify) |
||||||
|
|
||||||
|
0.7.3 / 2013-10-30 |
||||||
|
================== |
||||||
|
|
||||||
|
* fix: catch localStorage security error when cookies are blocked (Chrome) |
||||||
|
* add debug(err) support. Closes #46 |
||||||
|
* add .browser prop to package.json. Closes #42 |
||||||
|
|
||||||
|
0.7.2 / 2013-02-06 |
||||||
|
================== |
||||||
|
|
||||||
|
* fix package.json |
||||||
|
* fix: Mobile Safari (private mode) is broken with debug |
||||||
|
* fix: Use unicode to send escape character to shell instead of octal to work with strict mode javascript |
||||||
|
|
||||||
|
0.7.1 / 2013-02-05 |
||||||
|
================== |
||||||
|
|
||||||
|
* add repository URL to package.json |
||||||
|
* add DEBUG_COLORED to force colored output |
||||||
|
* add browserify support |
||||||
|
* fix component. Closes #24 |
||||||
|
|
||||||
|
0.7.0 / 2012-05-04 |
||||||
|
================== |
||||||
|
|
||||||
|
* Added .component to package.json |
||||||
|
* Added debug.component.js build |
||||||
|
|
||||||
|
0.6.0 / 2012-03-16 |
||||||
|
================== |
||||||
|
|
||||||
|
* Added support for "-" prefix in DEBUG [Vinay Pulim] |
||||||
|
* Added `.enabled` flag to the node version [TooTallNate] |
||||||
|
|
||||||
|
0.5.0 / 2012-02-02 |
||||||
|
================== |
||||||
|
|
||||||
|
* Added: humanize diffs. Closes #8 |
||||||
|
* Added `debug.disable()` to the CS variant |
||||||
|
* Removed padding. Closes #10 |
||||||
|
* Fixed: persist client-side variant again. Closes #9 |
||||||
|
|
||||||
|
0.4.0 / 2012-02-01 |
||||||
|
================== |
||||||
|
|
||||||
|
* Added browser variant support for older browsers [TooTallNate] |
||||||
|
* Added `debug.enable('project:*')` to browser variant [TooTallNate] |
||||||
|
* Added padding to diff (moved it to the right) |
||||||
|
|
||||||
|
0.3.0 / 2012-01-26 |
||||||
|
================== |
||||||
|
|
||||||
|
* Added millisecond diff when isatty, otherwise UTC string |
||||||
|
|
||||||
|
0.2.0 / 2012-01-22 |
||||||
|
================== |
||||||
|
|
||||||
|
* Added wildcard support |
||||||
|
|
||||||
|
0.1.0 / 2011-12-02 |
||||||
|
================== |
||||||
|
|
||||||
|
* Added: remove colors unless stderr isatty [TooTallNate] |
||||||
|
|
||||||
|
0.0.1 / 2010-01-03 |
||||||
|
================== |
||||||
|
|
||||||
|
* Initial release |
@ -0,0 +1,19 @@ |
|||||||
|
(The MIT License) |
||||||
|
|
||||||
|
Copyright (c) 2014 TJ Holowaychuk <tj@vision-media.ca> |
||||||
|
|
||||||
|
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. |
||||||
|
|
@ -0,0 +1,50 @@ |
|||||||
|
# get Makefile directory name: http://stackoverflow.com/a/5982798/376773
|
||||||
|
THIS_MAKEFILE_PATH:=$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
|
||||||
|
THIS_DIR:=$(shell cd $(dir $(THIS_MAKEFILE_PATH));pwd)
|
||||||
|
|
||||||
|
# BIN directory
|
||||||
|
BIN := $(THIS_DIR)/node_modules/.bin
|
||||||
|
|
||||||
|
# Path
|
||||||
|
PATH := node_modules/.bin:$(PATH)
|
||||||
|
SHELL := /bin/bash
|
||||||
|
|
||||||
|
# applications
|
||||||
|
NODE ?= $(shell which node)
|
||||||
|
YARN ?= $(shell which yarn)
|
||||||
|
PKG ?= $(if $(YARN),$(YARN),$(NODE) $(shell which npm))
|
||||||
|
BROWSERIFY ?= $(NODE) $(BIN)/browserify
|
||||||
|
|
||||||
|
.FORCE: |
||||||
|
|
||||||
|
install: node_modules |
||||||
|
|
||||||
|
node_modules: package.json |
||||||
|
@NODE_ENV= $(PKG) install
|
||||||
|
@touch node_modules
|
||||||
|
|
||||||
|
lint: .FORCE |
||||||
|
eslint browser.js debug.js index.js node.js
|
||||||
|
|
||||||
|
test-node: .FORCE |
||||||
|
istanbul cover node_modules/mocha/bin/_mocha -- test/**.js
|
||||||
|
|
||||||
|
test-browser: .FORCE |
||||||
|
mkdir -p dist
|
||||||
|
|
||||||
|
@$(BROWSERIFY) \
|
||||||
|
--standalone debug \
|
||||||
|
. > dist/debug.js
|
||||||
|
|
||||||
|
karma start --single-run
|
||||||
|
rimraf dist
|
||||||
|
|
||||||
|
test: .FORCE |
||||||
|
concurrently \
|
||||||
|
"make test-node" \
|
||||||
|
"make test-browser"
|
||||||
|
|
||||||
|
coveralls: |
||||||
|
cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js
|
||||||
|
|
||||||
|
.PHONY: all install clean distclean |
@ -0,0 +1,312 @@ |
|||||||
|
# debug |
||||||
|
[![Build Status](https://travis-ci.org/visionmedia/debug.svg?branch=master)](https://travis-ci.org/visionmedia/debug) [![Coverage Status](https://coveralls.io/repos/github/visionmedia/debug/badge.svg?branch=master)](https://coveralls.io/github/visionmedia/debug?branch=master) [![Slack](https://visionmedia-community-slackin.now.sh/badge.svg)](https://visionmedia-community-slackin.now.sh/) [![OpenCollective](https://opencollective.com/debug/backers/badge.svg)](#backers) |
||||||
|
[![OpenCollective](https://opencollective.com/debug/sponsors/badge.svg)](#sponsors) |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
A tiny node.js debugging utility modelled after node core's debugging technique. |
||||||
|
|
||||||
|
**Discussion around the V3 API is under way [here](https://github.com/visionmedia/debug/issues/370)** |
||||||
|
|
||||||
|
## Installation |
||||||
|
|
||||||
|
```bash |
||||||
|
$ npm install debug |
||||||
|
``` |
||||||
|
|
||||||
|
## Usage |
||||||
|
|
||||||
|
`debug` exposes a function; simply pass this function the name of your module, and it will return a decorated version of `console.error` for you to pass debug statements to. This will allow you to toggle the debug output for different parts of your module as well as the module as a whole. |
||||||
|
|
||||||
|
Example _app.js_: |
||||||
|
|
||||||
|
```js |
||||||
|
var debug = require('debug')('http') |
||||||
|
, http = require('http') |
||||||
|
, name = 'My App'; |
||||||
|
|
||||||
|
// fake app |
||||||
|
|
||||||
|
debug('booting %s', name); |
||||||
|
|
||||||
|
http.createServer(function(req, res){ |
||||||
|
debug(req.method + ' ' + req.url); |
||||||
|
res.end('hello\n'); |
||||||
|
}).listen(3000, function(){ |
||||||
|
debug('listening'); |
||||||
|
}); |
||||||
|
|
||||||
|
// fake worker of some kind |
||||||
|
|
||||||
|
require('./worker'); |
||||||
|
``` |
||||||
|
|
||||||
|
Example _worker.js_: |
||||||
|
|
||||||
|
```js |
||||||
|
var debug = require('debug')('worker'); |
||||||
|
|
||||||
|
setInterval(function(){ |
||||||
|
debug('doing some work'); |
||||||
|
}, 1000); |
||||||
|
``` |
||||||
|
|
||||||
|
The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples: |
||||||
|
|
||||||
|
![debug http and worker](http://f.cl.ly/items/18471z1H402O24072r1J/Screenshot.png) |
||||||
|
|
||||||
|
![debug worker](http://f.cl.ly/items/1X413v1a3M0d3C2c1E0i/Screenshot.png) |
||||||
|
|
||||||
|
#### Windows note |
||||||
|
|
||||||
|
On Windows the environment variable is set using the `set` command. |
||||||
|
|
||||||
|
```cmd |
||||||
|
set DEBUG=*,-not_this |
||||||
|
``` |
||||||
|
|
||||||
|
Note that PowerShell uses different syntax to set environment variables. |
||||||
|
|
||||||
|
```cmd |
||||||
|
$env:DEBUG = "*,-not_this" |
||||||
|
``` |
||||||
|
|
||||||
|
Then, run the program to be debugged as usual. |
||||||
|
|
||||||
|
## Millisecond diff |
||||||
|
|
||||||
|
When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls. |
||||||
|
|
||||||
|
![](http://f.cl.ly/items/2i3h1d3t121M2Z1A3Q0N/Screenshot.png) |
||||||
|
|
||||||
|
When stdout is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below: |
||||||
|
|
||||||
|
![](http://f.cl.ly/items/112H3i0e0o0P0a2Q2r11/Screenshot.png) |
||||||
|
|
||||||
|
## Conventions |
||||||
|
|
||||||
|
If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser". |
||||||
|
|
||||||
|
## Wildcards |
||||||
|
|
||||||
|
The `*` character may be used as a wildcard. Suppose for example your library has debuggers named "connect:bodyParser", "connect:compress", "connect:session", instead of listing all three with `DEBUG=connect:bodyParser,connect:compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`. |
||||||
|
|
||||||
|
You can also exclude specific debuggers by prefixing them with a "-" character. For example, `DEBUG=*,-connect:*` would include all debuggers except those starting with "connect:". |
||||||
|
|
||||||
|
## Environment Variables |
||||||
|
|
||||||
|
When running through Node.js, you can set a few environment variables that will |
||||||
|
change the behavior of the debug logging: |
||||||
|
|
||||||
|
| Name | Purpose | |
||||||
|
|-----------|-------------------------------------------------| |
||||||
|
| `DEBUG` | Enables/disables specific debugging namespaces. | |
||||||
|
| `DEBUG_COLORS`| Whether or not to use colors in the debug output. | |
||||||
|
| `DEBUG_DEPTH` | Object inspection depth. | |
||||||
|
| `DEBUG_SHOW_HIDDEN` | Shows hidden properties on inspected objects. | |
||||||
|
|
||||||
|
|
||||||
|
__Note:__ The environment variables beginning with `DEBUG_` end up being |
||||||
|
converted into an Options object that gets used with `%o`/`%O` formatters. |
||||||
|
See the Node.js documentation for |
||||||
|
[`util.inspect()`](https://nodejs.org/api/util.html#util_util_inspect_object_options) |
||||||
|
for the complete list. |
||||||
|
|
||||||
|
## Formatters |
||||||
|
|
||||||
|
|
||||||
|
Debug uses [printf-style](https://wikipedia.org/wiki/Printf_format_string) formatting. Below are the officially supported formatters: |
||||||
|
|
||||||
|
| Formatter | Representation | |
||||||
|
|-----------|----------------| |
||||||
|
| `%O` | Pretty-print an Object on multiple lines. | |
||||||
|
| `%o` | Pretty-print an Object all on a single line. | |
||||||
|
| `%s` | String. | |
||||||
|
| `%d` | Number (both integer and float). | |
||||||
|
| `%j` | JSON. Replaced with the string '[Circular]' if the argument contains circular references. | |
||||||
|
| `%%` | Single percent sign ('%'). This does not consume an argument. | |
||||||
|
|
||||||
|
### Custom formatters |
||||||
|
|
||||||
|
You can add custom formatters by extending the `debug.formatters` object. For example, if you wanted to add support for rendering a Buffer as hex with `%h`, you could do something like: |
||||||
|
|
||||||
|
```js |
||||||
|
const createDebug = require('debug') |
||||||
|
createDebug.formatters.h = (v) => { |
||||||
|
return v.toString('hex') |
||||||
|
} |
||||||
|
|
||||||
|
// …elsewhere |
||||||
|
const debug = createDebug('foo') |
||||||
|
debug('this is hex: %h', new Buffer('hello world')) |
||||||
|
// foo this is hex: 68656c6c6f20776f726c6421 +0ms |
||||||
|
``` |
||||||
|
|
||||||
|
## Browser support |
||||||
|
You can build a browser-ready script using [browserify](https://github.com/substack/node-browserify), |
||||||
|
or just use the [browserify-as-a-service](https://wzrd.in/) [build](https://wzrd.in/standalone/debug@latest), |
||||||
|
if you don't want to build it yourself. |
||||||
|
|
||||||
|
Debug's enable state is currently persisted by `localStorage`. |
||||||
|
Consider the situation shown below where you have `worker:a` and `worker:b`, |
||||||
|
and wish to debug both. You can enable this using `localStorage.debug`: |
||||||
|
|
||||||
|
```js |
||||||
|
localStorage.debug = 'worker:*' |
||||||
|
``` |
||||||
|
|
||||||
|
And then refresh the page. |
||||||
|
|
||||||
|
```js |
||||||
|
a = debug('worker:a'); |
||||||
|
b = debug('worker:b'); |
||||||
|
|
||||||
|
setInterval(function(){ |
||||||
|
a('doing some work'); |
||||||
|
}, 1000); |
||||||
|
|
||||||
|
setInterval(function(){ |
||||||
|
b('doing some work'); |
||||||
|
}, 1200); |
||||||
|
``` |
||||||
|
|
||||||
|
#### Web Inspector Colors |
||||||
|
|
||||||
|
Colors are also enabled on "Web Inspectors" that understand the `%c` formatting |
||||||
|
option. These are WebKit web inspectors, Firefox ([since version |
||||||
|
31](https://hacks.mozilla.org/2014/05/editable-box-model-multiple-selection-sublime-text-keys-much-more-firefox-developer-tools-episode-31/)) |
||||||
|
and the Firebug plugin for Firefox (any version). |
||||||
|
|
||||||
|
Colored output looks something like: |
||||||
|
|
||||||
|
![](https://cloud.githubusercontent.com/assets/71256/3139768/b98c5fd8-e8ef-11e3-862a-f7253b6f47c6.png) |
||||||
|
|
||||||
|
|
||||||
|
## Output streams |
||||||
|
|
||||||
|
By default `debug` will log to stderr, however this can be configured per-namespace by overriding the `log` method: |
||||||
|
|
||||||
|
Example _stdout.js_: |
||||||
|
|
||||||
|
```js |
||||||
|
var debug = require('debug'); |
||||||
|
var error = debug('app:error'); |
||||||
|
|
||||||
|
// by default stderr is used |
||||||
|
error('goes to stderr!'); |
||||||
|
|
||||||
|
var log = debug('app:log'); |
||||||
|
// set this namespace to log via console.log |
||||||
|
log.log = console.log.bind(console); // don't forget to bind to console! |
||||||
|
log('goes to stdout'); |
||||||
|
error('still goes to stderr!'); |
||||||
|
|
||||||
|
// set all output to go via console.info |
||||||
|
// overrides all per-namespace log settings |
||||||
|
debug.log = console.info.bind(console); |
||||||
|
error('now goes to stdout via console.info'); |
||||||
|
log('still goes to stdout, but via console.info now'); |
||||||
|
``` |
||||||
|
|
||||||
|
|
||||||
|
## Authors |
||||||
|
|
||||||
|
- TJ Holowaychuk |
||||||
|
- Nathan Rajlich |
||||||
|
- Andrew Rhyne |
||||||
|
|
||||||
|
## Backers |
||||||
|
|
||||||
|
Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/debug#backer)] |
||||||
|
|
||||||
|
<a href="https://opencollective.com/debug/backer/0/website" target="_blank"><img src="https://opencollective.com/debug/backer/0/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/backer/1/website" target="_blank"><img src="https://opencollective.com/debug/backer/1/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/backer/2/website" target="_blank"><img src="https://opencollective.com/debug/backer/2/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/backer/3/website" target="_blank"><img src="https://opencollective.com/debug/backer/3/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/backer/4/website" target="_blank"><img src="https://opencollective.com/debug/backer/4/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/backer/5/website" target="_blank"><img src="https://opencollective.com/debug/backer/5/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/backer/6/website" target="_blank"><img src="https://opencollective.com/debug/backer/6/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/backer/7/website" target="_blank"><img src="https://opencollective.com/debug/backer/7/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/backer/8/website" target="_blank"><img src="https://opencollective.com/debug/backer/8/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/backer/9/website" target="_blank"><img src="https://opencollective.com/debug/backer/9/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/backer/10/website" target="_blank"><img src="https://opencollective.com/debug/backer/10/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/backer/11/website" target="_blank"><img src="https://opencollective.com/debug/backer/11/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/backer/12/website" target="_blank"><img src="https://opencollective.com/debug/backer/12/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/backer/13/website" target="_blank"><img src="https://opencollective.com/debug/backer/13/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/backer/14/website" target="_blank"><img src="https://opencollective.com/debug/backer/14/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/backer/15/website" target="_blank"><img src="https://opencollective.com/debug/backer/15/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/backer/16/website" target="_blank"><img src="https://opencollective.com/debug/backer/16/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/backer/17/website" target="_blank"><img src="https://opencollective.com/debug/backer/17/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/backer/18/website" target="_blank"><img src="https://opencollective.com/debug/backer/18/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/backer/19/website" target="_blank"><img src="https://opencollective.com/debug/backer/19/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/backer/20/website" target="_blank"><img src="https://opencollective.com/debug/backer/20/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/backer/21/website" target="_blank"><img src="https://opencollective.com/debug/backer/21/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/backer/22/website" target="_blank"><img src="https://opencollective.com/debug/backer/22/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/backer/23/website" target="_blank"><img src="https://opencollective.com/debug/backer/23/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/backer/24/website" target="_blank"><img src="https://opencollective.com/debug/backer/24/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/backer/25/website" target="_blank"><img src="https://opencollective.com/debug/backer/25/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/backer/26/website" target="_blank"><img src="https://opencollective.com/debug/backer/26/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/backer/27/website" target="_blank"><img src="https://opencollective.com/debug/backer/27/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/backer/28/website" target="_blank"><img src="https://opencollective.com/debug/backer/28/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/backer/29/website" target="_blank"><img src="https://opencollective.com/debug/backer/29/avatar.svg"></a> |
||||||
|
|
||||||
|
|
||||||
|
## Sponsors |
||||||
|
|
||||||
|
Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/debug#sponsor)] |
||||||
|
|
||||||
|
<a href="https://opencollective.com/debug/sponsor/0/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/0/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/sponsor/1/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/1/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/sponsor/2/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/2/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/sponsor/3/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/3/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/sponsor/4/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/4/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/sponsor/5/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/5/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/sponsor/6/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/6/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/sponsor/7/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/7/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/sponsor/8/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/8/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/sponsor/9/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/9/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/sponsor/10/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/10/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/sponsor/11/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/11/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/sponsor/12/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/12/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/sponsor/13/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/13/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/sponsor/14/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/14/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/sponsor/15/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/15/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/sponsor/16/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/16/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/sponsor/17/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/17/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/sponsor/18/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/18/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/sponsor/19/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/19/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/sponsor/20/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/20/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/sponsor/21/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/21/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/sponsor/22/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/22/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/sponsor/23/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/23/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/sponsor/24/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/24/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/sponsor/25/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/25/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/sponsor/26/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/26/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/sponsor/27/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/27/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/sponsor/28/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/28/avatar.svg"></a> |
||||||
|
<a href="https://opencollective.com/debug/sponsor/29/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/29/avatar.svg"></a> |
||||||
|
|
||||||
|
## License |
||||||
|
|
||||||
|
(The MIT License) |
||||||
|
|
||||||
|
Copyright (c) 2014-2016 TJ Holowaychuk <tj@vision-media.ca> |
||||||
|
|
||||||
|
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. |
@ -0,0 +1,19 @@ |
|||||||
|
{ |
||||||
|
"name": "debug", |
||||||
|
"repo": "visionmedia/debug", |
||||||
|
"description": "small debugging utility", |
||||||
|
"version": "2.6.9", |
||||||
|
"keywords": [ |
||||||
|
"debug", |
||||||
|
"log", |
||||||
|
"debugger" |
||||||
|
], |
||||||
|
"main": "src/browser.js", |
||||||
|
"scripts": [ |
||||||
|
"src/browser.js", |
||||||
|
"src/debug.js" |
||||||
|
], |
||||||
|
"dependencies": { |
||||||
|
"rauchg/ms.js": "0.7.1" |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,70 @@ |
|||||||
|
// Karma configuration
|
||||||
|
// Generated on Fri Dec 16 2016 13:09:51 GMT+0000 (UTC)
|
||||||
|
|
||||||
|
module.exports = function(config) { |
||||||
|
config.set({ |
||||||
|
|
||||||
|
// base path that will be used to resolve all patterns (eg. files, exclude)
|
||||||
|
basePath: '', |
||||||
|
|
||||||
|
|
||||||
|
// frameworks to use
|
||||||
|
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
|
||||||
|
frameworks: ['mocha', 'chai', 'sinon'], |
||||||
|
|
||||||
|
|
||||||
|
// list of files / patterns to load in the browser
|
||||||
|
files: [ |
||||||
|
'dist/debug.js', |
||||||
|
'test/*spec.js' |
||||||
|
], |
||||||
|
|
||||||
|
|
||||||
|
// list of files to exclude
|
||||||
|
exclude: [ |
||||||
|
'src/node.js' |
||||||
|
], |
||||||
|
|
||||||
|
|
||||||
|
// preprocess matching files before serving them to the browser
|
||||||
|
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
|
||||||
|
preprocessors: { |
||||||
|
}, |
||||||
|
|
||||||
|
// test results reporter to use
|
||||||
|
// possible values: 'dots', 'progress'
|
||||||
|
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
|
||||||
|
reporters: ['progress'], |
||||||
|
|
||||||
|
|
||||||
|
// web server port
|
||||||
|
port: 9876, |
||||||
|
|
||||||
|
|
||||||
|
// enable / disable colors in the output (reporters and logs)
|
||||||
|
colors: true, |
||||||
|
|
||||||
|
|
||||||
|
// level of logging
|
||||||
|
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
|
||||||
|
logLevel: config.LOG_INFO, |
||||||
|
|
||||||
|
|
||||||
|
// enable / disable watching file and executing tests whenever any file changes
|
||||||
|
autoWatch: true, |
||||||
|
|
||||||
|
|
||||||
|
// start these browsers
|
||||||
|
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
|
||||||
|
browsers: ['PhantomJS'], |
||||||
|
|
||||||
|
|
||||||
|
// Continuous Integration mode
|
||||||
|
// if true, Karma captures browsers, runs the tests and exits
|
||||||
|
singleRun: false, |
||||||
|
|
||||||
|
// Concurrency level
|
||||||
|
// how many browser should be started simultaneous
|
||||||
|
concurrency: Infinity |
||||||
|
}) |
||||||
|
} |
@ -0,0 +1 @@ |
|||||||
|
module.exports = require('./src/node'); |
@ -0,0 +1,49 @@ |
|||||||
|
{ |
||||||
|
"name": "debug", |
||||||
|
"version": "2.6.9", |
||||||
|
"repository": { |
||||||
|
"type": "git", |
||||||
|
"url": "git://github.com/visionmedia/debug.git" |
||||||
|
}, |
||||||
|
"description": "small debugging utility", |
||||||
|
"keywords": [ |
||||||
|
"debug", |
||||||
|
"log", |
||||||
|
"debugger" |
||||||
|
], |
||||||
|
"author": "TJ Holowaychuk <tj@vision-media.ca>", |
||||||
|
"contributors": [ |
||||||
|
"Nathan Rajlich <nathan@tootallnate.net> (http://n8.io)", |
||||||
|
"Andrew Rhyne <rhyneandrew@gmail.com>" |
||||||
|
], |
||||||
|
"license": "MIT", |
||||||
|
"dependencies": { |
||||||
|
"ms": "2.0.0" |
||||||
|
}, |
||||||
|
"devDependencies": { |
||||||
|
"browserify": "9.0.3", |
||||||
|
"chai": "^3.5.0", |
||||||
|
"concurrently": "^3.1.0", |
||||||
|
"coveralls": "^2.11.15", |
||||||
|
"eslint": "^3.12.1", |
||||||
|
"istanbul": "^0.4.5", |
||||||
|
"karma": "^1.3.0", |
||||||
|
"karma-chai": "^0.1.0", |
||||||
|
"karma-mocha": "^1.3.0", |
||||||
|
"karma-phantomjs-launcher": "^1.0.2", |
||||||
|
"karma-sinon": "^1.0.5", |
||||||
|
"mocha": "^3.2.0", |
||||||
|
"mocha-lcov-reporter": "^1.2.0", |
||||||
|
"rimraf": "^2.5.4", |
||||||
|
"sinon": "^1.17.6", |
||||||
|
"sinon-chai": "^2.8.0" |
||||||
|
}, |
||||||
|
"main": "./src/index.js", |
||||||
|
"browser": "./src/browser.js", |
||||||
|
"component": { |
||||||
|
"scripts": { |
||||||
|
"debug/index.js": "browser.js", |
||||||
|
"debug/debug.js": "debug.js" |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,185 @@ |
|||||||
|
/** |
||||||
|
* This is the web browser implementation of `debug()`. |
||||||
|
* |
||||||
|
* Expose `debug()` as the module. |
||||||
|
*/ |
||||||
|
|
||||||
|
exports = module.exports = require('./debug'); |
||||||
|
exports.log = log; |
||||||
|
exports.formatArgs = formatArgs; |
||||||
|
exports.save = save; |
||||||
|
exports.load = load; |
||||||
|
exports.useColors = useColors; |
||||||
|
exports.storage = 'undefined' != typeof chrome |
||||||
|
&& 'undefined' != typeof chrome.storage |
||||||
|
? chrome.storage.local |
||||||
|
: localstorage(); |
||||||
|
|
||||||
|
/** |
||||||
|
* Colors. |
||||||
|
*/ |
||||||
|
|
||||||
|
exports.colors = [ |
||||||
|
'lightseagreen', |
||||||
|
'forestgreen', |
||||||
|
'goldenrod', |
||||||
|
'dodgerblue', |
||||||
|
'darkorchid', |
||||||
|
'crimson' |
||||||
|
]; |
||||||
|
|
||||||
|
/** |
||||||
|
* Currently only WebKit-based Web Inspectors, Firefox >= v31, |
||||||
|
* and the Firebug extension (any Firefox version) are known |
||||||
|
* to support "%c" CSS customizations. |
||||||
|
* |
||||||
|
* TODO: add a `localStorage` variable to explicitly enable/disable colors |
||||||
|
*/ |
||||||
|
|
||||||
|
function useColors() { |
||||||
|
// NB: In an Electron preload script, document will be defined but not fully
|
||||||
|
// initialized. Since we know we're in Chrome, we'll just detect this case
|
||||||
|
// explicitly
|
||||||
|
if (typeof window !== 'undefined' && window.process && window.process.type === 'renderer') { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
// is webkit? http://stackoverflow.com/a/16459606/376773
|
||||||
|
// document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
|
||||||
|
return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) || |
||||||
|
// is firebug? http://stackoverflow.com/a/398120/376773
|
||||||
|
(typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) || |
||||||
|
// is firefox >= v31?
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
|
||||||
|
(typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) || |
||||||
|
// double check webkit in userAgent just in case we are in a worker
|
||||||
|
(typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. |
||||||
|
*/ |
||||||
|
|
||||||
|
exports.formatters.j = function(v) { |
||||||
|
try { |
||||||
|
return JSON.stringify(v); |
||||||
|
} catch (err) { |
||||||
|
return '[UnexpectedJSONParseError]: ' + err.message; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Colorize log arguments if enabled. |
||||||
|
* |
||||||
|
* @api public |
||||||
|
*/ |
||||||
|
|
||||||
|
function formatArgs(args) { |
||||||
|
var useColors = this.useColors; |
||||||
|
|
||||||
|
args[0] = (useColors ? '%c' : '') |
||||||
|
+ this.namespace |
||||||
|
+ (useColors ? ' %c' : ' ') |
||||||
|
+ args[0] |
||||||
|
+ (useColors ? '%c ' : ' ') |
||||||
|
+ '+' + exports.humanize(this.diff); |
||||||
|
|
||||||
|
if (!useColors) return; |
||||||
|
|
||||||
|
var c = 'color: ' + this.color; |
||||||
|
args.splice(1, 0, c, 'color: inherit') |
||||||
|
|
||||||
|
// the final "%c" is somewhat tricky, because there could be other
|
||||||
|
// arguments passed either before or after the %c, so we need to
|
||||||
|
// figure out the correct index to insert the CSS into
|
||||||
|
var index = 0; |
||||||
|
var lastC = 0; |
||||||
|
args[0].replace(/%[a-zA-Z%]/g, function(match) { |
||||||
|
if ('%%' === match) return; |
||||||
|
index++; |
||||||
|
if ('%c' === match) { |
||||||
|
// we only are interested in the *last* %c
|
||||||
|
// (the user may have provided their own)
|
||||||
|
lastC = index; |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
args.splice(lastC, 0, c); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Invokes `console.log()` when available. |
||||||
|
* No-op when `console.log` is not a "function". |
||||||
|
* |
||||||
|
* @api public |
||||||
|
*/ |
||||||
|
|
||||||
|
function log() { |
||||||
|
// this hackery is required for IE8/9, where
|
||||||
|
// the `console.log` function doesn't have 'apply'
|
||||||
|
return 'object' === typeof console |
||||||
|
&& console.log |
||||||
|
&& Function.prototype.apply.call(console.log, console, arguments); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Save `namespaces`. |
||||||
|
* |
||||||
|
* @param {String} namespaces |
||||||
|
* @api private |
||||||
|
*/ |
||||||
|
|
||||||
|
function save(namespaces) { |
||||||
|
try { |
||||||
|
if (null == namespaces) { |
||||||
|
exports.storage.removeItem('debug'); |
||||||
|
} else { |
||||||
|
exports.storage.debug = namespaces; |
||||||
|
} |
||||||
|
} catch(e) {} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Load `namespaces`. |
||||||
|
* |
||||||
|
* @return {String} returns the previously persisted debug modes |
||||||
|
* @api private |
||||||
|
*/ |
||||||
|
|
||||||
|
function load() { |
||||||
|
var r; |
||||||
|
try { |
||||||
|
r = exports.storage.debug; |
||||||
|
} catch(e) {} |
||||||
|
|
||||||
|
// If debug isn't set in LS, and we're in Electron, try to load $DEBUG
|
||||||
|
if (!r && typeof process !== 'undefined' && 'env' in process) { |
||||||
|
r = process.env.DEBUG; |
||||||
|
} |
||||||
|
|
||||||
|
return r; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Enable namespaces listed in `localStorage.debug` initially. |
||||||
|
*/ |
||||||
|
|
||||||
|
exports.enable(load()); |
||||||
|
|
||||||
|
/** |
||||||
|
* Localstorage attempts to return the localstorage. |
||||||
|
* |
||||||
|
* This is necessary because safari throws |
||||||
|
* when a user disables cookies/localstorage |
||||||
|
* and you attempt to access it. |
||||||
|
* |
||||||
|
* @return {LocalStorage} |
||||||
|
* @api private |
||||||
|
*/ |
||||||
|
|
||||||
|
function localstorage() { |
||||||
|
try { |
||||||
|
return window.localStorage; |
||||||
|
} catch (e) {} |
||||||
|
} |
@ -0,0 +1,202 @@ |
|||||||
|
|
||||||
|
/** |
||||||
|
* This is the common logic for both the Node.js and web browser |
||||||
|
* implementations of `debug()`. |
||||||
|
* |
||||||
|
* Expose `debug()` as the module. |
||||||
|
*/ |
||||||
|
|
||||||
|
exports = module.exports = createDebug.debug = createDebug['default'] = createDebug; |
||||||
|
exports.coerce = coerce; |
||||||
|
exports.disable = disable; |
||||||
|
exports.enable = enable; |
||||||
|
exports.enabled = enabled; |
||||||
|
exports.humanize = require('ms'); |
||||||
|
|
||||||
|
/** |
||||||
|
* The currently active debug mode names, and names to skip. |
||||||
|
*/ |
||||||
|
|
||||||
|
exports.names = []; |
||||||
|
exports.skips = []; |
||||||
|
|
||||||
|
/** |
||||||
|
* Map of special "%n" handling functions, for the debug "format" argument. |
||||||
|
* |
||||||
|
* Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". |
||||||
|
*/ |
||||||
|
|
||||||
|
exports.formatters = {}; |
||||||
|
|
||||||
|
/** |
||||||
|
* Previous log timestamp. |
||||||
|
*/ |
||||||
|
|
||||||
|
var prevTime; |
||||||
|
|
||||||
|
/** |
||||||
|
* Select a color. |
||||||
|
* @param {String} namespace |
||||||
|
* @return {Number} |
||||||
|
* @api private |
||||||
|
*/ |
||||||
|
|
||||||
|
function selectColor(namespace) { |
||||||
|
var hash = 0, i; |
||||||
|
|
||||||
|
for (i in namespace) { |
||||||
|
hash = ((hash << 5) - hash) + namespace.charCodeAt(i); |
||||||
|
hash |= 0; // Convert to 32bit integer
|
||||||
|
} |
||||||
|
|
||||||
|
return exports.colors[Math.abs(hash) % exports.colors.length]; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a debugger with the given `namespace`. |
||||||
|
* |
||||||
|
* @param {String} namespace |
||||||
|
* @return {Function} |
||||||
|
* @api public |
||||||
|
*/ |
||||||
|
|
||||||
|
function createDebug(namespace) { |
||||||
|
|
||||||
|
function debug() { |
||||||
|
// disabled?
|
||||||
|
if (!debug.enabled) return; |
||||||
|
|
||||||
|
var self = debug; |
||||||
|
|
||||||
|
// set `diff` timestamp
|
||||||
|
var curr = +new Date(); |
||||||
|
var ms = curr - (prevTime || curr); |
||||||
|
self.diff = ms; |
||||||
|
self.prev = prevTime; |
||||||
|
self.curr = curr; |
||||||
|
prevTime = curr; |
||||||
|
|
||||||
|
// turn the `arguments` into a proper Array
|
||||||
|
var args = new Array(arguments.length); |
||||||
|
for (var i = 0; i < args.length; i++) { |
||||||
|
args[i] = arguments[i]; |
||||||
|
} |
||||||
|
|
||||||
|
args[0] = exports.coerce(args[0]); |
||||||
|
|
||||||
|
if ('string' !== typeof args[0]) { |
||||||
|
// anything else let's inspect with %O
|
||||||
|
args.unshift('%O'); |
||||||
|
} |
||||||
|
|
||||||
|
// apply any `formatters` transformations
|
||||||
|
var index = 0; |
||||||
|
args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) { |
||||||
|
// if we encounter an escaped % then don't increase the array index
|
||||||
|
if (match === '%%') return match; |
||||||
|
index++; |
||||||
|
var formatter = exports.formatters[format]; |
||||||
|
if ('function' === typeof formatter) { |
||||||
|
var val = args[index]; |
||||||
|
match = formatter.call(self, val); |
||||||
|
|
||||||
|
// now we need to remove `args[index]` since it's inlined in the `format`
|
||||||
|
args.splice(index, 1); |
||||||
|
index--; |
||||||
|
} |
||||||
|
return match; |
||||||
|
}); |
||||||
|
|
||||||
|
// apply env-specific formatting (colors, etc.)
|
||||||
|
exports.formatArgs.call(self, args); |
||||||
|
|
||||||
|
var logFn = debug.log || exports.log || console.log.bind(console); |
||||||
|
logFn.apply(self, args); |
||||||
|
} |
||||||
|
|
||||||
|
debug.namespace = namespace; |
||||||
|
debug.enabled = exports.enabled(namespace); |
||||||
|
debug.useColors = exports.useColors(); |
||||||
|
debug.color = selectColor(namespace); |
||||||
|
|
||||||
|
// env-specific initialization logic for debug instances
|
||||||
|
if ('function' === typeof exports.init) { |
||||||
|
exports.init(debug); |
||||||
|
} |
||||||
|
|
||||||
|
return debug; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Enables a debug mode by namespaces. This can include modes |
||||||
|
* separated by a colon and wildcards. |
||||||
|
* |
||||||
|
* @param {String} namespaces |
||||||
|
* @api public |
||||||
|
*/ |
||||||
|
|
||||||
|
function enable(namespaces) { |
||||||
|
exports.save(namespaces); |
||||||
|
|
||||||
|
exports.names = []; |
||||||
|
exports.skips = []; |
||||||
|
|
||||||
|
var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); |
||||||
|
var len = split.length; |
||||||
|
|
||||||
|
for (var i = 0; i < len; i++) { |
||||||
|
if (!split[i]) continue; // ignore empty strings
|
||||||
|
namespaces = split[i].replace(/\*/g, '.*?'); |
||||||
|
if (namespaces[0] === '-') { |
||||||
|
exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); |
||||||
|
} else { |
||||||
|
exports.names.push(new RegExp('^' + namespaces + '$')); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Disable debug output. |
||||||
|
* |
||||||
|
* @api public |
||||||
|
*/ |
||||||
|
|
||||||
|
function disable() { |
||||||
|
exports.enable(''); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns true if the given mode name is enabled, false otherwise. |
||||||
|
* |
||||||
|
* @param {String} name |
||||||
|
* @return {Boolean} |
||||||
|
* @api public |
||||||
|
*/ |
||||||
|
|
||||||
|
function enabled(name) { |
||||||
|
var i, len; |
||||||
|
for (i = 0, len = exports.skips.length; i < len; i++) { |
||||||
|
if (exports.skips[i].test(name)) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
for (i = 0, len = exports.names.length; i < len; i++) { |
||||||
|
if (exports.names[i].test(name)) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Coerce `val`. |
||||||
|
* |
||||||
|
* @param {Mixed} val |
||||||
|
* @return {Mixed} |
||||||
|
* @api private |
||||||
|
*/ |
||||||
|
|
||||||
|
function coerce(val) { |
||||||
|
if (val instanceof Error) return val.stack || val.message; |
||||||
|
return val; |
||||||
|
} |
@ -0,0 +1,10 @@ |
|||||||
|
/** |
||||||
|
* Detect Electron renderer process, which is node, but we should |
||||||
|
* treat as a browser. |
||||||
|
*/ |
||||||
|
|
||||||
|
if (typeof process !== 'undefined' && process.type === 'renderer') { |
||||||
|
module.exports = require('./browser.js'); |
||||||
|
} else { |
||||||
|
module.exports = require('./node.js'); |
||||||
|
} |
@ -0,0 +1,15 @@ |
|||||||
|
module.exports = inspectorLog; |
||||||
|
|
||||||
|
// black hole
|
||||||
|
const nullStream = new (require('stream').Writable)(); |
||||||
|
nullStream._write = () => {}; |
||||||
|
|
||||||
|
/** |
||||||
|
* Outputs a `console.log()` to the Node.js Inspector console *only*. |
||||||
|
*/ |
||||||
|
function inspectorLog() { |
||||||
|
const stdout = console._stdout; |
||||||
|
console._stdout = nullStream; |
||||||
|
console.log.apply(console, arguments); |
||||||
|
console._stdout = stdout; |
||||||
|
} |
@ -0,0 +1,248 @@ |
|||||||
|
/** |
||||||
|
* Module dependencies. |
||||||
|
*/ |
||||||
|
|
||||||
|
var tty = require('tty'); |
||||||
|
var util = require('util'); |
||||||
|
|
||||||
|
/** |
||||||
|
* This is the Node.js implementation of `debug()`. |
||||||
|
* |
||||||
|
* Expose `debug()` as the module. |
||||||
|
*/ |
||||||
|
|
||||||
|
exports = module.exports = require('./debug'); |
||||||
|
exports.init = init; |
||||||
|
exports.log = log; |
||||||
|
exports.formatArgs = formatArgs; |
||||||
|
exports.save = save; |
||||||
|
exports.load = load; |
||||||
|
exports.useColors = useColors; |
||||||
|
|
||||||
|
/** |
||||||
|
* Colors. |
||||||
|
*/ |
||||||
|
|
||||||
|
exports.colors = [6, 2, 3, 4, 5, 1]; |
||||||
|
|
||||||
|
/** |
||||||
|
* Build up the default `inspectOpts` object from the environment variables. |
||||||
|
* |
||||||
|
* $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js |
||||||
|
*/ |
||||||
|
|
||||||
|
exports.inspectOpts = Object.keys(process.env).filter(function (key) { |
||||||
|
return /^debug_/i.test(key); |
||||||
|
}).reduce(function (obj, key) { |
||||||
|
// camel-case
|
||||||
|
var prop = key |
||||||
|
.substring(6) |
||||||
|
.toLowerCase() |
||||||
|
.replace(/_([a-z])/g, function (_, k) { return k.toUpperCase() }); |
||||||
|
|
||||||
|
// coerce string value into JS value
|
||||||
|
var val = process.env[key]; |
||||||
|
if (/^(yes|on|true|enabled)$/i.test(val)) val = true; |
||||||
|
else if (/^(no|off|false|disabled)$/i.test(val)) val = false; |
||||||
|
else if (val === 'null') val = null; |
||||||
|
else val = Number(val); |
||||||
|
|
||||||
|
obj[prop] = val; |
||||||
|
return obj; |
||||||
|
}, {}); |
||||||
|
|
||||||
|
/** |
||||||
|
* The file descriptor to write the `debug()` calls to. |
||||||
|
* Set the `DEBUG_FD` env variable to override with another value. i.e.: |
||||||
|
* |
||||||
|
* $ DEBUG_FD=3 node script.js 3>debug.log |
||||||
|
*/ |
||||||
|
|
||||||
|
var fd = parseInt(process.env.DEBUG_FD, 10) || 2; |
||||||
|
|
||||||
|
if (1 !== fd && 2 !== fd) { |
||||||
|
util.deprecate(function(){}, 'except for stderr(2) and stdout(1), any other usage of DEBUG_FD is deprecated. Override debug.log if you want to use a different log function (https://git.io/debug_fd)')() |
||||||
|
} |
||||||
|
|
||||||
|
var stream = 1 === fd ? process.stdout : |
||||||
|
2 === fd ? process.stderr : |
||||||
|
createWritableStdioStream(fd); |
||||||
|
|
||||||
|
/** |
||||||
|
* Is stdout a TTY? Colored output is enabled when `true`. |
||||||
|
*/ |
||||||
|
|
||||||
|
function useColors() { |
||||||
|
return 'colors' in exports.inspectOpts |
||||||
|
? Boolean(exports.inspectOpts.colors) |
||||||
|
: tty.isatty(fd); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Map %o to `util.inspect()`, all on a single line. |
||||||
|
*/ |
||||||
|
|
||||||
|
exports.formatters.o = function(v) { |
||||||
|
this.inspectOpts.colors = this.useColors; |
||||||
|
return util.inspect(v, this.inspectOpts) |
||||||
|
.split('\n').map(function(str) { |
||||||
|
return str.trim() |
||||||
|
}).join(' '); |
||||||
|
}; |
||||||
|
|
||||||
|
/** |
||||||
|
* Map %o to `util.inspect()`, allowing multiple lines if needed. |
||||||
|
*/ |
||||||
|
|
||||||
|
exports.formatters.O = function(v) { |
||||||
|
this.inspectOpts.colors = this.useColors; |
||||||
|
return util.inspect(v, this.inspectOpts); |
||||||
|
}; |
||||||
|
|
||||||
|
/** |
||||||
|
* Adds ANSI color escape codes if enabled. |
||||||
|
* |
||||||
|
* @api public |
||||||
|
*/ |
||||||
|
|
||||||
|
function formatArgs(args) { |
||||||
|
var name = this.namespace; |
||||||
|
var useColors = this.useColors; |
||||||
|
|
||||||
|
if (useColors) { |
||||||
|
var c = this.color; |
||||||
|
var prefix = ' \u001b[3' + c + ';1m' + name + ' ' + '\u001b[0m'; |
||||||
|
|
||||||
|
args[0] = prefix + args[0].split('\n').join('\n' + prefix); |
||||||
|
args.push('\u001b[3' + c + 'm+' + exports.humanize(this.diff) + '\u001b[0m'); |
||||||
|
} else { |
||||||
|
args[0] = new Date().toUTCString() |
||||||
|
+ ' ' + name + ' ' + args[0]; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Invokes `util.format()` with the specified arguments and writes to `stream`. |
||||||
|
*/ |
||||||
|
|
||||||
|
function log() { |
||||||
|
return stream.write(util.format.apply(util, arguments) + '\n'); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Save `namespaces`. |
||||||
|
* |
||||||
|
* @param {String} namespaces |
||||||
|
* @api private |
||||||
|
*/ |
||||||
|
|
||||||
|
function save(namespaces) { |
||||||
|
if (null == namespaces) { |
||||||
|
// If you set a process.env field to null or undefined, it gets cast to the
|
||||||
|
// string 'null' or 'undefined'. Just delete instead.
|
||||||
|
delete process.env.DEBUG; |
||||||
|
} else { |
||||||
|
process.env.DEBUG = namespaces; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Load `namespaces`. |
||||||
|
* |
||||||
|
* @return {String} returns the previously persisted debug modes |
||||||
|
* @api private |
||||||
|
*/ |
||||||
|
|
||||||
|
function load() { |
||||||
|
return process.env.DEBUG; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Copied from `node/src/node.js`. |
||||||
|
* |
||||||
|
* XXX: It's lame that node doesn't expose this API out-of-the-box. It also |
||||||
|
* relies on the undocumented `tty_wrap.guessHandleType()` which is also lame. |
||||||
|
*/ |
||||||
|
|
||||||
|
function createWritableStdioStream (fd) { |
||||||
|
var stream; |
||||||
|
var tty_wrap = process.binding('tty_wrap'); |
||||||
|
|
||||||
|
// Note stream._type is used for test-module-load-list.js
|
||||||
|
|
||||||
|
switch (tty_wrap.guessHandleType(fd)) { |
||||||
|
case 'TTY': |
||||||
|
stream = new tty.WriteStream(fd); |
||||||
|
stream._type = 'tty'; |
||||||
|
|
||||||
|
// Hack to have stream not keep the event loop alive.
|
||||||
|
// See https://github.com/joyent/node/issues/1726
|
||||||
|
if (stream._handle && stream._handle.unref) { |
||||||
|
stream._handle.unref(); |
||||||
|
} |
||||||
|
break; |
||||||
|
|
||||||
|
case 'FILE': |
||||||
|
var fs = require('fs'); |
||||||
|
stream = new fs.SyncWriteStream(fd, { autoClose: false }); |
||||||
|
stream._type = 'fs'; |
||||||
|
break; |
||||||
|
|
||||||
|
case 'PIPE': |
||||||
|
case 'TCP': |
||||||
|
var net = require('net'); |
||||||
|
stream = new net.Socket({ |
||||||
|
fd: fd, |
||||||
|
readable: false, |
||||||
|
writable: true |
||||||
|
}); |
||||||
|
|
||||||
|
// FIXME Should probably have an option in net.Socket to create a
|
||||||
|
// stream from an existing fd which is writable only. But for now
|
||||||
|
// we'll just add this hack and set the `readable` member to false.
|
||||||
|
// Test: ./node test/fixtures/echo.js < /etc/passwd
|
||||||
|
stream.readable = false; |
||||||
|
stream.read = null; |
||||||
|
stream._type = 'pipe'; |
||||||
|
|
||||||
|
// FIXME Hack to have stream not keep the event loop alive.
|
||||||
|
// See https://github.com/joyent/node/issues/1726
|
||||||
|
if (stream._handle && stream._handle.unref) { |
||||||
|
stream._handle.unref(); |
||||||
|
} |
||||||
|
break; |
||||||
|
|
||||||
|
default: |
||||||
|
// Probably an error on in uv_guess_handle()
|
||||||
|
throw new Error('Implement me. Unknown stream file type!'); |
||||||
|
} |
||||||
|
|
||||||
|
// For supporting legacy API we put the FD here.
|
||||||
|
stream.fd = fd; |
||||||
|
|
||||||
|
stream._isStdio = true; |
||||||
|
|
||||||
|
return stream; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Init logic for `debug` instances. |
||||||
|
* |
||||||
|
* Create a new `inspectOpts` object in case `useColors` is set |
||||||
|
* differently for a particular `debug` instance. |
||||||
|
*/ |
||||||
|
|
||||||
|
function init (debug) { |
||||||
|
debug.inspectOpts = {}; |
||||||
|
|
||||||
|
var keys = Object.keys(exports.inspectOpts); |
||||||
|
for (var i = 0; i < keys.length; i++) { |
||||||
|
debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]]; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Enable namespaces listed in `process.env.DEBUG` initially. |
||||||
|
*/ |
||||||
|
|
||||||
|
exports.enable(load()); |
@ -0,0 +1,24 @@ |
|||||||
|
{ |
||||||
|
"root": true, |
||||||
|
|
||||||
|
"extends": "@ljharb", |
||||||
|
|
||||||
|
"rules": { |
||||||
|
"complexity": 0, |
||||||
|
"id-length": 0, |
||||||
|
"new-cap": ["error", { |
||||||
|
"capIsNewExceptions": [ |
||||||
|
"GetIntrinsic", |
||||||
|
], |
||||||
|
}], |
||||||
|
}, |
||||||
|
|
||||||
|
"overrides": [ |
||||||
|
{ |
||||||
|
"files": "test/**", |
||||||
|
"rules": { |
||||||
|
"max-lines-per-function": "off", |
||||||
|
}, |
||||||
|
}, |
||||||
|
], |
||||||
|
} |
@ -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/define-data-property |
||||||
|
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 up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] |
@ -0,0 +1,13 @@ |
|||||||
|
{ |
||||||
|
"all": true, |
||||||
|
"check-coverage": false, |
||||||
|
"reporter": ["text-summary", "text", "html", "json"], |
||||||
|
"lines": 86, |
||||||
|
"statements": 85.93, |
||||||
|
"functions": 82.43, |
||||||
|
"branches": 76.06, |
||||||
|
"exclude": [ |
||||||
|
"coverage", |
||||||
|
"test" |
||||||
|
] |
||||||
|
} |
@ -0,0 +1,70 @@ |
|||||||
|
# Changelog |
||||||
|
|
||||||
|
All notable changes to this project will be documented in this file. |
||||||
|
|
||||||
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) |
||||||
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). |
||||||
|
|
||||||
|
## [v1.1.4](https://github.com/ljharb/define-data-property/compare/v1.1.3...v1.1.4) - 2024-02-13 |
||||||
|
|
||||||
|
### Commits |
||||||
|
|
||||||
|
- [Refactor] use `es-define-property` [`90f2f4c`](https://github.com/ljharb/define-data-property/commit/90f2f4cc20298401e71c28e1e08888db12021453) |
||||||
|
- [Dev Deps] update `@types/object.getownpropertydescriptors` [`cd929d9`](https://github.com/ljharb/define-data-property/commit/cd929d9a04f5f2fdcfa9d5be140940b91a083153) |
||||||
|
|
||||||
|
## [v1.1.3](https://github.com/ljharb/define-data-property/compare/v1.1.2...v1.1.3) - 2024-02-12 |
||||||
|
|
||||||
|
### Commits |
||||||
|
|
||||||
|
- [types] hand-write d.ts instead of emitting it [`0cbc988`](https://github.com/ljharb/define-data-property/commit/0cbc988203c105f2d97948327c7167ebd33bd318) |
||||||
|
- [meta] simplify `exports` [`690781e`](https://github.com/ljharb/define-data-property/commit/690781eed28bbf2d6766237efda0ba6dd591609e) |
||||||
|
- [Dev Deps] update `hasown`; clean up DT packages [`6cdfd1c`](https://github.com/ljharb/define-data-property/commit/6cdfd1cb2d91d791bfd18cda5d5cab232fd5d8fc) |
||||||
|
- [actions] cleanup [`3142bc6`](https://github.com/ljharb/define-data-property/commit/3142bc6a4bc406a51f5b04f31e98562a27f35ffd) |
||||||
|
- [meta] add `funding` [`8474423`](https://github.com/ljharb/define-data-property/commit/847442391a79779af3e0f1bf0b5bb923552b7804) |
||||||
|
- [Deps] update `get-intrinsic` [`3e9be00`](https://github.com/ljharb/define-data-property/commit/3e9be00e07784ba34e7c77d8bc0fdbc832ad61de) |
||||||
|
|
||||||
|
## [v1.1.2](https://github.com/ljharb/define-data-property/compare/v1.1.1...v1.1.2) - 2024-02-05 |
||||||
|
|
||||||
|
### Commits |
||||||
|
|
||||||
|
- [Dev Deps] update @types packages, `object-inspect`, `tape`, `typescript` [`df41bf8`](https://github.com/ljharb/define-data-property/commit/df41bf84ca3456be6226055caab44e38e3a7fd2f) |
||||||
|
- [Dev Deps] update DT packages, `aud`, `npmignore`, `tape`, typescript` [`fab0e4e`](https://github.com/ljharb/define-data-property/commit/fab0e4ec709ee02b79f42d6db3ee5f26e0a34b8a) |
||||||
|
- [Dev Deps] use `hasown` instead of `has` [`aa51ef9`](https://github.com/ljharb/define-data-property/commit/aa51ef93f6403d49d9bb72a807bcdb6e418978c0) |
||||||
|
- [Refactor] use `es-errors`, so things that only need those do not need `get-intrinsic` [`d89be50`](https://github.com/ljharb/define-data-property/commit/d89be50571175888d391238605122679f7e65ffc) |
||||||
|
- [Deps] update `has-property-descriptors` [`7af887c`](https://github.com/ljharb/define-data-property/commit/7af887c9083b59b195b0079e04815cfed9fcee2b) |
||||||
|
- [Deps] update `get-intrinsic` [`bb8728e`](https://github.com/ljharb/define-data-property/commit/bb8728ec42cd998505a7157ae24853a560c20646) |
||||||
|
|
||||||
|
## [v1.1.1](https://github.com/ljharb/define-data-property/compare/v1.1.0...v1.1.1) - 2023-10-12 |
||||||
|
|
||||||
|
### Commits |
||||||
|
|
||||||
|
- [Tests] fix tests in ES3 engines [`5c6920e`](https://github.com/ljharb/define-data-property/commit/5c6920edd1f52f675b02f417e539c28135b43f94) |
||||||
|
- [Dev Deps] update `@types/es-value-fixtures`, `@types/for-each`, `@types/gopd`, `@types/has-property-descriptors`, `tape`, `typescript` [`7d82dfc`](https://github.com/ljharb/define-data-property/commit/7d82dfc20f778b4465bba06335dd53f6f431aea3) |
||||||
|
- [Fix] IE 8 has a broken `Object.defineProperty` [`0672e1a`](https://github.com/ljharb/define-data-property/commit/0672e1af2a9fcc787e7c23b96dea60d290df5548) |
||||||
|
- [meta] emit types on prepack [`73acb1f`](https://github.com/ljharb/define-data-property/commit/73acb1f903c21b314ec7156bf10f73c7910530c0) |
||||||
|
- [Dev Deps] update `tape`, `typescript` [`9489a77`](https://github.com/ljharb/define-data-property/commit/9489a7738bf2ecf0ac71d5b78ec4ca6ad7ba0142) |
||||||
|
|
||||||
|
## [v1.1.0](https://github.com/ljharb/define-data-property/compare/v1.0.1...v1.1.0) - 2023-09-13 |
||||||
|
|
||||||
|
### Commits |
||||||
|
|
||||||
|
- [New] add `loose` arg [`155235a`](https://github.com/ljharb/define-data-property/commit/155235a4c4d7741f6de01cd87c99599a56654b72) |
||||||
|
- [New] allow `null` to be passed for the non* args [`7d2fa5f`](https://github.com/ljharb/define-data-property/commit/7d2fa5f06be0392736c13b126f7cd38979f34792) |
||||||
|
|
||||||
|
## [v1.0.1](https://github.com/ljharb/define-data-property/compare/v1.0.0...v1.0.1) - 2023-09-12 |
||||||
|
|
||||||
|
### Commits |
||||||
|
|
||||||
|
- [meta] add TS types [`43d763c`](https://github.com/ljharb/define-data-property/commit/43d763c6c883f652de1c9c02ef6216ee507ffa69) |
||||||
|
- [Dev Deps] update `@types/tape`, `typescript` [`f444985`](https://github.com/ljharb/define-data-property/commit/f444985811c36f3e6448a03ad2f9b7898917f4c7) |
||||||
|
- [meta] add `safe-publish-latest`, [`172bb10`](https://github.com/ljharb/define-data-property/commit/172bb10890896ebb160e64398f6ee55760107bee) |
||||||
|
|
||||||
|
## v1.0.0 - 2023-09-12 |
||||||
|
|
||||||
|
### Commits |
||||||
|
|
||||||
|
- Initial implementation, tests, readme [`5b43d6b`](https://github.com/ljharb/define-data-property/commit/5b43d6b44e675a904810467a7d4e0adb7efc3196) |
||||||
|
- Initial commit [`35e577a`](https://github.com/ljharb/define-data-property/commit/35e577a6ba59a98befa97776d70d90f3bea9009d) |
||||||
|
- npm init [`82a0a04`](https://github.com/ljharb/define-data-property/commit/82a0a04a321ca7de220af02d41e2745e8a9962ed) |
||||||
|
- Only apps should have lockfiles [`96df244`](https://github.com/ljharb/define-data-property/commit/96df244a3c6f426f9a2437be825d1c6f5dd7158e) |
||||||
|
- [meta] use `npmignore` to autogenerate an npmignore file [`a87ff18`](https://github.com/ljharb/define-data-property/commit/a87ff18cb79e14c2eb5720486c4759fd9a189375) |
@ -0,0 +1,21 @@ |
|||||||
|
MIT License |
||||||
|
|
||||||
|
Copyright (c) 2023 Jordan Harband |
||||||
|
|
||||||
|
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. |
@ -0,0 +1,67 @@ |
|||||||
|
# define-data-property <sup>[![Version Badge][npm-version-svg]][package-url]</sup> |
||||||
|
|
||||||
|
[![github actions][actions-image]][actions-url] |
||||||
|
[![coverage][codecov-image]][codecov-url] |
||||||
|
[![License][license-image]][license-url] |
||||||
|
[![Downloads][downloads-image]][downloads-url] |
||||||
|
|
||||||
|
[![npm badge][npm-badge-png]][package-url] |
||||||
|
|
||||||
|
Define a data property on an object. Will fall back to assignment in an engine without descriptors. |
||||||
|
|
||||||
|
The three `non*` argument can also be passed `null`, which will use the existing state if available. |
||||||
|
|
||||||
|
The `loose` argument will mean that if you attempt to set a non-normal data property, in an environment without descriptor support, it will fall back to normal assignment. |
||||||
|
|
||||||
|
## Usage |
||||||
|
|
||||||
|
```javascript |
||||||
|
var defineDataProperty = require('define-data-property'); |
||||||
|
var assert = require('assert'); |
||||||
|
|
||||||
|
var obj = {}; |
||||||
|
defineDataProperty(obj, 'key', 'value'); |
||||||
|
defineDataProperty( |
||||||
|
obj, |
||||||
|
'key2', |
||||||
|
'value', |
||||||
|
true, // nonEnumerable, optional |
||||||
|
false, // nonWritable, optional |
||||||
|
true, // nonConfigurable, optional |
||||||
|
false // loose, optional |
||||||
|
); |
||||||
|
|
||||||
|
assert.deepEqual( |
||||||
|
Object.getOwnPropertyDescriptors(obj), |
||||||
|
{ |
||||||
|
key: { |
||||||
|
configurable: true, |
||||||
|
enumerable: true, |
||||||
|
value: 'value', |
||||||
|
writable: true, |
||||||
|
}, |
||||||
|
key2: { |
||||||
|
configurable: false, |
||||||
|
enumerable: false, |
||||||
|
value: 'value', |
||||||
|
writable: true, |
||||||
|
}, |
||||||
|
} |
||||||
|
); |
||||||
|
``` |
||||||
|
|
||||||
|
[package-url]: https://npmjs.org/package/define-data-property |
||||||
|
[npm-version-svg]: https://versionbadg.es/ljharb/define-data-property.svg |
||||||
|
[deps-svg]: https://david-dm.org/ljharb/define-data-property.svg |
||||||
|
[deps-url]: https://david-dm.org/ljharb/define-data-property |
||||||
|
[dev-deps-svg]: https://david-dm.org/ljharb/define-data-property/dev-status.svg |
||||||
|
[dev-deps-url]: https://david-dm.org/ljharb/define-data-property#info=devDependencies |
||||||
|
[npm-badge-png]: https://nodei.co/npm/define-data-property.png?downloads=true&stars=true |
||||||
|
[license-image]: https://img.shields.io/npm/l/define-data-property.svg |
||||||
|
[license-url]: LICENSE |
||||||
|
[downloads-image]: https://img.shields.io/npm/dm/define-data-property.svg |
||||||
|
[downloads-url]: https://npm-stat.com/charts.html?package=define-data-property |
||||||
|
[codecov-image]: https://codecov.io/gh/ljharb/define-data-property/branch/main/graphs/badge.svg |
||||||
|
[codecov-url]: https://app.codecov.io/gh/ljharb/define-data-property/ |
||||||
|
[actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/ljharb/define-data-property |
||||||
|
[actions-url]: https://github.com/ljharb/define-data-property/actions |
@ -0,0 +1,12 @@ |
|||||||
|
|
||||||
|
declare function defineDataProperty( |
||||||
|
obj: Record<PropertyKey, unknown>, |
||||||
|
property: keyof typeof obj, |
||||||
|
value: typeof obj[typeof property], |
||||||
|
nonEnumerable?: boolean | null, |
||||||
|
nonWritable?: boolean | null, |
||||||
|
nonConfigurable?: boolean | null, |
||||||
|
loose?: boolean |
||||||
|
): void; |
||||||
|
|
||||||
|
export = defineDataProperty; |
@ -0,0 +1,56 @@ |
|||||||
|
'use strict'; |
||||||
|
|
||||||
|
var $defineProperty = require('es-define-property'); |
||||||
|
|
||||||
|
var $SyntaxError = require('es-errors/syntax'); |
||||||
|
var $TypeError = require('es-errors/type'); |
||||||
|
|
||||||
|
var gopd = require('gopd'); |
||||||
|
|
||||||
|
/** @type {import('.')} */ |
||||||
|
module.exports = function defineDataProperty( |
||||||
|
obj, |
||||||
|
property, |
||||||
|
value |
||||||
|
) { |
||||||
|
if (!obj || (typeof obj !== 'object' && typeof obj !== 'function')) { |
||||||
|
throw new $TypeError('`obj` must be an object or a function`'); |
||||||
|
} |
||||||
|
if (typeof property !== 'string' && typeof property !== 'symbol') { |
||||||
|
throw new $TypeError('`property` must be a string or a symbol`'); |
||||||
|
} |
||||||
|
if (arguments.length > 3 && typeof arguments[3] !== 'boolean' && arguments[3] !== null) { |
||||||
|
throw new $TypeError('`nonEnumerable`, if provided, must be a boolean or null'); |
||||||
|
} |
||||||
|
if (arguments.length > 4 && typeof arguments[4] !== 'boolean' && arguments[4] !== null) { |
||||||
|
throw new $TypeError('`nonWritable`, if provided, must be a boolean or null'); |
||||||
|
} |
||||||
|
if (arguments.length > 5 && typeof arguments[5] !== 'boolean' && arguments[5] !== null) { |
||||||
|
throw new $TypeError('`nonConfigurable`, if provided, must be a boolean or null'); |
||||||
|
} |
||||||
|
if (arguments.length > 6 && typeof arguments[6] !== 'boolean') { |
||||||
|
throw new $TypeError('`loose`, if provided, must be a boolean'); |
||||||
|
} |
||||||
|
|
||||||
|
var nonEnumerable = arguments.length > 3 ? arguments[3] : null; |
||||||
|
var nonWritable = arguments.length > 4 ? arguments[4] : null; |
||||||
|
var nonConfigurable = arguments.length > 5 ? arguments[5] : null; |
||||||
|
var loose = arguments.length > 6 ? arguments[6] : false; |
||||||
|
|
||||||
|
/* @type {false | TypedPropertyDescriptor<unknown>} */ |
||||||
|
var desc = !!gopd && gopd(obj, property); |
||||||
|
|
||||||
|
if ($defineProperty) { |
||||||
|
$defineProperty(obj, property, { |
||||||
|
configurable: nonConfigurable === null && desc ? desc.configurable : !nonConfigurable, |
||||||
|
enumerable: nonEnumerable === null && desc ? desc.enumerable : !nonEnumerable, |
||||||
|
value: value, |
||||||
|
writable: nonWritable === null && desc ? desc.writable : !nonWritable |
||||||
|
}); |
||||||
|
} else if (loose || (!nonEnumerable && !nonWritable && !nonConfigurable)) { |
||||||
|
// must fall back to [[Set]], and was not explicitly asked to make non-enumerable, non-writable, or non-configurable
|
||||||
|
obj[property] = value; // eslint-disable-line no-param-reassign
|
||||||
|
} else { |
||||||
|
throw new $SyntaxError('This environment does not support defining a property as non-configurable, non-writable, or non-enumerable.'); |
||||||
|
} |
||||||
|
}; |
@ -0,0 +1,106 @@ |
|||||||
|
{ |
||||||
|
"name": "define-data-property", |
||||||
|
"version": "1.1.4", |
||||||
|
"description": "Define a data property on an object. Will fall back to assignment in an engine without descriptors.", |
||||||
|
"main": "index.js", |
||||||
|
"types": "./index.d.ts", |
||||||
|
"exports": { |
||||||
|
".": "./index.js", |
||||||
|
"./package.json": "./package.json" |
||||||
|
}, |
||||||
|
"sideEffects": false, |
||||||
|
"scripts": { |
||||||
|
"prepack": "npmignore --auto --commentLines=autogenerated", |
||||||
|
"prepublish": "not-in-publish || npm run prepublishOnly", |
||||||
|
"prepublishOnly": "safe-publish-latest", |
||||||
|
"tsc": "tsc -p .", |
||||||
|
"prelint": "evalmd README.md", |
||||||
|
"lint": "eslint --ext=js,mjs .", |
||||||
|
"postlint": "npm run tsc", |
||||||
|
"pretest": "npm run lint", |
||||||
|
"tests-only": "nyc tape 'test/**/*.js'", |
||||||
|
"test": "npm run tests-only", |
||||||
|
"posttest": "aud --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/define-data-property.git" |
||||||
|
}, |
||||||
|
"keywords": [ |
||||||
|
"define", |
||||||
|
"data", |
||||||
|
"property", |
||||||
|
"object", |
||||||
|
"accessor", |
||||||
|
"javascript", |
||||||
|
"ecmascript", |
||||||
|
"enumerable", |
||||||
|
"configurable", |
||||||
|
"writable" |
||||||
|
], |
||||||
|
"author": "Jordan Harband <ljharb@gmail.com>", |
||||||
|
"funding": { |
||||||
|
"url": "https://github.com/sponsors/ljharb" |
||||||
|
}, |
||||||
|
"license": "MIT", |
||||||
|
"bugs": { |
||||||
|
"url": "https://github.com/ljharb/define-data-property/issues" |
||||||
|
}, |
||||||
|
"homepage": "https://github.com/ljharb/define-data-property#readme", |
||||||
|
"dependencies": { |
||||||
|
"es-define-property": "^1.0.0", |
||||||
|
"es-errors": "^1.3.0", |
||||||
|
"gopd": "^1.0.1" |
||||||
|
}, |
||||||
|
"devDependencies": { |
||||||
|
"@ljharb/eslint-config": "^21.1.0", |
||||||
|
"@types/call-bind": "^1.0.5", |
||||||
|
"@types/define-properties": "^1.1.5", |
||||||
|
"@types/es-value-fixtures": "^1.4.4", |
||||||
|
"@types/for-each": "^0.3.3", |
||||||
|
"@types/get-intrinsic": "^1.2.2", |
||||||
|
"@types/gopd": "^1.0.3", |
||||||
|
"@types/has-property-descriptors": "^1.0.3", |
||||||
|
"@types/object-inspect": "^1.8.4", |
||||||
|
"@types/object.getownpropertydescriptors": "^2.1.4", |
||||||
|
"@types/tape": "^5.6.4", |
||||||
|
"aud": "^2.0.4", |
||||||
|
"auto-changelog": "^2.4.0", |
||||||
|
"es-value-fixtures": "^1.4.2", |
||||||
|
"eslint": "=8.8.0", |
||||||
|
"evalmd": "^0.0.19", |
||||||
|
"for-each": "^0.3.3", |
||||||
|
"hasown": "^2.0.1", |
||||||
|
"in-publish": "^2.0.1", |
||||||
|
"npmignore": "^0.3.1", |
||||||
|
"nyc": "^10.3.2", |
||||||
|
"object-inspect": "^1.13.1", |
||||||
|
"object.getownpropertydescriptors": "^2.1.7", |
||||||
|
"reflect.ownkeys": "^1.1.4", |
||||||
|
"safe-publish-latest": "^2.0.0", |
||||||
|
"tape": "^5.7.4", |
||||||
|
"typescript": "next" |
||||||
|
}, |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.4" |
||||||
|
}, |
||||||
|
"testling": { |
||||||
|
"files": "test/index.js" |
||||||
|
}, |
||||||
|
"auto-changelog": { |
||||||
|
"output": "CHANGELOG.md", |
||||||
|
"template": "keepachangelog", |
||||||
|
"unreleased": false, |
||||||
|
"commitLimit": false, |
||||||
|
"backfillLimit": false, |
||||||
|
"hideCredit": true |
||||||
|
}, |
||||||
|
"publishConfig": { |
||||||
|
"ignore": [ |
||||||
|
".github/workflows", |
||||||
|
"types/reflect.ownkeys" |
||||||
|
] |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,392 @@ |
|||||||
|
'use strict'; |
||||||
|
|
||||||
|
var test = require('tape'); |
||||||
|
var v = require('es-value-fixtures'); |
||||||
|
var forEach = require('for-each'); |
||||||
|
var inspect = require('object-inspect'); |
||||||
|
var hasOwn = require('hasown'); |
||||||
|
var hasPropertyDescriptors = require('has-property-descriptors')(); |
||||||
|
var getOwnPropertyDescriptors = require('object.getownpropertydescriptors'); |
||||||
|
var ownKeys = require('reflect.ownkeys'); |
||||||
|
|
||||||
|
var defineDataProperty = require('../'); |
||||||
|
|
||||||
|
test('defineDataProperty', function (t) { |
||||||
|
t.test('argument validation', function (st) { |
||||||
|
forEach(v.primitives, function (nonObject) { |
||||||
|
st['throws']( |
||||||
|
// @ts-expect-error
|
||||||
|
function () { defineDataProperty(nonObject, 'key', 'value'); }, |
||||||
|
TypeError, |
||||||
|
'throws on non-object input: ' + inspect(nonObject) |
||||||
|
); |
||||||
|
}); |
||||||
|
|
||||||
|
forEach(v.nonPropertyKeys, function (nonPropertyKey) { |
||||||
|
st['throws']( |
||||||
|
// @ts-expect-error
|
||||||
|
function () { defineDataProperty({}, nonPropertyKey, 'value'); }, |
||||||
|
TypeError, |
||||||
|
'throws on non-PropertyKey input: ' + inspect(nonPropertyKey) |
||||||
|
); |
||||||
|
}); |
||||||
|
|
||||||
|
forEach(v.nonBooleans, function (nonBoolean) { |
||||||
|
if (nonBoolean !== null) { |
||||||
|
st['throws']( |
||||||
|
// @ts-expect-error
|
||||||
|
function () { defineDataProperty({}, 'key', 'value', nonBoolean); }, |
||||||
|
TypeError, |
||||||
|
'throws on non-boolean nonEnumerable: ' + inspect(nonBoolean) |
||||||
|
); |
||||||
|
|
||||||
|
st['throws']( |
||||||
|
// @ts-expect-error
|
||||||
|
function () { defineDataProperty({}, 'key', 'value', false, nonBoolean); }, |
||||||
|
TypeError, |
||||||
|
'throws on non-boolean nonWritable: ' + inspect(nonBoolean) |
||||||
|
); |
||||||
|
|
||||||
|
st['throws']( |
||||||
|
// @ts-expect-error
|
||||||
|
function () { defineDataProperty({}, 'key', 'value', false, false, nonBoolean); }, |
||||||
|
TypeError, |
||||||
|
'throws on non-boolean nonConfigurable: ' + inspect(nonBoolean) |
||||||
|
); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
st.end(); |
||||||
|
}); |
||||||
|
|
||||||
|
t.test('normal data property', function (st) { |
||||||
|
/** @type {Record<PropertyKey, string>} */ |
||||||
|
var obj = { existing: 'existing property' }; |
||||||
|
st.ok(hasOwn(obj, 'existing'), 'has initial own property'); |
||||||
|
st.equal(obj.existing, 'existing property', 'has expected initial value'); |
||||||
|
|
||||||
|
var res = defineDataProperty(obj, 'added', 'added property'); |
||||||
|
st.equal(res, void undefined, 'returns `undefined`'); |
||||||
|
st.ok(hasOwn(obj, 'added'), 'has expected own property'); |
||||||
|
st.equal(obj.added, 'added property', 'has expected value'); |
||||||
|
|
||||||
|
defineDataProperty(obj, 'existing', 'new value'); |
||||||
|
st.ok(hasOwn(obj, 'existing'), 'still has expected own property'); |
||||||
|
st.equal(obj.existing, 'new value', 'has new expected value'); |
||||||
|
|
||||||
|
defineDataProperty(obj, 'explicit1', 'new value', false); |
||||||
|
st.ok(hasOwn(obj, 'explicit1'), 'has expected own property (explicit enumerable)'); |
||||||
|
st.equal(obj.explicit1, 'new value', 'has new expected value (explicit enumerable)'); |
||||||
|
|
||||||
|
defineDataProperty(obj, 'explicit2', 'new value', false, false); |
||||||
|
st.ok(hasOwn(obj, 'explicit2'), 'has expected own property (explicit writable)'); |
||||||
|
st.equal(obj.explicit2, 'new value', 'has new expected value (explicit writable)'); |
||||||
|
|
||||||
|
defineDataProperty(obj, 'explicit3', 'new value', false, false, false); |
||||||
|
st.ok(hasOwn(obj, 'explicit3'), 'has expected own property (explicit configurable)'); |
||||||
|
st.equal(obj.explicit3, 'new value', 'has new expected value (explicit configurable)'); |
||||||
|
|
||||||
|
st.end(); |
||||||
|
}); |
||||||
|
|
||||||
|
t.test('loose mode', { skip: !hasPropertyDescriptors }, function (st) { |
||||||
|
var obj = { existing: 'existing property' }; |
||||||
|
|
||||||
|
defineDataProperty(obj, 'added', 'added value 1', true, null, null, true); |
||||||
|
st.deepEqual( |
||||||
|
getOwnPropertyDescriptors(obj), |
||||||
|
{ |
||||||
|
existing: { |
||||||
|
configurable: true, |
||||||
|
enumerable: true, |
||||||
|
value: 'existing property', |
||||||
|
writable: true |
||||||
|
}, |
||||||
|
added: { |
||||||
|
configurable: true, |
||||||
|
enumerable: !hasPropertyDescriptors, |
||||||
|
value: 'added value 1', |
||||||
|
writable: true |
||||||
|
} |
||||||
|
}, |
||||||
|
'in loose mode, obj still adds property 1' |
||||||
|
); |
||||||
|
|
||||||
|
defineDataProperty(obj, 'added', 'added value 2', false, true, null, true); |
||||||
|
st.deepEqual( |
||||||
|
getOwnPropertyDescriptors(obj), |
||||||
|
{ |
||||||
|
existing: { |
||||||
|
configurable: true, |
||||||
|
enumerable: true, |
||||||
|
value: 'existing property', |
||||||
|
writable: true |
||||||
|
}, |
||||||
|
added: { |
||||||
|
configurable: true, |
||||||
|
enumerable: true, |
||||||
|
value: 'added value 2', |
||||||
|
writable: !hasPropertyDescriptors |
||||||
|
} |
||||||
|
}, |
||||||
|
'in loose mode, obj still adds property 2' |
||||||
|
); |
||||||
|
|
||||||
|
defineDataProperty(obj, 'added', 'added value 3', false, false, true, true); |
||||||
|
st.deepEqual( |
||||||
|
getOwnPropertyDescriptors(obj), |
||||||
|
{ |
||||||
|
existing: { |
||||||
|
configurable: true, |
||||||
|
enumerable: true, |
||||||
|
value: 'existing property', |
||||||
|
writable: true |
||||||
|
}, |
||||||
|
added: { |
||||||
|
configurable: !hasPropertyDescriptors, |
||||||
|
enumerable: true, |
||||||
|
value: 'added value 3', |
||||||
|
writable: true |
||||||
|
} |
||||||
|
}, |
||||||
|
'in loose mode, obj still adds property 3' |
||||||
|
); |
||||||
|
|
||||||
|
st.end(); |
||||||
|
}); |
||||||
|
|
||||||
|
t.test('non-normal data property, ES3', { skip: hasPropertyDescriptors }, function (st) { |
||||||
|
/** @type {Record<PropertyKey, string>} */ |
||||||
|
var obj = { existing: 'existing property' }; |
||||||
|
|
||||||
|
st['throws']( |
||||||
|
function () { defineDataProperty(obj, 'added', 'added value', true); }, |
||||||
|
SyntaxError, |
||||||
|
'nonEnumerable throws a Syntax Error' |
||||||
|
); |
||||||
|
|
||||||
|
st['throws']( |
||||||
|
function () { defineDataProperty(obj, 'added', 'added value', false, true); }, |
||||||
|
SyntaxError, |
||||||
|
'nonWritable throws a Syntax Error' |
||||||
|
); |
||||||
|
|
||||||
|
st['throws']( |
||||||
|
function () { defineDataProperty(obj, 'added', 'added value', false, false, true); }, |
||||||
|
SyntaxError, |
||||||
|
'nonWritable throws a Syntax Error' |
||||||
|
); |
||||||
|
|
||||||
|
st.deepEqual( |
||||||
|
ownKeys(obj), |
||||||
|
['existing'], |
||||||
|
'obj still has expected keys' |
||||||
|
); |
||||||
|
st.equal(obj.existing, 'existing property', 'obj still has expected values'); |
||||||
|
|
||||||
|
st.end(); |
||||||
|
}); |
||||||
|
|
||||||
|
t.test('new non-normal data property, ES5+', { skip: !hasPropertyDescriptors }, function (st) { |
||||||
|
/** @type {Record<PropertyKey, string>} */ |
||||||
|
var obj = { existing: 'existing property' }; |
||||||
|
|
||||||
|
defineDataProperty(obj, 'nonEnum', null, true); |
||||||
|
defineDataProperty(obj, 'nonWrit', null, false, true); |
||||||
|
defineDataProperty(obj, 'nonConf', null, false, false, true); |
||||||
|
|
||||||
|
st.deepEqual( |
||||||
|
getOwnPropertyDescriptors(obj), |
||||||
|
{ |
||||||
|
existing: { |
||||||
|
configurable: true, |
||||||
|
enumerable: true, |
||||||
|
value: 'existing property', |
||||||
|
writable: true |
||||||
|
}, |
||||||
|
nonEnum: { |
||||||
|
configurable: true, |
||||||
|
enumerable: false, |
||||||
|
value: null, |
||||||
|
writable: true |
||||||
|
}, |
||||||
|
nonWrit: { |
||||||
|
configurable: true, |
||||||
|
enumerable: true, |
||||||
|
value: null, |
||||||
|
writable: false |
||||||
|
}, |
||||||
|
nonConf: { |
||||||
|
configurable: false, |
||||||
|
enumerable: true, |
||||||
|
value: null, |
||||||
|
writable: true |
||||||
|
} |
||||||
|
}, |
||||||
|
'obj has expected property descriptors' |
||||||
|
); |
||||||
|
|
||||||
|
st.end(); |
||||||
|
}); |
||||||
|
|
||||||
|
t.test('existing non-normal data property, ES5+', { skip: !hasPropertyDescriptors }, function (st) { |
||||||
|
// test case changing an existing non-normal property
|
||||||
|
|
||||||
|
/** @type {Record<string, null | string>} */ |
||||||
|
var obj = {}; |
||||||
|
Object.defineProperty(obj, 'nonEnum', { configurable: true, enumerable: false, value: null, writable: true }); |
||||||
|
Object.defineProperty(obj, 'nonWrit', { configurable: true, enumerable: true, value: null, writable: false }); |
||||||
|
Object.defineProperty(obj, 'nonConf', { configurable: false, enumerable: true, value: null, writable: true }); |
||||||
|
|
||||||
|
st.deepEqual( |
||||||
|
getOwnPropertyDescriptors(obj), |
||||||
|
{ |
||||||
|
nonEnum: { |
||||||
|
configurable: true, |
||||||
|
enumerable: false, |
||||||
|
value: null, |
||||||
|
writable: true |
||||||
|
}, |
||||||
|
nonWrit: { |
||||||
|
configurable: true, |
||||||
|
enumerable: true, |
||||||
|
value: null, |
||||||
|
writable: false |
||||||
|
}, |
||||||
|
nonConf: { |
||||||
|
configurable: false, |
||||||
|
enumerable: true, |
||||||
|
value: null, |
||||||
|
writable: true |
||||||
|
} |
||||||
|
}, |
||||||
|
'obj initially has expected property descriptors' |
||||||
|
); |
||||||
|
|
||||||
|
defineDataProperty(obj, 'nonEnum', 'new value', false); |
||||||
|
defineDataProperty(obj, 'nonWrit', 'new value', false, false); |
||||||
|
st['throws']( |
||||||
|
function () { defineDataProperty(obj, 'nonConf', 'new value', false, false, false); }, |
||||||
|
TypeError, |
||||||
|
'can not alter a nonconfigurable property' |
||||||
|
); |
||||||
|
|
||||||
|
st.deepEqual( |
||||||
|
getOwnPropertyDescriptors(obj), |
||||||
|
{ |
||||||
|
nonEnum: { |
||||||
|
configurable: true, |
||||||
|
enumerable: true, |
||||||
|
value: 'new value', |
||||||
|
writable: true |
||||||
|
}, |
||||||
|
nonWrit: { |
||||||
|
configurable: true, |
||||||
|
enumerable: true, |
||||||
|
value: 'new value', |
||||||
|
writable: true |
||||||
|
}, |
||||||
|
nonConf: { |
||||||
|
configurable: false, |
||||||
|
enumerable: true, |
||||||
|
value: null, |
||||||
|
writable: true |
||||||
|
} |
||||||
|
}, |
||||||
|
'obj ends up with expected property descriptors' |
||||||
|
); |
||||||
|
|
||||||
|
st.end(); |
||||||
|
}); |
||||||
|
|
||||||
|
t.test('frozen object, ES5+', { skip: !hasPropertyDescriptors }, function (st) { |
||||||
|
var frozen = Object.freeze({ existing: true }); |
||||||
|
|
||||||
|
st['throws']( |
||||||
|
function () { defineDataProperty(frozen, 'existing', 'new value'); }, |
||||||
|
TypeError, |
||||||
|
'frozen object can not modify an existing property' |
||||||
|
); |
||||||
|
|
||||||
|
st['throws']( |
||||||
|
function () { defineDataProperty(frozen, 'new', 'new property'); }, |
||||||
|
TypeError, |
||||||
|
'frozen object can not add a new property' |
||||||
|
); |
||||||
|
|
||||||
|
st.end(); |
||||||
|
}); |
||||||
|
|
||||||
|
t.test('sealed object, ES5+', { skip: !hasPropertyDescriptors }, function (st) { |
||||||
|
var sealed = Object.seal({ existing: true }); |
||||||
|
st.deepEqual( |
||||||
|
Object.getOwnPropertyDescriptor(sealed, 'existing'), |
||||||
|
{ |
||||||
|
configurable: false, |
||||||
|
enumerable: true, |
||||||
|
value: true, |
||||||
|
writable: true |
||||||
|
}, |
||||||
|
'existing value on sealed object has expected descriptor' |
||||||
|
); |
||||||
|
|
||||||
|
defineDataProperty(sealed, 'existing', 'new value'); |
||||||
|
|
||||||
|
st.deepEqual( |
||||||
|
Object.getOwnPropertyDescriptor(sealed, 'existing'), |
||||||
|
{ |
||||||
|
configurable: false, |
||||||
|
enumerable: true, |
||||||
|
value: 'new value', |
||||||
|
writable: true |
||||||
|
}, |
||||||
|
'existing value on sealed object has changed descriptor' |
||||||
|
); |
||||||
|
|
||||||
|
st['throws']( |
||||||
|
function () { defineDataProperty(sealed, 'new', 'new property'); }, |
||||||
|
TypeError, |
||||||
|
'sealed object can not add a new property' |
||||||
|
); |
||||||
|
|
||||||
|
st.end(); |
||||||
|
}); |
||||||
|
|
||||||
|
t.test('nonextensible object, ES5+', { skip: !hasPropertyDescriptors }, function (st) { |
||||||
|
var nonExt = Object.preventExtensions({ existing: true }); |
||||||
|
|
||||||
|
st.deepEqual( |
||||||
|
Object.getOwnPropertyDescriptor(nonExt, 'existing'), |
||||||
|
{ |
||||||
|
configurable: true, |
||||||
|
enumerable: true, |
||||||
|
value: true, |
||||||
|
writable: true |
||||||
|
}, |
||||||
|
'existing value on non-extensible object has expected descriptor' |
||||||
|
); |
||||||
|
|
||||||
|
defineDataProperty(nonExt, 'existing', 'new value', true); |
||||||
|
|
||||||
|
st.deepEqual( |
||||||
|
Object.getOwnPropertyDescriptor(nonExt, 'existing'), |
||||||
|
{ |
||||||
|
configurable: true, |
||||||
|
enumerable: false, |
||||||
|
value: 'new value', |
||||||
|
writable: true |
||||||
|
}, |
||||||
|
'existing value on non-extensible object has changed descriptor' |
||||||
|
); |
||||||
|
|
||||||
|
st['throws']( |
||||||
|
function () { defineDataProperty(nonExt, 'new', 'new property'); }, |
||||||
|
TypeError, |
||||||
|
'non-extensible object can not add a new property' |
||||||
|
); |
||||||
|
|
||||||
|
st.end(); |
||||||
|
}); |
||||||
|
|
||||||
|
t.end(); |
||||||
|
}); |
@ -0,0 +1,59 @@ |
|||||||
|
{ |
||||||
|
"compilerOptions": { |
||||||
|
/* Visit https://aka.ms/tsconfig to read more about this file */ |
||||||
|
|
||||||
|
/* Projects */ |
||||||
|
|
||||||
|
/* Language and Environment */ |
||||||
|
"target": "es2022", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ |
||||||
|
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ |
||||||
|
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ |
||||||
|
"useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ |
||||||
|
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ |
||||||
|
|
||||||
|
/* Modules */ |
||||||
|
"module": "commonjs", /* Specify what module code is generated. */ |
||||||
|
// "rootDir": "./", /* Specify the root folder within your source files. */ |
||||||
|
// "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ |
||||||
|
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ |
||||||
|
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ |
||||||
|
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ |
||||||
|
"typeRoots": ["types"], /* Specify multiple folders that act like './node_modules/@types'. */ |
||||||
|
"resolveJsonModule": true, /* Enable importing .json files. */ |
||||||
|
|
||||||
|
/* JavaScript Support */ |
||||||
|
"allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ |
||||||
|
"checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ |
||||||
|
"maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ |
||||||
|
|
||||||
|
/* Emit */ |
||||||
|
"declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ |
||||||
|
"declarationMap": true, /* Create sourcemaps for d.ts files. */ |
||||||
|
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ |
||||||
|
"noEmit": true, /* Disable emitting files from a compilation. */ |
||||||
|
|
||||||
|
/* Interop Constraints */ |
||||||
|
"allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ |
||||||
|
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ |
||||||
|
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ |
||||||
|
|
||||||
|
/* Type Checking */ |
||||||
|
"strict": true, /* Enable all strict type-checking options. */ |
||||||
|
"noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ |
||||||
|
"noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ |
||||||
|
"useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ |
||||||
|
"noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ |
||||||
|
"noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ |
||||||
|
"noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ |
||||||
|
"noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ |
||||||
|
"noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ |
||||||
|
"noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ |
||||||
|
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ |
||||||
|
|
||||||
|
/* Completeness */ |
||||||
|
// "skipLibCheck": true /* Skip type checking all .d.ts files. */ |
||||||
|
}, |
||||||
|
"exclude": [ |
||||||
|
"coverage" |
||||||
|
] |
||||||
|
} |
@ -0,0 +1,103 @@ |
|||||||
|
2.0.0 / 2018-10-26 |
||||||
|
================== |
||||||
|
|
||||||
|
* Drop support for Node.js 0.6 |
||||||
|
* Replace internal `eval` usage with `Function` constructor |
||||||
|
* Use instance methods on `process` to check for listeners |
||||||
|
|
||||||
|
1.1.2 / 2018-01-11 |
||||||
|
================== |
||||||
|
|
||||||
|
* perf: remove argument reassignment |
||||||
|
* Support Node.js 0.6 to 9.x |
||||||
|
|
||||||
|
1.1.1 / 2017-07-27 |
||||||
|
================== |
||||||
|
|
||||||
|
* Remove unnecessary `Buffer` loading |
||||||
|
* Support Node.js 0.6 to 8.x |
||||||
|
|
||||||
|
1.1.0 / 2015-09-14 |
||||||
|
================== |
||||||
|
|
||||||
|
* Enable strict mode in more places |
||||||
|
* Support io.js 3.x |
||||||
|
* Support io.js 2.x |
||||||
|
* Support web browser loading |
||||||
|
- Requires bundler like Browserify or webpack |
||||||
|
|
||||||
|
1.0.1 / 2015-04-07 |
||||||
|
================== |
||||||
|
|
||||||
|
* Fix `TypeError`s when under `'use strict'` code |
||||||
|
* Fix useless type name on auto-generated messages |
||||||
|
* Support io.js 1.x |
||||||
|
* Support Node.js 0.12 |
||||||
|
|
||||||
|
1.0.0 / 2014-09-17 |
||||||
|
================== |
||||||
|
|
||||||
|
* No changes |
||||||
|
|
||||||
|
0.4.5 / 2014-09-09 |
||||||
|
================== |
||||||
|
|
||||||
|
* Improve call speed to functions using the function wrapper |
||||||
|
* Support Node.js 0.6 |
||||||
|
|
||||||
|
0.4.4 / 2014-07-27 |
||||||
|
================== |
||||||
|
|
||||||
|
* Work-around v8 generating empty stack traces |
||||||
|
|
||||||
|
0.4.3 / 2014-07-26 |
||||||
|
================== |
||||||
|
|
||||||
|
* Fix exception when global `Error.stackTraceLimit` is too low |
||||||
|
|
||||||
|
0.4.2 / 2014-07-19 |
||||||
|
================== |
||||||
|
|
||||||
|
* Correct call site for wrapped functions and properties |
||||||
|
|
||||||
|
0.4.1 / 2014-07-19 |
||||||
|
================== |
||||||
|
|
||||||
|
* Improve automatic message generation for function properties |
||||||
|
|
||||||
|
0.4.0 / 2014-07-19 |
||||||
|
================== |
||||||
|
|
||||||
|
* Add `TRACE_DEPRECATION` environment variable |
||||||
|
* Remove non-standard grey color from color output |
||||||
|
* Support `--no-deprecation` argument |
||||||
|
* Support `--trace-deprecation` argument |
||||||
|
* Support `deprecate.property(fn, prop, message)` |
||||||
|
|
||||||
|
0.3.0 / 2014-06-16 |
||||||
|
================== |
||||||
|
|
||||||
|
* Add `NO_DEPRECATION` environment variable |
||||||
|
|
||||||
|
0.2.0 / 2014-06-15 |
||||||
|
================== |
||||||
|
|
||||||
|
* Add `deprecate.property(obj, prop, message)` |
||||||
|
* Remove `supports-color` dependency for node.js 0.8 |
||||||
|
|
||||||
|
0.1.0 / 2014-06-15 |
||||||
|
================== |
||||||
|
|
||||||
|
* Add `deprecate.function(fn, message)` |
||||||
|
* Add `process.on('deprecation', fn)` emitter |
||||||
|
* Automatically generate message when omitted from `deprecate()` |
||||||
|
|
||||||
|
0.0.1 / 2014-06-15 |
||||||
|
================== |
||||||
|
|
||||||
|
* Fix warning for dynamic calls at singe call site |
||||||
|
|
||||||
|
0.0.0 / 2014-06-15 |
||||||
|
================== |
||||||
|
|
||||||
|
* Initial implementation |
@ -0,0 +1,22 @@ |
|||||||
|
(The MIT License) |
||||||
|
|
||||||
|
Copyright (c) 2014-2018 Douglas Christopher Wilson |
||||||
|
|
||||||
|
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. |
@ -0,0 +1,280 @@ |
|||||||
|
# depd |
||||||
|
|
||||||
|
[![NPM Version][npm-version-image]][npm-url] |
||||||
|
[![NPM Downloads][npm-downloads-image]][npm-url] |
||||||
|
[![Node.js Version][node-image]][node-url] |
||||||
|
[![Linux Build][travis-image]][travis-url] |
||||||
|
[![Windows Build][appveyor-image]][appveyor-url] |
||||||
|
[![Coverage Status][coveralls-image]][coveralls-url] |
||||||
|
|
||||||
|
Deprecate all the things |
||||||
|
|
||||||
|
> With great modules comes great responsibility; mark things deprecated! |
||||||
|
|
||||||
|
## Install |
||||||
|
|
||||||
|
This module is installed directly using `npm`: |
||||||
|
|
||||||
|
```sh |
||||||
|
$ npm install depd |
||||||
|
``` |
||||||
|
|
||||||
|
This module can also be bundled with systems like |
||||||
|
[Browserify](http://browserify.org/) or [webpack](https://webpack.github.io/), |
||||||
|
though by default this module will alter it's API to no longer display or |
||||||
|
track deprecations. |
||||||
|
|
||||||
|
## API |
||||||
|
|
||||||
|
<!-- eslint-disable no-unused-vars --> |
||||||
|
|
||||||
|
```js |
||||||
|
var deprecate = require('depd')('my-module') |
||||||
|
``` |
||||||
|
|
||||||
|
This library allows you to display deprecation messages to your users. |
||||||
|
This library goes above and beyond with deprecation warnings by |
||||||
|
introspection of the call stack (but only the bits that it is interested |
||||||
|
in). |
||||||
|
|
||||||
|
Instead of just warning on the first invocation of a deprecated |
||||||
|
function and never again, this module will warn on the first invocation |
||||||
|
of a deprecated function per unique call site, making it ideal to alert |
||||||
|
users of all deprecated uses across the code base, rather than just |
||||||
|
whatever happens to execute first. |
||||||
|
|
||||||
|
The deprecation warnings from this module also include the file and line |
||||||
|
information for the call into the module that the deprecated function was |
||||||
|
in. |
||||||
|
|
||||||
|
**NOTE** this library has a similar interface to the `debug` module, and |
||||||
|
this module uses the calling file to get the boundary for the call stacks, |
||||||
|
so you should always create a new `deprecate` object in each file and not |
||||||
|
within some central file. |
||||||
|
|
||||||
|
### depd(namespace) |
||||||
|
|
||||||
|
Create a new deprecate function that uses the given namespace name in the |
||||||
|
messages and will display the call site prior to the stack entering the |
||||||
|
file this function was called from. It is highly suggested you use the |
||||||
|
name of your module as the namespace. |
||||||
|
|
||||||
|
### deprecate(message) |
||||||
|
|
||||||
|
Call this function from deprecated code to display a deprecation message. |
||||||
|
This message will appear once per unique caller site. Caller site is the |
||||||
|
first call site in the stack in a different file from the caller of this |
||||||
|
function. |
||||||
|
|
||||||
|
If the message is omitted, a message is generated for you based on the site |
||||||
|
of the `deprecate()` call and will display the name of the function called, |
||||||
|
similar to the name displayed in a stack trace. |
||||||
|
|
||||||
|
### deprecate.function(fn, message) |
||||||
|
|
||||||
|
Call this function to wrap a given function in a deprecation message on any |
||||||
|
call to the function. An optional message can be supplied to provide a custom |
||||||
|
message. |
||||||
|
|
||||||
|
### deprecate.property(obj, prop, message) |
||||||
|
|
||||||
|
Call this function to wrap a given property on object in a deprecation message |
||||||
|
on any accessing or setting of the property. An optional message can be supplied |
||||||
|
to provide a custom message. |
||||||
|
|
||||||
|
The method must be called on the object where the property belongs (not |
||||||
|
inherited from the prototype). |
||||||
|
|
||||||
|
If the property is a data descriptor, it will be converted to an accessor |
||||||
|
descriptor in order to display the deprecation message. |
||||||
|
|
||||||
|
### process.on('deprecation', fn) |
||||||
|
|
||||||
|
This module will allow easy capturing of deprecation errors by emitting the |
||||||
|
errors as the type "deprecation" on the global `process`. If there are no |
||||||
|
listeners for this type, the errors are written to STDERR as normal, but if |
||||||
|
there are any listeners, nothing will be written to STDERR and instead only |
||||||
|
emitted. From there, you can write the errors in a different format or to a |
||||||
|
logging source. |
||||||
|
|
||||||
|
The error represents the deprecation and is emitted only once with the same |
||||||
|
rules as writing to STDERR. The error has the following properties: |
||||||
|
|
||||||
|
- `message` - This is the message given by the library |
||||||
|
- `name` - This is always `'DeprecationError'` |
||||||
|
- `namespace` - This is the namespace the deprecation came from |
||||||
|
- `stack` - This is the stack of the call to the deprecated thing |
||||||
|
|
||||||
|
Example `error.stack` output: |
||||||
|
|
||||||
|
``` |
||||||
|
DeprecationError: my-cool-module deprecated oldfunction |
||||||
|
at Object.<anonymous> ([eval]-wrapper:6:22) |
||||||
|
at Module._compile (module.js:456:26) |
||||||
|
at evalScript (node.js:532:25) |
||||||
|
at startup (node.js:80:7) |
||||||
|
at node.js:902:3 |
||||||
|
``` |
||||||
|
|
||||||
|
### process.env.NO_DEPRECATION |
||||||
|
|
||||||
|
As a user of modules that are deprecated, the environment variable `NO_DEPRECATION` |
||||||
|
is provided as a quick solution to silencing deprecation warnings from being |
||||||
|
output. The format of this is similar to that of `DEBUG`: |
||||||
|
|
||||||
|
```sh |
||||||
|
$ NO_DEPRECATION=my-module,othermod node app.js |
||||||
|
``` |
||||||
|
|
||||||
|
This will suppress deprecations from being output for "my-module" and "othermod". |
||||||
|
The value is a list of comma-separated namespaces. To suppress every warning |
||||||
|
across all namespaces, use the value `*` for a namespace. |
||||||
|
|
||||||
|
Providing the argument `--no-deprecation` to the `node` executable will suppress |
||||||
|
all deprecations (only available in Node.js 0.8 or higher). |
||||||
|
|
||||||
|
**NOTE** This will not suppress the deperecations given to any "deprecation" |
||||||
|
event listeners, just the output to STDERR. |
||||||
|
|
||||||
|
### process.env.TRACE_DEPRECATION |
||||||
|
|
||||||
|
As a user of modules that are deprecated, the environment variable `TRACE_DEPRECATION` |
||||||
|
is provided as a solution to getting more detailed location information in deprecation |
||||||
|
warnings by including the entire stack trace. The format of this is the same as |
||||||
|
`NO_DEPRECATION`: |
||||||
|
|
||||||
|
```sh |
||||||
|
$ TRACE_DEPRECATION=my-module,othermod node app.js |
||||||
|
``` |
||||||
|
|
||||||
|
This will include stack traces for deprecations being output for "my-module" and |
||||||
|
"othermod". The value is a list of comma-separated namespaces. To trace every |
||||||
|
warning across all namespaces, use the value `*` for a namespace. |
||||||
|
|
||||||
|
Providing the argument `--trace-deprecation` to the `node` executable will trace |
||||||
|
all deprecations (only available in Node.js 0.8 or higher). |
||||||
|
|
||||||
|
**NOTE** This will not trace the deperecations silenced by `NO_DEPRECATION`. |
||||||
|
|
||||||
|
## Display |
||||||
|
|
||||||
|
![message](files/message.png) |
||||||
|
|
||||||
|
When a user calls a function in your library that you mark deprecated, they |
||||||
|
will see the following written to STDERR (in the given colors, similar colors |
||||||
|
and layout to the `debug` module): |
||||||
|
|
||||||
|
``` |
||||||
|
bright cyan bright yellow |
||||||
|
| | reset cyan |
||||||
|
| | | | |
||||||
|
▼ ▼ ▼ ▼ |
||||||
|
my-cool-module deprecated oldfunction [eval]-wrapper:6:22 |
||||||
|
▲ ▲ ▲ ▲ |
||||||
|
| | | | |
||||||
|
namespace | | location of mycoolmod.oldfunction() call |
||||||
|
| deprecation message |
||||||
|
the word "deprecated" |
||||||
|
``` |
||||||
|
|
||||||
|
If the user redirects their STDERR to a file or somewhere that does not support |
||||||
|
colors, they see (similar layout to the `debug` module): |
||||||
|
|
||||||
|
``` |
||||||
|
Sun, 15 Jun 2014 05:21:37 GMT my-cool-module deprecated oldfunction at [eval]-wrapper:6:22 |
||||||
|
▲ ▲ ▲ ▲ ▲ |
||||||
|
| | | | | |
||||||
|
timestamp of message namespace | | location of mycoolmod.oldfunction() call |
||||||
|
| deprecation message |
||||||
|
the word "deprecated" |
||||||
|
``` |
||||||
|
|
||||||
|
## Examples |
||||||
|
|
||||||
|
### Deprecating all calls to a function |
||||||
|
|
||||||
|
This will display a deprecated message about "oldfunction" being deprecated |
||||||
|
from "my-module" on STDERR. |
||||||
|
|
||||||
|
```js |
||||||
|
var deprecate = require('depd')('my-cool-module') |
||||||
|
|
||||||
|
// message automatically derived from function name |
||||||
|
// Object.oldfunction |
||||||
|
exports.oldfunction = deprecate.function(function oldfunction () { |
||||||
|
// all calls to function are deprecated |
||||||
|
}) |
||||||
|
|
||||||
|
// specific message |
||||||
|
exports.oldfunction = deprecate.function(function () { |
||||||
|
// all calls to function are deprecated |
||||||
|
}, 'oldfunction') |
||||||
|
``` |
||||||
|
|
||||||
|
### Conditionally deprecating a function call |
||||||
|
|
||||||
|
This will display a deprecated message about "weirdfunction" being deprecated |
||||||
|
from "my-module" on STDERR when called with less than 2 arguments. |
||||||
|
|
||||||
|
```js |
||||||
|
var deprecate = require('depd')('my-cool-module') |
||||||
|
|
||||||
|
exports.weirdfunction = function () { |
||||||
|
if (arguments.length < 2) { |
||||||
|
// calls with 0 or 1 args are deprecated |
||||||
|
deprecate('weirdfunction args < 2') |
||||||
|
} |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
When calling `deprecate` as a function, the warning is counted per call site |
||||||
|
within your own module, so you can display different deprecations depending |
||||||
|
on different situations and the users will still get all the warnings: |
||||||
|
|
||||||
|
```js |
||||||
|
var deprecate = require('depd')('my-cool-module') |
||||||
|
|
||||||
|
exports.weirdfunction = function () { |
||||||
|
if (arguments.length < 2) { |
||||||
|
// calls with 0 or 1 args are deprecated |
||||||
|
deprecate('weirdfunction args < 2') |
||||||
|
} else if (typeof arguments[0] !== 'string') { |
||||||
|
// calls with non-string first argument are deprecated |
||||||
|
deprecate('weirdfunction non-string first arg') |
||||||
|
} |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
### Deprecating property access |
||||||
|
|
||||||
|
This will display a deprecated message about "oldprop" being deprecated |
||||||
|
from "my-module" on STDERR when accessed. A deprecation will be displayed |
||||||
|
when setting the value and when getting the value. |
||||||
|
|
||||||
|
```js |
||||||
|
var deprecate = require('depd')('my-cool-module') |
||||||
|
|
||||||
|
exports.oldprop = 'something' |
||||||
|
|
||||||
|
// message automatically derives from property name |
||||||
|
deprecate.property(exports, 'oldprop') |
||||||
|
|
||||||
|
// explicit message |
||||||
|
deprecate.property(exports, 'oldprop', 'oldprop >= 0.10') |
||||||
|
``` |
||||||
|
|
||||||
|
## License |
||||||
|
|
||||||
|
[MIT](LICENSE) |
||||||
|
|
||||||
|
[appveyor-image]: https://badgen.net/appveyor/ci/dougwilson/nodejs-depd/master?label=windows |
||||||
|
[appveyor-url]: https://ci.appveyor.com/project/dougwilson/nodejs-depd |
||||||
|
[coveralls-image]: https://badgen.net/coveralls/c/github/dougwilson/nodejs-depd/master |
||||||
|
[coveralls-url]: https://coveralls.io/r/dougwilson/nodejs-depd?branch=master |
||||||
|
[node-image]: https://badgen.net/npm/node/depd |
||||||
|
[node-url]: https://nodejs.org/en/download/ |
||||||
|
[npm-downloads-image]: https://badgen.net/npm/dm/depd |
||||||
|
[npm-url]: https://npmjs.org/package/depd |
||||||
|
[npm-version-image]: https://badgen.net/npm/v/depd |
||||||
|
[travis-image]: https://badgen.net/travis/dougwilson/nodejs-depd/master?label=linux |
||||||
|
[travis-url]: https://travis-ci.org/dougwilson/nodejs-depd |
@ -0,0 +1,538 @@ |
|||||||
|
/*! |
||||||
|
* depd |
||||||
|
* Copyright(c) 2014-2018 Douglas Christopher Wilson |
||||||
|
* MIT Licensed |
||||||
|
*/ |
||||||
|
|
||||||
|
/** |
||||||
|
* Module dependencies. |
||||||
|
*/ |
||||||
|
|
||||||
|
var relative = require('path').relative |
||||||
|
|
||||||
|
/** |
||||||
|
* Module exports. |
||||||
|
*/ |
||||||
|
|
||||||
|
module.exports = depd |
||||||
|
|
||||||
|
/** |
||||||
|
* Get the path to base files on. |
||||||
|
*/ |
||||||
|
|
||||||
|
var basePath = process.cwd() |
||||||
|
|
||||||
|
/** |
||||||
|
* Determine if namespace is contained in the string. |
||||||
|
*/ |
||||||
|
|
||||||
|
function containsNamespace (str, namespace) { |
||||||
|
var vals = str.split(/[ ,]+/) |
||||||
|
var ns = String(namespace).toLowerCase() |
||||||
|
|
||||||
|
for (var i = 0; i < vals.length; i++) { |
||||||
|
var val = vals[i] |
||||||
|
|
||||||
|
// namespace contained
|
||||||
|
if (val && (val === '*' || val.toLowerCase() === ns)) { |
||||||
|
return true |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return false |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Convert a data descriptor to accessor descriptor. |
||||||
|
*/ |
||||||
|
|
||||||
|
function convertDataDescriptorToAccessor (obj, prop, message) { |
||||||
|
var descriptor = Object.getOwnPropertyDescriptor(obj, prop) |
||||||
|
var value = descriptor.value |
||||||
|
|
||||||
|
descriptor.get = function getter () { return value } |
||||||
|
|
||||||
|
if (descriptor.writable) { |
||||||
|
descriptor.set = function setter (val) { return (value = val) } |
||||||
|
} |
||||||
|
|
||||||
|
delete descriptor.value |
||||||
|
delete descriptor.writable |
||||||
|
|
||||||
|
Object.defineProperty(obj, prop, descriptor) |
||||||
|
|
||||||
|
return descriptor |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create arguments string to keep arity. |
||||||
|
*/ |
||||||
|
|
||||||
|
function createArgumentsString (arity) { |
||||||
|
var str = '' |
||||||
|
|
||||||
|
for (var i = 0; i < arity; i++) { |
||||||
|
str += ', arg' + i |
||||||
|
} |
||||||
|
|
||||||
|
return str.substr(2) |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create stack string from stack. |
||||||
|
*/ |
||||||
|
|
||||||
|
function createStackString (stack) { |
||||||
|
var str = this.name + ': ' + this.namespace |
||||||
|
|
||||||
|
if (this.message) { |
||||||
|
str += ' deprecated ' + this.message |
||||||
|
} |
||||||
|
|
||||||
|
for (var i = 0; i < stack.length; i++) { |
||||||
|
str += '\n at ' + stack[i].toString() |
||||||
|
} |
||||||
|
|
||||||
|
return str |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create deprecate for namespace in caller. |
||||||
|
*/ |
||||||
|
|
||||||
|
function depd (namespace) { |
||||||
|
if (!namespace) { |
||||||
|
throw new TypeError('argument namespace is required') |
||||||
|
} |
||||||
|
|
||||||
|
var stack = getStack() |
||||||
|
var site = callSiteLocation(stack[1]) |
||||||
|
var file = site[0] |
||||||
|
|
||||||
|
function deprecate (message) { |
||||||
|
// call to self as log
|
||||||
|
log.call(deprecate, message) |
||||||
|
} |
||||||
|
|
||||||
|
deprecate._file = file |
||||||
|
deprecate._ignored = isignored(namespace) |
||||||
|
deprecate._namespace = namespace |
||||||
|
deprecate._traced = istraced(namespace) |
||||||
|
deprecate._warned = Object.create(null) |
||||||
|
|
||||||
|
deprecate.function = wrapfunction |
||||||
|
deprecate.property = wrapproperty |
||||||
|
|
||||||
|
return deprecate |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Determine if event emitter has listeners of a given type. |
||||||
|
* |
||||||
|
* The way to do this check is done three different ways in Node.js >= 0.8 |
||||||
|
* so this consolidates them into a minimal set using instance methods. |
||||||
|
* |
||||||
|
* @param {EventEmitter} emitter |
||||||
|
* @param {string} type |
||||||
|
* @returns {boolean} |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
function eehaslisteners (emitter, type) { |
||||||
|
var count = typeof emitter.listenerCount !== 'function' |
||||||
|
? emitter.listeners(type).length |
||||||
|
: emitter.listenerCount(type) |
||||||
|
|
||||||
|
return count > 0 |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Determine if namespace is ignored. |
||||||
|
*/ |
||||||
|
|
||||||
|
function isignored (namespace) { |
||||||
|
if (process.noDeprecation) { |
||||||
|
// --no-deprecation support
|
||||||
|
return true |
||||||
|
} |
||||||
|
|
||||||
|
var str = process.env.NO_DEPRECATION || '' |
||||||
|
|
||||||
|
// namespace ignored
|
||||||
|
return containsNamespace(str, namespace) |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Determine if namespace is traced. |
||||||
|
*/ |
||||||
|
|
||||||
|
function istraced (namespace) { |
||||||
|
if (process.traceDeprecation) { |
||||||
|
// --trace-deprecation support
|
||||||
|
return true |
||||||
|
} |
||||||
|
|
||||||
|
var str = process.env.TRACE_DEPRECATION || '' |
||||||
|
|
||||||
|
// namespace traced
|
||||||
|
return containsNamespace(str, namespace) |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Display deprecation message. |
||||||
|
*/ |
||||||
|
|
||||||
|
function log (message, site) { |
||||||
|
var haslisteners = eehaslisteners(process, 'deprecation') |
||||||
|
|
||||||
|
// abort early if no destination
|
||||||
|
if (!haslisteners && this._ignored) { |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
var caller |
||||||
|
var callFile |
||||||
|
var callSite |
||||||
|
var depSite |
||||||
|
var i = 0 |
||||||
|
var seen = false |
||||||
|
var stack = getStack() |
||||||
|
var file = this._file |
||||||
|
|
||||||
|
if (site) { |
||||||
|
// provided site
|
||||||
|
depSite = site |
||||||
|
callSite = callSiteLocation(stack[1]) |
||||||
|
callSite.name = depSite.name |
||||||
|
file = callSite[0] |
||||||
|
} else { |
||||||
|
// get call site
|
||||||
|
i = 2 |
||||||
|
depSite = callSiteLocation(stack[i]) |
||||||
|
callSite = depSite |
||||||
|
} |
||||||
|
|
||||||
|
// get caller of deprecated thing in relation to file
|
||||||
|
for (; i < stack.length; i++) { |
||||||
|
caller = callSiteLocation(stack[i]) |
||||||
|
callFile = caller[0] |
||||||
|
|
||||||
|
if (callFile === file) { |
||||||
|
seen = true |
||||||
|
} else if (callFile === this._file) { |
||||||
|
file = this._file |
||||||
|
} else if (seen) { |
||||||
|
break |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
var key = caller |
||||||
|
? depSite.join(':') + '__' + caller.join(':') |
||||||
|
: undefined |
||||||
|
|
||||||
|
if (key !== undefined && key in this._warned) { |
||||||
|
// already warned
|
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
this._warned[key] = true |
||||||
|
|
||||||
|
// generate automatic message from call site
|
||||||
|
var msg = message |
||||||
|
if (!msg) { |
||||||
|
msg = callSite === depSite || !callSite.name |
||||||
|
? defaultMessage(depSite) |
||||||
|
: defaultMessage(callSite) |
||||||
|
} |
||||||
|
|
||||||
|
// emit deprecation if listeners exist
|
||||||
|
if (haslisteners) { |
||||||
|
var err = DeprecationError(this._namespace, msg, stack.slice(i)) |
||||||
|
process.emit('deprecation', err) |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
// format and write message
|
||||||
|
var format = process.stderr.isTTY |
||||||
|
? formatColor |
||||||
|
: formatPlain |
||||||
|
var output = format.call(this, msg, caller, stack.slice(i)) |
||||||
|
process.stderr.write(output + '\n', 'utf8') |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get call site location as array. |
||||||
|
*/ |
||||||
|
|
||||||
|
function callSiteLocation (callSite) { |
||||||
|
var file = callSite.getFileName() || '<anonymous>' |
||||||
|
var line = callSite.getLineNumber() |
||||||
|
var colm = callSite.getColumnNumber() |
||||||
|
|
||||||
|
if (callSite.isEval()) { |
||||||
|
file = callSite.getEvalOrigin() + ', ' + file |
||||||
|
} |
||||||
|
|
||||||
|
var site = [file, line, colm] |
||||||
|
|
||||||
|
site.callSite = callSite |
||||||
|
site.name = callSite.getFunctionName() |
||||||
|
|
||||||
|
return site |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Generate a default message from the site. |
||||||
|
*/ |
||||||
|
|
||||||
|
function defaultMessage (site) { |
||||||
|
var callSite = site.callSite |
||||||
|
var funcName = site.name |
||||||
|
|
||||||
|
// make useful anonymous name
|
||||||
|
if (!funcName) { |
||||||
|
funcName = '<anonymous@' + formatLocation(site) + '>' |
||||||
|
} |
||||||
|
|
||||||
|
var context = callSite.getThis() |
||||||
|
var typeName = context && callSite.getTypeName() |
||||||
|
|
||||||
|
// ignore useless type name
|
||||||
|
if (typeName === 'Object') { |
||||||
|
typeName = undefined |
||||||
|
} |
||||||
|
|
||||||
|
// make useful type name
|
||||||
|
if (typeName === 'Function') { |
||||||
|
typeName = context.name || typeName |
||||||
|
} |
||||||
|
|
||||||
|
return typeName && callSite.getMethodName() |
||||||
|
? typeName + '.' + funcName |
||||||
|
: funcName |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Format deprecation message without color. |
||||||
|
*/ |
||||||
|
|
||||||
|
function formatPlain (msg, caller, stack) { |
||||||
|
var timestamp = new Date().toUTCString() |
||||||
|
|
||||||
|
var formatted = timestamp + |
||||||
|
' ' + this._namespace + |
||||||
|
' deprecated ' + msg |
||||||
|
|
||||||
|
// add stack trace
|
||||||
|
if (this._traced) { |
||||||
|
for (var i = 0; i < stack.length; i++) { |
||||||
|
formatted += '\n at ' + stack[i].toString() |
||||||
|
} |
||||||
|
|
||||||
|
return formatted |
||||||
|
} |
||||||
|
|
||||||
|
if (caller) { |
||||||
|
formatted += ' at ' + formatLocation(caller) |
||||||
|
} |
||||||
|
|
||||||
|
return formatted |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Format deprecation message with color. |
||||||
|
*/ |
||||||
|
|
||||||
|
function formatColor (msg, caller, stack) { |
||||||
|
var formatted = '\x1b[36;1m' + this._namespace + '\x1b[22;39m' + // bold cyan
|
||||||
|
' \x1b[33;1mdeprecated\x1b[22;39m' + // bold yellow
|
||||||
|
' \x1b[0m' + msg + '\x1b[39m' // reset
|
||||||
|
|
||||||
|
// add stack trace
|
||||||
|
if (this._traced) { |
||||||
|
for (var i = 0; i < stack.length; i++) { |
||||||
|
formatted += '\n \x1b[36mat ' + stack[i].toString() + '\x1b[39m' // cyan
|
||||||
|
} |
||||||
|
|
||||||
|
return formatted |
||||||
|
} |
||||||
|
|
||||||
|
if (caller) { |
||||||
|
formatted += ' \x1b[36m' + formatLocation(caller) + '\x1b[39m' // cyan
|
||||||
|
} |
||||||
|
|
||||||
|
return formatted |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Format call site location. |
||||||
|
*/ |
||||||
|
|
||||||
|
function formatLocation (callSite) { |
||||||
|
return relative(basePath, callSite[0]) + |
||||||
|
':' + callSite[1] + |
||||||
|
':' + callSite[2] |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get the stack as array of call sites. |
||||||
|
*/ |
||||||
|
|
||||||
|
function getStack () { |
||||||
|
var limit = Error.stackTraceLimit |
||||||
|
var obj = {} |
||||||
|
var prep = Error.prepareStackTrace |
||||||
|
|
||||||
|
Error.prepareStackTrace = prepareObjectStackTrace |
||||||
|
Error.stackTraceLimit = Math.max(10, limit) |
||||||
|
|
||||||
|
// capture the stack
|
||||||
|
Error.captureStackTrace(obj) |
||||||
|
|
||||||
|
// slice this function off the top
|
||||||
|
var stack = obj.stack.slice(1) |
||||||
|
|
||||||
|
Error.prepareStackTrace = prep |
||||||
|
Error.stackTraceLimit = limit |
||||||
|
|
||||||
|
return stack |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Capture call site stack from v8. |
||||||
|
*/ |
||||||
|
|
||||||
|
function prepareObjectStackTrace (obj, stack) { |
||||||
|
return stack |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return a wrapped function in a deprecation message. |
||||||
|
*/ |
||||||
|
|
||||||
|
function wrapfunction (fn, message) { |
||||||
|
if (typeof fn !== 'function') { |
||||||
|
throw new TypeError('argument fn must be a function') |
||||||
|
} |
||||||
|
|
||||||
|
var args = createArgumentsString(fn.length) |
||||||
|
var stack = getStack() |
||||||
|
var site = callSiteLocation(stack[1]) |
||||||
|
|
||||||
|
site.name = fn.name |
||||||
|
|
||||||
|
// eslint-disable-next-line no-new-func
|
||||||
|
var deprecatedfn = new Function('fn', 'log', 'deprecate', 'message', 'site', |
||||||
|
'"use strict"\n' + |
||||||
|
'return function (' + args + ') {' + |
||||||
|
'log.call(deprecate, message, site)\n' + |
||||||
|
'return fn.apply(this, arguments)\n' + |
||||||
|
'}')(fn, log, this, message, site) |
||||||
|
|
||||||
|
return deprecatedfn |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Wrap property in a deprecation message. |
||||||
|
*/ |
||||||
|
|
||||||
|
function wrapproperty (obj, prop, message) { |
||||||
|
if (!obj || (typeof obj !== 'object' && typeof obj !== 'function')) { |
||||||
|
throw new TypeError('argument obj must be object') |
||||||
|
} |
||||||
|
|
||||||
|
var descriptor = Object.getOwnPropertyDescriptor(obj, prop) |
||||||
|
|
||||||
|
if (!descriptor) { |
||||||
|
throw new TypeError('must call property on owner object') |
||||||
|
} |
||||||
|
|
||||||
|
if (!descriptor.configurable) { |
||||||
|
throw new TypeError('property must be configurable') |
||||||
|
} |
||||||
|
|
||||||
|
var deprecate = this |
||||||
|
var stack = getStack() |
||||||
|
var site = callSiteLocation(stack[1]) |
||||||
|
|
||||||
|
// set site name
|
||||||
|
site.name = prop |
||||||
|
|
||||||
|
// convert data descriptor
|
||||||
|
if ('value' in descriptor) { |
||||||
|
descriptor = convertDataDescriptorToAccessor(obj, prop, message) |
||||||
|
} |
||||||
|
|
||||||
|
var get = descriptor.get |
||||||
|
var set = descriptor.set |
||||||
|
|
||||||
|
// wrap getter
|
||||||
|
if (typeof get === 'function') { |
||||||
|
descriptor.get = function getter () { |
||||||
|
log.call(deprecate, message, site) |
||||||
|
return get.apply(this, arguments) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// wrap setter
|
||||||
|
if (typeof set === 'function') { |
||||||
|
descriptor.set = function setter () { |
||||||
|
log.call(deprecate, message, site) |
||||||
|
return set.apply(this, arguments) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
Object.defineProperty(obj, prop, descriptor) |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create DeprecationError for deprecation |
||||||
|
*/ |
||||||
|
|
||||||
|
function DeprecationError (namespace, message, stack) { |
||||||
|
var error = new Error() |
||||||
|
var stackString |
||||||
|
|
||||||
|
Object.defineProperty(error, 'constructor', { |
||||||
|
value: DeprecationError |
||||||
|
}) |
||||||
|
|
||||||
|
Object.defineProperty(error, 'message', { |
||||||
|
configurable: true, |
||||||
|
enumerable: false, |
||||||
|
value: message, |
||||||
|
writable: true |
||||||
|
}) |
||||||
|
|
||||||
|
Object.defineProperty(error, 'name', { |
||||||
|
enumerable: false, |
||||||
|
configurable: true, |
||||||
|
value: 'DeprecationError', |
||||||
|
writable: true |
||||||
|
}) |
||||||
|
|
||||||
|
Object.defineProperty(error, 'namespace', { |
||||||
|
configurable: true, |
||||||
|
enumerable: false, |
||||||
|
value: namespace, |
||||||
|
writable: true |
||||||
|
}) |
||||||
|
|
||||||
|
Object.defineProperty(error, 'stack', { |
||||||
|
configurable: true, |
||||||
|
enumerable: false, |
||||||
|
get: function () { |
||||||
|
if (stackString !== undefined) { |
||||||
|
return stackString |
||||||
|
} |
||||||
|
|
||||||
|
// prepare stack trace
|
||||||
|
return (stackString = createStackString.call(this, stack)) |
||||||
|
}, |
||||||
|
set: function setter (val) { |
||||||
|
stackString = val |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
return error |
||||||
|
} |
@ -0,0 +1,77 @@ |
|||||||
|
/*! |
||||||
|
* depd |
||||||
|
* Copyright(c) 2015 Douglas Christopher Wilson |
||||||
|
* MIT Licensed |
||||||
|
*/ |
||||||
|
|
||||||
|
'use strict' |
||||||
|
|
||||||
|
/** |
||||||
|
* Module exports. |
||||||
|
* @public |
||||||
|
*/ |
||||||
|
|
||||||
|
module.exports = depd |
||||||
|
|
||||||
|
/** |
||||||
|
* Create deprecate for namespace in caller. |
||||||
|
*/ |
||||||
|
|
||||||
|
function depd (namespace) { |
||||||
|
if (!namespace) { |
||||||
|
throw new TypeError('argument namespace is required') |
||||||
|
} |
||||||
|
|
||||||
|
function deprecate (message) { |
||||||
|
// no-op in browser
|
||||||
|
} |
||||||
|
|
||||||
|
deprecate._file = undefined |
||||||
|
deprecate._ignored = true |
||||||
|
deprecate._namespace = namespace |
||||||
|
deprecate._traced = false |
||||||
|
deprecate._warned = Object.create(null) |
||||||
|
|
||||||
|
deprecate.function = wrapfunction |
||||||
|
deprecate.property = wrapproperty |
||||||
|
|
||||||
|
return deprecate |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return a wrapped function in a deprecation message. |
||||||
|
* |
||||||
|
* This is a no-op version of the wrapper, which does nothing but call |
||||||
|
* validation. |
||||||
|
*/ |
||||||
|
|
||||||
|
function wrapfunction (fn, message) { |
||||||
|
if (typeof fn !== 'function') { |
||||||
|
throw new TypeError('argument fn must be a function') |
||||||
|
} |
||||||
|
|
||||||
|
return fn |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Wrap property in a deprecation message. |
||||||
|
* |
||||||
|
* This is a no-op version of the wrapper, which does nothing but call |
||||||
|
* validation. |
||||||
|
*/ |
||||||
|
|
||||||
|
function wrapproperty (obj, prop, message) { |
||||||
|
if (!obj || (typeof obj !== 'object' && typeof obj !== 'function')) { |
||||||
|
throw new TypeError('argument obj must be object') |
||||||
|
} |
||||||
|
|
||||||
|
var descriptor = Object.getOwnPropertyDescriptor(obj, prop) |
||||||
|
|
||||||
|
if (!descriptor) { |
||||||
|
throw new TypeError('must call property on owner object') |
||||||
|
} |
||||||
|
|
||||||
|
if (!descriptor.configurable) { |
||||||
|
throw new TypeError('property must be configurable') |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,45 @@ |
|||||||
|
{ |
||||||
|
"name": "depd", |
||||||
|
"description": "Deprecate all the things", |
||||||
|
"version": "2.0.0", |
||||||
|
"author": "Douglas Christopher Wilson <doug@somethingdoug.com>", |
||||||
|
"license": "MIT", |
||||||
|
"keywords": [ |
||||||
|
"deprecate", |
||||||
|
"deprecated" |
||||||
|
], |
||||||
|
"repository": "dougwilson/nodejs-depd", |
||||||
|
"browser": "lib/browser/index.js", |
||||||
|
"devDependencies": { |
||||||
|
"benchmark": "2.1.4", |
||||||
|
"beautify-benchmark": "0.2.4", |
||||||
|
"eslint": "5.7.0", |
||||||
|
"eslint-config-standard": "12.0.0", |
||||||
|
"eslint-plugin-import": "2.14.0", |
||||||
|
"eslint-plugin-markdown": "1.0.0-beta.7", |
||||||
|
"eslint-plugin-node": "7.0.1", |
||||||
|
"eslint-plugin-promise": "4.0.1", |
||||||
|
"eslint-plugin-standard": "4.0.0", |
||||||
|
"istanbul": "0.4.5", |
||||||
|
"mocha": "5.2.0", |
||||||
|
"safe-buffer": "5.1.2", |
||||||
|
"uid-safe": "2.1.5" |
||||||
|
}, |
||||||
|
"files": [ |
||||||
|
"lib/", |
||||||
|
"History.md", |
||||||
|
"LICENSE", |
||||||
|
"index.js", |
||||||
|
"Readme.md" |
||||||
|
], |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.8" |
||||||
|
}, |
||||||
|
"scripts": { |
||||||
|
"bench": "node benchmark/index.js", |
||||||
|
"lint": "eslint --plugin markdown --ext js,md .", |
||||||
|
"test": "mocha --reporter spec --bail test/", |
||||||
|
"test-ci": "istanbul cover --print=none node_modules/mocha/bin/_mocha -- --reporter spec test/ && istanbul report lcovonly text-summary", |
||||||
|
"test-cov": "istanbul cover --print=none node_modules/mocha/bin/_mocha -- --reporter dot test/ && istanbul report lcov text-summary" |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,23 @@ |
|||||||
|
|
||||||
|
The MIT License (MIT) |
||||||
|
|
||||||
|
Copyright (c) 2014 Jonathan Ong me@jongleberry.com |
||||||
|
Copyright (c) 2015-2022 Douglas Christopher Wilson doug@somethingdoug.com |
||||||
|
|
||||||
|
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. |
@ -0,0 +1,63 @@ |
|||||||
|
# destroy |
||||||
|
|
||||||
|
[![NPM version][npm-image]][npm-url] |
||||||
|
[![Build Status][github-actions-ci-image]][github-actions-ci-url] |
||||||
|
[![Test coverage][coveralls-image]][coveralls-url] |
||||||
|
[![License][license-image]][license-url] |
||||||
|
[![Downloads][downloads-image]][downloads-url] |
||||||
|
|
||||||
|
Destroy a stream. |
||||||
|
|
||||||
|
This module is meant to ensure a stream gets destroyed, handling different APIs |
||||||
|
and Node.js bugs. |
||||||
|
|
||||||
|
## API |
||||||
|
|
||||||
|
```js |
||||||
|
var destroy = require('destroy') |
||||||
|
``` |
||||||
|
|
||||||
|
### destroy(stream [, suppress]) |
||||||
|
|
||||||
|
Destroy the given stream, and optionally suppress any future `error` events. |
||||||
|
|
||||||
|
In most cases, this is identical to a simple `stream.destroy()` call. The rules |
||||||
|
are as follows for a given stream: |
||||||
|
|
||||||
|
1. If the `stream` is an instance of `ReadStream`, then call `stream.destroy()` |
||||||
|
and add a listener to the `open` event to call `stream.close()` if it is |
||||||
|
fired. This is for a Node.js bug that will leak a file descriptor if |
||||||
|
`.destroy()` is called before `open`. |
||||||
|
2. If the `stream` is an instance of a zlib stream, then call `stream.destroy()` |
||||||
|
and close the underlying zlib handle if open, otherwise call `stream.close()`. |
||||||
|
This is for consistency across Node.js versions and a Node.js bug that will |
||||||
|
leak a native zlib handle. |
||||||
|
3. If the `stream` is not an instance of `Stream`, then nothing happens. |
||||||
|
4. If the `stream` has a `.destroy()` method, then call it. |
||||||
|
|
||||||
|
The function returns the `stream` passed in as the argument. |
||||||
|
|
||||||
|
## Example |
||||||
|
|
||||||
|
```js |
||||||
|
var destroy = require('destroy') |
||||||
|
|
||||||
|
var fs = require('fs') |
||||||
|
var stream = fs.createReadStream('package.json') |
||||||
|
|
||||||
|
// ... and later |
||||||
|
destroy(stream) |
||||||
|
``` |
||||||
|
|
||||||
|
[npm-image]: https://img.shields.io/npm/v/destroy.svg?style=flat-square |
||||||
|
[npm-url]: https://npmjs.org/package/destroy |
||||||
|
[github-tag]: http://img.shields.io/github/tag/stream-utils/destroy.svg?style=flat-square |
||||||
|
[github-url]: https://github.com/stream-utils/destroy/tags |
||||||
|
[coveralls-image]: https://img.shields.io/coveralls/stream-utils/destroy.svg?style=flat-square |
||||||
|
[coveralls-url]: https://coveralls.io/r/stream-utils/destroy?branch=master |
||||||
|
[license-image]: http://img.shields.io/npm/l/destroy.svg?style=flat-square |
||||||
|
[license-url]: LICENSE.md |
||||||
|
[downloads-image]: http://img.shields.io/npm/dm/destroy.svg?style=flat-square |
||||||
|
[downloads-url]: https://npmjs.org/package/destroy |
||||||
|
[github-actions-ci-image]: https://img.shields.io/github/workflow/status/stream-utils/destroy/ci/master?label=ci&style=flat-square |
||||||
|
[github-actions-ci-url]: https://github.com/stream-utils/destroy/actions/workflows/ci.yml |
@ -0,0 +1,209 @@ |
|||||||
|
/*! |
||||||
|
* destroy |
||||||
|
* Copyright(c) 2014 Jonathan Ong |
||||||
|
* Copyright(c) 2015-2022 Douglas Christopher Wilson |
||||||
|
* MIT Licensed |
||||||
|
*/ |
||||||
|
|
||||||
|
'use strict' |
||||||
|
|
||||||
|
/** |
||||||
|
* Module dependencies. |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
var EventEmitter = require('events').EventEmitter |
||||||
|
var ReadStream = require('fs').ReadStream |
||||||
|
var Stream = require('stream') |
||||||
|
var Zlib = require('zlib') |
||||||
|
|
||||||
|
/** |
||||||
|
* Module exports. |
||||||
|
* @public |
||||||
|
*/ |
||||||
|
|
||||||
|
module.exports = destroy |
||||||
|
|
||||||
|
/** |
||||||
|
* Destroy the given stream, and optionally suppress any future `error` events. |
||||||
|
* |
||||||
|
* @param {object} stream |
||||||
|
* @param {boolean} suppress |
||||||
|
* @public |
||||||
|
*/ |
||||||
|
|
||||||
|
function destroy (stream, suppress) { |
||||||
|
if (isFsReadStream(stream)) { |
||||||
|
destroyReadStream(stream) |
||||||
|
} else if (isZlibStream(stream)) { |
||||||
|
destroyZlibStream(stream) |
||||||
|
} else if (hasDestroy(stream)) { |
||||||
|
stream.destroy() |
||||||
|
} |
||||||
|
|
||||||
|
if (isEventEmitter(stream) && suppress) { |
||||||
|
stream.removeAllListeners('error') |
||||||
|
stream.addListener('error', noop) |
||||||
|
} |
||||||
|
|
||||||
|
return stream |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Destroy a ReadStream. |
||||||
|
* |
||||||
|
* @param {object} stream |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
function destroyReadStream (stream) { |
||||||
|
stream.destroy() |
||||||
|
|
||||||
|
if (typeof stream.close === 'function') { |
||||||
|
// node.js core bug work-around
|
||||||
|
stream.on('open', onOpenClose) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Close a Zlib stream. |
||||||
|
* |
||||||
|
* Zlib streams below Node.js 4.5.5 have a buggy implementation |
||||||
|
* of .close() when zlib encountered an error. |
||||||
|
* |
||||||
|
* @param {object} stream |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
function closeZlibStream (stream) { |
||||||
|
if (stream._hadError === true) { |
||||||
|
var prop = stream._binding === null |
||||||
|
? '_binding' |
||||||
|
: '_handle' |
||||||
|
|
||||||
|
stream[prop] = { |
||||||
|
close: function () { this[prop] = null } |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
stream.close() |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Destroy a Zlib stream. |
||||||
|
* |
||||||
|
* Zlib streams don't have a destroy function in Node.js 6. On top of that |
||||||
|
* simply calling destroy on a zlib stream in Node.js 8+ will result in a |
||||||
|
* memory leak. So until that is fixed, we need to call both close AND destroy. |
||||||
|
* |
||||||
|
* PR to fix memory leak: https://github.com/nodejs/node/pull/23734
|
||||||
|
* |
||||||
|
* In Node.js 6+8, it's important that destroy is called before close as the |
||||||
|
* stream would otherwise emit the error 'zlib binding closed'. |
||||||
|
* |
||||||
|
* @param {object} stream |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
function destroyZlibStream (stream) { |
||||||
|
if (typeof stream.destroy === 'function') { |
||||||
|
// node.js core bug work-around
|
||||||
|
// istanbul ignore if: node.js 0.8
|
||||||
|
if (stream._binding) { |
||||||
|
// node.js < 0.10.0
|
||||||
|
stream.destroy() |
||||||
|
if (stream._processing) { |
||||||
|
stream._needDrain = true |
||||||
|
stream.once('drain', onDrainClearBinding) |
||||||
|
} else { |
||||||
|
stream._binding.clear() |
||||||
|
} |
||||||
|
} else if (stream._destroy && stream._destroy !== Stream.Transform.prototype._destroy) { |
||||||
|
// node.js >= 12, ^11.1.0, ^10.15.1
|
||||||
|
stream.destroy() |
||||||
|
} else if (stream._destroy && typeof stream.close === 'function') { |
||||||
|
// node.js 7, 8
|
||||||
|
stream.destroyed = true |
||||||
|
stream.close() |
||||||
|
} else { |
||||||
|
// fallback
|
||||||
|
// istanbul ignore next
|
||||||
|
stream.destroy() |
||||||
|
} |
||||||
|
} else if (typeof stream.close === 'function') { |
||||||
|
// node.js < 8 fallback
|
||||||
|
closeZlibStream(stream) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Determine if stream has destroy. |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
function hasDestroy (stream) { |
||||||
|
return stream instanceof Stream && |
||||||
|
typeof stream.destroy === 'function' |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Determine if val is EventEmitter. |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
function isEventEmitter (val) { |
||||||
|
return val instanceof EventEmitter |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Determine if stream is fs.ReadStream stream. |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
function isFsReadStream (stream) { |
||||||
|
return stream instanceof ReadStream |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Determine if stream is Zlib stream. |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
function isZlibStream (stream) { |
||||||
|
return stream instanceof Zlib.Gzip || |
||||||
|
stream instanceof Zlib.Gunzip || |
||||||
|
stream instanceof Zlib.Deflate || |
||||||
|
stream instanceof Zlib.DeflateRaw || |
||||||
|
stream instanceof Zlib.Inflate || |
||||||
|
stream instanceof Zlib.InflateRaw || |
||||||
|
stream instanceof Zlib.Unzip |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* No-op function. |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
function noop () {} |
||||||
|
|
||||||
|
/** |
||||||
|
* On drain handler to clear binding. |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
// istanbul ignore next: node.js 0.8
|
||||||
|
function onDrainClearBinding () { |
||||||
|
this._binding.clear() |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* On open handler to close stream. |
||||||
|
* @private |
||||||
|
*/ |
||||||
|
|
||||||
|
function onOpenClose () { |
||||||
|
if (typeof this.fd === 'number') { |
||||||
|
// actually close down the fd
|
||||||
|
this.close() |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,48 @@ |
|||||||
|
{ |
||||||
|
"name": "destroy", |
||||||
|
"description": "destroy a stream if possible", |
||||||
|
"version": "1.2.0", |
||||||
|
"author": { |
||||||
|
"name": "Jonathan Ong", |
||||||
|
"email": "me@jongleberry.com", |
||||||
|
"url": "http://jongleberry.com", |
||||||
|
"twitter": "https://twitter.com/jongleberry" |
||||||
|
}, |
||||||
|
"contributors": [ |
||||||
|
"Douglas Christopher Wilson <doug@somethingdoug.com>" |
||||||
|
], |
||||||
|
"license": "MIT", |
||||||
|
"repository": "stream-utils/destroy", |
||||||
|
"devDependencies": { |
||||||
|
"eslint": "7.32.0", |
||||||
|
"eslint-config-standard": "14.1.1", |
||||||
|
"eslint-plugin-import": "2.25.4", |
||||||
|
"eslint-plugin-node": "11.1.0", |
||||||
|
"eslint-plugin-promise": "5.2.0", |
||||||
|
"eslint-plugin-standard": "4.1.0", |
||||||
|
"mocha": "9.2.2", |
||||||
|
"nyc": "15.1.0" |
||||||
|
}, |
||||||
|
"engines": { |
||||||
|
"node": ">= 0.8", |
||||||
|
"npm": "1.2.8000 || >= 1.4.16" |
||||||
|
}, |
||||||
|
"scripts": { |
||||||
|
"lint": "eslint .", |
||||||
|
"test": "mocha --reporter spec", |
||||||
|
"test-ci": "nyc --reporter=lcovonly --reporter=text npm test", |
||||||
|
"test-cov": "nyc --reporter=html --reporter=text npm test" |
||||||
|
}, |
||||||
|
"files": [ |
||||||
|
"index.js", |
||||||
|
"LICENSE" |
||||||
|
], |
||||||
|
"keywords": [ |
||||||
|
"stream", |
||||||
|
"streams", |
||||||
|
"destroy", |
||||||
|
"cleanup", |
||||||
|
"leak", |
||||||
|
"fd" |
||||||
|
] |
||||||
|
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue