eyeling 1.6.0 → 1.6.1
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/eyeling.js +16 -11
- package/index.js +1 -4
- package/package.json +1 -1
- package/test/api.test.js +32 -47
- package/test/examples.test.js +29 -24
- package/test/package.test.js +27 -15
- package/test/packlist.test.js +14 -17
- /package/examples/{collect-all-in.n3 → log-collect-all-in.n3} +0 -0
- /package/examples/{for-all-in.n3 → log-for-all-in.n3} +0 -0
- /package/examples/{not-includes.n3 → log-not-includes.n3} +0 -0
- /package/examples/{skolem.n3 → log-skolem.n3} +0 -0
- /package/examples/{uri.n3 → log-uri.n3} +0 -0
- /package/examples/output/{collect-all-in.n3 → log-collect-all-in.n3} +0 -0
- /package/examples/output/{for-all-in.n3 → log-for-all-in.n3} +0 -0
- /package/examples/output/{not-includes.n3 → log-not-includes.n3} +0 -0
- /package/examples/output/{skolem.n3 → log-skolem.n3} +0 -0
- /package/examples/output/{uri.n3 → log-uri.n3} +0 -0
package/eyeling.js
CHANGED
|
@@ -2438,6 +2438,11 @@ function listAppendSplit(parts, resElems, subst) {
|
|
|
2438
2438
|
return out;
|
|
2439
2439
|
}
|
|
2440
2440
|
|
|
2441
|
+
function numEqualTerm(t, n, eps = 1e-9) {
|
|
2442
|
+
const v = parseNum(t);
|
|
2443
|
+
return v !== null && Math.abs(v - n) < eps;
|
|
2444
|
+
}
|
|
2445
|
+
|
|
2441
2446
|
// ============================================================================
|
|
2442
2447
|
// Backward proof & builtins mutual recursion — declarations first
|
|
2443
2448
|
// ============================================================================
|
|
@@ -2809,7 +2814,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
|
|
|
2809
2814
|
s2[g.o.name] = new Literal(formatNum(cVal));
|
|
2810
2815
|
return [s2];
|
|
2811
2816
|
}
|
|
2812
|
-
if (g.o
|
|
2817
|
+
if (numEqualTerm(g.o, cVal)) {
|
|
2813
2818
|
return [{ ...subst }];
|
|
2814
2819
|
}
|
|
2815
2820
|
}
|
|
@@ -2874,7 +2879,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
|
|
|
2874
2879
|
s2[g.o.name] = new Literal(formatNum(cVal));
|
|
2875
2880
|
return [s2];
|
|
2876
2881
|
}
|
|
2877
|
-
if (g.o
|
|
2882
|
+
if (numEqualTerm(g.o, cVal)) {
|
|
2878
2883
|
return [{ ...subst }];
|
|
2879
2884
|
}
|
|
2880
2885
|
}
|
|
@@ -2891,7 +2896,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
|
|
|
2891
2896
|
s2[g.o.name] = new Literal(formatNum(cVal));
|
|
2892
2897
|
return [s2];
|
|
2893
2898
|
}
|
|
2894
|
-
if (g.o
|
|
2899
|
+
if (numEqualTerm(g.o, cVal)) {
|
|
2895
2900
|
return [{ ...subst }];
|
|
2896
2901
|
}
|
|
2897
2902
|
}
|
|
@@ -2909,7 +2914,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
|
|
|
2909
2914
|
s2[g.o.name] = new Literal(formatNum(cVal));
|
|
2910
2915
|
return [s2];
|
|
2911
2916
|
}
|
|
2912
|
-
if (g.o
|
|
2917
|
+
if (numEqualTerm(g.o, cVal)) {
|
|
2913
2918
|
return [{ ...subst }];
|
|
2914
2919
|
}
|
|
2915
2920
|
}
|
|
@@ -2928,7 +2933,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
|
|
|
2928
2933
|
s2[g.o.name] = new Literal(formatNum(cVal));
|
|
2929
2934
|
return [s2];
|
|
2930
2935
|
}
|
|
2931
|
-
if (g.o
|
|
2936
|
+
if (numEqualTerm(g.o, cVal)) {
|
|
2932
2937
|
return [{ ...subst }];
|
|
2933
2938
|
}
|
|
2934
2939
|
}
|
|
@@ -2947,7 +2952,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
|
|
|
2947
2952
|
s2[g.o.name] = new Literal(formatNum(cVal));
|
|
2948
2953
|
return [s2];
|
|
2949
2954
|
}
|
|
2950
|
-
if (g.o
|
|
2955
|
+
if (numEqualTerm(g.o, cVal)) {
|
|
2951
2956
|
return [{ ...subst }];
|
|
2952
2957
|
}
|
|
2953
2958
|
}
|
|
@@ -2967,7 +2972,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
|
|
|
2967
2972
|
s2[g.o.name] = new Literal(formatNum(cVal));
|
|
2968
2973
|
return [s2];
|
|
2969
2974
|
}
|
|
2970
|
-
if (g.o
|
|
2975
|
+
if (numEqualTerm(g.o, cVal)) {
|
|
2971
2976
|
return [{ ...subst }];
|
|
2972
2977
|
}
|
|
2973
2978
|
}
|
|
@@ -2987,7 +2992,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
|
|
|
2987
2992
|
s2[g.o.name] = new Literal(formatNum(cVal));
|
|
2988
2993
|
return [s2];
|
|
2989
2994
|
}
|
|
2990
|
-
if (g.o
|
|
2995
|
+
if (numEqualTerm(g.o, cVal)) {
|
|
2991
2996
|
return [{ ...subst }];
|
|
2992
2997
|
}
|
|
2993
2998
|
}
|
|
@@ -3046,7 +3051,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
|
|
|
3046
3051
|
s2[g.o.name] = new Literal(formatNum(cVal));
|
|
3047
3052
|
return [s2];
|
|
3048
3053
|
}
|
|
3049
|
-
if (g.o
|
|
3054
|
+
if (numEqualTerm(g.o, cVal)) {
|
|
3050
3055
|
return [{ ...subst }];
|
|
3051
3056
|
}
|
|
3052
3057
|
}
|
|
@@ -3065,7 +3070,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
|
|
|
3065
3070
|
s2[g.o.name] = new Literal(formatNum(cVal));
|
|
3066
3071
|
return [s2];
|
|
3067
3072
|
}
|
|
3068
|
-
if (g.o
|
|
3073
|
+
if (numEqualTerm(g.o, cVal)) {
|
|
3069
3074
|
return [{ ...subst }];
|
|
3070
3075
|
}
|
|
3071
3076
|
}
|
|
@@ -3084,7 +3089,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
|
|
|
3084
3089
|
s2[g.o.name] = new Literal(formatNum(cVal));
|
|
3085
3090
|
return [s2];
|
|
3086
3091
|
}
|
|
3087
|
-
if (g.o
|
|
3092
|
+
if (numEqualTerm(g.o, cVal)) {
|
|
3088
3093
|
return [{ ...subst }];
|
|
3089
3094
|
}
|
|
3090
3095
|
}
|
package/index.js
CHANGED
|
@@ -19,9 +19,7 @@ function reason(opt = {}, n3_input = '') {
|
|
|
19
19
|
// default: proof comments OFF for API output (machine-friendly)
|
|
20
20
|
// set { proofComments: true } to keep them
|
|
21
21
|
const proofComments =
|
|
22
|
-
|
|
23
|
-
(typeof opt.noProofComments === 'boolean') ? !opt.noProofComments :
|
|
24
|
-
false;
|
|
22
|
+
typeof opt.proofComments === 'boolean' ? opt.proofComments : typeof opt.noProofComments === 'boolean' ? !opt.noProofComments : false;
|
|
25
23
|
|
|
26
24
|
if (!proofComments) args.push('--no-proof-comments'); // CLI already supports this :contentReference[oaicite:1]{index=1}
|
|
27
25
|
|
|
@@ -58,4 +56,3 @@ function reason(opt = {}, n3_input = '') {
|
|
|
58
56
|
module.exports = { reason };
|
|
59
57
|
// small interop nicety for ESM default import
|
|
60
58
|
module.exports.default = module.exports;
|
|
61
|
-
|
package/package.json
CHANGED
package/test/api.test.js
CHANGED
|
@@ -4,9 +4,7 @@ const assert = require('node:assert/strict');
|
|
|
4
4
|
const { reason } = require('..');
|
|
5
5
|
|
|
6
6
|
const TTY = process.stdout.isTTY;
|
|
7
|
-
const C = TTY
|
|
8
|
-
? { g: '\x1b[32m', r: '\x1b[31m', y: '\x1b[33m', dim: '\x1b[2m', n: '\x1b[0m' }
|
|
9
|
-
: { g: '', r: '', y: '', dim: '', n: '' };
|
|
7
|
+
const C = TTY ? { g: '\x1b[32m', r: '\x1b[31m', y: '\x1b[33m', dim: '\x1b[2m', n: '\x1b[0m' } : { g: '', r: '', y: '', dim: '', n: '' };
|
|
10
8
|
|
|
11
9
|
function ok(msg) {
|
|
12
10
|
console.log(`${C.g}OK${C.n} ${msg}`);
|
|
@@ -352,10 +350,7 @@ ${U('a')} ${U('p')} ${U('b')}.
|
|
|
352
350
|
name: '17 heavier reachability: branching graph reach closure',
|
|
353
351
|
opt: { proofComments: false, maxBuffer: 200 * 1024 * 1024 },
|
|
354
352
|
input: reachabilityGraphN3(12),
|
|
355
|
-
expect: [
|
|
356
|
-
new RegExp(`${EX}g0>\\s+<${EX}reach>\\s+<${EX}g12>\\s*\\.`),
|
|
357
|
-
new RegExp(`${EX}g2>\\s+<${EX}reach>\\s+<${EX}g10>\\s*\\.`),
|
|
358
|
-
],
|
|
353
|
+
expect: [new RegExp(`${EX}g0>\\s+<${EX}reach>\\s+<${EX}g12>\\s*\\.`), new RegExp(`${EX}g2>\\s+<${EX}reach>\\s+<${EX}g10>\\s*\\.`)],
|
|
359
354
|
},
|
|
360
355
|
{
|
|
361
356
|
name: '18 heavier taxonomy: diamond subclass inference',
|
|
@@ -383,10 +378,7 @@ ${U('a')} ${U('p')} ${U('b')}.
|
|
|
383
378
|
name: '21 heavier equivalence: sameAs propagation (with symmetric sameAs)',
|
|
384
379
|
opt: { proofComments: false },
|
|
385
380
|
input: sameAsN3(),
|
|
386
|
-
expect: [
|
|
387
|
-
new RegExp(`${EX}b>\\s+<${EX}p>\\s+<${EX}o>\\s*\\.`),
|
|
388
|
-
new RegExp(`${EX}b>\\s+<${EX}sameAs>\\s+<${EX}a>\\s*\\.`),
|
|
389
|
-
],
|
|
381
|
+
expect: [new RegExp(`${EX}b>\\s+<${EX}p>\\s+<${EX}o>\\s*\\.`), new RegExp(`${EX}b>\\s+<${EX}sameAs>\\s+<${EX}a>\\s*\\.`)],
|
|
390
382
|
},
|
|
391
383
|
{
|
|
392
384
|
name: '22 heavier closure: transitive property via generic rule',
|
|
@@ -398,10 +390,7 @@ ${U('c')} ${U('sub')} ${U('d')}.
|
|
|
398
390
|
${U('d')} ${U('sub')} ${U('e')}.
|
|
399
391
|
${transitiveClosureN3('sub')}
|
|
400
392
|
`,
|
|
401
|
-
expect: [
|
|
402
|
-
new RegExp(`${EX}a>\\s+<${EX}sub>\\s+<${EX}e>\\s*\\.`),
|
|
403
|
-
new RegExp(`${EX}b>\\s+<${EX}sub>\\s+<${EX}d>\\s*\\.`),
|
|
404
|
-
],
|
|
393
|
+
expect: [new RegExp(`${EX}a>\\s+<${EX}sub>\\s+<${EX}e>\\s*\\.`), new RegExp(`${EX}b>\\s+<${EX}sub>\\s+<${EX}d>\\s*\\.`)],
|
|
405
394
|
},
|
|
406
395
|
{
|
|
407
396
|
name: '23 heavier social: symmetric + reachFriend closure',
|
|
@@ -416,10 +405,7 @@ ${transitiveClosureN3('sub')}
|
|
|
416
405
|
name: '24 heavier volume: 400 facts, simple rewrite rule p -> q',
|
|
417
406
|
opt: { proofComments: false, maxBuffer: 200 * 1024 * 1024 },
|
|
418
407
|
input: bigFactsN3(400),
|
|
419
|
-
expect: [
|
|
420
|
-
new RegExp(`${EX}x>\\s+<${EX}q>\\s+<${EX}o0>\\s*\\.`),
|
|
421
|
-
new RegExp(`${EX}x>\\s+<${EX}q>\\s+<${EX}o399>\\s*\\.`),
|
|
422
|
-
],
|
|
408
|
+
expect: [new RegExp(`${EX}x>\\s+<${EX}q>\\s+<${EX}o0>\\s*\\.`), new RegExp(`${EX}x>\\s+<${EX}q>\\s+<${EX}o399>\\s*\\.`)],
|
|
423
409
|
},
|
|
424
410
|
{
|
|
425
411
|
name: '25 heavier negative entailment: batch + forbidden => false (expect exit 2)',
|
|
@@ -505,10 +491,7 @@ ${U('c')} ${U('p')} ${U('d')}.
|
|
|
505
491
|
|
|
506
492
|
{ ?s ${U('p')} ?o. } => { ?s ${U('q')} ?o. }.
|
|
507
493
|
`,
|
|
508
|
-
expect: [
|
|
509
|
-
new RegExp(`${EX}a>\\s+<${EX}q>\\s+<${EX}b>\\s*\\.`),
|
|
510
|
-
new RegExp(`${EX}c>\\s+<${EX}q>\\s+<${EX}d>\\s*\\.`),
|
|
511
|
-
],
|
|
494
|
+
expect: [new RegExp(`${EX}a>\\s+<${EX}q>\\s+<${EX}b>\\s*\\.`), new RegExp(`${EX}c>\\s+<${EX}q>\\s+<${EX}d>\\s*\\.`)],
|
|
512
495
|
},
|
|
513
496
|
|
|
514
497
|
{
|
|
@@ -554,10 +537,7 @@ ${U('s')} ${U('p')} ${U('o')}.
|
|
|
554
537
|
|
|
555
538
|
{ ${U('s')} ${U('p')} ${U('o')}. } => { ${U('s')} ${U('q')} ${U('o')}. ${U('s')} ${U('r')} ${U('o')}. }.
|
|
556
539
|
`,
|
|
557
|
-
expect: [
|
|
558
|
-
new RegExp(`${EX}s>\\s+<${EX}q>\\s+<${EX}o>\\s*\\.`),
|
|
559
|
-
new RegExp(`${EX}s>\\s+<${EX}r>\\s+<${EX}o>\\s*\\.`),
|
|
560
|
-
],
|
|
540
|
+
expect: [new RegExp(`${EX}s>\\s+<${EX}q>\\s+<${EX}o>\\s*\\.`), new RegExp(`${EX}s>\\s+<${EX}r>\\s+<${EX}o>\\s*\\.`)],
|
|
561
541
|
},
|
|
562
542
|
|
|
563
543
|
{
|
|
@@ -637,56 +617,61 @@ world"""@en.`,
|
|
|
637
617
|
expect: [new RegExp(`${EX}s>\\s+<${EX}q>\\s+(?:"""Hello[\\s\\S]*?world"""@en|"Hello\\\\nworld"@en)\\s*\\.`)],
|
|
638
618
|
},
|
|
639
619
|
|
|
640
|
-
{
|
|
620
|
+
{
|
|
621
|
+
name: '44 syntax: "<-" in predicate position swaps subject and object',
|
|
641
622
|
opt: { proofComments: false },
|
|
642
623
|
input: ` { ?s ${U('p')} ?o } => { ?s ${U('q')} ?o }.
|
|
643
624
|
${U('a')} <-${U('p')} ${U('b')}.`,
|
|
644
625
|
expect: [new RegExp(`${EX}b>\\s+<${EX}q>\\s+<${EX}a>\\s*\\.`)],
|
|
645
626
|
},
|
|
646
627
|
|
|
647
|
-
{
|
|
628
|
+
{
|
|
629
|
+
name: '45 syntax: "<-" works inside blank node property lists ([ ... ])',
|
|
648
630
|
opt: { proofComments: false },
|
|
649
631
|
input: ` ${U('s')} ${U('p')} [ <-${U('r')} ${U('o')} ].
|
|
650
632
|
{ ${U('o')} ${U('r')} ?x } => { ?x ${U('q')} ${U('k')} }.`,
|
|
651
633
|
expect: [new RegExp(`_:b1\\s+<${EX}q>\\s+<${EX}k>\\s*\\.`)],
|
|
652
634
|
},
|
|
653
635
|
|
|
654
|
-
{
|
|
636
|
+
{
|
|
637
|
+
name: '46 syntax: N3 resource paths (! / ^) expand to blank-node triples (forward chain)',
|
|
655
638
|
opt: { proofComments: false },
|
|
656
639
|
input: ` ${U('joe')}!${U('hasAddress')}!${U('hasCity')} ${U('name')} "Metropolis".
|
|
657
640
|
{ ${U('joe')} ${U('hasAddress')} ?a } => { ?a ${U('q')} "addr" }.
|
|
658
641
|
{ ?a ${U('hasCity')} ?c } => { ?c ${U('q')} "city" }.
|
|
659
642
|
`,
|
|
660
|
-
expect: [
|
|
661
|
-
new RegExp(`_:b1\\s+<${EX}q>\\s+"addr"\\s*\\.`),
|
|
662
|
-
new RegExp(`_:b2\\s+<${EX}q>\\s+"city"\\s*\\.`),
|
|
663
|
-
],
|
|
643
|
+
expect: [new RegExp(`_:b1\\s+<${EX}q>\\s+"addr"\\s*\\.`), new RegExp(`_:b2\\s+<${EX}q>\\s+"city"\\s*\\.`)],
|
|
664
644
|
},
|
|
665
645
|
|
|
666
|
-
{
|
|
646
|
+
{
|
|
647
|
+
name: '47 syntax: N3 resource paths support reverse steps (^) in the chain',
|
|
667
648
|
opt: { proofComments: false },
|
|
668
649
|
input: ` ${U('joe')}!${U('hasMother')}^${U('hasMother')} ${U('knows')} ${U('someone')}.
|
|
669
650
|
{ ?sib ${U('hasMother')} ?mom. ${U('joe')} ${U('hasMother')} ?mom } => { ?sib ${U('q')} ${U('joe')} }.
|
|
670
651
|
`,
|
|
671
|
-
expect: [
|
|
672
|
-
new RegExp(`_:b2\\s+<${EX}q>\\s+<${EX}joe>\\s*\\.`),
|
|
673
|
-
],
|
|
652
|
+
expect: [new RegExp(`_:b2\\s+<${EX}q>\\s+<${EX}joe>\\s*\\.`)],
|
|
674
653
|
},
|
|
675
654
|
|
|
676
|
-
{
|
|
677
|
-
|
|
655
|
+
{
|
|
656
|
+
name: '48 rdf:first: works on list terms (alias of list:first)',
|
|
657
|
+
opt: { proofComments: false },
|
|
658
|
+
input: ` { ( ${U('a')} ${U('b')} ${U('c')} ) rdf:first ?x. } => { ${U('s')} ${U('first')} ?x. }.
|
|
678
659
|
`,
|
|
679
660
|
expect: [new RegExp(`${EX}s>\\s+<${EX}first>\\s+<${EX}a>\\s*\\.`)],
|
|
680
661
|
},
|
|
681
662
|
|
|
682
|
-
{
|
|
683
|
-
|
|
663
|
+
{
|
|
664
|
+
name: '49 rdf:rest: works on list terms (alias of list:rest)',
|
|
665
|
+
opt: { proofComments: false },
|
|
666
|
+
input: ` { ( ${U('a')} ${U('b')} ${U('c')} ) rdf:rest ?r. ?r rdf:first ?y. } => { ${U('s')} ${U('second')} ?y. }.
|
|
684
667
|
`,
|
|
685
668
|
expect: [new RegExp(`${EX}s>\\s+<${EX}second>\\s+<${EX}b>\\s*\\.`)],
|
|
686
669
|
},
|
|
687
670
|
|
|
688
|
-
{
|
|
689
|
-
|
|
671
|
+
{
|
|
672
|
+
name: '50 rdf collection materialization: rdf:first/rdf:rest triples become list terms',
|
|
673
|
+
opt: { proofComments: false },
|
|
674
|
+
input: ` ${U('s')} ${U('p')} _:l1.
|
|
690
675
|
_:l1 rdf:first ${U('a')}.
|
|
691
676
|
_:l1 rdf:rest _:l2.
|
|
692
677
|
_:l2 rdf:first ${U('b')}.
|
|
@@ -741,7 +726,7 @@ let failed = 0;
|
|
|
741
726
|
fail(
|
|
742
727
|
`Expected exit code ${tc.expectErrorCode}, got: ${e && e.code != null ? e.code : 'unknown'}\n${
|
|
743
728
|
e && e.stderr ? e.stderr : e && e.stack ? e.stack : String(e)
|
|
744
|
-
}
|
|
729
|
+
}`,
|
|
745
730
|
);
|
|
746
731
|
failed++;
|
|
747
732
|
continue;
|
|
@@ -761,7 +746,8 @@ let failed = 0;
|
|
|
761
746
|
|
|
762
747
|
console.log('');
|
|
763
748
|
const suiteMs = Date.now() - suiteStart;
|
|
764
|
-
console.log(`${C.y}==${C.n} Total elapsed: ${suiteMs} ms`);
|
|
749
|
+
console.log(`${C.y}==${C.n} Total elapsed: ${suiteMs} ms (${(suiteMs / 1000).toFixed(2)} s)`);
|
|
750
|
+
|
|
765
751
|
if (failed === 0) {
|
|
766
752
|
ok(`All API tests passed (${passed}/${cases.length})`);
|
|
767
753
|
process.exit(0);
|
|
@@ -770,4 +756,3 @@ let failed = 0;
|
|
|
770
756
|
process.exit(1);
|
|
771
757
|
}
|
|
772
758
|
})();
|
|
773
|
-
|
package/test/examples.test.js
CHANGED
|
@@ -7,13 +7,18 @@ const path = require('node:path');
|
|
|
7
7
|
const cp = require('node:child_process');
|
|
8
8
|
|
|
9
9
|
const TTY = process.stdout.isTTY;
|
|
10
|
-
const C = TTY
|
|
11
|
-
|
|
12
|
-
: { g: '', r: '', y: '', dim: '', n: '' };
|
|
10
|
+
const C = TTY ? { g: '\x1b[32m', r: '\x1b[31m', y: '\x1b[33m', dim: '\x1b[2m', n: '\x1b[0m' } : { g: '', r: '', y: '', dim: '', n: '' };
|
|
11
|
+
const msTag = (ms) => `${C.dim}(${ms} ms)${C.n}`;
|
|
13
12
|
|
|
14
|
-
function ok(msg)
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
function ok(msg) {
|
|
14
|
+
console.log(`${C.g}OK${C.n} ${msg}`);
|
|
15
|
+
}
|
|
16
|
+
function fail(msg) {
|
|
17
|
+
console.error(`${C.r}FAIL${C.n} ${msg}`);
|
|
18
|
+
}
|
|
19
|
+
function info(msg) {
|
|
20
|
+
console.log(`${C.y}==${C.n} ${msg}`);
|
|
21
|
+
}
|
|
17
22
|
|
|
18
23
|
function run(cmd, args, opts = {}) {
|
|
19
24
|
return cp.spawnSync(cmd, args, {
|
|
@@ -57,7 +62,9 @@ function mkTmpDir() {
|
|
|
57
62
|
}
|
|
58
63
|
|
|
59
64
|
function rmrf(p) {
|
|
60
|
-
try {
|
|
65
|
+
try {
|
|
66
|
+
fs.rmSync(p, { recursive: true, force: true });
|
|
67
|
+
} catch {}
|
|
61
68
|
}
|
|
62
69
|
|
|
63
70
|
function showDiff({ IN_GIT, examplesDir, expectedPath, generatedPath, relExpectedPosix }) {
|
|
@@ -103,13 +110,12 @@ function main() {
|
|
|
103
110
|
|
|
104
111
|
const IN_GIT = inGitWorktree(root);
|
|
105
112
|
|
|
106
|
-
const files = fs
|
|
107
|
-
.
|
|
113
|
+
const files = fs
|
|
114
|
+
.readdirSync(examplesDir)
|
|
115
|
+
.filter((f) => f.endsWith('.n3'))
|
|
108
116
|
.sort((a, b) => a.localeCompare(b));
|
|
109
117
|
|
|
110
|
-
info(
|
|
111
|
-
`Running ${files.length} examples tests (${IN_GIT ? 'git worktree mode' : 'npm-installed mode'})`
|
|
112
|
-
);
|
|
118
|
+
info(`Running ${files.length} examples tests (${IN_GIT ? 'git worktree mode' : 'npm-installed mode'})`);
|
|
113
119
|
console.log(`${C.dim}${getEyelingVersion(nodePath, eyelingJsPath, root)}; node ${process.version}${C.n}`);
|
|
114
120
|
|
|
115
121
|
if (files.length === 0) {
|
|
@@ -138,7 +144,7 @@ function main() {
|
|
|
138
144
|
n3Text = fs.readFileSync(filePath, 'utf8');
|
|
139
145
|
} catch (e) {
|
|
140
146
|
const ms = Date.now() - start;
|
|
141
|
-
fail(`${idx} ${file}
|
|
147
|
+
fail(`${idx} ${file} ${msTag(ms)}`);
|
|
142
148
|
fail(`Cannot read input: ${e.message}`);
|
|
143
149
|
failed++;
|
|
144
150
|
continue;
|
|
@@ -154,7 +160,7 @@ function main() {
|
|
|
154
160
|
// npm-installed / no .git: never modify output/ in node_modules
|
|
155
161
|
if (!fs.existsSync(expectedPath)) {
|
|
156
162
|
const ms = Date.now() - start;
|
|
157
|
-
fail(`${idx} ${file}
|
|
163
|
+
fail(`${idx} ${file} ${msTag(ms)}`);
|
|
158
164
|
fail(`Missing expected output/${file}`);
|
|
159
165
|
failed++;
|
|
160
166
|
continue;
|
|
@@ -170,12 +176,12 @@ function main() {
|
|
|
170
176
|
cwd: examplesDir,
|
|
171
177
|
stdio: ['ignore', outFd, 'pipe'], // stdout -> file, stderr captured
|
|
172
178
|
maxBuffer: 200 * 1024 * 1024,
|
|
173
|
-
encoding: 'utf8'
|
|
179
|
+
encoding: 'utf8',
|
|
174
180
|
});
|
|
175
181
|
|
|
176
182
|
fs.closeSync(outFd);
|
|
177
183
|
|
|
178
|
-
const rc =
|
|
184
|
+
const rc = r.status == null ? 1 : r.status;
|
|
179
185
|
|
|
180
186
|
const ms = Date.now() - start;
|
|
181
187
|
|
|
@@ -183,28 +189,28 @@ function main() {
|
|
|
183
189
|
let diffOk = false;
|
|
184
190
|
if (IN_GIT) {
|
|
185
191
|
const d = run('git', ['diff', '--quiet', '--', relExpectedPosix], { cwd: examplesDir });
|
|
186
|
-
diffOk =
|
|
192
|
+
diffOk = d.status === 0;
|
|
187
193
|
} else {
|
|
188
194
|
if (hasGit()) {
|
|
189
195
|
const d = run('git', ['diff', '--no-index', '--quiet', expectedPath, generatedPath], { cwd: examplesDir });
|
|
190
|
-
diffOk =
|
|
196
|
+
diffOk = d.status === 0;
|
|
191
197
|
} else {
|
|
192
198
|
const d = run('diff', ['-u', expectedPath, generatedPath], { cwd: examplesDir });
|
|
193
|
-
diffOk =
|
|
199
|
+
diffOk = d.status === 0;
|
|
194
200
|
}
|
|
195
201
|
}
|
|
196
202
|
|
|
197
|
-
const rcOk =
|
|
203
|
+
const rcOk = rc === expectedRc;
|
|
198
204
|
|
|
199
205
|
if (diffOk && rcOk) {
|
|
200
206
|
if (expectedRc === 0) {
|
|
201
|
-
ok(`${idx} ${file}
|
|
207
|
+
ok(`${idx} ${file} ${msTag(ms)}`);
|
|
202
208
|
} else {
|
|
203
|
-
ok(`${idx} ${file} (expected exit ${expectedRc}
|
|
209
|
+
ok(`${idx} ${file} (expected exit ${expectedRc}) ${msTag(ms)}`);
|
|
204
210
|
}
|
|
205
211
|
passed++;
|
|
206
212
|
} else {
|
|
207
|
-
fail(`${idx} ${file}
|
|
213
|
+
fail(`${idx} ${file} ${msTag(ms)}`);
|
|
208
214
|
if (!rcOk) {
|
|
209
215
|
fail(`Exit code ${rc}, expected ${expectedRc}`);
|
|
210
216
|
}
|
|
@@ -242,4 +248,3 @@ function main() {
|
|
|
242
248
|
}
|
|
243
249
|
|
|
244
250
|
main();
|
|
245
|
-
|
package/test/package.test.js
CHANGED
|
@@ -7,19 +7,29 @@ const path = require('node:path');
|
|
|
7
7
|
const cp = require('node:child_process');
|
|
8
8
|
|
|
9
9
|
const TTY = process.stdout.isTTY;
|
|
10
|
-
const C = TTY
|
|
11
|
-
? { g: '\x1b[32m', r: '\x1b[31m', y: '\x1b[33m', dim: '\x1b[2m', n: '\x1b[0m' }
|
|
12
|
-
: { g: '', r: '', y: '', dim: '', n: '' };
|
|
10
|
+
const C = TTY ? { g: '\x1b[32m', r: '\x1b[31m', y: '\x1b[33m', dim: '\x1b[2m', n: '\x1b[0m' } : { g: '', r: '', y: '', dim: '', n: '' };
|
|
13
11
|
|
|
14
|
-
function info(msg) {
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
function info(msg) {
|
|
13
|
+
console.log(`${C.y}==${C.n} ${msg}`);
|
|
14
|
+
}
|
|
15
|
+
function ok(msg) {
|
|
16
|
+
console.log(`${C.g}OK${C.n} ${msg}`);
|
|
17
|
+
}
|
|
18
|
+
function fail(msg) {
|
|
19
|
+
console.error(`${C.r}FAIL${C.n} ${msg}`);
|
|
20
|
+
}
|
|
17
21
|
|
|
18
|
-
function isWin() {
|
|
19
|
-
|
|
22
|
+
function isWin() {
|
|
23
|
+
return process.platform === 'win32';
|
|
24
|
+
}
|
|
25
|
+
function npmCmd() {
|
|
26
|
+
return isWin() ? 'npm.cmd' : 'npm';
|
|
27
|
+
}
|
|
20
28
|
|
|
21
29
|
function rmrf(p) {
|
|
22
|
-
try {
|
|
30
|
+
try {
|
|
31
|
+
fs.rmSync(p, { recursive: true, force: true });
|
|
32
|
+
} catch {}
|
|
23
33
|
}
|
|
24
34
|
|
|
25
35
|
function run(cmd, args, opts = {}) {
|
|
@@ -49,7 +59,10 @@ function runChecked(cmd, args, opts = {}) {
|
|
|
49
59
|
function packTarball(root) {
|
|
50
60
|
// `npm pack --silent` prints the filename (usually one line)
|
|
51
61
|
const res = runChecked(npmCmd(), ['pack', '--silent'], { cwd: root });
|
|
52
|
-
const out = String(res.stdout || '')
|
|
62
|
+
const out = String(res.stdout || '')
|
|
63
|
+
.trim()
|
|
64
|
+
.split(/\r?\n/)
|
|
65
|
+
.filter(Boolean);
|
|
53
66
|
if (out.length === 0) throw new Error('npm pack produced no output');
|
|
54
67
|
return out[out.length - 1].trim(); // tarball filename in root
|
|
55
68
|
}
|
|
@@ -97,9 +110,7 @@ function main() {
|
|
|
97
110
|
ok('API works');
|
|
98
111
|
|
|
99
112
|
info('CLI smoke test');
|
|
100
|
-
const bin = isWin()
|
|
101
|
-
? path.join(tmp, 'node_modules', '.bin', 'eyeling.cmd')
|
|
102
|
-
: path.join(tmp, 'node_modules', '.bin', 'eyeling');
|
|
113
|
+
const bin = isWin() ? path.join(tmp, 'node_modules', '.bin', 'eyeling.cmd') : path.join(tmp, 'node_modules', '.bin', 'eyeling');
|
|
103
114
|
runChecked(bin, ['-v'], { cwd: tmp, stdio: 'inherit' });
|
|
104
115
|
ok('CLI works');
|
|
105
116
|
|
|
@@ -121,7 +132,9 @@ function main() {
|
|
|
121
132
|
if (tgzInRoot) {
|
|
122
133
|
const maybe = path.join(root, tgzInRoot);
|
|
123
134
|
if (fs.existsSync(maybe)) {
|
|
124
|
-
try {
|
|
135
|
+
try {
|
|
136
|
+
fs.unlinkSync(maybe);
|
|
137
|
+
} catch {}
|
|
125
138
|
}
|
|
126
139
|
}
|
|
127
140
|
cleanup();
|
|
@@ -129,4 +142,3 @@ function main() {
|
|
|
129
142
|
}
|
|
130
143
|
|
|
131
144
|
main();
|
|
132
|
-
|
package/test/packlist.test.js
CHANGED
|
@@ -5,13 +5,17 @@ const cp = require('node:child_process');
|
|
|
5
5
|
const fs = require('node:fs');
|
|
6
6
|
|
|
7
7
|
const TTY = process.stdout.isTTY;
|
|
8
|
-
const C = TTY
|
|
9
|
-
? { g: '\x1b[32m', r: '\x1b[31m', y: '\x1b[33m', n: '\x1b[0m' }
|
|
10
|
-
: { g: '', r: '', y: '', n: '' };
|
|
8
|
+
const C = TTY ? { g: '\x1b[32m', r: '\x1b[31m', y: '\x1b[33m', n: '\x1b[0m' } : { g: '', r: '', y: '', n: '' };
|
|
11
9
|
|
|
12
|
-
function ok(msg) {
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
function ok(msg) {
|
|
11
|
+
console.log(`${C.g}OK${C.n} ${msg}`);
|
|
12
|
+
}
|
|
13
|
+
function info(msg) {
|
|
14
|
+
console.log(`${C.y}${msg}${C.n}`);
|
|
15
|
+
}
|
|
16
|
+
function fail(msg) {
|
|
17
|
+
console.error(`${C.r}FAIL${C.n} ${msg}`);
|
|
18
|
+
}
|
|
15
19
|
|
|
16
20
|
try {
|
|
17
21
|
info('Checking packlist + metadata…');
|
|
@@ -37,21 +41,15 @@ try {
|
|
|
37
41
|
}
|
|
38
42
|
|
|
39
43
|
const pack = JSON.parse(packJson)[0];
|
|
40
|
-
const paths = new Set(pack.files.map(f => f.path));
|
|
44
|
+
const paths = new Set(pack.files.map((f) => f.path));
|
|
41
45
|
|
|
42
|
-
const mustHave = [
|
|
43
|
-
'package.json',
|
|
44
|
-
'README.md',
|
|
45
|
-
'LICENSE.md',
|
|
46
|
-
'eyeling.js',
|
|
47
|
-
'index.js',
|
|
48
|
-
];
|
|
46
|
+
const mustHave = ['package.json', 'README.md', 'LICENSE.md', 'eyeling.js', 'index.js'];
|
|
49
47
|
|
|
50
48
|
for (const p of mustHave) assert.ok(paths.has(p), `missing from npm pack: ${p}`);
|
|
51
49
|
|
|
52
50
|
assert.ok(
|
|
53
|
-
[...paths].some(p => p.startsWith('examples/output/')),
|
|
54
|
-
'missing from npm pack: examples/output/*'
|
|
51
|
+
[...paths].some((p) => p.startsWith('examples/output/')),
|
|
52
|
+
'missing from npm pack: examples/output/*',
|
|
55
53
|
);
|
|
56
54
|
|
|
57
55
|
ok('packlist + metadata sanity checks passed');
|
|
@@ -59,4 +57,3 @@ try {
|
|
|
59
57
|
fail(e && e.stack ? e.stack : String(e));
|
|
60
58
|
process.exit(1);
|
|
61
59
|
}
|
|
62
|
-
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|