forked from Arkisto-Platform/ohrm-jsonld-exporter
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.js
159 lines (147 loc) · 5.62 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
import path from "path";
import fsExtraPkg from "fs-extra";
const { ensureDir, writeJSON } = fsExtraPkg;
import { Sequelize } from "sequelize";
import initModels from "./models/init-models.js";
import {
ArcResource,
DObject,
DObjectVersion,
EntityArchivalRelationship,
EntityDobjectRelationship,
EntityFunctionRelationship,
Entity,
EntityEvent,
EntityName,
Function,
PubResource,
RelatedEntity,
RelatedResource,
} from "./exporters/index.js";
import lodashPkg from "lodash";
const { isArray, union, clone, uniqBy } = lodashPkg;
import { ROCrate } from "ro-crate";
import * as configuration from "./configuration.js";
import yargs from "yargs/yargs";
const argv = yargs(process.argv.slice(2))
.scriptName("ohrm-jsonld-converter")
.usage("Usage: $0 -o output path")
.option("o", {
alias: "output-path",
describe: "A path to output the JSON-LD files",
type: "string",
})
.help().argv;
main();
async function main() {
let sequelize = new Sequelize(
configuration.databaseConfig.database,
configuration.databaseConfig.username,
configuration.databaseConfig.database,
{
host: configuration.databaseConfig.host,
dialect: "postgres",
logging: false,
}
);
try {
await sequelize.authenticate();
} catch (error) {
console.error(`Unable to connect to the database!`);
}
let models = initModels(sequelize);
if (argv.outputPath) await ensureDir(argv.outputPath);
const crate = new ROCrate({ array: true, link: true });
// the name property is where those entities will be attached to the root dataset
// so for example: ArchivalResources will be at crate.rootDataset.archivalResource
// TODO: (ptsefton) This might be better done with a generic hasPart relationship -- avoid a lot of extra props
// Included initially so that the data can be demonstrated with Describo and there would
// be entry points to each type of data from the root dataset.
const resources = [
{ obj: ArcResource, name: "archivalResources" },
{ obj: DObject, name: "digitalObjects" },
{ obj: DObjectVersion, name: "digitalObjectVersions" },
{ obj: EntityArchivalRelationship, name: "entityArchivalRelationships" },
{ obj: EntityDobjectRelationship, name: "entityDobjectRelationships" },
{ obj: EntityFunctionRelationship, name: "entityFunctionRelationships" },
{ obj: Entity, name: "entities" },
{ obj: EntityEvent, name: "entityEvent" },
{ obj: EntityName, name: "entityName" },
{ obj: Function, name: "entityFunction" },
{ obj: PubResource, name: "publishedResources" },
{ obj: RelatedEntity, name: "entityRelationships" },
{ obj: RelatedResource, name: "resourceRelationships" },
];
const typeMaps = {
Person: [],
Place: [],
State: [],
Country: [],
Nationality: [],
Contact: [],
};
// run all the exporters
let extractEntitiesOfType = Object.keys(typeMaps);
for (let { obj, name } of resources) {
let resource = new obj();
let entities = await resource.export({ models });
entities.forEach((entity) => {
if (extractEntitiesOfType.includes(entity["@type"])) {
typeMaps[entity["@type"]].push(entity);
} else {
crate.addEntity(entity);
}
});
crate.rootDataset[name] = entities
.filter((e) => !extractEntitiesOfType.includes(e["@type"]))
.map((e) => ({ "@id": e["@id"] }));
}
for (let type of Object.keys(typeMaps)) {
typeMaps[type] = uniqBy(typeMaps[type], "@id");
typeMaps[type].forEach((entity) => {
crate.addEntity(entity);
});
crate.rootDataset[type] = typeMaps[type].map((e) => ({ "@id": e["@id"] }));
}
// iterate over all entities of type Relationship and link the entity
// back to the related entities
var i = 0;
// PT: Added more informative names
for (let entity of crate.entities()) {
if (entity["@type"].includes("Relationship")) {
var relationshipName = "";
if (entity["@type"].length > 1) {
entity["@type"] = entity["@type"].filter((x) => x != "Relationship");
}
try {
let srcEntity = crate.getEntity(entity.source[0]["@id"]);
crate.addValues(srcEntity, "sourceOf", entity, false);
relationshipName += `${srcEntity.name} -> `;
} catch (error) {
// console.log(`Can't find source: ${entity.source[0]["@id"]}`);
crate.deleteEntity(entity);
continue;
// relationshipsToRemove.push(entity);
}
relationshipName += `${entity["@type"]} -> `;
try {
let tgtEntity = crate.getEntity(entity.target[0]["@id"]);
crate.addValues(tgtEntity, "targetOf", entity, false);
relationshipName += `${tgtEntity.name}`;
} catch (error) {
// console.log(`Can't find target: ${entity.target[0]["@id"]}`);
crate.deleteEntity(entity);
continue;
}
entity.name = relationshipName;
}
}
if (argv.outputPath) {
await ensureDir(argv.outputPath);
await writeJSON(path.join(argv.outputPath, "ro-crate-metadata.json"), crate, { spaces: 4 });
} else {
console.log(JSON.stringify(crate.toJSON(), null, 2));
}
await sequelize.close();
process.exit();
}