@larsgw/formica 0.8.4 → 0.8.6
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/.github/workflows/ci.yml +1 -1
- package/CHANGELOG.md +34 -0
- package/lib/bin/generate-linked-data.js +209 -328
- package/lib/bin/process-resources-index.js +59 -130
- package/lib/bin/process-resources.js +303 -524
- package/lib/bin/util.js +21 -56
- package/lib/bin/validate-catalog.js +26 -70
- package/lib/bin/validate-resources-text.js +17 -61
- package/lib/catalog/entities.js +28 -84
- package/lib/catalog/entity.js +36 -50
- package/lib/catalog/index.js +11 -12
- package/lib/catalog/tables/author.js +7 -24
- package/lib/catalog/tables/index.js +5 -5
- package/lib/catalog/tables/place.js +7 -24
- package/lib/catalog/tables/publisher.js +7 -24
- package/lib/catalog/tables/taxon.js +7 -24
- package/lib/catalog/tables/work.js +13 -30
- package/lib/catalog/value.js +11 -11
- package/lib/csv.js +7 -8
- package/lib/resources/diff-resource.js +52 -55
- package/lib/resources/parse-name.d.ts +6 -0
- package/lib/resources/parse-name.js +354 -0
- package/lib/resources/parse-text.js +185 -475
- package/lib/resources/resource.js +7 -25
- package/lib/taxon-names/index.js +15 -20
- package/package.json +2 -1
- package/src/bin/generate-linked-data.ts +8 -5
- package/src/bin/process-resources.ts +1 -1
- package/src/bin/validate-resources-text.ts +1 -1
- package/src/module.d.ts +4 -2
- package/src/resources/diff-resource.ts +19 -15
- package/src/resources/parse-name.ts +379 -0
- package/src/resources/parse-text.ts +150 -440
- package/test/resources.js +161 -17
- package/tsconfig.json +4 -1
|
@@ -1,16 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
-
var __assign = (this && this.__assign) || function () {
|
|
4
|
-
__assign = Object.assign || function(t) {
|
|
5
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
6
|
-
s = arguments[i];
|
|
7
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
8
|
-
t[p] = s[p];
|
|
9
|
-
}
|
|
10
|
-
return t;
|
|
11
|
-
};
|
|
12
|
-
return __assign.apply(this, arguments);
|
|
13
|
-
};
|
|
14
3
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
15
4
|
if (k2 === undefined) k2 = k;
|
|
16
5
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
@@ -53,48 +42,21 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
53
42
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
54
43
|
});
|
|
55
44
|
};
|
|
56
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
57
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
58
|
-
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
59
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
60
|
-
function step(op) {
|
|
61
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
62
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
63
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
64
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
65
|
-
switch (op[0]) {
|
|
66
|
-
case 0: case 1: t = op; break;
|
|
67
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
68
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
69
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
70
|
-
default:
|
|
71
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
72
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
73
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
74
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
75
|
-
if (t[2]) _.ops.pop();
|
|
76
|
-
_.trys.pop(); continue;
|
|
77
|
-
}
|
|
78
|
-
op = body.call(thisArg, _);
|
|
79
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
80
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
45
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
84
46
|
exports.ResourceProcessorSource = void 0;
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
47
|
+
const fs_1 = require("fs");
|
|
48
|
+
const path = __importStar(require("path"));
|
|
49
|
+
const child_process_1 = require("child_process");
|
|
50
|
+
const util = __importStar(require("util"));
|
|
51
|
+
const index_1 = require("../index");
|
|
52
|
+
const util_1 = require("./util");
|
|
91
53
|
var ResourceProcessorSource;
|
|
92
54
|
(function (ResourceProcessorSource) {
|
|
93
55
|
ResourceProcessorSource["All"] = "all";
|
|
94
56
|
ResourceProcessorSource["Unprocessed"] = "unprocessed";
|
|
95
57
|
ResourceProcessorSource["Modified"] = "modified";
|
|
96
58
|
})(ResourceProcessorSource || (exports.ResourceProcessorSource = ResourceProcessorSource = {}));
|
|
97
|
-
|
|
59
|
+
const DWC_FIELDS = [
|
|
98
60
|
'scientificNameID',
|
|
99
61
|
'scientificName',
|
|
100
62
|
'scientificNameAuthorship',
|
|
@@ -125,7 +87,7 @@ var DWC_FIELDS = [
|
|
|
125
87
|
'colAcceptedTaxonID',
|
|
126
88
|
'gbifAcceptedTaxonID'
|
|
127
89
|
];
|
|
128
|
-
|
|
90
|
+
const DISPLAY_FIELDS = [
|
|
129
91
|
'scientificNameID',
|
|
130
92
|
'taxonRank',
|
|
131
93
|
'scientificName',
|
|
@@ -134,7 +96,7 @@ var DISPLAY_FIELDS = [
|
|
|
134
96
|
'colTaxonID',
|
|
135
97
|
'gbifTaxonID'
|
|
136
98
|
];
|
|
137
|
-
|
|
99
|
+
const GBIF_RANKS = [
|
|
138
100
|
'kingdom',
|
|
139
101
|
'phyllum',
|
|
140
102
|
'class',
|
|
@@ -146,12 +108,12 @@ var GBIF_RANKS = [
|
|
|
146
108
|
'variety'
|
|
147
109
|
];
|
|
148
110
|
function runGnverifier(names) {
|
|
149
|
-
return new Promise(
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
proc.stdout.on('data',
|
|
111
|
+
return new Promise((resolve, reject) => {
|
|
112
|
+
const proc = (0, child_process_1.spawn)('gnverifier', ['-s', '1,11', '-f', 'compact', '-M']);
|
|
113
|
+
let stdout = '';
|
|
114
|
+
proc.stdout.on('data', data => { stdout += data; });
|
|
153
115
|
proc.stderr.pipe(process.stdout);
|
|
154
|
-
proc.on('close',
|
|
116
|
+
proc.on('close', code => {
|
|
155
117
|
if (code === 0) {
|
|
156
118
|
resolve(stdout);
|
|
157
119
|
}
|
|
@@ -164,489 +126,319 @@ function runGnverifier(names) {
|
|
|
164
126
|
});
|
|
165
127
|
}
|
|
166
128
|
function listFiles(directory) {
|
|
167
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
168
|
-
|
|
169
|
-
return
|
|
170
|
-
switch (_a.label) {
|
|
171
|
-
case 0: return [4 /*yield*/, fs_1.promises.readdir(directory)];
|
|
172
|
-
case 1:
|
|
173
|
-
input = _a.sent();
|
|
174
|
-
return [2 /*return*/, input.map(function (file) { return path.basename(file, '.txt'); }).sort(util_1.numericSort)];
|
|
175
|
-
}
|
|
176
|
-
});
|
|
129
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
130
|
+
const input = yield fs_1.promises.readdir(directory);
|
|
131
|
+
return input.map(file => path.basename(file, '.txt')).sort(util_1.numericSort);
|
|
177
132
|
});
|
|
178
133
|
}
|
|
179
134
|
function listUnprocessedFiles(directory, outputDirectory) {
|
|
180
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
case 0: return [4 /*yield*/, listFiles(directory)];
|
|
185
|
-
case 1:
|
|
186
|
-
input = _b.sent();
|
|
187
|
-
_a = Set.bind;
|
|
188
|
-
return [4 /*yield*/, fs_1.promises.readdir(outputDirectory)];
|
|
189
|
-
case 2:
|
|
190
|
-
output = new (_a.apply(Set, [void 0, _b.sent()]))();
|
|
191
|
-
return [2 /*return*/, input.filter(function (file) { return !output.has(file + '-1.csv'); })];
|
|
192
|
-
}
|
|
193
|
-
});
|
|
135
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
136
|
+
const input = yield listFiles(directory);
|
|
137
|
+
const output = new Set(yield fs_1.promises.readdir(outputDirectory));
|
|
138
|
+
return input.filter(file => !output.has(file + '-1.csv'));
|
|
194
139
|
});
|
|
195
140
|
}
|
|
196
141
|
function listChangedFiles(directory) {
|
|
197
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
switch (_a.label) {
|
|
201
|
-
case 0: return [4 /*yield*/, (0, util_1.runCommand)('git', ['diff', '--name-only', 'HEAD', '--', directory], {
|
|
202
|
-
cwd: directory
|
|
203
|
-
})];
|
|
204
|
-
case 1:
|
|
205
|
-
output = _a.sent();
|
|
206
|
-
return [2 /*return*/, output.trimEnd().split('\n').map(function (file) { return path.basename(file, '.txt'); }).sort(util_1.numericSort)];
|
|
207
|
-
}
|
|
142
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
143
|
+
const output = yield (0, util_1.runCommand)('git', ['diff', '--name-only', 'HEAD', '--', directory], {
|
|
144
|
+
cwd: directory
|
|
208
145
|
});
|
|
146
|
+
return output.trimEnd().split('\n').map(file => path.basename(file, '.txt')).sort(util_1.numericSort);
|
|
209
147
|
});
|
|
210
148
|
}
|
|
211
149
|
function getOldFile(file) {
|
|
212
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
cwd: path.dirname(file)
|
|
219
|
-
};
|
|
220
|
-
return [4 /*yield*/, (0, util_1.runCommand)('git', ['rev-parse', '--show-toplevel'], options)];
|
|
221
|
-
case 1:
|
|
222
|
-
gitRoot = (_a.sent()).trim();
|
|
223
|
-
return [4 /*yield*/, (0, util_1.runCommand)('git', ['show', 'HEAD:' + path.relative(gitRoot, file)], options)];
|
|
224
|
-
case 2: return [2 /*return*/, _a.sent()];
|
|
225
|
-
}
|
|
226
|
-
});
|
|
150
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
151
|
+
const options = {
|
|
152
|
+
cwd: path.dirname(file)
|
|
153
|
+
};
|
|
154
|
+
const gitRoot = (yield (0, util_1.runCommand)('git', ['rev-parse', '--show-toplevel'], options)).trim();
|
|
155
|
+
return yield (0, util_1.runCommand)('git', ['show', 'HEAD:' + path.relative(gitRoot, file)], options);
|
|
227
156
|
});
|
|
228
157
|
}
|
|
229
|
-
|
|
230
|
-
|
|
158
|
+
class ResourceProcessor {
|
|
159
|
+
constructor(collectionPath) {
|
|
231
160
|
this.DIR_ROOT = path.resolve(collectionPath);
|
|
232
161
|
this.DIR_TXT = path.join(this.DIR_ROOT, 'txt');
|
|
233
162
|
this.DIR_DWC = path.join(this.DIR_ROOT, 'dwc');
|
|
234
163
|
this.FILE_PROBLEMS = path.join(this.DIR_ROOT, 'problems.csv');
|
|
235
164
|
}
|
|
236
|
-
|
|
237
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
case 1:
|
|
243
|
-
ids = _a.sent();
|
|
244
|
-
_i = 0, ids_1 = ids;
|
|
245
|
-
_a.label = 2;
|
|
246
|
-
case 2:
|
|
247
|
-
if (!(_i < ids_1.length)) return [3 /*break*/, 5];
|
|
248
|
-
id = ids_1[_i];
|
|
249
|
-
return [4 /*yield*/, this.processWork(id, config)];
|
|
250
|
-
case 3:
|
|
251
|
-
_a.sent();
|
|
252
|
-
_a.label = 4;
|
|
253
|
-
case 4:
|
|
254
|
-
_i++;
|
|
255
|
-
return [3 /*break*/, 2];
|
|
256
|
-
case 5: return [2 /*return*/];
|
|
257
|
-
}
|
|
258
|
-
});
|
|
259
|
-
});
|
|
260
|
-
};
|
|
261
|
-
ResourceProcessor.prototype.listWorks = function (source) {
|
|
262
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
263
|
-
return __generator(this, function (_a) {
|
|
264
|
-
switch (source) {
|
|
265
|
-
case ResourceProcessorSource.All:
|
|
266
|
-
return [2 /*return*/, listFiles(this.DIR_TXT)];
|
|
267
|
-
case ResourceProcessorSource.Unprocessed:
|
|
268
|
-
return [2 /*return*/, listUnprocessedFiles(this.DIR_TXT, this.DIR_DWC)];
|
|
269
|
-
case ResourceProcessorSource.Modified:
|
|
270
|
-
return [2 /*return*/, listChangedFiles(this.DIR_TXT)];
|
|
271
|
-
default:
|
|
272
|
-
return [2 /*return*/, []];
|
|
273
|
-
}
|
|
274
|
-
return [2 /*return*/];
|
|
275
|
-
});
|
|
165
|
+
run(source, config) {
|
|
166
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
167
|
+
const ids = yield this.listWorks(source);
|
|
168
|
+
for (const id of ids) {
|
|
169
|
+
yield this.processWork(id, config);
|
|
170
|
+
}
|
|
276
171
|
});
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
var _loop_1 = function (id_1) {
|
|
291
|
-
var taxon = resource.taxa[id_1];
|
|
292
|
-
table.push(header.map(function (column) { return taxon[column] || ''; }));
|
|
293
|
-
};
|
|
294
|
-
for (var id_1 in resource.taxa) {
|
|
295
|
-
_loop_1(id_1);
|
|
296
|
-
}
|
|
297
|
-
return fs_1.promises.writeFile(path.join(_this.DIR_DWC, "".concat(resource.file, ".csv")), index_1.csv.formatCsv(table, ',').trim());
|
|
298
|
-
}))];
|
|
299
|
-
case 2:
|
|
300
|
-
_a.sent();
|
|
301
|
-
return [2 /*return*/];
|
|
302
|
-
}
|
|
303
|
-
});
|
|
172
|
+
}
|
|
173
|
+
listWorks(source) {
|
|
174
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
175
|
+
switch (source) {
|
|
176
|
+
case ResourceProcessorSource.All:
|
|
177
|
+
return listFiles(this.DIR_TXT);
|
|
178
|
+
case ResourceProcessorSource.Unprocessed:
|
|
179
|
+
return listUnprocessedFiles(this.DIR_TXT, this.DIR_DWC);
|
|
180
|
+
case ResourceProcessorSource.Modified:
|
|
181
|
+
return listChangedFiles(this.DIR_TXT);
|
|
182
|
+
default:
|
|
183
|
+
return [];
|
|
184
|
+
}
|
|
304
185
|
});
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
_i = 0, resources_1 = resources;
|
|
316
|
-
_b.label = 2;
|
|
317
|
-
case 2:
|
|
318
|
-
if (!(_i < resources_1.length)) return [3 /*break*/, 11];
|
|
319
|
-
resource = resources_1[_i];
|
|
320
|
-
return [4 /*yield*/, this.processResourceDwc(resource, config)];
|
|
321
|
-
case 3:
|
|
322
|
-
results = _b.sent();
|
|
323
|
-
return [4 /*yield*/, this.shouldBeSkipped(resource.id)];
|
|
324
|
-
case 4:
|
|
325
|
-
skip = _b.sent();
|
|
326
|
-
if (!!skip) return [3 /*break*/, 9];
|
|
327
|
-
correct = this.checkResults(results);
|
|
328
|
-
if (!!correct) return [3 /*break*/, 9];
|
|
329
|
-
return [4 /*yield*/, (0, util_1.promptForAnswers)("".concat(resource.workId, ": problems found in ").concat(resource.id, ". Skip or retry (s/r)? "), ['s', 'S', 'r', 'R'])];
|
|
330
|
-
case 5:
|
|
331
|
-
choice = _b.sent();
|
|
332
|
-
_a = choice;
|
|
333
|
-
switch (_a) {
|
|
334
|
-
case 's': return [3 /*break*/, 6];
|
|
335
|
-
case 'S': return [3 /*break*/, 6];
|
|
336
|
-
case 'r': return [3 /*break*/, 8];
|
|
337
|
-
case 'R': return [3 /*break*/, 8];
|
|
338
|
-
}
|
|
339
|
-
return [3 /*break*/, 9];
|
|
340
|
-
case 6: return [4 /*yield*/, (0, util_1.prompt)('Reason for skipping? ')];
|
|
341
|
-
case 7:
|
|
342
|
-
reason = _b.sent();
|
|
343
|
-
fs_1.promises.appendFile(this.FILE_PROBLEMS, index_1.csv.formatCsv([[
|
|
344
|
-
resource.workId,
|
|
345
|
-
resource.id,
|
|
346
|
-
reason
|
|
347
|
-
]]));
|
|
348
|
-
console.log("".concat(resource.workId, ": skipping ").concat(resource.id));
|
|
349
|
-
return [3 /*break*/, 9];
|
|
350
|
-
case 8:
|
|
351
|
-
{
|
|
352
|
-
console.log("".concat(resource.workId, ": retrying ").concat(resource.id));
|
|
353
|
-
return [2 /*return*/, this.processResources(id, config)];
|
|
354
|
-
}
|
|
355
|
-
_b.label = 9;
|
|
356
|
-
case 9:
|
|
357
|
-
amendedResources.push(results);
|
|
358
|
-
_b.label = 10;
|
|
359
|
-
case 10:
|
|
360
|
-
_i++;
|
|
361
|
-
return [3 /*break*/, 2];
|
|
362
|
-
case 11: return [2 /*return*/, amendedResources];
|
|
186
|
+
}
|
|
187
|
+
processWork(id, config) {
|
|
188
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
189
|
+
const resources = yield this.processResources(id, config);
|
|
190
|
+
yield Promise.all(resources.map(resource => {
|
|
191
|
+
const header = DWC_FIELDS;
|
|
192
|
+
const table = [header];
|
|
193
|
+
for (const id in resource.taxa) {
|
|
194
|
+
const taxon = resource.taxa[id];
|
|
195
|
+
table.push(header.map(column => taxon[column] || ''));
|
|
363
196
|
}
|
|
364
|
-
|
|
197
|
+
return fs_1.promises.writeFile(path.join(this.DIR_DWC, `${resource.file}.csv`), index_1.csv.formatCsv(table, ',').trim());
|
|
198
|
+
}));
|
|
365
199
|
});
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
_e = (_d = index_1.csv).parseCsv;
|
|
395
|
-
return [4 /*yield*/, getOldFile(filePath_1)];
|
|
396
|
-
case 4:
|
|
397
|
-
_c.apply(_b, [_e.apply(_d, [_g.sent()])]);
|
|
398
|
-
_g.label = 5;
|
|
399
|
-
case 5:
|
|
400
|
-
_i++;
|
|
401
|
-
return [3 /*break*/, 3];
|
|
402
|
-
case 6:
|
|
403
|
-
_f = {};
|
|
404
|
-
return [4 /*yield*/, getOldFile(filePath)];
|
|
405
|
-
case 7:
|
|
406
|
-
old = (_f.txt = _g.sent(), _f.dwc = dwc, _f);
|
|
407
|
-
_g.label = 8;
|
|
408
|
-
case 8: return [4 /*yield*/, Promise.resolve().then(function () { return __importStar(require('../index')); })];
|
|
409
|
-
case 9:
|
|
410
|
-
resources = (_g.sent()).resources;
|
|
411
|
-
return [2 /*return*/, resources.parseTextFile(file, id, old)];
|
|
412
|
-
case 10:
|
|
413
|
-
error_1 = _g.sent();
|
|
414
|
-
console.log(error_1);
|
|
415
|
-
return [4 /*yield*/, (0, util_1.prompt)("".concat(id, ": generating Darwin Core failed, retry? "))
|
|
416
|
-
// Clear cache to re-import
|
|
417
|
-
];
|
|
418
|
-
case 11:
|
|
419
|
-
_g.sent();
|
|
420
|
-
prefix = path.dirname(require.resolve('../index'));
|
|
421
|
-
for (file in require.cache) {
|
|
422
|
-
if (file.startsWith(prefix)) {
|
|
423
|
-
delete require.cache[file];
|
|
200
|
+
}
|
|
201
|
+
processResources(id, config) {
|
|
202
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
203
|
+
const resources = yield this.processResourceText(id, config);
|
|
204
|
+
const amendedResources = [];
|
|
205
|
+
for (const resource of resources) {
|
|
206
|
+
const results = yield this.processResourceDwc(resource, config);
|
|
207
|
+
const skip = yield this.shouldBeSkipped(resource.id);
|
|
208
|
+
if (!skip) {
|
|
209
|
+
const correct = this.checkResults(results);
|
|
210
|
+
if (!correct) {
|
|
211
|
+
const choice = yield (0, util_1.promptForAnswers)(`${resource.workId}: problems found in ${resource.id}. Skip or retry (s/r)? `, ['s', 'S', 'r', 'R']);
|
|
212
|
+
switch (choice) {
|
|
213
|
+
case 's':
|
|
214
|
+
case 'S': {
|
|
215
|
+
const reason = yield (0, util_1.prompt)('Reason for skipping? ');
|
|
216
|
+
fs_1.promises.appendFile(this.FILE_PROBLEMS, index_1.csv.formatCsv([[
|
|
217
|
+
resource.workId,
|
|
218
|
+
resource.id,
|
|
219
|
+
reason
|
|
220
|
+
]]));
|
|
221
|
+
console.log(`${resource.workId}: skipping ${resource.id}`);
|
|
222
|
+
break;
|
|
223
|
+
}
|
|
224
|
+
case 'r':
|
|
225
|
+
case 'R': {
|
|
226
|
+
console.log(`${resource.workId}: retrying ${resource.id}`);
|
|
227
|
+
return this.processResources(id, config);
|
|
424
228
|
}
|
|
425
229
|
}
|
|
426
|
-
|
|
427
|
-
case 12: return [2 /*return*/];
|
|
230
|
+
}
|
|
428
231
|
}
|
|
429
|
-
|
|
232
|
+
amendedResources.push(results);
|
|
233
|
+
}
|
|
234
|
+
return amendedResources;
|
|
430
235
|
});
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
_a = _c.apply(_b, [_l.sent()]), header_1 = _a[0], rows = _a.slice(1);
|
|
446
|
-
for (_i = 0, rows_1 = rows; _i < rows_1.length; _i++) {
|
|
447
|
-
row = rows_1[_i];
|
|
448
|
-
oldTaxon = row.reduce(function (taxon, value, index) {
|
|
449
|
-
taxon[header_1[index]] = value;
|
|
450
|
-
return taxon;
|
|
451
|
-
}, {});
|
|
452
|
-
taxon = resource.taxa[oldTaxon.scientificNameID];
|
|
453
|
-
if (taxon) {
|
|
454
|
-
taxon.colTaxonID = oldTaxon.colTaxonID;
|
|
455
|
-
taxon.colAcceptedTaxonID = oldTaxon.colAcceptedTaxonID;
|
|
456
|
-
taxon.gbifTaxonID = oldTaxon.gbifTaxonID;
|
|
457
|
-
taxon.gbifAcceptedTaxonID = oldTaxon.gbifAcceptedTaxonID;
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
_l.label = 2;
|
|
461
|
-
case 2: return [2 /*return*/, resource];
|
|
462
|
-
case 3:
|
|
463
|
-
filteredResults = {};
|
|
464
|
-
taxonNames = {};
|
|
465
|
-
names = new Set();
|
|
466
|
-
for (id in resource.taxa) {
|
|
467
|
-
name_1 = resource.taxa[id].scientificName;
|
|
468
|
-
if (!taxonNames[name_1]) {
|
|
469
|
-
taxonNames[name_1] = [];
|
|
470
|
-
}
|
|
471
|
-
taxonNames[name_1].push(id);
|
|
472
|
-
names.add(name_1);
|
|
473
|
-
filteredResults[id] = [];
|
|
474
|
-
}
|
|
475
|
-
return [4 /*yield*/, runGnverifier(Array.from(names).join('\n'))];
|
|
476
|
-
case 4:
|
|
477
|
-
result = _l.sent();
|
|
478
|
-
_loop_2 = function (results) {
|
|
479
|
-
var _m = JSON.parse(results), name_2 = _m.name, matches = _m.results;
|
|
480
|
-
if (!matches) {
|
|
481
|
-
return "continue";
|
|
482
|
-
}
|
|
483
|
-
// Fix author scoring for some species, see https://github.com/gnames/gnverifier/issues/129
|
|
484
|
-
matches.sort(function (a, b) {
|
|
485
|
-
if (a.sortScore !== b.sortScore) {
|
|
486
|
-
return b.sortScore - a.sortScore;
|
|
487
|
-
}
|
|
488
|
-
return name_2 === a.matchedName ? -1 : name_2 === b.matchedName ? 1 : 0;
|
|
489
|
-
});
|
|
490
|
-
for (var _o = 0, _p = matches; _o < _p.length; _o++) {
|
|
491
|
-
var match = _p[_o];
|
|
492
|
-
var source = match.dataSourceId;
|
|
493
|
-
var currentRank = match.classificationRanks.split('|').pop();
|
|
494
|
-
if (match.scoreDetails.cardinalityScore === 0) {
|
|
495
|
-
// Rank mismatch
|
|
496
|
-
continue;
|
|
497
|
-
}
|
|
498
|
-
else if (source === 11 && currentRank === 'species' && match.classificationPath.endsWith(' spec')) {
|
|
499
|
-
// GBIF species like "Nomada spec"
|
|
500
|
-
continue;
|
|
501
|
-
}
|
|
502
|
-
for (var _q = 0, _r = taxonNames[name_2]; _q < _r.length; _q++) {
|
|
503
|
-
var loirId = _r[_q];
|
|
504
|
-
var taxon = resource.taxa[loirId];
|
|
505
|
-
if (source === 11 && !GBIF_RANKS.includes(taxon.taxonRank)) {
|
|
506
|
-
// Exclude GBIF matches for ranks that are not in GBIF
|
|
507
|
-
continue;
|
|
508
|
-
}
|
|
509
|
-
else if (source === 11 && !match.isSynonym && currentRank !== taxon.taxonRank) {
|
|
510
|
-
// Exclude matches with rank mismatches (only possible
|
|
511
|
-
// for non-synonyms).
|
|
512
|
-
continue;
|
|
513
|
-
}
|
|
514
|
-
if (!filteredResults[loirId]) {
|
|
515
|
-
filteredResults[loirId] = [];
|
|
516
|
-
}
|
|
517
|
-
filteredResults[loirId].push({
|
|
518
|
-
source: source,
|
|
519
|
-
id: match.recordId,
|
|
520
|
-
currentId: match.currentRecordId,
|
|
521
|
-
classificationPath: match.classificationPath.split('|')
|
|
522
|
-
});
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
};
|
|
526
|
-
for (_d = 0, _e = result.trim().split('\n'); _d < _e.length; _d++) {
|
|
527
|
-
results = _e[_d];
|
|
528
|
-
_loop_2(results);
|
|
236
|
+
}
|
|
237
|
+
processResourceText(id, config) {
|
|
238
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
239
|
+
try {
|
|
240
|
+
console.log(`${id}: generating Darwin Core`);
|
|
241
|
+
const filePath = path.join(this.DIR_TXT, id + '.txt');
|
|
242
|
+
const file = yield fs_1.promises.readFile(filePath, 'utf-8');
|
|
243
|
+
let old = undefined;
|
|
244
|
+
if (config.update) {
|
|
245
|
+
const dwc = [];
|
|
246
|
+
for (const file of yield fs_1.promises.readdir(this.DIR_DWC)) {
|
|
247
|
+
if (file.startsWith(id + '-')) {
|
|
248
|
+
const filePath = path.join(this.DIR_DWC, file);
|
|
249
|
+
dwc.push(index_1.csv.parseCsv(yield getOldFile(filePath)));
|
|
529
250
|
}
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
_f = (_l.sent()).taxonNames, amendResource = _f.amendResource, groupNameMatches = _f.groupNameMatches;
|
|
533
|
-
groupedNameMatches = groupNameMatches(filteredResults);
|
|
534
|
-
amendedResource = __assign(__assign({}, resource), { taxa: __assign({}, resource.taxa) });
|
|
535
|
-
_g = groupedNameMatches;
|
|
536
|
-
_h = [];
|
|
537
|
-
for (_j in _g)
|
|
538
|
-
_h.push(_j);
|
|
539
|
-
_k = 0;
|
|
540
|
-
_l.label = 6;
|
|
541
|
-
case 6:
|
|
542
|
-
if (!(_k < _h.length)) return [3 /*break*/, 9];
|
|
543
|
-
_j = _h[_k];
|
|
544
|
-
if (!(_j in _g)) return [3 /*break*/, 8];
|
|
545
|
-
source = _j;
|
|
546
|
-
return [4 /*yield*/, this.selectPrefixes(resource, groupedNameMatches, source)];
|
|
547
|
-
case 7:
|
|
548
|
-
matches = _l.sent();
|
|
549
|
-
amendResource(amendedResource, source, matches);
|
|
550
|
-
_l.label = 8;
|
|
551
|
-
case 8:
|
|
552
|
-
_k++;
|
|
553
|
-
return [3 /*break*/, 6];
|
|
554
|
-
case 9: return [2 /*return*/, amendedResource];
|
|
251
|
+
}
|
|
252
|
+
old = { txt: yield getOldFile(filePath), dwc };
|
|
555
253
|
}
|
|
556
|
-
|
|
254
|
+
const { resources } = yield Promise.resolve().then(() => __importStar(require('../index')));
|
|
255
|
+
return resources.parseTextFile(file, id, old);
|
|
256
|
+
}
|
|
257
|
+
catch (error) {
|
|
258
|
+
console.log(error.message);
|
|
259
|
+
yield (0, util_1.prompt)(`${id}: generating Darwin Core failed, retry? `);
|
|
260
|
+
// Clear cache to re-import
|
|
261
|
+
const prefix = path.dirname(require.resolve('../index'));
|
|
262
|
+
for (const file in require.cache) {
|
|
263
|
+
if (file.startsWith(prefix)) {
|
|
264
|
+
delete require.cache[file];
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return this.processResourceText(id, config);
|
|
268
|
+
}
|
|
557
269
|
});
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
missedTaxonCount = Object.keys(mappedTaxa).length - Object.keys(groupedNameMatches[source][prefixes[0]]).length;
|
|
580
|
-
if (missedTaxonCount === 0) {
|
|
581
|
-
// Multiple prefixes but the first one maps all taxa (not counting that are unmapped in all prefixes)
|
|
582
|
-
return [2 /*return*/, groupedNameMatches[source][prefixes[0]]];
|
|
270
|
+
}
|
|
271
|
+
processResourceDwc(resource, config) {
|
|
272
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
273
|
+
console.log(`${resource.workId}: matching ${resource.id}`);
|
|
274
|
+
if (!config.updateMappings) {
|
|
275
|
+
const file = path.join(this.DIR_DWC, resource.file + '.csv');
|
|
276
|
+
if ((0, fs_1.existsSync)(file)) {
|
|
277
|
+
const [header, ...rows] = index_1.csv.parseCsv(yield fs_1.promises.readFile(file, 'utf-8'));
|
|
278
|
+
for (const row of rows) {
|
|
279
|
+
const oldTaxon = row.reduce((taxon, value, index) => {
|
|
280
|
+
taxon[header[index]] = value;
|
|
281
|
+
return taxon;
|
|
282
|
+
}, {});
|
|
283
|
+
const taxon = resource.taxa[oldTaxon.scientificNameID];
|
|
284
|
+
if (taxon) {
|
|
285
|
+
taxon.colTaxonID = oldTaxon.colTaxonID;
|
|
286
|
+
taxon.colAcceptedTaxonID = oldTaxon.colAcceptedTaxonID;
|
|
287
|
+
taxon.gbifTaxonID = oldTaxon.gbifTaxonID;
|
|
288
|
+
taxon.gbifAcceptedTaxonID = oldTaxon.gbifAcceptedTaxonID;
|
|
583
289
|
}
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
return resource;
|
|
293
|
+
}
|
|
294
|
+
const filteredResults = {};
|
|
295
|
+
const taxonNames = {};
|
|
296
|
+
const names = new Set();
|
|
297
|
+
for (const id in resource.taxa) {
|
|
298
|
+
const name = resource.taxa[id].scientificName;
|
|
299
|
+
if (!taxonNames[name]) {
|
|
300
|
+
taxonNames[name] = [];
|
|
301
|
+
}
|
|
302
|
+
taxonNames[name].push(id);
|
|
303
|
+
names.add(name);
|
|
304
|
+
filteredResults[id] = [];
|
|
305
|
+
}
|
|
306
|
+
const result = yield runGnverifier(Array.from(names).join('\n'));
|
|
307
|
+
for (const results of result.trim().split('\n')) {
|
|
308
|
+
const { name, results: matches } = JSON.parse(results);
|
|
309
|
+
if (!matches) {
|
|
310
|
+
continue;
|
|
311
|
+
}
|
|
312
|
+
// Fix author scoring for some species, see https://github.com/gnames/gnverifier/issues/129
|
|
313
|
+
matches.sort((a, b) => {
|
|
314
|
+
if (a.sortScore !== b.sortScore) {
|
|
315
|
+
return b.sortScore - a.sortScore;
|
|
316
|
+
}
|
|
317
|
+
return name === a.matchedName ? -1 : name === b.matchedName ? 1 : 0;
|
|
318
|
+
});
|
|
319
|
+
for (const match of matches) {
|
|
320
|
+
const source = match.dataSourceId;
|
|
321
|
+
const currentRank = match.classificationRanks.split('|').pop();
|
|
322
|
+
if (match.scoreDetails.cardinalityScore === 0) {
|
|
323
|
+
// Rank mismatch
|
|
324
|
+
continue;
|
|
325
|
+
}
|
|
326
|
+
else if (source === 11 && currentRank === 'species' && match.classificationPath.endsWith(' spec')) {
|
|
327
|
+
// GBIF species like "Nomada spec"
|
|
328
|
+
continue;
|
|
329
|
+
}
|
|
330
|
+
for (const loirId of taxonNames[name]) {
|
|
331
|
+
const taxon = resource.taxa[loirId];
|
|
332
|
+
if (source === 11 && !GBIF_RANKS.includes(taxon.taxonRank)) {
|
|
333
|
+
// Exclude GBIF matches for ranks that are not in GBIF
|
|
334
|
+
continue;
|
|
609
335
|
}
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
_c.label = 5;
|
|
615
|
-
case 5:
|
|
616
|
-
if (!/^(|\d+(,\d+)*)$/.test(choice)) return [3 /*break*/, 3];
|
|
617
|
-
_c.label = 6;
|
|
618
|
-
case 6:
|
|
619
|
-
console.error(" Applying selection...");
|
|
620
|
-
if (choice === '') {
|
|
621
|
-
return [2 /*return*/, {}];
|
|
336
|
+
else if (source === 11 && !match.isSynonym && currentRank !== taxon.taxonRank) {
|
|
337
|
+
// Exclude matches with rank mismatches (only possible
|
|
338
|
+
// for non-synonyms).
|
|
339
|
+
continue;
|
|
622
340
|
}
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
i = _b[_a];
|
|
626
|
-
prefix = prefixes[parseInt(i) - 1];
|
|
627
|
-
taxa = groupedNameMatches[source][prefix];
|
|
628
|
-
for (id in taxa) {
|
|
629
|
-
if (id in matches) {
|
|
630
|
-
continue;
|
|
631
|
-
}
|
|
632
|
-
matches[id] = taxa[id];
|
|
633
|
-
}
|
|
341
|
+
if (!filteredResults[loirId]) {
|
|
342
|
+
filteredResults[loirId] = [];
|
|
634
343
|
}
|
|
635
|
-
|
|
344
|
+
filteredResults[loirId].push({
|
|
345
|
+
source,
|
|
346
|
+
id: match.recordId,
|
|
347
|
+
currentId: match.currentRecordId,
|
|
348
|
+
classificationPath: match.classificationPath.split('|')
|
|
349
|
+
});
|
|
350
|
+
}
|
|
636
351
|
}
|
|
637
|
-
}
|
|
352
|
+
}
|
|
353
|
+
const { taxonNames: { amendResource, groupNameMatches } } = yield Promise.resolve().then(() => __importStar(require('../index')));
|
|
354
|
+
const groupedNameMatches = groupNameMatches(filteredResults);
|
|
355
|
+
const amendedResource = Object.assign(Object.assign({}, resource), { taxa: Object.assign({}, resource.taxa) });
|
|
356
|
+
for (const source in groupedNameMatches) {
|
|
357
|
+
const matches = yield this.selectPrefixes(resource, groupedNameMatches, source);
|
|
358
|
+
amendResource(amendedResource, source, matches);
|
|
359
|
+
}
|
|
360
|
+
return amendedResource;
|
|
638
361
|
});
|
|
639
|
-
}
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
362
|
+
}
|
|
363
|
+
selectPrefixes(resource, groupedNameMatches, source) {
|
|
364
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
365
|
+
const prefixes = Object.keys(groupedNameMatches[source]);
|
|
366
|
+
if (prefixes.length === 0) {
|
|
367
|
+
return {};
|
|
368
|
+
}
|
|
369
|
+
else if (prefixes.length === 1) {
|
|
370
|
+
return groupedNameMatches[source][prefixes[0]];
|
|
371
|
+
}
|
|
372
|
+
// Count total mapped taxa
|
|
373
|
+
const mappedTaxa = {};
|
|
374
|
+
for (const prefix of prefixes) {
|
|
375
|
+
for (const taxon in groupedNameMatches[source][prefix]) {
|
|
376
|
+
mappedTaxa[taxon] = true;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
const missedTaxonCount = Object.keys(mappedTaxa).length - Object.keys(groupedNameMatches[source][prefixes[0]]).length;
|
|
380
|
+
if (missedTaxonCount === 0) {
|
|
381
|
+
// Multiple prefixes but the first one maps all taxa (not counting that are unmapped in all prefixes)
|
|
382
|
+
return groupedNameMatches[source][prefixes[0]];
|
|
383
|
+
}
|
|
384
|
+
console.error(`${resource.workId}: source ${source} results in multiple prefixes`);
|
|
385
|
+
let choice;
|
|
386
|
+
if (missedTaxonCount <= 5) {
|
|
387
|
+
console.error(` Most common prefix misses ${missedTaxonCount} taxa: automatically selecting most common prefix...`);
|
|
388
|
+
choice = '1';
|
|
389
|
+
}
|
|
390
|
+
else if (source === '1') {
|
|
391
|
+
console.error(` Catalogue of Life: automatically selecting most common prefix...`);
|
|
392
|
+
choice = '1';
|
|
393
|
+
}
|
|
394
|
+
else {
|
|
395
|
+
for (let i = 0; i < prefixes.length; i++) {
|
|
396
|
+
const prefix = prefixes[i];
|
|
397
|
+
const taxa = groupedNameMatches[source][prefix];
|
|
398
|
+
const taxonIds = Object.keys(taxa);
|
|
399
|
+
console.error(` [${i + 1}] ${prefix} (${taxonIds.length} taxa)`);
|
|
400
|
+
for (let j = 0; j < Math.min(9, taxonIds.length); j++) {
|
|
401
|
+
const taxonId = taxonIds[j];
|
|
402
|
+
const taxon = resource.taxa[taxonId];
|
|
403
|
+
const match = taxa[taxonId];
|
|
404
|
+
console.error(` taxon: ${taxonId} "${taxon.scientificName}" - ${match.classificationPath.join('|')}`);
|
|
405
|
+
}
|
|
406
|
+
if (taxonIds.length > 9) {
|
|
407
|
+
console.error(` ...`);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
do {
|
|
411
|
+
choice = yield (0, util_1.prompt)(` Select prefixes (1-${prefixes.length})? `);
|
|
412
|
+
} while (!/^(|\d+(,\d+)*)$/.test(choice));
|
|
413
|
+
}
|
|
414
|
+
console.error(` Applying selection...`);
|
|
415
|
+
if (choice === '') {
|
|
416
|
+
return {};
|
|
417
|
+
}
|
|
418
|
+
const matches = {};
|
|
419
|
+
for (const i of choice.split(',')) {
|
|
420
|
+
const prefix = prefixes[parseInt(i) - 1];
|
|
421
|
+
const taxa = groupedNameMatches[source][prefix];
|
|
422
|
+
for (const id in taxa) {
|
|
423
|
+
if (id in matches) {
|
|
424
|
+
continue;
|
|
425
|
+
}
|
|
426
|
+
matches[id] = taxa[id];
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
return matches;
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
checkResults(resource) {
|
|
433
|
+
let correct = true;
|
|
434
|
+
const missing = [];
|
|
435
|
+
for (const id in resource.taxa) {
|
|
436
|
+
const taxon = resource.taxa[id];
|
|
645
437
|
if (taxon.taxonomicStatus !== 'accepted') {
|
|
646
438
|
continue;
|
|
647
439
|
}
|
|
648
|
-
|
|
649
|
-
|
|
440
|
+
const missingCol = false; // !taxon.colTaxonID
|
|
441
|
+
const missingGbif = GBIF_RANKS.includes(taxon.taxonRank) && !taxon.gbifTaxonID;
|
|
650
442
|
if (missingCol || missingGbif) {
|
|
651
443
|
correct = false;
|
|
652
444
|
missing.push(taxon);
|
|
@@ -656,29 +448,16 @@ var ResourceProcessor = /** @class */ (function () {
|
|
|
656
448
|
console.table(missing, DISPLAY_FIELDS);
|
|
657
449
|
}
|
|
658
450
|
return correct;
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
662
|
-
|
|
663
|
-
return
|
|
664
|
-
switch (_c.label) {
|
|
665
|
-
case 0:
|
|
666
|
-
_b = (_a = index_1.csv).parseCsv;
|
|
667
|
-
return [4 /*yield*/, fs_1.promises.readFile(this.FILE_PROBLEMS, 'utf8')];
|
|
668
|
-
case 1:
|
|
669
|
-
problems = _b.apply(_a, [_c.sent()]);
|
|
670
|
-
return [2 /*return*/, problems.some(function (_a) {
|
|
671
|
-
var _work = _a[0], resource = _a[1], _problem = _a[2];
|
|
672
|
-
return resource === id;
|
|
673
|
-
})];
|
|
674
|
-
}
|
|
675
|
-
});
|
|
451
|
+
}
|
|
452
|
+
shouldBeSkipped(id) {
|
|
453
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
454
|
+
const problems = index_1.csv.parseCsv(yield fs_1.promises.readFile(this.FILE_PROBLEMS, 'utf8'));
|
|
455
|
+
return problems.some(([_work, resource, _problem]) => resource === id);
|
|
676
456
|
});
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
}());
|
|
457
|
+
}
|
|
458
|
+
}
|
|
680
459
|
function main() {
|
|
681
|
-
|
|
460
|
+
const args = util.parseArgs({
|
|
682
461
|
options: {
|
|
683
462
|
source: {
|
|
684
463
|
type: 'string',
|
|
@@ -692,16 +471,16 @@ function main() {
|
|
|
692
471
|
},
|
|
693
472
|
allowPositionals: true
|
|
694
473
|
});
|
|
695
|
-
|
|
696
|
-
process.on('exit',
|
|
474
|
+
const processor = new ResourceProcessor(args.positionals[0]);
|
|
475
|
+
process.on('exit', () => {
|
|
697
476
|
process.stdout.write('\n');
|
|
698
477
|
});
|
|
699
|
-
|
|
700
|
-
|
|
478
|
+
const source = args.values.source;
|
|
479
|
+
const config = {
|
|
701
480
|
update: source !== 'unprocessed',
|
|
702
481
|
updateMappings: !args.values['keep-mappings']
|
|
703
482
|
};
|
|
704
|
-
processor.run(source, config).catch(
|
|
483
|
+
processor.run(source, config).catch(error => {
|
|
705
484
|
console.error(error);
|
|
706
485
|
process.exit(1);
|
|
707
486
|
});
|