Replit Commit

This commit is contained in:
Dunemask 2022-05-05 12:35:47 +00:00
commit f49f965a42
41 changed files with 32720 additions and 0 deletions

View file

@ -0,0 +1,19 @@
CREATE SEQUENCE test_results_id_seq;
CREATE TABLE test_results (
id bigint NOT NULL DEFAULT nextval('test_results_seq') PRIMARY KEY,
test_name varchar(255) DEFAULT NULL,
test_class varchar(255) DEFAULT NULL,
test_method varchar(255) DEFAULT NULL,
test_path varchar(255) DEFAULT NULL,
test_type varchar(32) DEFAULT NULL,
test_timestamp timestamptz NOT NULL DEFAULT now(),
test_retry BOOLEAN DEFAULT FALSE,
origin varchar(255) DEFAULT NULL,
failed BOOLEAN DEFAULT FALSE,
failed_message varchar(2047) DEFAULT NULL,
screenshot_url varchar(255) DEFAULT NULL,
weblog_url varchar(255) DEFAULT NULL,
);
ALTER SEQUENCE test_results_id_seq OWNED BY test_results.id;

120
lib/database/pg-query.js Normal file
View file

@ -0,0 +1,120 @@
const buildPostgresEntry = (entry) => {
const pgEntry = { ...entry };
Object.keys(pgEntry).forEach((col) => {
if (pgEntry[col] === undefined) delete pgEntry[col];
});
return pgEntry;
};
export const buildPostgresValue = (jsVar) => {
if (jsVar === null) return "null";
if (typeof jsVar === "string") return buildPostgresString(jsVar);
if (Array.isArray(jsVar) && jsVar.length === 0) return "null";
if (Array.isArray(jsVar) && isTypeArray(jsVar, "string"))
return buildPostgresStringArray(jsVar);
return jsVar;
};
const buildPostgresStringArray = (jsonArray) => {
if (jsonArray.length === 0) return null;
var pgArray = [...jsonArray];
var arrayString = "ARRAY [";
pgArray.forEach((e, i) => (pgArray[i] = `'${e}'`));
arrayString += pgArray.join(",");
arrayString += "]";
return arrayString;
};
const isTypeArray = (jsonArray, type) =>
jsonArray.every((e) => typeof e === type);
const buildPostgresString = (jsonString) =>
(jsonString && `'${jsonString.replaceAll("'", "''")}'`) || null;
export const insertQuery = (table, jsEntry) => {
if (typeof jsEntry !== "object") throw Error("PG Inserts must be objects!");
const entry = buildPostgresEntry(jsEntry);
const cols = Object.keys(entry);
cols.forEach((col, i) => {
entry[col] = buildPostgresValue(entry[col]);
cols[i] = `"${col}"`;
});
var query = `INSERT INTO ${table}(${cols.join(",")})\n`;
query += `VALUES(${Object.values(entry).join(",")})`;
return query;
};
export const deleteQuery = (table, jsEntry) => {
if (typeof jsEntry !== "object")
throw Error("PG Delete conditionals must be an object!");
const entry = buildPostgresEntry(jsEntry);
const cols = Object.keys(entry);
const conditionals = [];
for (var col of cols) {
entry[col] = buildPostgresValue(entry[col]);
conditionals.push(`x.${col}=${entry[col]}`);
}
return `DELETE FROM ${table} x WHERE ${conditionals.join(" AND ")}`;
};
export const onConflictUpdate = (conflicts, updates) => {
if (!Array.isArray(conflicts)) throw Error("PG Conflicts must be an array!");
if (typeof updates !== "object") throw Error("PG Updates must be objects!");
const entry = buildPostgresEntry(updates);
var query = `ON CONFLICT (${conflicts.join(",")}) DO UPDATE SET\n`;
const cols = Object.keys(entry);
for (var col of cols) {
entry[col] = buildPostgresValue(entry[col]);
}
query += cols.map((c) => `${c}=${entry[c]}`).join(",");
return query;
};
export const clearTableQuery = (table) => {
return `TRUNCATE ${table}`;
};
export const selectWhereQuery = (table, jsEntry, joinWith) => {
if (typeof jsEntry !== "object") throw Error("PG Where must be an object!");
const where = buildPostgresEntry(jsEntry);
const cols = Object.keys(where);
var query = `SELECT * FROM ${table} AS x WHERE\n`;
for (var col of cols) {
where[col] = buildPostgresValue(where[col]);
}
return (query += cols.map((c) => `x.${c}=${where[c]}`).join(joinWith));
};
export const updateWhereQuery = (table, updates, wheres, joinWith) => {
if (typeof updates !== "object") throw Error("PG Updates must be an object!");
if (typeof wheres !== "object") throw Error("PG Wheres must be an object!");
const update = buildPostgresEntry(updates);
const where = buildPostgresEntry(wheres);
const updateCols = Object.keys(update);
const whereCols = Object.keys(where);
var query = `UPDATE ${table}\n`;
var updateQuery = updateCols
.map((c) => `${c} = ${buildPostgresValue(update[c])}`)
.join(",");
var whereQuery = whereCols
.map((c) => `${c} = ${buildPostgresValue(where[c])}`)
.join(joinWith);
return (query += `SET ${updateQuery} WHERE ${whereQuery}`);
};
export const updateWhereAnyQuery = (table, updates, wheres) =>
updateWhereQuery(table, updates, wheres, " OR ");
export const updateWhereAllQuery = (table, updates, wheres) =>
updateWhereQuery(table, updates, wheres, " AND ");
export const selectWhereAnyQuery = (table, where) =>
selectWhereQuery(table, where, " OR ");
export const selectWhereAllQuery = (table, where) =>
selectWhereQuery(table, where, " AND ");
export default {
selectWhereAnyQuery,
selectWhereAllQuery,
updateWhereAnyQuery,
updateWhereAllQuery,
insertQuery,
deleteQuery,
buildPostgresValue,
onConflictUpdate,
clearTableQuery,
};

