@unrdf/kgn 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/dist/index.mjs +9207 -0
- package/package.json +33 -28
- package/src/base/filter-templates.js +7 -1
- package/src/base/index.js +15 -10
- package/src/base/injection-targets.js +6 -0
- package/src/base/macro-templates.js +6 -0
- package/src/base/shacl-templates.js +6 -0
- package/src/base/template-base.js +7 -1
- package/src/core/attestor.js +50 -1
- package/src/core/filters.js +134 -1
- package/src/core/index.js +8 -1
- package/src/core/kgen-engine.js +49 -1
- package/src/core/parser.js +52 -1
- package/src/core/post-processor.js +7 -1
- package/src/core/renderer.js +67 -1
- package/src/doc-generator/mdx-generator.mjs +1 -1
- package/src/doc-generator/nav-generator.mjs +1 -1
- package/src/doc-generator/rdf-builder.mjs +2 -2
- package/src/engine/index.js +9 -0
- package/src/engine/pipeline.js +7 -1
- package/src/engine/renderer.js +18 -3
- package/src/engine/template-engine.js +12 -3
- package/src/filters/array.js +14 -6
- package/src/filters/index.js +165 -17
- package/src/filters/rdf.js +3 -3
- package/src/{index.js → index.mjs} +46 -0
- package/src/index.test.mjs +40 -0
- package/src/inheritance/index.js +19 -1
- package/src/injection/atomic-writer.js +22 -1
- package/src/injection/idempotency-manager.js +33 -0
- package/src/injection/injection-engine.js +46 -1
- package/src/injection/integration.js +3 -3
- package/src/injection/modes/index.js +30 -0
- package/src/injection/rollback-manager.js +26 -2
- package/src/injection/target-resolver.js +48 -3
- package/src/injection/tests/injection-engine.test.js +3 -3
- package/src/injection/tests/integration.test.js +2 -1
- package/src/injection/tests/run-tests.js +3 -0
- package/src/injection/validation-engine.js +71 -5
- package/src/linter/determinism-linter.js +20 -5
- package/src/linter/determinism.js +8 -2
- package/src/linter/index.js +3 -1
- package/src/linter/test-doubles.js +151 -4
- package/src/parser/frontmatter.js +6 -0
- package/src/parser/variables.js +7 -1
- package/src/rdf/filters.js +393 -0
- package/src/rdf/index.js +444 -0
- package/src/renderer/deterministic.js +6 -0
- package/src/renderer/index.js +3 -1
- package/src/templates/rdf/DELIVERY-SUMMARY.md +266 -0
- package/src/templates/rdf/README.md +595 -0
- package/src/templates/rdf/dataset.njk +83 -0
- package/src/templates/rdf/index.js +106 -0
- package/src/templates/rdf/jsonld-context.njk +63 -0
- package/src/templates/rdf/ontology.njk +107 -0
- package/src/templates/rdf/schema.njk +79 -0
- package/src/templates/rdf/shapes.njk +89 -0
- package/src/templates/rdf/sparql-queries.njk +70 -0
- package/src/templates/rdf/vocabulary.njk +79 -0
|
@@ -6,19 +6,25 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { promises as fs } from 'fs';
|
|
9
|
-
import { basename, extname } from 'path';
|
|
9
|
+
import { basename as _basename, extname } from 'path';
|
|
10
10
|
import { createHash } from 'crypto';
|
|
11
11
|
|
|
12
12
|
import {
|
|
13
13
|
ERROR_CODES,
|
|
14
|
-
VALIDATION_RULES,
|
|
14
|
+
VALIDATION_RULES as _VALIDATION_RULES,
|
|
15
15
|
BINARY_PATTERNS,
|
|
16
16
|
CONTENT_PATTERNS,
|
|
17
|
-
ENCODINGS,
|
|
17
|
+
ENCODINGS as _ENCODINGS,
|
|
18
18
|
CHECKSUM_ALGORITHMS
|
|
19
19
|
} from './constants.js';
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
*
|
|
23
|
+
*/
|
|
21
24
|
export class ValidationEngine {
|
|
25
|
+
/**
|
|
26
|
+
*
|
|
27
|
+
*/
|
|
22
28
|
constructor(config = {}) {
|
|
23
29
|
this.config = config;
|
|
24
30
|
this.validationCache = new Map();
|
|
@@ -240,6 +246,9 @@ export class ValidationEngine {
|
|
|
240
246
|
* Private validation methods
|
|
241
247
|
*/
|
|
242
248
|
|
|
249
|
+
/**
|
|
250
|
+
*
|
|
251
|
+
*/
|
|
243
252
|
async _validateExistence(target) {
|
|
244
253
|
try {
|
|
245
254
|
const stats = await fs.stat(target.resolvedPath);
|
|
@@ -258,6 +267,9 @@ export class ValidationEngine {
|
|
|
258
267
|
}
|
|
259
268
|
}
|
|
260
269
|
|
|
270
|
+
/**
|
|
271
|
+
*
|
|
272
|
+
*/
|
|
261
273
|
async _validatePermissions(target) {
|
|
262
274
|
try {
|
|
263
275
|
const stats = await fs.stat(target.resolvedPath);
|
|
@@ -274,6 +286,9 @@ export class ValidationEngine {
|
|
|
274
286
|
}
|
|
275
287
|
}
|
|
276
288
|
|
|
289
|
+
/**
|
|
290
|
+
*
|
|
291
|
+
*/
|
|
277
292
|
async _validateNotBinary(target) {
|
|
278
293
|
try {
|
|
279
294
|
// Read first 1KB to check for binary content
|
|
@@ -291,6 +306,9 @@ export class ValidationEngine {
|
|
|
291
306
|
}
|
|
292
307
|
}
|
|
293
308
|
|
|
309
|
+
/**
|
|
310
|
+
*
|
|
311
|
+
*/
|
|
294
312
|
async _validateSize(target) {
|
|
295
313
|
try {
|
|
296
314
|
const stats = await fs.stat(target.resolvedPath);
|
|
@@ -306,6 +324,9 @@ export class ValidationEngine {
|
|
|
306
324
|
}
|
|
307
325
|
}
|
|
308
326
|
|
|
327
|
+
/**
|
|
328
|
+
*
|
|
329
|
+
*/
|
|
309
330
|
async _validateEncoding(target) {
|
|
310
331
|
try {
|
|
311
332
|
const content = await fs.readFile(target.resolvedPath, 'utf8');
|
|
@@ -328,6 +349,9 @@ export class ValidationEngine {
|
|
|
328
349
|
}
|
|
329
350
|
}
|
|
330
351
|
|
|
352
|
+
/**
|
|
353
|
+
*
|
|
354
|
+
*/
|
|
331
355
|
async _validateSyntax(target) {
|
|
332
356
|
const ext = extname(target.resolvedPath).toLowerCase();
|
|
333
357
|
|
|
@@ -353,6 +377,9 @@ export class ValidationEngine {
|
|
|
353
377
|
}
|
|
354
378
|
}
|
|
355
379
|
|
|
380
|
+
/**
|
|
381
|
+
*
|
|
382
|
+
*/
|
|
356
383
|
_validateJavaScript(content) {
|
|
357
384
|
try {
|
|
358
385
|
// Basic syntax check - validate without executing
|
|
@@ -367,6 +394,9 @@ export class ValidationEngine {
|
|
|
367
394
|
}
|
|
368
395
|
}
|
|
369
396
|
|
|
397
|
+
/**
|
|
398
|
+
*
|
|
399
|
+
*/
|
|
370
400
|
_validateTypeScript(content) {
|
|
371
401
|
// TypeScript validation would require the TS compiler
|
|
372
402
|
// For now, just check basic syntax patterns
|
|
@@ -379,6 +409,9 @@ export class ValidationEngine {
|
|
|
379
409
|
};
|
|
380
410
|
}
|
|
381
411
|
|
|
412
|
+
/**
|
|
413
|
+
*
|
|
414
|
+
*/
|
|
382
415
|
_validateJSON(content) {
|
|
383
416
|
try {
|
|
384
417
|
JSON.parse(content);
|
|
@@ -391,6 +424,9 @@ export class ValidationEngine {
|
|
|
391
424
|
}
|
|
392
425
|
}
|
|
393
426
|
|
|
427
|
+
/**
|
|
428
|
+
*
|
|
429
|
+
*/
|
|
394
430
|
async _validateContentSyntax(content, target) {
|
|
395
431
|
const ext = extname(target.resolvedPath).toLowerCase();
|
|
396
432
|
|
|
@@ -407,6 +443,9 @@ export class ValidationEngine {
|
|
|
407
443
|
}
|
|
408
444
|
}
|
|
409
445
|
|
|
446
|
+
/**
|
|
447
|
+
*
|
|
448
|
+
*/
|
|
410
449
|
_validateContentEncoding(content) {
|
|
411
450
|
try {
|
|
412
451
|
// Check if content can be encoded as UTF-8
|
|
@@ -420,10 +459,16 @@ export class ValidationEngine {
|
|
|
420
459
|
}
|
|
421
460
|
}
|
|
422
461
|
|
|
462
|
+
/**
|
|
463
|
+
*
|
|
464
|
+
*/
|
|
423
465
|
_containsBinaryData(content) {
|
|
424
466
|
return BINARY_PATTERNS.some(pattern => pattern.test(content));
|
|
425
467
|
}
|
|
426
468
|
|
|
469
|
+
/**
|
|
470
|
+
*
|
|
471
|
+
*/
|
|
427
472
|
_validateLineEndings(content) {
|
|
428
473
|
const types = [];
|
|
429
474
|
|
|
@@ -437,6 +482,9 @@ export class ValidationEngine {
|
|
|
437
482
|
};
|
|
438
483
|
}
|
|
439
484
|
|
|
485
|
+
/**
|
|
486
|
+
*
|
|
487
|
+
*/
|
|
440
488
|
_isValidUtf8(str) {
|
|
441
489
|
try {
|
|
442
490
|
return str === Buffer.from(str, 'utf8').toString('utf8');
|
|
@@ -445,11 +493,17 @@ export class ValidationEngine {
|
|
|
445
493
|
}
|
|
446
494
|
}
|
|
447
495
|
|
|
496
|
+
/**
|
|
497
|
+
*
|
|
498
|
+
*/
|
|
448
499
|
_looksLikeCode(filePath) {
|
|
449
500
|
const ext = extname(filePath).toLowerCase();
|
|
450
501
|
return ['.js', '.ts', '.jsx', '.tsx', '.mjs'].includes(ext);
|
|
451
502
|
}
|
|
452
503
|
|
|
504
|
+
/**
|
|
505
|
+
*
|
|
506
|
+
*/
|
|
453
507
|
_findDuplicateStatements(content) {
|
|
454
508
|
const duplicates = [];
|
|
455
509
|
const statements = new Set();
|
|
@@ -466,7 +520,10 @@ export class ValidationEngine {
|
|
|
466
520
|
return duplicates;
|
|
467
521
|
}
|
|
468
522
|
|
|
469
|
-
|
|
523
|
+
/**
|
|
524
|
+
*
|
|
525
|
+
*/
|
|
526
|
+
_validateStructure(content, _target) {
|
|
470
527
|
// Basic structural validation
|
|
471
528
|
const brackets = { '(': 0, '[': 0, '{': 0 };
|
|
472
529
|
const closers = { ')': '(', ']': '[', '}': '{' };
|
|
@@ -498,7 +555,10 @@ export class ValidationEngine {
|
|
|
498
555
|
return { valid: true };
|
|
499
556
|
}
|
|
500
557
|
|
|
501
|
-
|
|
558
|
+
/**
|
|
559
|
+
*
|
|
560
|
+
*/
|
|
561
|
+
async _checkNamingConflicts(content, _target) {
|
|
502
562
|
// Simple naming conflict detection
|
|
503
563
|
const conflicts = [];
|
|
504
564
|
|
|
@@ -518,6 +578,9 @@ export class ValidationEngine {
|
|
|
518
578
|
return conflicts;
|
|
519
579
|
}
|
|
520
580
|
|
|
581
|
+
/**
|
|
582
|
+
*
|
|
583
|
+
*/
|
|
521
584
|
_getCacheKey(target) {
|
|
522
585
|
const hash = createHash(CHECKSUM_ALGORITHMS.SHA256);
|
|
523
586
|
hash.update(target.resolvedPath);
|
|
@@ -538,6 +601,9 @@ export class ValidationEngine {
|
|
|
538
601
|
* Custom validation error
|
|
539
602
|
*/
|
|
540
603
|
export class ValidationError extends Error {
|
|
604
|
+
/**
|
|
605
|
+
*
|
|
606
|
+
*/
|
|
541
607
|
constructor(message, errors = []) {
|
|
542
608
|
super(message);
|
|
543
609
|
this.name = 'ValidationError';
|
|
@@ -14,13 +14,19 @@
|
|
|
14
14
|
* Authority: ZERO TOLERANCE for nondeterminism
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import { readFileSync, statSync, readdirSync } from 'fs';
|
|
18
|
-
import { resolve, relative, extname } from 'path';
|
|
19
|
-
import { createHash } from 'crypto';
|
|
17
|
+
import { readFileSync, statSync, readdirSync as _readdirSync } from 'fs';
|
|
18
|
+
import { resolve as _resolve, relative as _relative, extname as _extname } from 'path';
|
|
19
|
+
import { createHash as _createHash } from 'crypto';
|
|
20
20
|
import { glob } from 'glob';
|
|
21
21
|
import consola from 'consola';
|
|
22
22
|
|
|
23
|
+
/**
|
|
24
|
+
*
|
|
25
|
+
*/
|
|
23
26
|
export class DeterminismLinter {
|
|
27
|
+
/**
|
|
28
|
+
*
|
|
29
|
+
*/
|
|
24
30
|
constructor(config = {}) {
|
|
25
31
|
this.config = {
|
|
26
32
|
// CRITICAL LIMITS (ZERO TOLERANCE)
|
|
@@ -206,7 +212,7 @@ export class DeterminismLinter {
|
|
|
206
212
|
* Scan content for violation patterns
|
|
207
213
|
*/
|
|
208
214
|
async scanPatterns(filePath, content, patterns, violations) {
|
|
209
|
-
const
|
|
215
|
+
const _lines = content.split('\n');
|
|
210
216
|
|
|
211
217
|
for (const patternConfig of patterns) {
|
|
212
218
|
const matches = [...content.matchAll(patternConfig.pattern)];
|
|
@@ -250,7 +256,7 @@ export class DeterminismLinter {
|
|
|
250
256
|
// Check for dynamic includes
|
|
251
257
|
const dynamicIncludes = content.match(/{%\s*include\s+[^'"][^%]*%}/g);
|
|
252
258
|
if (dynamicIncludes) {
|
|
253
|
-
dynamicIncludes.forEach((include,
|
|
259
|
+
dynamicIncludes.forEach((include, _index) => {
|
|
254
260
|
const position = this.getLineAndColumn(content, content.indexOf(include));
|
|
255
261
|
violations.push({
|
|
256
262
|
file: filePath,
|
|
@@ -403,6 +409,9 @@ export class DeterminismLinter {
|
|
|
403
409
|
return Math.max(includes, extends_, blocks);
|
|
404
410
|
}
|
|
405
411
|
|
|
412
|
+
/**
|
|
413
|
+
*
|
|
414
|
+
*/
|
|
406
415
|
getLineAndColumn(content, index) {
|
|
407
416
|
const lines = content.substring(0, index).split('\n');
|
|
408
417
|
return {
|
|
@@ -411,11 +420,17 @@ export class DeterminismLinter {
|
|
|
411
420
|
};
|
|
412
421
|
}
|
|
413
422
|
|
|
423
|
+
/**
|
|
424
|
+
*
|
|
425
|
+
*/
|
|
414
426
|
isTemplateFile(filePath) {
|
|
415
427
|
const templateExtensions = ['.njk', '.ejs', '.hbs', '.mustache', '.liquid'];
|
|
416
428
|
return templateExtensions.some(ext => filePath.endsWith(ext));
|
|
417
429
|
}
|
|
418
430
|
|
|
431
|
+
/**
|
|
432
|
+
*
|
|
433
|
+
*/
|
|
419
434
|
isJavaScriptFile(filePath) {
|
|
420
435
|
return filePath.endsWith('.js') || filePath.endsWith('.ts');
|
|
421
436
|
}
|
|
@@ -3,7 +3,13 @@
|
|
|
3
3
|
* Migrated from ~/unjucks with comprehensive determinism checking
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
*
|
|
8
|
+
*/
|
|
6
9
|
export class TemplateLinter {
|
|
10
|
+
/**
|
|
11
|
+
*
|
|
12
|
+
*/
|
|
7
13
|
constructor(options = {}) {
|
|
8
14
|
this.strict = options.strict !== false;
|
|
9
15
|
this.warnOnly = options.warnOnly === true;
|
|
@@ -332,7 +338,7 @@ export class TemplateLinter {
|
|
|
332
338
|
});
|
|
333
339
|
|
|
334
340
|
// Subtract points for warnings
|
|
335
|
-
warnings.forEach(
|
|
341
|
+
warnings.forEach(_warning => {
|
|
336
342
|
score -= 2;
|
|
337
343
|
});
|
|
338
344
|
|
|
@@ -380,7 +386,7 @@ export class TemplateLinter {
|
|
|
380
386
|
}
|
|
381
387
|
];
|
|
382
388
|
|
|
383
|
-
fixes.forEach(({ pattern, replacement, description }) => {
|
|
389
|
+
fixes.forEach(({ pattern, replacement, description: _description }) => {
|
|
384
390
|
const matches = fixed.match(pattern);
|
|
385
391
|
if (matches) {
|
|
386
392
|
fixed = fixed.replace(pattern, replacement);
|