@unrdf/knowledge-engine 5.0.1 → 26.4.2
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/package.json +23 -17
- package/src/ai-enhanced-search.mjs +371 -0
- package/src/anomaly-detector.mjs +226 -0
- package/src/artifact-generator.mjs +252 -0
- package/src/browser.mjs +1 -1
- package/src/chatman/disruption-arithmetic.mjs +140 -0
- package/src/chatman/market-dynamics.mjs +140 -0
- package/src/chatman/organizational-dynamics.mjs +140 -0
- package/src/chatman/strategic-dynamics.mjs +140 -0
- package/src/chatman-config-loader.mjs +282 -0
- package/src/chatman-engine.mjs +435 -0
- package/src/chatman-operator.mjs +343 -0
- package/src/dark-field-detector.mjs +332 -0
- package/src/formation-theorems.mjs +345 -0
- package/src/index.mjs +20 -2
- package/src/knowledge-hook-manager.mjs +1 -1
- package/src/lockchain-writer-browser.mjs +2 -2
- package/src/observability.mjs +40 -4
- package/src/query-optimizer.mjs +1 -1
- package/src/resolution-layer.mjs +1 -1
- package/src/transaction.mjs +11 -9
- package/README.md +0 -84
- package/src/browser-shims.mjs +0 -343
- package/src/canonicalize.mjs +0 -414
- package/src/condition-cache.mjs +0 -109
- package/src/condition-evaluator.mjs +0 -722
- package/src/dark-matter-core.mjs +0 -742
- package/src/define-hook.mjs +0 -213
- package/src/effect-sandbox-browser.mjs +0 -283
- package/src/effect-sandbox-worker.mjs +0 -170
- package/src/effect-sandbox.mjs +0 -517
- package/src/engines/index.mjs +0 -11
- package/src/engines/rdf-engine.mjs +0 -299
- package/src/file-resolver.mjs +0 -387
- package/src/hook-executor-batching.mjs +0 -277
- package/src/hook-executor.mjs +0 -870
- package/src/hook-management.mjs +0 -150
- package/src/ken-parliment.mjs +0 -119
- package/src/ken.mjs +0 -149
- package/src/knowledge-engine/builtin-rules.mjs +0 -190
- package/src/knowledge-engine/inference-engine.mjs +0 -418
- package/src/knowledge-engine/knowledge-engine.mjs +0 -317
- package/src/knowledge-engine/pattern-dsl.mjs +0 -142
- package/src/knowledge-engine/pattern-matcher.mjs +0 -215
- package/src/knowledge-engine/rules.mjs +0 -184
- package/src/knowledge-engine.mjs +0 -319
- package/src/knowledge-hook-engine.mjs +0 -360
- package/src/knowledge-substrate-core.mjs +0 -927
- package/src/lite.mjs +0 -222
- package/src/lockchain-writer.mjs +0 -602
- package/src/monitoring/andon-signals.mjs +0 -775
- package/src/parse.mjs +0 -290
- package/src/performance-optimizer.mjs +0 -678
- package/src/policy-pack.mjs +0 -572
- package/src/query-cache.mjs +0 -116
- package/src/query.mjs +0 -306
- package/src/reason.mjs +0 -350
- package/src/schemas.mjs +0 -1063
- package/src/security/error-sanitizer.mjs +0 -257
- package/src/security/path-validator.mjs +0 -194
- package/src/security/sandbox-restrictions.mjs +0 -331
- package/src/security-validator.mjs +0 -389
- package/src/store-cache.mjs +0 -137
- package/src/telemetry.mjs +0 -167
- package/src/utils/adaptive-monitor.mjs +0 -746
- package/src/utils/circuit-breaker.mjs +0 -513
- package/src/utils/edge-case-handler.mjs +0 -503
- package/src/utils/memory-manager.mjs +0 -498
- package/src/utils/ring-buffer.mjs +0 -282
- package/src/validate.mjs +0 -319
- package/src/validators/index.mjs +0 -338
|
@@ -1,282 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file ring-buffer.mjs
|
|
3
|
-
* @description TRIZ #10 Prior Action - Ring buffer for efficient streaming operations
|
|
4
|
-
* Pre-allocates fixed memory to avoid array reallocation overhead during high-throughput streaming
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* @typedef {Object} RingBufferOptions
|
|
9
|
-
* @property {number} [maxSize=100] - Maximum number of items in buffer
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* High-performance circular buffer for streaming data
|
|
14
|
-
* O(1) push operations with automatic wraparound, avoiding array slice/shift overhead
|
|
15
|
-
*
|
|
16
|
-
* @template T
|
|
17
|
-
* @example
|
|
18
|
-
* const buffer = new RingBuffer(100);
|
|
19
|
-
* buffer.push({ event: 'added', timestamp: Date.now() });
|
|
20
|
-
* const events = buffer.toArray(); // Returns items in insertion order
|
|
21
|
-
*/
|
|
22
|
-
export class RingBuffer {
|
|
23
|
-
/**
|
|
24
|
-
* @param {number} [maxSize=100] - Maximum buffer capacity
|
|
25
|
-
*/
|
|
26
|
-
constructor(maxSize = 100) {
|
|
27
|
-
/** @type {Array<T|undefined>} */
|
|
28
|
-
this.buffer = new Array(maxSize);
|
|
29
|
-
/** @type {number} - Index where next item will be written */
|
|
30
|
-
this.head = 0;
|
|
31
|
-
/** @type {number} - Index of oldest item */
|
|
32
|
-
this.tail = 0;
|
|
33
|
-
/** @type {number} - Current number of items */
|
|
34
|
-
this.size = 0;
|
|
35
|
-
/** @type {number} - Maximum capacity */
|
|
36
|
-
this.maxSize = maxSize;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Add item to buffer, overwriting oldest if full
|
|
41
|
-
* @param {T} item - Item to add
|
|
42
|
-
* @returns {T|undefined} - Overwritten item if buffer was full, undefined otherwise
|
|
43
|
-
*/
|
|
44
|
-
push(item) {
|
|
45
|
-
/** @type {T|undefined} */
|
|
46
|
-
let overwritten;
|
|
47
|
-
|
|
48
|
-
if (this.size === this.maxSize) {
|
|
49
|
-
// Buffer full - overwrite oldest item
|
|
50
|
-
overwritten = this.buffer[this.tail];
|
|
51
|
-
this.tail = (this.tail + 1) % this.maxSize;
|
|
52
|
-
} else {
|
|
53
|
-
this.size++;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
this.buffer[this.head] = item;
|
|
57
|
-
this.head = (this.head + 1) % this.maxSize;
|
|
58
|
-
|
|
59
|
-
return overwritten;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Remove and return oldest item from buffer
|
|
64
|
-
* @returns {T|undefined} - Oldest item or undefined if empty
|
|
65
|
-
*/
|
|
66
|
-
shift() {
|
|
67
|
-
if (this.size === 0) {
|
|
68
|
-
return undefined;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const item = this.buffer[this.tail];
|
|
72
|
-
this.buffer[this.tail] = undefined; // Allow GC
|
|
73
|
-
this.tail = (this.tail + 1) % this.maxSize;
|
|
74
|
-
this.size--;
|
|
75
|
-
|
|
76
|
-
return item;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Get item at index (0 = oldest)
|
|
81
|
-
* @param {number} index - Index from oldest item
|
|
82
|
-
* @returns {T|undefined} - Item at index or undefined
|
|
83
|
-
*/
|
|
84
|
-
get(index) {
|
|
85
|
-
if (index < 0 || index >= this.size) {
|
|
86
|
-
return undefined;
|
|
87
|
-
}
|
|
88
|
-
const actualIndex = (this.tail + index) % this.maxSize;
|
|
89
|
-
return this.buffer[actualIndex];
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Get most recent item without removing
|
|
94
|
-
* @returns {T|undefined} - Most recent item or undefined if empty
|
|
95
|
-
*/
|
|
96
|
-
peek() {
|
|
97
|
-
if (this.size === 0) {
|
|
98
|
-
return undefined;
|
|
99
|
-
}
|
|
100
|
-
const lastIndex = (this.head - 1 + this.maxSize) % this.maxSize;
|
|
101
|
-
return this.buffer[lastIndex];
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Get oldest item without removing
|
|
106
|
-
* @returns {T|undefined} - Oldest item or undefined if empty
|
|
107
|
-
*/
|
|
108
|
-
peekOldest() {
|
|
109
|
-
if (this.size === 0) {
|
|
110
|
-
return undefined;
|
|
111
|
-
}
|
|
112
|
-
return this.buffer[this.tail];
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Convert buffer to array in insertion order (oldest first)
|
|
117
|
-
* @returns {Array<T>} - Array of items
|
|
118
|
-
*/
|
|
119
|
-
toArray() {
|
|
120
|
-
if (this.size === 0) {
|
|
121
|
-
return [];
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/** @type {Array<T>} */
|
|
125
|
-
const result = new Array(this.size);
|
|
126
|
-
|
|
127
|
-
for (let i = 0; i < this.size; i++) {
|
|
128
|
-
const index = (this.tail + i) % this.maxSize;
|
|
129
|
-
result[i] = /** @type {T} */ (this.buffer[index]);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
return result;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Clear all items from buffer
|
|
137
|
-
*/
|
|
138
|
-
clear() {
|
|
139
|
-
// Clear references for GC
|
|
140
|
-
for (let i = 0; i < this.maxSize; i++) {
|
|
141
|
-
this.buffer[i] = undefined;
|
|
142
|
-
}
|
|
143
|
-
this.head = 0;
|
|
144
|
-
this.tail = 0;
|
|
145
|
-
this.size = 0;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Check if buffer is empty
|
|
150
|
-
* @returns {boolean}
|
|
151
|
-
*/
|
|
152
|
-
isEmpty() {
|
|
153
|
-
return this.size === 0;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* Check if buffer is full
|
|
158
|
-
* @returns {boolean}
|
|
159
|
-
*/
|
|
160
|
-
isFull() {
|
|
161
|
-
return this.size === this.maxSize;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* Get current number of items
|
|
166
|
-
* @returns {number}
|
|
167
|
-
*/
|
|
168
|
-
get length() {
|
|
169
|
-
return this.size;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* Get maximum capacity
|
|
174
|
-
* @returns {number}
|
|
175
|
-
*/
|
|
176
|
-
get capacity() {
|
|
177
|
-
return this.maxSize;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Get available space
|
|
182
|
-
* @returns {number}
|
|
183
|
-
*/
|
|
184
|
-
get available() {
|
|
185
|
-
return this.maxSize - this.size;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* Iterate over items (oldest to newest)
|
|
190
|
-
* @yields {T}
|
|
191
|
-
*/
|
|
192
|
-
*[Symbol.iterator]() {
|
|
193
|
-
for (let i = 0; i < this.size; i++) {
|
|
194
|
-
const index = (this.tail + i) % this.maxSize;
|
|
195
|
-
yield /** @type {T} */ (this.buffer[index]);
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* Apply function to each item
|
|
201
|
-
* @param {(item: T, index: number) => void} fn - Function to apply
|
|
202
|
-
*/
|
|
203
|
-
forEach(fn) {
|
|
204
|
-
for (let i = 0; i < this.size; i++) {
|
|
205
|
-
const index = (this.tail + i) % this.maxSize;
|
|
206
|
-
fn(/** @type {T} */ (this.buffer[index]), i);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* Filter items and return new array
|
|
212
|
-
* @param {(item: T, index: number) => boolean} predicate - Filter function
|
|
213
|
-
* @returns {Array<T>}
|
|
214
|
-
*/
|
|
215
|
-
filter(predicate) {
|
|
216
|
-
/** @type {Array<T>} */
|
|
217
|
-
const result = [];
|
|
218
|
-
for (let i = 0; i < this.size; i++) {
|
|
219
|
-
const index = (this.tail + i) % this.maxSize;
|
|
220
|
-
const item = /** @type {T} */ (this.buffer[index]);
|
|
221
|
-
if (predicate(item, i)) {
|
|
222
|
-
result.push(item);
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
return result;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* Find first item matching predicate
|
|
230
|
-
* @param {(item: T, index: number) => boolean} predicate - Search function
|
|
231
|
-
* @returns {T|undefined}
|
|
232
|
-
*/
|
|
233
|
-
find(predicate) {
|
|
234
|
-
for (let i = 0; i < this.size; i++) {
|
|
235
|
-
const index = (this.tail + i) % this.maxSize;
|
|
236
|
-
const item = /** @type {T} */ (this.buffer[index]);
|
|
237
|
-
if (predicate(item, i)) {
|
|
238
|
-
return item;
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
return undefined;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
/**
|
|
245
|
-
* Get last N items (most recent)
|
|
246
|
-
* @param {number} n - Number of items
|
|
247
|
-
* @returns {Array<T>}
|
|
248
|
-
*/
|
|
249
|
-
last(n) {
|
|
250
|
-
const count = Math.min(n, this.size);
|
|
251
|
-
/** @type {Array<T>} */
|
|
252
|
-
const result = new Array(count);
|
|
253
|
-
const startOffset = this.size - count;
|
|
254
|
-
|
|
255
|
-
for (let i = 0; i < count; i++) {
|
|
256
|
-
const index = (this.tail + startOffset + i) % this.maxSize;
|
|
257
|
-
result[i] = /** @type {T} */ (this.buffer[index]);
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
return result;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* Get first N items (oldest)
|
|
265
|
-
* @param {number} n - Number of items
|
|
266
|
-
* @returns {Array<T>}
|
|
267
|
-
*/
|
|
268
|
-
first(n) {
|
|
269
|
-
const count = Math.min(n, this.size);
|
|
270
|
-
/** @type {Array<T>} */
|
|
271
|
-
const result = new Array(count);
|
|
272
|
-
|
|
273
|
-
for (let i = 0; i < count; i++) {
|
|
274
|
-
const index = (this.tail + i) % this.maxSize;
|
|
275
|
-
result[i] = /** @type {T} */ (this.buffer[index]);
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
return result;
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
export default RingBuffer;
|
package/src/validate.mjs
DELETED
|
@@ -1,319 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file SHACL validation.
|
|
3
|
-
* @module validate
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { createStore } from '@unrdf/oxigraph';
|
|
7
|
-
import rdf from 'rdf-ext';
|
|
8
|
-
import SHACLValidator from 'rdf-validate-shacl';
|
|
9
|
-
import { trace, SpanStatusCode } from '@opentelemetry/api';
|
|
10
|
-
|
|
11
|
-
const tracer = trace.getTracer('unrdf');
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Validate a store against SHACL shapes.
|
|
15
|
-
* @param {Store} store - The store containing data to validate
|
|
16
|
-
* @param {Store|string} shapes - The store or Turtle string containing SHACL shapes
|
|
17
|
-
* @param {Object} [options] - Validation options
|
|
18
|
-
* @param {boolean} [options.strict] - Enable strict validation mode
|
|
19
|
-
* @param {boolean} [options.includeDetails] - Include detailed validation results
|
|
20
|
-
* @returns {{conforms: boolean, results: Array<object>}} Validation report
|
|
21
|
-
*
|
|
22
|
-
* @throws {Error} If validation fails
|
|
23
|
-
*
|
|
24
|
-
* @example
|
|
25
|
-
* const dataStore = new Store();
|
|
26
|
-
* // ... add data quads to store
|
|
27
|
-
*
|
|
28
|
-
* const shapesTtl = `
|
|
29
|
-
* @prefix sh: <http://www.w3.org/ns/shacl#> .
|
|
30
|
-
* @prefix ex: <http://example.org/> .
|
|
31
|
-
* ex:PersonShape a sh:NodeShape ;
|
|
32
|
-
* sh:targetClass ex:Person ;
|
|
33
|
-
* sh:property [
|
|
34
|
-
* sh:path ex:name ;
|
|
35
|
-
* sh:minCount 1 ;
|
|
36
|
-
* sh:maxCount 1
|
|
37
|
-
* ] .
|
|
38
|
-
* `;
|
|
39
|
-
*
|
|
40
|
-
* const report = validateShacl(dataStore, shapesTtl);
|
|
41
|
-
* console.log('Conforms:', report.conforms);
|
|
42
|
-
* console.log('Results:', report.results);
|
|
43
|
-
*/
|
|
44
|
-
export function validateShacl(store, shapes, options = {}) {
|
|
45
|
-
if (!store || typeof store.getQuads !== 'function') {
|
|
46
|
-
throw new TypeError('validateShacl: store must be a valid Store instance');
|
|
47
|
-
}
|
|
48
|
-
if (!shapes) {
|
|
49
|
-
throw new TypeError('validateShacl: shapes must be provided');
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
return tracer.startActiveSpan('validate.shacl', span => {
|
|
53
|
-
try {
|
|
54
|
-
const shapesType = typeof shapes === 'string' ? 'turtle' : 'store';
|
|
55
|
-
span.setAttributes({
|
|
56
|
-
'validate.shapes_type': shapesType,
|
|
57
|
-
'validate.data_size': store.size,
|
|
58
|
-
'validate.include_details': options.includeDetails || false,
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
// Parse Turtle shapes if provided as string
|
|
62
|
-
let shapesStore;
|
|
63
|
-
if (typeof shapes === 'string') {
|
|
64
|
-
shapesStore = createStore();
|
|
65
|
-
shapesStore.load(shapes, { format: 'text/turtle' });
|
|
66
|
-
} else {
|
|
67
|
-
shapesStore = shapes;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (!shapesStore || typeof shapesStore.getQuads !== 'function') {
|
|
71
|
-
throw new TypeError('validateShacl: shapes must be a valid Store or Turtle string');
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
span.setAttribute('validate.shapes_size', shapesStore.size);
|
|
75
|
-
|
|
76
|
-
const validator = new SHACLValidator(rdf.dataset(shapesStore.getQuads()));
|
|
77
|
-
const report = validator.validate(rdf.dataset(store.getQuads()));
|
|
78
|
-
|
|
79
|
-
const results = (report.results || []).map(r => ({
|
|
80
|
-
message: r.message?.[0]?.value || null,
|
|
81
|
-
path: r.path?.value || null,
|
|
82
|
-
focusNode: r.focusNode?.value || null,
|
|
83
|
-
severity: r.severity?.value || null,
|
|
84
|
-
sourceConstraint: r.sourceConstraint?.value || null,
|
|
85
|
-
sourceConstraintComponent: r.sourceConstraintComponent?.value || null,
|
|
86
|
-
sourceShape: r.sourceShape?.value || null,
|
|
87
|
-
value: r.value?.value || null,
|
|
88
|
-
...(options.includeDetails && {
|
|
89
|
-
detail: r.detail || null,
|
|
90
|
-
resultPath: r.resultPath?.value || null,
|
|
91
|
-
resultSeverity: r.resultSeverity?.value || null,
|
|
92
|
-
}),
|
|
93
|
-
}));
|
|
94
|
-
|
|
95
|
-
const errorCount = results.filter(
|
|
96
|
-
r => r.severity === 'http://www.w3.org/ns/shacl#Violation'
|
|
97
|
-
).length;
|
|
98
|
-
const warningCount = results.filter(
|
|
99
|
-
r => r.severity === 'http://www.w3.org/ns/shacl#Warning'
|
|
100
|
-
).length;
|
|
101
|
-
|
|
102
|
-
span.setAttributes({
|
|
103
|
-
'validate.conforms': report.conforms,
|
|
104
|
-
'validate.total_results': results.length,
|
|
105
|
-
'validate.error_count': errorCount,
|
|
106
|
-
'validate.warning_count': warningCount,
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
span.setStatus({ code: SpanStatusCode.OK });
|
|
110
|
-
|
|
111
|
-
const validationResult = {
|
|
112
|
-
conforms: report.conforms,
|
|
113
|
-
results,
|
|
114
|
-
...(options.includeDetails && {
|
|
115
|
-
totalResults: results.length,
|
|
116
|
-
errorCount: errorCount,
|
|
117
|
-
warningCount: warningCount,
|
|
118
|
-
infoCount: results.filter(r => r.severity === 'http://www.w3.org/ns/shacl#Info').length,
|
|
119
|
-
}),
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
span.end();
|
|
123
|
-
return validationResult;
|
|
124
|
-
} catch (error) {
|
|
125
|
-
span.recordException(error);
|
|
126
|
-
span.setStatus({
|
|
127
|
-
code: SpanStatusCode.ERROR,
|
|
128
|
-
message: error.message,
|
|
129
|
-
});
|
|
130
|
-
span.end();
|
|
131
|
-
throw new Error(`SHACL validation failed: ${error.message}`);
|
|
132
|
-
}
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Validate a store against multiple SHACL shape sets.
|
|
138
|
-
* @param {Store} store - The store containing data to validate
|
|
139
|
-
* @param {Array<Store|string>} shapesList - Array of stores or Turtle strings containing SHACL shapes
|
|
140
|
-
* @param {Object} [options] - Validation options
|
|
141
|
-
* @returns {{conforms: boolean, results: Array<object>, shapeResults: Array<object>}} Combined validation report
|
|
142
|
-
*
|
|
143
|
-
* @throws {Error} If validation fails
|
|
144
|
-
*
|
|
145
|
-
* @example
|
|
146
|
-
* const shapesList = [
|
|
147
|
-
* personShapesTtl,
|
|
148
|
-
* organizationShapesTtl,
|
|
149
|
-
* contactShapesTtl
|
|
150
|
-
* ];
|
|
151
|
-
*
|
|
152
|
-
* const report = validateShaclMultiple(store, shapesList);
|
|
153
|
-
* console.log('Overall conforms:', report.conforms);
|
|
154
|
-
* console.log('Shape-specific results:', report.shapeResults);
|
|
155
|
-
*/
|
|
156
|
-
export function validateShaclMultiple(store, shapesList, options = {}) {
|
|
157
|
-
if (!store || typeof store.getQuads !== 'function') {
|
|
158
|
-
throw new TypeError('validateShaclMultiple: store must be a valid Store instance');
|
|
159
|
-
}
|
|
160
|
-
if (!Array.isArray(shapesList) || shapesList.length === 0) {
|
|
161
|
-
throw new TypeError('validateShaclMultiple: shapesList must be a non-empty array');
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
try {
|
|
165
|
-
const shapeResults = [];
|
|
166
|
-
let allResults = [];
|
|
167
|
-
let overallConforms = true;
|
|
168
|
-
|
|
169
|
-
for (let i = 0; i < shapesList.length; i++) {
|
|
170
|
-
const shapes = shapesList[i];
|
|
171
|
-
const report = validateShacl(store, shapes, options);
|
|
172
|
-
|
|
173
|
-
shapeResults.push({
|
|
174
|
-
index: i,
|
|
175
|
-
shapes: typeof shapes === 'string' ? 'Turtle string' : 'Store',
|
|
176
|
-
conforms: report.conforms,
|
|
177
|
-
resultCount: report.results.length,
|
|
178
|
-
results: report.results,
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
allResults = allResults.concat(report.results);
|
|
182
|
-
if (!report.conforms) {
|
|
183
|
-
overallConforms = false;
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
return {
|
|
188
|
-
conforms: overallConforms,
|
|
189
|
-
results: allResults,
|
|
190
|
-
shapeResults,
|
|
191
|
-
totalShapes: shapesList.length,
|
|
192
|
-
totalResults: allResults.length,
|
|
193
|
-
};
|
|
194
|
-
} catch (error) {
|
|
195
|
-
throw new Error(`Multiple SHACL validation failed: ${error.message}`);
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* Create a SHACL validation report in a structured format.
|
|
201
|
-
* @param {Object} validationResult - Result from validateShacl
|
|
202
|
-
* @param {Object} [options] - Formatting options
|
|
203
|
-
* @param {boolean} [options.includeSummary] - Include summary statistics
|
|
204
|
-
* @param {boolean} [options.groupBySeverity] - Group results by severity
|
|
205
|
-
* @returns {Object} Formatted validation report
|
|
206
|
-
*
|
|
207
|
-
* @example
|
|
208
|
-
* const report = validateShacl(store, shapes);
|
|
209
|
-
* const formatted = formatValidationReport(report, {
|
|
210
|
-
* includeSummary: true,
|
|
211
|
-
* groupBySeverity: true
|
|
212
|
-
* });
|
|
213
|
-
*/
|
|
214
|
-
export function formatValidationReport(validationResult, options = {}) {
|
|
215
|
-
if (!validationResult || typeof validationResult !== 'object') {
|
|
216
|
-
throw new TypeError('formatValidationReport: validationResult must be an object');
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
const { results = [], conforms } = validationResult;
|
|
220
|
-
const { includeSummary = false, groupBySeverity = false } = options;
|
|
221
|
-
|
|
222
|
-
let formatted = {
|
|
223
|
-
conforms,
|
|
224
|
-
resultCount: results.length,
|
|
225
|
-
};
|
|
226
|
-
|
|
227
|
-
if (includeSummary) {
|
|
228
|
-
const severityCounts = results.reduce((acc, result) => {
|
|
229
|
-
const severity = result.severity || 'unknown';
|
|
230
|
-
acc[severity] = (acc[severity] || 0) + 1;
|
|
231
|
-
return acc;
|
|
232
|
-
}, {});
|
|
233
|
-
|
|
234
|
-
formatted.summary = {
|
|
235
|
-
totalResults: results.length,
|
|
236
|
-
severityCounts,
|
|
237
|
-
hasErrors: severityCounts['http://www.w3.org/ns/shacl#Violation'] > 0,
|
|
238
|
-
hasWarnings: severityCounts['http://www.w3.org/ns/shacl#Warning'] > 0,
|
|
239
|
-
hasInfo: severityCounts['http://www.w3.org/ns/shacl#Info'] > 0,
|
|
240
|
-
};
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
if (groupBySeverity) {
|
|
244
|
-
formatted.resultsBySeverity = results.reduce((acc, result) => {
|
|
245
|
-
const severity = result.severity || 'unknown';
|
|
246
|
-
if (!acc[severity]) {
|
|
247
|
-
acc[severity] = [];
|
|
248
|
-
}
|
|
249
|
-
acc[severity].push(result);
|
|
250
|
-
return acc;
|
|
251
|
-
}, {});
|
|
252
|
-
} else {
|
|
253
|
-
formatted.results = results;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
return formatted;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
/**
|
|
260
|
-
* Check if a validation result contains any errors.
|
|
261
|
-
* @param {Object} validationResult - Result from validateShacl
|
|
262
|
-
* @returns {boolean} True if there are any validation errors
|
|
263
|
-
*
|
|
264
|
-
* @example
|
|
265
|
-
* const report = validateShacl(store, shapes);
|
|
266
|
-
* if (hasValidationErrors(report)) {
|
|
267
|
-
* console.log('Validation failed with errors');
|
|
268
|
-
* }
|
|
269
|
-
*/
|
|
270
|
-
export function hasValidationErrors(validationResult) {
|
|
271
|
-
if (!validationResult || typeof validationResult !== 'object') {
|
|
272
|
-
return false;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
const { results = [] } = validationResult;
|
|
276
|
-
return results.some(result => result.severity === 'http://www.w3.org/ns/shacl#Violation');
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
/**
|
|
280
|
-
* Get validation errors from a validation result.
|
|
281
|
-
* @param {Object} validationResult - Result from validateShacl
|
|
282
|
-
* @returns {Array<Object>} Array of validation error objects
|
|
283
|
-
*
|
|
284
|
-
* @example
|
|
285
|
-
* const report = validateShacl(store, shapes);
|
|
286
|
-
* const errors = getValidationErrors(report);
|
|
287
|
-
* errors.forEach(error => {
|
|
288
|
-
* console.log(`Error: ${error.message} at ${error.focusNode}`);
|
|
289
|
-
* });
|
|
290
|
-
*/
|
|
291
|
-
export function getValidationErrors(validationResult) {
|
|
292
|
-
if (!validationResult || typeof validationResult !== 'object') {
|
|
293
|
-
return [];
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
const { results = [] } = validationResult;
|
|
297
|
-
return results.filter(result => result.severity === 'http://www.w3.org/ns/shacl#Violation');
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
/**
|
|
301
|
-
* Get validation warnings from a validation result.
|
|
302
|
-
* @param {Object} validationResult - Result from validateShacl
|
|
303
|
-
* @returns {Array<Object>} Array of validation warning objects
|
|
304
|
-
*
|
|
305
|
-
* @example
|
|
306
|
-
* const report = validateShacl(store, shapes);
|
|
307
|
-
* const warnings = getValidationWarnings(report);
|
|
308
|
-
* warnings.forEach(warning => {
|
|
309
|
-
* console.log(`Warning: ${warning.message} at ${warning.focusNode}`);
|
|
310
|
-
* });
|
|
311
|
-
*/
|
|
312
|
-
export function getValidationWarnings(validationResult) {
|
|
313
|
-
if (!validationResult || typeof validationResult !== 'object') {
|
|
314
|
-
return [];
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
const { results = [] } = validationResult;
|
|
318
|
-
return results.filter(result => result.severity === 'http://www.w3.org/ns/shacl#Warning');
|
|
319
|
-
}
|