eyeleng 1.0.6 → 1.0.7
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/README.md +275 -18
- package/dist/browser/eyeleng.browser.js +123 -13
- package/eyeleng.js +123 -13
- package/package.json +6 -4
- package/playground.html +1 -1
- package/reports/w3c-rdf-earl.ttl +11707 -0
- package/reports/w3c-shacl12-rules-earl.ttl +1055 -1336
- package/src/parser.js +76 -2
- package/src/rdfManifest.js +13 -0
- package/src/shacl12RulesManifest.js +386 -0
- package/src/tokenizer.js +47 -11
- package/test/api.test.js +32 -0
- package/test/shacl12-rules.test.js +37 -215
- package/test/w3c-rdf.test.js +5 -2
- package/tools/w3c-rdf.js +20 -1
- package/tools/w3c-shacl12-rules.js +55 -0
- package/HANDBOOK.md +0 -1070
|
@@ -1,24 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
const assert = require('node:assert/strict');
|
|
5
4
|
const fs = require('node:fs');
|
|
6
5
|
const path = require('node:path');
|
|
7
|
-
const { colors: C, info,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
function isLikelyNetworkError(err) {
|
|
19
|
-
const msg = String(err && (err.stack || err.message || err));
|
|
20
|
-
return /fetch failed|ENOTFOUND|EAI_AGAIN|ECONNREFUSED|ECONNRESET|network|timed out|GET .* failed/i.test(msg);
|
|
21
|
-
}
|
|
6
|
+
const { colors: C, info, summaryLine } = require('./harness.js');
|
|
7
|
+
const {
|
|
8
|
+
defaultShacl12RulesManifestUrl,
|
|
9
|
+
isLikelyNetworkError,
|
|
10
|
+
isW3cRequired,
|
|
11
|
+
runShacl12RulesManifest,
|
|
12
|
+
formatShacl12RulesProgressLine,
|
|
13
|
+
writeShacl12RulesEarlReport,
|
|
14
|
+
} = require('../src/shacl12RulesManifest.js');
|
|
15
|
+
|
|
16
|
+
const rootManifestUrl = process.env.EYELENG_SHACL12_RULES_MANIFEST || defaultShacl12RulesManifestUrl;
|
|
22
17
|
|
|
23
18
|
function appendSummary(summary) {
|
|
24
19
|
const file = process.env.EYELENG_TEST_SUMMARY_FILE;
|
|
@@ -27,226 +22,53 @@ function appendSummary(summary) {
|
|
|
27
22
|
fs.appendFileSync(file, `${JSON.stringify(summary)}\n`, 'utf8');
|
|
28
23
|
}
|
|
29
24
|
|
|
30
|
-
function stripHash(url) {
|
|
31
|
-
const parsed = new URL(url);
|
|
32
|
-
parsed.hash = '';
|
|
33
|
-
return parsed.href;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function resolveHref(baseUrl, href) {
|
|
37
|
-
return new URL(href, baseUrl).href;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
async function fetchText(url) {
|
|
41
|
-
const normalized = stripHash(url);
|
|
42
|
-
if (textCache.has(normalized)) return textCache.get(normalized);
|
|
43
|
-
|
|
44
|
-
const controller = new AbortController();
|
|
45
|
-
const timer = setTimeout(() => controller.abort(), fetchTimeoutMs);
|
|
46
|
-
try {
|
|
47
|
-
const response = await fetch(normalized, { signal: controller.signal });
|
|
48
|
-
if (!response.ok) throw new Error(`GET ${normalized} failed: ${response.status} ${response.statusText}`);
|
|
49
|
-
const text = await response.text();
|
|
50
|
-
textCache.set(normalized, text.replace(/\r\n/g, '\n').replace(/\r/g, '\n'));
|
|
51
|
-
return textCache.get(normalized);
|
|
52
|
-
} catch (err) {
|
|
53
|
-
if (err && err.name === 'AbortError') throw new Error(`GET ${normalized} timed out after ${fetchTimeoutMs} ms`);
|
|
54
|
-
throw err;
|
|
55
|
-
} finally {
|
|
56
|
-
clearTimeout(timer);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function parseIncludedManifests(rootUrl, text) {
|
|
61
|
-
const includeMatch = /mf:include\s*\(([\s\S]*?)\)\s*\./m.exec(text);
|
|
62
|
-
if (!includeMatch) throw new Error(`No mf:include list found in ${rootUrl}`);
|
|
63
|
-
return [...includeMatch[1].matchAll(/<([^>]+)>/g)].map((match) => resolveHref(rootUrl, match[1]));
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function sectionName(manifestUrl) {
|
|
67
|
-
const pieces = new URL(manifestUrl).pathname.split('/').filter(Boolean);
|
|
68
|
-
if (pieces.length < 2) return manifestUrl;
|
|
69
|
-
return pieces[pieces.length - 2];
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
function manifestStatements(text) {
|
|
73
|
-
const statements = [];
|
|
74
|
-
const re = /([^\s;]+)\s+rdf:type\s+srt:([A-Za-z0-9]+)\s*;([\s\S]*?)\n\s*\./g;
|
|
75
|
-
let match;
|
|
76
|
-
while ((match = re.exec(text)) !== null) {
|
|
77
|
-
statements.push({ id: match[1], type: match[2], body: match[3] });
|
|
78
|
-
}
|
|
79
|
-
return statements;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
function parseManifestTests(manifestUrl, text) {
|
|
83
|
-
const section = sectionName(manifestUrl);
|
|
84
|
-
const tests = [];
|
|
85
|
-
|
|
86
|
-
for (const statement of manifestStatements(text)) {
|
|
87
|
-
const name = /mf:name\s+"((?:[^"\\]|\\.)*)"/m.exec(statement.body)?.[1] || statement.id;
|
|
88
|
-
|
|
89
|
-
if (statement.type === 'RulesEvalTest') {
|
|
90
|
-
const ruleset = /srt:ruleset\s+<([^>]+)>/m.exec(statement.body)?.[1];
|
|
91
|
-
const data = /srt:data\s+<([^>]+)>/m.exec(statement.body)?.[1];
|
|
92
|
-
const result = /mf:result\s+<([^>]+)>/m.exec(statement.body)?.[1];
|
|
93
|
-
if (!ruleset || !data || !result) throw new Error(`Incomplete eval test ${statement.id} in ${manifestUrl}`);
|
|
94
|
-
tests.push({
|
|
95
|
-
section,
|
|
96
|
-
id: statement.id,
|
|
97
|
-
type: statement.type,
|
|
98
|
-
name,
|
|
99
|
-
manifestUrl,
|
|
100
|
-
rulesetUrl: resolveHref(manifestUrl, ruleset),
|
|
101
|
-
dataUrl: resolveHref(manifestUrl, data),
|
|
102
|
-
resultUrl: resolveHref(manifestUrl, result),
|
|
103
|
-
});
|
|
104
|
-
continue;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const action = /mf:action\s+<([^>]+)>/m.exec(statement.body)?.[1];
|
|
108
|
-
if (!action) throw new Error(`No mf:action found for ${statement.id} in ${manifestUrl}`);
|
|
109
|
-
tests.push({
|
|
110
|
-
section,
|
|
111
|
-
id: statement.id,
|
|
112
|
-
type: statement.type,
|
|
113
|
-
name,
|
|
114
|
-
manifestUrl,
|
|
115
|
-
actionUrl: resolveHref(manifestUrl, action),
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
return tests;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
async function loadTests() {
|
|
123
|
-
const rootText = await fetchText(rootManifestUrl);
|
|
124
|
-
const manifestUrls = parseIncludedManifests(rootManifestUrl, rootText);
|
|
125
|
-
const suites = await Promise.all(manifestUrls.map(async (manifestUrl) => ({
|
|
126
|
-
manifestUrl,
|
|
127
|
-
text: await fetchText(manifestUrl),
|
|
128
|
-
})));
|
|
129
|
-
return suites.flatMap(({ manifestUrl, text }) => parseManifestTests(manifestUrl, text));
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
function shouldPass(type) {
|
|
133
|
-
return /Positive/.test(type) || type === 'RulesEvalTest';
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
async function runSyntaxOrWellformedTest(test) {
|
|
137
|
-
const source = await fetchText(test.actionUrl);
|
|
138
|
-
const options = { filename: test.actionUrl, baseIRI: test.actionUrl, shacl12Conformance: true };
|
|
139
|
-
|
|
140
|
-
if (test.type.includes('Syntax')) {
|
|
141
|
-
if (shouldPass(test.type)) eyeleng.parse(source, options);
|
|
142
|
-
else assert.throws(() => eyeleng.parse(source, options), Error);
|
|
143
|
-
return;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
if (shouldPass(test.type)) eyeleng.compile(source, options);
|
|
147
|
-
else assert.throws(() => eyeleng.compile(source, options), Error);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
async function parseTurtleTriples(url) {
|
|
151
|
-
const source = await fetchText(url);
|
|
152
|
-
return eyeleng.parseRdfDocument(source, { filename: url, baseIRI: url }).triples;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
function sortedTripleKeys(triples) {
|
|
156
|
-
return triples.map(tripleKey).sort();
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
function setDiff(actual, expected) {
|
|
160
|
-
const actualSet = new Set(actual);
|
|
161
|
-
return expected.filter((item) => !actualSet.has(item));
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
async function runEvalTest(test) {
|
|
165
|
-
const [rulesSource, dataTriples, expectedTriples] = await Promise.all([
|
|
166
|
-
fetchText(test.rulesetUrl),
|
|
167
|
-
parseTurtleTriples(test.dataUrl),
|
|
168
|
-
parseTurtleTriples(test.resultUrl),
|
|
169
|
-
]);
|
|
170
|
-
|
|
171
|
-
const compiled = eyeleng.compile(rulesSource, { filename: test.rulesetUrl, baseIRI: test.rulesetUrl, shacl12Conformance: true });
|
|
172
|
-
const program = { ...compiled.program, data: [...compiled.program.data, ...dataTriples] };
|
|
173
|
-
const result = eyeleng.evaluate(program, { analysis: compiled.analysis, shacl12Conformance: true });
|
|
174
|
-
|
|
175
|
-
const externalInput = new Set(dataTriples.map(tripleKey));
|
|
176
|
-
const actualTriples = result.closure.filter((triple) => !externalInput.has(tripleKey(triple)));
|
|
177
|
-
const actual = sortedTripleKeys(actualTriples);
|
|
178
|
-
const expected = sortedTripleKeys(expectedTriples);
|
|
179
|
-
|
|
180
|
-
try {
|
|
181
|
-
assert.deepEqual(actual, expected);
|
|
182
|
-
} catch (err) {
|
|
183
|
-
err.message += `\nMissing expected:\n${setDiff(actual, expected).join('\n')}\nUnexpected actual:\n${setDiff(expected, actual).join('\n')}`;
|
|
184
|
-
throw err;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
async function runOne(test) {
|
|
189
|
-
if (test.type === 'RulesEvalTest') return runEvalTest(test);
|
|
190
|
-
return runSyntaxOrWellformedTest(test);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
25
|
async function main() {
|
|
194
26
|
const suiteStart = Date.now();
|
|
195
27
|
info('W3C SHACL 1.2 Rules');
|
|
196
28
|
console.log(`${C.dim}manifest: ${rootManifestUrl}${C.n}`);
|
|
197
29
|
|
|
198
|
-
let
|
|
30
|
+
let result;
|
|
199
31
|
try {
|
|
200
|
-
|
|
32
|
+
result = await runShacl12RulesManifest(rootManifestUrl, {
|
|
33
|
+
onProgress(item, index) {
|
|
34
|
+
console.log(formatShacl12RulesProgressLine(item, index, { colors: C }));
|
|
35
|
+
},
|
|
36
|
+
});
|
|
201
37
|
} catch (err) {
|
|
202
|
-
if (isLikelyNetworkError(err) &&
|
|
203
|
-
console.log(`${C.dim}W3C SHACL 1.2 Rules manifests not reachable
|
|
38
|
+
if (isLikelyNetworkError(err) && !isW3cRequired()) {
|
|
39
|
+
console.log(`${C.dim}W3C SHACL 1.2 Rules manifests not reachable; EYELENG_W3C_REQUIRED=0 permits this skip.${C.n}`);
|
|
204
40
|
appendSummary({ section: 'W3C SHACL 1.2 Rules', passed: 1, failed: 0, total: 1, ms: Date.now() - suiteStart });
|
|
205
41
|
return;
|
|
206
42
|
}
|
|
207
|
-
failLine('---', 'load W3C SHACL 1.2 Rules manifests', Date.now() - suiteStart);
|
|
208
43
|
console.error(err.stack || err.message || String(err));
|
|
209
44
|
appendSummary({ section: 'W3C SHACL 1.2 Rules', passed: 0, failed: 1, total: 1, ms: Date.now() - suiteStart });
|
|
210
45
|
process.exitCode = 1;
|
|
211
46
|
return;
|
|
212
47
|
}
|
|
213
48
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
const test = tests[i];
|
|
221
|
-
const idx = String(i + 1).padStart(idxWidth, '0');
|
|
222
|
-
const start = Date.now();
|
|
223
|
-
try {
|
|
224
|
-
await runOne(test);
|
|
225
|
-
okLine(idx, `${test.section}/${test.name}`, Date.now() - start);
|
|
226
|
-
passed++;
|
|
227
|
-
const section = bySection.get(test.section) || { passed: 0, failed: 0 };
|
|
228
|
-
section.passed++;
|
|
229
|
-
bySection.set(test.section, section);
|
|
230
|
-
} catch (err) {
|
|
231
|
-
failLine(idx, `${test.section}/${test.name}`, Date.now() - start);
|
|
232
|
-
console.error(err.stack || err.message || String(err));
|
|
233
|
-
failed++;
|
|
234
|
-
const section = bySection.get(test.section) || { passed: 0, failed: 0 };
|
|
235
|
-
section.failed++;
|
|
236
|
-
bySection.set(test.section, section);
|
|
237
|
-
}
|
|
49
|
+
try {
|
|
50
|
+
const reportPath = writeShacl12RulesEarlReport(result);
|
|
51
|
+
console.log(`${C.dim}EARL report: ${path.relative(path.join(__dirname, '..'), reportPath)}${C.n}`);
|
|
52
|
+
} catch (err) {
|
|
53
|
+
console.error(`Failed to write SHACL Rules EARL report: ${err.message}`);
|
|
54
|
+
result.counts.fail += 1;
|
|
238
55
|
}
|
|
239
56
|
|
|
240
|
-
const
|
|
241
|
-
|
|
242
|
-
const total = counts.passed + counts.failed;
|
|
243
|
-
summaryLine(counts.failed === 0 ? 'ok' : 'fail', counts.passed, total, null, { label: section });
|
|
57
|
+
for (const section of result.bySection) {
|
|
58
|
+
summaryLine(section.failed === 0 ? 'ok' : 'fail', section.passed, section.total, null, { label: section.section });
|
|
244
59
|
}
|
|
245
|
-
summaryLine(
|
|
60
|
+
summaryLine(result.counts.fail === 0 ? 'ok' : 'fail', result.counts.pass, result.counts.total, result.durationMs);
|
|
246
61
|
console.log('');
|
|
247
62
|
|
|
248
|
-
appendSummary({
|
|
249
|
-
|
|
63
|
+
appendSummary({
|
|
64
|
+
section: 'W3C SHACL 1.2 Rules',
|
|
65
|
+
passed: result.counts.pass,
|
|
66
|
+
failed: result.counts.fail,
|
|
67
|
+
skipped: result.counts.skip,
|
|
68
|
+
total: result.counts.total,
|
|
69
|
+
ms: result.durationMs,
|
|
70
|
+
});
|
|
71
|
+
if (result.counts.fail > 0) process.exitCode = 1;
|
|
250
72
|
}
|
|
251
73
|
|
|
252
74
|
main().catch((err) => {
|
package/test/w3c-rdf.test.js
CHANGED
|
@@ -9,6 +9,7 @@ const {
|
|
|
9
9
|
defaultW3cRdfManifestUrls,
|
|
10
10
|
runW3cRdfManifests,
|
|
11
11
|
formatW3cRdfProgressLine,
|
|
12
|
+
writeRdfEarlReport,
|
|
12
13
|
} = require('../src/rdfManifest.js');
|
|
13
14
|
const { parseNQuads, parseN3 } = require('../src/rdfSyntax.js');
|
|
14
15
|
const { evaluateEntailmentTest, entails } = require('../src/rdfEntailment.js');
|
|
@@ -177,14 +178,16 @@ test('official W3C RDF manifests run with streaming progress when reachable', as
|
|
|
177
178
|
},
|
|
178
179
|
});
|
|
179
180
|
} catch (err) {
|
|
180
|
-
if (isLikelyNetworkError(err) && process.env.EYELENG_W3C_REQUIRED
|
|
181
|
-
console.log(`${C.dim}W3C RDF manifests not reachable
|
|
181
|
+
if (isLikelyNetworkError(err) && process.env.EYELENG_W3C_REQUIRED === '0') {
|
|
182
|
+
console.log(`${C.dim}W3C RDF manifests not reachable; EYELENG_W3C_REQUIRED=0 permits this skip.${C.n}`);
|
|
182
183
|
return;
|
|
183
184
|
}
|
|
184
185
|
throw err;
|
|
185
186
|
}
|
|
186
187
|
assert.equal(result.counts.fail, 0, `${result.counts.fail} W3C RDF failure(s)`);
|
|
187
188
|
assert.ok(result.counts.pass > 0, 'expected at least one W3C RDF parser test to pass');
|
|
189
|
+
const reportPath = writeRdfEarlReport(result);
|
|
190
|
+
console.log(`${C.dim}EARL report: ${path.relative(path.join(__dirname, '..'), reportPath)}${C.n}`);
|
|
188
191
|
summaryLine('ok', result.counts.pass, result.counts.total, result.durationMs, {
|
|
189
192
|
skipped: result.counts.skip,
|
|
190
193
|
label: 'W3C RDF manifests',
|
package/tools/w3c-rdf.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
+
const path = require('node:path');
|
|
4
5
|
const { colors: C } = require('../test/harness.js');
|
|
5
6
|
const {
|
|
6
7
|
defaultW3cRdfManifestUrls,
|
|
@@ -8,13 +9,27 @@ const {
|
|
|
8
9
|
formatW3cRdfProgressLine,
|
|
9
10
|
formatW3cRdfManifestsResult,
|
|
10
11
|
rdfManifestsToEarl,
|
|
12
|
+
writeRdfEarlReport,
|
|
13
|
+
defaultRdfReportPath,
|
|
11
14
|
} = require('../src/rdfManifest.js');
|
|
12
15
|
|
|
16
|
+
function argValue(argv, name) {
|
|
17
|
+
const index = argv.indexOf(name);
|
|
18
|
+
if (index < 0) return null;
|
|
19
|
+
return argv[index + 1] || null;
|
|
20
|
+
}
|
|
21
|
+
|
|
13
22
|
async function main(argv = process.argv.slice(2)) {
|
|
14
23
|
const json = argv.includes('--json');
|
|
15
24
|
const earl = argv.includes('--earl');
|
|
25
|
+
const noReport = argv.includes('--no-report');
|
|
16
26
|
const quiet = json || earl || argv.includes('--quiet');
|
|
17
|
-
const
|
|
27
|
+
const output = argValue(argv, '--output') || defaultRdfReportPath();
|
|
28
|
+
const manifests = argv.filter((arg, index) => {
|
|
29
|
+
if (arg.startsWith('--')) return false;
|
|
30
|
+
if (argv[index - 1] === '--output') return false;
|
|
31
|
+
return true;
|
|
32
|
+
});
|
|
18
33
|
const resources = manifests.length ? manifests : defaultW3cRdfManifestUrls;
|
|
19
34
|
const result = await runW3cRdfManifests(resources, {
|
|
20
35
|
onManifestStart(resource, index, total) {
|
|
@@ -24,6 +39,10 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
24
39
|
if (!quiet) console.log(formatW3cRdfProgressLine(item, index, { colors: C }));
|
|
25
40
|
},
|
|
26
41
|
});
|
|
42
|
+
if (!noReport) {
|
|
43
|
+
const reportPath = writeRdfEarlReport(result, output, { assertedBy: '<https://github.com/eyereasoner/eyeleng>' });
|
|
44
|
+
if (!quiet) console.log(`${C.dim}EARL report: ${path.relative(path.join(__dirname, '..'), reportPath)}${C.n}`);
|
|
45
|
+
}
|
|
27
46
|
if (json) process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
28
47
|
else if (earl) process.stdout.write(`${rdfManifestsToEarl(result, { assertedBy: '<https://github.com/eyereasoner/eyeleng>' })}\n`);
|
|
29
48
|
else process.stdout.write(`${formatW3cRdfManifestsResult(result, { colors: C })}\n`);
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const path = require('node:path');
|
|
5
|
+
const { colors: C } = require('../test/harness.js');
|
|
6
|
+
const {
|
|
7
|
+
defaultShacl12RulesManifestUrl,
|
|
8
|
+
runShacl12RulesManifest,
|
|
9
|
+
formatShacl12RulesProgressLine,
|
|
10
|
+
formatShacl12RulesManifestResult,
|
|
11
|
+
shacl12RulesManifestToEarl,
|
|
12
|
+
writeShacl12RulesEarlReport,
|
|
13
|
+
defaultReportPath,
|
|
14
|
+
} = require('../src/shacl12RulesManifest.js');
|
|
15
|
+
|
|
16
|
+
function argValue(argv, name) {
|
|
17
|
+
const index = argv.indexOf(name);
|
|
18
|
+
if (index < 0) return null;
|
|
19
|
+
return argv[index + 1] || null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async function main(argv = process.argv.slice(2)) {
|
|
23
|
+
const json = argv.includes('--json');
|
|
24
|
+
const earl = argv.includes('--earl');
|
|
25
|
+
const noReport = argv.includes('--no-report');
|
|
26
|
+
const quiet = json || earl || argv.includes('--quiet');
|
|
27
|
+
const output = argValue(argv, '--output') || defaultReportPath();
|
|
28
|
+
const manifests = argv.filter((arg, index) => {
|
|
29
|
+
if (arg.startsWith('--')) return false;
|
|
30
|
+
if (argv[index - 1] === '--output') return false;
|
|
31
|
+
return true;
|
|
32
|
+
});
|
|
33
|
+
const manifest = manifests[0] || process.env.EYELENG_SHACL12_RULES_MANIFEST || defaultShacl12RulesManifestUrl;
|
|
34
|
+
|
|
35
|
+
const result = await runShacl12RulesManifest(manifest, {
|
|
36
|
+
onProgress(item, index) {
|
|
37
|
+
if (!quiet) console.log(formatShacl12RulesProgressLine(item, index, { colors: C }));
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
if (!noReport) {
|
|
42
|
+
const reportPath = writeShacl12RulesEarlReport(result, output);
|
|
43
|
+
if (!quiet) console.log(`${C.dim}EARL report: ${path.relative(path.join(__dirname, '..'), reportPath)}${C.n}`);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (json) process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
47
|
+
else if (earl) process.stdout.write(`${shacl12RulesManifestToEarl(result)}\n`);
|
|
48
|
+
else process.stdout.write(`${formatShacl12RulesManifestResult(result, { colors: C })}\n`);
|
|
49
|
+
return result.counts.fail === 0 ? 0 : 1;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
main().then((code) => { process.exitCode = code; }, (err) => {
|
|
53
|
+
console.error(err.stack || err.message || String(err));
|
|
54
|
+
process.exitCode = 1;
|
|
55
|
+
});
|