@lsbjordao/type-taxon-script 1.1.18 → 1.1.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/exportOntology.js +132 -41
- package/package.json +1 -1
package/dist/exportOntology.js
CHANGED
|
@@ -18,7 +18,7 @@ const child_process_1 = require("child_process");
|
|
|
18
18
|
const fast_glob_1 = __importDefault(require("fast-glob"));
|
|
19
19
|
const n3_1 = require("n3");
|
|
20
20
|
const tscBin = require.resolve('typescript/bin/tsc');
|
|
21
|
-
const { namedNode, literal,
|
|
21
|
+
const { namedNode, literal, blankNode } = n3_1.DataFactory;
|
|
22
22
|
const NS = {
|
|
23
23
|
tts: 'https://tts.example.org/ontology/',
|
|
24
24
|
inst: 'https://tts.example.org/instance/',
|
|
@@ -30,6 +30,7 @@ const NS = {
|
|
|
30
30
|
dcterms: 'http://purl.org/dc/terms/',
|
|
31
31
|
prov: 'http://www.w3.org/ns/prov#'
|
|
32
32
|
};
|
|
33
|
+
const ONTOLOGY_IRI = namedNode(NS.tts);
|
|
33
34
|
function tts(local) {
|
|
34
35
|
return namedNode(`${NS.tts}${encodeURIComponent(local)}`);
|
|
35
36
|
}
|
|
@@ -54,9 +55,6 @@ function xsd(local) {
|
|
|
54
55
|
function dcterms(local) {
|
|
55
56
|
return namedNode(`${NS.dcterms}${local}`);
|
|
56
57
|
}
|
|
57
|
-
function prov(local) {
|
|
58
|
-
return namedNode(`${NS.prov}${local}`);
|
|
59
|
-
}
|
|
60
58
|
function createWriter() {
|
|
61
59
|
return new n3_1.Writer({
|
|
62
60
|
prefixes: {
|
|
@@ -114,6 +112,9 @@ function toPascalLike(input) {
|
|
|
114
112
|
.replace(/[_\-\s]+([a-zA-Z0-9])/g, (_, c) => c.toUpperCase())
|
|
115
113
|
.replace(/^[a-z]/, c => c.toUpperCase());
|
|
116
114
|
}
|
|
115
|
+
function capitalize(input) {
|
|
116
|
+
return input.charAt(0).toUpperCase() + input.slice(1);
|
|
117
|
+
}
|
|
117
118
|
function localId(value, fallback) {
|
|
118
119
|
var _a, _b;
|
|
119
120
|
return (_b = (_a = value === null || value === void 0 ? void 0 : value._id) !== null && _a !== void 0 ? _a : value === null || value === void 0 ? void 0 : value.id) !== null && _b !== void 0 ? _b : fallback;
|
|
@@ -125,31 +126,78 @@ function primitiveToLiteral(value) {
|
|
|
125
126
|
return literal(String(value), xsd('decimal'));
|
|
126
127
|
return literal(String(value), xsd('boolean'));
|
|
127
128
|
}
|
|
129
|
+
function getLatestCharactersVersion() {
|
|
130
|
+
const baseDir = './characters';
|
|
131
|
+
if (!fs_1.default.existsSync(baseDir))
|
|
132
|
+
return null;
|
|
133
|
+
const versions = fs_1.default.readdirSync(baseDir)
|
|
134
|
+
.filter(d => /^v\d+$/.test(d))
|
|
135
|
+
.map(d => ({ dir: d, num: parseInt(d.slice(1), 10) }))
|
|
136
|
+
.sort((a, b) => b.num - a.num);
|
|
137
|
+
return versions.length > 0 ? versions[0].dir : null;
|
|
138
|
+
}
|
|
139
|
+
function shouldSkipClass(cls) {
|
|
140
|
+
return !cls.name || cls.name.startsWith('_');
|
|
141
|
+
}
|
|
142
|
+
function getRelationPredicateName(fieldName, relation) {
|
|
143
|
+
if (relation === null || relation === void 0 ? void 0 : relation.predicate)
|
|
144
|
+
return relation.predicate;
|
|
145
|
+
return `has${capitalize(fieldName)}`;
|
|
146
|
+
}
|
|
147
|
+
function getRelationAnchor(relation) {
|
|
148
|
+
// relationIri takes precedence — anchors directly to external ontology (e.g. RO)
|
|
149
|
+
if (relation === null || relation === void 0 ? void 0 : relation.relationIri) {
|
|
150
|
+
return namedNode(relation.relationIri);
|
|
151
|
+
}
|
|
152
|
+
// fallback to tts-local anchor based on relationType label
|
|
153
|
+
switch (relation === null || relation === void 0 ? void 0 : relation.relationType) {
|
|
154
|
+
case 'partOf':
|
|
155
|
+
return tts('partOf');
|
|
156
|
+
case 'hasComponent':
|
|
157
|
+
return tts('hasComponent');
|
|
158
|
+
case 'hasPart':
|
|
159
|
+
default:
|
|
160
|
+
return tts('hasPart');
|
|
161
|
+
}
|
|
162
|
+
}
|
|
128
163
|
function importModules(pattern) {
|
|
129
164
|
var _a, _b;
|
|
130
165
|
return __awaiter(this, void 0, void 0, function* () {
|
|
131
166
|
const tsFiles = yield (0, fast_glob_1.default)(pattern, { absolute: true });
|
|
132
167
|
if (tsFiles.length === 0)
|
|
133
168
|
return [];
|
|
134
|
-
const tempDir = path_1.default.join(process.cwd(), 'temp');
|
|
169
|
+
const tempDir = path_1.default.join(process.cwd(), '.tts-temp-ontology');
|
|
135
170
|
fs_1.default.mkdirSync(tempDir, { recursive: true });
|
|
136
171
|
const tempTsConfigPath = path_1.default.join(tempDir, 'tsconfig.ontology.json');
|
|
137
172
|
fs_1.default.writeFileSync(tempTsConfigPath, JSON.stringify({
|
|
138
|
-
compilerOptions: {
|
|
173
|
+
compilerOptions: {
|
|
174
|
+
target: 'ES2016',
|
|
175
|
+
module: 'commonjs',
|
|
176
|
+
esModuleInterop: true,
|
|
177
|
+
skipLibCheck: true,
|
|
178
|
+
outDir: tempDir,
|
|
179
|
+
rootDir: process.cwd()
|
|
180
|
+
},
|
|
139
181
|
files: tsFiles
|
|
140
182
|
}), 'utf-8');
|
|
141
183
|
try {
|
|
142
|
-
(0, child_process_1.execSync)(`node "${tscBin}" -p "${tempTsConfigPath}"
|
|
184
|
+
(0, child_process_1.execSync)(`node "${tscBin}" -p "${tempTsConfigPath}"`, { stdio: 'pipe' });
|
|
143
185
|
}
|
|
144
186
|
catch (e) {
|
|
145
|
-
|
|
187
|
+
cleanupTempDir(tempDir);
|
|
146
188
|
throw new Error(((_a = e.stdout) === null || _a === void 0 ? void 0 : _a.toString()) || ((_b = e.stderr) === null || _b === void 0 ? void 0 : _b.toString()) || e.message);
|
|
147
189
|
}
|
|
148
|
-
|
|
190
|
+
finally {
|
|
191
|
+
try {
|
|
192
|
+
fs_1.default.unlinkSync(tempTsConfigPath);
|
|
193
|
+
}
|
|
194
|
+
catch (_c) { }
|
|
195
|
+
}
|
|
149
196
|
const modules = [];
|
|
150
197
|
const jsFiles = [];
|
|
151
198
|
for (const file of tsFiles) {
|
|
152
|
-
const
|
|
199
|
+
const relative = path_1.default.relative(process.cwd(), file);
|
|
200
|
+
const jsFile = path_1.default.join(tempDir, relative.replace(/\.ts$/, '.js'));
|
|
153
201
|
jsFiles.push(jsFile);
|
|
154
202
|
modules.push({ file, mod: require(jsFile) });
|
|
155
203
|
}
|
|
@@ -157,23 +205,25 @@ function importModules(pattern) {
|
|
|
157
205
|
try {
|
|
158
206
|
fs_1.default.unlinkSync(jsFile);
|
|
159
207
|
}
|
|
160
|
-
catch (
|
|
161
|
-
}
|
|
162
|
-
try {
|
|
163
|
-
fs_1.default.rmdirSync(tempDir);
|
|
208
|
+
catch (_d) { }
|
|
164
209
|
}
|
|
165
|
-
|
|
210
|
+
cleanupTempDir(tempDir);
|
|
166
211
|
return modules;
|
|
167
212
|
});
|
|
168
213
|
}
|
|
169
|
-
function
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
214
|
+
function cleanupTempDir(tempDir) {
|
|
215
|
+
try {
|
|
216
|
+
fs_1.default.rmSync(tempDir, { recursive: true, force: true });
|
|
217
|
+
}
|
|
218
|
+
catch (_a) { }
|
|
219
|
+
}
|
|
220
|
+
function getPredicateForField(object, fieldName) {
|
|
221
|
+
var _a;
|
|
222
|
+
const ctor = object.constructor;
|
|
223
|
+
const rel = (_a = ctor === null || ctor === void 0 ? void 0 : ctor.semanticRelations) === null || _a === void 0 ? void 0 : _a[fieldName];
|
|
224
|
+
if (rel === null || rel === void 0 ? void 0 : rel.predicate)
|
|
225
|
+
return tts(rel.predicate);
|
|
226
|
+
return tts(fieldName);
|
|
177
227
|
}
|
|
178
228
|
function serializeSourceLikeArray(writer, subject, values) {
|
|
179
229
|
for (const v of values) {
|
|
@@ -214,7 +264,7 @@ function serializeObject(writer, subject, object, objectTypeName, objectId, visi
|
|
|
214
264
|
serializeSourceLikeArray(writer, subject, value);
|
|
215
265
|
continue;
|
|
216
266
|
}
|
|
217
|
-
const predicate =
|
|
267
|
+
const predicate = getPredicateForField(object, key);
|
|
218
268
|
if (isPrimitive(value)) {
|
|
219
269
|
writer.addQuad(subject, predicate, primitiveToLiteral(value));
|
|
220
270
|
continue;
|
|
@@ -244,20 +294,23 @@ function serializeObject(writer, subject, object, objectTypeName, objectId, visi
|
|
|
244
294
|
}
|
|
245
295
|
}
|
|
246
296
|
}
|
|
247
|
-
function getLatestCharactersVersion() {
|
|
248
|
-
const baseDir = './characters';
|
|
249
|
-
if (!fs_1.default.existsSync(baseDir))
|
|
250
|
-
return null;
|
|
251
|
-
const versions = fs_1.default.readdirSync(baseDir)
|
|
252
|
-
.filter(d => /^v\d+$/.test(d))
|
|
253
|
-
.map(d => ({ dir: d, num: parseInt(d.slice(1), 10) }))
|
|
254
|
-
.sort((a, b) => b.num - a.num);
|
|
255
|
-
return versions.length > 0 ? versions[0].dir : null;
|
|
256
|
-
}
|
|
257
297
|
function buildOntologyTTL() {
|
|
258
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
298
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
259
299
|
return __awaiter(this, void 0, void 0, function* () {
|
|
260
300
|
const writer = createWriter();
|
|
301
|
+
const seenClasses = new Set();
|
|
302
|
+
const seenDatatypeProperties = new Set();
|
|
303
|
+
const seenObjectProperties = new Set();
|
|
304
|
+
// Core generic relation properties (tts-local, subPropertyOf RO when relationIri is set per-class)
|
|
305
|
+
writer.addQuad(tts('hasPart'), rdf('type'), owl('ObjectProperty'));
|
|
306
|
+
writer.addQuad(tts('hasPart'), rdfs('label'), literal('has part', 'en'));
|
|
307
|
+
writer.addQuad(tts('hasPart'), rdfs('isDefinedBy'), ONTOLOGY_IRI);
|
|
308
|
+
writer.addQuad(tts('partOf'), rdf('type'), owl('ObjectProperty'));
|
|
309
|
+
writer.addQuad(tts('partOf'), rdfs('label'), literal('part of', 'en'));
|
|
310
|
+
writer.addQuad(tts('partOf'), rdfs('isDefinedBy'), ONTOLOGY_IRI);
|
|
311
|
+
writer.addQuad(tts('hasComponent'), rdf('type'), owl('ObjectProperty'));
|
|
312
|
+
writer.addQuad(tts('hasComponent'), rdfs('label'), literal('has component', 'en'));
|
|
313
|
+
writer.addQuad(tts('hasComponent'), rdfs('isDefinedBy'), ONTOLOGY_IRI);
|
|
261
314
|
const version = getLatestCharactersVersion();
|
|
262
315
|
if (!version) {
|
|
263
316
|
console.error('\x1b[31m✖ No versioned directory found under ./characters/\x1b[0m');
|
|
@@ -269,22 +322,34 @@ function buildOntologyTTL() {
|
|
|
269
322
|
if (!isClassLike(exported))
|
|
270
323
|
continue;
|
|
271
324
|
const cls = exported;
|
|
325
|
+
if (shouldSkipClass(cls))
|
|
326
|
+
continue;
|
|
327
|
+
if (seenClasses.has(cls.name))
|
|
328
|
+
continue;
|
|
329
|
+
seenClasses.add(cls.name);
|
|
272
330
|
const classNode = tts(cls.name);
|
|
273
331
|
writer.addQuad(classNode, rdf('type'), owl('Class'));
|
|
274
|
-
writer.addQuad(classNode,
|
|
332
|
+
writer.addQuad(classNode, rdf('type'), rdfs('Class'));
|
|
333
|
+
writer.addQuad(classNode, rdfs('isDefinedBy'), ONTOLOGY_IRI);
|
|
334
|
+
writer.addQuad(classNode, rdfs('label'), literal((_b = (_a = cls.semantic) === null || _a === void 0 ? void 0 : _a.label) !== null && _b !== void 0 ? _b : cls.name, 'en'));
|
|
275
335
|
if ((_c = cls.semantic) === null || _c === void 0 ? void 0 : _c.definition) {
|
|
276
|
-
writer.addQuad(classNode, rdfs('comment'), literal(cls.semantic.definition));
|
|
336
|
+
writer.addQuad(classNode, rdfs('comment'), literal(cls.semantic.definition, 'en'));
|
|
277
337
|
}
|
|
278
338
|
addMappings(writer, classNode, (_d = cls.semantic) === null || _d === void 0 ? void 0 : _d.ontologyMappings);
|
|
339
|
+
// Datatype / object properties from semanticAttributes
|
|
279
340
|
const attrs = (_e = cls.semanticAttributes) !== null && _e !== void 0 ? _e : {};
|
|
280
341
|
for (const [attrName, meta] of Object.entries(attrs)) {
|
|
342
|
+
if (seenDatatypeProperties.has(attrName))
|
|
343
|
+
continue;
|
|
344
|
+
seenDatatypeProperties.add(attrName);
|
|
281
345
|
const propNode = tts(attrName);
|
|
282
346
|
const kind = meta.kind === 'object' ? owl('ObjectProperty') : owl('DatatypeProperty');
|
|
283
347
|
writer.addQuad(propNode, rdf('type'), kind);
|
|
348
|
+
writer.addQuad(propNode, rdfs('isDefinedBy'), ONTOLOGY_IRI);
|
|
284
349
|
writer.addQuad(propNode, rdfs('domain'), classNode);
|
|
285
|
-
writer.addQuad(propNode, rdfs('label'), literal((_f = meta.label) !== null && _f !== void 0 ? _f : attrName));
|
|
350
|
+
writer.addQuad(propNode, rdfs('label'), literal((_f = meta.label) !== null && _f !== void 0 ? _f : attrName, 'en'));
|
|
286
351
|
if (meta.definition) {
|
|
287
|
-
writer.addQuad(propNode, rdfs('comment'), literal(meta.definition));
|
|
352
|
+
writer.addQuad(propNode, rdfs('comment'), literal(meta.definition, 'en'));
|
|
288
353
|
}
|
|
289
354
|
const dt = normalizeDatatype(meta.datatype);
|
|
290
355
|
if (dt) {
|
|
@@ -300,6 +365,31 @@ function buildOntologyTTL() {
|
|
|
300
365
|
}
|
|
301
366
|
}
|
|
302
367
|
}
|
|
368
|
+
// Structural class relations from semanticRelations
|
|
369
|
+
const rels = (_h = cls.semanticRelations) !== null && _h !== void 0 ? _h : {};
|
|
370
|
+
for (const [fieldName, rel] of Object.entries(rels)) {
|
|
371
|
+
const predicateName = getRelationPredicateName(fieldName, rel);
|
|
372
|
+
const propNode = tts(predicateName);
|
|
373
|
+
const targetNode = tts(rel.target);
|
|
374
|
+
if (!seenObjectProperties.has(predicateName)) {
|
|
375
|
+
seenObjectProperties.add(predicateName);
|
|
376
|
+
writer.addQuad(propNode, rdf('type'), owl('ObjectProperty'));
|
|
377
|
+
writer.addQuad(propNode, rdfs('isDefinedBy'), ONTOLOGY_IRI);
|
|
378
|
+
writer.addQuad(propNode, rdfs('label'), literal(predicateName, 'en'));
|
|
379
|
+
writer.addQuad(propNode, rdfs('domain'), classNode);
|
|
380
|
+
writer.addQuad(propNode, rdfs('range'), targetNode);
|
|
381
|
+
// subPropertyOf: points directly to RO IRI if provided,
|
|
382
|
+
// otherwise falls back to tts-local anchor (hasPart / partOf / hasComponent)
|
|
383
|
+
writer.addQuad(propNode, rdfs('subPropertyOf'), getRelationAnchor(rel));
|
|
384
|
+
// relationType as human-readable label on the anchor node (only when both fields present)
|
|
385
|
+
if (rel.relationType && rel.relationIri) {
|
|
386
|
+
writer.addQuad(namedNode(rel.relationIri), rdfs('label'), literal(rel.relationType, 'en'));
|
|
387
|
+
}
|
|
388
|
+
addMappings(writer, propNode, rel.ontologyMappings);
|
|
389
|
+
}
|
|
390
|
+
// explicit schema-level relation triple between classes
|
|
391
|
+
writer.addQuad(classNode, propNode, targetNode);
|
|
392
|
+
}
|
|
303
393
|
}
|
|
304
394
|
}
|
|
305
395
|
return writerToString(writer);
|
|
@@ -351,8 +441,9 @@ function ttsExportOntology(genus) {
|
|
|
351
441
|
console.error('\x1b[31m✖ Argument `--genus` cannot be empty.\x1b[0m');
|
|
352
442
|
return;
|
|
353
443
|
}
|
|
354
|
-
|
|
355
|
-
|
|
444
|
+
const version = getLatestCharactersVersion();
|
|
445
|
+
if (!version) {
|
|
446
|
+
console.error('\x1b[31m✖ No versioned directory (v1, v2, ...) found under ./characters/\x1b[0m');
|
|
356
447
|
return;
|
|
357
448
|
}
|
|
358
449
|
if (!fs_1.default.existsSync(`./taxon/${genus}`)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lsbjordao/type-taxon-script",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.19",
|
|
4
4
|
"author": "Lucas Jordão <tucarj@gmail.com> & André Eppinghaus <andreeppinghaus@gmail.com> & Vicente Calfo <vicentecalfo@gmail.com>",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"description": "TypeTaxonScript",
|