Bring in helmet and cors support then setup for the nicer configuration and runner commands.

main
Zed A. Shaw 9 months ago
parent 7421ff513d
commit ae6996372b
  1. 3
      bando
  2. 85
      bin/bando.js
  3. 43
      bin/tester.js
  4. 9
      commands/app.js
  5. 53
      commands/tester.js
  6. 20
      lib/tooling.js
  7. 41
      package-lock.json
  8. 2
      package.json

@ -0,0 +1,3 @@
#!/usr/bin/env bash
node ./bin/bando.js "$@"

@ -0,0 +1,85 @@
#!/usr/bin/env node
import { Command } from "commander";
// NOTE: this changed in node 18 to be node:url for...stupid
import { fileURLToPath } from "url";
import { glob } from "../lib/tooling.js";
import path from "path";
import assert from "assert";
import fs from "fs";
// BUG: this will load the commands but most of them assume the root
const __filename = fileURLToPath(import.meta.url);
const { dir } = path.parse(__filename);
let __dirname = path.resolve(dir);
// now even exec commands will know where the project root is
process.env['PROJECT_ROOT'] = path.resolve(path.join(__dirname, ".."));
const program = new Command();
// remember that glob doesn't like windows \
const command_dir = path.resolve(path.join(__dirname, "..", "commands"));
if(!fs.existsSync(command_dir)) {
console.error("ERROR: there is no command directory at", command_dir);
process.exit(1);
}
program
.name("bando")
.description("Command runner for the bando project.")
.version("0.1.0");
// only load the commands modules if any options are given
if(process.argv.length === 2) {
console.log("COMMANDS:\n");
const commands = glob(`${command_dir}/*.js`).map(cmd => {
console.log(path.parse(cmd).name);
});
if(process.platform === "win32") {
console.log("\nUse './bando help' for full help.");
} else {
console.log("\nUse './bando.js help' for full help.");
}
} else {
try {
const name = process.argv[2];
const command = path.join(command_dir, `${name}.js`);
if(fs.existsSync(command)) {
const mod = await import(`file://${command}`);
assert(mod.description, `export const description missing in ${command}`);
assert(mod.main, `export const main missing in ${command}`);
const build = program.command(name)
.description(mod.description)
.action(mod.main);
if(mod.options) {
mod.options.forEach(opt => build.option(...opt));
}
if(mod.required) {
mod.required.forEach(opt => build.requiredOption(...opt));
}
if(mod.argument) {
build.argument(...mod.argument);
}
}
} catch(error) {
console.log(error, `Loading file ${process.argv[2]}`);
}
}
try {
program.parse();
} catch(error) {
console.log("------------- ERROR, here's the stack trace.");
console.error(error.stack);
process.exit(1);
}

@ -1,43 +0,0 @@
import glob from "fast-glob";
import path from "path";
const test_files = await glob("./tests/**/*_test?.js");
const stats = {
pass: 0, fail: 0
}
const errors = {}
const report_error = (id, error) => {
console.error(error, `Running function ${id}`);
}
for(let suite_name of test_files) {
const full_path = path.resolve(suite_name);
const test_module = await import(`file://${full_path}`);
for(let [name, func] of Object.entries(test_module)) {
const id = `${suite_name}:${name}`;
console.log("------- RUNNING", id);
try {
await func();
stats.pass += 1;
} catch(error) {
stats.fail += 1;
errors[id] = error;
report_error(func, id, error);
}
console.log("\n");
}
}
if(Object.keys(errors).length > 0) {
console.log("!!!!!!!!!!!!!! ERRORS !!!!!!!!!!!!!!!!");
for(let [id, error] of Object.entries(errors)) {
report_error(id, error);
}
}
console.log("\nPASS: ", stats.pass, "FAIL: ", stats.fail);

