Added in fastify/formbody so I can...handle forms...in a webserver...in 2024...I guess that's why it's so 'small'.

main
Zed A. Shaw 3 months ago
parent 53d67f185b
commit 2d73c70186
  1. 44
      commands/app.js
  2. 15
      controllers/todo.js
  3. 10
      package-lock.json
  4. 1
      package.json
  5. 7
      templates/todo.html

@ -1,6 +1,7 @@
import Fastify from "fastify";
import { restartable } from "@fastify/restartable";
import FastifyStatic from "@fastify/static";
import Formbody from "@fastify/formbody";
import path from "path";
import fs from "fs";
import chokidar from "chokidar";
@ -20,30 +21,30 @@ nunjucks.configure("templates", { watch: true });
const configure = async (fastify, opts) => {
const app = fastify(opts);
// MAGIC: this is how you trick the importer to reload modules
// that have changed. Since it uses a URL you can add a query
// to it, but that isn't parsed as the file. Using a date then
// tags the module as being "new" when it's still the same file
// TODO: maybe use fs timestamps instead?
// BUG: sometimes reload is too fast for vim and crashes
// forces reload of the modules
const control_mod = await import(`../controllers/todo.js?update=${new Date()}`);
// this is a sample that uses the handler we dynamic load
// to handle the /todo but not sure how to work the actual
// URL mappings for it. Also not sure about using classes
// TODO: mappings are very simple for now
for(let [url, controller] of Object.entries(control_mod.default)) {
const handler = new controller();
app.get(`/${url}`, async (req, rep) => {
try {
await handler.get(req, rep);
} catch(error) {
console.error(error);
console.error(error.stack);
console.error(error.source);
// this goes through all the allowed verbs
for(let verb of ["get", "post", "put", "delete"]) {
if(verb in handler) {
app[verb](`/${url}`, async (req, rep) => {
try {
await handler[verb](req, rep);
} catch(error) {
console.error(error);
console.error(error.stack);
console.error(error.source);
}
});
}
});
}
}
app.register(Formbody);
app.register(FastifyStatic, {
root: path.join(path.resolve("."), 'static'),
prefix: '/', // optional: default '/'
@ -51,15 +52,6 @@ const configure = async (fastify, opts) => {
index: "index.html"
});
// this is from fastify/restartable
app.addHook('onClose', async () => {
if(!app.closingRestartable) {
console.log('closing the app because of restart')
} else{
console.log('closing the app because server is stopping')
}
})
return app;
}

@ -2,9 +2,6 @@ import { ToDo } from "../lib/models.js";
import nunjucks from "nunjucks";
export class Todo {
constructor() {
}
async get(req, rep) {
const todo_list = await ToDo.all({});
@ -13,6 +10,18 @@ export class Todo {
rep.code(200).type("text/html").send(result);
}
async post(req, rep) {
if(req.query.todo_id !== undefined) {
await ToDo.delete({id: req.query.todo_id});
} else {
console.log("ADDING TASK", req.body.task);
await ToDo.insert({task: req.body.task});
}
// this is how you can prevent the annoying double submit
rep.redirect("/todo");
}
}
// you use the export default to set the route URL?

10
package-lock.json generated

@ -9,6 +9,7 @@
"version": "0.1.0",
"dependencies": {
"@fastify/cors": "^9.0.1",
"@fastify/formbody": "^7.4.0",
"@fastify/helmet": "^11.1.1",
"@fastify/static": "^7.0.0",
"commander": "^12.0.0",
@ -72,6 +73,15 @@
"fast-json-stringify": "^5.7.0"
}
},
"node_modules/@fastify/formbody": {
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/@fastify/formbody/-/formbody-7.4.0.tgz",
"integrity": "sha512-H3C6h1GN56/SMrZS8N2vCT2cZr7mIHzBHzOBa5OPpjfB/D6FzP9mMpE02ZzrFX0ANeh0BAJdoXKOF2e7IbV+Og==",
"dependencies": {
"fast-querystring": "^1.0.0",
"fastify-plugin": "^4.0.0"
}
},
"node_modules/@fastify/helmet": {
"version": "11.1.1",
"resolved": "https://registry.npmjs.org/@fastify/helmet/-/helmet-11.1.1.tgz",

@ -9,6 +9,7 @@
"scripts": {},
"dependencies": {
"@fastify/cors": "^9.0.1",
"@fastify/formbody": "^7.4.0",
"@fastify/helmet": "^11.1.1",
"@fastify/static": "^7.0.0",
"commander": "^12.0.0",

@ -19,11 +19,16 @@
<ol>
{% for todo in todo_list %}
<li>{{ todo.task }}</li>
<li style="display: flex; gap: 1rem;"><form action="/todo?todo_id={{ todo.id }}" method="POST"><button>X</button></form> {{ todo.task }}</li>
{% else %}
<li>No TODO Items</li>
{% endfor %}
</ol>
<h4>Add a New TODO</h4>
<form action="/todo" method="POST">
<label for="task">Task</label>
<input name="task"></input>
</form>
{% include "./footer.html" %}

Loading…
Cancel
Save