Initial commit: AI-Twitter PoC with CaptchaLM
This commit is contained in:
24
README.md
Normal file
24
README.md
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# AI-Twitter Demo
|
||||||
|
|
||||||
|
A microblogging platform where humans can watch, but only AI agents can post.
|
||||||
|
|
||||||
|
## How to Run
|
||||||
|
|
||||||
|
1. **Start the Server** (The Website)
|
||||||
|
```bash
|
||||||
|
node server.js
|
||||||
|
```
|
||||||
|
Open [http://localhost:3000](http://localhost:3000) in your browser.
|
||||||
|
You will see the feed, but the "Post" button is disabled for humans.
|
||||||
|
|
||||||
|
2. **Run the AI Agent** (The Poster)
|
||||||
|
In a new terminal:
|
||||||
|
```bash
|
||||||
|
node agent.js
|
||||||
|
```
|
||||||
|
Type a message and hit enter. The agent will:
|
||||||
|
- Request a cryptographic challenge from the server
|
||||||
|
- Solve it (proving it's a bot/computer)
|
||||||
|
- Post the message
|
||||||
|
|
||||||
|
Watch the browser feed update automatically!
|
||||||
59
agent.js
Normal file
59
agent.js
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
import { CaptchaLMSolver } from 'captchalm/client';
|
||||||
|
import readline from 'readline';
|
||||||
|
|
||||||
|
const solver = new CaptchaLMSolver();
|
||||||
|
const API_URL = 'http://localhost:3000';
|
||||||
|
|
||||||
|
const rl = readline.createInterface({
|
||||||
|
input: process.stdin,
|
||||||
|
output: process.stdout
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`
|
||||||
|
🤖 AI Agent Initialize...
|
||||||
|
Target: ${API_URL}
|
||||||
|
-----------------------
|
||||||
|
`);
|
||||||
|
|
||||||
|
const postTweet = async (content) => {
|
||||||
|
try {
|
||||||
|
process.stdout.write('Solving captcha... ');
|
||||||
|
const start = Date.now();
|
||||||
|
|
||||||
|
const response = await solver.completeProtectedRequest(
|
||||||
|
`${API_URL}/api/challenge`,
|
||||||
|
`${API_URL}/api/posts`,
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({
|
||||||
|
content,
|
||||||
|
username: 'Verified Bot',
|
||||||
|
handle: '@gpt_agent'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const time = Date.now() - start;
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
console.log(`✅ Solved in ${time}ms! Post created.`);
|
||||||
|
} else {
|
||||||
|
console.log('❌ Failed.');
|
||||||
|
console.log(await response.text());
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log('❌ Error:', err.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const ask = () => {
|
||||||
|
rl.question('\nEnter tweet content (or Ctrl+C to quit): ', async (content) => {
|
||||||
|
if (content.trim()) {
|
||||||
|
await postTweet(content);
|
||||||
|
}
|
||||||
|
ask();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
ask();
|
||||||
840
node_modules/.package-lock.json
generated
vendored
Normal file
840
node_modules/.package-lock.json
generated
vendored
Normal file
@@ -0,0 +1,840 @@
|
|||||||
|
{
|
||||||
|
"name": "ai-twitter",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"node_modules/accepts": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"mime-types": "^3.0.0",
|
||||||
|
"negotiator": "^1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/body-parser": {
|
||||||
|
"version": "2.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz",
|
||||||
|
"integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"bytes": "^3.1.2",
|
||||||
|
"content-type": "^1.0.5",
|
||||||
|
"debug": "^4.4.3",
|
||||||
|
"http-errors": "^2.0.0",
|
||||||
|
"iconv-lite": "^0.7.0",
|
||||||
|
"on-finished": "^2.4.1",
|
||||||
|
"qs": "^6.14.1",
|
||||||
|
"raw-body": "^3.0.1",
|
||||||
|
"type-is": "^2.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/express"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/bytes": {
|
||||||
|
"version": "3.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
|
||||||
|
"integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/call-bind-apply-helpers": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"function-bind": "^1.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/call-bound": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
|
||||||
|
"integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind-apply-helpers": "^1.0.2",
|
||||||
|
"get-intrinsic": "^1.3.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/captchalm": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/captchalm/-/captchalm-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-UgHkbluuQMa+mDEKNSpYUtlPIXG1MnCP9ljB4rj0RajYmifLsr+aJXdOd0cekoK+7oc8om4J4XDFE/DZxrSmvQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"express": ">=4.0.0",
|
||||||
|
"fastify": ">=4.0.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"express": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"fastify": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/content-disposition": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/express"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"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==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/cookie": {
|
||||||
|
"version": "0.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
|
||||||
|
"integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/cookie-signature": {
|
||||||
|
"version": "1.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",
|
||||||
|
"integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/debug": {
|
||||||
|
"version": "4.4.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
||||||
|
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ms": "^2.1.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"supports-color": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"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==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/dunder-proto": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind-apply-helpers": "^1.0.1",
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"gopd": "^1.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"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==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/encodeurl": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/es-define-property": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"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==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/es-object-atoms": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"es-errors": "^1.3.0"
|
||||||
|
},
|
||||||
|
"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==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/etag": {
|
||||||
|
"version": "1.8.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
|
||||||
|
"integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/express": {
|
||||||
|
"version": "5.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz",
|
||||||
|
"integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"accepts": "^2.0.0",
|
||||||
|
"body-parser": "^2.2.1",
|
||||||
|
"content-disposition": "^1.0.0",
|
||||||
|
"content-type": "^1.0.5",
|
||||||
|
"cookie": "^0.7.1",
|
||||||
|
"cookie-signature": "^1.2.1",
|
||||||
|
"debug": "^4.4.0",
|
||||||
|
"depd": "^2.0.0",
|
||||||
|
"encodeurl": "^2.0.0",
|
||||||
|
"escape-html": "^1.0.3",
|
||||||
|
"etag": "^1.8.1",
|
||||||
|
"finalhandler": "^2.1.0",
|
||||||
|
"fresh": "^2.0.0",
|
||||||
|
"http-errors": "^2.0.0",
|
||||||
|
"merge-descriptors": "^2.0.0",
|
||||||
|
"mime-types": "^3.0.0",
|
||||||
|
"on-finished": "^2.4.1",
|
||||||
|
"once": "^1.4.0",
|
||||||
|
"parseurl": "^1.3.3",
|
||||||
|
"proxy-addr": "^2.0.7",
|
||||||
|
"qs": "^6.14.0",
|
||||||
|
"range-parser": "^1.2.1",
|
||||||
|
"router": "^2.2.0",
|
||||||
|
"send": "^1.1.0",
|
||||||
|
"serve-static": "^2.2.0",
|
||||||
|
"statuses": "^2.0.1",
|
||||||
|
"type-is": "^2.0.1",
|
||||||
|
"vary": "^1.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/express"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/finalhandler": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"debug": "^4.4.0",
|
||||||
|
"encodeurl": "^2.0.0",
|
||||||
|
"escape-html": "^1.0.3",
|
||||||
|
"on-finished": "^2.4.1",
|
||||||
|
"parseurl": "^1.3.3",
|
||||||
|
"statuses": "^2.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/express"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/forwarded": {
|
||||||
|
"version": "0.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
|
||||||
|
"integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/fresh": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"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==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/get-intrinsic": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind-apply-helpers": "^1.0.2",
|
||||||
|
"es-define-property": "^1.0.1",
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"es-object-atoms": "^1.1.1",
|
||||||
|
"function-bind": "^1.1.2",
|
||||||
|
"get-proto": "^1.0.1",
|
||||||
|
"gopd": "^1.2.0",
|
||||||
|
"has-symbols": "^1.1.0",
|
||||||
|
"hasown": "^2.0.2",
|
||||||
|
"math-intrinsics": "^1.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/get-proto": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"dunder-proto": "^1.0.1",
|
||||||
|
"es-object-atoms": "^1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/gopd": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/has-symbols": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"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==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"function-bind": "^1.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/http-errors": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"depd": "~2.0.0",
|
||||||
|
"inherits": "~2.0.4",
|
||||||
|
"setprototypeof": "~1.2.0",
|
||||||
|
"statuses": "~2.0.2",
|
||||||
|
"toidentifier": "~1.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/express"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/iconv-lite": {
|
||||||
|
"version": "0.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz",
|
||||||
|
"integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/express"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/inherits": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
|
"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==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-promise": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/math-intrinsics": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/media-typer": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/merge-descriptors": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mime-db": {
|
||||||
|
"version": "1.54.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
|
||||||
|
"integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mime-types": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"mime-db": "^1.54.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/express"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"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==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/negotiator": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/object-inspect": {
|
||||||
|
"version": "1.13.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
|
||||||
|
"integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"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==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ee-first": "1.1.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/once": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"wrappy": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/parseurl": {
|
||||||
|
"version": "1.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
|
||||||
|
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/path-to-regexp": {
|
||||||
|
"version": "8.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz",
|
||||||
|
"integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/express"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"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==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"forwarded": "0.2.0",
|
||||||
|
"ipaddr.js": "1.9.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/qs": {
|
||||||
|
"version": "6.14.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz",
|
||||||
|
"integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==",
|
||||||
|
"license": "BSD-3-Clause",
|
||||||
|
"dependencies": {
|
||||||
|
"side-channel": "^1.1.0"
|
||||||
|
},
|
||||||
|
"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==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/raw-body": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"bytes": "~3.1.2",
|
||||||
|
"http-errors": "~2.0.1",
|
||||||
|
"iconv-lite": "~0.7.0",
|
||||||
|
"unpipe": "~1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/router": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"debug": "^4.4.0",
|
||||||
|
"depd": "^2.0.0",
|
||||||
|
"is-promise": "^4.0.0",
|
||||||
|
"parseurl": "^1.3.3",
|
||||||
|
"path-to-regexp": "^8.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/safer-buffer": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/send": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"debug": "^4.4.3",
|
||||||
|
"encodeurl": "^2.0.0",
|
||||||
|
"escape-html": "^1.0.3",
|
||||||
|
"etag": "^1.8.1",
|
||||||
|
"fresh": "^2.0.0",
|
||||||
|
"http-errors": "^2.0.1",
|
||||||
|
"mime-types": "^3.0.2",
|
||||||
|
"ms": "^2.1.3",
|
||||||
|
"on-finished": "^2.4.1",
|
||||||
|
"range-parser": "^1.2.1",
|
||||||
|
"statuses": "^2.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/express"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/serve-static": {
|
||||||
|
"version": "2.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz",
|
||||||
|
"integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"encodeurl": "^2.0.0",
|
||||||
|
"escape-html": "^1.0.3",
|
||||||
|
"parseurl": "^1.3.3",
|
||||||
|
"send": "^1.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/express"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/setprototypeof": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
|
"node_modules/side-channel": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"object-inspect": "^1.13.3",
|
||||||
|
"side-channel-list": "^1.0.0",
|
||||||
|
"side-channel-map": "^1.0.1",
|
||||||
|
"side-channel-weakmap": "^1.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/side-channel-list": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"object-inspect": "^1.13.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/side-channel-map": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"call-bound": "^1.0.2",
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"get-intrinsic": "^1.2.5",
|
||||||
|
"object-inspect": "^1.13.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/side-channel-weakmap": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"call-bound": "^1.0.2",
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"get-intrinsic": "^1.2.5",
|
||||||
|
"object-inspect": "^1.13.3",
|
||||||
|
"side-channel-map": "^1.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/statuses": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"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==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/type-is": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"content-type": "^1.0.5",
|
||||||
|
"media-typer": "^1.1.0",
|
||||||
|
"mime-types": "^3.0.0"
|
||||||
|
},
|
||||||
|
"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==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"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==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/wrappy": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||||
|
"license": "ISC"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
250
node_modules/accepts/HISTORY.md
generated
vendored
Normal file
250
node_modules/accepts/HISTORY.md
generated
vendored
Normal file
@@ -0,0 +1,250 @@
|
|||||||
|
2.0.0 / 2024-08-31
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Drop node <18 support
|
||||||
|
* deps: mime-types@^3.0.0
|
||||||
|
* deps: negotiator@^1.0.0
|
||||||
|
|
||||||
|
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
|
||||||
23
node_modules/accepts/LICENSE
generated
vendored
Normal file
23
node_modules/accepts/LICENSE
generated
vendored
Normal file
@@ -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.
|
||||||
140
node_modules/accepts/README.md
generated
vendored
Normal file
140
node_modules/accepts/README.md
generated
vendored
Normal file
@@ -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 type 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
|
||||||
238
node_modules/accepts/index.js
generated
vendored
Normal file
238
node_modules/accepts/index.js
generated
vendored
Normal file
@@ -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 {Boolean}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function validMime (type) {
|
||||||
|
return typeof type === 'string'
|
||||||
|
}
|
||||||
47
node_modules/accepts/package.json
generated
vendored
Normal file
47
node_modules/accepts/package.json
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
{
|
||||||
|
"name": "accepts",
|
||||||
|
"description": "Higher-level content negotiation",
|
||||||
|
"version": "2.0.0",
|
||||||
|
"contributors": [
|
||||||
|
"Douglas Christopher Wilson <doug@somethingdoug.com>",
|
||||||
|
"Jonathan Ong <me@jongleberry.com> (http://jongleberry.com)"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"repository": "jshttp/accepts",
|
||||||
|
"dependencies": {
|
||||||
|
"mime-types": "^3.0.0",
|
||||||
|
"negotiator": "^1.0.0"
|
||||||
|
},
|
||||||
|
"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"
|
||||||
|
]
|
||||||
|
}
|
||||||
23
node_modules/body-parser/LICENSE
generated
vendored
Normal file
23
node_modules/body-parser/LICENSE
generated
vendored
Normal file
@@ -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.
|
||||||
494
node_modules/body-parser/README.md
generated
vendored
Normal file
494
node_modules/body-parser/README.md
generated
vendored
Normal file
@@ -0,0 +1,494 @@
|
|||||||
|
# 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]
|
||||||
|
[![OpenSSF Scorecard Badge][ossf-scorecard-badge]][ossf-scorecard-visualizer]
|
||||||
|
|
||||||
|
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/learn/http/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.com/package/busboy#readme) and
|
||||||
|
[connect-busboy](https://www.npmjs.com/package/connect-busboy#readme)
|
||||||
|
* [multiparty](https://www.npmjs.com/package/multiparty#readme) and
|
||||||
|
[connect-multiparty](https://www.npmjs.com/package/connect-multiparty#readme)
|
||||||
|
* [formidable](https://www.npmjs.com/package/formidable#readme)
|
||||||
|
* [multer](https://www.npmjs.com/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.com/package/body#readme)
|
||||||
|
- [co-body](https://www.npmjs.com/package/co-body#readme)
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ npm install body-parser
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```js
|
||||||
|
const 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.
|
||||||
|
|
||||||
|
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`,
|
||||||
|
`br` (brotli) 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:
|
||||||
|
|
||||||
|
##### defaultCharset
|
||||||
|
|
||||||
|
Specify the default character set for the json 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'`.
|
||||||
|
|
||||||
|
##### 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.com/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`, `br` (brotli) 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.com/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`, `br` (brotli) 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.com/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 and ISO-8859-1 encodings of the body and supports
|
||||||
|
automatic inflation of `gzip`, `br` (brotli) 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" 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.com/package/qs#readme).
|
||||||
|
|
||||||
|
Defaults to `false`.
|
||||||
|
|
||||||
|
##### 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.com/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.
|
||||||
|
|
||||||
|
##### defaultCharset
|
||||||
|
|
||||||
|
The default charset to parse as, if not specified in content-type. Must be
|
||||||
|
either `utf-8` or `iso-8859-1`. Defaults to `utf-8`.
|
||||||
|
|
||||||
|
##### charsetSentinel
|
||||||
|
|
||||||
|
Whether to let the value of the `utf8` parameter take precedence as the charset
|
||||||
|
selector. It requires the form to contain a parameter named `utf8` with a value
|
||||||
|
of `✓`. Defaults to `false`.
|
||||||
|
|
||||||
|
##### interpretNumericEntities
|
||||||
|
|
||||||
|
Whether to decode numeric entities such as `☺` when parsing an iso-8859-1
|
||||||
|
form. Defaults to `false`.
|
||||||
|
|
||||||
|
|
||||||
|
##### depth
|
||||||
|
|
||||||
|
The `depth` option is used to configure the maximum depth of the `qs` library when `extended` is `true`. This allows you to limit the amount of keys that are parsed and can be useful to prevent certain types of abuse. Defaults to `32`. It is recommended to keep this value as low as possible.
|
||||||
|
|
||||||
|
## 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.
|
||||||
|
|
||||||
|
### The input exceeded the depth
|
||||||
|
|
||||||
|
This error occurs when using `bodyParser.urlencoded` with the `extended` property set to `true` and the input exceeds the configured `depth` option. The `status` property is set to `400`. It is recommended to review the `depth` option and evaluate if it requires a higher value. When the `depth` option is set to `32` (default value), the error will not be thrown.
|
||||||
|
|
||||||
|
## 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
|
||||||
|
const express = require('express')
|
||||||
|
const bodyParser = require('body-parser')
|
||||||
|
|
||||||
|
const app = express()
|
||||||
|
|
||||||
|
// parse application/x-www-form-urlencoded
|
||||||
|
app.use(bodyParser.urlencoded())
|
||||||
|
|
||||||
|
// 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(String(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
|
||||||
|
const express = require('express')
|
||||||
|
const bodyParser = require('body-parser')
|
||||||
|
|
||||||
|
const app = express()
|
||||||
|
|
||||||
|
// create application/json parser
|
||||||
|
const jsonParser = bodyParser.json()
|
||||||
|
|
||||||
|
// create application/x-www-form-urlencoded parser
|
||||||
|
const urlencodedParser = bodyParser.urlencoded()
|
||||||
|
|
||||||
|
// POST /login gets urlencoded bodies
|
||||||
|
app.post('/login', urlencodedParser, function (req, res) {
|
||||||
|
if (!req.body || !req.body.username) res.sendStatus(400)
|
||||||
|
res.send('welcome, ' + req.body.username)
|
||||||
|
})
|
||||||
|
|
||||||
|
// POST /api/users gets JSON bodies
|
||||||
|
app.post('/api/users', jsonParser, function (req, res) {
|
||||||
|
if (!req.body) res.sendStatus(400)
|
||||||
|
// 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
|
||||||
|
const express = require('express')
|
||||||
|
const bodyParser = require('body-parser')
|
||||||
|
|
||||||
|
const 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://img.shields.io/github/actions/workflow/status/expressjs/body-parser/ci.yml?branch=master&label=ci
|
||||||
|
[ci-url]: https://github.com/expressjs/body-parser/actions/workflows/ci.yml
|
||||||
|
[coveralls-image]: https://img.shields.io/coverallsCoverage/github/expressjs/body-parser?branch=master
|
||||||
|
[coveralls-url]: https://coveralls.io/r/expressjs/body-parser?branch=master
|
||||||
|
[npm-downloads-image]: https://img.shields.io/npm/dm/body-parser
|
||||||
|
[npm-url]: https://npmjs.com/package/body-parser
|
||||||
|
[npm-version-image]: https://img.shields.io/npm/v/body-parser
|
||||||
|
[ossf-scorecard-badge]: https://api.scorecard.dev/projects/github.com/expressjs/body-parser/badge
|
||||||
|
[ossf-scorecard-visualizer]: https://ossf.github.io/scorecard-visualizer/#/projects/github.com/expressjs/body-parser
|
||||||
71
node_modules/body-parser/index.js
generated
vendored
Normal file
71
node_modules/body-parser/index.js
generated
vendored
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
/*!
|
||||||
|
* body-parser
|
||||||
|
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||||||
|
* MIT Licensed
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} Parsers
|
||||||
|
* @property {Function} json JSON parser
|
||||||
|
* @property {Function} raw Raw parser
|
||||||
|
* @property {Function} text Text parser
|
||||||
|
* @property {Function} urlencoded URL-encoded parser
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module exports.
|
||||||
|
* @type {Function & Parsers}
|
||||||
|
*/
|
||||||
|
exports = module.exports = bodyParser
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JSON parser.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
Object.defineProperty(exports, 'json', {
|
||||||
|
configurable: true,
|
||||||
|
enumerable: true,
|
||||||
|
get: () => require('./lib/types/json')
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Raw parser.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
Object.defineProperty(exports, 'raw', {
|
||||||
|
configurable: true,
|
||||||
|
enumerable: true,
|
||||||
|
get: () => require('./lib/types/raw')
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Text parser.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
Object.defineProperty(exports, 'text', {
|
||||||
|
configurable: true,
|
||||||
|
enumerable: true,
|
||||||
|
get: () => require('./lib/types/text')
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* URL-encoded parser.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
Object.defineProperty(exports, 'urlencoded', {
|
||||||
|
configurable: true,
|
||||||
|
enumerable: true,
|
||||||
|
get: () => require('./lib/types/urlencoded')
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a middleware to parse json and urlencoded bodies.
|
||||||
|
*
|
||||||
|
* @deprecated
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
function bodyParser () {
|
||||||
|
throw new Error('The bodyParser() generic has been split into individual middleware to use instead.')
|
||||||
|
}
|
||||||
247
node_modules/body-parser/lib/read.js
generated
vendored
Normal file
247
node_modules/body-parser/lib/read.js
generated
vendored
Normal file
@@ -0,0 +1,247 @@
|
|||||||
|
/*!
|
||||||
|
* body-parser
|
||||||
|
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||||||
|
* MIT Licensed
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module dependencies.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
var createError = require('http-errors')
|
||||||
|
var getBody = require('raw-body')
|
||||||
|
var iconv = require('iconv-lite')
|
||||||
|
var onFinished = require('on-finished')
|
||||||
|
var zlib = require('node:zlib')
|
||||||
|
var hasBody = require('type-is').hasBody
|
||||||
|
var { getCharset } = require('./utils')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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) {
|
||||||
|
if (onFinished.isFinished(req)) {
|
||||||
|
debug('body already parsed')
|
||||||
|
next()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!('body' in req)) {
|
||||||
|
req.body = undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip requests without bodies
|
||||||
|
if (!hasBody(req)) {
|
||||||
|
debug('skip empty body')
|
||||||
|
next()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
debug('content-type %j', req.headers['content-type'])
|
||||||
|
|
||||||
|
// determine if request should be parsed
|
||||||
|
if (!options.shouldParse(req)) {
|
||||||
|
debug('skip parsing')
|
||||||
|
next()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var encoding = null
|
||||||
|
if (options?.skipCharset !== true) {
|
||||||
|
encoding = getCharset(req) || options.defaultCharset
|
||||||
|
|
||||||
|
// validate charset
|
||||||
|
if (!!options?.isValidCharset && !options.isValidCharset(encoding)) {
|
||||||
|
debug('invalid charset')
|
||||||
|
next(createError(415, 'unsupported charset "' + encoding.toUpperCase() + '"', {
|
||||||
|
charset: encoding,
|
||||||
|
type: 'charset.unsupported'
|
||||||
|
}))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var length
|
||||||
|
var opts = options
|
||||||
|
var stream
|
||||||
|
|
||||||
|
// read options
|
||||||
|
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) {
|
||||||
|
req.unpipe()
|
||||||
|
stream.destroy()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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, encoding)
|
||||||
|
} 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
|
||||||
|
* @returns {Object}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
function contentstream (req, debug, inflate) {
|
||||||
|
var encoding = (req.headers['content-encoding'] || 'identity').toLowerCase()
|
||||||
|
var length = req.headers['content-length']
|
||||||
|
|
||||||
|
debug('content-encoding "%s"', encoding)
|
||||||
|
|
||||||
|
if (inflate === false && encoding !== 'identity') {
|
||||||
|
throw createError(415, 'content encoding unsupported', {
|
||||||
|
encoding: encoding,
|
||||||
|
type: 'encoding.unsupported'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (encoding === 'identity') {
|
||||||
|
req.length = length
|
||||||
|
return req
|
||||||
|
}
|
||||||
|
|
||||||
|
var stream = createDecompressionStream(encoding, debug)
|
||||||
|
req.pipe(stream)
|
||||||
|
return stream
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a decompression stream for the given encoding.
|
||||||
|
* @param {string} encoding
|
||||||
|
* @param {Function} debug
|
||||||
|
* @returns {Object}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
function createDecompressionStream (encoding, debug) {
|
||||||
|
switch (encoding) {
|
||||||
|
case 'deflate':
|
||||||
|
debug('inflate body')
|
||||||
|
return zlib.createInflate()
|
||||||
|
case 'gzip':
|
||||||
|
debug('gunzip body')
|
||||||
|
return zlib.createGunzip()
|
||||||
|
case 'br':
|
||||||
|
debug('brotli decompress body')
|
||||||
|
return zlib.createBrotliDecompress()
|
||||||
|
default:
|
||||||
|
throw createError(415, 'unsupported content encoding "' + encoding + '"', {
|
||||||
|
encoding: encoding,
|
||||||
|
type: 'encoding.unsupported'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dump the contents of a request.
|
||||||
|
*
|
||||||
|
* @param {Object} req
|
||||||
|
* @param {Function} callback
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
function dump (req, callback) {
|
||||||
|
if (onFinished.isFinished(req)) {
|
||||||
|
callback(null)
|
||||||
|
} else {
|
||||||
|
onFinished(req, callback)
|
||||||
|
req.resume()
|
||||||
|
}
|
||||||
|
}
|
||||||
158
node_modules/body-parser/lib/types/json.js
generated
vendored
Normal file
158
node_modules/body-parser/lib/types/json.js
generated
vendored
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
/*!
|
||||||
|
* body-parser
|
||||||
|
* Copyright(c) 2014 Jonathan Ong
|
||||||
|
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||||||
|
* MIT Licensed
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module dependencies.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
var debug = require('debug')('body-parser:json')
|
||||||
|
var read = require('../read')
|
||||||
|
var { normalizeOptions } = require('../utils')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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]
|
||||||
|
* @returns {Function}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
function json (options) {
|
||||||
|
const normalizedOptions = normalizeOptions(options, 'application/json')
|
||||||
|
|
||||||
|
var reviver = options?.reviver
|
||||||
|
var strict = options?.strict !== false
|
||||||
|
|
||||||
|
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
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const readOptions = {
|
||||||
|
...normalizedOptions,
|
||||||
|
// assert charset per RFC 7159 sec 8.1
|
||||||
|
isValidCharset: (charset) => charset.slice(0, 4) === 'utf-'
|
||||||
|
}
|
||||||
|
|
||||||
|
return function jsonParser (req, res, next) {
|
||||||
|
read(req, res, next, parse, debug, readOptions)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create strict violation syntax error matching native error.
|
||||||
|
*
|
||||||
|
* @param {string} str
|
||||||
|
* @param {string} char
|
||||||
|
* @returns {Error}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
function createStrictSyntaxError (str, char) {
|
||||||
|
var index = str.indexOf(char)
|
||||||
|
var partial = ''
|
||||||
|
|
||||||
|
if (index !== -1) {
|
||||||
|
partial = str.substring(0, index) + JSON_SYNTAX_CHAR.repeat(str.length - index)
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
* @returns {string|undefined}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
function firstchar (str) {
|
||||||
|
var match = FIRST_CHAR_REGEXP.exec(str)
|
||||||
|
|
||||||
|
return match
|
||||||
|
? match[1]
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalize a SyntaxError for JSON.parse.
|
||||||
|
*
|
||||||
|
* @param {SyntaxError} error
|
||||||
|
* @param {Object} obj
|
||||||
|
* @returns {SyntaxError}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
}
|
||||||
42
node_modules/body-parser/lib/types/raw.js
generated
vendored
Normal file
42
node_modules/body-parser/lib/types/raw.js
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
/*!
|
||||||
|
* body-parser
|
||||||
|
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||||||
|
* MIT Licensed
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module dependencies.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var debug = require('debug')('body-parser:raw')
|
||||||
|
var read = require('../read')
|
||||||
|
var { normalizeOptions, passthrough } = require('../utils')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module exports.
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = raw
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a middleware to parse raw bodies.
|
||||||
|
*
|
||||||
|
* @param {Object} [options]
|
||||||
|
* @returns {Function}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
function raw (options) {
|
||||||
|
const normalizedOptions = normalizeOptions(options, 'application/octet-stream')
|
||||||
|
|
||||||
|
const readOptions = {
|
||||||
|
...normalizedOptions,
|
||||||
|
// Skip charset validation and parse the body as is
|
||||||
|
skipCharset: true
|
||||||
|
}
|
||||||
|
|
||||||
|
return function rawParser (req, res, next) {
|
||||||
|
read(req, res, next, passthrough, debug, readOptions)
|
||||||
|
}
|
||||||
|
}
|
||||||
36
node_modules/body-parser/lib/types/text.js
generated
vendored
Normal file
36
node_modules/body-parser/lib/types/text.js
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/*!
|
||||||
|
* body-parser
|
||||||
|
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||||||
|
* MIT Licensed
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module dependencies.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var debug = require('debug')('body-parser:text')
|
||||||
|
var read = require('../read')
|
||||||
|
var { normalizeOptions, passthrough } = require('../utils')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module exports.
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = text
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a middleware to parse text bodies.
|
||||||
|
*
|
||||||
|
* @param {Object} [options]
|
||||||
|
* @returns {Function}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
function text (options) {
|
||||||
|
const normalizedOptions = normalizeOptions(options, 'text/plain')
|
||||||
|
|
||||||
|
return function textParser (req, res, next) {
|
||||||
|
read(req, res, next, passthrough, debug, normalizedOptions)
|
||||||
|
}
|
||||||
|
}
|
||||||
142
node_modules/body-parser/lib/types/urlencoded.js
generated
vendored
Normal file
142
node_modules/body-parser/lib/types/urlencoded.js
generated
vendored
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
/*!
|
||||||
|
* body-parser
|
||||||
|
* Copyright(c) 2014 Jonathan Ong
|
||||||
|
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||||||
|
* MIT Licensed
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module dependencies.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
var createError = require('http-errors')
|
||||||
|
var debug = require('debug')('body-parser:urlencoded')
|
||||||
|
var read = require('../read')
|
||||||
|
var qs = require('qs')
|
||||||
|
var { normalizeOptions } = require('../utils')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module exports.
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = urlencoded
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a middleware to parse urlencoded bodies.
|
||||||
|
*
|
||||||
|
* @param {Object} [options]
|
||||||
|
* @returns {Function}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
function urlencoded (options) {
|
||||||
|
const normalizedOptions = normalizeOptions(options, 'application/x-www-form-urlencoded')
|
||||||
|
|
||||||
|
if (normalizedOptions.defaultCharset !== 'utf-8' && normalizedOptions.defaultCharset !== 'iso-8859-1') {
|
||||||
|
throw new TypeError('option defaultCharset must be either utf-8 or iso-8859-1')
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the appropriate query parser
|
||||||
|
var queryparse = createQueryParser(options)
|
||||||
|
|
||||||
|
function parse (body, encoding) {
|
||||||
|
return body.length
|
||||||
|
? queryparse(body, encoding)
|
||||||
|
: {}
|
||||||
|
}
|
||||||
|
|
||||||
|
const readOptions = {
|
||||||
|
...normalizedOptions,
|
||||||
|
// assert charset
|
||||||
|
isValidCharset: (charset) => charset === 'utf-8' || charset === 'iso-8859-1'
|
||||||
|
}
|
||||||
|
|
||||||
|
return function urlencodedParser (req, res, next) {
|
||||||
|
read(req, res, next, parse, debug, readOptions)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the extended query parser.
|
||||||
|
*
|
||||||
|
* @param {Object} options
|
||||||
|
* @returns {Function}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
function createQueryParser (options) {
|
||||||
|
var extended = Boolean(options?.extended)
|
||||||
|
var parameterLimit = options?.parameterLimit !== undefined
|
||||||
|
? options?.parameterLimit
|
||||||
|
: 1000
|
||||||
|
var charsetSentinel = options?.charsetSentinel
|
||||||
|
var interpretNumericEntities = options?.interpretNumericEntities
|
||||||
|
var depth = extended ? (options?.depth !== undefined ? options?.depth : 32) : 0
|
||||||
|
|
||||||
|
if (isNaN(parameterLimit) || parameterLimit < 1) {
|
||||||
|
throw new TypeError('option parameterLimit must be a positive number')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNaN(depth) || depth < 0) {
|
||||||
|
throw new TypeError('option depth must be a zero or a positive number')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isFinite(parameterLimit)) {
|
||||||
|
parameterLimit = parameterLimit | 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return function queryparse (body, encoding) {
|
||||||
|
var paramCount = parameterCount(body, parameterLimit)
|
||||||
|
|
||||||
|
if (paramCount === undefined) {
|
||||||
|
debug('too many parameters')
|
||||||
|
throw createError(413, 'too many parameters', {
|
||||||
|
type: 'parameters.too.many'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
var arrayLimit = extended ? Math.max(100, paramCount) : paramCount
|
||||||
|
|
||||||
|
debug('parse ' + (extended ? 'extended ' : '') + 'urlencoding')
|
||||||
|
try {
|
||||||
|
return qs.parse(body, {
|
||||||
|
allowPrototypes: true,
|
||||||
|
arrayLimit: arrayLimit,
|
||||||
|
depth: depth,
|
||||||
|
charsetSentinel: charsetSentinel,
|
||||||
|
interpretNumericEntities: interpretNumericEntities,
|
||||||
|
charset: encoding,
|
||||||
|
parameterLimit: parameterLimit,
|
||||||
|
strictDepth: true
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
if (err instanceof RangeError) {
|
||||||
|
throw createError(400, 'The input exceeded the depth', {
|
||||||
|
type: 'querystring.parse.rangeError'
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count the number of parameters, stopping once limit reached
|
||||||
|
*
|
||||||
|
* @param {string} body
|
||||||
|
* @param {number} limit
|
||||||
|
* @returns {number|undefined} Returns undefined if limit exceeded
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
function parameterCount (body, limit) {
|
||||||
|
let count = 0
|
||||||
|
let index = -1
|
||||||
|
do {
|
||||||
|
count++
|
||||||
|
if (count > limit) return undefined // Early exit if limit exceeded
|
||||||
|
index = body.indexOf('&', index + 1)
|
||||||
|
} while (index !== -1)
|
||||||
|
return count
|
||||||
|
}
|
||||||
98
node_modules/body-parser/lib/utils.js
generated
vendored
Normal file
98
node_modules/body-parser/lib/utils.js
generated
vendored
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module dependencies.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var bytes = require('bytes')
|
||||||
|
var contentType = require('content-type')
|
||||||
|
var typeis = require('type-is')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module exports.
|
||||||
|
*/
|
||||||
|
module.exports = {
|
||||||
|
getCharset,
|
||||||
|
normalizeOptions,
|
||||||
|
passthrough
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the charset of a request.
|
||||||
|
*
|
||||||
|
* @param {Object} req
|
||||||
|
* @returns {string | undefined}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
function getCharset (req) {
|
||||||
|
try {
|
||||||
|
return (contentType.parse(req).parameters.charset || '').toLowerCase()
|
||||||
|
} catch {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the simple type checker.
|
||||||
|
*
|
||||||
|
* @param {string | string[]} type
|
||||||
|
* @returns {Function}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
function typeChecker (type) {
|
||||||
|
return function checkType (req) {
|
||||||
|
return Boolean(typeis(req, type))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalizes the common options for all parsers.
|
||||||
|
*
|
||||||
|
* @param {Object} options options to normalize
|
||||||
|
* @param {string | string[] | Function} defaultType default content type(s) or a function to determine it
|
||||||
|
* @returns {Object}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
function normalizeOptions (options, defaultType) {
|
||||||
|
if (!defaultType) {
|
||||||
|
// Parsers must define a default content type
|
||||||
|
throw new TypeError('defaultType must be provided')
|
||||||
|
}
|
||||||
|
|
||||||
|
var inflate = options?.inflate !== false
|
||||||
|
var limit = typeof options?.limit !== 'number'
|
||||||
|
? bytes.parse(options?.limit || '100kb')
|
||||||
|
: options?.limit
|
||||||
|
var type = options?.type || defaultType
|
||||||
|
var verify = options?.verify || false
|
||||||
|
var defaultCharset = options?.defaultCharset || 'utf-8'
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
return {
|
||||||
|
inflate,
|
||||||
|
limit,
|
||||||
|
verify,
|
||||||
|
defaultCharset,
|
||||||
|
shouldParse
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Passthrough function that returns input unchanged.
|
||||||
|
* Used by parsers that don't need to transform the data.
|
||||||
|
*
|
||||||
|
* @param {*} value
|
||||||
|
* @returns {*}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
function passthrough (value) {
|
||||||
|
return value
|
||||||
|
}
|
||||||
52
node_modules/body-parser/package.json
generated
vendored
Normal file
52
node_modules/body-parser/package.json
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
{
|
||||||
|
"name": "body-parser",
|
||||||
|
"description": "Node.js body parsing middleware",
|
||||||
|
"version": "2.2.2",
|
||||||
|
"contributors": [
|
||||||
|
"Douglas Christopher Wilson <doug@somethingdoug.com>",
|
||||||
|
"Jonathan Ong <me@jongleberry.com> (http://jongleberry.com)"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"repository": "expressjs/body-parser",
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/express"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"bytes": "^3.1.2",
|
||||||
|
"content-type": "^1.0.5",
|
||||||
|
"debug": "^4.4.3",
|
||||||
|
"http-errors": "^2.0.0",
|
||||||
|
"iconv-lite": "^0.7.0",
|
||||||
|
"on-finished": "^2.4.1",
|
||||||
|
"qs": "^6.14.1",
|
||||||
|
"raw-body": "^3.0.1",
|
||||||
|
"type-is": "^2.0.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"eslint": "^8.57.1",
|
||||||
|
"eslint-config-standard": "^14.1.1",
|
||||||
|
"eslint-plugin-import": "^2.31.0",
|
||||||
|
"eslint-plugin-markdown": "^3.0.1",
|
||||||
|
"eslint-plugin-node": "^11.1.0",
|
||||||
|
"eslint-plugin-promise": "^6.6.0",
|
||||||
|
"eslint-plugin-standard": "^4.1.0",
|
||||||
|
"mocha": "^11.1.0",
|
||||||
|
"nyc": "^17.1.0",
|
||||||
|
"supertest": "^7.0.0"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"lib/",
|
||||||
|
"LICENSE",
|
||||||
|
"index.js"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"lint": "eslint .",
|
||||||
|
"test": "mocha --reporter spec --check-leaks test/",
|
||||||
|
"test-ci": "nyc --reporter=lcovonly --reporter=text npm test",
|
||||||
|
"test-cov": "nyc --reporter=html --reporter=text npm test"
|
||||||
|
}
|
||||||
|
}
|
||||||
97
node_modules/bytes/History.md
generated
vendored
Normal file
97
node_modules/bytes/History.md
generated
vendored
Normal file
@@ -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]
|
||||||
23
node_modules/bytes/LICENSE
generated
vendored
Normal file
23
node_modules/bytes/LICENSE
generated
vendored
Normal file
@@ -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.
|
||||||
152
node_modules/bytes/Readme.md
generated
vendored
Normal file
152
node_modules/bytes/Readme.md
generated
vendored
Normal file
@@ -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
|
||||||
170
node_modules/bytes/index.js
generated
vendored
Normal file
170
node_modules/bytes/index.js
generated
vendored
Normal file
@@ -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);
|
||||||
|
}
|
||||||
42
node_modules/bytes/package.json
generated
vendored
Normal file
42
node_modules/bytes/package.json
generated
vendored
Normal file
@@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
17
node_modules/call-bind-apply-helpers/.eslintrc
generated
vendored
Normal file
17
node_modules/call-bind-apply-helpers/.eslintrc
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"root": true,
|
||||||
|
|
||||||
|
"extends": "@ljharb",
|
||||||
|
|
||||||
|
"rules": {
|
||||||
|
"func-name-matching": 0,
|
||||||
|
"id-length": 0,
|
||||||
|
"new-cap": [2, {
|
||||||
|
"capIsNewExceptions": [
|
||||||
|
"GetIntrinsic",
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
"no-extra-parens": 0,
|
||||||
|
"no-magic-numbers": 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
12
node_modules/call-bind-apply-helpers/.github/FUNDING.yml
generated
vendored
Normal file
12
node_modules/call-bind-apply-helpers/.github/FUNDING.yml
generated
vendored
Normal file
@@ -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-apply-helpers
|
||||||
|
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']
|
||||||
9
node_modules/call-bind-apply-helpers/.nycrc
generated
vendored
Normal file
9
node_modules/call-bind-apply-helpers/.nycrc
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"all": true,
|
||||||
|
"check-coverage": false,
|
||||||
|
"reporter": ["text-summary", "text", "html", "json"],
|
||||||
|
"exclude": [
|
||||||
|
"coverage",
|
||||||
|
"test"
|
||||||
|
]
|
||||||
|
}
|
||||||
30
node_modules/call-bind-apply-helpers/CHANGELOG.md
generated
vendored
Normal file
30
node_modules/call-bind-apply-helpers/CHANGELOG.md
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# 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.2](https://github.com/ljharb/call-bind-apply-helpers/compare/v1.0.1...v1.0.2) - 2025-02-12
|
||||||
|
|
||||||
|
### Commits
|
||||||
|
|
||||||
|
- [types] improve inferred types [`e6f9586`](https://github.com/ljharb/call-bind-apply-helpers/commit/e6f95860a3c72879cb861a858cdfb8138fbedec1)
|
||||||
|
- [Dev Deps] update `@arethetypeswrong/cli`, `@ljharb/tsconfig`, `@types/tape`, `es-value-fixtures`, `for-each`, `has-strict-mode`, `object-inspect` [`e43d540`](https://github.com/ljharb/call-bind-apply-helpers/commit/e43d5409f97543bfbb11f345d47d8ce4e066d8c1)
|
||||||
|
|
||||||
|
## [v1.0.1](https://github.com/ljharb/call-bind-apply-helpers/compare/v1.0.0...v1.0.1) - 2024-12-08
|
||||||
|
|
||||||
|
### Commits
|
||||||
|
|
||||||
|
- [types] `reflectApply`: fix types [`4efc396`](https://github.com/ljharb/call-bind-apply-helpers/commit/4efc3965351a4f02cc55e836fa391d3d11ef2ef8)
|
||||||
|
- [Fix] `reflectApply`: oops, Reflect is not a function [`83cc739`](https://github.com/ljharb/call-bind-apply-helpers/commit/83cc7395de6b79b7730bdf092f1436f0b1263c75)
|
||||||
|
- [Dev Deps] update `@arethetypeswrong/cli` [`80bd5d3`](https://github.com/ljharb/call-bind-apply-helpers/commit/80bd5d3ae58b4f6b6995ce439dd5a1bcb178a940)
|
||||||
|
|
||||||
|
## v1.0.0 - 2024-12-05
|
||||||
|
|
||||||
|
### Commits
|
||||||
|
|
||||||
|
- Initial implementation, tests, readme [`7879629`](https://github.com/ljharb/call-bind-apply-helpers/commit/78796290f9b7430c9934d6f33d94ae9bc89fce04)
|
||||||
|
- Initial commit [`3f1dc16`](https://github.com/ljharb/call-bind-apply-helpers/commit/3f1dc164afc43285631b114a5f9dd9137b2b952f)
|
||||||
|
- npm init [`081df04`](https://github.com/ljharb/call-bind-apply-helpers/commit/081df048c312fcee400922026f6e97281200a603)
|
||||||
|
- Only apps should have lockfiles [`5b9ca0f`](https://github.com/ljharb/call-bind-apply-helpers/commit/5b9ca0fe8101ebfaf309c549caac4e0a017ed930)
|
||||||
21
node_modules/call-bind-apply-helpers/LICENSE
generated
vendored
Normal file
21
node_modules/call-bind-apply-helpers/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2024 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.
|
||||||
62
node_modules/call-bind-apply-helpers/README.md
generated
vendored
Normal file
62
node_modules/call-bind-apply-helpers/README.md
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
# call-bind-apply-helpers <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]
|
||||||
|
|
||||||
|
Helper functions around Function call/apply/bind, for use in `call-bind`.
|
||||||
|
|
||||||
|
The only packages that should likely ever use this package directly are `call-bind` and `get-intrinsic`.
|
||||||
|
Please use `call-bind` unless you have a very good reason not to.
|
||||||
|
|
||||||
|
## Getting started
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm install --save call-bind-apply-helpers
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage/Examples
|
||||||
|
|
||||||
|
```js
|
||||||
|
const assert = require('assert');
|
||||||
|
const callBindBasic = require('call-bind-apply-helpers');
|
||||||
|
|
||||||
|
function f(a, b) {
|
||||||
|
assert.equal(this, 1);
|
||||||
|
assert.equal(a, 2);
|
||||||
|
assert.equal(b, 3);
|
||||||
|
assert.equal(arguments.length, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
const fBound = callBindBasic([f, 1]);
|
||||||
|
|
||||||
|
delete Function.prototype.call;
|
||||||
|
delete Function.prototype.bind;
|
||||||
|
|
||||||
|
fBound(2, 3);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
|
||||||
|
Clone the repo, `npm install`, and run `npm test`
|
||||||
|
|
||||||
|
[package-url]: https://npmjs.org/package/call-bind-apply-helpers
|
||||||
|
[npm-version-svg]: https://versionbadg.es/ljharb/call-bind-apply-helpers.svg
|
||||||
|
[deps-svg]: https://david-dm.org/ljharb/call-bind-apply-helpers.svg
|
||||||
|
[deps-url]: https://david-dm.org/ljharb/call-bind-apply-helpers
|
||||||
|
[dev-deps-svg]: https://david-dm.org/ljharb/call-bind-apply-helpers/dev-status.svg
|
||||||
|
[dev-deps-url]: https://david-dm.org/ljharb/call-bind-apply-helpers#info=devDependencies
|
||||||
|
[npm-badge-png]: https://nodei.co/npm/call-bind-apply-helpers.png?downloads=true&stars=true
|
||||||
|
[license-image]: https://img.shields.io/npm/l/call-bind-apply-helpers.svg
|
||||||
|
[license-url]: LICENSE
|
||||||
|
[downloads-image]: https://img.shields.io/npm/dm/call-bind-apply-helpers.svg
|
||||||
|
[downloads-url]: https://npm-stat.com/charts.html?package=call-bind-apply-helpers
|
||||||
|
[codecov-image]: https://codecov.io/gh/ljharb/call-bind-apply-helpers/branch/main/graphs/badge.svg
|
||||||
|
[codecov-url]: https://app.codecov.io/gh/ljharb/call-bind-apply-helpers/
|
||||||
|
[actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/ljharb/call-bind-apply-helpers
|
||||||
|
[actions-url]: https://github.com/ljharb/call-bind-apply-helpers/actions
|
||||||
1
node_modules/call-bind-apply-helpers/actualApply.d.ts
generated
vendored
Normal file
1
node_modules/call-bind-apply-helpers/actualApply.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export = Reflect.apply;
|
||||||
10
node_modules/call-bind-apply-helpers/actualApply.js
generated
vendored
Normal file
10
node_modules/call-bind-apply-helpers/actualApply.js
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var bind = require('function-bind');
|
||||||
|
|
||||||
|
var $apply = require('./functionApply');
|
||||||
|
var $call = require('./functionCall');
|
||||||
|
var $reflectApply = require('./reflectApply');
|
||||||
|
|
||||||
|
/** @type {import('./actualApply')} */
|
||||||
|
module.exports = $reflectApply || bind.call($call, $apply);
|
||||||
19
node_modules/call-bind-apply-helpers/applyBind.d.ts
generated
vendored
Normal file
19
node_modules/call-bind-apply-helpers/applyBind.d.ts
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import actualApply from './actualApply';
|
||||||
|
|
||||||
|
type TupleSplitHead<T extends any[], N extends number> = T['length'] extends N
|
||||||
|
? T
|
||||||
|
: T extends [...infer R, any]
|
||||||
|
? TupleSplitHead<R, N>
|
||||||
|
: never
|
||||||
|
|
||||||
|
type TupleSplitTail<T, N extends number, O extends any[] = []> = O['length'] extends N
|
||||||
|
? T
|
||||||
|
: T extends [infer F, ...infer R]
|
||||||
|
? TupleSplitTail<[...R], N, [...O, F]>
|
||||||
|
: never
|
||||||
|
|
||||||
|
type TupleSplit<T extends any[], N extends number> = [TupleSplitHead<T, N>, TupleSplitTail<T, N>]
|
||||||
|
|
||||||
|
declare function applyBind(...args: TupleSplit<Parameters<typeof actualApply>, 2>[1]): ReturnType<typeof actualApply>;
|
||||||
|
|
||||||
|
export = applyBind;
|
||||||
10
node_modules/call-bind-apply-helpers/applyBind.js
generated
vendored
Normal file
10
node_modules/call-bind-apply-helpers/applyBind.js
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var bind = require('function-bind');
|
||||||
|
var $apply = require('./functionApply');
|
||||||
|
var actualApply = require('./actualApply');
|
||||||
|
|
||||||
|
/** @type {import('./applyBind')} */
|
||||||
|
module.exports = function applyBind() {
|
||||||
|
return actualApply(bind, $apply, arguments);
|
||||||
|
};
|
||||||
1
node_modules/call-bind-apply-helpers/functionApply.d.ts
generated
vendored
Normal file
1
node_modules/call-bind-apply-helpers/functionApply.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export = Function.prototype.apply;
|
||||||
4
node_modules/call-bind-apply-helpers/functionApply.js
generated
vendored
Normal file
4
node_modules/call-bind-apply-helpers/functionApply.js
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
/** @type {import('./functionApply')} */
|
||||||
|
module.exports = Function.prototype.apply;
|
||||||
1
node_modules/call-bind-apply-helpers/functionCall.d.ts
generated
vendored
Normal file
1
node_modules/call-bind-apply-helpers/functionCall.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export = Function.prototype.call;
|
||||||
4
node_modules/call-bind-apply-helpers/functionCall.js
generated
vendored
Normal file
4
node_modules/call-bind-apply-helpers/functionCall.js
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
/** @type {import('./functionCall')} */
|
||||||
|
module.exports = Function.prototype.call;
|
||||||
64
node_modules/call-bind-apply-helpers/index.d.ts
generated
vendored
Normal file
64
node_modules/call-bind-apply-helpers/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
type RemoveFromTuple<
|
||||||
|
Tuple extends readonly unknown[],
|
||||||
|
RemoveCount extends number,
|
||||||
|
Index extends 1[] = []
|
||||||
|
> = Index["length"] extends RemoveCount
|
||||||
|
? Tuple
|
||||||
|
: Tuple extends [infer First, ...infer Rest]
|
||||||
|
? RemoveFromTuple<Rest, RemoveCount, [...Index, 1]>
|
||||||
|
: Tuple;
|
||||||
|
|
||||||
|
type ConcatTuples<
|
||||||
|
Prefix extends readonly unknown[],
|
||||||
|
Suffix extends readonly unknown[]
|
||||||
|
> = [...Prefix, ...Suffix];
|
||||||
|
|
||||||
|
type ExtractFunctionParams<T> = T extends (this: infer TThis, ...args: infer P extends readonly unknown[]) => infer R
|
||||||
|
? { thisArg: TThis; params: P; returnType: R }
|
||||||
|
: never;
|
||||||
|
|
||||||
|
type BindFunction<
|
||||||
|
T extends (this: any, ...args: any[]) => any,
|
||||||
|
TThis,
|
||||||
|
TBoundArgs extends readonly unknown[],
|
||||||
|
ReceiverBound extends boolean
|
||||||
|
> = ExtractFunctionParams<T> extends {
|
||||||
|
thisArg: infer OrigThis;
|
||||||
|
params: infer P extends readonly unknown[];
|
||||||
|
returnType: infer R;
|
||||||
|
}
|
||||||
|
? ReceiverBound extends true
|
||||||
|
? (...args: RemoveFromTuple<P, Extract<TBoundArgs["length"], number>>) => R extends [OrigThis, ...infer Rest]
|
||||||
|
? [TThis, ...Rest] // Replace `this` with `thisArg`
|
||||||
|
: R
|
||||||
|
: <U, RemainingArgs extends RemoveFromTuple<P, Extract<TBoundArgs["length"], number>>>(
|
||||||
|
thisArg: U,
|
||||||
|
...args: RemainingArgs
|
||||||
|
) => R extends [OrigThis, ...infer Rest]
|
||||||
|
? [U, ...ConcatTuples<TBoundArgs, Rest>] // Preserve bound args in return type
|
||||||
|
: R
|
||||||
|
: never;
|
||||||
|
|
||||||
|
declare function callBind<
|
||||||
|
const T extends (this: any, ...args: any[]) => any,
|
||||||
|
Extracted extends ExtractFunctionParams<T>,
|
||||||
|
const TBoundArgs extends Partial<Extracted["params"]> & readonly unknown[],
|
||||||
|
const TThis extends Extracted["thisArg"]
|
||||||
|
>(
|
||||||
|
args: [fn: T, thisArg: TThis, ...boundArgs: TBoundArgs]
|
||||||
|
): BindFunction<T, TThis, TBoundArgs, true>;
|
||||||
|
|
||||||
|
declare function callBind<
|
||||||
|
const T extends (this: any, ...args: any[]) => any,
|
||||||
|
Extracted extends ExtractFunctionParams<T>,
|
||||||
|
const TBoundArgs extends Partial<Extracted["params"]> & readonly unknown[]
|
||||||
|
>(
|
||||||
|
args: [fn: T, ...boundArgs: TBoundArgs]
|
||||||
|
): BindFunction<T, Extracted["thisArg"], TBoundArgs, false>;
|
||||||
|
|
||||||
|
declare function callBind<const TArgs extends readonly unknown[]>(
|
||||||
|
args: [fn: Exclude<TArgs[0], Function>, ...rest: TArgs]
|
||||||
|
): never;
|
||||||
|
|
||||||
|
// export as namespace callBind;
|
||||||
|
export = callBind;
|
||||||
15
node_modules/call-bind-apply-helpers/index.js
generated
vendored
Normal file
15
node_modules/call-bind-apply-helpers/index.js
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var bind = require('function-bind');
|
||||||
|
var $TypeError = require('es-errors/type');
|
||||||
|
|
||||||
|
var $call = require('./functionCall');
|
||||||
|
var $actualApply = require('./actualApply');
|
||||||
|
|
||||||
|
/** @type {(args: [Function, thisArg?: unknown, ...args: unknown[]]) => Function} TODO FIXME, find a way to use import('.') */
|
||||||
|
module.exports = function callBindBasic(args) {
|
||||||
|
if (args.length < 1 || typeof args[0] !== 'function') {
|
||||||
|
throw new $TypeError('a function is required');
|
||||||
|
}
|
||||||
|
return $actualApply(bind, $call, args);
|
||||||
|
};
|
||||||
85
node_modules/call-bind-apply-helpers/package.json
generated
vendored
Normal file
85
node_modules/call-bind-apply-helpers/package.json
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
{
|
||||||
|
"name": "call-bind-apply-helpers",
|
||||||
|
"version": "1.0.2",
|
||||||
|
"description": "Helper functions around Function call/apply/bind, for use in `call-bind`",
|
||||||
|
"main": "index.js",
|
||||||
|
"exports": {
|
||||||
|
".": "./index.js",
|
||||||
|
"./actualApply": "./actualApply.js",
|
||||||
|
"./applyBind": "./applyBind.js",
|
||||||
|
"./functionApply": "./functionApply.js",
|
||||||
|
"./functionCall": "./functionCall.js",
|
||||||
|
"./reflectApply": "./reflectApply.js",
|
||||||
|
"./package.json": "./package.json"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"prepack": "npmignore --auto --commentLines=auto",
|
||||||
|
"prepublish": "not-in-publish || npm run prepublishOnly",
|
||||||
|
"prepublishOnly": "safe-publish-latest",
|
||||||
|
"prelint": "evalmd README.md",
|
||||||
|
"lint": "eslint --ext=.js,.mjs .",
|
||||||
|
"postlint": "tsc -p . && attw -P",
|
||||||
|
"pretest": "npm run lint",
|
||||||
|
"tests-only": "nyc tape 'test/**/*.js'",
|
||||||
|
"test": "npm run tests-only",
|
||||||
|
"posttest": "npx npm@'>=10.2' audit --production",
|
||||||
|
"version": "auto-changelog && git add CHANGELOG.md",
|
||||||
|
"postversion": "auto-changelog && git add CHANGELOG.md && git commit --no-edit --amend && git tag -f \"v$(node -e \"console.log(require('./package.json').version)\")\""
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/ljharb/call-bind-apply-helpers.git"
|
||||||
|
},
|
||||||
|
"author": "Jordan Harband <ljharb@gmail.com>",
|
||||||
|
"license": "MIT",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/ljharb/call-bind-apply-helpers/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/ljharb/call-bind-apply-helpers#readme",
|
||||||
|
"dependencies": {
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"function-bind": "^1.1.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@arethetypeswrong/cli": "^0.17.3",
|
||||||
|
"@ljharb/eslint-config": "^21.1.1",
|
||||||
|
"@ljharb/tsconfig": "^0.2.3",
|
||||||
|
"@types/for-each": "^0.3.3",
|
||||||
|
"@types/function-bind": "^1.1.10",
|
||||||
|
"@types/object-inspect": "^1.13.0",
|
||||||
|
"@types/tape": "^5.8.1",
|
||||||
|
"auto-changelog": "^2.5.0",
|
||||||
|
"encoding": "^0.1.13",
|
||||||
|
"es-value-fixtures": "^1.7.1",
|
||||||
|
"eslint": "=8.8.0",
|
||||||
|
"evalmd": "^0.0.19",
|
||||||
|
"for-each": "^0.3.5",
|
||||||
|
"has-strict-mode": "^1.1.0",
|
||||||
|
"in-publish": "^2.0.1",
|
||||||
|
"npmignore": "^0.3.1",
|
||||||
|
"nyc": "^10.3.2",
|
||||||
|
"object-inspect": "^1.13.4",
|
||||||
|
"safe-publish-latest": "^2.0.0",
|
||||||
|
"tape": "^5.9.0",
|
||||||
|
"typescript": "next"
|
||||||
|
},
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
3
node_modules/call-bind-apply-helpers/reflectApply.d.ts
generated
vendored
Normal file
3
node_modules/call-bind-apply-helpers/reflectApply.d.ts
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
declare const reflectApply: false | typeof Reflect.apply;
|
||||||
|
|
||||||
|
export = reflectApply;
|
||||||
4
node_modules/call-bind-apply-helpers/reflectApply.js
generated
vendored
Normal file
4
node_modules/call-bind-apply-helpers/reflectApply.js
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
/** @type {import('./reflectApply')} */
|
||||||
|
module.exports = typeof Reflect !== 'undefined' && Reflect && Reflect.apply;
|
||||||
63
node_modules/call-bind-apply-helpers/test/index.js
generated
vendored
Normal file
63
node_modules/call-bind-apply-helpers/test/index.js
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var callBind = require('../');
|
||||||
|
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');
|
||||||
|
|
||||||
|
test('callBindBasic', function (t) {
|
||||||
|
forEach(v.nonFunctions, function (nonFunction) {
|
||||||
|
t['throws'](
|
||||||
|
// @ts-expect-error
|
||||||
|
function () { callBind([nonFunction]); },
|
||||||
|
TypeError,
|
||||||
|
inspect(nonFunction) + ' is not a function'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
var sentinel = { sentinel: true };
|
||||||
|
/** @type {<T, A extends number, B extends number>(this: T, a: A, b: B) => [T | undefined, A, B]} */
|
||||||
|
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');
|
||||||
|
|
||||||
|
/** type {(thisArg: unknown, a: number, b: number) => [unknown, number, number]} */
|
||||||
|
var bound = callBind([func]);
|
||||||
|
/** type {((a: number, b: number) => [typeof sentinel, typeof a, typeof b])} */
|
||||||
|
var boundR = callBind([func, sentinel]);
|
||||||
|
/** type {((b: number) => [typeof sentinel, number, typeof b])} */
|
||||||
|
var boundArg = callBind([func, sentinel, /** @type {const} */ (1)]);
|
||||||
|
|
||||||
|
// @ts-expect-error
|
||||||
|
t.deepEqual(bound(), [undefined, undefined, undefined], 'bound func with no args');
|
||||||
|
|
||||||
|
// @ts-expect-error
|
||||||
|
t.deepEqual(func(), [undefined, undefined, undefined], 'unbound func with too few args');
|
||||||
|
// @ts-expect-error
|
||||||
|
t.deepEqual(bound(1, 2), [hasStrictMode ? 1 : Object(1), 2, undefined], 'bound func too few args');
|
||||||
|
// @ts-expect-error
|
||||||
|
t.deepEqual(boundR(), [sentinel, undefined, undefined], 'bound func with receiver, with too few args');
|
||||||
|
// @ts-expect-error
|
||||||
|
t.deepEqual(boundArg(), [sentinel, 1, undefined], 'bound func with receiver and arg, with too few args');
|
||||||
|
|
||||||
|
t.deepEqual(func(1, 2), [undefined, 1, 2], 'unbound func with right args');
|
||||||
|
t.deepEqual(bound(1, 2, 3), [hasStrictMode ? 1 : Object(1), 2, 3], 'bound func with right args');
|
||||||
|
t.deepEqual(boundR(1, 2), [sentinel, 1, 2], 'bound func with receiver, with right args');
|
||||||
|
t.deepEqual(boundArg(2), [sentinel, 1, 2], 'bound func with receiver and arg, with right arg');
|
||||||
|
|
||||||
|
// @ts-expect-error
|
||||||
|
t.deepEqual(func(1, 2, 3), [undefined, 1, 2], 'unbound func with too many args');
|
||||||
|
// @ts-expect-error
|
||||||
|
t.deepEqual(bound(1, 2, 3, 4), [hasStrictMode ? 1 : Object(1), 2, 3], 'bound func with too many args');
|
||||||
|
// @ts-expect-error
|
||||||
|
t.deepEqual(boundR(1, 2, 3), [sentinel, 1, 2], 'bound func with receiver, with too many args');
|
||||||
|
// @ts-expect-error
|
||||||
|
t.deepEqual(boundArg(2, 3), [sentinel, 1, 2], 'bound func with receiver and arg, with too many args');
|
||||||
|
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
9
node_modules/call-bind-apply-helpers/tsconfig.json
generated
vendored
Normal file
9
node_modules/call-bind-apply-helpers/tsconfig.json
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"extends": "@ljharb/tsconfig",
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es2021",
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"coverage",
|
||||||
|
],
|
||||||
|
}
|
||||||
13
node_modules/call-bound/.eslintrc
generated
vendored
Normal file
13
node_modules/call-bound/.eslintrc
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"root": true,
|
||||||
|
|
||||||
|
"extends": "@ljharb",
|
||||||
|
|
||||||
|
"rules": {
|
||||||
|
"new-cap": [2, {
|
||||||
|
"capIsNewExceptions": [
|
||||||
|
"GetIntrinsic",
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
},
|
||||||
|
}
|
||||||
12
node_modules/call-bound/.github/FUNDING.yml
generated
vendored
Normal file
12
node_modules/call-bound/.github/FUNDING.yml
generated
vendored
Normal file
@@ -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-bound
|
||||||
|
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']
|
||||||
9
node_modules/call-bound/.nycrc
generated
vendored
Normal file
9
node_modules/call-bound/.nycrc
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"all": true,
|
||||||
|
"check-coverage": false,
|
||||||
|
"reporter": ["text-summary", "text", "html", "json"],
|
||||||
|
"exclude": [
|
||||||
|
"coverage",
|
||||||
|
"test"
|
||||||
|
]
|
||||||
|
}
|
||||||
42
node_modules/call-bound/CHANGELOG.md
generated
vendored
Normal file
42
node_modules/call-bound/CHANGELOG.md
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
# 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.4](https://github.com/ljharb/call-bound/compare/v1.0.3...v1.0.4) - 2025-03-03
|
||||||
|
|
||||||
|
### Commits
|
||||||
|
|
||||||
|
- [types] improve types [`e648922`](https://github.com/ljharb/call-bound/commit/e6489222a9e54f350fbf952ceabe51fd8b6027ff)
|
||||||
|
- [Dev Deps] update `@arethetypeswrong/cli`, `@ljharb/tsconfig`, `@types/tape`, `es-value-fixtures`, `for-each`, `has-strict-mode`, `object-inspect` [`a42a5eb`](https://github.com/ljharb/call-bound/commit/a42a5ebe6c1b54fcdc7997c7dc64fdca9e936719)
|
||||||
|
- [Deps] update `call-bind-apply-helpers`, `get-intrinsic` [`f529eac`](https://github.com/ljharb/call-bound/commit/f529eac132404c17156bbc23ab2297a25d0f20b8)
|
||||||
|
|
||||||
|
## [v1.0.3](https://github.com/ljharb/call-bound/compare/v1.0.2...v1.0.3) - 2024-12-15
|
||||||
|
|
||||||
|
### Commits
|
||||||
|
|
||||||
|
- [Refactor] use `call-bind-apply-helpers` instead of `call-bind` [`5e0b134`](https://github.com/ljharb/call-bound/commit/5e0b13496df14fb7d05dae9412f088da8d3f75be)
|
||||||
|
- [Deps] update `get-intrinsic` [`41fc967`](https://github.com/ljharb/call-bound/commit/41fc96732a22c7b7e8f381f93ccc54bb6293be2e)
|
||||||
|
- [readme] fix example [`79a0137`](https://github.com/ljharb/call-bound/commit/79a0137723f7c6d09c9c05452bbf8d5efb5d6e49)
|
||||||
|
- [meta] add `sideEffects` flag [`08b07be`](https://github.com/ljharb/call-bound/commit/08b07be7f1c03f67dc6f3cdaf0906259771859f7)
|
||||||
|
|
||||||
|
## [v1.0.2](https://github.com/ljharb/call-bound/compare/v1.0.1...v1.0.2) - 2024-12-10
|
||||||
|
|
||||||
|
### Commits
|
||||||
|
|
||||||
|
- [Dev Deps] update `@arethetypeswrong/cli`, `@ljharb/tsconfig`, `gopd` [`e6a5ffe`](https://github.com/ljharb/call-bound/commit/e6a5ffe849368fe4f74dfd6cdeca1b9baa39e8d5)
|
||||||
|
- [Deps] update `call-bind`, `get-intrinsic` [`2aeb5b5`](https://github.com/ljharb/call-bound/commit/2aeb5b521dc2b2683d1345c753ea1161de2d1c14)
|
||||||
|
- [types] improve return type [`1a0c9fe`](https://github.com/ljharb/call-bound/commit/1a0c9fe3114471e7ca1f57d104e2efe713bb4871)
|
||||||
|
|
||||||
|
## v1.0.1 - 2024-12-05
|
||||||
|
|
||||||
|
### Commits
|
||||||
|
|
||||||
|
- Initial implementation, tests, readme, types [`6d94121`](https://github.com/ljharb/call-bound/commit/6d94121a9243602e506334069f7a03189fe3363d)
|
||||||
|
- Initial commit [`0eae867`](https://github.com/ljharb/call-bound/commit/0eae867334ea025c33e6e91cdecfc9df96680cf9)
|
||||||
|
- npm init [`71b2479`](https://github.com/ljharb/call-bound/commit/71b2479c6723e0b7d91a6b663613067e98b7b275)
|
||||||
|
- Only apps should have lockfiles [`c3754a9`](https://github.com/ljharb/call-bound/commit/c3754a949b7f9132b47e2d18c1729889736741eb)
|
||||||
|
- [actions] skip `npm ls` in node < 10 [`74275a5`](https://github.com/ljharb/call-bound/commit/74275a5186b8caf6309b6b97472bdcb0df4683a8)
|
||||||
|
- [Dev Deps] add missing peer dep [`1354de8`](https://github.com/ljharb/call-bound/commit/1354de8679413e4ae9c523d85f76fa7a5e032d97)
|
||||||
21
node_modules/call-bound/LICENSE
generated
vendored
Normal file
21
node_modules/call-bound/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2024 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.
|
||||||
53
node_modules/call-bound/README.md
generated
vendored
Normal file
53
node_modules/call-bound/README.md
generated
vendored
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
# call-bound <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]
|
||||||
|
|
||||||
|
Robust call-bound JavaScript intrinsics, using `call-bind` and `get-intrinsic`.
|
||||||
|
|
||||||
|
## Getting started
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm install --save call-bound
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage/Examples
|
||||||
|
|
||||||
|
```js
|
||||||
|
const assert = require('assert');
|
||||||
|
const callBound = require('call-bound');
|
||||||
|
|
||||||
|
const slice = callBound('Array.prototype.slice');
|
||||||
|
|
||||||
|
delete Function.prototype.call;
|
||||||
|
delete Function.prototype.bind;
|
||||||
|
delete Array.prototype.slice;
|
||||||
|
|
||||||
|
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-bound
|
||||||
|
[npm-version-svg]: https://versionbadg.es/ljharb/call-bound.svg
|
||||||
|
[deps-svg]: https://david-dm.org/ljharb/call-bound.svg
|
||||||
|
[deps-url]: https://david-dm.org/ljharb/call-bound
|
||||||
|
[dev-deps-svg]: https://david-dm.org/ljharb/call-bound/dev-status.svg
|
||||||
|
[dev-deps-url]: https://david-dm.org/ljharb/call-bound#info=devDependencies
|
||||||
|
[npm-badge-png]: https://nodei.co/npm/call-bound.png?downloads=true&stars=true
|
||||||
|
[license-image]: https://img.shields.io/npm/l/call-bound.svg
|
||||||
|
[license-url]: LICENSE
|
||||||
|
[downloads-image]: https://img.shields.io/npm/dm/call-bound.svg
|
||||||
|
[downloads-url]: https://npm-stat.com/charts.html?package=call-bound
|
||||||
|
[codecov-image]: https://codecov.io/gh/ljharb/call-bound/branch/main/graphs/badge.svg
|
||||||
|
[codecov-url]: https://app.codecov.io/gh/ljharb/call-bound/
|
||||||
|
[actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/ljharb/call-bound
|
||||||
|
[actions-url]: https://github.com/ljharb/call-bound/actions
|
||||||
94
node_modules/call-bound/index.d.ts
generated
vendored
Normal file
94
node_modules/call-bound/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
type Intrinsic = typeof globalThis;
|
||||||
|
|
||||||
|
type IntrinsicName = keyof Intrinsic | `%${keyof Intrinsic}%`;
|
||||||
|
|
||||||
|
type IntrinsicPath = IntrinsicName | `${StripPercents<IntrinsicName>}.${string}` | `%${StripPercents<IntrinsicName>}.${string}%`;
|
||||||
|
|
||||||
|
type AllowMissing = boolean;
|
||||||
|
|
||||||
|
type StripPercents<T extends string> = T extends `%${infer U}%` ? U : T;
|
||||||
|
|
||||||
|
type BindMethodPrecise<F> =
|
||||||
|
F extends (this: infer This, ...args: infer Args) => infer R
|
||||||
|
? (obj: This, ...args: Args) => R
|
||||||
|
: F extends {
|
||||||
|
(this: infer This1, ...args: infer Args1): infer R1;
|
||||||
|
(this: infer This2, ...args: infer Args2): infer R2
|
||||||
|
}
|
||||||
|
? {
|
||||||
|
(obj: This1, ...args: Args1): R1;
|
||||||
|
(obj: This2, ...args: Args2): R2
|
||||||
|
}
|
||||||
|
: never
|
||||||
|
|
||||||
|
// Extract method type from a prototype
|
||||||
|
type GetPrototypeMethod<T extends keyof typeof globalThis, M extends string> =
|
||||||
|
(typeof globalThis)[T] extends { prototype: any }
|
||||||
|
? M extends keyof (typeof globalThis)[T]['prototype']
|
||||||
|
? (typeof globalThis)[T]['prototype'][M]
|
||||||
|
: never
|
||||||
|
: never
|
||||||
|
|
||||||
|
// Get static property/method
|
||||||
|
type GetStaticMember<T extends keyof typeof globalThis, P extends string> =
|
||||||
|
P extends keyof (typeof globalThis)[T] ? (typeof globalThis)[T][P] : never
|
||||||
|
|
||||||
|
// Type that maps string path to actual bound function or value with better precision
|
||||||
|
type BoundIntrinsic<S extends string> =
|
||||||
|
S extends `${infer Obj}.prototype.${infer Method}`
|
||||||
|
? Obj extends keyof typeof globalThis
|
||||||
|
? BindMethodPrecise<GetPrototypeMethod<Obj, Method & string>>
|
||||||
|
: unknown
|
||||||
|
: S extends `${infer Obj}.${infer Prop}`
|
||||||
|
? Obj extends keyof typeof globalThis
|
||||||
|
? GetStaticMember<Obj, Prop & string>
|
||||||
|
: unknown
|
||||||
|
: unknown
|
||||||
|
|
||||||
|
declare function arraySlice<T>(array: readonly T[], start?: number, end?: number): T[];
|
||||||
|
declare function arraySlice<T>(array: ArrayLike<T>, start?: number, end?: number): T[];
|
||||||
|
declare function arraySlice<T>(array: IArguments, start?: number, end?: number): T[];
|
||||||
|
|
||||||
|
// Special cases for methods that need explicit typing
|
||||||
|
interface SpecialCases {
|
||||||
|
'%Object.prototype.isPrototypeOf%': (thisArg: {}, obj: unknown) => boolean;
|
||||||
|
'%String.prototype.replace%': {
|
||||||
|
(str: string, searchValue: string | RegExp, replaceValue: string): string;
|
||||||
|
(str: string, searchValue: string | RegExp, replacer: (substring: string, ...args: any[]) => string): string
|
||||||
|
};
|
||||||
|
'%Object.prototype.toString%': (obj: {}) => string;
|
||||||
|
'%Object.prototype.hasOwnProperty%': (obj: {}, v: PropertyKey) => boolean;
|
||||||
|
'%Array.prototype.slice%': typeof arraySlice;
|
||||||
|
'%Array.prototype.map%': <T, U>(array: readonly T[], callbackfn: (value: T, index: number, array: readonly T[]) => U, thisArg?: any) => U[];
|
||||||
|
'%Array.prototype.filter%': <T>(array: readonly T[], predicate: (value: T, index: number, array: readonly T[]) => unknown, thisArg?: any) => T[];
|
||||||
|
'%Array.prototype.indexOf%': <T>(array: readonly T[], searchElement: T, fromIndex?: number) => number;
|
||||||
|
'%Function.prototype.apply%': <T, A extends any[], R>(fn: (...args: A) => R, thisArg: any, args: A) => R;
|
||||||
|
'%Function.prototype.call%': <T, A extends any[], R>(fn: (...args: A) => R, thisArg: any, ...args: A) => R;
|
||||||
|
'%Function.prototype.bind%': <T, A extends any[], R>(fn: (...args: A) => R, thisArg: any, ...args: A) => (...remainingArgs: A) => R;
|
||||||
|
'%Promise.prototype.then%': {
|
||||||
|
<T, R>(promise: Promise<T>, onfulfilled: (value: T) => R | PromiseLike<R>): Promise<R>;
|
||||||
|
<T, R>(promise: Promise<T>, onfulfilled: ((value: T) => R | PromiseLike<R>) | undefined | null, onrejected: (reason: any) => R | PromiseLike<R>): Promise<R>;
|
||||||
|
};
|
||||||
|
'%RegExp.prototype.test%': (regexp: RegExp, str: string) => boolean;
|
||||||
|
'%RegExp.prototype.exec%': (regexp: RegExp, str: string) => RegExpExecArray | null;
|
||||||
|
'%Error.prototype.toString%': (error: Error) => string;
|
||||||
|
'%TypeError.prototype.toString%': (error: TypeError) => string;
|
||||||
|
'%String.prototype.split%': (
|
||||||
|
obj: unknown,
|
||||||
|
splitter: string | RegExp | {
|
||||||
|
[Symbol.split](string: string, limit?: number): string[];
|
||||||
|
},
|
||||||
|
limit?: number | undefined
|
||||||
|
) => string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a bound function for a prototype method, or a value for a static property.
|
||||||
|
*
|
||||||
|
* @param name - The name of the intrinsic (e.g. 'Array.prototype.slice')
|
||||||
|
* @param {AllowMissing} [allowMissing] - Whether to allow missing intrinsics (default: false)
|
||||||
|
*/
|
||||||
|
declare function callBound<K extends keyof SpecialCases | StripPercents<keyof SpecialCases>, S extends IntrinsicPath>(name: K, allowMissing?: AllowMissing): SpecialCases[`%${StripPercents<K>}%`];
|
||||||
|
declare function callBound<K extends keyof SpecialCases | StripPercents<keyof SpecialCases>, S extends IntrinsicPath>(name: S, allowMissing?: AllowMissing): BoundIntrinsic<S>;
|
||||||
|
|
||||||
|
export = callBound;
|
||||||
19
node_modules/call-bound/index.js
generated
vendored
Normal file
19
node_modules/call-bound/index.js
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var GetIntrinsic = require('get-intrinsic');
|
||||||
|
|
||||||
|
var callBindBasic = require('call-bind-apply-helpers');
|
||||||
|
|
||||||
|
/** @type {(thisArg: string, searchString: string, position?: number) => number} */
|
||||||
|
var $indexOf = callBindBasic([GetIntrinsic('%String.prototype.indexOf%')]);
|
||||||
|
|
||||||
|
/** @type {import('.')} */
|
||||||
|
module.exports = function callBoundIntrinsic(name, allowMissing) {
|
||||||
|
/* eslint no-extra-parens: 0 */
|
||||||
|
|
||||||
|
var intrinsic = /** @type {(this: unknown, ...args: unknown[]) => unknown} */ (GetIntrinsic(name, !!allowMissing));
|
||||||
|
if (typeof intrinsic === 'function' && $indexOf(name, '.prototype.') > -1) {
|
||||||
|
return callBindBasic(/** @type {const} */ ([intrinsic]));
|
||||||
|
}
|
||||||
|
return intrinsic;
|
||||||
|
};
|
||||||
99
node_modules/call-bound/package.json
generated
vendored
Normal file
99
node_modules/call-bound/package.json
generated
vendored
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
{
|
||||||
|
"name": "call-bound",
|
||||||
|
"version": "1.0.4",
|
||||||
|
"description": "Robust call-bound JavaScript intrinsics, using `call-bind` and `get-intrinsic`.",
|
||||||
|
"main": "index.js",
|
||||||
|
"exports": {
|
||||||
|
".": "./index.js",
|
||||||
|
"./package.json": "./package.json"
|
||||||
|
},
|
||||||
|
"sideEffects": false,
|
||||||
|
"scripts": {
|
||||||
|
"prepack": "npmignore --auto --commentLines=auto",
|
||||||
|
"prepublish": "not-in-publish || npm run prepublishOnly",
|
||||||
|
"prepublishOnly": "safe-publish-latest",
|
||||||
|
"prelint": "evalmd README.md",
|
||||||
|
"lint": "eslint --ext=.js,.mjs .",
|
||||||
|
"postlint": "tsc -p . && attw -P",
|
||||||
|
"pretest": "npm run lint",
|
||||||
|
"tests-only": "nyc tape 'test/**/*.js'",
|
||||||
|
"test": "npm run tests-only",
|
||||||
|
"posttest": "npx npm@'>=10.2' audit --production",
|
||||||
|
"version": "auto-changelog && git add CHANGELOG.md",
|
||||||
|
"postversion": "auto-changelog && git add CHANGELOG.md && git commit --no-edit --amend && git tag -f \"v$(node -e \"console.log(require('./package.json').version)\")\""
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/ljharb/call-bound.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-bound/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/ljharb/call-bound#readme",
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind-apply-helpers": "^1.0.2",
|
||||||
|
"get-intrinsic": "^1.3.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@arethetypeswrong/cli": "^0.17.4",
|
||||||
|
"@ljharb/eslint-config": "^21.1.1",
|
||||||
|
"@ljharb/tsconfig": "^0.3.0",
|
||||||
|
"@types/call-bind": "^1.0.5",
|
||||||
|
"@types/get-intrinsic": "^1.2.3",
|
||||||
|
"@types/tape": "^5.8.1",
|
||||||
|
"auto-changelog": "^2.5.0",
|
||||||
|
"encoding": "^0.1.13",
|
||||||
|
"es-value-fixtures": "^1.7.1",
|
||||||
|
"eslint": "=8.8.0",
|
||||||
|
"evalmd": "^0.0.19",
|
||||||
|
"for-each": "^0.3.5",
|
||||||
|
"gopd": "^1.2.0",
|
||||||
|
"has-strict-mode": "^1.1.0",
|
||||||
|
"in-publish": "^2.0.1",
|
||||||
|
"npmignore": "^0.3.1",
|
||||||
|
"nyc": "^10.3.2",
|
||||||
|
"object-inspect": "^1.13.4",
|
||||||
|
"safe-publish-latest": "^2.0.0",
|
||||||
|
"tape": "^5.9.0",
|
||||||
|
"typescript": "next"
|
||||||
|
},
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
61
node_modules/call-bound/test/index.js
generated
vendored
Normal file
61
node_modules/call-bound/test/index.js
generated
vendored
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var test = require('tape');
|
||||||
|
|
||||||
|
var callBound = require('../');
|
||||||
|
|
||||||
|
/** @template {true} T @template U @typedef {T extends U ? T : never} AssertType */
|
||||||
|
|
||||||
|
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');
|
||||||
|
|
||||||
|
var x = callBound('Object.prototype.toString');
|
||||||
|
var y = callBound('%Object.prototype.toString%');
|
||||||
|
|
||||||
|
// prototype function
|
||||||
|
t.notEqual(x, Object.prototype.toString, 'Object.prototype.toString does not yield itself');
|
||||||
|
t.notEqual(y, Object.prototype.toString, '%Object.prototype.toString% does not yield itself');
|
||||||
|
t.equal(x(true), Object.prototype.toString.call(true), 'call-bound Object.prototype.toString calls into the original');
|
||||||
|
t.equal(y(true), Object.prototype.toString.call(true), 'call-bound %Object.prototype.toString% calls into the original');
|
||||||
|
|
||||||
|
t['throws'](
|
||||||
|
// @ts-expect-error
|
||||||
|
function () { callBound('does not exist'); },
|
||||||
|
SyntaxError,
|
||||||
|
'nonexistent intrinsic throws'
|
||||||
|
);
|
||||||
|
t['throws'](
|
||||||
|
// @ts-expect-error
|
||||||
|
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();
|
||||||
|
});
|
||||||
10
node_modules/call-bound/tsconfig.json
generated
vendored
Normal file
10
node_modules/call-bound/tsconfig.json
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"extends": "@ljharb/tsconfig",
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ESNext",
|
||||||
|
"lib": ["es2024"],
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"coverage",
|
||||||
|
],
|
||||||
|
}
|
||||||
21
node_modules/captchalm/LICENSE
generated
vendored
Normal file
21
node_modules/captchalm/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2024
|
||||||
|
|
||||||
|
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.
|
||||||
182
node_modules/captchalm/README.md
generated
vendored
Normal file
182
node_modules/captchalm/README.md
generated
vendored
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
# CaptchaLM
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="Banner.png" alt="CaptchaLM - I AM A ROBOT" width="600">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<strong>The reverse CAPTCHA for the AI age</strong><br>
|
||||||
|
Let AI agents through. Keep humans guessing.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<a href="#installation">Installation</a> •
|
||||||
|
<a href="#quick-start">Quick Start</a> •
|
||||||
|
<a href="docs/api.md">API Docs</a> •
|
||||||
|
<a href="docs/challenges.md">Challenge Types</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## What is CaptchaLM?
|
||||||
|
|
||||||
|
Traditional CAPTCHAs block bots and let humans through. **CaptchaLM flips the script.**
|
||||||
|
|
||||||
|
It presents computational challenges that are trivial for AI agents but tedious for humans:
|
||||||
|
|
||||||
|
| AI Agents | Humans |
|
||||||
|
|-----------|--------|
|
||||||
|
| ✅ Execute code instantly | ❌ Mental math is slow |
|
||||||
|
| ✅ Decode base64/hex easily | ❌ Manual decoding is painful |
|
||||||
|
| ✅ Parse structured data | ❌ Pattern matching takes time |
|
||||||
|
| ✅ Chain operations precisely | ❌ Easy to make mistakes |
|
||||||
|
|
||||||
|
**Use cases:**
|
||||||
|
- API endpoints that should only be accessed by AI agents
|
||||||
|
- Rate limiting humans while allowing automated workflows
|
||||||
|
- Creating "AI-only" zones in your application
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install captchalm
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
### 1. Protect your server
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import express from 'express';
|
||||||
|
import { createExpressMiddleware } from 'captchalm';
|
||||||
|
|
||||||
|
const app = express();
|
||||||
|
app.use(express.json());
|
||||||
|
|
||||||
|
const { protect, challenge } = createExpressMiddleware({
|
||||||
|
secret: process.env.UNCAPTCHA_SECRET,
|
||||||
|
difficulty: 'medium', // 'easy' | 'medium' | 'hard'
|
||||||
|
});
|
||||||
|
|
||||||
|
// Endpoint where agents get challenges
|
||||||
|
app.get('/challenge', challenge);
|
||||||
|
|
||||||
|
// Protected endpoint - only AI agents can access
|
||||||
|
app.post('/api/agent-only', protect, (req, res) => {
|
||||||
|
res.json({ message: 'Welcome, AI agent!' });
|
||||||
|
});
|
||||||
|
|
||||||
|
app.listen(3000);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Access from your AI agent
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { CaptchaLMSolver } from 'captchalm/client';
|
||||||
|
|
||||||
|
const solver = new CaptchaLMSolver();
|
||||||
|
|
||||||
|
// One-liner to solve and access protected endpoint
|
||||||
|
const response = await solver.completeProtectedRequest(
|
||||||
|
'https://api.example.com/challenge',
|
||||||
|
'https://api.example.com/api/agent-only',
|
||||||
|
{ method: 'POST', body: JSON.stringify({ data: 'hello' }) }
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log(await response.json());
|
||||||
|
// { message: 'Welcome, AI agent!' }
|
||||||
|
```
|
||||||
|
|
||||||
|
That's it! Your endpoint is now AI-agent-only.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## How It Works
|
||||||
|
|
||||||
|
1. **Agent requests a challenge** from your `/challenge` endpoint
|
||||||
|
2. **Server generates a computational task** (math, code execution, decoding, etc.)
|
||||||
|
3. **Agent solves the challenge** using the solver SDK
|
||||||
|
4. **Agent sends solution** with the protected request
|
||||||
|
5. **Server verifies** and grants access if correct
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────┐ GET /challenge ┌─────────────┐
|
||||||
|
│ AI Agent │ ──────────────────────► │ Server │
|
||||||
|
│ │ ◄────────────────────── │ │
|
||||||
|
│ │ Challenge data │ │
|
||||||
|
│ │ │ │
|
||||||
|
│ [Solver] │ POST /api/data │ [Verify] │
|
||||||
|
│ solves │ ──────────────────────► │ checks │
|
||||||
|
│ │ + solution headers │ │
|
||||||
|
│ │ ◄────────────────────── │ │
|
||||||
|
└─────────────┘ ✓ Access granted └─────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Challenge Types
|
||||||
|
|
||||||
|
CaptchaLM includes 5 types of challenges. See [docs/challenges.md](docs/challenges.md) for details.
|
||||||
|
|
||||||
|
| Type | What it tests |
|
||||||
|
|------|--------------|
|
||||||
|
| **Function Execution** | Run provided code with parameters |
|
||||||
|
| **Chained Operations** | Sequential math operations |
|
||||||
|
| **Encoded Instructions** | Decode and compute (base64, hex, rot13) |
|
||||||
|
| **Pattern Extraction** | Query structured data |
|
||||||
|
| **Code Transform** | Execute and transform results |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
createExpressMiddleware({
|
||||||
|
// Required
|
||||||
|
secret: 'your-secret-key',
|
||||||
|
|
||||||
|
// Optional
|
||||||
|
difficulty: 'medium', // 'easy' | 'medium' | 'hard'
|
||||||
|
expirationMs: 30000, // Challenge timeout (30s default)
|
||||||
|
challengeTypes: ['function_execution', 'chained_operations'],
|
||||||
|
rateLimit: {
|
||||||
|
maxAttempts: 10, // Per client
|
||||||
|
windowMs: 60000, // 1 minute window
|
||||||
|
},
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
- 📖 [API Reference](docs/api.md) - Full API documentation
|
||||||
|
- 🧩 [Challenge Types](docs/challenges.md) - Detailed challenge descriptions
|
||||||
|
- 🔒 [Security Guide](docs/security.md) - Security considerations
|
||||||
|
- 🤖 [For AI Agents](docs/llm.txt) - Machine-readable documentation
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
- **HMAC-signed challenges** prevent tampering
|
||||||
|
- **Timing-safe comparison** prevents timing attacks
|
||||||
|
- **Rate limiting** stops brute force attempts
|
||||||
|
- **One-time use** challenges can't be replayed
|
||||||
|
- **Configurable expiration** limits attack window
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<sub>🤖 AI agents: see <a href="docs/llm.txt">docs/llm.txt</a> for machine-readable documentation</sub>
|
||||||
|
</p>
|
||||||
368
node_modules/captchalm/dist/client/index.cjs
generated
vendored
Normal file
368
node_modules/captchalm/dist/client/index.cjs
generated
vendored
Normal file
@@ -0,0 +1,368 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
// src/core/encoding.ts
|
||||||
|
function encode(value, encoding) {
|
||||||
|
switch (encoding) {
|
||||||
|
case "plain":
|
||||||
|
return value;
|
||||||
|
case "base64":
|
||||||
|
return encodeBase64(value);
|
||||||
|
case "hex":
|
||||||
|
return encodeHex(value);
|
||||||
|
case "rot13":
|
||||||
|
return encodeRot13(value);
|
||||||
|
default:
|
||||||
|
throw new Error(`Unknown encoding type: ${encoding}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function decode(value, encoding) {
|
||||||
|
switch (encoding) {
|
||||||
|
case "plain":
|
||||||
|
return value;
|
||||||
|
case "base64":
|
||||||
|
return decodeBase64(value);
|
||||||
|
case "hex":
|
||||||
|
return decodeHex(value);
|
||||||
|
case "rot13":
|
||||||
|
return decodeRot13(value);
|
||||||
|
// ROT13 is symmetric
|
||||||
|
default:
|
||||||
|
throw new Error(`Unknown encoding type: ${encoding}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function encodeBase64(value) {
|
||||||
|
return Buffer.from(value, "utf-8").toString("base64");
|
||||||
|
}
|
||||||
|
function decodeBase64(value) {
|
||||||
|
return Buffer.from(value, "base64").toString("utf-8");
|
||||||
|
}
|
||||||
|
function encodeHex(value) {
|
||||||
|
return Buffer.from(value, "utf-8").toString("hex");
|
||||||
|
}
|
||||||
|
function decodeHex(value) {
|
||||||
|
return Buffer.from(value, "hex").toString("utf-8");
|
||||||
|
}
|
||||||
|
function encodeRot13(value) {
|
||||||
|
return value.replace(/[a-zA-Z]/g, (char) => {
|
||||||
|
const base = char <= "Z" ? 65 : 97;
|
||||||
|
return String.fromCharCode((char.charCodeAt(0) - base + 13) % 26 + base);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function decodeRot13(value) {
|
||||||
|
return encodeRot13(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// src/client/executor.ts
|
||||||
|
function executeFunction(code, params) {
|
||||||
|
try {
|
||||||
|
const wrapper = new Function(`
|
||||||
|
${code}
|
||||||
|
return ${extractFunctionName(code)};
|
||||||
|
`);
|
||||||
|
const fn = wrapper();
|
||||||
|
return fn(...params);
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(`Failed to execute function: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function extractFunctionName(code) {
|
||||||
|
const match = code.match(/function\s+(\w+)/);
|
||||||
|
if (match) {
|
||||||
|
return match[1];
|
||||||
|
}
|
||||||
|
throw new Error("Could not extract function name from code");
|
||||||
|
}
|
||||||
|
function executeChainedOperations(initialValue, operations) {
|
||||||
|
let result = initialValue;
|
||||||
|
for (const op of operations) {
|
||||||
|
switch (op.operation) {
|
||||||
|
case "add":
|
||||||
|
result += op.value ?? 0;
|
||||||
|
break;
|
||||||
|
case "subtract":
|
||||||
|
result -= op.value ?? 0;
|
||||||
|
break;
|
||||||
|
case "multiply":
|
||||||
|
result *= op.value ?? 1;
|
||||||
|
break;
|
||||||
|
case "divide":
|
||||||
|
if (op.value === 0) throw new Error("Division by zero");
|
||||||
|
result /= op.value ?? 1;
|
||||||
|
break;
|
||||||
|
case "modulo":
|
||||||
|
if (op.value === 0) throw new Error("Modulo by zero");
|
||||||
|
result %= op.value ?? 1;
|
||||||
|
break;
|
||||||
|
case "power":
|
||||||
|
result = Math.pow(result, op.value ?? 1);
|
||||||
|
break;
|
||||||
|
case "floor":
|
||||||
|
result = Math.floor(result);
|
||||||
|
break;
|
||||||
|
case "ceil":
|
||||||
|
result = Math.ceil(result);
|
||||||
|
break;
|
||||||
|
case "abs":
|
||||||
|
result = Math.abs(result);
|
||||||
|
break;
|
||||||
|
case "negate":
|
||||||
|
result = -result;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error(`Unknown operation: ${op.operation}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
function executeEncodedInstruction(encodedInstruction, encoding) {
|
||||||
|
const instruction = decode(encodedInstruction, encoding);
|
||||||
|
const match = instruction.match(/Calculate:\s*(\d+)\s*([+\-*\/])\s*(\d+)/);
|
||||||
|
if (!match) {
|
||||||
|
throw new Error(`Could not parse instruction: ${instruction}`);
|
||||||
|
}
|
||||||
|
const a = parseInt(match[1], 10);
|
||||||
|
const op = match[2];
|
||||||
|
const b = parseInt(match[3], 10);
|
||||||
|
switch (op) {
|
||||||
|
case "+":
|
||||||
|
return a + b;
|
||||||
|
case "-":
|
||||||
|
return a - b;
|
||||||
|
case "*":
|
||||||
|
return a * b;
|
||||||
|
case "/":
|
||||||
|
return a / b;
|
||||||
|
default:
|
||||||
|
throw new Error(`Unknown operator: ${op}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function executePatternExtraction(data, query) {
|
||||||
|
const funcMatch = query.match(/^(\w+)\(([^)]+)\)$/);
|
||||||
|
if (!funcMatch) {
|
||||||
|
throw new Error(`Invalid query format: ${query}`);
|
||||||
|
}
|
||||||
|
const [, func, path] = funcMatch;
|
||||||
|
const values = extractPathValues(data, path);
|
||||||
|
switch (func.toLowerCase()) {
|
||||||
|
case "sum":
|
||||||
|
return values.reduce((a, b) => a + b, 0);
|
||||||
|
case "max":
|
||||||
|
return Math.max(...values);
|
||||||
|
case "min":
|
||||||
|
return Math.min(...values);
|
||||||
|
case "count":
|
||||||
|
return values.length;
|
||||||
|
case "avg":
|
||||||
|
const nums = values;
|
||||||
|
return nums.reduce((a, b) => a + b, 0) / nums.length;
|
||||||
|
default:
|
||||||
|
throw new Error(`Unknown function: ${func}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function extractPathValues(data, path) {
|
||||||
|
const wildcardMatch = path.match(/^(\w+)\[\*\]\.(\w+)$/);
|
||||||
|
if (wildcardMatch) {
|
||||||
|
const [, arrayName, propName] = wildcardMatch;
|
||||||
|
const arr = data[arrayName];
|
||||||
|
if (!Array.isArray(arr)) {
|
||||||
|
throw new Error(`Expected array at ${arrayName}`);
|
||||||
|
}
|
||||||
|
return arr.map((item) => item[propName]);
|
||||||
|
}
|
||||||
|
if (path in data) {
|
||||||
|
const value = data[path];
|
||||||
|
return Array.isArray(value) ? value : [value];
|
||||||
|
}
|
||||||
|
throw new Error(`Invalid path: ${path}`);
|
||||||
|
}
|
||||||
|
function executeCodeTransform(code, transform) {
|
||||||
|
const fn = new Function(code);
|
||||||
|
const result = fn();
|
||||||
|
switch (transform) {
|
||||||
|
case "execute":
|
||||||
|
return result;
|
||||||
|
case "execute_and_base64":
|
||||||
|
return Buffer.from(String(result)).toString("base64");
|
||||||
|
case "execute_and_hash":
|
||||||
|
const str = String(result);
|
||||||
|
let hash = 0;
|
||||||
|
for (let i = 0; i < str.length; i++) {
|
||||||
|
const char = str.charCodeAt(i);
|
||||||
|
hash = (hash << 5) - hash + char;
|
||||||
|
hash = hash & hash;
|
||||||
|
}
|
||||||
|
return Math.abs(hash).toString(16);
|
||||||
|
default:
|
||||||
|
throw new Error(`Unknown transform: ${transform}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function executePayload(payload) {
|
||||||
|
switch (payload.type) {
|
||||||
|
case "function_execution": {
|
||||||
|
const p = payload;
|
||||||
|
return executeFunction(p.functionCode, p.parameters);
|
||||||
|
}
|
||||||
|
case "chained_operations": {
|
||||||
|
const p = payload;
|
||||||
|
return executeChainedOperations(p.initialValue, p.operations);
|
||||||
|
}
|
||||||
|
case "encoded_instruction": {
|
||||||
|
const p = payload;
|
||||||
|
return executeEncodedInstruction(p.instruction, p.instructionEncoding);
|
||||||
|
}
|
||||||
|
case "pattern_extraction": {
|
||||||
|
const p = payload;
|
||||||
|
return executePatternExtraction(p.data, p.query);
|
||||||
|
}
|
||||||
|
case "code_transform": {
|
||||||
|
const p = payload;
|
||||||
|
return executeCodeTransform(p.code, p.transform);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw new Error(`Unknown challenge type: ${payload.type}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// src/client/solver.ts
|
||||||
|
var CaptchaLMSolver = class {
|
||||||
|
options;
|
||||||
|
constructor(options) {
|
||||||
|
this.options = {
|
||||||
|
timeout: options?.timeout ?? 1e4,
|
||||||
|
debug: options?.debug ?? false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Solve a challenge
|
||||||
|
*/
|
||||||
|
solve(challenge) {
|
||||||
|
const startTime = Date.now();
|
||||||
|
try {
|
||||||
|
if (Date.now() > challenge.expiresAt) {
|
||||||
|
return {
|
||||||
|
solution: "",
|
||||||
|
solveDuration: Date.now() - startTime,
|
||||||
|
success: false,
|
||||||
|
error: "Challenge has expired"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (this.options.debug) {
|
||||||
|
console.log(`[CaptchaLM] Solving ${challenge.type} challenge...`);
|
||||||
|
}
|
||||||
|
const rawResult = executePayload(challenge.payload);
|
||||||
|
const responseEncoding = challenge.payload.responseEncoding || "plain";
|
||||||
|
const solution = encode(String(rawResult), responseEncoding);
|
||||||
|
const duration = Date.now() - startTime;
|
||||||
|
if (this.options.debug) {
|
||||||
|
console.log(`[CaptchaLM] Solved in ${duration}ms`);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
solution,
|
||||||
|
solveDuration: duration,
|
||||||
|
success: true
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
const duration = Date.now() - startTime;
|
||||||
|
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
||||||
|
if (this.options.debug) {
|
||||||
|
console.error(`[CaptchaLM] Failed to solve: ${errorMessage}`);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
solution: "",
|
||||||
|
solveDuration: duration,
|
||||||
|
success: false,
|
||||||
|
error: errorMessage
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Solve a challenge and return formatted headers for HTTP request
|
||||||
|
*/
|
||||||
|
solveForRequest(challenge) {
|
||||||
|
const result = this.solve(challenge);
|
||||||
|
if (!result.success) {
|
||||||
|
return {
|
||||||
|
headers: {},
|
||||||
|
body: { _CaptchaLMChallenge: challenge },
|
||||||
|
success: false,
|
||||||
|
error: result.error
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
headers: {
|
||||||
|
"x-captchalm-id": challenge.id,
|
||||||
|
"x-captchalm-solution": result.solution
|
||||||
|
},
|
||||||
|
body: {
|
||||||
|
_CaptchaLMChallenge: challenge
|
||||||
|
},
|
||||||
|
success: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Fetch a challenge from a server and solve it
|
||||||
|
*/
|
||||||
|
async fetchAndSolve(challengeUrl, fetchOptions) {
|
||||||
|
try {
|
||||||
|
const response = await fetch(challengeUrl, {
|
||||||
|
method: "GET",
|
||||||
|
...fetchOptions
|
||||||
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Failed to fetch challenge: ${response.statusText}`);
|
||||||
|
}
|
||||||
|
const data = await response.json();
|
||||||
|
if (!data.success || !data.challenge) {
|
||||||
|
throw new Error(data.error || "Invalid challenge response");
|
||||||
|
}
|
||||||
|
const challenge = data.challenge;
|
||||||
|
const result = this.solve(challenge);
|
||||||
|
return {
|
||||||
|
challenge,
|
||||||
|
solution: result.solution,
|
||||||
|
success: result.success,
|
||||||
|
error: result.error
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
challenge: null,
|
||||||
|
solution: "",
|
||||||
|
success: false,
|
||||||
|
error: error instanceof Error ? error.message : "Unknown error"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Complete a protected request including challenge solving
|
||||||
|
*/
|
||||||
|
async completeProtectedRequest(challengeUrl, protectedUrl, requestOptions) {
|
||||||
|
const { challenge, solution, success, error } = await this.fetchAndSolve(challengeUrl);
|
||||||
|
if (!success) {
|
||||||
|
throw new Error(`Failed to solve challenge: ${error}`);
|
||||||
|
}
|
||||||
|
const headers = new Headers(requestOptions?.headers);
|
||||||
|
headers.set("x-captchalm-id", challenge.id);
|
||||||
|
headers.set("x-captchalm-solution", solution);
|
||||||
|
headers.set("Content-Type", "application/json");
|
||||||
|
const body = requestOptions?.body ? { ...JSON.parse(requestOptions.body), _CaptchaLMChallenge: challenge } : { _CaptchaLMChallenge: challenge };
|
||||||
|
return fetch(protectedUrl, {
|
||||||
|
...requestOptions,
|
||||||
|
headers,
|
||||||
|
body: JSON.stringify(body)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
function createSolver(options) {
|
||||||
|
return new CaptchaLMSolver(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.CaptchaLMSolver = CaptchaLMSolver;
|
||||||
|
exports.createSolver = createSolver;
|
||||||
|
exports.executeChainedOperations = executeChainedOperations;
|
||||||
|
exports.executeCodeTransform = executeCodeTransform;
|
||||||
|
exports.executeEncodedInstruction = executeEncodedInstruction;
|
||||||
|
exports.executeFunction = executeFunction;
|
||||||
|
exports.executePatternExtraction = executePatternExtraction;
|
||||||
|
exports.executePayload = executePayload;
|
||||||
|
//# sourceMappingURL=index.cjs.map
|
||||||
|
//# sourceMappingURL=index.cjs.map
|
||||||
1
node_modules/captchalm/dist/client/index.cjs.map
generated
vendored
Normal file
1
node_modules/captchalm/dist/client/index.cjs.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
99
node_modules/captchalm/dist/client/index.d.cts
generated
vendored
Normal file
99
node_modules/captchalm/dist/client/index.d.cts
generated
vendored
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
import { ChainedOperationsPayload, ChallengePayload, Challenge } from '../core/types.cjs';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Safe code executor for client-side challenge solving
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute a function from code string
|
||||||
|
* Uses Function constructor for sandboxed execution
|
||||||
|
*/
|
||||||
|
declare function executeFunction(code: string, params: unknown[]): unknown;
|
||||||
|
/**
|
||||||
|
* Execute chained operations
|
||||||
|
*/
|
||||||
|
declare function executeChainedOperations(initialValue: number, operations: ChainedOperationsPayload['operations']): number;
|
||||||
|
/**
|
||||||
|
* Parse and execute encoded instructions
|
||||||
|
*/
|
||||||
|
declare function executeEncodedInstruction(encodedInstruction: string, encoding: string): unknown;
|
||||||
|
/**
|
||||||
|
* Execute pattern extraction query
|
||||||
|
*/
|
||||||
|
declare function executePatternExtraction(data: Record<string, unknown>, query: string): unknown;
|
||||||
|
/**
|
||||||
|
* Execute code transform
|
||||||
|
*/
|
||||||
|
declare function executeCodeTransform(code: string, transform: string): unknown;
|
||||||
|
/**
|
||||||
|
* Execute any challenge payload and return the result
|
||||||
|
*/
|
||||||
|
declare function executePayload(payload: ChallengePayload): unknown;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Challenge solver for AI agents
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Solver options
|
||||||
|
*/
|
||||||
|
interface SolverOptions {
|
||||||
|
/** Timeout for solving (ms) */
|
||||||
|
timeout?: number;
|
||||||
|
/** Enable debug logging */
|
||||||
|
debug?: boolean;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Solution result
|
||||||
|
*/
|
||||||
|
interface SolutionResult {
|
||||||
|
/** The computed solution */
|
||||||
|
solution: string;
|
||||||
|
/** Time taken to solve (ms) */
|
||||||
|
solveDuration: number;
|
||||||
|
/** Whether the solve was successful */
|
||||||
|
success: boolean;
|
||||||
|
/** Error message if failed */
|
||||||
|
error?: string;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* CaptchaLM Solver for AI agents
|
||||||
|
*/
|
||||||
|
declare class CaptchaLMSolver {
|
||||||
|
private options;
|
||||||
|
constructor(options?: SolverOptions);
|
||||||
|
/**
|
||||||
|
* Solve a challenge
|
||||||
|
*/
|
||||||
|
solve(challenge: Challenge): SolutionResult;
|
||||||
|
/**
|
||||||
|
* Solve a challenge and return formatted headers for HTTP request
|
||||||
|
*/
|
||||||
|
solveForRequest(challenge: Challenge): {
|
||||||
|
headers: Record<string, string>;
|
||||||
|
body: {
|
||||||
|
_CaptchaLMChallenge: Challenge;
|
||||||
|
};
|
||||||
|
success: boolean;
|
||||||
|
error?: string;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Fetch a challenge from a server and solve it
|
||||||
|
*/
|
||||||
|
fetchAndSolve(challengeUrl: string, fetchOptions?: RequestInit): Promise<{
|
||||||
|
challenge: Challenge;
|
||||||
|
solution: string;
|
||||||
|
success: boolean;
|
||||||
|
error?: string;
|
||||||
|
}>;
|
||||||
|
/**
|
||||||
|
* Complete a protected request including challenge solving
|
||||||
|
*/
|
||||||
|
completeProtectedRequest(challengeUrl: string, protectedUrl: string, requestOptions?: RequestInit): Promise<Response>;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Create a solver instance
|
||||||
|
*/
|
||||||
|
declare function createSolver(options?: SolverOptions): CaptchaLMSolver;
|
||||||
|
|
||||||
|
export { CaptchaLMSolver, type SolutionResult, type SolverOptions, createSolver, executeChainedOperations, executeCodeTransform, executeEncodedInstruction, executeFunction, executePatternExtraction, executePayload };
|
||||||
99
node_modules/captchalm/dist/client/index.d.ts
generated
vendored
Normal file
99
node_modules/captchalm/dist/client/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
import { ChainedOperationsPayload, ChallengePayload, Challenge } from '../core/types.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Safe code executor for client-side challenge solving
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute a function from code string
|
||||||
|
* Uses Function constructor for sandboxed execution
|
||||||
|
*/
|
||||||
|
declare function executeFunction(code: string, params: unknown[]): unknown;
|
||||||
|
/**
|
||||||
|
* Execute chained operations
|
||||||
|
*/
|
||||||
|
declare function executeChainedOperations(initialValue: number, operations: ChainedOperationsPayload['operations']): number;
|
||||||
|
/**
|
||||||
|
* Parse and execute encoded instructions
|
||||||
|
*/
|
||||||
|
declare function executeEncodedInstruction(encodedInstruction: string, encoding: string): unknown;
|
||||||
|
/**
|
||||||
|
* Execute pattern extraction query
|
||||||
|
*/
|
||||||
|
declare function executePatternExtraction(data: Record<string, unknown>, query: string): unknown;
|
||||||
|
/**
|
||||||
|
* Execute code transform
|
||||||
|
*/
|
||||||
|
declare function executeCodeTransform(code: string, transform: string): unknown;
|
||||||
|
/**
|
||||||
|
* Execute any challenge payload and return the result
|
||||||
|
*/
|
||||||
|
declare function executePayload(payload: ChallengePayload): unknown;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Challenge solver for AI agents
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Solver options
|
||||||
|
*/
|
||||||
|
interface SolverOptions {
|
||||||
|
/** Timeout for solving (ms) */
|
||||||
|
timeout?: number;
|
||||||
|
/** Enable debug logging */
|
||||||
|
debug?: boolean;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Solution result
|
||||||
|
*/
|
||||||
|
interface SolutionResult {
|
||||||
|
/** The computed solution */
|
||||||
|
solution: string;
|
||||||
|
/** Time taken to solve (ms) */
|
||||||
|
solveDuration: number;
|
||||||
|
/** Whether the solve was successful */
|
||||||
|
success: boolean;
|
||||||
|
/** Error message if failed */
|
||||||
|
error?: string;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* CaptchaLM Solver for AI agents
|
||||||
|
*/
|
||||||
|
declare class CaptchaLMSolver {
|
||||||
|
private options;
|
||||||
|
constructor(options?: SolverOptions);
|
||||||
|
/**
|
||||||
|
* Solve a challenge
|
||||||
|
*/
|
||||||
|
solve(challenge: Challenge): SolutionResult;
|
||||||
|
/**
|
||||||
|
* Solve a challenge and return formatted headers for HTTP request
|
||||||
|
*/
|
||||||
|
solveForRequest(challenge: Challenge): {
|
||||||
|
headers: Record<string, string>;
|
||||||
|
body: {
|
||||||
|
_CaptchaLMChallenge: Challenge;
|
||||||
|
};
|
||||||
|
success: boolean;
|
||||||
|
error?: string;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Fetch a challenge from a server and solve it
|
||||||
|
*/
|
||||||
|
fetchAndSolve(challengeUrl: string, fetchOptions?: RequestInit): Promise<{
|
||||||
|
challenge: Challenge;
|
||||||
|
solution: string;
|
||||||
|
success: boolean;
|
||||||
|
error?: string;
|
||||||
|
}>;
|
||||||
|
/**
|
||||||
|
* Complete a protected request including challenge solving
|
||||||
|
*/
|
||||||
|
completeProtectedRequest(challengeUrl: string, protectedUrl: string, requestOptions?: RequestInit): Promise<Response>;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Create a solver instance
|
||||||
|
*/
|
||||||
|
declare function createSolver(options?: SolverOptions): CaptchaLMSolver;
|
||||||
|
|
||||||
|
export { CaptchaLMSolver, type SolutionResult, type SolverOptions, createSolver, executeChainedOperations, executeCodeTransform, executeEncodedInstruction, executeFunction, executePatternExtraction, executePayload };
|
||||||
359
node_modules/captchalm/dist/client/index.js
generated
vendored
Normal file
359
node_modules/captchalm/dist/client/index.js
generated
vendored
Normal file
@@ -0,0 +1,359 @@
|
|||||||
|
// src/core/encoding.ts
|
||||||
|
function encode(value, encoding) {
|
||||||
|
switch (encoding) {
|
||||||
|
case "plain":
|
||||||
|
return value;
|
||||||
|
case "base64":
|
||||||
|
return encodeBase64(value);
|
||||||
|
case "hex":
|
||||||
|
return encodeHex(value);
|
||||||
|
case "rot13":
|
||||||
|
return encodeRot13(value);
|
||||||
|
default:
|
||||||
|
throw new Error(`Unknown encoding type: ${encoding}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function decode(value, encoding) {
|
||||||
|
switch (encoding) {
|
||||||
|
case "plain":
|
||||||
|
return value;
|
||||||
|
case "base64":
|
||||||
|
return decodeBase64(value);
|
||||||
|
case "hex":
|
||||||
|
return decodeHex(value);
|
||||||
|
case "rot13":
|
||||||
|
return decodeRot13(value);
|
||||||
|
// ROT13 is symmetric
|
||||||
|
default:
|
||||||
|
throw new Error(`Unknown encoding type: ${encoding}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function encodeBase64(value) {
|
||||||
|
return Buffer.from(value, "utf-8").toString("base64");
|
||||||
|
}
|
||||||
|
function decodeBase64(value) {
|
||||||
|
return Buffer.from(value, "base64").toString("utf-8");
|
||||||
|
}
|
||||||
|
function encodeHex(value) {
|
||||||
|
return Buffer.from(value, "utf-8").toString("hex");
|
||||||
|
}
|
||||||
|
function decodeHex(value) {
|
||||||
|
return Buffer.from(value, "hex").toString("utf-8");
|
||||||
|
}
|
||||||
|
function encodeRot13(value) {
|
||||||
|
return value.replace(/[a-zA-Z]/g, (char) => {
|
||||||
|
const base = char <= "Z" ? 65 : 97;
|
||||||
|
return String.fromCharCode((char.charCodeAt(0) - base + 13) % 26 + base);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function decodeRot13(value) {
|
||||||
|
return encodeRot13(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// src/client/executor.ts
|
||||||
|
function executeFunction(code, params) {
|
||||||
|
try {
|
||||||
|
const wrapper = new Function(`
|
||||||
|
${code}
|
||||||
|
return ${extractFunctionName(code)};
|
||||||
|
`);
|
||||||
|
const fn = wrapper();
|
||||||
|
return fn(...params);
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(`Failed to execute function: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function extractFunctionName(code) {
|
||||||
|
const match = code.match(/function\s+(\w+)/);
|
||||||
|
if (match) {
|
||||||
|
return match[1];
|
||||||
|
}
|
||||||
|
throw new Error("Could not extract function name from code");
|
||||||
|
}
|
||||||
|
function executeChainedOperations(initialValue, operations) {
|
||||||
|
let result = initialValue;
|
||||||
|
for (const op of operations) {
|
||||||
|
switch (op.operation) {
|
||||||
|
case "add":
|
||||||
|
result += op.value ?? 0;
|
||||||
|
break;
|
||||||
|
case "subtract":
|
||||||
|
result -= op.value ?? 0;
|
||||||
|
break;
|
||||||
|
case "multiply":
|
||||||
|
result *= op.value ?? 1;
|
||||||
|
break;
|
||||||
|
case "divide":
|
||||||
|
if (op.value === 0) throw new Error("Division by zero");
|
||||||
|
result /= op.value ?? 1;
|
||||||
|
break;
|
||||||
|
case "modulo":
|
||||||
|
if (op.value === 0) throw new Error("Modulo by zero");
|
||||||
|
result %= op.value ?? 1;
|
||||||
|
break;
|
||||||
|
case "power":
|
||||||
|
result = Math.pow(result, op.value ?? 1);
|
||||||
|
break;
|
||||||
|
case "floor":
|
||||||
|
result = Math.floor(result);
|
||||||
|
break;
|
||||||
|
case "ceil":
|
||||||
|
result = Math.ceil(result);
|
||||||
|
break;
|
||||||
|
case "abs":
|
||||||
|
result = Math.abs(result);
|
||||||
|
break;
|
||||||
|
case "negate":
|
||||||
|
result = -result;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error(`Unknown operation: ${op.operation}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
function executeEncodedInstruction(encodedInstruction, encoding) {
|
||||||
|
const instruction = decode(encodedInstruction, encoding);
|
||||||
|
const match = instruction.match(/Calculate:\s*(\d+)\s*([+\-*\/])\s*(\d+)/);
|
||||||
|
if (!match) {
|
||||||
|
throw new Error(`Could not parse instruction: ${instruction}`);
|
||||||
|
}
|
||||||
|
const a = parseInt(match[1], 10);
|
||||||
|
const op = match[2];
|
||||||
|
const b = parseInt(match[3], 10);
|
||||||
|
switch (op) {
|
||||||
|
case "+":
|
||||||
|
return a + b;
|
||||||
|
case "-":
|
||||||
|
return a - b;
|
||||||
|
case "*":
|
||||||
|
return a * b;
|
||||||
|
case "/":
|
||||||
|
return a / b;
|
||||||
|
default:
|
||||||
|
throw new Error(`Unknown operator: ${op}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function executePatternExtraction(data, query) {
|
||||||
|
const funcMatch = query.match(/^(\w+)\(([^)]+)\)$/);
|
||||||
|
if (!funcMatch) {
|
||||||
|
throw new Error(`Invalid query format: ${query}`);
|
||||||
|
}
|
||||||
|
const [, func, path] = funcMatch;
|
||||||
|
const values = extractPathValues(data, path);
|
||||||
|
switch (func.toLowerCase()) {
|
||||||
|
case "sum":
|
||||||
|
return values.reduce((a, b) => a + b, 0);
|
||||||
|
case "max":
|
||||||
|
return Math.max(...values);
|
||||||
|
case "min":
|
||||||
|
return Math.min(...values);
|
||||||
|
case "count":
|
||||||
|
return values.length;
|
||||||
|
case "avg":
|
||||||
|
const nums = values;
|
||||||
|
return nums.reduce((a, b) => a + b, 0) / nums.length;
|
||||||
|
default:
|
||||||
|
throw new Error(`Unknown function: ${func}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function extractPathValues(data, path) {
|
||||||
|
const wildcardMatch = path.match(/^(\w+)\[\*\]\.(\w+)$/);
|
||||||
|
if (wildcardMatch) {
|
||||||
|
const [, arrayName, propName] = wildcardMatch;
|
||||||
|
const arr = data[arrayName];
|
||||||
|
if (!Array.isArray(arr)) {
|
||||||
|
throw new Error(`Expected array at ${arrayName}`);
|
||||||
|
}
|
||||||
|
return arr.map((item) => item[propName]);
|
||||||
|
}
|
||||||
|
if (path in data) {
|
||||||
|
const value = data[path];
|
||||||
|
return Array.isArray(value) ? value : [value];
|
||||||
|
}
|
||||||
|
throw new Error(`Invalid path: ${path}`);
|
||||||
|
}
|
||||||
|
function executeCodeTransform(code, transform) {
|
||||||
|
const fn = new Function(code);
|
||||||
|
const result = fn();
|
||||||
|
switch (transform) {
|
||||||
|
case "execute":
|
||||||
|
return result;
|
||||||
|
case "execute_and_base64":
|
||||||
|
return Buffer.from(String(result)).toString("base64");
|
||||||
|
case "execute_and_hash":
|
||||||
|
const str = String(result);
|
||||||
|
let hash = 0;
|
||||||
|
for (let i = 0; i < str.length; i++) {
|
||||||
|
const char = str.charCodeAt(i);
|
||||||
|
hash = (hash << 5) - hash + char;
|
||||||
|
hash = hash & hash;
|
||||||
|
}
|
||||||
|
return Math.abs(hash).toString(16);
|
||||||
|
default:
|
||||||
|
throw new Error(`Unknown transform: ${transform}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function executePayload(payload) {
|
||||||
|
switch (payload.type) {
|
||||||
|
case "function_execution": {
|
||||||
|
const p = payload;
|
||||||
|
return executeFunction(p.functionCode, p.parameters);
|
||||||
|
}
|
||||||
|
case "chained_operations": {
|
||||||
|
const p = payload;
|
||||||
|
return executeChainedOperations(p.initialValue, p.operations);
|
||||||
|
}
|
||||||
|
case "encoded_instruction": {
|
||||||
|
const p = payload;
|
||||||
|
return executeEncodedInstruction(p.instruction, p.instructionEncoding);
|
||||||
|
}
|
||||||
|
case "pattern_extraction": {
|
||||||
|
const p = payload;
|
||||||
|
return executePatternExtraction(p.data, p.query);
|
||||||
|
}
|
||||||
|
case "code_transform": {
|
||||||
|
const p = payload;
|
||||||
|
return executeCodeTransform(p.code, p.transform);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw new Error(`Unknown challenge type: ${payload.type}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// src/client/solver.ts
|
||||||
|
var CaptchaLMSolver = class {
|
||||||
|
options;
|
||||||
|
constructor(options) {
|
||||||
|
this.options = {
|
||||||
|
timeout: options?.timeout ?? 1e4,
|
||||||
|
debug: options?.debug ?? false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Solve a challenge
|
||||||
|
*/
|
||||||
|
solve(challenge) {
|
||||||
|
const startTime = Date.now();
|
||||||
|
try {
|
||||||
|
if (Date.now() > challenge.expiresAt) {
|
||||||
|
return {
|
||||||
|
solution: "",
|
||||||
|
solveDuration: Date.now() - startTime,
|
||||||
|
success: false,
|
||||||
|
error: "Challenge has expired"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (this.options.debug) {
|
||||||
|
console.log(`[CaptchaLM] Solving ${challenge.type} challenge...`);
|
||||||
|
}
|
||||||
|
const rawResult = executePayload(challenge.payload);
|
||||||
|
const responseEncoding = challenge.payload.responseEncoding || "plain";
|
||||||
|
const solution = encode(String(rawResult), responseEncoding);
|
||||||
|
const duration = Date.now() - startTime;
|
||||||
|
if (this.options.debug) {
|
||||||
|
console.log(`[CaptchaLM] Solved in ${duration}ms`);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
solution,
|
||||||
|
solveDuration: duration,
|
||||||
|
success: true
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
const duration = Date.now() - startTime;
|
||||||
|
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
||||||
|
if (this.options.debug) {
|
||||||
|
console.error(`[CaptchaLM] Failed to solve: ${errorMessage}`);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
solution: "",
|
||||||
|
solveDuration: duration,
|
||||||
|
success: false,
|
||||||
|
error: errorMessage
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Solve a challenge and return formatted headers for HTTP request
|
||||||
|
*/
|
||||||
|
solveForRequest(challenge) {
|
||||||
|
const result = this.solve(challenge);
|
||||||
|
if (!result.success) {
|
||||||
|
return {
|
||||||
|
headers: {},
|
||||||
|
body: { _CaptchaLMChallenge: challenge },
|
||||||
|
success: false,
|
||||||
|
error: result.error
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
headers: {
|
||||||
|
"x-captchalm-id": challenge.id,
|
||||||
|
"x-captchalm-solution": result.solution
|
||||||
|
},
|
||||||
|
body: {
|
||||||
|
_CaptchaLMChallenge: challenge
|
||||||
|
},
|
||||||
|
success: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Fetch a challenge from a server and solve it
|
||||||
|
*/
|
||||||
|
async fetchAndSolve(challengeUrl, fetchOptions) {
|
||||||
|
try {
|
||||||
|
const response = await fetch(challengeUrl, {
|
||||||
|
method: "GET",
|
||||||
|
...fetchOptions
|
||||||
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Failed to fetch challenge: ${response.statusText}`);
|
||||||
|
}
|
||||||
|
const data = await response.json();
|
||||||
|
if (!data.success || !data.challenge) {
|
||||||
|
throw new Error(data.error || "Invalid challenge response");
|
||||||
|
}
|
||||||
|
const challenge = data.challenge;
|
||||||
|
const result = this.solve(challenge);
|
||||||
|
return {
|
||||||
|
challenge,
|
||||||
|
solution: result.solution,
|
||||||
|
success: result.success,
|
||||||
|
error: result.error
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
challenge: null,
|
||||||
|
solution: "",
|
||||||
|
success: false,
|
||||||
|
error: error instanceof Error ? error.message : "Unknown error"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Complete a protected request including challenge solving
|
||||||
|
*/
|
||||||
|
async completeProtectedRequest(challengeUrl, protectedUrl, requestOptions) {
|
||||||
|
const { challenge, solution, success, error } = await this.fetchAndSolve(challengeUrl);
|
||||||
|
if (!success) {
|
||||||
|
throw new Error(`Failed to solve challenge: ${error}`);
|
||||||
|
}
|
||||||
|
const headers = new Headers(requestOptions?.headers);
|
||||||
|
headers.set("x-captchalm-id", challenge.id);
|
||||||
|
headers.set("x-captchalm-solution", solution);
|
||||||
|
headers.set("Content-Type", "application/json");
|
||||||
|
const body = requestOptions?.body ? { ...JSON.parse(requestOptions.body), _CaptchaLMChallenge: challenge } : { _CaptchaLMChallenge: challenge };
|
||||||
|
return fetch(protectedUrl, {
|
||||||
|
...requestOptions,
|
||||||
|
headers,
|
||||||
|
body: JSON.stringify(body)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
function createSolver(options) {
|
||||||
|
return new CaptchaLMSolver(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
export { CaptchaLMSolver, createSolver, executeChainedOperations, executeCodeTransform, executeEncodedInstruction, executeFunction, executePatternExtraction, executePayload };
|
||||||
|
//# sourceMappingURL=index.js.map
|
||||||
|
//# sourceMappingURL=index.js.map
|
||||||
1
node_modules/captchalm/dist/client/index.js.map
generated
vendored
Normal file
1
node_modules/captchalm/dist/client/index.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
4
node_modules/captchalm/dist/core/types.cjs
generated
vendored
Normal file
4
node_modules/captchalm/dist/core/types.cjs
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
//# sourceMappingURL=types.cjs.map
|
||||||
|
//# sourceMappingURL=types.cjs.map
|
||||||
1
node_modules/captchalm/dist/core/types.cjs.map
generated
vendored
Normal file
1
node_modules/captchalm/dist/core/types.cjs.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"sources":[],"names":[],"mappings":"","file":"types.cjs"}
|
||||||
149
node_modules/captchalm/dist/core/types.d.cts
generated
vendored
Normal file
149
node_modules/captchalm/dist/core/types.d.cts
generated
vendored
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
/**
|
||||||
|
* CaptchaLM - AI-Only Access Control
|
||||||
|
*
|
||||||
|
* Core type definitions for challenges, responses, and configurations
|
||||||
|
*/
|
||||||
|
type EncodingType = 'plain' | 'base64' | 'hex' | 'rot13';
|
||||||
|
type ChallengeType = 'function_execution' | 'chained_operations' | 'encoded_instruction' | 'pattern_extraction' | 'code_transform';
|
||||||
|
/**
|
||||||
|
* Function Execution Challenge
|
||||||
|
* Present a function definition and parameters, expect computed output
|
||||||
|
*/
|
||||||
|
interface FunctionExecutionPayload {
|
||||||
|
type: 'function_execution';
|
||||||
|
/** The function name to execute */
|
||||||
|
functionName: string;
|
||||||
|
/** Function code as a string */
|
||||||
|
functionCode: string;
|
||||||
|
/** Parameters to pass to the function */
|
||||||
|
parameters: unknown[];
|
||||||
|
/** Required encoding for the response */
|
||||||
|
responseEncoding: EncodingType;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Chained Operations Challenge
|
||||||
|
* Multi-step instructions requiring sequential execution
|
||||||
|
*/
|
||||||
|
interface ChainedOperationsPayload {
|
||||||
|
type: 'chained_operations';
|
||||||
|
/** Initial value to start with */
|
||||||
|
initialValue: number;
|
||||||
|
/** Operations to apply sequentially */
|
||||||
|
operations: ChainedOperation[];
|
||||||
|
/** Required encoding for the response */
|
||||||
|
responseEncoding: EncodingType;
|
||||||
|
}
|
||||||
|
interface ChainedOperation {
|
||||||
|
operation: 'add' | 'subtract' | 'multiply' | 'divide' | 'modulo' | 'power' | 'floor' | 'ceil' | 'abs' | 'negate';
|
||||||
|
value?: number;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Encoded Instruction Challenge
|
||||||
|
* Instructions encoded in various formats
|
||||||
|
*/
|
||||||
|
interface EncodedInstructionPayload {
|
||||||
|
type: 'encoded_instruction';
|
||||||
|
/** The encoded instruction */
|
||||||
|
instruction: string;
|
||||||
|
/** How the instruction is encoded */
|
||||||
|
instructionEncoding: EncodingType;
|
||||||
|
/** Required encoding for the response */
|
||||||
|
responseEncoding: EncodingType;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Pattern Extraction Challenge
|
||||||
|
* Extract specific patterns from structured data
|
||||||
|
*/
|
||||||
|
interface PatternExtractionPayload {
|
||||||
|
type: 'pattern_extraction';
|
||||||
|
/** The data to query */
|
||||||
|
data: Record<string, unknown>;
|
||||||
|
/** The query expression */
|
||||||
|
query: string;
|
||||||
|
/** Required encoding for the response */
|
||||||
|
responseEncoding: EncodingType;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Code Transform Challenge
|
||||||
|
* Transform code according to specified rules
|
||||||
|
*/
|
||||||
|
interface CodeTransformPayload {
|
||||||
|
type: 'code_transform';
|
||||||
|
/** The code to transform/execute */
|
||||||
|
code: string;
|
||||||
|
/** The transformation to apply */
|
||||||
|
transform: 'execute' | 'execute_and_hash' | 'execute_and_base64';
|
||||||
|
/** Required encoding for the response */
|
||||||
|
responseEncoding: EncodingType;
|
||||||
|
}
|
||||||
|
type ChallengePayload = FunctionExecutionPayload | ChainedOperationsPayload | EncodedInstructionPayload | PatternExtractionPayload | CodeTransformPayload;
|
||||||
|
interface Challenge {
|
||||||
|
/** Unique challenge identifier */
|
||||||
|
id: string;
|
||||||
|
/** Type of challenge */
|
||||||
|
type: ChallengeType;
|
||||||
|
/** Difficulty level */
|
||||||
|
difficulty: ChallengeDifficulty;
|
||||||
|
/** Challenge-specific payload */
|
||||||
|
payload: ChallengePayload;
|
||||||
|
/** Expiration timestamp (Unix ms) */
|
||||||
|
expiresAt: number;
|
||||||
|
/** HMAC signature for integrity verification */
|
||||||
|
signature: string;
|
||||||
|
}
|
||||||
|
type ChallengeDifficulty = 'easy' | 'medium' | 'hard';
|
||||||
|
interface ChallengeSolution {
|
||||||
|
/** Challenge ID being solved */
|
||||||
|
challengeId: string;
|
||||||
|
/** The computed solution */
|
||||||
|
solution: string;
|
||||||
|
}
|
||||||
|
interface VerificationResult {
|
||||||
|
/** Whether the solution is valid */
|
||||||
|
valid: boolean;
|
||||||
|
/** Error message if invalid */
|
||||||
|
error?: string;
|
||||||
|
/** Error code for programmatic handling */
|
||||||
|
errorCode?: VerificationErrorCode;
|
||||||
|
}
|
||||||
|
type VerificationErrorCode = 'EXPIRED' | 'INVALID_SIGNATURE' | 'INVALID_SOLUTION' | 'RATE_LIMITED' | 'CHALLENGE_NOT_FOUND';
|
||||||
|
interface CaptchaLMConfig {
|
||||||
|
/** Secret key for HMAC signing */
|
||||||
|
secret: string;
|
||||||
|
/** Default difficulty level */
|
||||||
|
difficulty?: ChallengeDifficulty;
|
||||||
|
/** Challenge types to use (defaults to all) */
|
||||||
|
challengeTypes?: ChallengeType[];
|
||||||
|
/** Challenge expiration time in milliseconds */
|
||||||
|
expirationMs?: number;
|
||||||
|
/** Rate limiting configuration */
|
||||||
|
rateLimit?: RateLimitConfig;
|
||||||
|
}
|
||||||
|
interface RateLimitConfig {
|
||||||
|
/** Maximum attempts per window */
|
||||||
|
maxAttempts: number;
|
||||||
|
/** Window duration in milliseconds */
|
||||||
|
windowMs: number;
|
||||||
|
}
|
||||||
|
interface RegisteredFunction {
|
||||||
|
/** Function name */
|
||||||
|
name: string;
|
||||||
|
/** Function implementation */
|
||||||
|
fn: (...args: unknown[]) => unknown;
|
||||||
|
/** Parameter types for validation */
|
||||||
|
parameterTypes: string[];
|
||||||
|
/** Description for documentation */
|
||||||
|
description: string;
|
||||||
|
/** Difficulty level of this function */
|
||||||
|
difficulty: ChallengeDifficulty;
|
||||||
|
}
|
||||||
|
interface MiddlewareConfig extends CaptchaLMConfig {
|
||||||
|
/** Header name for challenge ID */
|
||||||
|
challengeIdHeader?: string;
|
||||||
|
/** Header name for solution */
|
||||||
|
solutionHeader?: string;
|
||||||
|
/** Path to challenge endpoint */
|
||||||
|
challengeEndpoint?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type { CaptchaLMConfig, ChainedOperation, ChainedOperationsPayload, Challenge, ChallengeDifficulty, ChallengePayload, ChallengeSolution, ChallengeType, CodeTransformPayload, EncodedInstructionPayload, EncodingType, FunctionExecutionPayload, MiddlewareConfig, PatternExtractionPayload, RateLimitConfig, RegisteredFunction, VerificationErrorCode, VerificationResult };
|
||||||
149
node_modules/captchalm/dist/core/types.d.ts
generated
vendored
Normal file
149
node_modules/captchalm/dist/core/types.d.ts
generated
vendored
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
/**
|
||||||
|
* CaptchaLM - AI-Only Access Control
|
||||||
|
*
|
||||||
|
* Core type definitions for challenges, responses, and configurations
|
||||||
|
*/
|
||||||
|
type EncodingType = 'plain' | 'base64' | 'hex' | 'rot13';
|
||||||
|
type ChallengeType = 'function_execution' | 'chained_operations' | 'encoded_instruction' | 'pattern_extraction' | 'code_transform';
|
||||||
|
/**
|
||||||
|
* Function Execution Challenge
|
||||||
|
* Present a function definition and parameters, expect computed output
|
||||||
|
*/
|
||||||
|
interface FunctionExecutionPayload {
|
||||||
|
type: 'function_execution';
|
||||||
|
/** The function name to execute */
|
||||||
|
functionName: string;
|
||||||
|
/** Function code as a string */
|
||||||
|
functionCode: string;
|
||||||
|
/** Parameters to pass to the function */
|
||||||
|
parameters: unknown[];
|
||||||
|
/** Required encoding for the response */
|
||||||
|
responseEncoding: EncodingType;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Chained Operations Challenge
|
||||||
|
* Multi-step instructions requiring sequential execution
|
||||||
|
*/
|
||||||
|
interface ChainedOperationsPayload {
|
||||||
|
type: 'chained_operations';
|
||||||
|
/** Initial value to start with */
|
||||||
|
initialValue: number;
|
||||||
|
/** Operations to apply sequentially */
|
||||||
|
operations: ChainedOperation[];
|
||||||
|
/** Required encoding for the response */
|
||||||
|
responseEncoding: EncodingType;
|
||||||
|
}
|
||||||
|
interface ChainedOperation {
|
||||||
|
operation: 'add' | 'subtract' | 'multiply' | 'divide' | 'modulo' | 'power' | 'floor' | 'ceil' | 'abs' | 'negate';
|
||||||
|
value?: number;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Encoded Instruction Challenge
|
||||||
|
* Instructions encoded in various formats
|
||||||
|
*/
|
||||||
|
interface EncodedInstructionPayload {
|
||||||
|
type: 'encoded_instruction';
|
||||||
|
/** The encoded instruction */
|
||||||
|
instruction: string;
|
||||||
|
/** How the instruction is encoded */
|
||||||
|
instructionEncoding: EncodingType;
|
||||||
|
/** Required encoding for the response */
|
||||||
|
responseEncoding: EncodingType;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Pattern Extraction Challenge
|
||||||
|
* Extract specific patterns from structured data
|
||||||
|
*/
|
||||||
|
interface PatternExtractionPayload {
|
||||||
|
type: 'pattern_extraction';
|
||||||
|
/** The data to query */
|
||||||
|
data: Record<string, unknown>;
|
||||||
|
/** The query expression */
|
||||||
|
query: string;
|
||||||
|
/** Required encoding for the response */
|
||||||
|
responseEncoding: EncodingType;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Code Transform Challenge
|
||||||
|
* Transform code according to specified rules
|
||||||
|
*/
|
||||||
|
interface CodeTransformPayload {
|
||||||
|
type: 'code_transform';
|
||||||
|
/** The code to transform/execute */
|
||||||
|
code: string;
|
||||||
|
/** The transformation to apply */
|
||||||
|
transform: 'execute' | 'execute_and_hash' | 'execute_and_base64';
|
||||||
|
/** Required encoding for the response */
|
||||||
|
responseEncoding: EncodingType;
|
||||||
|
}
|
||||||
|
type ChallengePayload = FunctionExecutionPayload | ChainedOperationsPayload | EncodedInstructionPayload | PatternExtractionPayload | CodeTransformPayload;
|
||||||
|
interface Challenge {
|
||||||
|
/** Unique challenge identifier */
|
||||||
|
id: string;
|
||||||
|
/** Type of challenge */
|
||||||
|
type: ChallengeType;
|
||||||
|
/** Difficulty level */
|
||||||
|
difficulty: ChallengeDifficulty;
|
||||||
|
/** Challenge-specific payload */
|
||||||
|
payload: ChallengePayload;
|
||||||
|
/** Expiration timestamp (Unix ms) */
|
||||||
|
expiresAt: number;
|
||||||
|
/** HMAC signature for integrity verification */
|
||||||
|
signature: string;
|
||||||
|
}
|
||||||
|
type ChallengeDifficulty = 'easy' | 'medium' | 'hard';
|
||||||
|
interface ChallengeSolution {
|
||||||
|
/** Challenge ID being solved */
|
||||||
|
challengeId: string;
|
||||||
|
/** The computed solution */
|
||||||
|
solution: string;
|
||||||
|
}
|
||||||
|
interface VerificationResult {
|
||||||
|
/** Whether the solution is valid */
|
||||||
|
valid: boolean;
|
||||||
|
/** Error message if invalid */
|
||||||
|
error?: string;
|
||||||
|
/** Error code for programmatic handling */
|
||||||
|
errorCode?: VerificationErrorCode;
|
||||||
|
}
|
||||||
|
type VerificationErrorCode = 'EXPIRED' | 'INVALID_SIGNATURE' | 'INVALID_SOLUTION' | 'RATE_LIMITED' | 'CHALLENGE_NOT_FOUND';
|
||||||
|
interface CaptchaLMConfig {
|
||||||
|
/** Secret key for HMAC signing */
|
||||||
|
secret: string;
|
||||||
|
/** Default difficulty level */
|
||||||
|
difficulty?: ChallengeDifficulty;
|
||||||
|
/** Challenge types to use (defaults to all) */
|
||||||
|
challengeTypes?: ChallengeType[];
|
||||||
|
/** Challenge expiration time in milliseconds */
|
||||||
|
expirationMs?: number;
|
||||||
|
/** Rate limiting configuration */
|
||||||
|
rateLimit?: RateLimitConfig;
|
||||||
|
}
|
||||||
|
interface RateLimitConfig {
|
||||||
|
/** Maximum attempts per window */
|
||||||
|
maxAttempts: number;
|
||||||
|
/** Window duration in milliseconds */
|
||||||
|
windowMs: number;
|
||||||
|
}
|
||||||
|
interface RegisteredFunction {
|
||||||
|
/** Function name */
|
||||||
|
name: string;
|
||||||
|
/** Function implementation */
|
||||||
|
fn: (...args: unknown[]) => unknown;
|
||||||
|
/** Parameter types for validation */
|
||||||
|
parameterTypes: string[];
|
||||||
|
/** Description for documentation */
|
||||||
|
description: string;
|
||||||
|
/** Difficulty level of this function */
|
||||||
|
difficulty: ChallengeDifficulty;
|
||||||
|
}
|
||||||
|
interface MiddlewareConfig extends CaptchaLMConfig {
|
||||||
|
/** Header name for challenge ID */
|
||||||
|
challengeIdHeader?: string;
|
||||||
|
/** Header name for solution */
|
||||||
|
solutionHeader?: string;
|
||||||
|
/** Path to challenge endpoint */
|
||||||
|
challengeEndpoint?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type { CaptchaLMConfig, ChainedOperation, ChainedOperationsPayload, Challenge, ChallengeDifficulty, ChallengePayload, ChallengeSolution, ChallengeType, CodeTransformPayload, EncodedInstructionPayload, EncodingType, FunctionExecutionPayload, MiddlewareConfig, PatternExtractionPayload, RateLimitConfig, RegisteredFunction, VerificationErrorCode, VerificationResult };
|
||||||
3
node_modules/captchalm/dist/core/types.js
generated
vendored
Normal file
3
node_modules/captchalm/dist/core/types.js
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
|
||||||
|
//# sourceMappingURL=types.js.map
|
||||||
|
//# sourceMappingURL=types.js.map
|
||||||
1
node_modules/captchalm/dist/core/types.js.map
generated
vendored
Normal file
1
node_modules/captchalm/dist/core/types.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"sources":[],"names":[],"mappings":"","file":"types.js"}
|
||||||
1924
node_modules/captchalm/dist/index.cjs
generated
vendored
Normal file
1924
node_modules/captchalm/dist/index.cjs
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
node_modules/captchalm/dist/index.cjs.map
generated
vendored
Normal file
1
node_modules/captchalm/dist/index.cjs.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
321
node_modules/captchalm/dist/index.d.cts
generated
vendored
Normal file
321
node_modules/captchalm/dist/index.d.cts
generated
vendored
Normal file
@@ -0,0 +1,321 @@
|
|||||||
|
import { EncodingType, CaptchaLMConfig, ChallengeType, ChallengeDifficulty, Challenge, ChallengeSolution, VerificationResult, MiddlewareConfig, RegisteredFunction } from './core/types.cjs';
|
||||||
|
export { ChainedOperation, ChainedOperationsPayload, ChallengePayload, CodeTransformPayload, EncodedInstructionPayload, FunctionExecutionPayload, PatternExtractionPayload, RateLimitConfig, VerificationErrorCode } from './core/types.cjs';
|
||||||
|
import { Request, RequestHandler } from 'express';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encoding utilities for CaptchaLM challenges
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode a value using the specified encoding
|
||||||
|
*/
|
||||||
|
declare function encode(value: string, encoding: EncodingType): string;
|
||||||
|
/**
|
||||||
|
* Decode a value using the specified encoding
|
||||||
|
*/
|
||||||
|
declare function decode(value: string, encoding: EncodingType): string;
|
||||||
|
/**
|
||||||
|
* Base64 encode a string
|
||||||
|
*/
|
||||||
|
declare function encodeBase64(value: string): string;
|
||||||
|
/**
|
||||||
|
* Base64 decode a string
|
||||||
|
*/
|
||||||
|
declare function decodeBase64(value: string): string;
|
||||||
|
/**
|
||||||
|
* Hex encode a string
|
||||||
|
*/
|
||||||
|
declare function encodeHex(value: string): string;
|
||||||
|
/**
|
||||||
|
* Hex decode a string
|
||||||
|
*/
|
||||||
|
declare function decodeHex(value: string): string;
|
||||||
|
/**
|
||||||
|
* ROT13 encode/decode a string (symmetric cipher)
|
||||||
|
*/
|
||||||
|
declare function encodeRot13(value: string): string;
|
||||||
|
/**
|
||||||
|
* ROT13 decode (same as encode, symmetric)
|
||||||
|
*/
|
||||||
|
declare function decodeRot13(value: string): string;
|
||||||
|
/**
|
||||||
|
* Apply multiple encoding layers
|
||||||
|
*/
|
||||||
|
declare function encodeChain(value: string, encodings: EncodingType[]): string;
|
||||||
|
/**
|
||||||
|
* Decode multiple encoding layers (in reverse order)
|
||||||
|
*/
|
||||||
|
declare function decodeChain(value: string, encodings: EncodingType[]): string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Challenge generator for CaptchaLM
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Challenge generator class
|
||||||
|
*/
|
||||||
|
declare class ChallengeGenerator {
|
||||||
|
private config;
|
||||||
|
constructor(config: CaptchaLMConfig);
|
||||||
|
/**
|
||||||
|
* Generate a new challenge
|
||||||
|
*/
|
||||||
|
generate(overrides?: Partial<{
|
||||||
|
type: ChallengeType;
|
||||||
|
difficulty: ChallengeDifficulty;
|
||||||
|
}>): {
|
||||||
|
challenge: Challenge;
|
||||||
|
expectedAnswer: string;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Generate payload for a specific challenge type
|
||||||
|
*/
|
||||||
|
private generatePayload;
|
||||||
|
/**
|
||||||
|
* Generate a function execution challenge
|
||||||
|
*/
|
||||||
|
private generateFunctionExecution;
|
||||||
|
/**
|
||||||
|
* Generate a chained operations challenge
|
||||||
|
*/
|
||||||
|
private generateChainedOperations;
|
||||||
|
/**
|
||||||
|
* Generate an encoded instruction challenge
|
||||||
|
*/
|
||||||
|
private generateEncodedInstruction;
|
||||||
|
/**
|
||||||
|
* Generate a pattern extraction challenge
|
||||||
|
*/
|
||||||
|
private generatePatternExtraction;
|
||||||
|
/**
|
||||||
|
* Generate a code transform challenge
|
||||||
|
*/
|
||||||
|
private generateCodeTransform;
|
||||||
|
/**
|
||||||
|
* Get response encoding based on difficulty
|
||||||
|
*/
|
||||||
|
private getResponseEncoding;
|
||||||
|
/**
|
||||||
|
* Get instruction encoding based on difficulty
|
||||||
|
*/
|
||||||
|
private getInstructionEncoding;
|
||||||
|
/**
|
||||||
|
* Generate parameters for a function
|
||||||
|
*/
|
||||||
|
private generateParameters;
|
||||||
|
/**
|
||||||
|
* Generate random words joined by spaces
|
||||||
|
*/
|
||||||
|
private generateRandomWords;
|
||||||
|
/**
|
||||||
|
* Generate a random word
|
||||||
|
*/
|
||||||
|
private generateRandomWord;
|
||||||
|
/**
|
||||||
|
* Mutate a word by changing N characters
|
||||||
|
*/
|
||||||
|
private mutateWord;
|
||||||
|
/**
|
||||||
|
* Generate a random array of numbers
|
||||||
|
*/
|
||||||
|
private generateRandomArray;
|
||||||
|
/**
|
||||||
|
* Get function code as string (for display)
|
||||||
|
*/
|
||||||
|
private getFunctionCodeString;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Create a challenge generator
|
||||||
|
*/
|
||||||
|
declare function createGenerator(config: CaptchaLMConfig): ChallengeGenerator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Challenge verifier for CaptchaLM
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Challenge verifier class
|
||||||
|
*/
|
||||||
|
declare class ChallengeVerifier {
|
||||||
|
private config;
|
||||||
|
private rateLimiter;
|
||||||
|
private challengeStore;
|
||||||
|
private cleanupInterval;
|
||||||
|
constructor(config: CaptchaLMConfig);
|
||||||
|
/**
|
||||||
|
* Store expected answer for a challenge
|
||||||
|
*/
|
||||||
|
storeChallenge(challengeId: string, expectedAnswer: string, expiresAt: number): void;
|
||||||
|
/**
|
||||||
|
* Verify a challenge solution
|
||||||
|
*/
|
||||||
|
verify(challenge: Challenge, solution: ChallengeSolution, clientIdentifier?: string): VerificationResult;
|
||||||
|
/**
|
||||||
|
* Verify a solution using only the signature (stateless mode)
|
||||||
|
*
|
||||||
|
* In stateless mode, the expected answer is encoded in the signature
|
||||||
|
* This is less secure but allows for distributed deployments
|
||||||
|
*/
|
||||||
|
verifyStateless(challenge: Challenge, solution: ChallengeSolution, clientIdentifier?: string): VerificationResult;
|
||||||
|
/**
|
||||||
|
* Get rate limit status for a client
|
||||||
|
*/
|
||||||
|
getRateLimitStatus(clientIdentifier: string): {
|
||||||
|
remaining: number;
|
||||||
|
isLimited: boolean;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Start periodic cleanup of expired challenges
|
||||||
|
*/
|
||||||
|
private startCleanup;
|
||||||
|
/**
|
||||||
|
* Clean up expired challenges
|
||||||
|
*/
|
||||||
|
private cleanup;
|
||||||
|
/**
|
||||||
|
* Destroy the verifier and clean up resources
|
||||||
|
*/
|
||||||
|
destroy(): void;
|
||||||
|
/**
|
||||||
|
* Get stats for monitoring
|
||||||
|
*/
|
||||||
|
getStats(): {
|
||||||
|
pendingChallenges: number;
|
||||||
|
rateLimitStats: {
|
||||||
|
activeKeys: number;
|
||||||
|
totalAttempts: number;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Create a challenge verifier
|
||||||
|
*/
|
||||||
|
declare function createVerifier(config: CaptchaLMConfig): ChallengeVerifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Standalone CaptchaLM API
|
||||||
|
* Framework-agnostic implementation for custom integrations
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main CaptchaLM class for standalone usage
|
||||||
|
*/
|
||||||
|
declare class CaptchaLM {
|
||||||
|
private generator;
|
||||||
|
private verifier;
|
||||||
|
private config;
|
||||||
|
constructor(config: CaptchaLMConfig);
|
||||||
|
/**
|
||||||
|
* Generate a new challenge
|
||||||
|
*/
|
||||||
|
generate(options?: {
|
||||||
|
type?: ChallengeType;
|
||||||
|
difficulty?: ChallengeDifficulty;
|
||||||
|
}): {
|
||||||
|
challenge: Challenge;
|
||||||
|
expectedAnswer: string;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Verify a challenge solution
|
||||||
|
*/
|
||||||
|
verify(challenge: Challenge, solution: string, clientIdentifier?: string): VerificationResult;
|
||||||
|
/**
|
||||||
|
* Verify a challenge solution in stateless mode
|
||||||
|
* (no server-side storage required)
|
||||||
|
*/
|
||||||
|
verifyStateless(challenge: Challenge, solution: string, clientIdentifier?: string): VerificationResult;
|
||||||
|
/**
|
||||||
|
* Get rate limit status for a client
|
||||||
|
*/
|
||||||
|
getRateLimitStatus(clientIdentifier: string): {
|
||||||
|
remaining: number;
|
||||||
|
isLimited: boolean;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Get stats for monitoring
|
||||||
|
*/
|
||||||
|
getStats(): {
|
||||||
|
pendingChallenges: number;
|
||||||
|
rateLimitStats: {
|
||||||
|
activeKeys: number;
|
||||||
|
totalAttempts: number;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Get the current configuration
|
||||||
|
*/
|
||||||
|
getConfig(): CaptchaLMConfig;
|
||||||
|
/**
|
||||||
|
* Destroy and clean up resources
|
||||||
|
*/
|
||||||
|
destroy(): void;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Create an CaptchaLM instance
|
||||||
|
*/
|
||||||
|
declare function createCaptchaLM(config: CaptchaLMConfig): CaptchaLM;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Express middleware for CaptchaLM
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extended request with CaptchaLM properties
|
||||||
|
*/
|
||||||
|
interface CaptchaLMRequest extends Request {
|
||||||
|
CaptchaLM?: {
|
||||||
|
verified: boolean;
|
||||||
|
challenge?: Challenge;
|
||||||
|
clientIdentifier: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Create Express middleware for CaptchaLM protection
|
||||||
|
*/
|
||||||
|
declare function createExpressMiddleware(config: MiddlewareConfig): {
|
||||||
|
protect: RequestHandler;
|
||||||
|
challenge: RequestHandler;
|
||||||
|
generator: ChallengeGenerator;
|
||||||
|
verifier: ChallengeVerifier;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Create a simple verification endpoint
|
||||||
|
*/
|
||||||
|
declare function createVerificationEndpoint(config: MiddlewareConfig): RequestHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function registry for CaptchaLM challenges
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Combined registry of all available functions
|
||||||
|
*/
|
||||||
|
declare const allFunctions: RegisteredFunction[];
|
||||||
|
/**
|
||||||
|
* Get functions filtered by difficulty
|
||||||
|
*/
|
||||||
|
declare function getFunctionsByDifficulty(difficulty: ChallengeDifficulty): RegisteredFunction[];
|
||||||
|
/**
|
||||||
|
* Get a function by name
|
||||||
|
*/
|
||||||
|
declare function getFunctionByName(name: string): RegisteredFunction | undefined;
|
||||||
|
/**
|
||||||
|
* Get a random function matching the difficulty
|
||||||
|
*/
|
||||||
|
declare function getRandomFunction(difficulty?: ChallengeDifficulty): RegisteredFunction;
|
||||||
|
/**
|
||||||
|
* Function categories for organization
|
||||||
|
*/
|
||||||
|
declare const functionCategories: {
|
||||||
|
readonly math: RegisteredFunction[];
|
||||||
|
readonly string: RegisteredFunction[];
|
||||||
|
readonly array: RegisteredFunction[];
|
||||||
|
readonly composite: RegisteredFunction[];
|
||||||
|
};
|
||||||
|
type FunctionCategory = keyof typeof functionCategories;
|
||||||
|
/**
|
||||||
|
* Get functions by category
|
||||||
|
*/
|
||||||
|
declare function getFunctionsByCategory(category: FunctionCategory): RegisteredFunction[];
|
||||||
|
|
||||||
|
export { CaptchaLM, CaptchaLMConfig, type CaptchaLMRequest, Challenge, ChallengeDifficulty, ChallengeGenerator, ChallengeSolution, ChallengeType, ChallengeVerifier, EncodingType, MiddlewareConfig, RegisteredFunction, VerificationResult, allFunctions, createCaptchaLM, createExpressMiddleware, createGenerator, createVerificationEndpoint, createVerifier, decode, decodeBase64, decodeChain, decodeHex, decodeRot13, encode, encodeBase64, encodeChain, encodeHex, encodeRot13, functionCategories, getFunctionByName, getFunctionsByCategory, getFunctionsByDifficulty, getRandomFunction };
|
||||||
321
node_modules/captchalm/dist/index.d.ts
generated
vendored
Normal file
321
node_modules/captchalm/dist/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,321 @@
|
|||||||
|
import { EncodingType, CaptchaLMConfig, ChallengeType, ChallengeDifficulty, Challenge, ChallengeSolution, VerificationResult, MiddlewareConfig, RegisteredFunction } from './core/types.js';
|
||||||
|
export { ChainedOperation, ChainedOperationsPayload, ChallengePayload, CodeTransformPayload, EncodedInstructionPayload, FunctionExecutionPayload, PatternExtractionPayload, RateLimitConfig, VerificationErrorCode } from './core/types.js';
|
||||||
|
import { Request, RequestHandler } from 'express';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encoding utilities for CaptchaLM challenges
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode a value using the specified encoding
|
||||||
|
*/
|
||||||
|
declare function encode(value: string, encoding: EncodingType): string;
|
||||||
|
/**
|
||||||
|
* Decode a value using the specified encoding
|
||||||
|
*/
|
||||||
|
declare function decode(value: string, encoding: EncodingType): string;
|
||||||
|
/**
|
||||||
|
* Base64 encode a string
|
||||||
|
*/
|
||||||
|
declare function encodeBase64(value: string): string;
|
||||||
|
/**
|
||||||
|
* Base64 decode a string
|
||||||
|
*/
|
||||||
|
declare function decodeBase64(value: string): string;
|
||||||
|
/**
|
||||||
|
* Hex encode a string
|
||||||
|
*/
|
||||||
|
declare function encodeHex(value: string): string;
|
||||||
|
/**
|
||||||
|
* Hex decode a string
|
||||||
|
*/
|
||||||
|
declare function decodeHex(value: string): string;
|
||||||
|
/**
|
||||||
|
* ROT13 encode/decode a string (symmetric cipher)
|
||||||
|
*/
|
||||||
|
declare function encodeRot13(value: string): string;
|
||||||
|
/**
|
||||||
|
* ROT13 decode (same as encode, symmetric)
|
||||||
|
*/
|
||||||
|
declare function decodeRot13(value: string): string;
|
||||||
|
/**
|
||||||
|
* Apply multiple encoding layers
|
||||||
|
*/
|
||||||
|
declare function encodeChain(value: string, encodings: EncodingType[]): string;
|
||||||
|
/**
|
||||||
|
* Decode multiple encoding layers (in reverse order)
|
||||||
|
*/
|
||||||
|
declare function decodeChain(value: string, encodings: EncodingType[]): string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Challenge generator for CaptchaLM
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Challenge generator class
|
||||||
|
*/
|
||||||
|
declare class ChallengeGenerator {
|
||||||
|
private config;
|
||||||
|
constructor(config: CaptchaLMConfig);
|
||||||
|
/**
|
||||||
|
* Generate a new challenge
|
||||||
|
*/
|
||||||
|
generate(overrides?: Partial<{
|
||||||
|
type: ChallengeType;
|
||||||
|
difficulty: ChallengeDifficulty;
|
||||||
|
}>): {
|
||||||
|
challenge: Challenge;
|
||||||
|
expectedAnswer: string;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Generate payload for a specific challenge type
|
||||||
|
*/
|
||||||
|
private generatePayload;
|
||||||
|
/**
|
||||||
|
* Generate a function execution challenge
|
||||||
|
*/
|
||||||
|
private generateFunctionExecution;
|
||||||
|
/**
|
||||||
|
* Generate a chained operations challenge
|
||||||
|
*/
|
||||||
|
private generateChainedOperations;
|
||||||
|
/**
|
||||||
|
* Generate an encoded instruction challenge
|
||||||
|
*/
|
||||||
|
private generateEncodedInstruction;
|
||||||
|
/**
|
||||||
|
* Generate a pattern extraction challenge
|
||||||
|
*/
|
||||||
|
private generatePatternExtraction;
|
||||||
|
/**
|
||||||
|
* Generate a code transform challenge
|
||||||
|
*/
|
||||||
|
private generateCodeTransform;
|
||||||
|
/**
|
||||||
|
* Get response encoding based on difficulty
|
||||||
|
*/
|
||||||
|
private getResponseEncoding;
|
||||||
|
/**
|
||||||
|
* Get instruction encoding based on difficulty
|
||||||
|
*/
|
||||||
|
private getInstructionEncoding;
|
||||||
|
/**
|
||||||
|
* Generate parameters for a function
|
||||||
|
*/
|
||||||
|
private generateParameters;
|
||||||
|
/**
|
||||||
|
* Generate random words joined by spaces
|
||||||
|
*/
|
||||||
|
private generateRandomWords;
|
||||||
|
/**
|
||||||
|
* Generate a random word
|
||||||
|
*/
|
||||||
|
private generateRandomWord;
|
||||||
|
/**
|
||||||
|
* Mutate a word by changing N characters
|
||||||
|
*/
|
||||||
|
private mutateWord;
|
||||||
|
/**
|
||||||
|
* Generate a random array of numbers
|
||||||
|
*/
|
||||||
|
private generateRandomArray;
|
||||||
|
/**
|
||||||
|
* Get function code as string (for display)
|
||||||
|
*/
|
||||||
|
private getFunctionCodeString;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Create a challenge generator
|
||||||
|
*/
|
||||||
|
declare function createGenerator(config: CaptchaLMConfig): ChallengeGenerator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Challenge verifier for CaptchaLM
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Challenge verifier class
|
||||||
|
*/
|
||||||
|
declare class ChallengeVerifier {
|
||||||
|
private config;
|
||||||
|
private rateLimiter;
|
||||||
|
private challengeStore;
|
||||||
|
private cleanupInterval;
|
||||||
|
constructor(config: CaptchaLMConfig);
|
||||||
|
/**
|
||||||
|
* Store expected answer for a challenge
|
||||||
|
*/
|
||||||
|
storeChallenge(challengeId: string, expectedAnswer: string, expiresAt: number): void;
|
||||||
|
/**
|
||||||
|
* Verify a challenge solution
|
||||||
|
*/
|
||||||
|
verify(challenge: Challenge, solution: ChallengeSolution, clientIdentifier?: string): VerificationResult;
|
||||||
|
/**
|
||||||
|
* Verify a solution using only the signature (stateless mode)
|
||||||
|
*
|
||||||
|
* In stateless mode, the expected answer is encoded in the signature
|
||||||
|
* This is less secure but allows for distributed deployments
|
||||||
|
*/
|
||||||
|
verifyStateless(challenge: Challenge, solution: ChallengeSolution, clientIdentifier?: string): VerificationResult;
|
||||||
|
/**
|
||||||
|
* Get rate limit status for a client
|
||||||
|
*/
|
||||||
|
getRateLimitStatus(clientIdentifier: string): {
|
||||||
|
remaining: number;
|
||||||
|
isLimited: boolean;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Start periodic cleanup of expired challenges
|
||||||
|
*/
|
||||||
|
private startCleanup;
|
||||||
|
/**
|
||||||
|
* Clean up expired challenges
|
||||||
|
*/
|
||||||
|
private cleanup;
|
||||||
|
/**
|
||||||
|
* Destroy the verifier and clean up resources
|
||||||
|
*/
|
||||||
|
destroy(): void;
|
||||||
|
/**
|
||||||
|
* Get stats for monitoring
|
||||||
|
*/
|
||||||
|
getStats(): {
|
||||||
|
pendingChallenges: number;
|
||||||
|
rateLimitStats: {
|
||||||
|
activeKeys: number;
|
||||||
|
totalAttempts: number;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Create a challenge verifier
|
||||||
|
*/
|
||||||
|
declare function createVerifier(config: CaptchaLMConfig): ChallengeVerifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Standalone CaptchaLM API
|
||||||
|
* Framework-agnostic implementation for custom integrations
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main CaptchaLM class for standalone usage
|
||||||
|
*/
|
||||||
|
declare class CaptchaLM {
|
||||||
|
private generator;
|
||||||
|
private verifier;
|
||||||
|
private config;
|
||||||
|
constructor(config: CaptchaLMConfig);
|
||||||
|
/**
|
||||||
|
* Generate a new challenge
|
||||||
|
*/
|
||||||
|
generate(options?: {
|
||||||
|
type?: ChallengeType;
|
||||||
|
difficulty?: ChallengeDifficulty;
|
||||||
|
}): {
|
||||||
|
challenge: Challenge;
|
||||||
|
expectedAnswer: string;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Verify a challenge solution
|
||||||
|
*/
|
||||||
|
verify(challenge: Challenge, solution: string, clientIdentifier?: string): VerificationResult;
|
||||||
|
/**
|
||||||
|
* Verify a challenge solution in stateless mode
|
||||||
|
* (no server-side storage required)
|
||||||
|
*/
|
||||||
|
verifyStateless(challenge: Challenge, solution: string, clientIdentifier?: string): VerificationResult;
|
||||||
|
/**
|
||||||
|
* Get rate limit status for a client
|
||||||
|
*/
|
||||||
|
getRateLimitStatus(clientIdentifier: string): {
|
||||||
|
remaining: number;
|
||||||
|
isLimited: boolean;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Get stats for monitoring
|
||||||
|
*/
|
||||||
|
getStats(): {
|
||||||
|
pendingChallenges: number;
|
||||||
|
rateLimitStats: {
|
||||||
|
activeKeys: number;
|
||||||
|
totalAttempts: number;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Get the current configuration
|
||||||
|
*/
|
||||||
|
getConfig(): CaptchaLMConfig;
|
||||||
|
/**
|
||||||
|
* Destroy and clean up resources
|
||||||
|
*/
|
||||||
|
destroy(): void;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Create an CaptchaLM instance
|
||||||
|
*/
|
||||||
|
declare function createCaptchaLM(config: CaptchaLMConfig): CaptchaLM;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Express middleware for CaptchaLM
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extended request with CaptchaLM properties
|
||||||
|
*/
|
||||||
|
interface CaptchaLMRequest extends Request {
|
||||||
|
CaptchaLM?: {
|
||||||
|
verified: boolean;
|
||||||
|
challenge?: Challenge;
|
||||||
|
clientIdentifier: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Create Express middleware for CaptchaLM protection
|
||||||
|
*/
|
||||||
|
declare function createExpressMiddleware(config: MiddlewareConfig): {
|
||||||
|
protect: RequestHandler;
|
||||||
|
challenge: RequestHandler;
|
||||||
|
generator: ChallengeGenerator;
|
||||||
|
verifier: ChallengeVerifier;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Create a simple verification endpoint
|
||||||
|
*/
|
||||||
|
declare function createVerificationEndpoint(config: MiddlewareConfig): RequestHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function registry for CaptchaLM challenges
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Combined registry of all available functions
|
||||||
|
*/
|
||||||
|
declare const allFunctions: RegisteredFunction[];
|
||||||
|
/**
|
||||||
|
* Get functions filtered by difficulty
|
||||||
|
*/
|
||||||
|
declare function getFunctionsByDifficulty(difficulty: ChallengeDifficulty): RegisteredFunction[];
|
||||||
|
/**
|
||||||
|
* Get a function by name
|
||||||
|
*/
|
||||||
|
declare function getFunctionByName(name: string): RegisteredFunction | undefined;
|
||||||
|
/**
|
||||||
|
* Get a random function matching the difficulty
|
||||||
|
*/
|
||||||
|
declare function getRandomFunction(difficulty?: ChallengeDifficulty): RegisteredFunction;
|
||||||
|
/**
|
||||||
|
* Function categories for organization
|
||||||
|
*/
|
||||||
|
declare const functionCategories: {
|
||||||
|
readonly math: RegisteredFunction[];
|
||||||
|
readonly string: RegisteredFunction[];
|
||||||
|
readonly array: RegisteredFunction[];
|
||||||
|
readonly composite: RegisteredFunction[];
|
||||||
|
};
|
||||||
|
type FunctionCategory = keyof typeof functionCategories;
|
||||||
|
/**
|
||||||
|
* Get functions by category
|
||||||
|
*/
|
||||||
|
declare function getFunctionsByCategory(category: FunctionCategory): RegisteredFunction[];
|
||||||
|
|
||||||
|
export { CaptchaLM, CaptchaLMConfig, type CaptchaLMRequest, Challenge, ChallengeDifficulty, ChallengeGenerator, ChallengeSolution, ChallengeType, ChallengeVerifier, EncodingType, MiddlewareConfig, RegisteredFunction, VerificationResult, allFunctions, createCaptchaLM, createExpressMiddleware, createGenerator, createVerificationEndpoint, createVerifier, decode, decodeBase64, decodeChain, decodeHex, decodeRot13, encode, encodeBase64, encodeChain, encodeHex, encodeRot13, functionCategories, getFunctionByName, getFunctionsByCategory, getFunctionsByDifficulty, getRandomFunction };
|
||||||
1899
node_modules/captchalm/dist/index.js
generated
vendored
Normal file
1899
node_modules/captchalm/dist/index.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
node_modules/captchalm/dist/index.js.map
generated
vendored
Normal file
1
node_modules/captchalm/dist/index.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
88
node_modules/captchalm/package.json
generated
vendored
Normal file
88
node_modules/captchalm/package.json
generated
vendored
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
{
|
||||||
|
"name": "captchalm",
|
||||||
|
"version": "1.1.0",
|
||||||
|
"description": "AI-only access control - a reverse CAPTCHA that allows AI agents while blocking humans",
|
||||||
|
"main": "./dist/index.cjs",
|
||||||
|
"module": "./dist/index.js",
|
||||||
|
"types": "./dist/index.d.ts",
|
||||||
|
"type": "module",
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"types": "./dist/index.d.ts",
|
||||||
|
"import": "./dist/index.js",
|
||||||
|
"require": "./dist/index.cjs"
|
||||||
|
},
|
||||||
|
"./client": {
|
||||||
|
"types": "./dist/client/index.d.ts",
|
||||||
|
"import": "./dist/client/index.js",
|
||||||
|
"require": "./dist/client/index.cjs"
|
||||||
|
},
|
||||||
|
"./types": {
|
||||||
|
"types": "./dist/core/types.d.ts",
|
||||||
|
"import": "./dist/core/types.js",
|
||||||
|
"require": "./dist/core/types.cjs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"dist",
|
||||||
|
"README.md",
|
||||||
|
"LICENSE"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"build": "tsup",
|
||||||
|
"dev": "tsup --watch",
|
||||||
|
"test": "vitest",
|
||||||
|
"test:run": "vitest run",
|
||||||
|
"lint": "eslint src",
|
||||||
|
"typecheck": "tsc --noEmit",
|
||||||
|
"prepublishOnly": "npm run build",
|
||||||
|
"release": "npm version patch && npm publish --access public",
|
||||||
|
"release:minor": "npm version minor && npm publish --access public",
|
||||||
|
"release:major": "npm version major && npm publish --access public"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"captcha",
|
||||||
|
"ai",
|
||||||
|
"agent",
|
||||||
|
"authentication",
|
||||||
|
"access-control",
|
||||||
|
"llm",
|
||||||
|
"reverse-captcha",
|
||||||
|
"ai-agent",
|
||||||
|
"bot-protection",
|
||||||
|
"machine-learning"
|
||||||
|
],
|
||||||
|
"author": "",
|
||||||
|
"license": "MIT",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/YOUR_USERNAME/captchalm.git"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/YOUR_USERNAME/captchalm#readme",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/YOUR_USERNAME/captchalm/issues"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/express": "^5.0.6",
|
||||||
|
"@types/node": "^20.10.0",
|
||||||
|
"eslint": "^8.55.0",
|
||||||
|
"tsup": "^8.0.1",
|
||||||
|
"typescript": "^5.3.0",
|
||||||
|
"vitest": "^1.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"express": ">=4.0.0",
|
||||||
|
"fastify": ">=4.0.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"express": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"fastify": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
72
node_modules/content-disposition/HISTORY.md
generated
vendored
Normal file
72
node_modules/content-disposition/HISTORY.md
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
1.0.1 / 2025-11-18
|
||||||
|
=================
|
||||||
|
|
||||||
|
* Updated `engines` field to Node@18 or higher (fixed reference, see 1.0.0)
|
||||||
|
* Remove dependency `safe-buffer`
|
||||||
|
|
||||||
|
1.0.0 / 2024-08-31
|
||||||
|
==================
|
||||||
|
|
||||||
|
* drop node <18
|
||||||
|
* allow utf8 as alias for utf-8
|
||||||
|
|
||||||
|
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
|
||||||
22
node_modules/content-disposition/LICENSE
generated
vendored
Normal file
22
node_modules/content-disposition/LICENSE
generated
vendored
Normal file
@@ -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.
|
||||||
142
node_modules/content-disposition/README.md
generated
vendored
Normal file
142
node_modules/content-disposition/README.md
generated
vendored
Normal file
@@ -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
|
||||||
|
const 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
|
||||||
|
const 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
|
||||||
|
const contentDisposition = require('content-disposition')
|
||||||
|
const destroy = require('destroy')
|
||||||
|
const fs = require('fs')
|
||||||
|
const http = require('http')
|
||||||
|
const onFinished = require('on-finished')
|
||||||
|
|
||||||
|
const 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
|
||||||
|
const 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
|
||||||
|
[npm-url]: https://npmjs.org/package/content-disposition
|
||||||
|
[node-version-image]: https://img.shields.io/node/v/content-disposition
|
||||||
|
[node-version-url]: https://nodejs.org/en/download
|
||||||
|
[coveralls-image]: https://img.shields.io/coverallsCoverage/github/jshttp/content-disposition
|
||||||
|
[coveralls-url]: https://coveralls.io/r/jshttp/content-disposition?branch=master
|
||||||
|
[downloads-image]: https://img.shields.io/npm/dm/content-disposition
|
||||||
|
[downloads-url]: https://npmjs.org/package/content-disposition
|
||||||
|
[github-actions-ci-image]: https://img.shields.io/github/actions/workflow/status/jshttp/content-disposition/ci.yml
|
||||||
|
[github-actions-ci-url]: https://github.com/jshttp/content-disposition/actions/workflows/ci.yml
|
||||||
458
node_modules/content-disposition/index.js
generated
vendored
Normal file
458
node_modules/content-disposition/index.js
generated
vendored
Normal file
@@ -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
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.slice(-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':
|
||||||
|
case 'utf8':
|
||||||
|
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].slice(-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
|
||||||
|
.slice(1, -1)
|
||||||
|
.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
|
||||||
|
}
|
||||||
43
node_modules/content-disposition/package.json
generated
vendored
Normal file
43
node_modules/content-disposition/package.json
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
{
|
||||||
|
"name": "content-disposition",
|
||||||
|
"description": "Create and parse Content-Disposition header",
|
||||||
|
"version": "1.0.1",
|
||||||
|
"author": "Douglas Christopher Wilson <doug@somethingdoug.com>",
|
||||||
|
"license": "MIT",
|
||||||
|
"keywords": [
|
||||||
|
"content-disposition",
|
||||||
|
"http",
|
||||||
|
"rfc6266",
|
||||||
|
"res"
|
||||||
|
],
|
||||||
|
"repository": "jshttp/content-disposition",
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/express"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"c8": "^10.1.2",
|
||||||
|
"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"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"LICENSE",
|
||||||
|
"HISTORY.md",
|
||||||
|
"README.md",
|
||||||
|
"index.js"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"lint": "eslint .",
|
||||||
|
"test": "node --test --test-reporter spec",
|
||||||
|
"test-ci": "c8 --reporter=lcovonly --reporter=text npm test",
|
||||||
|
"test-cov": "c8 --reporter=html --reporter=text npm test"
|
||||||
|
}
|
||||||
|
}
|
||||||
29
node_modules/content-type/HISTORY.md
generated
vendored
Normal file
29
node_modules/content-type/HISTORY.md
generated
vendored
Normal file
@@ -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`
|
||||||
22
node_modules/content-type/LICENSE
generated
vendored
Normal file
22
node_modules/content-type/LICENSE
generated
vendored
Normal file
@@ -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.
|
||||||
94
node_modules/content-type/README.md
generated
vendored
Normal file
94
node_modules/content-type/README.md
generated
vendored
Normal file
@@ -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
|
||||||
225
node_modules/content-type/index.js
generated
vendored
Normal file
225
node_modules/content-type/index.js
generated
vendored
Normal file
@@ -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
|
||||||
|
}
|
||||||
42
node_modules/content-type/package.json
generated
vendored
Normal file
42
node_modules/content-type/package.json
generated
vendored
Normal file
@@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
70
node_modules/cookie-signature/History.md
generated
vendored
Normal file
70
node_modules/cookie-signature/History.md
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
1.2.2 / 2024-10-29
|
||||||
|
==================
|
||||||
|
|
||||||
|
* various metadata/documentation tweaks (incl. #51)
|
||||||
|
|
||||||
|
|
||||||
|
1.2.1 / 2023-02-27
|
||||||
|
==================
|
||||||
|
|
||||||
|
* update annotations for allowed secret key types (#44, thanks @jyasskin!)
|
||||||
|
|
||||||
|
|
||||||
|
1.2.0 / 2022-02-17
|
||||||
|
==================
|
||||||
|
|
||||||
|
* allow buffer and other node-supported types as key (#33)
|
||||||
|
* be pickier about extra content after signed portion (#40)
|
||||||
|
* some internal code clarity/cleanup improvements (#26)
|
||||||
|
|
||||||
|
|
||||||
|
1.1.0 / 2018-01-18
|
||||||
|
==================
|
||||||
|
|
||||||
|
* switch to built-in `crypto.timingSafeEqual` for validation instead of previous double-hash method (thank you @jodevsa!)
|
||||||
|
|
||||||
|
|
||||||
|
1.0.7 / 2023-04-12
|
||||||
|
==================
|
||||||
|
|
||||||
|
Later release for older node.js versions. See the [v1.0.x branch notes](https://github.com/tj/node-cookie-signature/blob/v1.0.x/History.md#107--2023-04-12).
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
22
node_modules/cookie-signature/LICENSE
generated
vendored
Normal file
22
node_modules/cookie-signature/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
(The MIT License)
|
||||||
|
|
||||||
|
Copyright (c) 2012–2024 LearnBoost <tj@learnboost.com> and other contributors;
|
||||||
|
|
||||||
|
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.
|
||||||
23
node_modules/cookie-signature/Readme.md
generated
vendored
Normal file
23
node_modules/cookie-signature/Readme.md
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
MIT.
|
||||||
|
|
||||||
|
See LICENSE file for details.
|
||||||
47
node_modules/cookie-signature/index.js
generated
vendored
Normal file
47
node_modules/cookie-signature/index.js
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/**
|
||||||
|
* Module dependencies.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var crypto = require('crypto');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sign the given `val` with `secret`.
|
||||||
|
*
|
||||||
|
* @param {String} val
|
||||||
|
* @param {String|NodeJS.ArrayBufferView|crypto.KeyObject} 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 (null == secret) throw new TypeError("Secret key must be provided.");
|
||||||
|
return val + '.' + crypto
|
||||||
|
.createHmac('sha256', secret)
|
||||||
|
.update(val)
|
||||||
|
.digest('base64')
|
||||||
|
.replace(/\=+$/, '');
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unsign and decode the given `input` with `secret`,
|
||||||
|
* returning `false` if the signature is invalid.
|
||||||
|
*
|
||||||
|
* @param {String} input
|
||||||
|
* @param {String|NodeJS.ArrayBufferView|crypto.KeyObject} secret
|
||||||
|
* @return {String|Boolean}
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
|
||||||
|
exports.unsign = function(input, secret){
|
||||||
|
if ('string' != typeof input) throw new TypeError("Signed cookie string must be provided.");
|
||||||
|
if (null == secret) throw new TypeError("Secret key must be provided.");
|
||||||
|
var tentativeValue = input.slice(0, input.lastIndexOf('.')),
|
||||||
|
expectedInput = exports.sign(tentativeValue, secret),
|
||||||
|
expectedBuffer = Buffer.from(expectedInput),
|
||||||
|
inputBuffer = Buffer.from(input);
|
||||||
|
return (
|
||||||
|
expectedBuffer.length === inputBuffer.length &&
|
||||||
|
crypto.timingSafeEqual(expectedBuffer, inputBuffer)
|
||||||
|
) ? tentativeValue : false;
|
||||||
|
};
|
||||||
24
node_modules/cookie-signature/package.json
generated
vendored
Normal file
24
node_modules/cookie-signature/package.json
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"name": "cookie-signature",
|
||||||
|
"version": "1.2.2",
|
||||||
|
"main": "index.js",
|
||||||
|
"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": {},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.6.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"mocha": "*",
|
||||||
|
"should": "*"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test": "mocha --require should --reporter spec"
|
||||||
|
}
|
||||||
|
}
|
||||||
24
node_modules/cookie/LICENSE
generated
vendored
Normal file
24
node_modules/cookie/LICENSE
generated
vendored
Normal file
@@ -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.
|
||||||
|
|
||||||
317
node_modules/cookie/README.md
generated
vendored
Normal file
317
node_modules/cookie/README.md
generated
vendored
Normal file
@@ -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
|
||||||
25
node_modules/cookie/SECURITY.md
generated
vendored
Normal file
25
node_modules/cookie/SECURITY.md
generated
vendored
Normal file
@@ -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.
|
||||||
335
node_modules/cookie/index.js
generated
vendored
Normal file
335
node_modules/cookie/index.js
generated
vendored
Normal file
@@ -0,0 +1,335 @@
|
|||||||
|
/*!
|
||||||
|
* 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
|
||||||
|
var __hasOwnProperty = Object.prototype.hasOwnProperty
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RegExp to match cookie-name in RFC 6265 sec 4.1.1
|
||||||
|
* This refers out to the obsoleted definition of token in RFC 2616 sec 2.2
|
||||||
|
* which has been replaced by the token definition in RFC 7230 appendix B.
|
||||||
|
*
|
||||||
|
* cookie-name = token
|
||||||
|
* token = 1*tchar
|
||||||
|
* tchar = "!" / "#" / "$" / "%" / "&" / "'" /
|
||||||
|
* "*" / "+" / "-" / "." / "^" / "_" /
|
||||||
|
* "`" / "|" / "~" / DIGIT / ALPHA
|
||||||
|
*/
|
||||||
|
|
||||||
|
var cookieNameRegExp = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RegExp to match cookie-value in RFC 6265 sec 4.1.1
|
||||||
|
*
|
||||||
|
* cookie-value = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE )
|
||||||
|
* cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
|
||||||
|
* ; US-ASCII characters excluding CTLs,
|
||||||
|
* ; whitespace DQUOTE, comma, semicolon,
|
||||||
|
* ; and backslash
|
||||||
|
*/
|
||||||
|
|
||||||
|
var cookieValueRegExp = /^("?)[\u0021\u0023-\u002B\u002D-\u003A\u003C-\u005B\u005D-\u007E]*\1$/;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RegExp to match domain-value in RFC 6265 sec 4.1.1
|
||||||
|
*
|
||||||
|
* domain-value = <subdomain>
|
||||||
|
* ; defined in [RFC1034], Section 3.5, as
|
||||||
|
* ; enhanced by [RFC1123], Section 2.1
|
||||||
|
* <subdomain> = <label> | <subdomain> "." <label>
|
||||||
|
* <label> = <let-dig> [ [ <ldh-str> ] <let-dig> ]
|
||||||
|
* Labels must be 63 characters or less.
|
||||||
|
* 'let-dig' not 'letter' in the first char, per RFC1123
|
||||||
|
* <ldh-str> = <let-dig-hyp> | <let-dig-hyp> <ldh-str>
|
||||||
|
* <let-dig-hyp> = <let-dig> | "-"
|
||||||
|
* <let-dig> = <letter> | <digit>
|
||||||
|
* <letter> = any one of the 52 alphabetic characters A through Z in
|
||||||
|
* upper case and a through z in lower case
|
||||||
|
* <digit> = any one of the ten digits 0 through 9
|
||||||
|
*
|
||||||
|
* Keep support for leading dot: https://github.com/jshttp/cookie/issues/173
|
||||||
|
*
|
||||||
|
* > (Note that a leading %x2E ("."), if present, is ignored even though that
|
||||||
|
* character is not permitted, but a trailing %x2E ("."), if present, will
|
||||||
|
* cause the user agent to ignore the attribute.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
var domainValueRegExp = /^([.]?[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)([.][a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)*$/i;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RegExp to match path-value in RFC 6265 sec 4.1.1
|
||||||
|
*
|
||||||
|
* path-value = <any CHAR except CTLs or ";">
|
||||||
|
* CHAR = %x01-7F
|
||||||
|
* ; defined in RFC 5234 appendix B.1
|
||||||
|
*/
|
||||||
|
|
||||||
|
var pathValueRegExp = /^[\u0020-\u003A\u003D-\u007E]*$/;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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} [opt]
|
||||||
|
* @return {object}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
function parse(str, opt) {
|
||||||
|
if (typeof str !== 'string') {
|
||||||
|
throw new TypeError('argument str must be a string');
|
||||||
|
}
|
||||||
|
|
||||||
|
var obj = {};
|
||||||
|
var len = str.length;
|
||||||
|
// RFC 6265 sec 4.1.1, RFC 2616 2.2 defines a cookie name consists of one char minimum, plus '='.
|
||||||
|
if (len < 2) return obj;
|
||||||
|
|
||||||
|
var dec = (opt && opt.decode) || decode;
|
||||||
|
var index = 0;
|
||||||
|
var eqIdx = 0;
|
||||||
|
var endIdx = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
eqIdx = str.indexOf('=', index);
|
||||||
|
if (eqIdx === -1) break; // No more cookie pairs.
|
||||||
|
|
||||||
|
endIdx = str.indexOf(';', index);
|
||||||
|
|
||||||
|
if (endIdx === -1) {
|
||||||
|
endIdx = len;
|
||||||
|
} else if (eqIdx > endIdx) {
|
||||||
|
// backtrack on prior semicolon
|
||||||
|
index = str.lastIndexOf(';', eqIdx - 1) + 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var keyStartIdx = startIndex(str, index, eqIdx);
|
||||||
|
var keyEndIdx = endIndex(str, eqIdx, keyStartIdx);
|
||||||
|
var key = str.slice(keyStartIdx, keyEndIdx);
|
||||||
|
|
||||||
|
// only assign once
|
||||||
|
if (!__hasOwnProperty.call(obj, key)) {
|
||||||
|
var valStartIdx = startIndex(str, eqIdx + 1, endIdx);
|
||||||
|
var valEndIdx = endIndex(str, endIdx, valStartIdx);
|
||||||
|
|
||||||
|
if (str.charCodeAt(valStartIdx) === 0x22 /* " */ && str.charCodeAt(valEndIdx - 1) === 0x22 /* " */) {
|
||||||
|
valStartIdx++;
|
||||||
|
valEndIdx--;
|
||||||
|
}
|
||||||
|
|
||||||
|
var val = str.slice(valStartIdx, valEndIdx);
|
||||||
|
obj[key] = tryDecode(val, dec);
|
||||||
|
}
|
||||||
|
|
||||||
|
index = endIdx + 1
|
||||||
|
} while (index < len);
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
function startIndex(str, index, max) {
|
||||||
|
do {
|
||||||
|
var code = str.charCodeAt(index);
|
||||||
|
if (code !== 0x20 /* */ && code !== 0x09 /* \t */) return index;
|
||||||
|
} while (++index < max);
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
function endIndex(str, index, min) {
|
||||||
|
while (index > min) {
|
||||||
|
var code = str.charCodeAt(--index);
|
||||||
|
if (code !== 0x20 /* */ && code !== 0x09 /* \t */) return index + 1;
|
||||||
|
}
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize data into a cookie header.
|
||||||
|
*
|
||||||
|
* Serialize a name value pair into a cookie string suitable for
|
||||||
|
* http headers. An optional options object specifies cookie parameters.
|
||||||
|
*
|
||||||
|
* serialize('foo', 'bar', { httpOnly: true })
|
||||||
|
* => "foo=bar; httpOnly"
|
||||||
|
*
|
||||||
|
* @param {string} name
|
||||||
|
* @param {string} val
|
||||||
|
* @param {object} [opt]
|
||||||
|
* @return {string}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
function serialize(name, val, opt) {
|
||||||
|
var enc = (opt && opt.encode) || encodeURIComponent;
|
||||||
|
|
||||||
|
if (typeof enc !== 'function') {
|
||||||
|
throw new TypeError('option encode is invalid');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cookieNameRegExp.test(name)) {
|
||||||
|
throw new TypeError('argument name is invalid');
|
||||||
|
}
|
||||||
|
|
||||||
|
var value = enc(val);
|
||||||
|
|
||||||
|
if (!cookieValueRegExp.test(value)) {
|
||||||
|
throw new TypeError('argument val is invalid');
|
||||||
|
}
|
||||||
|
|
||||||
|
var str = name + '=' + value;
|
||||||
|
if (!opt) return str;
|
||||||
|
|
||||||
|
if (null != opt.maxAge) {
|
||||||
|
var maxAge = Math.floor(opt.maxAge);
|
||||||
|
|
||||||
|
if (!isFinite(maxAge)) {
|
||||||
|
throw new TypeError('option maxAge is invalid')
|
||||||
|
}
|
||||||
|
|
||||||
|
str += '; Max-Age=' + maxAge;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opt.domain) {
|
||||||
|
if (!domainValueRegExp.test(opt.domain)) {
|
||||||
|
throw new TypeError('option domain is invalid');
|
||||||
|
}
|
||||||
|
|
||||||
|
str += '; Domain=' + opt.domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opt.path) {
|
||||||
|
if (!pathValueRegExp.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
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if value is a Date.
|
||||||
|
*
|
||||||
|
* @param {*} val
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function isDate (val) {
|
||||||
|
return __toString.call(val) === '[object 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
44
node_modules/cookie/package.json
generated
vendored
Normal file
44
node_modules/cookie/package.json
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"name": "cookie",
|
||||||
|
"description": "HTTP server cookie parsing and serialization",
|
||||||
|
"version": "0.7.2",
|
||||||
|
"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"
|
||||||
|
],
|
||||||
|
"main": "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"
|
||||||
|
}
|
||||||
|
}
|
||||||
20
node_modules/debug/LICENSE
generated
vendored
Normal file
20
node_modules/debug/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
(The MIT License)
|
||||||
|
|
||||||
|
Copyright (c) 2014-2017 TJ Holowaychuk <tj@vision-media.ca>
|
||||||
|
Copyright (c) 2018-2021 Josh Junon
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
481
node_modules/debug/README.md
generated
vendored
Normal file
481
node_modules/debug/README.md
generated
vendored
Normal file
@@ -0,0 +1,481 @@
|
|||||||
|
# debug
|
||||||
|
[](#backers)
|
||||||
|
[](#sponsors)
|
||||||
|
|
||||||
|
<img width="647" src="https://user-images.githubusercontent.com/71256/29091486-fa38524c-7c37-11e7-895f-e7ec8e1039b6.png">
|
||||||
|
|
||||||
|
A tiny JavaScript debugging utility modelled after Node.js core's debugging
|
||||||
|
technique. Works in Node.js and web browsers.
|
||||||
|
|
||||||
|
## 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_](./examples/node/app.js):
|
||||||
|
|
||||||
|
```js
|
||||||
|
var debug = require('debug')('http')
|
||||||
|
, http = require('http')
|
||||||
|
, name = 'My App';
|
||||||
|
|
||||||
|
// fake app
|
||||||
|
|
||||||
|
debug('booting %o', 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_](./examples/node/worker.js):
|
||||||
|
|
||||||
|
```js
|
||||||
|
var a = require('debug')('worker:a')
|
||||||
|
, b = require('debug')('worker:b');
|
||||||
|
|
||||||
|
function work() {
|
||||||
|
a('doing lots of uninteresting work');
|
||||||
|
setTimeout(work, Math.random() * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
work();
|
||||||
|
|
||||||
|
function workb() {
|
||||||
|
b('doing some work');
|
||||||
|
setTimeout(workb, Math.random() * 2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
workb();
|
||||||
|
```
|
||||||
|
|
||||||
|
The `DEBUG` environment variable is then used to enable these based on space or
|
||||||
|
comma-delimited names.
|
||||||
|
|
||||||
|
Here are some examples:
|
||||||
|
|
||||||
|
<img width="647" alt="screen shot 2017-08-08 at 12 53 04 pm" src="https://user-images.githubusercontent.com/71256/29091703-a6302cdc-7c38-11e7-8304-7c0b3bc600cd.png">
|
||||||
|
<img width="647" alt="screen shot 2017-08-08 at 12 53 38 pm" src="https://user-images.githubusercontent.com/71256/29091700-a62a6888-7c38-11e7-800b-db911291ca2b.png">
|
||||||
|
<img width="647" alt="screen shot 2017-08-08 at 12 53 25 pm" src="https://user-images.githubusercontent.com/71256/29091701-a62ea114-7c38-11e7-826a-2692bedca740.png">
|
||||||
|
|
||||||
|
#### Windows command prompt notes
|
||||||
|
|
||||||
|
##### CMD
|
||||||
|
|
||||||
|
On Windows the environment variable is set using the `set` command.
|
||||||
|
|
||||||
|
```cmd
|
||||||
|
set DEBUG=*,-not_this
|
||||||
|
```
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```cmd
|
||||||
|
set DEBUG=* & node app.js
|
||||||
|
```
|
||||||
|
|
||||||
|
##### PowerShell (VS Code default)
|
||||||
|
|
||||||
|
PowerShell uses different syntax to set environment variables.
|
||||||
|
|
||||||
|
```cmd
|
||||||
|
$env:DEBUG = "*,-not_this"
|
||||||
|
```
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```cmd
|
||||||
|
$env:DEBUG='app';node app.js
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, run the program to be debugged as usual.
|
||||||
|
|
||||||
|
npm script example:
|
||||||
|
```js
|
||||||
|
"windowsDebug": "@powershell -Command $env:DEBUG='*';node app.js",
|
||||||
|
```
|
||||||
|
|
||||||
|
## Namespace Colors
|
||||||
|
|
||||||
|
Every debug instance has a color generated for it based on its namespace name.
|
||||||
|
This helps when visually parsing the debug output to identify which debug instance
|
||||||
|
a debug line belongs to.
|
||||||
|
|
||||||
|
#### Node.js
|
||||||
|
|
||||||
|
In Node.js, colors are enabled when stderr is a TTY. You also _should_ install
|
||||||
|
the [`supports-color`](https://npmjs.org/supports-color) module alongside debug,
|
||||||
|
otherwise debug will only use a small handful of basic colors.
|
||||||
|
|
||||||
|
<img width="521" src="https://user-images.githubusercontent.com/71256/29092181-47f6a9e6-7c3a-11e7-9a14-1928d8a711cd.png">
|
||||||
|
|
||||||
|
#### Web Browser
|
||||||
|
|
||||||
|
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).
|
||||||
|
|
||||||
|
<img width="524" src="https://user-images.githubusercontent.com/71256/29092033-b65f9f2e-7c39-11e7-8e32-f6f0d8e865c1.png">
|
||||||
|
|
||||||
|
|
||||||
|
## 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.
|
||||||
|
|
||||||
|
<img width="647" src="https://user-images.githubusercontent.com/71256/29091486-fa38524c-7c37-11e7-895f-e7ec8e1039b6.png">
|
||||||
|
|
||||||
|
When stdout is not a TTY, `Date#toISOString()` is used, making it more useful for logging the debug information as shown below:
|
||||||
|
|
||||||
|
<img width="647" src="https://user-images.githubusercontent.com/71256/29091956-6bd78372-7c39-11e7-8c55-c948396d6edd.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". If you append a "*" to the end of your name, it will always be enabled regardless of the setting of the DEBUG environment variable. You can then use it for normal output as well as debug output.
|
||||||
|
|
||||||
|
## 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_HIDE_DATE` | Hide date from debug output (non-TTY). |
|
||||||
|
| `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);
|
||||||
|
```
|
||||||
|
|
||||||
|
In Chromium-based web browsers (e.g. Brave, Chrome, and Electron), the JavaScript console will—by default—only show messages logged by `debug` if the "Verbose" log level is _enabled_.
|
||||||
|
|
||||||
|
<img width="647" src="https://user-images.githubusercontent.com/7143133/152083257-29034707-c42c-4959-8add-3cee850e6fcf.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_](./examples/node/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');
|
||||||
|
```
|
||||||
|
|
||||||
|
## Extend
|
||||||
|
You can simply extend debugger
|
||||||
|
```js
|
||||||
|
const log = require('debug')('auth');
|
||||||
|
|
||||||
|
//creates new debug instance with extended namespace
|
||||||
|
const logSign = log.extend('sign');
|
||||||
|
const logLogin = log.extend('login');
|
||||||
|
|
||||||
|
log('hello'); // auth hello
|
||||||
|
logSign('hello'); //auth:sign hello
|
||||||
|
logLogin('hello'); //auth:login hello
|
||||||
|
```
|
||||||
|
|
||||||
|
## Set dynamically
|
||||||
|
|
||||||
|
You can also enable debug dynamically by calling the `enable()` method :
|
||||||
|
|
||||||
|
```js
|
||||||
|
let debug = require('debug');
|
||||||
|
|
||||||
|
console.log(1, debug.enabled('test'));
|
||||||
|
|
||||||
|
debug.enable('test');
|
||||||
|
console.log(2, debug.enabled('test'));
|
||||||
|
|
||||||
|
debug.disable();
|
||||||
|
console.log(3, debug.enabled('test'));
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
print :
|
||||||
|
```
|
||||||
|
1 false
|
||||||
|
2 true
|
||||||
|
3 false
|
||||||
|
```
|
||||||
|
|
||||||
|
Usage :
|
||||||
|
`enable(namespaces)`
|
||||||
|
`namespaces` can include modes separated by a colon and wildcards.
|
||||||
|
|
||||||
|
Note that calling `enable()` completely overrides previously set DEBUG variable :
|
||||||
|
|
||||||
|
```
|
||||||
|
$ DEBUG=foo node -e 'var dbg = require("debug"); dbg.enable("bar"); console.log(dbg.enabled("foo"))'
|
||||||
|
=> false
|
||||||
|
```
|
||||||
|
|
||||||
|
`disable()`
|
||||||
|
|
||||||
|
Will disable all namespaces. The functions returns the namespaces currently
|
||||||
|
enabled (and skipped). This can be useful if you want to disable debugging
|
||||||
|
temporarily without knowing what was enabled to begin with.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```js
|
||||||
|
let debug = require('debug');
|
||||||
|
debug.enable('foo:*,-foo:bar');
|
||||||
|
let namespaces = debug.disable();
|
||||||
|
debug.enable(namespaces);
|
||||||
|
```
|
||||||
|
|
||||||
|
Note: There is no guarantee that the string will be identical to the initial
|
||||||
|
enable string, but semantically they will be identical.
|
||||||
|
|
||||||
|
## Checking whether a debug target is enabled
|
||||||
|
|
||||||
|
After you've created a debug instance, you can determine whether or not it is
|
||||||
|
enabled by checking the `enabled` property:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const debug = require('debug')('http');
|
||||||
|
|
||||||
|
if (debug.enabled) {
|
||||||
|
// do stuff...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also manually toggle this property to force the debug instance to be
|
||||||
|
enabled or disabled.
|
||||||
|
|
||||||
|
## Usage in child processes
|
||||||
|
|
||||||
|
Due to the way `debug` detects if the output is a TTY or not, colors are not shown in child processes when `stderr` is piped. A solution is to pass the `DEBUG_COLORS=1` environment variable to the child process.
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
worker = fork(WORKER_WRAP_PATH, [workerPath], {
|
||||||
|
stdio: [
|
||||||
|
/* stdin: */ 0,
|
||||||
|
/* stdout: */ 'pipe',
|
||||||
|
/* stderr: */ 'pipe',
|
||||||
|
'ipc',
|
||||||
|
],
|
||||||
|
env: Object.assign({}, process.env, {
|
||||||
|
DEBUG_COLORS: 1 // without this settings, colors won't be shown
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
worker.stderr.pipe(process.stderr, { end: false });
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Authors
|
||||||
|
|
||||||
|
- TJ Holowaychuk
|
||||||
|
- Nathan Rajlich
|
||||||
|
- Andrew Rhyne
|
||||||
|
- Josh Junon
|
||||||
|
|
||||||
|
## 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-2017 TJ Holowaychuk <tj@vision-media.ca>
|
||||||
|
Copyright (c) 2018-2021 Josh Junon
|
||||||
|
|
||||||
|
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.
|
||||||
64
node_modules/debug/package.json
generated
vendored
Normal file
64
node_modules/debug/package.json
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
{
|
||||||
|
"name": "debug",
|
||||||
|
"version": "4.4.3",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git://github.com/debug-js/debug.git"
|
||||||
|
},
|
||||||
|
"description": "Lightweight debugging utility for Node.js and the browser",
|
||||||
|
"keywords": [
|
||||||
|
"debug",
|
||||||
|
"log",
|
||||||
|
"debugger"
|
||||||
|
],
|
||||||
|
"files": [
|
||||||
|
"src",
|
||||||
|
"LICENSE",
|
||||||
|
"README.md"
|
||||||
|
],
|
||||||
|
"author": "Josh Junon (https://github.com/qix-)",
|
||||||
|
"contributors": [
|
||||||
|
"TJ Holowaychuk <tj@vision-media.ca>",
|
||||||
|
"Nathan Rajlich <nathan@tootallnate.net> (http://n8.io)",
|
||||||
|
"Andrew Rhyne <rhyneandrew@gmail.com>"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"scripts": {
|
||||||
|
"lint": "xo",
|
||||||
|
"test": "npm run test:node && npm run test:browser && npm run lint",
|
||||||
|
"test:node": "mocha test.js test.node.js",
|
||||||
|
"test:browser": "karma start --single-run",
|
||||||
|
"test:coverage": "cat ./coverage/lcov.info | coveralls"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"ms": "^2.1.3"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"brfs": "^2.0.1",
|
||||||
|
"browserify": "^16.2.3",
|
||||||
|
"coveralls": "^3.0.2",
|
||||||
|
"karma": "^3.1.4",
|
||||||
|
"karma-browserify": "^6.0.0",
|
||||||
|
"karma-chrome-launcher": "^2.2.0",
|
||||||
|
"karma-mocha": "^1.3.0",
|
||||||
|
"mocha": "^5.2.0",
|
||||||
|
"mocha-lcov-reporter": "^1.2.0",
|
||||||
|
"sinon": "^14.0.0",
|
||||||
|
"xo": "^0.23.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"supports-color": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"main": "./src/index.js",
|
||||||
|
"browser": "./src/browser.js",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0"
|
||||||
|
},
|
||||||
|
"xo": {
|
||||||
|
"rules": {
|
||||||
|
"import/extensions": "off"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
272
node_modules/debug/src/browser.js
generated
vendored
Normal file
272
node_modules/debug/src/browser.js
generated
vendored
Normal file
@@ -0,0 +1,272 @@
|
|||||||
|
/* eslint-env browser */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the web browser implementation of `debug()`.
|
||||||
|
*/
|
||||||
|
|
||||||
|
exports.formatArgs = formatArgs;
|
||||||
|
exports.save = save;
|
||||||
|
exports.load = load;
|
||||||
|
exports.useColors = useColors;
|
||||||
|
exports.storage = localstorage();
|
||||||
|
exports.destroy = (() => {
|
||||||
|
let warned = false;
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
if (!warned) {
|
||||||
|
warned = true;
|
||||||
|
console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Colors.
|
||||||
|
*/
|
||||||
|
|
||||||
|
exports.colors = [
|
||||||
|
'#0000CC',
|
||||||
|
'#0000FF',
|
||||||
|
'#0033CC',
|
||||||
|
'#0033FF',
|
||||||
|
'#0066CC',
|
||||||
|
'#0066FF',
|
||||||
|
'#0099CC',
|
||||||
|
'#0099FF',
|
||||||
|
'#00CC00',
|
||||||
|
'#00CC33',
|
||||||
|
'#00CC66',
|
||||||
|
'#00CC99',
|
||||||
|
'#00CCCC',
|
||||||
|
'#00CCFF',
|
||||||
|
'#3300CC',
|
||||||
|
'#3300FF',
|
||||||
|
'#3333CC',
|
||||||
|
'#3333FF',
|
||||||
|
'#3366CC',
|
||||||
|
'#3366FF',
|
||||||
|
'#3399CC',
|
||||||
|
'#3399FF',
|
||||||
|
'#33CC00',
|
||||||
|
'#33CC33',
|
||||||
|
'#33CC66',
|
||||||
|
'#33CC99',
|
||||||
|
'#33CCCC',
|
||||||
|
'#33CCFF',
|
||||||
|
'#6600CC',
|
||||||
|
'#6600FF',
|
||||||
|
'#6633CC',
|
||||||
|
'#6633FF',
|
||||||
|
'#66CC00',
|
||||||
|
'#66CC33',
|
||||||
|
'#9900CC',
|
||||||
|
'#9900FF',
|
||||||
|
'#9933CC',
|
||||||
|
'#9933FF',
|
||||||
|
'#99CC00',
|
||||||
|
'#99CC33',
|
||||||
|
'#CC0000',
|
||||||
|
'#CC0033',
|
||||||
|
'#CC0066',
|
||||||
|
'#CC0099',
|
||||||
|
'#CC00CC',
|
||||||
|
'#CC00FF',
|
||||||
|
'#CC3300',
|
||||||
|
'#CC3333',
|
||||||
|
'#CC3366',
|
||||||
|
'#CC3399',
|
||||||
|
'#CC33CC',
|
||||||
|
'#CC33FF',
|
||||||
|
'#CC6600',
|
||||||
|
'#CC6633',
|
||||||
|
'#CC9900',
|
||||||
|
'#CC9933',
|
||||||
|
'#CCCC00',
|
||||||
|
'#CCCC33',
|
||||||
|
'#FF0000',
|
||||||
|
'#FF0033',
|
||||||
|
'#FF0066',
|
||||||
|
'#FF0099',
|
||||||
|
'#FF00CC',
|
||||||
|
'#FF00FF',
|
||||||
|
'#FF3300',
|
||||||
|
'#FF3333',
|
||||||
|
'#FF3366',
|
||||||
|
'#FF3399',
|
||||||
|
'#FF33CC',
|
||||||
|
'#FF33FF',
|
||||||
|
'#FF6600',
|
||||||
|
'#FF6633',
|
||||||
|
'#FF9900',
|
||||||
|
'#FF9933',
|
||||||
|
'#FFCC00',
|
||||||
|
'#FFCC33'
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
// eslint-disable-next-line complexity
|
||||||
|
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' || window.process.__nwjs)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internet Explorer and Edge do not support colors.
|
||||||
|
if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let m;
|
||||||
|
|
||||||
|
// Is webkit? http://stackoverflow.com/a/16459606/376773
|
||||||
|
// document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
|
||||||
|
// eslint-disable-next-line no-return-assign
|
||||||
|
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 && (m = navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)) && parseInt(m[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+)/));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Colorize log arguments if enabled.
|
||||||
|
*
|
||||||
|
* @api public
|
||||||
|
*/
|
||||||
|
|
||||||
|
function formatArgs(args) {
|
||||||
|
args[0] = (this.useColors ? '%c' : '') +
|
||||||
|
this.namespace +
|
||||||
|
(this.useColors ? ' %c' : ' ') +
|
||||||
|
args[0] +
|
||||||
|
(this.useColors ? '%c ' : ' ') +
|
||||||
|
'+' + module.exports.humanize(this.diff);
|
||||||
|
|
||||||
|
if (!this.useColors) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const 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
|
||||||
|
let index = 0;
|
||||||
|
let lastC = 0;
|
||||||
|
args[0].replace(/%[a-zA-Z%]/g, match => {
|
||||||
|
if (match === '%%') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
if (match === '%c') {
|
||||||
|
// We only are interested in the *last* %c
|
||||||
|
// (the user may have provided their own)
|
||||||
|
lastC = index;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
args.splice(lastC, 0, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invokes `console.debug()` when available.
|
||||||
|
* No-op when `console.debug` is not a "function".
|
||||||
|
* If `console.debug` is not available, falls back
|
||||||
|
* to `console.log`.
|
||||||
|
*
|
||||||
|
* @api public
|
||||||
|
*/
|
||||||
|
exports.log = console.debug || console.log || (() => {});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save `namespaces`.
|
||||||
|
*
|
||||||
|
* @param {String} namespaces
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
function save(namespaces) {
|
||||||
|
try {
|
||||||
|
if (namespaces) {
|
||||||
|
exports.storage.setItem('debug', namespaces);
|
||||||
|
} else {
|
||||||
|
exports.storage.removeItem('debug');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// Swallow
|
||||||
|
// XXX (@Qix-) should we be logging these?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load `namespaces`.
|
||||||
|
*
|
||||||
|
* @return {String} returns the previously persisted debug modes
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
function load() {
|
||||||
|
let r;
|
||||||
|
try {
|
||||||
|
r = exports.storage.getItem('debug') || exports.storage.getItem('DEBUG') ;
|
||||||
|
} catch (error) {
|
||||||
|
// Swallow
|
||||||
|
// XXX (@Qix-) should we be logging these?
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 {
|
||||||
|
// TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context
|
||||||
|
// The Browser also has localStorage in the global context.
|
||||||
|
return localStorage;
|
||||||
|
} catch (error) {
|
||||||
|
// Swallow
|
||||||
|
// XXX (@Qix-) should we be logging these?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = require('./common')(exports);
|
||||||
|
|
||||||
|
const {formatters} = module.exports;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
|
||||||
|
*/
|
||||||
|
|
||||||
|
formatters.j = function (v) {
|
||||||
|
try {
|
||||||
|
return JSON.stringify(v);
|
||||||
|
} catch (error) {
|
||||||
|
return '[UnexpectedJSONParseError]: ' + error.message;
|
||||||
|
}
|
||||||
|
};
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user