feat: populate database function

This commit is contained in:
alok8bb 2022-07-10 00:26:51 +05:30
parent 899ffa1799
commit 68eebf1229
No known key found for this signature in database
GPG Key ID: 748A8580B906551C
5 changed files with 92 additions and 4 deletions

3
.gitignore vendored
View File

@ -2,4 +2,5 @@
node_modules/
public/
test/
data/
data/
words.txt

79
src/db/index.ts Normal file
View File

@ -0,0 +1,79 @@
import { logError, logSuccess, projectRoot } from "../utils";
import fs from "fs";
import path from "path";
import { Client, QueryResult } from "pg";
export const tableExists = async (db: Client): Promise<boolean> => {
const result = await db
.query(
"SELECT EXISTS (SELECT * FROM information_schema.tables WHERE table_name = 'words');"
)
.catch((err) => err);
return result.rows[0].exists;
};
// used for generating param query string
// expand(rowCount: 3, columnCount: 2) returns "($1, $2), ($3, $4), ($5, $6)"
function expand(rowCount: number, columnCount = 1, startAt = 1) {
var index = startAt;
return Array(rowCount)
.fill(0)
.map(
(v) =>
`(${Array(columnCount)
.fill(0)
.map((v) => `$${index++}`)
.join(", ")})`
)
.join(", ");
}
export const populateDB = async (db: Client) => {
let filename = "words.txt";
let filepath = path.join(projectRoot, filename);
// check for source file
if (!fs.existsSync(filepath)) {
logError(
"Could not find `okiba/words.txt` for populating the database!\n"
);
process.exit(1);
}
await db
.query(
"CREATE TABLE words (id SERIAL PRIMARY KEY, val VARCHAR NOT NULL, taken BOOLEAN DEFAULT 'f');"
)
.catch((err) => err);
fs.readFile(
filepath,
{ encoding: "utf-8" },
async (err: Error | null, data: string) => {
if (err != null) {
logError(err.message);
throw err;
}
let arr: Array<string> = data.split("\r\n");
// 1k entries per query
const chunkSize = 1000;
for (let i = 0; i < arr.length; i += chunkSize) {
const chunk: Array<string> = arr.slice(i, i + chunkSize);
const queryStr = {
text: `INSERT INTO words (val) VALUES ${expand(
chunk.length
)}`,
values: chunk,
};
await db.query(queryStr);
}
}
);
logSuccess("Successfully populated the database!");
};

View File

@ -3,14 +3,15 @@ import dotenv from "dotenv";
import BinRouter from "./routes/bin";
import { Client, Pool } from "pg";
import { createDataDir, errorHandler, logError, logSuccess } from "./utils";
import { tableExists, populateDB } from "./db";
const main = async () => {
dotenv.config();
createDataDir();
// init db
const pool = await new Pool();
const client = await new Client();
const pool = new Pool();
const client = new Client();
client
.connect()
@ -22,6 +23,12 @@ const main = async () => {
throw err;
});
// check if `words` table exists
// else populate db with `/okiba/words.txt`
if (!(await tableExists(client))) {
await populateDB(client);
}
// start server
const app: Express = express();
const port = process.env.PORT;

View File

@ -18,7 +18,7 @@ export default function BinRouter(db: Pool) {
const word: Word | undefined = await getAvailableWord(db);
if (word != undefined) {
await fs.writeFile(
fs.writeFile(
path.join(projectRoot, "data", word.val + ".txt"),
body,
(err) => err

View File

@ -6,6 +6,7 @@ import fs from "fs";
// logs
export const logError = (msg: string) => console.error(chalk.bold.red(msg));
export const logSuccess = (msg: string) => console.log(chalk.bold.green(msg));
export const logWarning = (msg: string) => console.log(chalk.bold.yellow(msg));
export const projectRoot = path.join(__dirname, "..", "..");