47
lib/database/postgres.js Normal file
View file

@ -0,0 +1,47 @@
// Imports
import { migrate } from "postgres-migrations";
import createPgp from "pg-promise";
import moment from "moment";
import { WARN } from "../util/logging.js";
// Environment Variables
const {
POSTGRES_DATABASE: database,
POSTGRES_DISABLED: pgDisabled,
POSTGRES_HOST: host,
POSTGRES_PASSWORD: password,
POSTGRES_PORT: port,
POSTGRES_USER: user,
} = process.env;
// Postgres-promise Configuration
// Ensure dates get saved as UTC date strings
// This prevents the parser from doing strange datetime operations
const pgp = createPgp();
pgp.pg.types.setTypeParser(1114, (str) => moment.utc(str).format());
// Database Config
const dbConfig = {
database: database ?? "qualiteer",
user: user ?? "postgres",
password: password ?? "postgres",
host: host ?? "localhost",
port: port ?? 5432,
ensureDatabaseExists: true,
};
const migrationsDir = "lib/database/migrations";
const configure = async () => {
if (pgDisabled) {
WARN("POSTGRES", "Postgres Disabled!");
return { query: (str) => INFO("POSTGRES MOCK", str) };
}
await migrate(dbConfig, migrationsDir);
// Override the global variable DB
const pg = pgp(dbConfig);
await pg.connect();
OK("POSTGRES", `Connected to database ${database}!`);
return pg;
};
export default await configure();

View file

@ -0,0 +1,51 @@
import pg from "../postgres.js";
// Imports
import {
insertQuery,
selectWhereAnyQuery,
updateWhereAnyQuery,
} from "../pg-query.js";
// Constants
const table = "test_results";
// Queries
export const insertTestResult = (testResult) => {
const {
test_name,
test_class,
test_method,
test_path,
test_type,
test_timestamp,
test_retry,
origin,
failed,
failed_message,
screenshot_url,
expected_screenshot_url,
weblog_url,
} = testResult;
var query = insertQuery(table, {
test_name,
test_class,
test_method,
test_path,
test_type,
test_timestamp,
test_retry,
origin,
failed,
failed_message,
screenshot_url,
expected_screenshot_url,
weblog_url,
});
query += "\n RETURNING *";
return pg.query(query);
};
export const getCurrentlyFailing = () => {
const query = "SELECT *";
return pg.query(query);
};