oli-dbjson
Version:
Lets you make a db in json
347 lines (282 loc) • 8.47 kB
JavaScript
const readline = require('readline');
const dbjson = require('oli-dbjson');
const fs = require('fs');
const path = require('path');
const sqlite3 = require('sqlite3').verbose();
const color = {
reset: '\x1b[0m',
red: '\x1b[31m',
green: '\x1b[32m',
yellow: '\x1b[33m',
cyan: '\x1b[36m',
magenta: '\x1b[35m',
white: '\x1b[37m',
gray: '\x1b[90m',
};
function log(col, ...args) {
process.stdout.write(col);
console.log(...args);
process.stdout.write(color.reset);
}
function logInfo(...args) {
console.log(color.yellow, ...args, color.reset);
}
function logError(...args) {
console.error(color.red, ...args, color.reset);
}
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
let db;
async function start(dbFilePath) {
const dbPath = path.resolve(process.cwd(), dbFilePath);
if (!fs.existsSync(dbPath)) {
log(color.yellow, `[Oli-dbjson] Creating ${dbPath}...`);
} else {
log(color.cyan, `[Oli-dbjson] ${dbPath} already exists`);
}
return new Promise((resolve, reject) => {
db = new sqlite3.Database(dbPath, (err) => {
if (err) {
log(color.red, '[Oli-dbjson ERROR] Failed to open DB: ', color.white, err.message);
log(color.gray, err);
reject(err);
} else {
log(color.green, `[Oli-dbjson] Connected to ${dbPath}`);
resolve();
}
});
});
}
dbjson.start = start;
dbjson.addTable = async (name) => {
return Promise.resolve();
};
dbjson.search = async (table, query, options) => {
return [];
};
dbjson.add = async (table, data) => {
return 1;
};
dbjson.get = async (table, id) => {
return null;
};
dbjson.update = async (table, id, newData) => {
return;
};
dbjson.remove = async (table, id) => {
return;
};
dbjson.listTables = async () => {
return ['default'];
};
const commands = [
'.help', '.version', '.tables', '.table', '.list',
'.add', '.edit', '.remove', '.clear', '.exit'
];
function completer(line) {
const hits = commands.filter(c => c.startsWith(line));
return [hits.length ? hits : commands, line];
}
function printHelp() {
console.log(color.yellow,
`
Commands (commands start with a dot):
.help
Show this help message
.version
Show oli-dbjson version
.tables
List all tables
.table <table-name>
Select or create a table
.list
List entries in current table
.add <JSON data>
Add new entry (pass JSON object inline)
.edit <ID> <JSON data>
Edit entry by ID (pass JSON object inline)
.remove <ID>
Remove entry by ID
.clear
Clear the screen
.exit
Exit the editor
Note: You must select a table first using .table <name> before other table commands.
`,
color.reset);
}
async function main() {
const dbFilePath = process.argv[2];
if (!dbFilePath) {
logError('ERROR: You must specify a database file path as the first argument.');
logError('Usage: oli-dbjson <path/to/database.db>');
process.exit(1);
}
try {
await dbjson.start(dbFilePath);
} catch (err) {
logError('Failed to start DB:', err.message);
process.exit(1);
}
let currentTable = null;
logInfo('Welcome to oli-dbjson CLI. No table selected.');
logInfo('Use .table <name> to select or create a table.');
logInfo('Type .help for commands.');
await delay(1000);
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
prompt: `${color.green}oli-dbjson> ${color.reset}`,
completer: completer
});
rl.prompt();
rl.on('line', async (line) => {
const input = line.trim();
if (!input.startsWith('.')) {
logError('Commands must start with a dot (e.g. .list)');
rl.prompt();
return;
}
const spaceIndex = input.indexOf(' ');
let cmd, argsString;
if (spaceIndex === -1) {
cmd = input.slice(1).toLowerCase();
argsString = '';
} else {
cmd = input.slice(1, spaceIndex).toLowerCase();
argsString = input.slice(spaceIndex + 1).trim();
}
try {
switch (cmd) {
case 'help':
printHelp();
break;
case 'version':
logInfo('oli-dbjson version: 1.0.0');
break;
case 'tables':
{
const tables = await dbjson.listTables();
if (tables.length === 0) {
logInfo('(No tables found)');
} else {
logInfo('Tables:');
tables.forEach(t => console.log(`- ${t}`));
}
}
break;
case 'table':
if (!argsString) {
logError('Usage: .table <table-name>');
break;
}
await dbjson.addTable(argsString);
currentTable = argsString;
logInfo(`Selected table "${currentTable}"`);
break;
case 'list':
if (!currentTable) {
logError('No table selected. Use .table <name> first.');
break;
}
{
const results = await dbjson.search(currentTable, {}, { limit: 100 });
if (results.length === 0) {
logInfo('(No entries)');
} else {
logInfo(`Entries in table "${currentTable}":`);
results.forEach(({ id, data }) => {
console.log(`${color.magenta}ID ${id}:${color.reset}`, JSON.stringify(data, null, 2));
});
}
}
break;
case 'add':
if (!currentTable) {
logError('No table selected. Use .table <name> first.');
break;
}
if (!argsString) {
logError('Usage: .add <JSON data>');
break;
}
try {
const data = JSON.parse(argsString);
const id = await dbjson.add(currentTable, data);
logInfo(`Added entry with ID ${id}`);
} catch (err) {
logError('Invalid JSON:', err.message);
}
break;
case 'edit':
if (!currentTable) {
logError('No table selected. Use .table <name> first.');
break;
}
{
const firstSpace = argsString.indexOf(' ');
if (firstSpace === -1) {
logError('Usage: .edit <ID> <JSON data>');
break;
}
const idArg = argsString.slice(0, firstSpace);
const jsonArg = argsString.slice(firstSpace + 1).trim();
const id = Number(idArg);
if (isNaN(id)) {
logError('Invalid ID.');
break;
}
const entry = await dbjson.get(currentTable, id);
if (!entry) {
logError('Entry not found.');
break;
}
try {
const newData = JSON.parse(jsonArg);
await dbjson.update(currentTable, id, newData);
logInfo('Entry updated.');
} catch (err) {
logError('Invalid JSON:', err.message);
}
}
break;
case 'remove':
if (!currentTable) {
logError('No table selected. Use .table <name> first.');
break;
}
{
const id = Number(argsString);
if (isNaN(id)) {
logError('Usage: .remove <ID>');
break;
}
try {
await dbjson.remove(currentTable, id);
logInfo('Entry removed.');
} catch (e) {
logError('Error removing entry:', e.message);
}
}
break;
case 'clear':
process.stdout.write('\x1Bc');
break;
case 'exit':
logInfo('Exiting. Bye!');
rl.close();
return;
default:
logError('Unknown command. Type .help for list of commands.');
break;
}
} catch (err) {
logError('Error:', err.message);
}
rl.prompt();
});
rl.on('close', () => process.exit(0));
}
main();