205 lines
4.8 KiB
JavaScript
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();
|