@ -5,10 +5,17 @@ import { ToDo } from "../lib/models.js";
import fs from "fs"; import fs from "fs";
import nunjucks from "nunjucks"; import nunjucks from "nunjucks";
export const description = "Runs your app.";
export const options = [];
export const required = [];
const fastify = Fastify({ const fastify = Fastify({
logger: true logger: true
}); });
fastify.get("/todo", async (req, rep) => { fastify.get("/todo", async (req, rep) => {
try { try {
const todo_list = await ToDo.all({}); const todo_list = await ToDo.all({});
@ -34,9 +41,11 @@ fastify.register(FastifyStatic, {
index: "index.html" index: "index.html"
}) })
export const main = async (arg, opts) => {
try { try {
await fastify.listen({port: 3000}); await fastify.listen({port: 3000});
} catch(err) { } catch(err) {
fastify.log.error(err); fastify.log.error(err);
process.exit(1); process.exit(1);
} }
}

@ -0,0 +1,53 @@
import glob from "fast-glob";
import path from "path";
export const description = "Runs tests.";
export const options = [];
export const required = [
["--glob <regex>", "Directory pattern to find test runners.", "./tests/**/*_test?.js"],
];
const report_error = (id, error) => {
console.error(error, `Running function ${id}`);
}
export const main = async (opts) => {
const test_files = await glob(opts.glob);
const stats = {
pass: 0, fail: 0
}
const errors = {}
for(let suite_name of test_files) {
const full_path = path.resolve(suite_name);
const test_module = await import(`file://${full_path}`);
for(let [name, func] of Object.entries(test_module)) {
const id = `${suite_name}:${name}`;
console.log("------- RUNNING", id);
try {
await func();
stats.pass += 1;
} catch(error) {
stats.fail += 1;
errors[id] = error;
report_error(func, id, error);
}
console.log("\n");
}
}
if(Object.keys(errors).length > 0) {
console.log("!!!!!!!!!!!!!! ERRORS !!!!!!!!!!!!!!!!");
for(let [id, error] of Object.entries(errors)) {
report_error(id, error);
}
}
console.log("\nPASS: ", stats.pass, "FAIL: ", stats.fail);
}

@ -0,0 +1,20 @@
import fg from "fast-glob";
/*
Fixes some common problems with `fast-glob` on windows. It removes
leading "C:\" from paths and replaces all of the `\\` with `/`.
__BUG__: This obviously won't work if you're on a different drive than C:.
+ `path string` -- The path/glob pattern to use.
*/
export const glob = (path) => {
if(process.platform === "win32") {
// fast-glob doesn't understand \\ or C:\
const fixed_path = path.replace("C:","").replaceAll('\\', '/')
return fg.sync(fixed_path);
} else {
return fg.sync(path);
}
}

41
package-lock.json generated

@ -8,6 +8,8 @@
"name": "bandolier2", "name": "bandolier2",
"version": "0.1.0", "version": "0.1.0",
"dependencies": { "dependencies": {
"@fastify/cors": "^9.0.1",
"@fastify/helmet": "^11.1.1",
"@fastify/static": "^7.0.0", "@fastify/static": "^7.0.0",
"commander": "^12.0.0", "commander": "^12.0.0",
"fast-glob": "^3.3.2", "fast-glob": "^3.3.2",
@ -39,6 +41,15 @@
"fast-uri": "^2.0.0" "fast-uri": "^2.0.0"
} }
}, },
"node_modules/@fastify/cors": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/@fastify/cors/-/cors-9.0.1.tgz",
"integrity": "sha512-YY9Ho3ovI+QHIL2hW+9X4XqQjXLjJqsU+sMV/xFsxZkE8p3GNnYVFpoOxF7SsP5ZL76gwvbo3V9L+FIekBGU4Q==",
"dependencies": {
"fastify-plugin": "^4.0.0",
"mnemonist": "0.39.6"
}
},
"node_modules/@fastify/deepmerge": { "node_modules/@fastify/deepmerge": {
"version": "1.3.0", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/@fastify/deepmerge/-/deepmerge-1.3.0.tgz", "resolved": "https://registry.npmjs.org/@fastify/deepmerge/-/deepmerge-1.3.0.tgz",
@ -57,6 +68,15 @@
"fast-json-stringify": "^5.7.0" "fast-json-stringify": "^5.7.0"
} }
}, },
"node_modules/@fastify/helmet": {
"version": "11.1.1",
"resolved": "https://registry.npmjs.org/@fastify/helmet/-/helmet-11.1.1.tgz",
"integrity": "sha512-pjJxjk6SLEimITWadtYIXt6wBMfFC1I6OQyH/jYVCqSAn36sgAIFjeNiibHtifjCd+e25442pObis3Rjtame6A==",
"dependencies": {
"fastify-plugin": "^4.2.1",
"helmet": "^7.0.0"
}
},
"node_modules/@fastify/send": { "node_modules/@fastify/send": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/@fastify/send/-/send-2.1.0.tgz", "resolved": "https://registry.npmjs.org/@fastify/send/-/send-2.1.0.tgz",
@ -1179,6 +1199,14 @@
"node": ">= 0.4" "node": ">= 0.4"
} }
}, },
"node_modules/helmet": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/helmet/-/helmet-7.1.0.tgz",
"integrity": "sha512-g+HZqgfbpXdCkme/Cd/mZkV0aV3BZZZSugecH03kl38m/Kmdx8jKjBikpDj2cr+Iynv4KpYEviojNdTJActJAg==",
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/http-cache-semantics": { "node_modules/http-cache-semantics": {
"version": "4.1.1", "version": "4.1.1",
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
@ -1790,6 +1818,14 @@
"resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="
}, },
"node_modules/mnemonist": {
"version": "0.39.6",
"resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.39.6.tgz",
"integrity": "sha512-A/0v5Z59y63US00cRSLiloEIw3t5G+MiKz4BhX21FI+YBJXBOGW0ohFxTxO08dsOYlzxo87T7vGfZKYp2bcAWA==",
"dependencies": {
"obliterator": "^2.0.1"
}
},
"node_modules/ms": { "node_modules/ms": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@ -1956,6 +1992,11 @@
"node": ">= 6" "node": ">= 6"
} }
}, },
"node_modules/obliterator": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.4.tgz",
"integrity": "sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ=="
},
"node_modules/on-exit-leak-free": { "node_modules/on-exit-leak-free": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz",

@ -8,6 +8,8 @@
}, },
"scripts": {}, "scripts": {},
"dependencies": { "dependencies": {
"@fastify/cors": "^9.0.1",
"@fastify/helmet": "^11.1.1",
"@fastify/static": "^7.0.0", "@fastify/static": "^7.0.0",
"commander": "^12.0.0", "commander": "^12.0.0",
"fast-glob": "^3.3.2", "fast-glob": "^3.3.2",

Loading…
Cancel
Save