@factoidal/core 0.7.1 → 0.11.0
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/CHANGELOG.md +616 -1
- package/NOTICE +2 -21
- package/README.md +123 -993
- package/api.d.ts +53 -0
- package/api.js +5 -0
- package/api.mjs +56 -0
- package/bin/engine.mjs +38 -19
- package/bin/ext.mjs +16 -20
- package/bin/factoidal.mjs +667 -118
- package/bin/pack.mjs +37 -0
- package/bin/serve-worker.mjs +32 -0
- package/bin/serve.mjs +423 -0
- package/bin/store-worker-host.mjs +1 -1
- package/bin/store.mjs +1 -1
- package/browser.d.ts +114 -507
- package/browser.js +155 -2257
- package/docs/fuseki-replacement.md +108 -0
- package/fn.d.ts +25 -96
- package/fn.js +131 -240
- package/index.d.ts +620 -260
- package/index.js +4 -234
- package/index.mjs +180 -84
- package/l4-assets/l4factoidal.js +47 -7
- package/l4-assets/l4factoidal.mjs +1 -1
- package/l4-assets/l4factoidal.wasm +0 -0
- package/l4-assets/version.json +11 -7
- package/lib/api.mjs +2337 -0
- package/lib/browser-engine.mjs +69 -0
- package/lib/dataset.mjs +471 -0
- package/lib/delta-log-hosts.mjs +191 -0
- package/lib/lean-entry.mjs +213 -0
- package/lib/pure.mjs +98 -0
- package/lib/store.mjs +115 -0
- package/lib/version.mjs +5 -0
- package/lws/README.md +137 -0
- package/lws/persist.mjs +78 -0
- package/lws/server.mjs +416 -0
- package/package.json +59 -61
- package/rdfjs.js +5 -536
- package/rdfjs.mjs +517 -0
- package/sample-store.d.ts +8 -16
- package/sample-store.mjs +39 -29
- package/solid/client/README.md +100 -0
- package/solid/client/index.mjs +293 -0
- package/solid/server/README.md +96 -0
- package/solid/server/index.mjs +395 -0
- package/store-host/deno.mjs +8 -0
- package/store-host/index.mjs +12 -0
- package/store-host/node.mjs +8 -0
- package/xmpp/README.md +107 -0
- package/xmpp/index.mjs +229 -0
- package/browser-wasm.js +0 -872
- package/factoidal-npm-entry.js +0 -15477
- package/factoidal-npm-entry.wasm.assets/code-5a7fc68f2ab1323718b8.wasm +0 -0
- package/factoidal-npm-entry.wasm.js +0 -455
- package/factoidal.js +0 -13118
- package/factoidal.wasm.assets/code-bbe6099bfb5b10c4c3ab.wasm +0 -0
- package/factoidal.wasm.js +0 -457
- package/hacl-init.js +0 -92
- package/hacl-wasm/FStar.wasm +0 -0
- package/hacl-wasm/Hacl_Bignum.wasm +0 -0
- package/hacl-wasm/Hacl_Bignum25519_51.wasm +0 -0
- package/hacl-wasm/Hacl_Bignum_Base.wasm +0 -0
- package/hacl-wasm/Hacl_Curve25519_51.wasm +0 -0
- package/hacl-wasm/Hacl_Ed25519.wasm +0 -0
- package/hacl-wasm/Hacl_Ed25519_PrecompTable.wasm +0 -0
- package/hacl-wasm/Hacl_Hash_Base.wasm +0 -0
- package/hacl-wasm/Hacl_Hash_SHA2.wasm +0 -0
- package/hacl-wasm/Hacl_IntTypes_Intrinsics.wasm +0 -0
- package/hacl-wasm/LowStar_Endianness.wasm +0 -0
- package/hacl-wasm/WasmSupport.wasm +0 -0
- package/hacl-wasm/api.js +0 -775
- package/hacl-wasm/api.json +0 -3787
- package/hacl-wasm/layouts.json +0 -1
- package/hacl-wasm/loader.js +0 -568
- package/hacl-wasm/shell.js +0 -12
- package/l4-core.d.ts +0 -159
- package/l4-core.js +0 -188
- package/l4.d.ts +0 -50
- package/l4.js +0 -104
- package/lib/api.js +0 -2300
- package/lib/engine-js.js +0 -165
- package/lib/engine-wasm.js +0 -300
- package/sample-store/CURRENT +0 -1
- package/sample-store/gen-1/manifest.sbm2 +0 -0
- package/sample-store/gen-1/manifest.tsv +0 -14
- package/sample-store/gen-1/predicate-0.ibk3 +0 -0
- package/sample-store/gen-1/predicate-0.ibk3.merkle +0 -1
- package/sample-store/gen-1/predicate-0.ibk3.oli2 +0 -0
- package/sample-store/gen-1/predicate-0.ibk3.oli2.merkle +0 -1
- package/sample-store/gen-1/predicate-0.ibk3.sri2 +0 -0
- package/sample-store/gen-1/predicate-0.ibk3.sri2.merkle +0 -1
- package/sample-store/gen-1/predicate-0.ibk3.tli1 +0 -0
- package/sample-store/gen-1/predicate-0.ibk3.tli1.merkle +0 -0
- package/sample-store/gen-1/predicate-1.ibk3 +0 -0
- package/sample-store/gen-1/predicate-1.ibk3.merkle +0 -0
- package/sample-store/gen-1/predicate-1.ibk3.oli2 +0 -0
- package/sample-store/gen-1/predicate-1.ibk3.oli2.merkle +0 -0
- package/sample-store/gen-1/predicate-1.ibk3.sri2 +0 -0
- package/sample-store/gen-1/predicate-1.ibk3.sri2.merkle +0 -1
- package/sample-store/gen-1/predicate-1.ibk3.tli1 +0 -0
- package/sample-store/gen-1/predicate-1.ibk3.tli1.merkle +0 -1
- package/sample-store/gen-1/predicate-10.ibk3 +0 -0
- package/sample-store/gen-1/predicate-10.ibk3.merkle +0 -1
- package/sample-store/gen-1/predicate-10.ibk3.oli2 +0 -0
- package/sample-store/gen-1/predicate-10.ibk3.oli2.merkle +0 -0
- package/sample-store/gen-1/predicate-10.ibk3.sri2 +0 -0
- package/sample-store/gen-1/predicate-10.ibk3.sri2.merkle +0 -1
- package/sample-store/gen-1/predicate-10.ibk3.tli1 +0 -0
- package/sample-store/gen-1/predicate-10.ibk3.tli1.merkle +0 -1
- package/sample-store/gen-1/predicate-11.ibk3 +0 -0
- package/sample-store/gen-1/predicate-11.ibk3.merkle +0 -0
- package/sample-store/gen-1/predicate-11.ibk3.oli2 +0 -0
- package/sample-store/gen-1/predicate-11.ibk3.oli2.merkle +0 -1
- package/sample-store/gen-1/predicate-11.ibk3.sri2 +0 -0
- package/sample-store/gen-1/predicate-11.ibk3.sri2.merkle +0 -1
- package/sample-store/gen-1/predicate-11.ibk3.tli1 +0 -0
- package/sample-store/gen-1/predicate-11.ibk3.tli1.merkle +0 -1
- package/sample-store/gen-1/predicate-12.ibk3 +0 -0
- package/sample-store/gen-1/predicate-12.ibk3.merkle +0 -1
- package/sample-store/gen-1/predicate-12.ibk3.oli2 +0 -0
- package/sample-store/gen-1/predicate-12.ibk3.oli2.merkle +0 -1
- package/sample-store/gen-1/predicate-12.ibk3.sri2 +0 -0
- package/sample-store/gen-1/predicate-12.ibk3.sri2.merkle +0 -1
- package/sample-store/gen-1/predicate-12.ibk3.tli1 +0 -0
- package/sample-store/gen-1/predicate-12.ibk3.tli1.merkle +0 -1
- package/sample-store/gen-1/predicate-2.ibk3 +0 -0
- package/sample-store/gen-1/predicate-2.ibk3.merkle +0 -1
- package/sample-store/gen-1/predicate-2.ibk3.oli2 +0 -0
- package/sample-store/gen-1/predicate-2.ibk3.oli2.merkle +0 -1
- package/sample-store/gen-1/predicate-2.ibk3.sri2 +0 -0
- package/sample-store/gen-1/predicate-2.ibk3.sri2.merkle +0 -0
- package/sample-store/gen-1/predicate-2.ibk3.tli1 +0 -0
- package/sample-store/gen-1/predicate-2.ibk3.tli1.merkle +0 -0
- package/sample-store/gen-1/predicate-3.ibk3 +0 -0
- package/sample-store/gen-1/predicate-3.ibk3.merkle +0 -1
- package/sample-store/gen-1/predicate-3.ibk3.oli2 +0 -0
- package/sample-store/gen-1/predicate-3.ibk3.oli2.merkle +0 -1
- package/sample-store/gen-1/predicate-3.ibk3.sri2 +0 -0
- package/sample-store/gen-1/predicate-3.ibk3.sri2.merkle +0 -1
- package/sample-store/gen-1/predicate-3.ibk3.tli1 +0 -0
- package/sample-store/gen-1/predicate-3.ibk3.tli1.merkle +0 -1
- package/sample-store/gen-1/predicate-4.ibk3 +0 -0
- package/sample-store/gen-1/predicate-4.ibk3.merkle +0 -0
- package/sample-store/gen-1/predicate-4.ibk3.oli2 +0 -0
- package/sample-store/gen-1/predicate-4.ibk3.oli2.merkle +0 -1
- package/sample-store/gen-1/predicate-4.ibk3.sri2 +0 -0
- package/sample-store/gen-1/predicate-4.ibk3.sri2.merkle +0 -1
- package/sample-store/gen-1/predicate-4.ibk3.tli1 +0 -0
- package/sample-store/gen-1/predicate-4.ibk3.tli1.merkle +0 -2
- package/sample-store/gen-1/predicate-5.ibk3 +0 -0
- package/sample-store/gen-1/predicate-5.ibk3.merkle +0 -1
- package/sample-store/gen-1/predicate-5.ibk3.oli2 +0 -0
- package/sample-store/gen-1/predicate-5.ibk3.oli2.merkle +0 -1
- package/sample-store/gen-1/predicate-5.ibk3.sri2 +0 -0
- package/sample-store/gen-1/predicate-5.ibk3.sri2.merkle +0 -1
- package/sample-store/gen-1/predicate-5.ibk3.tli1 +0 -0
- package/sample-store/gen-1/predicate-5.ibk3.tli1.merkle +0 -1
- package/sample-store/gen-1/predicate-6.ibk3 +0 -0
- package/sample-store/gen-1/predicate-6.ibk3.merkle +0 -1
- package/sample-store/gen-1/predicate-6.ibk3.oli2 +0 -0
- package/sample-store/gen-1/predicate-6.ibk3.oli2.merkle +0 -1
- package/sample-store/gen-1/predicate-6.ibk3.sri2 +0 -0
- package/sample-store/gen-1/predicate-6.ibk3.sri2.merkle +0 -1
- package/sample-store/gen-1/predicate-6.ibk3.tli1 +0 -0
- package/sample-store/gen-1/predicate-6.ibk3.tli1.merkle +0 -0
- package/sample-store/gen-1/predicate-7.ibk3 +0 -0
- package/sample-store/gen-1/predicate-7.ibk3.merkle +0 -0
- package/sample-store/gen-1/predicate-7.ibk3.oli2 +0 -0
- package/sample-store/gen-1/predicate-7.ibk3.oli2.merkle +0 -2
- package/sample-store/gen-1/predicate-7.ibk3.sri2 +0 -0
- package/sample-store/gen-1/predicate-7.ibk3.sri2.merkle +0 -1
- package/sample-store/gen-1/predicate-7.ibk3.tli1 +0 -0
- package/sample-store/gen-1/predicate-7.ibk3.tli1.merkle +0 -1
- package/sample-store/gen-1/predicate-8.ibk3 +0 -0
- package/sample-store/gen-1/predicate-8.ibk3.merkle +0 -1
- package/sample-store/gen-1/predicate-8.ibk3.oli2 +0 -0
- package/sample-store/gen-1/predicate-8.ibk3.oli2.merkle +0 -1
- package/sample-store/gen-1/predicate-8.ibk3.sri2 +0 -0
- package/sample-store/gen-1/predicate-8.ibk3.sri2.merkle +0 -1
- package/sample-store/gen-1/predicate-8.ibk3.tli1 +0 -0
- package/sample-store/gen-1/predicate-8.ibk3.tli1.merkle +0 -1
- package/sample-store/gen-1/predicate-9.ibk3 +0 -0
- package/sample-store/gen-1/predicate-9.ibk3.merkle +0 -1
- package/sample-store/gen-1/predicate-9.ibk3.oli2 +0 -0
- package/sample-store/gen-1/predicate-9.ibk3.oli2.merkle +0 -1
- package/sample-store/gen-1/predicate-9.ibk3.sri2 +0 -0
- package/sample-store/gen-1/predicate-9.ibk3.sri2.merkle +0 -3
- package/sample-store/gen-1/predicate-9.ibk3.tli1 +0 -0
- package/sample-store/gen-1/predicate-9.ibk3.tli1.merkle +0 -2
- package/select.d.ts +0 -116
- package/select.js +0 -492
- package/version.json +0 -102
- package/wasm.d.ts +0 -130
- package/wasm.js +0 -158
package/rdfjs.mjs
ADDED
|
@@ -0,0 +1,517 @@
|
|
|
1
|
+
// factoidal — RDF/JS data model + N-Quads token converters.
|
|
2
|
+
//
|
|
3
|
+
// Implements the RDF/JS Data Model specification
|
|
4
|
+
// (https://rdf.js.org/data-model-spec/): DataFactory producing
|
|
5
|
+
// NamedNode / BlankNode / Literal / Variable / DefaultGraph / Quad
|
|
6
|
+
// terms with spec-compliant `termType` / `value` / `language` /
|
|
7
|
+
// `datatype` and `.equals()`. Self-contained — no runtime deps.
|
|
8
|
+
//
|
|
9
|
+
// Also: the field copy between RDF/JS terms and the engine's term objects
|
|
10
|
+
// (Lean L4Factoidal.RDF.TermJson), and N-Quads text in and out through
|
|
11
|
+
// engine ops. This file reads and writes no RDF syntax itself: no escaping,
|
|
12
|
+
// no tokenising (https://github.com/danbri/factoidal/issues/894). The text
|
|
13
|
+
// functions need the engine, which lib/api.mjs installs when it loads.
|
|
14
|
+
//
|
|
15
|
+
// ES module (0.9.0): the same file serves Node (index.mjs, and rdfjs.js for
|
|
16
|
+
// require()) and the browser (browser.js), with no build step.
|
|
17
|
+
|
|
18
|
+
// RDF/JS Data Model defaults of DataFactory.literal.
|
|
19
|
+
const XSD_STRING = 'http://www.w3.org/2001/XMLSchema#string'; // purity-lint: allow RDF/JS DataFactory default
|
|
20
|
+
const RDF_LANGSTRING =
|
|
21
|
+
'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString'; // purity-lint: allow RDF/JS DataFactory default
|
|
22
|
+
const RDF_DIRLANGSTRING =
|
|
23
|
+
'http://www.w3.org/1999/02/22-rdf-syntax-ns#dirLangString'; // purity-lint: allow RDF/JS DataFactory default
|
|
24
|
+
|
|
25
|
+
// ---------------------------------------------------------------------
|
|
26
|
+
// Terms
|
|
27
|
+
// ---------------------------------------------------------------------
|
|
28
|
+
|
|
29
|
+
class NamedNode {
|
|
30
|
+
constructor(iri) {
|
|
31
|
+
this.termType = 'NamedNode';
|
|
32
|
+
this.value = iri;
|
|
33
|
+
Object.freeze(this);
|
|
34
|
+
}
|
|
35
|
+
equals(other) {
|
|
36
|
+
return !!other && other.termType === 'NamedNode' &&
|
|
37
|
+
other.value === this.value;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
class BlankNode {
|
|
42
|
+
constructor(label) {
|
|
43
|
+
this.termType = 'BlankNode';
|
|
44
|
+
this.value = label;
|
|
45
|
+
Object.freeze(this);
|
|
46
|
+
}
|
|
47
|
+
equals(other) {
|
|
48
|
+
return !!other && other.termType === 'BlankNode' &&
|
|
49
|
+
other.value === this.value;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
class Literal {
|
|
54
|
+
constructor(value, language, datatype, direction) {
|
|
55
|
+
this.termType = 'Literal';
|
|
56
|
+
this.value = value;
|
|
57
|
+
this.language = language || '';
|
|
58
|
+
// RDF/JS Data Model DataFactory.literal: no datatype argument means
|
|
59
|
+
// xsd:string, a language means rdf:langString, a language and a
|
|
60
|
+
// direction mean rdf:dirLangString.
|
|
61
|
+
this.datatype = datatype ||
|
|
62
|
+
new NamedNode(language ? (direction ? RDF_DIRLANGSTRING : RDF_LANGSTRING) : XSD_STRING); // purity-lint: allow RDF/JS DataFactory default
|
|
63
|
+
this.direction = direction || '';
|
|
64
|
+
Object.freeze(this);
|
|
65
|
+
}
|
|
66
|
+
equals(other) {
|
|
67
|
+
return !!other && other.termType === 'Literal' &&
|
|
68
|
+
other.value === this.value &&
|
|
69
|
+
other.language === this.language &&
|
|
70
|
+
(other.direction || '') === this.direction &&
|
|
71
|
+
!!other.datatype && other.datatype.value === this.datatype.value;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
class Variable {
|
|
76
|
+
constructor(name) {
|
|
77
|
+
this.termType = 'Variable';
|
|
78
|
+
this.value = name;
|
|
79
|
+
Object.freeze(this);
|
|
80
|
+
}
|
|
81
|
+
equals(other) {
|
|
82
|
+
return !!other && other.termType === 'Variable' &&
|
|
83
|
+
other.value === this.value;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
class DefaultGraph {
|
|
88
|
+
constructor() {
|
|
89
|
+
this.termType = 'DefaultGraph';
|
|
90
|
+
this.value = '';
|
|
91
|
+
Object.freeze(this);
|
|
92
|
+
}
|
|
93
|
+
equals(other) {
|
|
94
|
+
return !!other && other.termType === 'DefaultGraph';
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const DEFAULT_GRAPH = new DefaultGraph();
|
|
99
|
+
|
|
100
|
+
class Quad {
|
|
101
|
+
constructor(subject, predicate, object, graph) {
|
|
102
|
+
// Per spec, a Quad is itself a Term with termType 'Quad', value ''.
|
|
103
|
+
this.termType = 'Quad';
|
|
104
|
+
this.value = '';
|
|
105
|
+
this.subject = subject;
|
|
106
|
+
this.predicate = predicate;
|
|
107
|
+
this.object = object;
|
|
108
|
+
this.graph = graph || DEFAULT_GRAPH;
|
|
109
|
+
Object.freeze(this);
|
|
110
|
+
}
|
|
111
|
+
equals(other) {
|
|
112
|
+
return !!other &&
|
|
113
|
+
(other.termType === 'Quad' || other.termType === undefined) &&
|
|
114
|
+
this.subject.equals(other.subject) &&
|
|
115
|
+
this.predicate.equals(other.predicate) &&
|
|
116
|
+
this.object.equals(other.object) &&
|
|
117
|
+
this.graph.equals(other.graph);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// ---------------------------------------------------------------------
|
|
122
|
+
// DataFactory
|
|
123
|
+
// ---------------------------------------------------------------------
|
|
124
|
+
|
|
125
|
+
let blankNodeCounter = 0;
|
|
126
|
+
|
|
127
|
+
const dataFactory = {
|
|
128
|
+
namedNode(value) {
|
|
129
|
+
return new NamedNode(String(value));
|
|
130
|
+
},
|
|
131
|
+
blankNode(label) {
|
|
132
|
+
return new BlankNode(
|
|
133
|
+
label !== undefined && label !== null
|
|
134
|
+
? String(label)
|
|
135
|
+
: 'fjs_b' + (blankNodeCounter++)
|
|
136
|
+
);
|
|
137
|
+
},
|
|
138
|
+
literal(value, languageOrDatatype) {
|
|
139
|
+
const v = String(value);
|
|
140
|
+
if (languageOrDatatype === undefined || languageOrDatatype === null) {
|
|
141
|
+
return new Literal(v, '', null);
|
|
142
|
+
}
|
|
143
|
+
if (typeof languageOrDatatype === 'string') {
|
|
144
|
+
return new Literal(v, languageOrDatatype, null);
|
|
145
|
+
}
|
|
146
|
+
// RDF/JS Data Model 1.1: {language, direction} for a directional
|
|
147
|
+
// language-tagged string.
|
|
148
|
+
if (typeof languageOrDatatype.language === 'string' && languageOrDatatype.termType === undefined) {
|
|
149
|
+
return new Literal(v, languageOrDatatype.language, null, languageOrDatatype.direction || '');
|
|
150
|
+
}
|
|
151
|
+
// A NamedNode datatype.
|
|
152
|
+
if (languageOrDatatype.termType === 'NamedNode') {
|
|
153
|
+
if (languageOrDatatype.value === RDF_LANGSTRING) {
|
|
154
|
+
// langString without a language tag is not constructible; treat
|
|
155
|
+
// as plain string per the most defensive reading of the spec.
|
|
156
|
+
return new Literal(v, '', null);
|
|
157
|
+
}
|
|
158
|
+
return new Literal(v, '', new NamedNode(languageOrDatatype.value));
|
|
159
|
+
}
|
|
160
|
+
throw new TypeError(
|
|
161
|
+
'literal: second argument must be a language string or a NamedNode'
|
|
162
|
+
);
|
|
163
|
+
},
|
|
164
|
+
variable(name) {
|
|
165
|
+
return new Variable(String(name));
|
|
166
|
+
},
|
|
167
|
+
defaultGraph() {
|
|
168
|
+
return DEFAULT_GRAPH;
|
|
169
|
+
},
|
|
170
|
+
quad(subject, predicate, object, graph) {
|
|
171
|
+
return new Quad(subject, predicate, object, graph);
|
|
172
|
+
},
|
|
173
|
+
fromTerm(original) {
|
|
174
|
+
if (!original || typeof original.termType !== 'string') {
|
|
175
|
+
throw new TypeError('fromTerm: not a term');
|
|
176
|
+
}
|
|
177
|
+
switch (original.termType) {
|
|
178
|
+
case 'NamedNode': return new NamedNode(original.value);
|
|
179
|
+
case 'BlankNode': return new BlankNode(original.value);
|
|
180
|
+
case 'Variable': return new Variable(original.value);
|
|
181
|
+
case 'DefaultGraph': return DEFAULT_GRAPH;
|
|
182
|
+
case 'Literal':
|
|
183
|
+
return new Literal(
|
|
184
|
+
original.value,
|
|
185
|
+
original.language || '',
|
|
186
|
+
original.datatype ? new NamedNode(original.datatype.value) : null,
|
|
187
|
+
original.direction || ''
|
|
188
|
+
);
|
|
189
|
+
case 'Quad': return dataFactory.fromQuad(original);
|
|
190
|
+
default:
|
|
191
|
+
throw new TypeError(`fromTerm: unknown termType '${original.termType}'`);
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
fromQuad(original) {
|
|
195
|
+
if (!original || !original.subject) {
|
|
196
|
+
throw new TypeError('fromQuad: not a quad');
|
|
197
|
+
}
|
|
198
|
+
return new Quad(
|
|
199
|
+
dataFactory.fromTerm(original.subject),
|
|
200
|
+
dataFactory.fromTerm(original.predicate),
|
|
201
|
+
dataFactory.fromTerm(original.object),
|
|
202
|
+
original.graph ? dataFactory.fromTerm(original.graph) : DEFAULT_GRAPH
|
|
203
|
+
);
|
|
204
|
+
},
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
// ---------------------------------------------------------------------
|
|
208
|
+
// SPARQL Results JSON term -> RDF/JS term
|
|
209
|
+
// ---------------------------------------------------------------------
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Convert a SPARQL 1.1 Results JSON term object
|
|
213
|
+
* ({type:'uri'|'bnode'|'literal'|'typed-literal', value, 'xml:lang',
|
|
214
|
+
* datatype}) into an RDF/JS term.
|
|
215
|
+
*/
|
|
216
|
+
function termFromSrj(t) {
|
|
217
|
+
return termFromSrjWith(t, dataFactory);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function termFromSrjWith(t, f) {
|
|
221
|
+
if (!t || typeof t.type !== 'string') {
|
|
222
|
+
throw new TypeError('termFromSrj: not a results-JSON term');
|
|
223
|
+
}
|
|
224
|
+
switch (t.type) {
|
|
225
|
+
case 'uri':
|
|
226
|
+
return f.namedNode(t.value);
|
|
227
|
+
case 'bnode':
|
|
228
|
+
return f.blankNode(t.value);
|
|
229
|
+
case 'literal':
|
|
230
|
+
case 'typed-literal': {
|
|
231
|
+
const lang = t['xml:lang'];
|
|
232
|
+
if (lang) {
|
|
233
|
+
if (t['its:dir'] && f === dataFactory) {
|
|
234
|
+
return new Literal(t.value, lang,
|
|
235
|
+
t.datatype ? new NamedNode(t.datatype) : null, t['its:dir']);
|
|
236
|
+
}
|
|
237
|
+
return f.literal(t.value, lang);
|
|
238
|
+
}
|
|
239
|
+
if (t.datatype) return f.literal(t.value, f.namedNode(t.datatype));
|
|
240
|
+
return f.literal(t.value);
|
|
241
|
+
}
|
|
242
|
+
case 'triple': {
|
|
243
|
+
// RDF 1.2 triple term:
|
|
244
|
+
// {"type":"triple","value":{"subject":T,"predicate":T,"object":T}}
|
|
245
|
+
// -> an RDF/JS Quad term. The object may itself be a triple term.
|
|
246
|
+
const v = t.value || {};
|
|
247
|
+
return f.quad(termFromSrjWith(v.subject, f), termFromSrjWith(v.predicate, f),
|
|
248
|
+
termFromSrjWith(v.object, f));
|
|
249
|
+
}
|
|
250
|
+
default:
|
|
251
|
+
throw new TypeError(`termFromSrj: unknown term type '${t.type}'`);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// ---------------------------------------------------------------------
|
|
256
|
+
// RDF/JS term <-> engine term object (Lean `L4Factoidal.RDF.TermJson`).
|
|
257
|
+
//
|
|
258
|
+
// These functions copy fields; they read and write no RDF syntax. Every
|
|
259
|
+
// N-Quads parse and write below is an engine op
|
|
260
|
+
// (https://github.com/danbri/factoidal/issues/894 items 1 and 2).
|
|
261
|
+
// ---------------------------------------------------------------------
|
|
262
|
+
|
|
263
|
+
/** The engine term object of an RDF/JS term (`TermJson.encodeTerm`'s shape). */
|
|
264
|
+
function termToJson(term) {
|
|
265
|
+
if (term === null || term === undefined) return null;
|
|
266
|
+
// A term given as text is one RDF 1.2 N-Triples term (`<IRI>`, `_:label`,
|
|
267
|
+
// a literal, `<<( s p o )>>`). The engine reads it
|
|
268
|
+
// (L4Factoidal.RDF.TermJson.readTermString); this file copies the text.
|
|
269
|
+
if (typeof term === 'string') return { type: 'nt', value: term };
|
|
270
|
+
switch (term.termType) {
|
|
271
|
+
case 'NamedNode': return { type: 'uri', value: term.value };
|
|
272
|
+
case 'BlankNode': return { type: 'bnode', value: term.value };
|
|
273
|
+
case 'Literal': {
|
|
274
|
+
const o = { type: 'literal', value: term.value };
|
|
275
|
+
if (term.datatype) o.datatype = term.datatype.value;
|
|
276
|
+
if (term.language) o['xml:lang'] = term.language;
|
|
277
|
+
if (term.direction) o['its:dir'] = term.direction;
|
|
278
|
+
return o;
|
|
279
|
+
}
|
|
280
|
+
case 'Quad':
|
|
281
|
+
return { type: 'triple', value: {
|
|
282
|
+
subject: termToJson(term.subject), predicate: termToJson(term.predicate),
|
|
283
|
+
object: termToJson(term.object) } };
|
|
284
|
+
case 'DefaultGraph': return { type: 'default' };
|
|
285
|
+
default:
|
|
286
|
+
throw new TypeError(`termToJson: cannot send termType '${term.termType}' to the engine`);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* The engine term object of a term an application supplies, for example an
|
|
292
|
+
* extension function's answer: an RDF/JS term (duck-typed on termType), an
|
|
293
|
+
* engine term object ({type, value, ...}), or a plain object
|
|
294
|
+
* {value, datatype} or {value, language, direction?}. The components are
|
|
295
|
+
* copied as given; the engine checks them (TermJson.decodeCheckedTerm) and
|
|
296
|
+
* keeps the lexical form and the datatype IRI unchanged.
|
|
297
|
+
*/
|
|
298
|
+
function appTermToJson(out) {
|
|
299
|
+
if (typeof out.termType === 'string') return termToJson(out);
|
|
300
|
+
if (typeof out.type === 'string') return out;
|
|
301
|
+
const o = { type: 'literal', value: out.value };
|
|
302
|
+
if (out.datatype !== undefined && out.datatype !== null) {
|
|
303
|
+
o.datatype = typeof out.datatype === 'string' ? out.datatype : out.datatype.value;
|
|
304
|
+
}
|
|
305
|
+
if (out.language !== undefined && out.language !== null && out.language !== '') o['xml:lang'] = out.language;
|
|
306
|
+
if (out.direction !== undefined && out.direction !== null && out.direction !== '') o['its:dir'] = out.direction;
|
|
307
|
+
return o;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/** The engine quad array of an RDF/JS quad: [s, p, o] or [s, p, o, g]. */
|
|
311
|
+
function quadToJson(quad) {
|
|
312
|
+
const out = [termToJson(quad.subject), termToJson(quad.predicate), termToJson(quad.object)];
|
|
313
|
+
if (quad.graph && quad.graph.termType !== 'DefaultGraph') out.push(termToJson(quad.graph));
|
|
314
|
+
return out;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/** The RDF/JS quad of an engine quad array. */
|
|
318
|
+
function quadFromJson(arr, factory) {
|
|
319
|
+
const f = factory || dataFactory;
|
|
320
|
+
return f.quad(termFromSrjWith(arr[0], f), termFromSrjWith(arr[1], f),
|
|
321
|
+
termFromSrjWith(arr[2], f), arr.length > 3 ? termFromSrjWith(arr[3], f) : f.defaultGraph());
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// The engine the text functions below call. lib/api.mjs installs it when it
|
|
325
|
+
// loads the engine; until then they throw.
|
|
326
|
+
let textEngine = null;
|
|
327
|
+
|
|
328
|
+
/** @private lib/api.mjs: install the engine ops the text functions call. */
|
|
329
|
+
function _setTextEngine(engine) { textEngine = engine; }
|
|
330
|
+
|
|
331
|
+
function needEngine(who) {
|
|
332
|
+
if (!textEngine) {
|
|
333
|
+
throw new Error(
|
|
334
|
+
`${who}: N-Quads text is read and written by the engine, which is not ` +
|
|
335
|
+
'loaded yet. Await any @factoidal/core call first (for example ' +
|
|
336
|
+
'`await ready()`), or use parse() and Dataset.toString().');
|
|
337
|
+
}
|
|
338
|
+
return textEngine;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/** One RDF/JS term as its canonical N-Quads token (the engine writes it). */
|
|
342
|
+
function termToNQuads(term) {
|
|
343
|
+
if (term && term.termType === 'DefaultGraph') return '';
|
|
344
|
+
return needEngine('termToNQuads').termTokens([termToJson(term)])[0];
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/** One RDF/JS quad as its canonical N-Quads line (with trailing newline). */
|
|
348
|
+
function quadToNQuads(quad) {
|
|
349
|
+
return needEngine('quadToNQuads').writeQuads([quadToJson(quad)]);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/** An iterable of RDF/JS quads as an N-Quads document, one line per quad. */
|
|
353
|
+
function quadsToNQuads(quads) {
|
|
354
|
+
const arr = [];
|
|
355
|
+
for (const q of quads) arr.push(quadToJson(q));
|
|
356
|
+
return needEngine('quadsToNQuads').writeQuads(arr);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Parse an N-Quads document (RDF 1.2 grammar) into RDF/JS quads; the engine
|
|
361
|
+
* parses it and rejects any line the grammar rejects.
|
|
362
|
+
* The quads come in the engine's order: the default graph, then each named
|
|
363
|
+
* graph in the order of its first quad.
|
|
364
|
+
* options.blankNodePrefix: prepended to every blank-node label (keeps the
|
|
365
|
+
* labels of separate documents apart); options.factory: an RDF/JS
|
|
366
|
+
* DataFactory.
|
|
367
|
+
*/
|
|
368
|
+
function nquadsToQuads(text, options) {
|
|
369
|
+
const opts = options || {};
|
|
370
|
+
const factory = opts.factory || dataFactory;
|
|
371
|
+
const f = opts.blankNodePrefix
|
|
372
|
+
? { ...factory, blankNode: (label) => factory.blankNode(opts.blankNodePrefix + label) }
|
|
373
|
+
: factory;
|
|
374
|
+
const quads = needEngine('nquadsToQuads').parseQuads(String(text));
|
|
375
|
+
return quads.map((q) => quadFromJson(q, f));
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/** One N-Quads statement as an RDF/JS quad; null for a blank or comment line. */
|
|
379
|
+
function nquadsLineToQuad(line, _lineNo, factory) {
|
|
380
|
+
const qs = nquadsToQuads(line, { factory });
|
|
381
|
+
return qs.length ? qs[0] : null;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// ---------------------------------------------------------------------
|
|
385
|
+
// Dataset — a minimal RDF/JS DatasetCore over an in-memory quad array.
|
|
386
|
+
// ---------------------------------------------------------------------
|
|
387
|
+
|
|
388
|
+
// A string that two terms share exactly when equals() holds between them
|
|
389
|
+
// (the fields each equals() above compares). JSON arrays are
|
|
390
|
+
// self-delimiting, so the key of a quad, four term keys in a row, is
|
|
391
|
+
// injective too. The Dataset keeps the keys of its quads in a Set: add()
|
|
392
|
+
// and has() are then one lookup each. Until 2026-10-10 both scanned the
|
|
393
|
+
// quad array, so building a Dataset of n quads cost n^2/2 equals() calls:
|
|
394
|
+
// 12,000 quads took 3.1 s in parse() (issue 713 stage 5).
|
|
395
|
+
function termKey(t) {
|
|
396
|
+
if (!t) return 'null';
|
|
397
|
+
switch (t.termType) {
|
|
398
|
+
case 'Literal':
|
|
399
|
+
return JSON.stringify(['Literal', t.value, t.language, t.datatype ? t.datatype.value : null,
|
|
400
|
+
t.direction || '']);
|
|
401
|
+
case 'DefaultGraph':
|
|
402
|
+
return '["DefaultGraph"]';
|
|
403
|
+
case 'Quad':
|
|
404
|
+
return '["Quad",' + termKey(t.subject) + ',' + termKey(t.predicate) + ',' +
|
|
405
|
+
termKey(t.object) + ',' + termKey(t.graph) + ']';
|
|
406
|
+
default:
|
|
407
|
+
return JSON.stringify([t.termType, t.value]);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
function quadKey(q) {
|
|
412
|
+
return termKey(q.subject) + termKey(q.predicate) + termKey(q.object) +
|
|
413
|
+
termKey(q.graph || DEFAULT_GRAPH);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* An in-memory RDF/JS DatasetCore over a quad array. The package's Dataset
|
|
418
|
+
* (lib/dataset.mjs) keeps its data in the engine; this class is for callers
|
|
419
|
+
* that build quads in JavaScript, for example to hand to fn.js.
|
|
420
|
+
*/
|
|
421
|
+
class DatasetCore {
|
|
422
|
+
constructor(quads, options) {
|
|
423
|
+
this._quads = [];
|
|
424
|
+
// The quadKey() of every quad in _quads, for set semantics in O(1).
|
|
425
|
+
this._keys = new Set();
|
|
426
|
+
if (quads) for (const q of quads) this.add(q);
|
|
427
|
+
const opts = options || {};
|
|
428
|
+
// Own, non-enumerable properties (issue #680/#681): a frozen
|
|
429
|
+
// snapshot of the prefixes/diagnostics the engine reported at
|
|
430
|
+
// parse time, so JSON.stringify()/toArray() (and any caller
|
|
431
|
+
// enumerating own enumerable keys) see only the quads, exactly as
|
|
432
|
+
// before this landed.
|
|
433
|
+
Object.defineProperty(this, 'prefixes', {
|
|
434
|
+
value: Object.freeze({ ...(opts.prefixes || {}) }),
|
|
435
|
+
enumerable: false, writable: false, configurable: false,
|
|
436
|
+
});
|
|
437
|
+
Object.defineProperty(this, 'diagnostics', {
|
|
438
|
+
value: Object.freeze((opts.diagnostics || []).slice()),
|
|
439
|
+
enumerable: false, writable: false, configurable: false,
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
get size() {
|
|
443
|
+
return this._quads.length;
|
|
444
|
+
}
|
|
445
|
+
add(quad) {
|
|
446
|
+
const key = quadKey(quad);
|
|
447
|
+
if (!this._keys.has(key)) {
|
|
448
|
+
this._keys.add(key);
|
|
449
|
+
this._quads.push(quad);
|
|
450
|
+
}
|
|
451
|
+
return this;
|
|
452
|
+
}
|
|
453
|
+
delete(quad) {
|
|
454
|
+
if (this._keys.delete(quadKey(quad))) {
|
|
455
|
+
const ix = this._quads.findIndex((q) => q.equals(quad));
|
|
456
|
+
if (ix >= 0) this._quads.splice(ix, 1);
|
|
457
|
+
}
|
|
458
|
+
return this;
|
|
459
|
+
}
|
|
460
|
+
has(quad) {
|
|
461
|
+
return this._keys.has(quadKey(quad));
|
|
462
|
+
}
|
|
463
|
+
match(subject, predicate, object, graph) {
|
|
464
|
+
const out = new DatasetCore();
|
|
465
|
+
for (const q of this._quads) {
|
|
466
|
+
if (subject && !subject.equals(q.subject)) continue;
|
|
467
|
+
if (predicate && !predicate.equals(q.predicate)) continue;
|
|
468
|
+
if (object && !object.equals(q.object)) continue;
|
|
469
|
+
if (graph && !graph.equals(q.graph)) continue;
|
|
470
|
+
out._quads.push(q);
|
|
471
|
+
out._keys.add(quadKey(q));
|
|
472
|
+
}
|
|
473
|
+
return out;
|
|
474
|
+
}
|
|
475
|
+
[Symbol.iterator]() {
|
|
476
|
+
return this._quads[Symbol.iterator]();
|
|
477
|
+
}
|
|
478
|
+
toArray() {
|
|
479
|
+
return this._quads.slice();
|
|
480
|
+
}
|
|
481
|
+
/** N-Quads text, written by the engine. */
|
|
482
|
+
toNQuads() {
|
|
483
|
+
return quadsToNQuads(this._quads);
|
|
484
|
+
}
|
|
485
|
+
toString() {
|
|
486
|
+
return this.toNQuads();
|
|
487
|
+
}
|
|
488
|
+
static fromNQuads(text, options) {
|
|
489
|
+
return new DatasetCore(nquadsToQuads(text, options), options);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
export {
|
|
494
|
+
dataFactory,
|
|
495
|
+
NamedNode,
|
|
496
|
+
BlankNode,
|
|
497
|
+
Literal,
|
|
498
|
+
Variable,
|
|
499
|
+
DefaultGraph,
|
|
500
|
+
Quad,
|
|
501
|
+
DatasetCore,
|
|
502
|
+
termFromSrj,
|
|
503
|
+
termToJson,
|
|
504
|
+
appTermToJson,
|
|
505
|
+
quadToJson,
|
|
506
|
+
quadFromJson,
|
|
507
|
+
quadKey,
|
|
508
|
+
termKey,
|
|
509
|
+
_setTextEngine,
|
|
510
|
+
nquadsLineToQuad,
|
|
511
|
+
termToNQuads,
|
|
512
|
+
quadToNQuads,
|
|
513
|
+
quadsToNQuads,
|
|
514
|
+
nquadsToQuads,
|
|
515
|
+
XSD_STRING,
|
|
516
|
+
RDF_LANGSTRING,
|
|
517
|
+
}
|
package/sample-store.d.ts
CHANGED
|
@@ -1,16 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
export
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
wireVersion: number
|
|
10
|
-
source: string
|
|
11
|
-
licence: string
|
|
12
|
-
licenceUrl: string
|
|
13
|
-
publisher: string
|
|
14
|
-
}>
|
|
15
|
-
|
|
16
|
-
export default sampleStorePath
|
|
1
|
+
// @factoidal/core/sample-store (Node only): a small store packed on demand.
|
|
2
|
+
/** The triples of the sample store, as Turtle. */
|
|
3
|
+
export const SAMPLE_TURTLE: string;
|
|
4
|
+
/** What the sample store holds. */
|
|
5
|
+
export const sampleStoreFacts: Readonly<{ triples: number; source: string; layout: string }>;
|
|
6
|
+
/** Pack the sample store under `dir` (or a new temporary directory) unless it holds CURRENT; return the root. */
|
|
7
|
+
export function sampleStorePath(dir?: string): string;
|
|
8
|
+
export default sampleStorePath;
|
package/sample-store.mjs
CHANGED
|
@@ -1,37 +1,47 @@
|
|
|
1
|
-
//
|
|
2
|
-
// answers a SPARQL query with no other download and no native binary.
|
|
1
|
+
// @factoidal/core/sample-store - a small store made on demand (Node only).
|
|
3
2
|
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
// 4,434 triples in 13 predicate blocks. See NOTICE.
|
|
3
|
+
// Owner, 2026-10-20, verbatim: "All the CLIs are still bundled i just didn't
|
|
4
|
+
// want any actual demo triples cluttering the file." So the package ships no
|
|
5
|
+
// store. sampleStorePath() packs the few triples below (written for this
|
|
6
|
+
// package, no third-party content) into a Shardborough store with the
|
|
7
|
+
// package's own `factoidal pack` and `factoidal activate`, under DIR or the
|
|
8
|
+
// OS temporary directory, and returns the collection root. A DIR that
|
|
9
|
+
// already holds CURRENT is returned as it is.
|
|
12
10
|
|
|
13
|
-
import {
|
|
11
|
+
import { execFileSync } from 'node:child_process'
|
|
12
|
+
import { existsSync } from 'node:fs'
|
|
13
|
+
import { join } from 'node:path'
|
|
14
|
+
import { fileURLToPath } from 'node:url'
|
|
14
15
|
|
|
15
|
-
/** The
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
16
|
+
/** The triples of the sample store, as Turtle. */
|
|
17
|
+
export const SAMPLE_TURTLE = `@prefix skos: <http://www.w3.org/2004/02/skos/core#> .
|
|
18
|
+
@prefix ex: <http://example.org/codec/> .
|
|
19
|
+
ex:scheme a skos:ConceptScheme ; skos:prefLabel "Video codecs"@en .
|
|
20
|
+
ex:c1 a skos:Concept ; skos:inScheme ex:scheme ; skos:prefLabel "PAL"@en ; skos:notation "c1" .
|
|
21
|
+
ex:c2 a skos:Concept ; skos:inScheme ex:scheme ; skos:prefLabel "NTSC"@en ; skos:notation "c2" .
|
|
22
|
+
ex:c3 a skos:Concept ; skos:inScheme ex:scheme ; skos:prefLabel "SECAM"@en ; skos:notation "c3" ;
|
|
23
|
+
skos:broader ex:c1 .
|
|
24
|
+
`
|
|
22
25
|
|
|
23
|
-
/** What the sample store holds
|
|
24
|
-
* is the authority on every one of these numbers at run time; they are here
|
|
25
|
-
* so a caller can print something before it opens the store. */
|
|
26
|
+
/** What the sample store holds. */
|
|
26
27
|
export const sampleStoreFacts = Object.freeze({
|
|
27
|
-
triples:
|
|
28
|
-
|
|
29
|
-
layout: '
|
|
30
|
-
wireVersion: 6,
|
|
31
|
-
source: 'IPTC NewsCodes (spamfstat, videoqualifier, subjectqualifier, videocodec, spct)',
|
|
32
|
-
licence: 'CC BY 4.0',
|
|
33
|
-
licenceUrl: 'https://creativecommons.org/licenses/by/4.0/',
|
|
34
|
-
publisher: 'https://iptc.org/'
|
|
28
|
+
triples: 15,
|
|
29
|
+
source: 'SAMPLE_TURTLE in sample-store.mjs (written for this package)',
|
|
30
|
+
layout: 'ibk3'
|
|
35
31
|
})
|
|
36
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Pack the sample store (if DIR holds no CURRENT) and return its root.
|
|
35
|
+
* @param {string} [dir] the collection root to use; default a new
|
|
36
|
+
* directory under the OS temporary directory
|
|
37
|
+
* @returns {string}
|
|
38
|
+
*/
|
|
39
|
+
export function sampleStorePath (dir) {
|
|
40
|
+
if (typeof dir === 'string' && existsSync(join(dir, 'CURRENT'))) return dir
|
|
41
|
+
const cli = fileURLToPath(new URL('./bin/factoidal.mjs', import.meta.url))
|
|
42
|
+
const args = [cli, 'sample-store']
|
|
43
|
+
if (typeof dir === 'string') args.push(dir)
|
|
44
|
+
return execFileSync(process.execPath, args, { encoding: 'utf8' }).trim()
|
|
45
|
+
}
|
|
46
|
+
|
|
37
47
|
export default sampleStorePath
|