mirror of
https://github.com/okiba-org/backend.git
synced 2025-02-22 09:12:06 +00:00
feat: populate database function
This commit is contained in:
parent
899ffa1799
commit
68eebf1229
1
.gitignore
vendored
1
.gitignore
vendored
@ -3,3 +3,4 @@ node_modules/
|
|||||||
public/
|
public/
|
||||||
test/
|
test/
|
||||||
data/
|
data/
|
||||||
|
words.txt
|
79
src/db/index.ts
Normal file
79
src/db/index.ts
Normal 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!");
|
||||||
|
};
|
11
src/main.ts
11
src/main.ts
@ -3,14 +3,15 @@ import dotenv from "dotenv";
|
|||||||
import BinRouter from "./routes/bin";
|
import BinRouter from "./routes/bin";
|
||||||
import { Client, Pool } from "pg";
|
import { Client, Pool } from "pg";
|
||||||
import { createDataDir, errorHandler, logError, logSuccess } from "./utils";
|
import { createDataDir, errorHandler, logError, logSuccess } from "./utils";
|
||||||
|
import { tableExists, populateDB } from "./db";
|
||||||
|
|
||||||
const main = async () => {
|
const main = async () => {
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
createDataDir();
|
createDataDir();
|
||||||
|
|
||||||
// init db
|
// init db
|
||||||
const pool = await new Pool();
|
const pool = new Pool();
|
||||||
const client = await new Client();
|
const client = new Client();
|
||||||
|
|
||||||
client
|
client
|
||||||
.connect()
|
.connect()
|
||||||
@ -22,6 +23,12 @@ const main = async () => {
|
|||||||
throw err;
|
throw err;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// check if `words` table exists
|
||||||
|
// else populate db with `/okiba/words.txt`
|
||||||
|
if (!(await tableExists(client))) {
|
||||||
|
await populateDB(client);
|
||||||
|
}
|
||||||
|
|
||||||
// start server
|
// start server
|
||||||
const app: Express = express();
|
const app: Express = express();
|
||||||
const port = process.env.PORT;
|
const port = process.env.PORT;
|
||||||
|
@ -18,7 +18,7 @@ export default function BinRouter(db: Pool) {
|
|||||||
const word: Word | undefined = await getAvailableWord(db);
|
const word: Word | undefined = await getAvailableWord(db);
|
||||||
|
|
||||||
if (word != undefined) {
|
if (word != undefined) {
|
||||||
await fs.writeFile(
|
fs.writeFile(
|
||||||
path.join(projectRoot, "data", word.val + ".txt"),
|
path.join(projectRoot, "data", word.val + ".txt"),
|
||||||
body,
|
body,
|
||||||
(err) => err
|
(err) => err
|
||||||
|
@ -6,6 +6,7 @@ import fs from "fs";
|
|||||||
// logs
|
// logs
|
||||||
export const logError = (msg: string) => console.error(chalk.bold.red(msg));
|
export const logError = (msg: string) => console.error(chalk.bold.red(msg));
|
||||||
export const logSuccess = (msg: string) => console.log(chalk.bold.green(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, "..", "..");
|
export const projectRoot = path.join(__dirname, "..", "..");
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user