Files
coins/bin/insert.mjs
T

205 lines
4.8 KiB
JavaScript

import fs from "fs/promises";
import path from "path";
import Database from "better-sqlite3";
const db = new Database("main.db");
db.pragma("journal_mode = WAL");
const omit = (data, keys = []) =>
Object.fromEntries(
Object.entries(data).filter(
([key, value]) =>
!keys.includes(key) &&
(typeof value === "number" || typeof value === "boolean" || !!value),
),
);
const exists = (table, primaryKey, value) => {
const stmt = `SELECT COUNT(*) count FROM ${table} WHERE ${primaryKey}=${
typeof value === "string" ? `'${value}'` : value
}`;
return db.prepare(stmt).get().count > 0;
};
const inserter = (table, data, primaryKey) => {
console.log();
if (primaryKey && exists(table, primaryKey, data[primaryKey])) {
console.log(`${table} ${data[primaryKey]} already exists`);
return;
}
const entries = Object.entries(data);
const stmt = `INSERT INTO ${table} (${entries
.map(([key]) => key)
.join(", ")}) VALUES (${entries
.map(([, value]) => {
if (Array.isArray(value)) {
return `'${value.join(", ").replaceAll("'", "''")}'`;
}
if (typeof value === "string") {
return `'${value.replaceAll("'", "''")}'`;
}
return value;
})
.join(", ")});`;
console.log(stmt);
db.exec(stmt);
};
const handleType = (type) => {
if (type.issuer) {
inserter("Issuer", omit(type.issuer), "code");
}
if (type.value) {
if (type.value.currency) {
inserter("Currency", omit(type.value.currency), "id");
}
inserter(
"Value",
omit(
{
...type.value,
currency_id: type.value.currency?.id,
id: type.id,
},
["currency"],
),
"id",
);
}
if (type.demonetization) {
inserter(
"Demonetization",
omit({ ...type.demonetization, id: type.id }),
"id",
);
}
if (type.composition) {
inserter("Composition", omit({ ...type.composition, id: type.id }), "id");
}
if (type.technique) {
inserter("Technique", omit({ ...type.technique, id: type.id }), "id");
}
if (type.obverse) {
inserter("Obverse", omit({ ...type.obverse, id: type.id }), "id");
}
if (type.reverse) {
inserter("Reverse", omit({ ...type.reverse, id: type.id }), "id");
}
if (type.edge) {
inserter("Edge", omit({ ...type.edge, id: type.id }), "id");
}
if (type.watermark) {
inserter("Watermark", omit({ ...type.watermark, id: type.id }), "id");
}
inserter(
"NumistaType",
omit(
{
...type,
issuer_code: type.issuer?.code,
count: type.count || 1,
...(type.value && { value_id: type.id }),
...(type.demonetization && { demonetization_id: type.id }),
...(type.composition && { composition_id: type.id }),
...(type.technique && { technique_id: type.id }),
...(type.obverse && { obverse_id: type.id }),
...(type.reverse && { reverse_id: type.id }),
...(type.edge && { edge_id: type.id }),
...(type.watermark && { watermark_id: type.id }),
},
[
"issuer",
"value",
"ruler",
"obverse",
"reverse",
"edge",
"watermark",
"tags",
"references",
"mints",
"printers",
"demonetization",
"composition",
"technique",
"related_types",
],
),
"id",
);
if (type.ruler?.length > 0) {
for (const ruler of type.ruler) {
if (ruler.group) {
inserter("RulerGroup", omit(ruler.group), "id");
}
inserter(
"Ruler",
omit(
{
...ruler,
group_id: ruler.group?.id,
},
["group"],
),
"id",
);
try {
inserter("TypeRuler", {
type_id: type.id,
ruler_id: ruler.id,
});
} catch {
//ok
}
}
}
};
const handleRelated = (type) => {
if (type.related_types?.length > 0) {
for (const related_type of type.related_types) {
if (exists("NumistaType", "id", related_type.id)) {
inserter(
"TypeRelated",
omit({
type1_id: type.id,
type2_id: related_type.id,
}),
);
}
}
}
};
const forEachType = async (callback) => {
for (const typeRoot of ["coins", "banknotes"]) {
for (const country of await fs.readdir(path.join("../public", typeRoot))) {
for (const typePath of (
await fs.readdir(path.join("../public", typeRoot, country))
).filter((filepath) => filepath.endsWith(".json"))) {
const type = JSON.parse(
await fs.readFile(
path.join("../public", typeRoot, country, typePath),
"utf-8",
),
);
callback(type);
}
}
}
};
await forEachType(handleType);
await forEachType(handleRelated);
db.close();