This commit is contained in:
darenhsu
2022-07-17 13:16:16 +08:00
parent 84759556ff
commit befd344ab0
28070 changed files with 4008428 additions and 1 deletions
+60
View File
@@ -0,0 +1,60 @@
<a name="2.0.5"></a>
## [2.0.5](https://github.com/poppinss/youch/compare/v2.0.4...v2.0.5) (2017-06-13)
### Bug Fixes
* **template:** improve css for smaller screens ([b07c77d](https://github.com/poppinss/youch/commit/b07c77d))
<a name="2.0.4"></a>
## [2.0.4](https://github.com/poppinss/youch/compare/v2.0.3...v2.0.4) (2017-01-31)
### Bug Fixes
* **test:** use mocha instead of japa ([8bf7039](https://github.com/poppinss/youch/commit/8bf7039))
<a name="2.0.3"></a>
## [2.0.3](https://github.com/poppinss/youch/compare/v2.0.2...v2.0.3) (2017-01-30)
### Bug Fixes
* **regex:** use plain regex over path.sep ([db3e2dc](https://github.com/poppinss/youch/commit/db3e2dc))
<a name="2.0.2"></a>
## [2.0.2](https://github.com/poppinss/youch/compare/v2.0.0...v2.0.2) (2017-01-27)
### Bug Fixes
* **package:** fix path to main file ([5ad3b4a](https://github.com/poppinss/youch/commit/5ad3b4a))
<a name="2.0.1"></a>
## [2.0.1](https://github.com/poppinss/youch/compare/v2.0.0...v2.0.1) (2017-01-26)
### Bug Fixes
* **package:** fix path to main file ([5ad3b4a](https://github.com/poppinss/youch/commit/5ad3b4a))
<a name="2.0.0"></a>
# 2.0.0 (2017-01-26)
### Features
* initial implementation ([aba222a](https://github.com/poppinss/youch/commit/aba222a))
+6
View File
@@ -0,0 +1,6 @@
# Contributing
In favor of active development we accept contributions from everyone. You can contribute by submitting a bug, creating pull requests or even by improving documentation.
Below is the guide to be followed strictly before submitting your pull requests.
http://adonisjs.com/docs/contributing
+89
View File
@@ -0,0 +1,89 @@
# Youch!
> Pretty error reporting for Node.js 🚀 (Modified for Nuxt.js & SSR Bundles)
<br />
<p>
<img src="https://user-images.githubusercontent.com/5158436/28990900-0a4766f8-7997-11e7-9f0b-4336fa2e2e0b.png" style="width: 600px;" />
</p>
<br />
---
<br />
[![NPM Version][npm-image]][npm-url]
[![Build Status][travis-image]][travis-url]
[![Downloads Stats][npm-downloads]][npm-url]
[![Appveyor][appveyor-image]][appveyor-url]
[![Gitter Channel][gitter-image]][gitter-url]
[![Trello][trello-image]][trello-url]
[![Patreon][patreon-image]][patreon-url]
Youch is inspired by [Whoops](https://filp.github.io/whoops) but with a modern design. Reading stack trace of the console slows you down from active development. Instead **Youch** print those errors in structured HTML to the browser.
## Features
1. HTML reporter
2. JSON reporter, if request accepts a json instead of text/html.
3. Sorted frames of error stack.
## Installation
```bash
npm i --save @nuxtjs/youch
```
## Basic Usage
Youch is used by [AdonisJs](http://adonisjs.com) and [Nuxt.js](https://nuxtjs.org), but it can be used by express or raw HTTP server as well.
```javascript
const Youch = require('@nuxtjs/youch')
const http = require('http')
http.createServer(function (req, res) {
// PERFORM SOME ACTION
if (error) {
const youch = new Youch(error, req)
youch
.toHTML()
.then((html) => {
res.writeHead(200, {'content-type': 'text/html'})
res.write(html)
res.end()
})
}
}).listen(8000)
```
## Release History
Checkout [CHANGELOG.md](CHANGELOG.md) file for release history.
## Meta
Checkout [LICENSE.txt](LICENSE.txt) for license information
Harminder Virk (Aman) - [https://github.com/thetutlage](https://github.com/thetutlage)
[appveyor-image]: https://ci.appveyor.com/api/projects/status/github/nuxt/youch?branch=master&svg=true&passingText=Passing%20On%20Windows
[appveyor-url]: https://ci.appveyor.com/project/nuxt/youch
[npm-image]: https://img.shields.io/npm/v/@nuxtjs/youch.svg?style=flat-square
[npm-url]: https://npmjs.org/package/@nuxtjs/youch
[travis-image]: https://img.shields.io/travis/nuxt/youch/master.svg?style=flat-square
[travis-url]: https://travis-ci.org/nuxt/youch
[gitter-url]: https://gitter.im/adonisjs/adonis-framework
[gitter-image]: https://img.shields.io/badge/gitter-join%20us-1DCE73.svg?style=flat-square
[trello-url]: https://trello.com/b/yzpqCgdl/adonis-for-humans
[trello-image]: https://img.shields.io/badge/trello-roadmap-89609E.svg?style=flat-square
[patreon-url]: https://www.patreon.com/adonisframework
[patreon-image]: https://img.shields.io/badge/patreon-support%20AdonisJs-brightgreen.svg?style=flat-square
[npm-downloads]: https://img.shields.io/npm/dm/@nuxtjs/youch.svg?style=flat-square
+21
View File
@@ -0,0 +1,21 @@
environment:
matrix:
- nodejs_version: 'Stable'
init:
git config --global core.autocrlf true
install:
- ps: Install-Product node $env:nodejs_version
- npm install
test_script:
- node --version
- npm --version
- npm run test:win
build: off
clone_depth: 1
matrix:
fast_finish: true
+40
View File
@@ -0,0 +1,40 @@
'use strict'
const http = require('http')
const Youch = require('../src/Youch')
class HttpException extends Error {
constructor (...args) {
super(...args)
this.name = this.constructor.name
}
}
function foo () {
const error = new HttpException('Some weird error')
error.status = 503
throw error
}
http.createServer((req, res) => {
let youch = null
try {
foo()
} catch (e) {
youch = new Youch(e, req)
}
youch
.toHTML()
.then((response) => {
res.writeHead(200, {'content-type': 'text/html'})
res.write(response)
res.end()
}).catch((error) => {
res.writeHead(500)
res.write(error.message)
res.end()
})
}).listen(8000, () => {
console.log('listening to port 8000')
})
+118
View File
@@ -0,0 +1,118 @@
0.3.1 / 2016-05-26
==================
* Fix `sameSite: true` to work with draft-7 clients
- `true` now sends `SameSite=Strict` instead of `SameSite`
0.3.0 / 2016-05-26
==================
* Add `sameSite` option
- Replaces `firstPartyOnly` option, never implemented by browsers
* Improve error message when `encode` is not a function
* Improve error message when `expires` is not a `Date`
0.2.4 / 2016-05-20
==================
* perf: enable strict mode
* perf: use for loop in parse
* perf: use string concatination for serialization
0.2.3 / 2015-10-25
==================
* Fix cookie `Max-Age` to never be a floating point number
0.2.2 / 2015-09-17
==================
* Fix regression when setting empty cookie value
- Ease the new restriction, which is just basic header-level validation
* Fix typo in invalid value errors
0.2.1 / 2015-09-17
==================
* Throw on invalid values provided to `serialize`
- Ensures the resulting string is a valid HTTP header value
0.2.0 / 2015-08-13
==================
* Add `firstPartyOnly` option
* Throw better error for invalid argument to parse
* perf: hoist regular expression
0.1.5 / 2015-09-17
==================
* Fix regression when setting empty cookie value
- Ease the new restriction, which is just basic header-level validation
* Fix typo in invalid value errors
0.1.4 / 2015-09-17
==================
* Throw better error for invalid argument to parse
* Throw on invalid values provided to `serialize`
- Ensures the resulting string is a valid HTTP header value
0.1.3 / 2015-05-19
==================
* Reduce the scope of try-catch deopt
* Remove argument reassignments
0.1.2 / 2014-04-16
==================
* Remove unnecessary files from npm package
0.1.1 / 2014-02-23
==================
* Fix bad parse when cookie value contained a comma
* Fix support for `maxAge` of `0`
0.1.0 / 2013-05-01
==================
* Add `decode` option
* Add `encode` option
0.0.6 / 2013-04-08
==================
* Ignore cookie parts missing `=`
0.0.5 / 2012-10-29
==================
* Return raw cookie value if value unescape errors
0.0.4 / 2012-06-21
==================
* Use encode/decodeURIComponent for cookie encoding/decoding
- Improve server/client interoperability
0.0.3 / 2012-06-06
==================
* Only escape special characters per the cookie RFC
0.0.2 / 2012-06-01
==================
* Fix `maxAge` option to not throw error
0.0.1 / 2012-05-28
==================
* Add more tests
0.0.0 / 2012-05-28
==================
* Initial release
+24
View 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.
+220
View File
@@ -0,0 +1,220 @@
# cookie
[![NPM Version][npm-image]][npm-url]
[![NPM Downloads][downloads-image]][downloads-url]
[![Node.js Version][node-version-image]][node-version-url]
[![Build Status][travis-image]][travis-url]
[![Test Coverage][coveralls-image]][coveralls-url]
Basic HTTP cookie parser and serializer for HTTP servers.
## Installation
```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-6266-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 `ecodeURIComponent`, 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-6266-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-6266-5.3] states that if both `expires` and
`magAge` are set, then `maxAge` takes precedence, but it is possiblke 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-6266-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-6266-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-6266-5.3] states that if both `expires` and
`magAge` are set, then `maxAge` takes precedence, but it is possiblke not all clients by obey this,
so if both are set, they should point to the same date and time.
##### path
Specifies the value for the [`Path` `Set-Cookie` attribute][rfc-6266-5.2.4]. By default, the path
is considered the ["default path"][rfc-6266-5.1.4]. By default, no maximum age 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.
##### sameSite
Specifies the `boolean` or `string` to be the value for the [`SameSite` `Set-Cookie` attribute][draft-west-first-party-cookies-07].
- `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.
- `'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
https://tools.ietf.org/html/draft-west-first-party-cookies-07#section-4.1.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.
##### secure
Specifies the `boolean` value for the [`Secure` `Set-Cookie` attribute][rfc-6266-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
```
## References
- [RFC 6266: HTTP State Management Mechanism][rfc-6266]
- [Same-site Cookies][draft-west-first-party-cookies-07]
[draft-west-first-party-cookies-07]: https://tools.ietf.org/html/draft-west-first-party-cookies-07
[rfc-6266]: https://tools.ietf.org/html/rfc6266
[rfc-6266-5.1.4]: https://tools.ietf.org/html/rfc6266#section-5.1.4
[rfc-6266-5.2.1]: https://tools.ietf.org/html/rfc6266#section-5.2.1
[rfc-6266-5.2.2]: https://tools.ietf.org/html/rfc6266#section-5.2.2
[rfc-6266-5.2.3]: https://tools.ietf.org/html/rfc6266#section-5.2.3
[rfc-6266-5.2.4]: https://tools.ietf.org/html/rfc6266#section-5.2.4
[rfc-6266-5.3]: https://tools.ietf.org/html/rfc6266#section-5.3
## License
[MIT](LICENSE)
[npm-image]: https://img.shields.io/npm/v/cookie.svg
[npm-url]: https://npmjs.org/package/cookie
[node-version-image]: https://img.shields.io/node/v/cookie.svg
[node-version-url]: https://nodejs.org/en/download
[travis-image]: https://img.shields.io/travis/jshttp/cookie/master.svg
[travis-url]: https://travis-ci.org/jshttp/cookie
[coveralls-image]: https://img.shields.io/coveralls/jshttp/cookie/master.svg
[coveralls-url]: https://coveralls.io/r/jshttp/cookie?branch=master
[downloads-image]: https://img.shields.io/npm/dm/cookie.svg
[downloads-url]: https://npmjs.org/package/cookie
+195
View File
@@ -0,0 +1,195 @@
/*!
* 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 decode = decodeURIComponent;
var encode = encodeURIComponent;
var pairSplitRegExp = /; */;
/**
* RegExp to match field-content in RFC 7230 sec 3.2
*
* field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
* field-vchar = VCHAR / obs-text
* obs-text = %x80-FF
*/
var fieldContentRegExp = /^[\u0009\u0020-\u007e\u0080-\u00ff]+$/;
/**
* Parse a cookie header.
*
* Parse the given cookie header string into an object
* The object has the various cookies as keys(names) => values
*
* @param {string} str
* @param {object} [options]
* @return {object}
* @public
*/
function parse(str, options) {
if (typeof str !== 'string') {
throw new TypeError('argument str must be a string');
}
var obj = {}
var opt = options || {};
var pairs = str.split(pairSplitRegExp);
var dec = opt.decode || decode;
for (var i = 0; i < pairs.length; i++) {
var pair = pairs[i];
var eq_idx = pair.indexOf('=');
// skip things that don't look like key=value
if (eq_idx < 0) {
continue;
}
var key = pair.substr(0, eq_idx).trim()
var val = pair.substr(++eq_idx, pair.length).trim();
// quoted values
if ('"' == val[0]) {
val = val.slice(1, -1);
}
// only assign once
if (undefined == obj[key]) {
obj[key] = tryDecode(val, dec);
}
}
return obj;
}
/**
* Serialize data into a cookie header.
*
* Serialize the a name value pair into a cookie string suitable for
* http headers. An optional options object specified cookie parameters.
*
* serialize('foo', 'bar', { httpOnly: true })
* => "foo=bar; httpOnly"
*
* @param {string} name
* @param {string} val
* @param {object} [options]
* @return {string}
* @public
*/
function serialize(name, val, options) {
var opt = options || {};
var enc = opt.encode || encode;
if (typeof enc !== 'function') {
throw new TypeError('option encode is invalid');
}
if (!fieldContentRegExp.test(name)) {
throw new TypeError('argument name is invalid');
}
var value = enc(val);
if (value && !fieldContentRegExp.test(value)) {
throw new TypeError('argument val is invalid');
}
var str = name + '=' + value;
if (null != opt.maxAge) {
var maxAge = opt.maxAge - 0;
if (isNaN(maxAge)) throw new Error('maxAge should be a Number');
str += '; Max-Age=' + Math.floor(maxAge);
}
if (opt.domain) {
if (!fieldContentRegExp.test(opt.domain)) {
throw new TypeError('option domain is invalid');
}
str += '; Domain=' + opt.domain;
}
if (opt.path) {
if (!fieldContentRegExp.test(opt.path)) {
throw new TypeError('option path is invalid');
}
str += '; Path=' + opt.path;
}
if (opt.expires) {
if (typeof opt.expires.toUTCString !== 'function') {
throw new TypeError('option expires is invalid');
}
str += '; Expires=' + opt.expires.toUTCString();
}
if (opt.httpOnly) {
str += '; HttpOnly';
}
if (opt.secure) {
str += '; Secure';
}
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;
default:
throw new TypeError('option sameSite is invalid');
}
}
return str;
}
/**
* 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;
}
}
+74
View File
@@ -0,0 +1,74 @@
{
"_args": [
[
"cookie@0.3.1",
"/mnt/Foxconn/Digitalent/Deverloper/liff-push_2series"
]
],
"_from": "cookie@0.3.1",
"_id": "cookie@0.3.1",
"_inBundle": false,
"_integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=",
"_location": "/@nuxtjs/youch/cookie",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
"raw": "cookie@0.3.1",
"name": "cookie",
"escapedName": "cookie",
"rawSpec": "0.3.1",
"saveSpec": null,
"fetchSpec": "0.3.1"
},
"_requiredBy": [
"/@nuxtjs/youch"
],
"_resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
"_spec": "0.3.1",
"_where": "/mnt/Foxconn/Digitalent/Deverloper/liff-push_2series",
"author": {
"name": "Roman Shtylman",
"email": "shtylman@gmail.com"
},
"bugs": {
"url": "https://github.com/jshttp/cookie/issues"
},
"contributors": [
{
"name": "Douglas Christopher Wilson",
"email": "doug@somethingdoug.com"
}
],
"description": "HTTP server cookie parsing and serialization",
"devDependencies": {
"istanbul": "0.4.3",
"mocha": "1.21.5"
},
"engines": {
"node": ">= 0.6"
},
"files": [
"HISTORY.md",
"LICENSE",
"README.md",
"index.js"
],
"homepage": "https://github.com/jshttp/cookie#readme",
"keywords": [
"cookie",
"cookies"
],
"license": "MIT",
"name": "cookie",
"repository": {
"type": "git",
"url": "git+https://github.com/jshttp/cookie.git"
},
"scripts": {
"test": "mocha --reporter spec --bail --check-leaks test/",
"test-ci": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/",
"test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/"
},
"version": "0.3.1"
}
+80
View File
@@ -0,0 +1,80 @@
{
"_args": [
[
"@nuxtjs/youch@4.2.3",
"/mnt/Foxconn/Digitalent/Deverloper/liff-push_2series"
]
],
"_from": "@nuxtjs/youch@4.2.3",
"_id": "@nuxtjs/youch@4.2.3",
"_inBundle": false,
"_integrity": "sha512-XiTWdadTwtmL/IGkNqbVe+dOlT+IMvcBu7TvKI7plWhVQeBCQ9iKhk3jgvVWFyiwL2yHJDlEwOM5v9oVES5Xmw==",
"_location": "/@nuxtjs/youch",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
"raw": "@nuxtjs/youch@4.2.3",
"name": "@nuxtjs/youch",
"escapedName": "@nuxtjs%2fyouch",
"scope": "@nuxtjs",
"rawSpec": "4.2.3",
"saveSpec": null,
"fetchSpec": "4.2.3"
},
"_requiredBy": [
"/@nuxt/server"
],
"_resolved": "https://registry.npmjs.org/@nuxtjs/youch/-/youch-4.2.3.tgz",
"_spec": "4.2.3",
"_where": "/mnt/Foxconn/Digitalent/Deverloper/liff-push_2series",
"author": {
"name": "amanvirk"
},
"bugs": {
"url": "https://github.com/poppinss/nuxt/issues"
},
"config": {
"commitizen": {
"path": "./node_modules/cz-conventional-changelog"
}
},
"dependencies": {
"cookie": "^0.3.1",
"mustache": "^2.3.0",
"stack-trace": "0.0.10"
},
"description": "Pretty error reporting for Node.js 🚀 (Modified for Nuxt.js & SSR Bundles)",
"devDependencies": {
"cz-conventional-changelog": "^2.0.0",
"japa": "^1.0.3",
"japa-cli": "^1.0.1",
"standard": "^10.0.2",
"supertest": "^3.0.0"
},
"directories": {
"example": "examples"
},
"homepage": "https://github.com/poppinss/nuxt#readme",
"keywords": [
"errors",
"error-reporting",
"whoops"
],
"license": "MIT",
"main": "src/Youch/index.js",
"name": "@nuxtjs/youch",
"publishConfig": {
"access": "public"
},
"repository": {
"type": "git",
"url": "git+https://github.com/nuxt/youch.git"
},
"scripts": {
"lint": "standard",
"test": "japa",
"test:win": "node ./node_modules/japa-cli/index.js"
},
"version": "4.2.3"
}
+349
View File
@@ -0,0 +1,349 @@
'use strict'
/*
* youch
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
const Mustache = require('mustache')
const path = require('path')
const stackTrace = require('stack-trace')
const fs = require('fs')
const cookie = require('cookie')
const VIEW_PATH = '../resources/error.mustache'
const startingSlashRegex = /\\|\//
const viewTemplate = fs.readFileSync(path.join(__dirname, VIEW_PATH), 'utf-8')
class Youch {
constructor (error, request, readSource, baseURL, addCol) {
this.error = error
this.request = request
this.readSource = typeof readSource === 'function' ? readSource : this._readSource
this.baseURL = baseURL || '/'
this.addCol = addCol === undefined ? true : Boolean(addCol)
this.codeContext = 5
this._filterHeaders = ['cookie', 'connection']
this._filterFrames = [
/regenerator-runtime/,
/babel-runtime/,
/core-js\/library/
]
}
/**
* Reads the source code for a given frame into frame.contents
*
* @param {String} path
* @return {Promise}
*/
_readSource (frame) {
return new Promise((resolve, reject) => {
if(!frame.fileName) {
return resolve()
}
fs.readFile(frame.fileName, 'utf-8', (error, contents) => {
if (!error && contents) {
frame.contents = contents
}
resolve()
})
})
}
/**
* Returns source code for a given frame.
*
* @param {Object} frame
* @return {Promise}
*/
_getFrameSource (frame) {
return this.readSource(frame).then(()=> {
if (!frame.contents) {
return
}
const lines = frame.contents.split(/\r?\n/)
const lineNumber = frame.getLineNumber()
return {
pre: lines.slice(Math.max(0, lineNumber - (this.codeContext + 1)), lineNumber - 1),
line: lines[lineNumber - 1],
post: lines.slice(lineNumber, lineNumber + this.codeContext)
}
})
}
/**
* Parses the error stack and returns serialized
* frames out of it.
*
* @return {Object}
*/
_parseError () {
const stack = stackTrace.parse(this.error)
return Promise.all(stack.map((frame) => {
if (this._isNode(frame)) {
return Promise.resolve(frame)
}
return this._getFrameSource(frame).then((context) => {
frame.context = context
return frame
})
}))
.then(stack => stack.filter(this._isVisible.bind(this)))
.then(stack => {
let hasInternal = false
for (let frame of stack) {
if (!this._isApp(frame) && !this._isNode(frame)) {
hasInternal = true
break
}
}
return {stack, hasInternal}
})
}
/**
* Returns the context with code for a given
* frame.
*
* @param {Object}
* @return {Object}
*/
_getContext (frame) {
if (!frame.context) {
return {}
}
return {
start: frame.getLineNumber() - (frame.context.pre || []).length,
pre: frame.context.pre.join('\n'),
line: frame.context.line,
post: frame.context.post.join('\n'),
}
}
/**
* Returns classes to be used inside HTML when
* displaying the frames list.
*
* @param {Object}
* @param {Number}
*
* @return {String}
*/
_getDisplayClasses (frame, index) {
const classes = []
if (index === 0) {
classes.push('active')
}
if (!this._isApp(frame)) {
classes.push('native-frame')
}
return classes.join(' ')
}
/**
* Compiles the view using HTML
*
* @param {String}
* @param {Object}
*
* @return {String}
*/
_compileView (view, data) {
return Mustache.render(view, data)
}
/**
* Serializes frame to a usable error object.
*
* @param {Object}
*
* @return {Object}
*/
_serializeFrame (frame) {
const relativeFileName = frame.getFileName().indexOf(process.cwd()) > -1
? frame.getFileName().replace(process.cwd(), '').replace(startingSlashRegex, '')
: frame.getFileName()
return {
file: relativeFileName,
method: frame.getFunctionName(),
line: frame.getLineNumber(),
column: frame.getColumnNumber(),
context: this._getContext(frame),
lang: this._getLang(frame),
open: this._openURL(frame)
}
}
_openURL(frame) {
if (!frame.fullPath) {
return
}
return this.baseURL + '__open-in-editor' +
'?file=' + encodeURI(frame.fullPath || frame.fileName) +
':' + (frame.getLineNumber() || 0) +
(this.addCol ? (':' + (frame.getColumnNumber() || 0)) : '')
}
/**
* Returns whether frame belongs to nodejs
* or not.
*
* @return {Boolean} [description]
*/
_isNode (frame) {
if (frame.isNative()) {
return true
}
// const filename = frame.getFileName() || ''
// return !path.isAbsolute(filename) && filename[0] !== '.'
return false
}
/**
* Returns whether code belongs to the app
* or not.
*
* @return {Boolean} [description]
*/
_isApp (frame) {
if (this._isNode(frame)) {
return false
}
return !~(frame.getFileName() || '').indexOf('node_modules' + path.sep)
}
/**
* Returns whether frame should be visible
* or not.
*
* @return {Boolean} [description]
*/
_isVisible (frame) {
return this._filterFrames.every(f => !f.test(frame.getFileName()))
}
_getLang(frame) {
let name = frame.getFileName() || ''
let lang = 'js'
if(name.indexOf('.vue') !== -1) {
lang = 'html'
}
return lang
}
/**
* Serializes stack to Mustache friendly object to
* be used within the view. Optionally can pass
* a callback to customize the frames output.
*
* @param {Object}
* @param {Function} [callback]
*
* @return {Object}
*/
_serializeData (stack, callback) {
callback = callback || this._serializeFrame.bind(this)
return {
message: this.error.message,
name: this.error.name,
status: this.error.status,
frames: stack instanceof Array === true ? stack.filter((frame) => frame.getFileName()).map(callback) : []
}
}
/**
* Returns a serialized object with important
* information.
*
* @return {Object}
*/
_serializeRequest () {
const headers = []
Object.keys(this.request.headers).forEach((key) => {
if (this._filterHeaders.indexOf(key) > -1) {
return
}
headers.push({
key: key.toUpperCase(),
value: this.request.headers[key]
})
})
const parsedCookies = cookie.parse(this.request.headers.cookie || '')
const cookies = Object.keys(parsedCookies).map((key) => {
return {key, value: parsedCookies[key]}
})
return {
url: this.request.url,
httpVersion: this.request.httpVersion,
method: this.request.method,
connection: this.request.headers.connection,
headers: headers,
cookies: cookies
}
}
/**
* Returns error stack as JSON.
*
* @return {Promise}
*/
toJSON () {
return new Promise((resolve, reject) => {
this
._parseError()
.then(({ stack, hasInternal }) => {
resolve({
error: this._serializeData(stack),
hasInternal
})
})
.catch(reject)
})
}
/**
* Returns HTML representation of the error stack
* by parsing the stack into frames and getting
* important info out of it.
*
* @return {Promise}
*/
toHTML () {
return new Promise((resolve, reject) => {
this
._parseError()
.then(({ stack, hasInternal }) => {
const data = this._serializeData(stack, (frame, index) => {
const serializedFrame = this._serializeFrame(frame)
serializedFrame.classes = this._getDisplayClasses(frame, index)
return serializedFrame
})
const request = this._serializeRequest()
data.request = request
data.hasInternal = hasInternal
resolve(this._compileView(viewTemplate, data))
})
.catch(reject)
})
}
}
module.exports = Youch
File diff suppressed because one or more lines are too long
+1359
View File
File diff suppressed because it is too large Load Diff