From 2da0ee24e4c08e2e84d9a8deff266a8df5f7948f Mon Sep 17 00:00:00 2001 From: Matt Date: Tue, 15 Apr 2025 15:33:50 -0400 Subject: [PATCH] add cli for admin tools --- cli/Dockerfile | 12 +++++ cli/index.js | 127 +++++++++++++++++++++++++++++++++++++++++++++++ cli/package.json | 18 +++++++ 3 files changed, 157 insertions(+) create mode 100644 cli/Dockerfile create mode 100644 cli/index.js create mode 100644 cli/package.json diff --git a/cli/Dockerfile b/cli/Dockerfile new file mode 100644 index 0000000..a5392c8 --- /dev/null +++ b/cli/Dockerfile @@ -0,0 +1,12 @@ +FROM node:lts-alpine3.17 + +# add project files to /app +ADD ./cli /app +ADD ./prisma /app/prisma +ADD ./mqtt/utils /app/utils +WORKDIR /app + +# install node dependencies +RUN npm install && npx prisma generate + +ENTRYPOINT ["node", "index.js"] diff --git a/cli/index.js b/cli/index.js new file mode 100644 index 0000000..e9fbbef --- /dev/null +++ b/cli/index.js @@ -0,0 +1,127 @@ +// node src/admin.js --purge-node-id 123 +// node src/admin.js --purge-node-id '!AABBCCDD' + +const commandLineArgs = require("command-line-args"); +const commandLineUsage = require("command-line-usage"); + +// create prisma db client +const { PrismaClient } = require("@prisma/client"); +const NodeIdUtil = require("./utils/node_id_util"); +const prisma = new PrismaClient(); + +const optionsList = [ + { + name: 'help', + alias: 'h', + type: Boolean, + description: 'Display this usage guide.' + }, + { + name: "purge-node-id", + type: String, + description: "Purges all records for the provided node id.", + }, +]; + +// parse command line args +const options = commandLineArgs(optionsList); + +// show help +if(options.help){ + const usage = commandLineUsage([ + { + header: 'Meshtastic Map Admin', + content: 'Command line admin tool for the Meshtastic Map', + }, + { + header: 'Options', + optionList: optionsList, + }, + ]); + console.log(usage); + return; +} + +// get options and fallback to default values +const purgeNodeId = options["purge-node-id"] ?? null; + +async function purgeNodeById(nodeId) { + + // convert to numeric id + nodeId = NodeIdUtil.convertToNumeric(nodeId); + + // purge environment metrics + await prisma.environmentMetric.deleteMany({ + where: { + node_id: nodeId, + }, + }); + + // purge map reports + await prisma.mapReport.deleteMany({ + where: { + node_id: nodeId, + }, + }); + + // purge neighbour infos + await prisma.neighbourInfo.deleteMany({ + where: { + node_id: nodeId, + }, + }); + + // purge this node + await prisma.node.deleteMany({ + where: { + node_id: nodeId, + }, + }); + + // purge positions + await prisma.position.deleteMany({ + where: { + node_id: nodeId, + }, + }); + + // purge power metrics + await prisma.powerMetric.deleteMany({ + where: { + node_id: nodeId, + }, + }); + + // purge text messages + await prisma.textMessage.deleteMany({ + where: { + from: nodeId, + }, + }); + + // purge traceroutes + await prisma.traceRoute.deleteMany({ + where: { + from: nodeId, + }, + }); + + // purge waypoints + await prisma.waypoint.deleteMany({ + where: { + from: nodeId, + }, + }); + + console.log(`✅ Node '${nodeId}' has been purged from the database.`); + +} + +(async () => { + + // purge node by id + if(purgeNodeId){ + await purgeNodeById(purgeNodeId); + } + +})(); diff --git a/cli/package.json b/cli/package.json new file mode 100644 index 0000000..454daa7 --- /dev/null +++ b/cli/package.json @@ -0,0 +1,18 @@ +{ + "name": "mqtt", + "version": "1.0.0", + "main": "index.js", + "author": "", + "license": "ISC", + "description": "", + "dependencies": { + "@prisma/client": "^5.11.0", + "command-line-args": "^5.2.1", + "command-line-usage": "^7.0.1", + "mqtt": "^5.11.0", + "protobufjs": "^7.5.0" + }, + "devDependencies": { + "prisma": "^5.10.2" + } +}