From 4e87195739f2a5d9a05451b48773c8afdc680765 Mon Sep 17 00:00:00 2001
From: akiyamn
Date: Sun, 24 Sep 2023 23:22:21 +1000
Subject: Initial commit (by create-cloudflare CLI)
---
node_modules/youch/LICENSE.md | 19 +
node_modules/youch/README.md | 166 ++++++
node_modules/youch/index.d.ts | 66 +++
node_modules/youch/package.json | 59 ++
node_modules/youch/src/Youch.js | 381 ++++++++++++
node_modules/youch/src/error.compiled.mustache | 766 +++++++++++++++++++++++++
6 files changed, 1457 insertions(+)
create mode 100644 node_modules/youch/LICENSE.md
create mode 100644 node_modules/youch/README.md
create mode 100644 node_modules/youch/index.d.ts
create mode 100644 node_modules/youch/package.json
create mode 100644 node_modules/youch/src/Youch.js
create mode 100644 node_modules/youch/src/error.compiled.mustache
(limited to 'node_modules/youch')
diff --git a/node_modules/youch/LICENSE.md b/node_modules/youch/LICENSE.md
new file mode 100644
index 0000000..cf42283
--- /dev/null
+++ b/node_modules/youch/LICENSE.md
@@ -0,0 +1,19 @@
+Copyright (c) 2018 virk.officials@gmail.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.
diff --git a/node_modules/youch/README.md b/node_modules/youch/README.md
new file mode 100644
index 0000000..1466c21
--- /dev/null
+++ b/node_modules/youch/README.md
@@ -0,0 +1,166 @@
+# Youch!
+> Pretty error reporting for Node.js :rocket:
+
+
+
+
+
+
+
+
+
+
+
+---
+
+
+
+[![NPM Version][npm-image]][npm-url]
+[![Tests][gh-workflow-image]][gh-workflow-url]
+[![Downloads Stats][npm-downloads-image]][npm-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.
+4. Support for ESM.
+
+> Checkout [youch terminal](https://github.com/poppinss/youch-terminal) to beautify errors on terminal.
+
+## Installation
+```bash
+npm i --save youch
+```
+
+## Basic Usage
+Youch is used by [AdonisJs](http://adonisjs.com), but it can be used by express or raw HTTP server as well.
+
+```javascript
+const Youch = require('youch')
+const http = require('http')
+
+http.createServer(async function (req, res) {
+
+ // PERFORM SOME ACTION
+ if (error) {
+ const youch = new Youch(error, req)
+ const html = await youch.toHTML()
+
+ res.writeHead(200, {'content-type': 'text/html'})
+ res.write(html)
+ res.end()
+ }
+
+}).listen(8000)
+```
+
+## Adding helpful links
+Everytime an error occurs, we can help users we letting search for the error on Google, over even on the Github repo of our project.
+
+Youch let you define clickable links to redirect the user to a website with the error message.
+
+```js
+const youch = new Youch(error)
+
+await youch
+ .addLink(({ message }) => {
+ const url = `https://stackoverflow.com/search?q=${encodeURIComponent(`[adonis.js] ${message}`)}`
+
+ return `Search stackoverflow `
+ })
+ .toHTML()
+```
+
+Also you can make use of [Font awesome brands icons](https://fontawesome.com/icons?d=gallery&s=brands&m=free) to display icons.
+
+**If you will use fontawesome icons, then Youch will automatically load the CSS files from the font awesome CDN for you.**
+
+```js
+const youch = new Youch(error)
+
+await youch
+ .addLink(({ message }) => {
+ const url = `https://stackoverflow.com/search?q=${encodeURIComponent(`[adonis.js] ${message}`)}`
+ return ` `
+ })
+ .toHTML()
+```
+
+## Toggle show all frames checkbox
+When rendering HTML you can call the `toggleShowAllFrames` method to check/uncheck the show all frames checkbox.
+
+By default, the checkbox is not checked and calling this method once will toggle the state.
+
+```js
+const youch = new Youch(error)
+
+await youch
+ .toggleShowAllFrames()
+ .toHTML()
+```
+
+## Adding CSP nonce
+Youch HTML output outputs inline `style` and `script` tags and therefore you will have add `nonce` attribute to them when you have enabled CSP on your website.
+
+You can pass the `cspNonce` property to the `toHTML` method at the time of rendering the error to an HTML output.
+
+```js
+const youch = new Youch(error, req)
+const html = await youch.toHTML({
+ cspNonce: 'nonce-value'
+})
+```
+
+## Get stack as JSON
+You can also the error stack frames as JSON by calling the `.toJSON` method.
+
+```js
+const youch = new Youch(error, {})
+const jsonResponse = await youch.toJSON()
+```
+
+Following is the shape of the `toJSON` return data type.
+
+```ts
+type JsonResponse = {
+ error: {
+ message: string;
+ name: string;
+ status: number;
+ frames: {
+ file: string,
+ filePath: string,
+ line: number,
+ column: number,
+ callee: string,
+ calleeShort: string,
+ context: {
+ start: number,
+ pre: string,
+ line: string,
+ post: string,
+ },
+ isModule: boolean,
+ isNative: boolean,
+ isApp: boolean
+ }[];
+ };
+}
+```
+
+## Release History
+Checkout [CHANGELOG.md](CHANGELOG.md) file for release history.
+
+## Meta
+Checkout [LICENSE.md](LICENSE.md) for license information
+Harminder Virk (Aman) - [https://github.com/thetutlage](https://github.com/thetutlage)
+
+[gh-workflow-image]: https://img.shields.io/github/actions/workflow/status/poppinss/youch/test.yml?style=for-the-badge
+[gh-workflow-url]: https://github.com/poppinss/youch/actions/workflows/test.yml "Github action"
+
+[npm-image]: https://img.shields.io/npm/v/youch.svg?style=for-the-badge&logo=npm
+[npm-url]: https://npmjs.org/package/youch 'npm'
+
+[npm-downloads-image]: https://img.shields.io/npm/dm/youch.svg?style=for-the-badge
diff --git a/node_modules/youch/index.d.ts b/node_modules/youch/index.d.ts
new file mode 100644
index 0000000..b83370a
--- /dev/null
+++ b/node_modules/youch/index.d.ts
@@ -0,0 +1,66 @@
+declare module "youch" {
+
+ interface YouchOptionsContract {
+ /**
+ * Number of lines to be displayed above the error
+ * in the stack trace.
+ */
+ preLines?: number;
+
+ /**
+ * Number of lines to be displayed below the error
+ * in the stack trace.
+ */
+ postLines?: number;
+ }
+
+ class Youch {
+ constructor(error: Error, request: Request, options?: YouchOptionsContract);
+
+ /**
+ * Stores the link `callback` which
+ * will be processed when rendering
+ * the HTML view.
+ */
+ addLink(callback: Function): this;
+
+ /**
+ * Returns error stack as JSON.
+ */
+ toJSON(): Promise<{
+ error: {
+ message: string;
+ name: string;
+ cause?: any;
+ help?: any;
+ status: number;
+ frames: {
+ file: string;
+ filePath: string;
+ line: number;
+ column: number;
+ callee: string;
+ calleeShort: string;
+ context: {
+ start: number;
+ pre: string;
+ line: string;
+ post: string;
+ };
+ isModule: boolean;
+ isNative: boolean;
+ isApp: boolean;
+ }[];
+ };
+ }>;
+
+ /**
+ * Returns HTML representation of the error stack
+ * by parsing the stack into frames and getting
+ * important info out of it.
+ */
+ toHTML(data: Record): Promise;
+ }
+
+ export default Youch;
+}
diff --git a/node_modules/youch/package.json b/node_modules/youch/package.json
new file mode 100644
index 0000000..216a199
--- /dev/null
+++ b/node_modules/youch/package.json
@@ -0,0 +1,59 @@
+{
+ "name": "youch",
+ "version": "3.3.2",
+ "description": "HTML Pretty error stack viewer",
+ "main": "src/Youch.js",
+ "files": [
+ "src",
+ "index.d.ts"
+ ],
+ "types": "./index.d.ts",
+ "directories": {
+ "example": "examples"
+ },
+ "scripts": {
+ "pretest": "npm run lint",
+ "prepublishOnly": "npm run build",
+ "build": "node bin/compile.js",
+ "test": "npm run build && node test/youch.spec.js && node test/youch.spec.mjs",
+ "lint": "standard"
+ },
+ "author": "amanvirk",
+ "license": "MIT",
+ "devDependencies": {
+ "concat": "^1.0.3",
+ "cz-conventional-changelog": "^3.3.0",
+ "japa": "^4.0.0",
+ "standard": "^17.0.0",
+ "supertest": "^6.3.3",
+ "uglify-js": "^3.17.4"
+ },
+ "config": {
+ "commitizen": {
+ "path": "./node_modules/cz-conventional-changelog"
+ }
+ },
+ "dependencies": {
+ "cookie": "^0.5.0",
+ "mustache": "^4.2.0",
+ "stacktracey": "^2.1.8"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/poppinss/youch.git"
+ },
+ "keywords": [
+ "errors",
+ "error-reporting",
+ "whoops"
+ ],
+ "bugs": {
+ "url": "https://github.com/poppinss/youch/issues"
+ },
+ "standard": {
+ "ignore": [
+ "static"
+ ]
+ },
+ "homepage": "https://github.com/poppinss/youch#readme"
+}
diff --git a/node_modules/youch/src/Youch.js b/node_modules/youch/src/Youch.js
new file mode 100644
index 0000000..bcd3899
--- /dev/null
+++ b/node_modules/youch/src/Youch.js
@@ -0,0 +1,381 @@
+'use strict'
+
+/*
+ * youch
+ *
+ * (c) Harminder Virk
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+const fs = require('fs')
+const path = require('path')
+const cookie = require('cookie')
+const Mustache = require('mustache')
+const { fileURLToPath } = require('url')
+const StackTracey = require('stacktracey')
+
+const VIEW_PATH = './error.compiled.mustache'
+const viewTemplate = fs.readFileSync(path.join(__dirname, VIEW_PATH), 'utf-8')
+
+class Youch {
+ constructor (error, request, options = {}) {
+ this.options = options
+ this.options.postLines = options.postLines || 5
+ this.options.preLines = options.preLines || 5
+
+ this._filterHeaders = ['cookie', 'connection']
+ this.error = error
+ this.request = request
+ this.links = []
+ this.showAllFrames = false
+ }
+
+ /**
+ * Returns the source code for a given file. It unable to
+ * read file it resolves the promise with a null.
+ *
+ * @param {Object} frame
+ * @return {Promise}
+ */
+ _getFrameSource (frame) {
+ let path = frame
+ .file
+ .replace(/dist\/webpack:\//g, '') // unix
+ .replace(/dist\\webpack:\\/g, '') // windows
+
+ /**
+ * We ignore the error when "fileURLToPath" is unable to parse
+ * the path, since returning the frame source is an optional
+ * thing
+ */
+ try {
+ path = path.startsWith('file:') ? fileURLToPath(path) : path
+ } catch {
+ }
+
+ return new Promise((resolve) => {
+ fs.readFile(path, 'utf-8', (error, contents) => {
+ if (error) {
+ resolve(null)
+ return
+ }
+
+ const lines = contents.split(/\r?\n/)
+ const lineNumber = frame.line
+
+ resolve({
+ pre: lines.slice(
+ Math.max(0, lineNumber - (this.options.preLines + 1)),
+ lineNumber - 1
+ ),
+ line: lines[lineNumber - 1],
+ post: lines.slice(lineNumber, lineNumber + this.options.postLines)
+ })
+ })
+ })
+ }
+
+ /**
+ * Parses the error stack and returns serialized
+ * frames out of it.
+ *
+ * @return {Object}
+ */
+ _parseError () {
+ return new Promise((resolve, reject) => {
+ const stack = new StackTracey(this.error)
+ Promise.all(
+ stack.items.map(async (frame) => {
+ if (this._isNode(frame)) {
+ return Promise.resolve(frame)
+ }
+ return this._getFrameSource(frame).then((context) => {
+ frame.context = context
+ return frame
+ })
+ })
+ )
+ .then(resolve)
+ .catch(reject)
+ })
+ }
+
+ /**
+ * Returns the context with code for a given
+ * frame.
+ *
+ * @param {Object}
+ * @return {Object}
+ */
+ _getContext (frame) {
+ if (!frame.context) {
+ return {}
+ }
+
+ return {
+ start: frame.line - (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) {
+ const classes = []
+ if (!frame.isApp) {
+ classes.push('native-frame')
+ }
+
+ return classes
+ }
+
+ /**
+ * 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) {
+ return {
+ file: frame.fileRelative,
+ filePath: frame.file.startsWith('file:')
+ ? fileURLToPath(frame.file).replaceAll('\\', '/')
+ : frame.file,
+ line: frame.line,
+ callee: frame.callee,
+ calleeShort: frame.calleeShort,
+ column: frame.column,
+ context: this._getContext(frame),
+ isModule: frame.thirdParty,
+ isNative: frame.native,
+ isApp: this._isApp(frame)
+ }
+ }
+
+ /**
+ * Returns whether frame belongs to nodejs
+ * or not.
+ *
+ * @return {Boolean} [description]
+ */
+ _isNode (frame) {
+ if (frame.native) {
+ return true
+ }
+
+ const filename = frame.file || ''
+ if (filename.startsWith('node:')) {
+ return true
+ }
+ return false
+
+ // return !path.isAbsolute(filename) && filename[0] !== '.'
+ }
+
+ /**
+ * Returns whether code belongs to the app
+ * or not.
+ *
+ * @return {Boolean} [description]
+ */
+ _isApp (frame) {
+ return !this._isNode(frame) && !this._isNodeModule(frame)
+ }
+
+ /**
+ * Returns whether frame belongs to a node_module or
+ * not
+ *
+ * @method _isNodeModule
+ *
+ * @param {Object} frame
+ *
+ * @return {Boolean}
+ *
+ * @private
+ */
+ _isNodeModule (frame) {
+ return (frame.file || '').indexOf('node_modules/') > -1
+ }
+
+ /**
+ * 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,
+ help: this.error.help,
+ cause: this.error.cause,
+ name: this.error.name,
+ status: this.error.status,
+ frames:
+ stack instanceof Array === true
+ ? stack.filter((frame) => frame.file).map(callback)
+ : []
+ }
+ }
+
+ /**
+ * Returns a serialized object with important
+ * information.
+ *
+ * @return {Object}
+ */
+ _serializeRequest () {
+ const headers = []
+ const cookies = []
+
+ if (this.request.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]
+ })
+ })
+
+ if (this.request.headers.cookie) {
+ const parsedCookies = cookie.parse(this.request.headers.cookie || '')
+ Object.keys(parsedCookies).forEach((key) => {
+ cookies.push({ key, value: parsedCookies[key] })
+ })
+ }
+ }
+
+ return {
+ url: this.request.url,
+ httpVersion: this.request.httpVersion,
+ method: this.request.method,
+ connection: this.request.headers ? this.request.headers.connection : null,
+ headers,
+ cookies
+ }
+ }
+
+ /**
+ * Stores the link `callback` which
+ * will be processed when rendering
+ * the HTML view.
+ *
+ * @param {Function} callback
+ *
+ * @returns {Object}
+ */
+ addLink (callback) {
+ if (typeof callback === 'function') {
+ this.links.push(callback)
+ return this
+ }
+
+ throw new Error('Pass a callback function to "addLink"')
+ }
+
+ /**
+ * Toggle the state of showing all frames by default
+ */
+ toggleShowAllFrames () {
+ this.showAllFrames = !this.showAllFrames
+ return this
+ }
+
+ /**
+ * Returns error stack as JSON.
+ *
+ * @return {Promise}
+ */
+ toJSON () {
+ return new Promise((resolve, reject) => {
+ this._parseError()
+ .then((stack) => {
+ resolve({
+ error: this._serializeData(stack)
+ })
+ })
+ .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 (templateState) {
+ return new Promise((resolve, reject) => {
+ this._parseError()
+ .then((stack) => {
+ let foundActiveFrame = false
+
+ const data = this._serializeData(stack, (frame, index) => {
+ const serializedFrame = this._serializeFrame(frame)
+ const classes = this._getDisplayClasses(serializedFrame)
+
+ /**
+ * Adding active class to first app framework
+ */
+ if (!foundActiveFrame && (serializedFrame.isApp || index + 1 === stack.length)) {
+ classes.push('active')
+ foundActiveFrame = true
+ }
+
+ serializedFrame.classes = classes.join(' ')
+
+ return serializedFrame
+ })
+
+ if (templateState) {
+ Object.assign(data, templateState)
+ }
+
+ if (this.request) {
+ data.request = this._serializeRequest()
+ }
+
+ data.links = this.links.map((renderLink) => renderLink(data))
+ data.loadFA = !!data.links.find((link) => link.includes('fa-'))
+ data.showAllFrames = this.showAllFrames
+
+ return resolve(this._compileView(viewTemplate, data))
+ })
+ .catch(reject)
+ })
+ }
+}
+
+module.exports = Youch
diff --git a/node_modules/youch/src/error.compiled.mustache b/node_modules/youch/src/error.compiled.mustache
new file mode 100644
index 0000000..952db8b
--- /dev/null
+++ b/node_modules/youch/src/error.compiled.mustache
@@ -0,0 +1,766 @@
+
+
+
+
+
+
+ {{#loadFA}}
+
+
+ {{/loadFA}}
+
+ {{#cspNonce}}
+
+
+
+
+
+
+ {{ status }}
+
+
+
{{ name }}
+
{{ message }}
+
+ {{#links}}
+ {{{ . }}}
+ {{/links}}
+
+
+
+
+ {{!-- Filled using frontend code, based upon the active frame --}}
+
+
+
+
+
+ Show all frames
+
+
+
+ {{#frames}}
+ {{ index }}
+
+
+ {{ file }}:{{ line }}:{{ column }}
+
+
+ {{ callee }}
+
+
{{ context.pre }}
+{{ context.line }}
+{{ context.post }}
+
+
+ {{/frames}}
+
+
+
+
+
+ {{#request}}
+
+ Request Details
+
+
+
+ URI
+ {{ request.url }}
+
+
+
+ Request Method
+ {{ request.method }}
+
+
+
+ HTTP Version
+ {{ request.httpVersion }}
+
+
+
+ Connection
+ {{ request.connection }}
+
+
+
+ Headers
+
+
+ {{#request.headers}}
+
+ {{ key }}
+ {{ value }}
+
+ {{/request.headers}}
+
+
+ Cookies
+
+ {{#request.cookies}}
+
+ {{ key }}
+ {{ value }}
+
+ {{/request.cookies}}
+
+
+ {{/request}}
+
+ {{#cspNonce}}
+
+
+
--
cgit v1.2.3