parent
							
								
									1158bbc1a1
								
							
						
					
					
						commit
						78f2399c8e
					
				@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    "private": true,
 | 
				
			||||||
 | 
					    "name": "super-hog",
 | 
				
			||||||
 | 
					    "workspaces": [
 | 
				
			||||||
 | 
					        "packages/*"
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    "scripts": {
 | 
				
			||||||
 | 
					        "start": "yarn workspace runner run start"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
											
												
													File diff suppressed because it is too large
													Load Diff
												
											
										
									
								@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    "name": "frontend",
 | 
				
			||||||
 | 
					    "version": "0.1.0",
 | 
				
			||||||
 | 
					    "dependencies": {
 | 
				
			||||||
 | 
					        "@tiny-components/plain-ui": "^0.5.0",
 | 
				
			||||||
 | 
					        "@tiny-components/validator": "^0.1.0",
 | 
				
			||||||
 | 
					        "riot": "^6.1.2"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "devDependencies": {
 | 
				
			||||||
 | 
					        "@riotjs/webpack-loader": "^6.0.0",
 | 
				
			||||||
 | 
					        "laravel-mix": "^6.0.43",
 | 
				
			||||||
 | 
					        "laravel-mix-purgecss": "^6.0.0",
 | 
				
			||||||
 | 
					        "svg-spritemap-webpack-plugin": "^4.4.0"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					{% layout 'layout.liquid' %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block app_main %}
 | 
				
			||||||
 | 
					<div class="container">
 | 
				
			||||||
 | 
					    <div class="grid justify-center">
 | 
				
			||||||
 | 
					        <div class="col-12 col-md-8">
 | 
				
			||||||
 | 
					            <app-view></app-view>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					{% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block script %}
 | 
				
			||||||
 | 
					<script async src="/js/app.js"></script>
 | 
				
			||||||
 | 
					{% endblock %}
 | 
				
			||||||
@ -0,0 +1,59 @@
 | 
				
			|||||||
 | 
					<!doctype html>
 | 
				
			||||||
 | 
					<html lang="en_EN">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<head>
 | 
				
			||||||
 | 
					    <meta charset="utf-8">
 | 
				
			||||||
 | 
					    <title></title>
 | 
				
			||||||
 | 
					    <meta name="description" content="">
 | 
				
			||||||
 | 
					    <meta name="viewport" content="width=device-width, initial-scale=1">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <link href="/css/styles.css" rel="stylesheet" type="text/css">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {% block head %}{% endblock %}
 | 
				
			||||||
 | 
					</head>
 | 
				
			||||||
 | 
					<body>
 | 
				
			||||||
 | 
					    <header>
 | 
				
			||||||
 | 
					        {% block app_header %}
 | 
				
			||||||
 | 
					            <div class="bar">
 | 
				
			||||||
 | 
					                <div class="bar__start">
 | 
				
			||||||
 | 
					                    <h1 class="m-top-4 m-bottom-4 h4">
 | 
				
			||||||
 | 
					                        Super Hog
 | 
				
			||||||
 | 
					                    </h1>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        {% endblock %}
 | 
				
			||||||
 | 
					    </header>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <main>
 | 
				
			||||||
 | 
					        {% block app_main %}{% endblock %}
 | 
				
			||||||
 | 
					    </main>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <footer>
 | 
				
			||||||
 | 
					        <div class="container">
 | 
				
			||||||
 | 
					            <div class="grid justify-center">
 | 
				
			||||||
 | 
					                <div class="col-12 col-md-8">
 | 
				
			||||||
 | 
					                    <hr / class="m-top-8">
 | 
				
			||||||
 | 
					                    <div class="group">
 | 
				
			||||||
 | 
					                        <div class="group__item">
 | 
				
			||||||
 | 
					                            Published under
 | 
				
			||||||
 | 
					                            <strong>
 | 
				
			||||||
 | 
					                                MIT License
 | 
				
			||||||
 | 
					                            </strong>
 | 
				
			||||||
 | 
					                        </div>
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    </footer>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <noscript>
 | 
				
			||||||
 | 
					        <p>Only works with Javascript!</p>
 | 
				
			||||||
 | 
					    </noscript>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <script>
 | 
				
			||||||
 | 
					        const csrfToken = '{{ csrfToken }}'
 | 
				
			||||||
 | 
					    </script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {% block script %}{% endblock %}
 | 
				
			||||||
 | 
					</body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					import Interface from 'es6-interface'
 | 
				
			||||||
 | 
					import https from 'https'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import ActionInterface from './actionInterface.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Action extends Interface(ActionInterface)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  @param {[type]} data
 | 
				
			||||||
 | 
					     *  @param {[type]} source
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    constructor(source, data, options)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        super()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.source = source
 | 
				
			||||||
 | 
					        this.data = data
 | 
				
			||||||
 | 
					        this.options = options
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Action
 | 
				
			||||||
@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ActionInterface = {
 | 
				
			||||||
 | 
					    run: function()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default ActionInterface
 | 
				
			||||||
@ -0,0 +1,58 @@
 | 
				
			|||||||
 | 
					import got from 'got'
 | 
				
			||||||
 | 
					import url from 'url'
 | 
				
			||||||
 | 
					import path from 'path'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { createWriteStream } from 'fs'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import Action from './action.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  @extends Action
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class DownloadPodcast extends Action
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    async run()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // count of files 
 | 
				
			||||||
 | 
					        let files = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // errors
 | 
				
			||||||
 | 
					        let errors = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (let item of this.data.rss.channel.item)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // gettin
 | 
				
			||||||
 | 
					            const pubDate = new Date(item.pubDate)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // check for new entries
 | 
				
			||||||
 | 
					            if (pubDate >= new Date(this.source.last_run_at))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                const parsedUrl = url.parse(item.link)
 | 
				
			||||||
 | 
					                const filename = decodeURIComponent(path.basename(parsedUrl.pathname))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                const downloadStream = got.stream(item.link)
 | 
				
			||||||
 | 
					                const fileWriterStream = createWriteStream(this.options.destination + '/' + filename)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                downloadStream
 | 
				
			||||||
 | 
					                    .on('error', (error) => {
 | 
				
			||||||
 | 
					                        console.error(`Download failed: ${error.message}`)
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                fileWriterStream
 | 
				
			||||||
 | 
					                    .on('error', (error) => {
 | 
				
			||||||
 | 
					                        console.error(`Could not write file to system: ${error.message}`)
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					                    .on('finish', () => {
 | 
				
			||||||
 | 
					                        files++
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                await downloadStream.pipe(fileWriterStream)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default DownloadPodcast
 | 
				
			||||||
@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					import Interface from 'es6-interface'
 | 
				
			||||||
 | 
					import Action from './../../actions/action.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class MoveFile extends Action
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    run()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        for (const item of this.data.rss.channel.item) {
 | 
				
			||||||
 | 
					            console.log(item)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default MoveFile
 | 
				
			||||||
@ -0,0 +1,72 @@
 | 
				
			|||||||
 | 
					import path from 'path'
 | 
				
			||||||
 | 
					import fs from 'fs'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ResolverClass
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  @param {String} prefix
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    constructor(prefix)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        this.prefix = prefix
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  @param  {String}  className
 | 
				
			||||||
 | 
					     *  @param  {Boolean} [isCustom=false]
 | 
				
			||||||
 | 
					     *  @return {String}
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    lookupPath(className, isCustom = false)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        let custom = ''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (isCustom) {
 | 
				
			||||||
 | 
					            custom = '/custom/'
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return path.join(path.resolve(), custom + this.prefix + '/' + className + '.js')
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  @param  {[type]} className
 | 
				
			||||||
 | 
					     *  @return {[type]}           [description]
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    find(className)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // getting
 | 
				
			||||||
 | 
					        let classPath = this.lookupPath(className, true)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // results
 | 
				
			||||||
 | 
					        let result = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (fs.existsSync(classPath)) {
 | 
				
			||||||
 | 
					            result = classPath
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            classPath = this.lookupPath(className)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (fs.existsSync(classPath)) {
 | 
				
			||||||
 | 
					                result = classPath
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!result) {
 | 
				
			||||||
 | 
					            throw new Error('Class ' + className + ' not found!')
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return result
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default ResolverClass
 | 
				
			||||||
@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					import cron from 'node-cron'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const tasks = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// uuid, schedule, source, requestHandler, actions, state
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// start main cron to check for updates while running
 | 
				
			||||||
 | 
					//const main = cron.schedule('* * * * *', () =>  {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//main.start()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import RssHandler from './requestHandlers/rssHandler.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const source = {
 | 
				
			||||||
 | 
					    'name': 'Insert Moin',
 | 
				
			||||||
 | 
					    'url': 'https://steadyhq.com/rss/insertmoin?auth=d37bffc9-9a84-4eed-95f6-3b6cb77c2406',
 | 
				
			||||||
 | 
					    'actions': [{
 | 
				
			||||||
 | 
					        'className': 'downloadPodcast',
 | 
				
			||||||
 | 
					        'options': {
 | 
				
			||||||
 | 
					            'destination': '/home/herrhase/Downloads'
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }],
 | 
				
			||||||
 | 
					    'last_run_at': '2022-01-16T23:01:00.000Z'
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const rssHandler = new RssHandler(source)
 | 
				
			||||||
 | 
					rssHandler.send()
 | 
				
			||||||
@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Notiication
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    webhook(url)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
											
												
													File diff suppressed because it is too large
													Load Diff
												
											
										
									
								@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    "name": "runner",
 | 
				
			||||||
 | 
					    "version": "0.1.0",
 | 
				
			||||||
 | 
					    "scripts": {
 | 
				
			||||||
 | 
					        "start": "node index.js"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "type": "module",
 | 
				
			||||||
 | 
					    "dependencies": {
 | 
				
			||||||
 | 
					        "date-format-parse": "^0.2.7",
 | 
				
			||||||
 | 
					        "dotenv": "^10.0.0",
 | 
				
			||||||
 | 
					        "es6-interface": "^3.2.1",
 | 
				
			||||||
 | 
					        "fast-xml-parser": "^4.0.1",
 | 
				
			||||||
 | 
					        "got": "^12.0.1",
 | 
				
			||||||
 | 
					        "isomorphic-dompurify": "^0.16.0",
 | 
				
			||||||
 | 
					        "node-cron": "^3.0.0",
 | 
				
			||||||
 | 
					        "pouchdb": "^7.2.2",
 | 
				
			||||||
 | 
					        "pouchdb-find": "^7.2.2",
 | 
				
			||||||
 | 
					        "slugify": "^1.6.5"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					import got from 'got'
 | 
				
			||||||
 | 
					import { XMLParser } from 'fast-xml-parser'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import RequestHandler from './requestHandler.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class JsonHandler extends RequestHandler
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     *  getting rss feed from url
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async send()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const buffer = await got(this.source.url, {
 | 
				
			||||||
 | 
					            responseType: 'buffer',
 | 
				
			||||||
 | 
					            resolveBodyOnly: true
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const parser = new XMLParser()
 | 
				
			||||||
 | 
					        const feed = parser.parse(buffer.toString())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.processActions(feed)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default RssHandler
 | 
				
			||||||
@ -0,0 +1,64 @@
 | 
				
			|||||||
 | 
					import Interface from 'es6-interface'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import RequestHandlerInterface from './requestHandlerInterface.js'
 | 
				
			||||||
 | 
					import ResolverClass from './../helpers/resolverClass.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class RequestHandler extends Interface(RequestHandlerInterface)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  @param {[type]} source
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    constructor(source)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        super()
 | 
				
			||||||
 | 
					        this.source = source
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     *  process actions that are saved in a source
 | 
				
			||||||
 | 
					     *  
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  @param  {object} data
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async processActions(data)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        let errors = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.source.actions.forEach(async (actions) =>
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            const resolverClass = new ResolverClass('actions')
 | 
				
			||||||
 | 
					            const classPath = resolverClass.find(actions.className)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // import class from action
 | 
				
			||||||
 | 
					            const Action = await import(classPath)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // create action an call run
 | 
				
			||||||
 | 
					            const action = new Action.default(this.source, data, actions.options)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            //
 | 
				
			||||||
 | 
					            if (!await action.run())
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                errors = true
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // if errors
 | 
				
			||||||
 | 
					        if (errors && this.source.errors < 5) {
 | 
				
			||||||
 | 
					            this.source.errors++
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            this.source.last_run_at = new Date()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default RequestHandler
 | 
				
			||||||
@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const RequestHandlerInterface = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    send: function() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default RequestHandlerInterface
 | 
				
			||||||
@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					import got from 'got'
 | 
				
			||||||
 | 
					import { XMLParser } from 'fast-xml-parser'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import RequestHandler from './requestHandler.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class RssHandler extends RequestHandler
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     *  getting rss feed from url
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async send()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const buffer = await got(this.source.url, {
 | 
				
			||||||
 | 
					            responseType: 'buffer',
 | 
				
			||||||
 | 
					            resolveBodyOnly: true
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const parser = new XMLParser()
 | 
				
			||||||
 | 
					        const feed = parser.parse(buffer.toString())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.processActions(feed)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default RssHandler
 | 
				
			||||||
@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					import fastify from 'fastify'
 | 
				
			||||||
 | 
					import dotenv from 'dotenv'
 | 
				
			||||||
 | 
					import path from 'path'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// getting .env
 | 
				
			||||||
 | 
					dotenv.config({ path: path.join(path.resolve(), '/../../.env') })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// create server
 | 
				
			||||||
 | 
					const server = fastify()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 *  add plugins
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import liquid from './plugins/liquid.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					server.register(liquid)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 *  add routes
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					import authHttp from './http/api/auth.js'
 | 
				
			||||||
 | 
					import indexHttp from './http/index.js'
 | 
				
			||||||
 | 
					import staticHttp from './http/static.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					server
 | 
				
			||||||
 | 
					    .register(authHttp, {
 | 
				
			||||||
 | 
					        'prefix': '/api'
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					    .register(indexHttp)
 | 
				
			||||||
 | 
					    .register(staticHttp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default server
 | 
				
			||||||
@ -0,0 +1,65 @@
 | 
				
			|||||||
 | 
					import DOMPurify from 'isomorphic-dompurify'
 | 
				
			||||||
 | 
					import bcrypt from 'bcrypt'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import UserRepository from './../../repositories/userRepository.js'
 | 
				
			||||||
 | 
					import loginSchema from './../../schemas/auth/login.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 *  handle auth
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  @author Björn Hase, Tentakelfabrik
 | 
				
			||||||
 | 
					 *  @license http://opensource.org/licenses/MIT The MIT License
 | 
				
			||||||
 | 
					 *  @link https://github.com/tentakelfabrik/fastify-lowdb-riotjs-lessons-learned
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default async function(fastify, opts)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     *  auth
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  @param  {object} request
 | 
				
			||||||
 | 
					     *  @param  {object} response
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    fastify.post('/auth', loginSchema, async function (request, reply)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        let { username, password } = request.body
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // strip crap from strings
 | 
				
			||||||
 | 
					        username = DOMPurify.sanitize(username)
 | 
				
			||||||
 | 
					        password = DOMPurify.sanitize(password)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const userRepository = new UserRepository()
 | 
				
			||||||
 | 
					        const user = await userRepository.findOneByUsername(username)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // add header for json
 | 
				
			||||||
 | 
					        reply.header('Content-Type', 'application/json; charset=utf-8')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // user not found
 | 
				
			||||||
 | 
					        if (!user) {
 | 
				
			||||||
 | 
					            return reply
 | 
				
			||||||
 | 
					                .code(404)
 | 
				
			||||||
 | 
					                .send()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // password wrong
 | 
				
			||||||
 | 
					        if (!bcrypt.compareSync(password, user.password)) {
 | 
				
			||||||
 | 
					            return reply
 | 
				
			||||||
 | 
					                .code(401)
 | 
				
			||||||
 | 
					                .send()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // setting session to store and set cookie
 | 
				
			||||||
 | 
					        request.sessionStore.set(request.session.sessionId, request.session, async function() {
 | 
				
			||||||
 | 
					            user.sessionId = request.session.sessionId
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            await userRepository.update(user)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // send 200 and send set-token
 | 
				
			||||||
 | 
					            reply
 | 
				
			||||||
 | 
					                .code(200)
 | 
				
			||||||
 | 
					                .send()
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,43 @@
 | 
				
			|||||||
 | 
					import token from '@fastify/csrf'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 *  index
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  - home view
 | 
				
			||||||
 | 
					 *  - logout user
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  @author Björn Hase, Tentakelfabrik
 | 
				
			||||||
 | 
					 *  @license http://opensource.org/licenses/MIT The MIT License
 | 
				
			||||||
 | 
					 *  @link https://github.com/tentakelfabrik/fastify-lowdb-riotjs-lessons-learned
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default async function(fastify, opts)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     *  home
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  @param  {object} request
 | 
				
			||||||
 | 
					     *  @param  {object} response
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    fastify.get('/', async function(request, response)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        response.view('./views/index.liquid')
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     *  logout 
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  @param  {object} request
 | 
				
			||||||
 | 
					     *  @param  {object} response
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    fastify.get('/logout', async function(request, response)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        request.destroySession(() => {
 | 
				
			||||||
 | 
					            response.redirect('/')
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					import fastifyStatic from 'fastify-static'
 | 
				
			||||||
 | 
					import path from 'path'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 *  handle static
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  @author Björn Hase, Tentakelfabrik
 | 
				
			||||||
 | 
					 *  @license http://opensource.org/licenses/MIT The MIT License
 | 
				
			||||||
 | 
					 *  @link https://github.com/tentakelfabrik/fastify-lowdb-riotjs-lessons-learned
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default async function(fastify, opts)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    fastify.register(fastifyStatic, {
 | 
				
			||||||
 | 
					        root: path.join(path.resolve(), '/../../public'),
 | 
				
			||||||
 | 
					        prefix: '/',
 | 
				
			||||||
 | 
					        preCompressed: true
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					import server from './bootstrap.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// let it rain
 | 
				
			||||||
 | 
					const start = async () => {
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					        await server.listen(process.env.APP_PORT)
 | 
				
			||||||
 | 
					        console.log('Server is running on port ' + process.env.APP_PORT)
 | 
				
			||||||
 | 
					    } catch (error) {
 | 
				
			||||||
 | 
					        console.log(error)
 | 
				
			||||||
 | 
					        process.exit(1)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					start()
 | 
				
			||||||
@ -0,0 +1,689 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    "name": "server",
 | 
				
			||||||
 | 
					    "version": "0.1.0",
 | 
				
			||||||
 | 
					    "lockfileVersion": 1,
 | 
				
			||||||
 | 
					    "requires": true,
 | 
				
			||||||
 | 
					    "dependencies": {
 | 
				
			||||||
 | 
					        "@fastify/ajv-compiler": {
 | 
				
			||||||
 | 
					            "version": "1.1.0",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/@fastify/ajv-compiler/-/ajv-compiler-1.1.0.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-gvCOUNpXsWrIQ3A4aXCLIdblL0tDq42BG/2Xw7oxbil9h11uow10ztS2GuFazNBfjbrsZ5nl+nPl5jDSjj5TSg==",
 | 
				
			||||||
 | 
					            "requires": {
 | 
				
			||||||
 | 
					                "ajv": "^6.12.6"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "abstract-logging": {
 | 
				
			||||||
 | 
					            "version": "2.0.1",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/abstract-logging/-/abstract-logging-2.0.1.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "ajv": {
 | 
				
			||||||
 | 
					            "version": "6.12.6",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
 | 
				
			||||||
 | 
					            "requires": {
 | 
				
			||||||
 | 
					                "fast-deep-equal": "^3.1.1",
 | 
				
			||||||
 | 
					                "fast-json-stable-stringify": "^2.0.0",
 | 
				
			||||||
 | 
					                "json-schema-traverse": "^0.4.1",
 | 
				
			||||||
 | 
					                "uri-js": "^4.2.2"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "archy": {
 | 
				
			||||||
 | 
					            "version": "1.0.0",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "atomic-sleep": {
 | 
				
			||||||
 | 
					            "version": "1.0.0",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "avvio": {
 | 
				
			||||||
 | 
					            "version": "7.2.2",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/avvio/-/avvio-7.2.2.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-XW2CMCmZaCmCCsIaJaLKxAzPwF37fXi1KGxNOvedOpeisLdmxZnblGc3hpHWYnlP+KOUxZsazh43WXNHgXpbqw==",
 | 
				
			||||||
 | 
					            "requires": {
 | 
				
			||||||
 | 
					                "archy": "^1.0.0",
 | 
				
			||||||
 | 
					                "debug": "^4.0.0",
 | 
				
			||||||
 | 
					                "fastq": "^1.6.1",
 | 
				
			||||||
 | 
					                "queue-microtask": "^1.1.2"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "balanced-match": {
 | 
				
			||||||
 | 
					            "version": "1.0.2",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "basic-auth": {
 | 
				
			||||||
 | 
					            "version": "2.0.1",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==",
 | 
				
			||||||
 | 
					            "requires": {
 | 
				
			||||||
 | 
					                "safe-buffer": "5.1.2"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "dependencies": {
 | 
				
			||||||
 | 
					                "safe-buffer": {
 | 
				
			||||||
 | 
					                    "version": "5.1.2",
 | 
				
			||||||
 | 
					                    "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
 | 
				
			||||||
 | 
					                    "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "brace-expansion": {
 | 
				
			||||||
 | 
					            "version": "1.1.11",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
 | 
				
			||||||
 | 
					            "requires": {
 | 
				
			||||||
 | 
					                "balanced-match": "^1.0.0",
 | 
				
			||||||
 | 
					                "concat-map": "0.0.1"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "concat-map": {
 | 
				
			||||||
 | 
					            "version": "0.0.1",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "content-disposition": {
 | 
				
			||||||
 | 
					            "version": "0.5.4",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
 | 
				
			||||||
 | 
					            "requires": {
 | 
				
			||||||
 | 
					                "safe-buffer": "5.2.1"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "cookie": {
 | 
				
			||||||
 | 
					            "version": "0.4.1",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "debug": {
 | 
				
			||||||
 | 
					            "version": "4.3.3",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
 | 
				
			||||||
 | 
					            "requires": {
 | 
				
			||||||
 | 
					                "ms": "2.1.2"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "deepmerge": {
 | 
				
			||||||
 | 
					            "version": "4.2.2",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "depd": {
 | 
				
			||||||
 | 
					            "version": "1.1.2",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "destroy": {
 | 
				
			||||||
 | 
					            "version": "1.0.4",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "dotenv": {
 | 
				
			||||||
 | 
					            "version": "10.0.0",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "ee-first": {
 | 
				
			||||||
 | 
					            "version": "1.1.1",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "encodeurl": {
 | 
				
			||||||
 | 
					            "version": "1.0.2",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "encoding-negotiator": {
 | 
				
			||||||
 | 
					            "version": "2.0.1",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/encoding-negotiator/-/encoding-negotiator-2.0.1.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-GSK7qphNR4iPcejfAlZxKDoz3xMhnspwImK+Af5WhePS9jUpK/Oh7rUdyENWu+9rgDflOCTmAojBsgsvM8neAQ=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "escape-html": {
 | 
				
			||||||
 | 
					            "version": "1.0.3",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "etag": {
 | 
				
			||||||
 | 
					            "version": "1.8.1",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "fast-decode-uri-component": {
 | 
				
			||||||
 | 
					            "version": "1.0.1",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "fast-deep-equal": {
 | 
				
			||||||
 | 
					            "version": "3.1.3",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "fast-json-stable-stringify": {
 | 
				
			||||||
 | 
					            "version": "2.1.0",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "fast-json-stringify": {
 | 
				
			||||||
 | 
					            "version": "2.7.13",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-2.7.13.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-ar+hQ4+OIurUGjSJD1anvYSDcUflywhKjfxnsW4TBTD7+u0tJufv6DKRWoQk3vI6YBOWMoz0TQtfbe7dxbQmvA==",
 | 
				
			||||||
 | 
					            "requires": {
 | 
				
			||||||
 | 
					                "ajv": "^6.11.0",
 | 
				
			||||||
 | 
					                "deepmerge": "^4.2.2",
 | 
				
			||||||
 | 
					                "rfdc": "^1.2.0",
 | 
				
			||||||
 | 
					                "string-similarity": "^4.0.1"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "fast-redact": {
 | 
				
			||||||
 | 
					            "version": "3.1.0",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.1.0.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-dir8LOnvialLxiXDPESMDHGp82CHi6ZEYTVkcvdn5d7psdv9ZkkButXrOeXST4aqreIRR+N7CYlsrwFuorurVg=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "fast-safe-stringify": {
 | 
				
			||||||
 | 
					            "version": "2.1.1",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "fastify": {
 | 
				
			||||||
 | 
					            "version": "3.27.0",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/fastify/-/fastify-3.27.0.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-p99Fd7xt4DFew39U5Wnp/Soy7jkpxpaqToekwQ3XWv+ECUPXd6bSF9l79EiwkutWALtEU/JiRlzS9qjP2gLHFg==",
 | 
				
			||||||
 | 
					            "requires": {
 | 
				
			||||||
 | 
					                "@fastify/ajv-compiler": "^1.0.0",
 | 
				
			||||||
 | 
					                "abstract-logging": "^2.0.0",
 | 
				
			||||||
 | 
					                "avvio": "^7.1.2",
 | 
				
			||||||
 | 
					                "fast-json-stringify": "^2.5.2",
 | 
				
			||||||
 | 
					                "fastify-error": "^0.3.0",
 | 
				
			||||||
 | 
					                "find-my-way": "^4.5.0",
 | 
				
			||||||
 | 
					                "flatstr": "^1.0.12",
 | 
				
			||||||
 | 
					                "light-my-request": "^4.2.0",
 | 
				
			||||||
 | 
					                "pino": "^6.13.0",
 | 
				
			||||||
 | 
					                "process-warning": "^1.0.0",
 | 
				
			||||||
 | 
					                "proxy-addr": "^2.0.7",
 | 
				
			||||||
 | 
					                "rfdc": "^1.1.4",
 | 
				
			||||||
 | 
					                "secure-json-parse": "^2.0.0",
 | 
				
			||||||
 | 
					                "semver": "^7.3.2",
 | 
				
			||||||
 | 
					                "tiny-lru": "^7.0.0"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "fastify-auth": {
 | 
				
			||||||
 | 
					            "version": "1.1.0",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/fastify-auth/-/fastify-auth-1.1.0.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-8IajmAZB3QJ3wTP0q8Z3TG9DkxrIcAlS85TdPCBEfJi3mMKQd/sCYxtZ0dYv11v5hZaJ9z8XmNzhK3AH6/JpNw==",
 | 
				
			||||||
 | 
					            "requires": {
 | 
				
			||||||
 | 
					                "fastify-plugin": "^3.0.0",
 | 
				
			||||||
 | 
					                "reusify": "^1.0.4"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "fastify-basic-auth": {
 | 
				
			||||||
 | 
					            "version": "2.2.0",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/fastify-basic-auth/-/fastify-basic-auth-2.2.0.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-xXeNhyhONlQNoWIzy9rhms0td6PFL1KCRqu0lkEpd54Ju4dHLbB/woPwtK0Vutuqy0sDav77If6UtdfDajx44Q==",
 | 
				
			||||||
 | 
					            "requires": {
 | 
				
			||||||
 | 
					                "basic-auth": "^2.0.1",
 | 
				
			||||||
 | 
					                "fastify-plugin": "^3.0.0",
 | 
				
			||||||
 | 
					                "http-errors": "^1.7.3"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "fastify-error": {
 | 
				
			||||||
 | 
					            "version": "0.3.1",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/fastify-error/-/fastify-error-0.3.1.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-oCfpcsDndgnDVgiI7bwFKAun2dO+4h84vBlkWsWnz/OUK9Reff5UFoFl241xTiLeHWX/vU9zkDVXqYUxjOwHcQ=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "fastify-formbody": {
 | 
				
			||||||
 | 
					            "version": "5.2.0",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/fastify-formbody/-/fastify-formbody-5.2.0.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-d8Y5hCL82akPyoFiXh2wYOm3es0pV9jqoPo3pO9OV2cNF0cQx39J5WAVXzCh4MSt9Z2qF4Fy5gHlvlyESwjtvg==",
 | 
				
			||||||
 | 
					            "requires": {
 | 
				
			||||||
 | 
					                "fastify-plugin": "^3.0.0"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "fastify-plugin": {
 | 
				
			||||||
 | 
					            "version": "3.0.0",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-3.0.0.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-ZdCvKEEd92DNLps5n0v231Bha8bkz1DjnPP/aEz37rz/q42Z5JVLmgnqR4DYuNn3NXAO3IDCPyRvgvxtJ4Ym4w=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "fastify-static": {
 | 
				
			||||||
 | 
					            "version": "4.5.0",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/fastify-static/-/fastify-static-4.5.0.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-Q7Tgl55AjsmBwiO4hKYib2BUCt+XTWLJ6Xp8YPPHU3EsrKNpevJ4cz8pjf1Ey1QhHw9O8Y2FDKdu+IC74oHvqw==",
 | 
				
			||||||
 | 
					            "requires": {
 | 
				
			||||||
 | 
					                "content-disposition": "^0.5.3",
 | 
				
			||||||
 | 
					                "encoding-negotiator": "^2.0.1",
 | 
				
			||||||
 | 
					                "fastify-plugin": "^3.0.0",
 | 
				
			||||||
 | 
					                "glob": "^7.1.4",
 | 
				
			||||||
 | 
					                "p-limit": "^3.1.0",
 | 
				
			||||||
 | 
					                "readable-stream": "^3.4.0",
 | 
				
			||||||
 | 
					                "send": "^0.17.1"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "fastify-warning": {
 | 
				
			||||||
 | 
					            "version": "0.2.0",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/fastify-warning/-/fastify-warning-0.2.0.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-s1EQguBw/9qtc1p/WTY4eq9WMRIACkj+HTcOIK1in4MV5aFaQC9ZCIt0dJ7pr5bIf4lPpHvAtP2ywpTNgs7hqw=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "fastq": {
 | 
				
			||||||
 | 
					            "version": "1.13.0",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==",
 | 
				
			||||||
 | 
					            "requires": {
 | 
				
			||||||
 | 
					                "reusify": "^1.0.4"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "find-my-way": {
 | 
				
			||||||
 | 
					            "version": "4.5.1",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-4.5.1.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-kE0u7sGoUFbMXcOG/xpkmz4sRLCklERnBcg7Ftuu1iAxsfEt2S46RLJ3Sq7vshsEy2wJT2hZxE58XZK27qa8kg==",
 | 
				
			||||||
 | 
					            "requires": {
 | 
				
			||||||
 | 
					                "fast-decode-uri-component": "^1.0.1",
 | 
				
			||||||
 | 
					                "fast-deep-equal": "^3.1.3",
 | 
				
			||||||
 | 
					                "safe-regex2": "^2.0.0",
 | 
				
			||||||
 | 
					                "semver-store": "^0.3.0"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "flatstr": {
 | 
				
			||||||
 | 
					            "version": "1.0.12",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/flatstr/-/flatstr-1.0.12.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "forwarded": {
 | 
				
			||||||
 | 
					            "version": "0.2.0",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "fresh": {
 | 
				
			||||||
 | 
					            "version": "0.5.2",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "fs.realpath": {
 | 
				
			||||||
 | 
					            "version": "1.0.0",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "glob": {
 | 
				
			||||||
 | 
					            "version": "7.2.0",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
 | 
				
			||||||
 | 
					            "requires": {
 | 
				
			||||||
 | 
					                "fs.realpath": "^1.0.0",
 | 
				
			||||||
 | 
					                "inflight": "^1.0.4",
 | 
				
			||||||
 | 
					                "inherits": "2",
 | 
				
			||||||
 | 
					                "minimatch": "^3.0.4",
 | 
				
			||||||
 | 
					                "once": "^1.3.0",
 | 
				
			||||||
 | 
					                "path-is-absolute": "^1.0.0"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "hashlru": {
 | 
				
			||||||
 | 
					            "version": "2.3.0",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/hashlru/-/hashlru-2.3.0.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-0cMsjjIC8I+D3M44pOQdsy0OHXGLVz6Z0beRuufhKa0KfaD2wGwAev6jILzXsd3/vpnNQJmWyZtIILqM1N+n5A=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "http-errors": {
 | 
				
			||||||
 | 
					            "version": "1.8.1",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==",
 | 
				
			||||||
 | 
					            "requires": {
 | 
				
			||||||
 | 
					                "depd": "~1.1.2",
 | 
				
			||||||
 | 
					                "inherits": "2.0.4",
 | 
				
			||||||
 | 
					                "setprototypeof": "1.2.0",
 | 
				
			||||||
 | 
					                "statuses": ">= 1.5.0 < 2",
 | 
				
			||||||
 | 
					                "toidentifier": "1.0.1"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "inflight": {
 | 
				
			||||||
 | 
					            "version": "1.0.6",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
 | 
				
			||||||
 | 
					            "requires": {
 | 
				
			||||||
 | 
					                "once": "^1.3.0",
 | 
				
			||||||
 | 
					                "wrappy": "1"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "inherits": {
 | 
				
			||||||
 | 
					            "version": "2.0.4",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "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=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "json-schema-traverse": {
 | 
				
			||||||
 | 
					            "version": "0.4.1",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "light-my-request": {
 | 
				
			||||||
 | 
					            "version": "4.7.0",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-4.7.0.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-LTa8YZp3K2AUpqUnwwKajoIHcsKOBnzwJNQSrk7unziPwo6CjOYjyO0F9wfkxFvP+nBsCGe3eMPnedVgIIgdAw==",
 | 
				
			||||||
 | 
					            "requires": {
 | 
				
			||||||
 | 
					                "ajv": "^8.1.0",
 | 
				
			||||||
 | 
					                "cookie": "^0.4.0",
 | 
				
			||||||
 | 
					                "fastify-warning": "^0.2.0",
 | 
				
			||||||
 | 
					                "set-cookie-parser": "^2.4.1"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "dependencies": {
 | 
				
			||||||
 | 
					                "ajv": {
 | 
				
			||||||
 | 
					                    "version": "8.9.0",
 | 
				
			||||||
 | 
					                    "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.9.0.tgz",
 | 
				
			||||||
 | 
					                    "integrity": "sha512-qOKJyNj/h+OWx7s5DePL6Zu1KeM9jPZhwBqs+7DzP6bGOvqzVCSf0xueYmVuaC/oQ/VtS2zLMLHdQFbkka+XDQ==",
 | 
				
			||||||
 | 
					                    "requires": {
 | 
				
			||||||
 | 
					                        "fast-deep-equal": "^3.1.1",
 | 
				
			||||||
 | 
					                        "json-schema-traverse": "^1.0.0",
 | 
				
			||||||
 | 
					                        "require-from-string": "^2.0.2",
 | 
				
			||||||
 | 
					                        "uri-js": "^4.2.2"
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                "json-schema-traverse": {
 | 
				
			||||||
 | 
					                    "version": "1.0.0",
 | 
				
			||||||
 | 
					                    "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
 | 
				
			||||||
 | 
					                    "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "liquidjs": {
 | 
				
			||||||
 | 
					            "version": "9.33.1",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/liquidjs/-/liquidjs-9.33.1.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-qIMSXkUMFG5VZmBp1qxcOEFeGzmA2A8Fy818rMTAWKyy2ftUwOEoVtvXFdqm3iSeQEoj8pzTOmC6KQOP0SipUA=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "lru-cache": {
 | 
				
			||||||
 | 
					            "version": "6.0.0",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
 | 
				
			||||||
 | 
					            "requires": {
 | 
				
			||||||
 | 
					                "yallist": "^4.0.0"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "mime": {
 | 
				
			||||||
 | 
					            "version": "1.6.0",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "minimatch": {
 | 
				
			||||||
 | 
					            "version": "3.0.4",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
 | 
				
			||||||
 | 
					            "requires": {
 | 
				
			||||||
 | 
					                "brace-expansion": "^1.1.7"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "ms": {
 | 
				
			||||||
 | 
					            "version": "2.1.2",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "on-finished": {
 | 
				
			||||||
 | 
					            "version": "2.3.0",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
 | 
				
			||||||
 | 
					            "requires": {
 | 
				
			||||||
 | 
					                "ee-first": "1.1.1"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "once": {
 | 
				
			||||||
 | 
					            "version": "1.4.0",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
 | 
				
			||||||
 | 
					            "requires": {
 | 
				
			||||||
 | 
					                "wrappy": "1"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "p-limit": {
 | 
				
			||||||
 | 
					            "version": "3.1.0",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
 | 
				
			||||||
 | 
					            "requires": {
 | 
				
			||||||
 | 
					                "yocto-queue": "^0.1.0"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "path-is-absolute": {
 | 
				
			||||||
 | 
					            "version": "1.0.1",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "pino": {
 | 
				
			||||||
 | 
					            "version": "6.13.4",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/pino/-/pino-6.13.4.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-g4tHSISmQJYUEKEMVdaZ+ZokWwFnTwZL5JPn+lnBVZ1BuBbrSchrXwQINknkM5+Q4fF6U9NjiI8PWwwMDHt9zA==",
 | 
				
			||||||
 | 
					            "requires": {
 | 
				
			||||||
 | 
					                "fast-redact": "^3.0.0",
 | 
				
			||||||
 | 
					                "fast-safe-stringify": "^2.0.8",
 | 
				
			||||||
 | 
					                "flatstr": "^1.0.12",
 | 
				
			||||||
 | 
					                "pino-std-serializers": "^3.1.0",
 | 
				
			||||||
 | 
					                "process-warning": "^1.0.0",
 | 
				
			||||||
 | 
					                "quick-format-unescaped": "^4.0.3",
 | 
				
			||||||
 | 
					                "sonic-boom": "^1.0.2"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "pino-std-serializers": {
 | 
				
			||||||
 | 
					            "version": "3.2.0",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-3.2.0.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-EqX4pwDPrt3MuOAAUBMU0Tk5kR/YcCM5fNPEzgCO2zJ5HfX0vbiH9HbJglnyeQsN96Kznae6MWD47pZB5avTrg=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "point-of-view": {
 | 
				
			||||||
 | 
					            "version": "5.0.0",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/point-of-view/-/point-of-view-5.0.0.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-JY12G3+jVFYccKTexe2OHG9WHrEUb3eLKPtLM/YEnaJf2i2OuzIun/v6SBzjHFm5sOuNXyKKo47HIe/YkGtEMA==",
 | 
				
			||||||
 | 
					            "requires": {
 | 
				
			||||||
 | 
					                "fastify-plugin": "^3.0.0",
 | 
				
			||||||
 | 
					                "hashlru": "^2.3.0"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "process-warning": {
 | 
				
			||||||
 | 
					            "version": "1.0.0",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-1.0.0.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "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==",
 | 
				
			||||||
 | 
					            "requires": {
 | 
				
			||||||
 | 
					                "forwarded": "0.2.0",
 | 
				
			||||||
 | 
					                "ipaddr.js": "1.9.1"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "punycode": {
 | 
				
			||||||
 | 
					            "version": "2.1.1",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "queue-microtask": {
 | 
				
			||||||
 | 
					            "version": "1.2.3",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "quick-format-unescaped": {
 | 
				
			||||||
 | 
					            "version": "4.0.4",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "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=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "readable-stream": {
 | 
				
			||||||
 | 
					            "version": "3.6.0",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
 | 
				
			||||||
 | 
					            "requires": {
 | 
				
			||||||
 | 
					                "inherits": "^2.0.3",
 | 
				
			||||||
 | 
					                "string_decoder": "^1.1.1",
 | 
				
			||||||
 | 
					                "util-deprecate": "^1.0.1"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "require-from-string": {
 | 
				
			||||||
 | 
					            "version": "2.0.2",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "ret": {
 | 
				
			||||||
 | 
					            "version": "0.2.2",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/ret/-/ret-0.2.2.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "reusify": {
 | 
				
			||||||
 | 
					            "version": "1.0.4",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "rfdc": {
 | 
				
			||||||
 | 
					            "version": "1.3.0",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "safe-buffer": {
 | 
				
			||||||
 | 
					            "version": "5.2.1",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "safe-regex2": {
 | 
				
			||||||
 | 
					            "version": "2.0.0",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/safe-regex2/-/safe-regex2-2.0.0.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-PaUSFsUaNNuKwkBijoAPHAK6/eM6VirvyPWlZ7BAQy4D+hCvh4B6lIG+nPdhbFfIbP+gTGBcrdsOaUs0F+ZBOQ==",
 | 
				
			||||||
 | 
					            "requires": {
 | 
				
			||||||
 | 
					                "ret": "~0.2.0"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "secure-json-parse": {
 | 
				
			||||||
 | 
					            "version": "2.4.0",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.4.0.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-Q5Z/97nbON5t/L/sH6mY2EacfjVGwrCcSi5D3btRO2GZ8pf1K1UN7Z9H5J57hjVU2Qzxr1xO+FmBhOvEkzCMmg=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "semver": {
 | 
				
			||||||
 | 
					            "version": "7.3.5",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
 | 
				
			||||||
 | 
					            "requires": {
 | 
				
			||||||
 | 
					                "lru-cache": "^6.0.0"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "semver-store": {
 | 
				
			||||||
 | 
					            "version": "0.3.0",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/semver-store/-/semver-store-0.3.0.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-TcZvGMMy9vodEFSse30lWinkj+JgOBvPn8wRItpQRSayhc+4ssDs335uklkfvQQJgL/WvmHLVj4Ycv2s7QCQMg=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "send": {
 | 
				
			||||||
 | 
					            "version": "0.17.2",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==",
 | 
				
			||||||
 | 
					            "requires": {
 | 
				
			||||||
 | 
					                "debug": "2.6.9",
 | 
				
			||||||
 | 
					                "depd": "~1.1.2",
 | 
				
			||||||
 | 
					                "destroy": "~1.0.4",
 | 
				
			||||||
 | 
					                "encodeurl": "~1.0.2",
 | 
				
			||||||
 | 
					                "escape-html": "~1.0.3",
 | 
				
			||||||
 | 
					                "etag": "~1.8.1",
 | 
				
			||||||
 | 
					                "fresh": "0.5.2",
 | 
				
			||||||
 | 
					                "http-errors": "1.8.1",
 | 
				
			||||||
 | 
					                "mime": "1.6.0",
 | 
				
			||||||
 | 
					                "ms": "2.1.3",
 | 
				
			||||||
 | 
					                "on-finished": "~2.3.0",
 | 
				
			||||||
 | 
					                "range-parser": "~1.2.1",
 | 
				
			||||||
 | 
					                "statuses": "~1.5.0"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "dependencies": {
 | 
				
			||||||
 | 
					                "debug": {
 | 
				
			||||||
 | 
					                    "version": "2.6.9",
 | 
				
			||||||
 | 
					                    "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
 | 
				
			||||||
 | 
					                    "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
 | 
				
			||||||
 | 
					                    "requires": {
 | 
				
			||||||
 | 
					                        "ms": "2.0.0"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "dependencies": {
 | 
				
			||||||
 | 
					                        "ms": {
 | 
				
			||||||
 | 
					                            "version": "2.0.0",
 | 
				
			||||||
 | 
					                            "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
 | 
				
			||||||
 | 
					                            "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                "ms": {
 | 
				
			||||||
 | 
					                    "version": "2.1.3",
 | 
				
			||||||
 | 
					                    "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
 | 
				
			||||||
 | 
					                    "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "set-cookie-parser": {
 | 
				
			||||||
 | 
					            "version": "2.4.8",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.4.8.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-edRH8mBKEWNVIVMKejNnuJxleqYE/ZSdcT8/Nem9/mmosx12pctd80s2Oy00KNZzrogMZS5mauK2/ymL1bvlvg=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "setprototypeof": {
 | 
				
			||||||
 | 
					            "version": "1.2.0",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "sonic-boom": {
 | 
				
			||||||
 | 
					            "version": "1.4.1",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-1.4.1.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-LRHh/A8tpW7ru89lrlkU4AszXt1dbwSjVWguGrmlxE7tawVmDBlI1PILMkXAxJTwqhgsEeTHzj36D5CmHgQmNg==",
 | 
				
			||||||
 | 
					            "requires": {
 | 
				
			||||||
 | 
					                "atomic-sleep": "^1.0.0",
 | 
				
			||||||
 | 
					                "flatstr": "^1.0.12"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "statuses": {
 | 
				
			||||||
 | 
					            "version": "1.5.0",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "string-similarity": {
 | 
				
			||||||
 | 
					            "version": "4.0.4",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/string-similarity/-/string-similarity-4.0.4.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-/q/8Q4Bl4ZKAPjj8WerIBJWALKkaPRfrvhfF8k/B23i4nzrlRj2/go1m90In7nG/3XDSbOo0+pu6RvCTM9RGMQ=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "string_decoder": {
 | 
				
			||||||
 | 
					            "version": "1.3.0",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
 | 
				
			||||||
 | 
					            "requires": {
 | 
				
			||||||
 | 
					                "safe-buffer": "~5.2.0"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "tiny-lru": {
 | 
				
			||||||
 | 
					            "version": "7.0.6",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/tiny-lru/-/tiny-lru-7.0.6.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-zNYO0Kvgn5rXzWpL0y3RS09sMK67eGaQj9805jlK9G6pSadfriTczzLHFXa/xcW4mIRfmlB9HyQ/+SgL0V1uow=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "toidentifier": {
 | 
				
			||||||
 | 
					            "version": "1.0.1",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "uri-js": {
 | 
				
			||||||
 | 
					            "version": "4.4.1",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
 | 
				
			||||||
 | 
					            "requires": {
 | 
				
			||||||
 | 
					                "punycode": "^2.1.0"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "util-deprecate": {
 | 
				
			||||||
 | 
					            "version": "1.0.2",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "wrappy": {
 | 
				
			||||||
 | 
					            "version": "1.0.2",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "yallist": {
 | 
				
			||||||
 | 
					            "version": "4.0.0",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "yocto-queue": {
 | 
				
			||||||
 | 
					            "version": "0.1.0",
 | 
				
			||||||
 | 
					            "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
 | 
				
			||||||
 | 
					            "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    "name": "server",
 | 
				
			||||||
 | 
					    "version": "0.1.0",
 | 
				
			||||||
 | 
					    "scripts": {
 | 
				
			||||||
 | 
					        "start": "node index.js"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "type": "module",
 | 
				
			||||||
 | 
					    "dependencies": {
 | 
				
			||||||
 | 
					        "dotenv": "^10.0.0",
 | 
				
			||||||
 | 
					        "fastify": "^3.27.0",
 | 
				
			||||||
 | 
					        "fastify-auth": "^1.1.0",
 | 
				
			||||||
 | 
					        "fastify-basic-auth": "^2.2.0",
 | 
				
			||||||
 | 
					        "fastify-formbody": "^5.2.0",
 | 
				
			||||||
 | 
					        "fastify-static": "^4.5.0",
 | 
				
			||||||
 | 
					        "liquidjs": "^9.33.1",
 | 
				
			||||||
 | 
					        "point-of-view": "^5.0.0",
 | 
				
			||||||
 | 
					        "pouchdb": "^7.2.2",
 | 
				
			||||||
 | 
					        "pouchdb-find": "^7.2.2"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					import { Liquid } from 'liquidjs'
 | 
				
			||||||
 | 
					import pov from 'point-of-view'
 | 
				
			||||||
 | 
					import path from 'path'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 *  plugin: usindg render engine liquidjs
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function plugin(fastify, options, next) {
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const engine = new Liquid({
 | 
				
			||||||
 | 
					        root: path.join(path.resolve(), '/views'),
 | 
				
			||||||
 | 
					        extname: '.liquid',
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fastify.register(pov, {
 | 
				
			||||||
 | 
					        engine: {
 | 
				
			||||||
 | 
					            liquid: engine
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = plugin
 | 
				
			||||||
@ -0,0 +1,212 @@
 | 
				
			|||||||
 | 
					import fastifySession from '@fastify/session'
 | 
				
			||||||
 | 
					import fastifyCookie from 'fastify-cookie'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import PouchDB from 'pouchdb'
 | 
				
			||||||
 | 
					import PouchDBfind from 'pouchdb-find'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 *  pouchdb storage
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  @extends Store
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class PouchdbStore extends Store
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  @param {Object}
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    constructor()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        super()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        PouchDB.plugin(PouchDBfind)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // create db if not already exists
 | 
				
			||||||
 | 
					        this.db = new PouchDB('./../../storage/session', {
 | 
				
			||||||
 | 
					            revs_limit: 0
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  @param {[type]}   sessionId  [description]
 | 
				
			||||||
 | 
					     *  @param {Function} callback   [description]
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async set(sessionId, session, callback)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const result = await this.db.find({
 | 
				
			||||||
 | 
					            'selector': {
 | 
				
			||||||
 | 
					                '_id': sessionId
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (result.docs.length === 0) {
 | 
				
			||||||
 | 
					            session._id = sessionId
 | 
				
			||||||
 | 
					            await this.db.post(session)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        callback()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  @param  {[type]}   sessionId               [description]
 | 
				
			||||||
 | 
					     *  @param  {Function} callback                [description]
 | 
				
			||||||
 | 
					     *  @return {[type]}             [description]
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async get(sessionId, callback)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const result = await this.db.find({
 | 
				
			||||||
 | 
					            'selector': {
 | 
				
			||||||
 | 
					                '_id': sessionId
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let session = null
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (result.docs.length > 0) {
 | 
				
			||||||
 | 
					            session = result.docs[0]
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        callback(null, session)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  @param  {[type]}   sessionId               [description]
 | 
				
			||||||
 | 
					     *  @param  {Function} callback                [description]
 | 
				
			||||||
 | 
					     *  @return {[type]}             [description]
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async destroy(sessionId, callback)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const result = await this.db.find({
 | 
				
			||||||
 | 
					            'selector': {
 | 
				
			||||||
 | 
					                '_id': sessionId
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (result.docs.length > 0) {
 | 
				
			||||||
 | 
					            await this.db.remove(result.docs[0])
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        callback()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 const loginSchema = {
 | 
				
			||||||
 | 
					     schema: {
 | 
				
			||||||
 | 
					         body: {
 | 
				
			||||||
 | 
					             username: { type: 'string' },
 | 
				
			||||||
 | 
					             password: { type: 'string' }
 | 
				
			||||||
 | 
					         },
 | 
				
			||||||
 | 
					         response: {
 | 
				
			||||||
 | 
					             200: {
 | 
				
			||||||
 | 
					                 type: 'object',
 | 
				
			||||||
 | 
					                 properties: {
 | 
				
			||||||
 | 
					                     token: { type: 'string' }
 | 
				
			||||||
 | 
					                 }
 | 
				
			||||||
 | 
					             }
 | 
				
			||||||
 | 
					         }
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 *  create Plugin
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function plugin(fastify, options, next) {
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // create cookie
 | 
				
			||||||
 | 
					    fastify
 | 
				
			||||||
 | 
					        .register(fastifyCookie)
 | 
				
			||||||
 | 
					        .register(fastifySession, {
 | 
				
			||||||
 | 
					            secret: options.secret,
 | 
				
			||||||
 | 
					            cookieName: 'session',
 | 
				
			||||||
 | 
					            cookie: {
 | 
				
			||||||
 | 
					                path: '/',
 | 
				
			||||||
 | 
					                maxAge: options.secret,
 | 
				
			||||||
 | 
					                secure: true,
 | 
				
			||||||
 | 
					                httpOnly: true,
 | 
				
			||||||
 | 
					                sameSite: 'Strict'
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            store: new PouchdbStore()
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     *  route: logout user and destroy session
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    fastify.get('/logout', async function(request, response)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        request.destroySession(() => {
 | 
				
			||||||
 | 
					            response.redirect('/')
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     *  route: auth
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  @param  {object} request
 | 
				
			||||||
 | 
					     *  @param  {object} response
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    fastify.post('/auth', loginSchema, async function (request, reply)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        let { username, password } = request.body
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // strip crap from strings
 | 
				
			||||||
 | 
					        username = DOMPurify.sanitize(username)
 | 
				
			||||||
 | 
					        password = DOMPurify.sanitize(password)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const userRepository = new UserRepository()
 | 
				
			||||||
 | 
					        const user = await userRepository.findOneByUsername(username)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // add header for json
 | 
				
			||||||
 | 
					        reply.header('Content-Type', 'application/json; charset=utf-8')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // user not found
 | 
				
			||||||
 | 
					        if (!user) {
 | 
				
			||||||
 | 
					            return reply
 | 
				
			||||||
 | 
					                .code(404)
 | 
				
			||||||
 | 
					                .send()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // password wrong
 | 
				
			||||||
 | 
					        if (!bcrypt.compareSync(password, user.password)) {
 | 
				
			||||||
 | 
					            return reply
 | 
				
			||||||
 | 
					                .code(401)
 | 
				
			||||||
 | 
					                .send()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // setting session to store and set cookie
 | 
				
			||||||
 | 
					        request.sessionStore.set(request.session.sessionId, request.session, async function() {
 | 
				
			||||||
 | 
					            user.sessionId = request.session.sessionId
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            await userRepository.update(user)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // send 200 and send set-token
 | 
				
			||||||
 | 
					            reply
 | 
				
			||||||
 | 
					                .code(200)
 | 
				
			||||||
 | 
					                .send()
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    done()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = plugin
 | 
				
			||||||
					Loading…
					
					
				
		Reference in new issue