Chapter 4,6: prettier updates and web framework samples

This commit is contained in:
Beth Griggs
2020-05-31 19:31:42 +01:00
parent b43bf2c378
commit 0d8170c265
43 changed files with 4820 additions and 242 deletions
+3 -3
View File
@@ -1,5 +1,5 @@
<form method="POST" enctype="multipart/form-data"> <form method="POST" enctype="multipart/form-data">
<label for="userfile">File:</label> <label for="userfile">File:</label>
<input type="file" id="userfile" name="userfile"><br> <input type="file" id="userfile" name="userfile" /><br />
<input type="submit"> <input type="submit" />
</form> </form>
+43 -40
View File
@@ -1,55 +1,58 @@
const fs = require('fs') const fs = require("fs");
const http = require('http') const http = require("http");
const path = require('path') const path = require("path");
const form = fs.readFileSync(path.join(__dirname, 'public', 'form.html')) const form = fs.readFileSync(path.join(__dirname, "public", "form.html"));
const formidable = require('formidable') const formidable = require("formidable");
http
http.createServer((req, res) => { .createServer((req, res) => {
if (req.method === 'GET') { if (req.method === "GET") {
get(res) get(res);
return return;
} }
if (req.method === 'POST') { if (req.method === "POST") {
post(req, res) post(req, res);
return return;
} }
error(405, res) error(405, res);
}).listen(3000) })
.listen(3000);
function get(res) { function get(res) {
res.writeHead(200, { res.writeHead(200, {
'Content-Type': 'text/html' "Content-Type": "text/html",
}) });
res.end(form) res.end(form);
} }
function post(req, res) { function post(req, res) {
if (!/multipart\/form-data/.test(req.headers['content-type'])) { if (!/multipart\/form-data/.test(req.headers["content-type"])) {
error(415, res) error(415, res);
return return;
} }
const form = formidable({ const form = formidable({
multiples: true, multiples: true,
uploadDir: './uploads' uploadDir: "./uploads",
});
form.parse(req, (err, fields, files) => {
if (err) return err;
res.writeHead(200, {
"Content-Type": "application/json",
}); });
res.end(
form.parse(req, (err, fields, files) => { JSON.stringify({
if (err) return err fields,
res.writeHead(200, { files,
'Content-Type': 'application/json' })
}); );
res.end(JSON.stringify({ });
fields,
files
}))
})
} }
function error(code, res) { function error(code, res) {
res.statusCode = code res.statusCode = code;
res.end(http.STATUS_CODES[code]) res.end(http.STATUS_CODES[code]);
} }
+13 -13
View File
@@ -1,28 +1,28 @@
const http = require('http') const http = require("http");
const HOSTNAME = process.env.HOSTNAME || '0.0.0.0' const HOSTNAME = process.env.HOSTNAME || "0.0.0.0";
const PORT = process.env.PORT || 8080 const PORT = process.env.PORT || 8080;
const server = http.createServer((req, res) => { const server = http.createServer((req, res) => {
if (req.method !== 'GET') return error(res, 405) if (req.method !== "GET") return error(res, 405);
if (req.url === '/todo') return todo(res) if (req.url === "/todo") return todo(res);
if (req.url === '/') return index(res) if (req.url === "/") return index(res);
error(res, 404) error(res, 404);
}); });
function error(res, code) { function error(res, code) {
res.statusCode = code res.statusCode = code;
res.end(`{"error": "${http.STATUS_CODES[code]}"}`) res.end(`{"error": "${http.STATUS_CODES[code]}"}`);
} }
function todo(res) { function todo(res) {
res.end('[{"task_id": 1, "description": "walk dog"}]}') res.end('[{"task_id": 1, "description": "walk dog"}]}');
} }
function index(res) { function index(res) {
res.end('{"name": "todo-server"}') res.end('{"name": "todo-server"}');
} }
server.listen(PORT, HOSTNAME, () => { server.listen(PORT, HOSTNAME, () => {
console.log('Server listening on', server.address()) console.log("Server listening on", server.address());
}) });
+16 -16
View File
@@ -1,28 +1,28 @@
const https = require('https') const https = require("https");
// http.get('http://example.com', (res) => res.pipe(process.stdout)) // http.get('http://example.com', (res) => res.pipe(process.stdout))
const payload = `{ const payload = `{
"name": "Beth", "name": "Beth",
"job": "Software Engineer" "job": "Software Engineer"
}` }`;
const opts = { const opts = {
method: 'POST', method: "POST",
hostname: 'postman-echo.com', hostname: "postman-echo.com",
path: '/post', path: "/post",
headers: { headers: {
'Content-Type': 'application/json', "Content-Type": "application/json",
'Content-Length': Buffer.byteLength(payload) "Content-Length": Buffer.byteLength(payload),
} },
} };
const req = https.request(opts, (res) => { const req = https.request(opts, (res) => {
process.stdout.write('Status Code: ' + res.statusCode + '\n') process.stdout.write("Status Code: " + res.statusCode + "\n");
process.stdout.write('Body: ') process.stdout.write("Body: ");
res.pipe(process.stdout) res.pipe(process.stdout);
}) });
req.on('error', (err) => console.error('Error: ', err)) req.on("error", (err) => console.error("Error: ", err));
req.end(payload) req.end(payload);
+42 -41
View File
@@ -1,56 +1,57 @@
const http = require('http') const http = require("http");
const fs = require('fs') const fs = require("fs");
const path = require('path') const path = require("path");
const form = fs.readFileSync(path.join(__dirname, 'public', 'form.html')) const form = fs.readFileSync(path.join(__dirname, "public", "form.html"));
http.createServer((req, res) => { http
if (req.method === 'GET') { .createServer((req, res) => {
get(res) if (req.method === "GET") {
return get(res);
return;
} }
if (req.method === 'POST') { if (req.method === "POST") {
post(req, res) post(req, res);
return return;
} }
error(405, res) error(405, res);
}).listen(3000) })
.listen(3000);
function get(res) { function get(res) {
res.writeHead(200, { res.writeHead(200, {
'Content-Type': 'text/html' "Content-Type": "text/html",
}) });
res.end(form) res.end(form);
} }
function post(req, res) { function post(req, res) {
if (req.headers['content-type'] !== 'application/json') { if (req.headers["content-type"] !== "application/json") {
error(415, res) error(415, res);
return return;
}
let input = "";
req.on("data", (chunk) => {
input += chunk.toString();
});
req.on("end", () => {
const parsed = JSON.parse(input);
if (parsed.err) {
error(400, "Bad Request", res);
return;
} }
let input = ''; console.log("Received data: ", parsed);
res.end('{"data": ' + input + "}");
req.on('data', chunk => { });
input += chunk.toString()
})
req.on('end', () => {
const parsed = JSON.parse(input)
if (parsed.err) {
error(400, 'Bad Request', res)
return
}
console.log('Received data: ', parsed)
res.end('{"data": ' + input + "}")
})
} }
function error(code, res) { function error(code, res) {
res.statusCode = code res.statusCode = code;
res.end(http.STATUS_CODES[code]) res.end(http.STATUS_CODES[code]);
} }
+23 -23
View File
@@ -1,30 +1,30 @@
<form method="POST"> <form method="POST">
<label for="forename">Forename:</label> <label for="forename">Forename:</label>
<input id="forename" name="forename"> <input id="forename" name="forename" />
<label for="surname">Surname:</label> <label for="surname">Surname:</label>
<input id="surname" name="surname"> <input id="surname" name="surname" />
<input type="submit" value="Submit"> <input type="submit" value="Submit" />
</form> </form>
<script> <script>
document.forms[0].addEventListener('submit', (event) => { document.forms[0].addEventListener("submit", (event) => {
event.preventDefault() event.preventDefault();
let data = { let data = {
'forename': document.getElementById('forename').value, forename: document.getElementById("forename").value,
'surname': document.getElementById('surname').value surname: document.getElementById("surname").value,
}; };
console.log('data', data); console.log("data", data);
fetch('http://localhost:3000', { fetch("http://localhost:3000", {
method: 'post', method: "post",
headers: { headers: {
'Content-Type': 'application/json' "Content-Type": "application/json",
}, },
body: JSON.stringify(data) body: JSON.stringify(data),
}).then(function (response) { }).then(function (response) {
console.log(response); console.log(response);
return response.json(); return response.json();
});
}); });
</script> });
</script>
+34 -32
View File
@@ -1,48 +1,50 @@
const http = require('http') const http = require("http");
const fs = require('fs') const fs = require("fs");
const path = require('path') const path = require("path");
const form = fs.readFileSync(path.join(__dirname, 'public', 'form.html')) const form = fs.readFileSync(path.join(__dirname, "public", "form.html"));
http.createServer((req, res) => { http
if (req.method === 'GET') { .createServer((req, res) => {
get(res) if (req.method === "GET") {
return get(res);
return;
} }
if (req.method === 'POST') { if (req.method === "POST") {
post(req, res) post(req, res);
return return;
} }
error(405, res) error(405, res);
}).listen(3000) })
.listen(3000);
function get(res) { function get(res) {
res.writeHead(200, { res.writeHead(200, {
'Content-Type': 'text/html' "Content-Type": "text/html",
}) });
res.end(form) res.end(form);
} }
function post(req, res) { function post(req, res) {
if (req.headers['content-type'] !== 'application/x-www-form-urlencoded') { if (req.headers["content-type"] !== "application/x-www-form-urlencoded") {
error(415, res) error(415, res);
return return;
} }
let input = ''; let input = "";
req.on('data', chunk => { req.on("data", (chunk) => {
input += chunk.toString() input += chunk.toString();
}) });
req.on('end', () => { req.on("end", () => {
console.log(input); console.log(input);
res.end(http.STATUS_CODES[200]) res.end(http.STATUS_CODES[200]);
}) });
} }
function error(code, res) { function error(code, res) {
res.statusCode = code res.statusCode = code;
res.end(http.STATUS_CODES[code]) res.end(http.STATUS_CODES[code]);
} }
+15 -12
View File
@@ -1,18 +1,21 @@
const nodemailer = require("nodemailer") const nodemailer = require("nodemailer");
let transporter = nodemailer.createTransport({ let transporter = nodemailer.createTransport({
host: "localhost", host: "localhost",
port: 4321 port: 4321,
}) });
transporter.sendMail({ transporter.sendMail(
from: 'beth@example.com', {
to: 'laddie@example.com', from: "beth@example.com",
to: "laddie@example.com",
subject: "Hello", subject: "Hello",
text: "Hello world!" text: "Hello world!",
}, (err, info) => { },
(err, info) => {
if (err) { if (err) {
console.log(err) console.log(err);
} }
console.log("Message Sent:", info) console.log("Message Sent:", info);
}) }
);
+9 -9
View File
@@ -1,14 +1,14 @@
const SMTPServer = require("smtp-server").SMTPServer const SMTPServer = require("smtp-server").SMTPServer;
const PORT = 4321 const PORT = 4321;
const server = new SMTPServer({ const server = new SMTPServer({
disabledCommands: ['STARTTLS', 'AUTH'], disabledCommands: ["STARTTLS", "AUTH"],
logger: true logger: true,
}) });
server.on('error', err => { server.on("error", (err) => {
console.error(err); console.error(err);
}) });
server.listen(PORT) server.listen(PORT);
+7 -7
View File
@@ -1,11 +1,11 @@
const fs = require('fs') const fs = require("fs");
const http = require('http') const http = require("http");
const index = fs.readFileSync('public/index.html') const index = fs.readFileSync("public/index.html");
const server = http.createServer((req, res) => { const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html') res.setHeader("Content-Type", "text/html");
res.end(index) res.end(index);
}) });
server.listen(8080) server.listen(8080);
+13 -13
View File
@@ -1,18 +1,18 @@
const WebSocket = require('ws') const WebSocket = require("ws");
const ws = new WebSocket('ws://localhost:3000') const ws = new WebSocket("ws://localhost:3000");
ws.on('open', () => { ws.on("open", () => {
console.log('Connected') console.log("Connected");
}) });
ws.on('close', () => { ws.on("close", () => {
console.log('Disconnected') console.log("Disconnected");
}) });
ws.on('message', (message) => { ws.on("message", (message) => {
console.log('Received:', message) console.log("Received:", message);
}) });
setInterval(() => { setInterval(() => {
ws.send("Hello") ws.send("Hello");
}, 3000) }, 3000);
+21 -21
View File
@@ -1,32 +1,32 @@
<h1>Communicating with WebSockets</h1> <h1>Communicating with WebSockets</h1>
<input id="msg"><button id="send">Send</button> <input id="msg" /><button id="send">Send</button>
<div id="output"></div> <div id="output"></div>
<script> <script>
const ws = new WebSocket('ws://localhost:3000') const ws = new WebSocket("ws://localhost:3000");
const output = document.getElementById('output') const output = document.getElementById("output");
const send = document.getElementById('send') const send = document.getElementById("send");
send.addEventListener('click', () => { send.addEventListener("click", () => {
const msg = document.getElementById('msg').value const msg = document.getElementById("msg").value;
ws.send(msg) ws.send(msg);
output.innerHTML += log('Sent', msg) output.innerHTML += log("Sent", msg);
}) });
function log(event, msg) { function log(event, msg) {
return '<p>' + event + ': ' + msg + '</p>' return "<p>" + event + ": " + msg + "</p>";
} }
ws.onmessage = function (e) { ws.onmessage = function (e) {
output.innerHTML += log('Received', e.data) output.innerHTML += log("Received", e.data);
} };
ws.onclose = function (e) { ws.onclose = function (e) {
output.innerHTML += log('Disconnected', e.code) output.innerHTML += log("Disconnected", e.code);
} };
ws.onerror = function (e) { ws.onerror = function (e) {
output.innerHTML += log('Error', e.data) output.innerHTML += log("Error", e.data);
} };
</script> </script>
+9 -9
View File
@@ -1,12 +1,12 @@
const WebSocket = require('ws') const WebSocket = require("ws");
const WebSocketServer = new WebSocket.Server({ const WebSocketServer = new WebSocket.Server({
port: 3000 port: 3000,
}) });
WebSocketServer.on('connection', (socket) => { WebSocketServer.on("connection", (socket) => {
socket.on('message', (msg) => { socket.on("message", (msg) => {
console.log('Received:', msg) console.log("Received:", msg);
if (msg === 'Hello') socket.send('World!') if (msg === "Hello") socket.send("World!");
}) });
}) });
@@ -0,0 +1,62 @@
# Logs
logs
*.log
npm-debug.log*
# Runtime data
pids
*.pid
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules
jspm_packages
# Optional npm cache directory
.npm
# Optional REPL history
.node_repl_history
# 0x
profile-*
# mac files
.DS_Store
# vim swap files
*.swp
# webstorm
.idea
# vscode
.vscode
*code-workspace
# clinic
profile*
*clinic*
*flamegraph*
# generated code
examples/typescript-server.js
test/types/index.js
+28
View File
@@ -0,0 +1,28 @@
'use strict'
const path = require('path')
const AutoLoad = require('fastify-autoload')
module.exports = function (fastify, opts, next) {
// Place here your custom code!
// Do not touch the following lines
// This loads all plugins defined in plugins
// those should be support plugins that are reused
// through your application
fastify.register(AutoLoad, {
dir: path.join(__dirname, 'plugins'),
options: Object.assign({}, opts)
})
// This loads all plugins defined in services
// define your routes in one of these
fastify.register(AutoLoad, {
dir: path.join(__dirname, 'services'),
options: Object.assign({}, opts)
})
// Make sure to call next when done
next()
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,26 @@
{
"name": "fastify-generated",
"version": "1.0.0",
"description": "",
"main": "app.js",
"directories": {
"test": "test"
},
"scripts": {
"test": "tap test/**/*.test.js",
"start": "fastify start -l info app.js",
"dev": "fastify start -w -l info -P app.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"fastify": "^2.0.0",
"fastify-plugin": "^1.5.0",
"fastify-autoload": "^1.0.0",
"fastify-cli": "^1.5.0"
},
"devDependencies": {
"tap": "^12.5.3"
}
}
@@ -0,0 +1,16 @@
# Plugins Folder
Plugins define behavior that is common to all the routes in your
application. Authentication, caching, templates, and all the other cross
cutting concerns should be handled by plugins placed in this folder.
Files in this folder are typically defined through the
[`fastify-plugin`](https://github.com/fastify/fastify-plugin) module,
making them non-encapsulated. They can define decorators and set hooks
that will then be used in the rest of your application.
Check out:
* [The hitchhiker's guide to plugins](https://github.com/fastify/fastify/blob/master/docs/Plugins-Guide.md)
* [Fastify decorators](https://www.fastify.io/docs/latest/Decorators/).
* [Fastify lifecycle](https://www.fastify.io/docs/latest/Lifecycle/).
@@ -0,0 +1,21 @@
'use strict'
const fp = require('fastify-plugin')
// the use of fastify-plugin is required to be able
// to export the decorators to the outer scope
module.exports = fp(function (fastify, opts, next) {
fastify.decorate('someSupport', function () {
return 'hugs'
})
next()
})
// If you prefer async/await, use the following
//
// module.exports = fp(async function (fastify, opts) {
// fastify.decorate('someSupport', function () {
// return 'hugs'
// })
// })
@@ -0,0 +1,24 @@
# Services Folder
Services define routes within your application. Fastify provides an
easy path to a microservice architecture, in the future you might want
to independently deploy some of those.
In this folder you should define all the services that define the routes
of your web application.
Each service is a [Fastify
plugin](https://www.fastify.io/docs/latest/Plugins/), it is
encapsulated (it can have its own independent plugins) and it is
typically stored in a file; be careful to group your routes logically,
e.g. all `/users` routes in a `users.js` file. We have added
a `root.js` file for you with a '/' root added.
If a single file become too large, create a folder and add a `index.js` file there:
this file must be a Fastify plugin, and it will be loaded automatically
by the application. You can now add as many files as you want inside that folder.
In this way you can create complex services within a single monolith,
and eventually extract them.
If you need to share functionality between services, place that
functionality into the `plugins` folder, and share it via
[decorators](https://www.fastify.io/docs/latest/Decorators/).
@@ -0,0 +1,17 @@
'use strict'
module.exports = function (fastify, opts, next) {
fastify.get('/example', function (request, reply) {
reply.send('this is an example')
})
next()
}
// If you prefer async/await, use the following
//
// module.exports = async function (fastify, opts) {
// fastify.get('/example', async function (request, reply) {
// return 'this is an example'
// })
// }
@@ -0,0 +1,17 @@
'use strict'
module.exports = function (fastify, opts, next) {
fastify.get('/', function (request, reply) {
reply.send({ root: true })
})
next()
}
// If you prefer async/await, use the following
//
// module.exports = async function (fastify, opts) {
// fastify.get('/', async function (request, reply) {
// return { root: true }
// })
// }
@@ -0,0 +1,34 @@
'use strict'
// This file contains code that we reuse
// between our tests.
const Fastify = require('fastify')
const fp = require('fastify-plugin')
const App = require('../app')
// Fill in this config with all the configurations
// needed for testing the application
function config () {
return {}
}
// automatically build and tear down our instance
function build (t) {
const app = Fastify()
// fastify-plugin ensures that all decorators
// are exposed for testing purposes, this is
// different from the production setup
app.register(fp(App), config())
// tear down our app after we are done
t.tearDown(app.close.bind(app))
return app
}
module.exports = {
config,
build
}
@@ -0,0 +1,26 @@
'use strict'
const { test } = require('tap')
const Fastify = require('fastify')
const Support = require('../../plugins/support')
test('support works standalone', (t) => {
t.plan(2)
const fastify = Fastify()
fastify.register(Support)
fastify.ready((err) => {
t.error(err)
t.equal(fastify.someSupport(), 'hugs')
})
})
// If you prefer async/await, use the following
//
// test('support works standalone', async (t) => {
// const fastify = Fastify()
// fastify.register(Support)
//
// await fastify.ready()
// t.equal(fastify.someSupport(), 'hugs')
// })
@@ -0,0 +1,27 @@
'use strict'
const { test } = require('tap')
const { build } = require('../helper')
test('example is loaded', (t) => {
t.plan(2)
const app = build(t)
app.inject({
url: '/example'
}, (err, res) => {
t.error(err)
t.equal(res.payload, 'this is an example')
})
})
// If you prefer async/await, use the following
//
// test('example is loaded', async (t) => {
// const app = build(t)
//
// const res = await app.inject({
// url: '/example'
// })
// t.equal(res.payload, 'this is an example')
// })
@@ -0,0 +1,27 @@
'use strict'
const { test } = require('tap')
const { build } = require('../helper')
test('default root route', (t) => {
t.plan(2)
const app = build(t)
app.inject({
url: '/'
}, (err, res) => {
t.error(err)
t.deepEqual(JSON.parse(res.payload), { root: true })
})
})
// If you prefer async/await, use the following
//
// test('default root route', async (t) => {
// const app = build(t)
//
// const res = await app.inject({
// url: '/'
// })
// t.deepEqual(JSON.parse(res.payload), { root: true })
// })
@@ -0,0 +1,7 @@
async function routes(fastify) {
fastify.get("/", async (request, reply) => {
return { message: "Hello world!" };
});
}
module.exports = routes;
+1 -3
View File
@@ -2,9 +2,7 @@ const fastify = require("fastify")();
const PORT = process.env.PORT || 3000; const PORT = process.env.PORT || 3000;
fastify.get("/", async (request, reply) => { fastify.register(require("./plugins/hello-route"));
return { message: "Hello world!" };
});
const startServer = async () => { const startServer = async () => {
try { try {
+1
View File
@@ -0,0 +1 @@
This is a static file.
+336
View File
@@ -0,0 +1,336 @@
{
"name": "hapi-app",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@hapi/accept": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/@hapi/accept/-/accept-5.0.1.tgz",
"integrity": "sha512-fMr4d7zLzsAXo28PRRQPXR1o2Wmu+6z+VY1UzDp0iFo13Twj8WePakwXBiqn3E1aAlTpSNzCXdnnQXFhst8h8Q==",
"requires": {
"@hapi/boom": "9.x.x",
"@hapi/hoek": "9.x.x"
}
},
"@hapi/address": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@hapi/address/-/address-4.0.1.tgz",
"integrity": "sha512-0oEP5UiyV4f3d6cBL8F3Z5S7iWSX39Knnl0lY8i+6gfmmIBj44JCBNtcMgwyS+5v7j3VYavNay0NFHDS+UGQcw==",
"requires": {
"@hapi/hoek": "^9.0.0"
}
},
"@hapi/ammo": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/@hapi/ammo/-/ammo-5.0.1.tgz",
"integrity": "sha512-FbCNwcTbnQP4VYYhLNGZmA76xb2aHg9AMPiy18NZyWMG310P5KdFGyA9v2rm5ujrIny77dEEIkMOwl0Xv+fSSA==",
"requires": {
"@hapi/hoek": "9.x.x"
}
},
"@hapi/b64": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/@hapi/b64/-/b64-5.0.0.tgz",
"integrity": "sha512-ngu0tSEmrezoiIaNGG6rRvKOUkUuDdf4XTPnONHGYfSGRmDqPZX5oJL6HAdKTo1UQHECbdB4OzhWrfgVppjHUw==",
"requires": {
"@hapi/hoek": "9.x.x"
}
},
"@hapi/boom": {
"version": "9.1.0",
"resolved": "https://registry.npmjs.org/@hapi/boom/-/boom-9.1.0.tgz",
"integrity": "sha512-4nZmpp4tXbm162LaZT45P7F7sgiem8dwAh2vHWT6XX24dozNjGMg6BvKCRvtCUcmcXqeMIUqWN8Rc5X8yKuROQ==",
"requires": {
"@hapi/hoek": "9.x.x"
}
},
"@hapi/bounce": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@hapi/bounce/-/bounce-2.0.0.tgz",
"integrity": "sha512-JesW92uyzOOyuzJKjoLHM1ThiOvHPOLDHw01YV8yh5nCso7sDwJho1h0Ad2N+E62bZyz46TG3xhAi/78Gsct6A==",
"requires": {
"@hapi/boom": "9.x.x",
"@hapi/hoek": "9.x.x"
}
},
"@hapi/bourne": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@hapi/bourne/-/bourne-2.0.0.tgz",
"integrity": "sha512-WEezM1FWztfbzqIUbsDzFRVMxSoLy3HugVcux6KDDtTqzPsLE8NDRHfXvev66aH1i2oOKKar3/XDjbvh/OUBdg=="
},
"@hapi/call": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/@hapi/call/-/call-8.0.0.tgz",
"integrity": "sha512-4xHIWWqaIDQlVU88XAnomACSoC7iWUfaLfdu2T7I0y+HFFwZUrKKGfwn6ik4kwKsJRMnOliG3UXsF8V/94+Lkg==",
"requires": {
"@hapi/address": "4.x.x",
"@hapi/boom": "9.x.x",
"@hapi/hoek": "9.x.x"
}
},
"@hapi/catbox": {
"version": "11.1.0",
"resolved": "https://registry.npmjs.org/@hapi/catbox/-/catbox-11.1.0.tgz",
"integrity": "sha512-FDEjfn26RZRyOEPeZdaAL7dRiAK5FOGuwTnTw0gxK30csAlKeOHsEnoIxnLIXx7QOS17eUaOk6+MiweWQM6Keg==",
"requires": {
"@hapi/boom": "9.x.x",
"@hapi/hoek": "9.x.x",
"@hapi/joi": "17.x.x",
"@hapi/podium": "4.x.x"
}
},
"@hapi/catbox-memory": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/@hapi/catbox-memory/-/catbox-memory-5.0.0.tgz",
"integrity": "sha512-ByuxVJPHNaXwLzbBv4GdTr6ccpe1nG+AfYt+8ftDWEJY7EWBWzD+Klhy5oPTDGzU26pNUh1e7fcYI1ILZRxAXQ==",
"requires": {
"@hapi/boom": "9.x.x",
"@hapi/hoek": "9.x.x"
}
},
"@hapi/content": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/@hapi/content/-/content-5.0.2.tgz",
"integrity": "sha512-mre4dl1ygd4ZyOH3tiYBrOUBzV7Pu/EOs8VLGf58vtOEECWed8Uuw6B4iR9AN/8uQt42tB04qpVaMyoMQh0oMw==",
"requires": {
"@hapi/boom": "9.x.x"
}
},
"@hapi/cryptiles": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/@hapi/cryptiles/-/cryptiles-5.1.0.tgz",
"integrity": "sha512-fo9+d1Ba5/FIoMySfMqPBR/7Pa29J2RsiPrl7bkwo5W5o+AN1dAYQRi4SPrPwwVxVGKjgLOEWrsvt1BonJSfLA==",
"requires": {
"@hapi/boom": "9.x.x"
}
},
"@hapi/file": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@hapi/file/-/file-2.0.0.tgz",
"integrity": "sha512-WSrlgpvEqgPWkI18kkGELEZfXr0bYLtr16iIN4Krh9sRnzBZN6nnWxHFxtsnP684wueEySBbXPDg/WfA9xJdBQ=="
},
"@hapi/formula": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@hapi/formula/-/formula-2.0.0.tgz",
"integrity": "sha512-V87P8fv7PI0LH7LiVi8Lkf3x+KCO7pQozXRssAHNXXL9L1K+uyu4XypLXwxqVDKgyQai6qj3/KteNlrqDx4W5A=="
},
"@hapi/hapi": {
"version": "19.1.1",
"resolved": "https://registry.npmjs.org/@hapi/hapi/-/hapi-19.1.1.tgz",
"integrity": "sha512-rpQzSs0XsHSF7usM4qdJJ0Bcmhs9stWhUW3OiamW33bw4qL8q3uEgUKB9KH8ODmluCAkkXOQ0X0Dh9t94E5VIw==",
"requires": {
"@hapi/accept": "^5.0.1",
"@hapi/ammo": "^5.0.1",
"@hapi/boom": "9.x.x",
"@hapi/bounce": "2.x.x",
"@hapi/call": "8.x.x",
"@hapi/catbox": "11.x.x",
"@hapi/catbox-memory": "5.x.x",
"@hapi/heavy": "7.x.x",
"@hapi/hoek": "9.x.x",
"@hapi/joi": "17.x.x",
"@hapi/mimos": "5.x.x",
"@hapi/podium": "4.x.x",
"@hapi/shot": "5.x.x",
"@hapi/somever": "3.x.x",
"@hapi/statehood": "^7.0.2",
"@hapi/subtext": "^7.0.3",
"@hapi/teamwork": "4.x.x",
"@hapi/topo": "5.x.x"
}
},
"@hapi/heavy": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/@hapi/heavy/-/heavy-7.0.0.tgz",
"integrity": "sha512-n/nheUG6zNleWkjY+3fzV3VJIAumUCaa/WoTmurjqlYY5JgC5ZKOpvP7tWi8rXmKZhbcXgjH3fHFoM55LoBT7g==",
"requires": {
"@hapi/boom": "9.x.x",
"@hapi/hoek": "9.x.x",
"@hapi/joi": "17.x.x"
}
},
"@hapi/hoek": {
"version": "9.0.4",
"resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.0.4.tgz",
"integrity": "sha512-EwaJS7RjoXUZ2cXXKZZxZqieGtc7RbvQhUy8FwDoMQtxWVi14tFjeFCYPZAM1mBCpOpiBpyaZbb9NeHc7eGKgw=="
},
"@hapi/inert": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/@hapi/inert/-/inert-6.0.1.tgz",
"integrity": "sha512-oLxAmtWni3nH4INU2gcXFnHBw0GhHYF3HR71hAWrPc91dq+iFYGfawfaMbonwGr5DkzFiGe8Ir5sZAt2AqeINA==",
"requires": {
"@hapi/ammo": "5.x.x",
"@hapi/boom": "9.x.x",
"@hapi/bounce": "2.x.x",
"@hapi/hoek": "9.x.x",
"@hapi/joi": "17.x.x",
"lru-cache": "5.x.x"
}
},
"@hapi/iron": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/@hapi/iron/-/iron-6.0.0.tgz",
"integrity": "sha512-zvGvWDufiTGpTJPG1Y/McN8UqWBu0k/xs/7l++HVU535NLHXsHhy54cfEMdW7EjwKfbBfM9Xy25FmTiobb7Hvw==",
"requires": {
"@hapi/b64": "5.x.x",
"@hapi/boom": "9.x.x",
"@hapi/bourne": "2.x.x",
"@hapi/cryptiles": "5.x.x",
"@hapi/hoek": "9.x.x"
}
},
"@hapi/joi": {
"version": "17.1.1",
"resolved": "https://registry.npmjs.org/@hapi/joi/-/joi-17.1.1.tgz",
"integrity": "sha512-p4DKeZAoeZW4g3u7ZeRo+vCDuSDgSvtsB/NpfjXEHTUjSeINAi/RrVOWiVQ1isaoLzMvFEhe8n5065mQq1AdQg==",
"requires": {
"@hapi/address": "^4.0.1",
"@hapi/formula": "^2.0.0",
"@hapi/hoek": "^9.0.0",
"@hapi/pinpoint": "^2.0.0",
"@hapi/topo": "^5.0.0"
}
},
"@hapi/mimos": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/@hapi/mimos/-/mimos-5.0.0.tgz",
"integrity": "sha512-EVS6wJYeE73InTlPWt+2e3Izn319iIvffDreci3qDNT+t3lA5ylJ0/SoTaID8e0TPNUkHUSsgJZXEmLHvoYzrA==",
"requires": {
"@hapi/hoek": "9.x.x",
"mime-db": "1.x.x"
}
},
"@hapi/nigel": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@hapi/nigel/-/nigel-4.0.0.tgz",
"integrity": "sha512-Bqs1pjcDnDQo/XGoiCCNHWTFcMzPbz3L4KU04njeFQMzzEmsojMRX7TX+PezQYCMKtHJOtMg0bHxZyMGqYtbSA==",
"requires": {
"@hapi/hoek": "9.x.x",
"@hapi/vise": "4.x.x"
}
},
"@hapi/pez": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/@hapi/pez/-/pez-5.0.2.tgz",
"integrity": "sha512-jr1lAm8mE7J2IBxvDIuDI1qy2aAsoaD2jxOUd/7JRg/Vmrzco8HdKhtz4fKk6KHU6zbbsAp5m5aSWWVTUrag7g==",
"requires": {
"@hapi/b64": "5.x.x",
"@hapi/boom": "9.x.x",
"@hapi/content": "^5.0.2",
"@hapi/hoek": "9.x.x",
"@hapi/nigel": "4.x.x"
}
},
"@hapi/pinpoint": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@hapi/pinpoint/-/pinpoint-2.0.0.tgz",
"integrity": "sha512-vzXR5MY7n4XeIvLpfl3HtE3coZYO4raKXW766R6DZw/6aLqR26iuZ109K7a0NtF2Db0jxqh7xz2AxkUwpUFybw=="
},
"@hapi/podium": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/@hapi/podium/-/podium-4.1.0.tgz",
"integrity": "sha512-k/n0McAu8PvonfQRLyKKUvvdb+Gh/O5iAeIwv535Hpxw9B1qZcrYdZyWtHZ8O5PkA9/b/Kk+BdvtgcxeKMB/2g==",
"requires": {
"@hapi/hoek": "9.x.x",
"@hapi/joi": "17.x.x",
"@hapi/teamwork": "4.x.x"
}
},
"@hapi/shot": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/@hapi/shot/-/shot-5.0.0.tgz",
"integrity": "sha512-JXddnJkRh3Xhv9lY1tA+TSIUaoODKbdNIPL/M8WFvFQKOttmGaDeqTW5e8Gf01LtLI7L5DraLMULHjrK1+YNFg==",
"requires": {
"@hapi/hoek": "9.x.x",
"@hapi/joi": "17.x.x"
}
},
"@hapi/somever": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@hapi/somever/-/somever-3.0.0.tgz",
"integrity": "sha512-Upw/kmKotC9iEmK4y047HMYe4LDKsE5NWfjgX41XNKmFvxsQL7OiaCWVhuyyhU0ShDGBfIAnCH8jZr49z/JzZA==",
"requires": {
"@hapi/bounce": "2.x.x",
"@hapi/hoek": "9.x.x"
}
},
"@hapi/statehood": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@hapi/statehood/-/statehood-7.0.2.tgz",
"integrity": "sha512-+0VNxysQu+UYzkfvAXq3X4aN65TnUwiR7gsq2cQ/4Rq26nCJjHAfrkYReEeshU2hPmJ3m5QuaBzyDqRm8WOpyg==",
"requires": {
"@hapi/boom": "9.x.x",
"@hapi/bounce": "2.x.x",
"@hapi/bourne": "2.x.x",
"@hapi/cryptiles": "5.x.x",
"@hapi/hoek": "9.x.x",
"@hapi/iron": "6.x.x",
"@hapi/joi": "17.x.x"
}
},
"@hapi/subtext": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/@hapi/subtext/-/subtext-7.0.3.tgz",
"integrity": "sha512-CekDizZkDGERJ01C0+TzHlKtqdXZxzSWTOaH6THBrbOHnsr3GY+yiMZC+AfNCypfE17RaIakGIAbpL2Tk1z2+A==",
"requires": {
"@hapi/boom": "9.x.x",
"@hapi/bourne": "2.x.x",
"@hapi/content": "^5.0.2",
"@hapi/file": "2.x.x",
"@hapi/hoek": "9.x.x",
"@hapi/pez": "^5.0.1",
"@hapi/wreck": "17.x.x"
}
},
"@hapi/teamwork": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@hapi/teamwork/-/teamwork-4.0.0.tgz",
"integrity": "sha512-V6xYOrr5aFv/IJqNPneaYCu8vuGTKisamqHVRS3JJnbZr18TrpXdsJOYk9pjPhFti+M2YETPebQLUr820N5NoQ=="
},
"@hapi/topo": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.0.0.tgz",
"integrity": "sha512-tFJlT47db0kMqVm3H4nQYgn6Pwg10GTZHb1pwmSiv1K4ks6drQOtfEF5ZnPjkvC+y4/bUPHK+bc87QvLcL+WMw==",
"requires": {
"@hapi/hoek": "^9.0.0"
}
},
"@hapi/vise": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@hapi/vise/-/vise-4.0.0.tgz",
"integrity": "sha512-eYyLkuUiFZTer59h+SGy7hUm+qE9p+UemePTHLlIWppEd+wExn3Df5jO04bFQTm7nleF5V8CtuYQYb+VFpZ6Sg==",
"requires": {
"@hapi/hoek": "9.x.x"
}
},
"@hapi/wreck": {
"version": "17.0.0",
"resolved": "https://registry.npmjs.org/@hapi/wreck/-/wreck-17.0.0.tgz",
"integrity": "sha512-d8lqCinbKyDByn7GzJDRDbitddhIEydNm44UcAMejfhEH3o4IYvKYq6K8cAqXbilXPuvZc0ErlUOg9SDdgRtMw==",
"requires": {
"@hapi/boom": "9.x.x",
"@hapi/bourne": "2.x.x",
"@hapi/hoek": "9.x.x"
}
},
"lru-cache": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
"integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
"requires": {
"yallist": "^3.0.2"
}
},
"mime-db": {
"version": "1.44.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz",
"integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg=="
},
"yallist": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
}
}
}
+16
View File
@@ -0,0 +1,16 @@
{
"name": "hapi-app",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@hapi/hapi": "^19.1.1",
"@hapi/inert": "^6.0.1"
}
}
+27
View File
@@ -0,0 +1,27 @@
const Hapi = require("@hapi/hapi");
const path = require("path");
const PORT = process.env.PORT || 3000;
const HOSTNAME = process.env.HOSTNAME || "localhost";
const initialize = async () => {
const server = Hapi.server({
port: PORT,
host: HOSTNAME,
});
await server.register(require("@hapi/inert"));
server.route({
method: "GET",
path: "/",
handler: {
file: path.join(__dirname, "files/file.txt"),
},
});
await server.start();
console.log("Server running on %s", server.info.uri);
};
initialize();
+3
View File
@@ -0,0 +1,3 @@
{
"git.ignoreLimitWarning": true
}