@factoidal/core 0.7.1 → 0.10.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.
Files changed (193) hide show
  1. package/CHANGELOG.md +503 -1
  2. package/NOTICE +2 -21
  3. package/README.md +117 -993
  4. package/api.d.ts +53 -0
  5. package/api.js +5 -0
  6. package/api.mjs +56 -0
  7. package/bin/engine.mjs +38 -19
  8. package/bin/factoidal.mjs +512 -66
  9. package/bin/pack.mjs +37 -0
  10. package/bin/serve-worker.mjs +32 -0
  11. package/bin/serve.mjs +423 -0
  12. package/bin/store-worker-host.mjs +1 -1
  13. package/bin/store.mjs +1 -1
  14. package/browser.d.ts +110 -507
  15. package/browser.js +151 -2257
  16. package/docs/fuseki-replacement.md +108 -0
  17. package/fn.d.ts +24 -95
  18. package/fn.js +104 -150
  19. package/index.d.ts +598 -259
  20. package/index.js +4 -234
  21. package/index.mjs +176 -84
  22. package/l4-assets/l4factoidal.js +47 -7
  23. package/l4-assets/l4factoidal.mjs +1 -1
  24. package/l4-assets/l4factoidal.wasm +0 -0
  25. package/l4-assets/version.json +11 -7
  26. package/lib/api.mjs +2300 -0
  27. package/lib/browser-engine.mjs +69 -0
  28. package/lib/dataset.mjs +377 -0
  29. package/lib/delta-log-hosts.mjs +191 -0
  30. package/lib/lean-entry.mjs +204 -0
  31. package/lib/pure.mjs +98 -0
  32. package/lib/store.mjs +115 -0
  33. package/lib/version.mjs +5 -0
  34. package/lws/README.md +97 -0
  35. package/lws/server.mjs +331 -0
  36. package/package.json +59 -61
  37. package/rdfjs.js +5 -536
  38. package/rdfjs.mjs +594 -0
  39. package/sample-store.d.ts +8 -16
  40. package/sample-store.mjs +39 -29
  41. package/solid/client/README.md +100 -0
  42. package/solid/client/index.mjs +277 -0
  43. package/solid/server/README.md +96 -0
  44. package/solid/server/index.mjs +317 -0
  45. package/store-host/deno.mjs +8 -0
  46. package/store-host/index.mjs +12 -0
  47. package/store-host/node.mjs +8 -0
  48. package/xmpp/README.md +107 -0
  49. package/xmpp/index.mjs +229 -0
  50. package/browser-wasm.js +0 -872
  51. package/factoidal-npm-entry.js +0 -15477
  52. package/factoidal-npm-entry.wasm.assets/code-5a7fc68f2ab1323718b8.wasm +0 -0
  53. package/factoidal-npm-entry.wasm.js +0 -455
  54. package/factoidal.js +0 -13118
  55. package/factoidal.wasm.assets/code-bbe6099bfb5b10c4c3ab.wasm +0 -0
  56. package/factoidal.wasm.js +0 -457
  57. package/hacl-init.js +0 -92
  58. package/hacl-wasm/FStar.wasm +0 -0
  59. package/hacl-wasm/Hacl_Bignum.wasm +0 -0
  60. package/hacl-wasm/Hacl_Bignum25519_51.wasm +0 -0
  61. package/hacl-wasm/Hacl_Bignum_Base.wasm +0 -0
  62. package/hacl-wasm/Hacl_Curve25519_51.wasm +0 -0
  63. package/hacl-wasm/Hacl_Ed25519.wasm +0 -0
  64. package/hacl-wasm/Hacl_Ed25519_PrecompTable.wasm +0 -0
  65. package/hacl-wasm/Hacl_Hash_Base.wasm +0 -0
  66. package/hacl-wasm/Hacl_Hash_SHA2.wasm +0 -0
  67. package/hacl-wasm/Hacl_IntTypes_Intrinsics.wasm +0 -0
  68. package/hacl-wasm/LowStar_Endianness.wasm +0 -0
  69. package/hacl-wasm/WasmSupport.wasm +0 -0
  70. package/hacl-wasm/api.js +0 -775
  71. package/hacl-wasm/api.json +0 -3787
  72. package/hacl-wasm/layouts.json +0 -1
  73. package/hacl-wasm/loader.js +0 -568
  74. package/hacl-wasm/shell.js +0 -12
  75. package/l4-core.d.ts +0 -159
  76. package/l4-core.js +0 -188
  77. package/l4.d.ts +0 -50
  78. package/l4.js +0 -104
  79. package/lib/api.js +0 -2300
  80. package/lib/engine-js.js +0 -165
  81. package/lib/engine-wasm.js +0 -300
  82. package/sample-store/CURRENT +0 -1
  83. package/sample-store/gen-1/manifest.sbm2 +0 -0
  84. package/sample-store/gen-1/manifest.tsv +0 -14
  85. package/sample-store/gen-1/predicate-0.ibk3 +0 -0
  86. package/sample-store/gen-1/predicate-0.ibk3.merkle +0 -1
  87. package/sample-store/gen-1/predicate-0.ibk3.oli2 +0 -0
  88. package/sample-store/gen-1/predicate-0.ibk3.oli2.merkle +0 -1
  89. package/sample-store/gen-1/predicate-0.ibk3.sri2 +0 -0
  90. package/sample-store/gen-1/predicate-0.ibk3.sri2.merkle +0 -1
  91. package/sample-store/gen-1/predicate-0.ibk3.tli1 +0 -0
  92. package/sample-store/gen-1/predicate-0.ibk3.tli1.merkle +0 -0
  93. package/sample-store/gen-1/predicate-1.ibk3 +0 -0
  94. package/sample-store/gen-1/predicate-1.ibk3.merkle +0 -0
  95. package/sample-store/gen-1/predicate-1.ibk3.oli2 +0 -0
  96. package/sample-store/gen-1/predicate-1.ibk3.oli2.merkle +0 -0
  97. package/sample-store/gen-1/predicate-1.ibk3.sri2 +0 -0
  98. package/sample-store/gen-1/predicate-1.ibk3.sri2.merkle +0 -1
  99. package/sample-store/gen-1/predicate-1.ibk3.tli1 +0 -0
  100. package/sample-store/gen-1/predicate-1.ibk3.tli1.merkle +0 -1
  101. package/sample-store/gen-1/predicate-10.ibk3 +0 -0
  102. package/sample-store/gen-1/predicate-10.ibk3.merkle +0 -1
  103. package/sample-store/gen-1/predicate-10.ibk3.oli2 +0 -0
  104. package/sample-store/gen-1/predicate-10.ibk3.oli2.merkle +0 -0
  105. package/sample-store/gen-1/predicate-10.ibk3.sri2 +0 -0
  106. package/sample-store/gen-1/predicate-10.ibk3.sri2.merkle +0 -1
  107. package/sample-store/gen-1/predicate-10.ibk3.tli1 +0 -0
  108. package/sample-store/gen-1/predicate-10.ibk3.tli1.merkle +0 -1
  109. package/sample-store/gen-1/predicate-11.ibk3 +0 -0
  110. package/sample-store/gen-1/predicate-11.ibk3.merkle +0 -0
  111. package/sample-store/gen-1/predicate-11.ibk3.oli2 +0 -0
  112. package/sample-store/gen-1/predicate-11.ibk3.oli2.merkle +0 -1
  113. package/sample-store/gen-1/predicate-11.ibk3.sri2 +0 -0
  114. package/sample-store/gen-1/predicate-11.ibk3.sri2.merkle +0 -1
  115. package/sample-store/gen-1/predicate-11.ibk3.tli1 +0 -0
  116. package/sample-store/gen-1/predicate-11.ibk3.tli1.merkle +0 -1
  117. package/sample-store/gen-1/predicate-12.ibk3 +0 -0
  118. package/sample-store/gen-1/predicate-12.ibk3.merkle +0 -1
  119. package/sample-store/gen-1/predicate-12.ibk3.oli2 +0 -0
  120. package/sample-store/gen-1/predicate-12.ibk3.oli2.merkle +0 -1
  121. package/sample-store/gen-1/predicate-12.ibk3.sri2 +0 -0
  122. package/sample-store/gen-1/predicate-12.ibk3.sri2.merkle +0 -1
  123. package/sample-store/gen-1/predicate-12.ibk3.tli1 +0 -0
  124. package/sample-store/gen-1/predicate-12.ibk3.tli1.merkle +0 -1
  125. package/sample-store/gen-1/predicate-2.ibk3 +0 -0
  126. package/sample-store/gen-1/predicate-2.ibk3.merkle +0 -1
  127. package/sample-store/gen-1/predicate-2.ibk3.oli2 +0 -0
  128. package/sample-store/gen-1/predicate-2.ibk3.oli2.merkle +0 -1
  129. package/sample-store/gen-1/predicate-2.ibk3.sri2 +0 -0
  130. package/sample-store/gen-1/predicate-2.ibk3.sri2.merkle +0 -0
  131. package/sample-store/gen-1/predicate-2.ibk3.tli1 +0 -0
  132. package/sample-store/gen-1/predicate-2.ibk3.tli1.merkle +0 -0
  133. package/sample-store/gen-1/predicate-3.ibk3 +0 -0
  134. package/sample-store/gen-1/predicate-3.ibk3.merkle +0 -1
  135. package/sample-store/gen-1/predicate-3.ibk3.oli2 +0 -0
  136. package/sample-store/gen-1/predicate-3.ibk3.oli2.merkle +0 -1
  137. package/sample-store/gen-1/predicate-3.ibk3.sri2 +0 -0
  138. package/sample-store/gen-1/predicate-3.ibk3.sri2.merkle +0 -1
  139. package/sample-store/gen-1/predicate-3.ibk3.tli1 +0 -0
  140. package/sample-store/gen-1/predicate-3.ibk3.tli1.merkle +0 -1
  141. package/sample-store/gen-1/predicate-4.ibk3 +0 -0
  142. package/sample-store/gen-1/predicate-4.ibk3.merkle +0 -0
  143. package/sample-store/gen-1/predicate-4.ibk3.oli2 +0 -0
  144. package/sample-store/gen-1/predicate-4.ibk3.oli2.merkle +0 -1
  145. package/sample-store/gen-1/predicate-4.ibk3.sri2 +0 -0
  146. package/sample-store/gen-1/predicate-4.ibk3.sri2.merkle +0 -1
  147. package/sample-store/gen-1/predicate-4.ibk3.tli1 +0 -0
  148. package/sample-store/gen-1/predicate-4.ibk3.tli1.merkle +0 -2
  149. package/sample-store/gen-1/predicate-5.ibk3 +0 -0
  150. package/sample-store/gen-1/predicate-5.ibk3.merkle +0 -1
  151. package/sample-store/gen-1/predicate-5.ibk3.oli2 +0 -0
  152. package/sample-store/gen-1/predicate-5.ibk3.oli2.merkle +0 -1
  153. package/sample-store/gen-1/predicate-5.ibk3.sri2 +0 -0
  154. package/sample-store/gen-1/predicate-5.ibk3.sri2.merkle +0 -1
  155. package/sample-store/gen-1/predicate-5.ibk3.tli1 +0 -0
  156. package/sample-store/gen-1/predicate-5.ibk3.tli1.merkle +0 -1
  157. package/sample-store/gen-1/predicate-6.ibk3 +0 -0
  158. package/sample-store/gen-1/predicate-6.ibk3.merkle +0 -1
  159. package/sample-store/gen-1/predicate-6.ibk3.oli2 +0 -0
  160. package/sample-store/gen-1/predicate-6.ibk3.oli2.merkle +0 -1
  161. package/sample-store/gen-1/predicate-6.ibk3.sri2 +0 -0
  162. package/sample-store/gen-1/predicate-6.ibk3.sri2.merkle +0 -1
  163. package/sample-store/gen-1/predicate-6.ibk3.tli1 +0 -0
  164. package/sample-store/gen-1/predicate-6.ibk3.tli1.merkle +0 -0
  165. package/sample-store/gen-1/predicate-7.ibk3 +0 -0
  166. package/sample-store/gen-1/predicate-7.ibk3.merkle +0 -0
  167. package/sample-store/gen-1/predicate-7.ibk3.oli2 +0 -0
  168. package/sample-store/gen-1/predicate-7.ibk3.oli2.merkle +0 -2
  169. package/sample-store/gen-1/predicate-7.ibk3.sri2 +0 -0
  170. package/sample-store/gen-1/predicate-7.ibk3.sri2.merkle +0 -1
  171. package/sample-store/gen-1/predicate-7.ibk3.tli1 +0 -0
  172. package/sample-store/gen-1/predicate-7.ibk3.tli1.merkle +0 -1
  173. package/sample-store/gen-1/predicate-8.ibk3 +0 -0
  174. package/sample-store/gen-1/predicate-8.ibk3.merkle +0 -1
  175. package/sample-store/gen-1/predicate-8.ibk3.oli2 +0 -0
  176. package/sample-store/gen-1/predicate-8.ibk3.oli2.merkle +0 -1
  177. package/sample-store/gen-1/predicate-8.ibk3.sri2 +0 -0
  178. package/sample-store/gen-1/predicate-8.ibk3.sri2.merkle +0 -1
  179. package/sample-store/gen-1/predicate-8.ibk3.tli1 +0 -0
  180. package/sample-store/gen-1/predicate-8.ibk3.tli1.merkle +0 -1
  181. package/sample-store/gen-1/predicate-9.ibk3 +0 -0
  182. package/sample-store/gen-1/predicate-9.ibk3.merkle +0 -1
  183. package/sample-store/gen-1/predicate-9.ibk3.oli2 +0 -0
  184. package/sample-store/gen-1/predicate-9.ibk3.oli2.merkle +0 -1
  185. package/sample-store/gen-1/predicate-9.ibk3.sri2 +0 -0
  186. package/sample-store/gen-1/predicate-9.ibk3.sri2.merkle +0 -3
  187. package/sample-store/gen-1/predicate-9.ibk3.tli1 +0 -0
  188. package/sample-store/gen-1/predicate-9.ibk3.tli1.merkle +0 -2
  189. package/select.d.ts +0 -116
  190. package/select.js +0 -492
  191. package/version.json +0 -102
  192. package/wasm.d.ts +0 -130
  193. package/wasm.js +0 -158
package/rdfjs.mjs ADDED
@@ -0,0 +1,594 @@
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 provides converters between RDF/JS quads and the engine's
10
+ // N-Quads token strings, which are the package's dataset interchange
11
+ // handle (the Lean engine parses and serializes N-Quads; the
12
+ // converters below only tokenize/untokenize the engine's own output —
13
+ // full RDF parsing of user input always goes through the engine).
14
+ //
15
+ // ES module (0.9.0): the same file serves Node (index.mjs, and
16
+ // rdfjs.js for require()) and the browser (browser.js), with no build
17
+ // step. On output, \\ \" \n \r \t (and nothing else) are escaped;
18
+ // unescaping additionally accepts the full N-Triples ECHAR + UCHAR set
19
+ // (\t \b \n \r \f \" \' \\ \uXXXX \UXXXXXXXX) since engine input may
20
+ // legally contain them.
21
+
22
+ const XSD_STRING = 'http://www.w3.org/2001/XMLSchema#string';
23
+ const RDF_LANGSTRING =
24
+ 'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString';
25
+
26
+ // ---------------------------------------------------------------------
27
+ // Terms
28
+ // ---------------------------------------------------------------------
29
+
30
+ class NamedNode {
31
+ constructor(iri) {
32
+ this.termType = 'NamedNode';
33
+ this.value = iri;
34
+ Object.freeze(this);
35
+ }
36
+ equals(other) {
37
+ return !!other && other.termType === 'NamedNode' &&
38
+ other.value === this.value;
39
+ }
40
+ }
41
+
42
+ class BlankNode {
43
+ constructor(label) {
44
+ this.termType = 'BlankNode';
45
+ this.value = label;
46
+ Object.freeze(this);
47
+ }
48
+ equals(other) {
49
+ return !!other && other.termType === 'BlankNode' &&
50
+ other.value === this.value;
51
+ }
52
+ }
53
+
54
+ class Literal {
55
+ constructor(value, language, datatype) {
56
+ this.termType = 'Literal';
57
+ this.value = value;
58
+ this.language = language || '';
59
+ this.datatype = datatype ||
60
+ new NamedNode(language ? RDF_LANGSTRING : XSD_STRING);
61
+ Object.freeze(this);
62
+ }
63
+ equals(other) {
64
+ return !!other && other.termType === 'Literal' &&
65
+ other.value === this.value &&
66
+ other.language === this.language &&
67
+ !!other.datatype && other.datatype.value === this.datatype.value;
68
+ }
69
+ }
70
+
71
+ class Variable {
72
+ constructor(name) {
73
+ this.termType = 'Variable';
74
+ this.value = name;
75
+ Object.freeze(this);
76
+ }
77
+ equals(other) {
78
+ return !!other && other.termType === 'Variable' &&
79
+ other.value === this.value;
80
+ }
81
+ }
82
+
83
+ class DefaultGraph {
84
+ constructor() {
85
+ this.termType = 'DefaultGraph';
86
+ this.value = '';
87
+ Object.freeze(this);
88
+ }
89
+ equals(other) {
90
+ return !!other && other.termType === 'DefaultGraph';
91
+ }
92
+ }
93
+
94
+ const DEFAULT_GRAPH = new DefaultGraph();
95
+
96
+ class Quad {
97
+ constructor(subject, predicate, object, graph) {
98
+ // Per spec, a Quad is itself a Term with termType 'Quad', value ''.
99
+ this.termType = 'Quad';
100
+ this.value = '';
101
+ this.subject = subject;
102
+ this.predicate = predicate;
103
+ this.object = object;
104
+ this.graph = graph || DEFAULT_GRAPH;
105
+ Object.freeze(this);
106
+ }
107
+ equals(other) {
108
+ return !!other &&
109
+ (other.termType === 'Quad' || other.termType === undefined) &&
110
+ this.subject.equals(other.subject) &&
111
+ this.predicate.equals(other.predicate) &&
112
+ this.object.equals(other.object) &&
113
+ this.graph.equals(other.graph);
114
+ }
115
+ }
116
+
117
+ // ---------------------------------------------------------------------
118
+ // DataFactory
119
+ // ---------------------------------------------------------------------
120
+
121
+ let blankNodeCounter = 0;
122
+
123
+ const dataFactory = {
124
+ namedNode(value) {
125
+ return new NamedNode(String(value));
126
+ },
127
+ blankNode(label) {
128
+ return new BlankNode(
129
+ label !== undefined && label !== null
130
+ ? String(label)
131
+ : 'fjs_b' + (blankNodeCounter++)
132
+ );
133
+ },
134
+ literal(value, languageOrDatatype) {
135
+ const v = String(value);
136
+ if (languageOrDatatype === undefined || languageOrDatatype === null) {
137
+ return new Literal(v, '', null);
138
+ }
139
+ if (typeof languageOrDatatype === 'string') {
140
+ return new Literal(v, languageOrDatatype, null);
141
+ }
142
+ // A NamedNode datatype.
143
+ if (languageOrDatatype.termType === 'NamedNode') {
144
+ if (languageOrDatatype.value === RDF_LANGSTRING) {
145
+ // langString without a language tag is not constructible; treat
146
+ // as plain string per the most defensive reading of the spec.
147
+ return new Literal(v, '', null);
148
+ }
149
+ return new Literal(v, '', new NamedNode(languageOrDatatype.value));
150
+ }
151
+ throw new TypeError(
152
+ 'literal: second argument must be a language string or a NamedNode'
153
+ );
154
+ },
155
+ variable(name) {
156
+ return new Variable(String(name));
157
+ },
158
+ defaultGraph() {
159
+ return DEFAULT_GRAPH;
160
+ },
161
+ quad(subject, predicate, object, graph) {
162
+ return new Quad(subject, predicate, object, graph);
163
+ },
164
+ fromTerm(original) {
165
+ if (!original || typeof original.termType !== 'string') {
166
+ throw new TypeError('fromTerm: not a term');
167
+ }
168
+ switch (original.termType) {
169
+ case 'NamedNode': return new NamedNode(original.value);
170
+ case 'BlankNode': return new BlankNode(original.value);
171
+ case 'Variable': return new Variable(original.value);
172
+ case 'DefaultGraph': return DEFAULT_GRAPH;
173
+ case 'Literal':
174
+ return new Literal(
175
+ original.value,
176
+ original.language || '',
177
+ original.language
178
+ ? null
179
+ : new NamedNode(
180
+ (original.datatype && original.datatype.value) || XSD_STRING)
181
+ );
182
+ case 'Quad': return dataFactory.fromQuad(original);
183
+ default:
184
+ throw new TypeError(`fromTerm: unknown termType '${original.termType}'`);
185
+ }
186
+ },
187
+ fromQuad(original) {
188
+ if (!original || !original.subject) {
189
+ throw new TypeError('fromQuad: not a quad');
190
+ }
191
+ return new Quad(
192
+ dataFactory.fromTerm(original.subject),
193
+ dataFactory.fromTerm(original.predicate),
194
+ dataFactory.fromTerm(original.object),
195
+ original.graph ? dataFactory.fromTerm(original.graph) : DEFAULT_GRAPH
196
+ );
197
+ },
198
+ };
199
+
200
+ // ---------------------------------------------------------------------
201
+ // SPARQL Results JSON term -> RDF/JS term
202
+ // ---------------------------------------------------------------------
203
+
204
+ /**
205
+ * Convert a SPARQL 1.1 Results JSON term object
206
+ * ({type:'uri'|'bnode'|'literal'|'typed-literal', value, 'xml:lang',
207
+ * datatype}) into an RDF/JS term.
208
+ */
209
+ function termFromSrj(t) {
210
+ if (!t || typeof t.type !== 'string') {
211
+ throw new TypeError('termFromSrj: not a results-JSON term');
212
+ }
213
+ switch (t.type) {
214
+ case 'uri':
215
+ return dataFactory.namedNode(t.value);
216
+ case 'bnode':
217
+ return dataFactory.blankNode(t.value);
218
+ case 'literal':
219
+ case 'typed-literal': {
220
+ const lang = t['xml:lang'];
221
+ if (lang) return dataFactory.literal(t.value, lang);
222
+ if (t.datatype) {
223
+ return dataFactory.literal(t.value, dataFactory.namedNode(t.datatype));
224
+ }
225
+ return dataFactory.literal(t.value);
226
+ }
227
+ case 'triple': {
228
+ // RDF 1.2 triple term in SPARQL Results JSON:
229
+ // {"type":"triple","value":{"subject":T,"predicate":T,"object":T}}
230
+ // (SPARQL_Protocol.json_term) -> an RDF/JS Quad term. Recursive:
231
+ // the object may itself be a triple term.
232
+ const v = t.value || {};
233
+ return dataFactory.quad(
234
+ termFromSrj(v.subject), termFromSrj(v.predicate), termFromSrj(v.object));
235
+ }
236
+ default:
237
+ throw new TypeError(`termFromSrj: unknown term type '${t.type}'`);
238
+ }
239
+ }
240
+
241
+ // ---------------------------------------------------------------------
242
+ // N-Quads token output (mirrors RDF.NQuads.Serialize.escape_char)
243
+ // ---------------------------------------------------------------------
244
+
245
+ function escapeLiteral(s) {
246
+ let out = '';
247
+ for (const ch of s) {
248
+ switch (ch) {
249
+ case '\\': out += '\\\\'; break;
250
+ case '"': out += '\\"'; break;
251
+ case '\n': out += '\\n'; break;
252
+ case '\r': out += '\\r'; break;
253
+ case '\t': out += '\\t'; break;
254
+ default: out += ch;
255
+ }
256
+ }
257
+ return out;
258
+ }
259
+
260
+ /** Serialize one RDF/JS term to its N-Quads token. */
261
+ function termToNQuads(term) {
262
+ switch (term.termType) {
263
+ case 'NamedNode':
264
+ return '<' + term.value + '>';
265
+ case 'BlankNode':
266
+ return '_:' + term.value;
267
+ case 'Literal': {
268
+ const body = '"' + escapeLiteral(term.value) + '"';
269
+ if (term.language) return body + '@' + term.language;
270
+ if (term.datatype && term.datatype.value !== XSD_STRING) {
271
+ return body + '^^<' + term.datatype.value + '>';
272
+ }
273
+ return body;
274
+ }
275
+ case 'DefaultGraph':
276
+ return '';
277
+ case 'Quad':
278
+ // RDF 1.2 triple term -> <<( s p o )>> (matches the engine's
279
+ // Mode_12 N-Quads serializer, so it round-trips back through the
280
+ // *12 parse path).
281
+ return '<<( ' + termToNQuads(term.subject) + ' ' +
282
+ termToNQuads(term.predicate) + ' ' +
283
+ termToNQuads(term.object) + ' )>>';
284
+ default:
285
+ throw new TypeError(
286
+ `termToNQuads: cannot serialize termType '${term.termType}'`);
287
+ }
288
+ }
289
+
290
+ /** Serialize one RDF/JS quad to an N-Quads line (with trailing " .\n"). */
291
+ function quadToNQuads(quad) {
292
+ const g = quad.graph && quad.graph.termType !== 'DefaultGraph'
293
+ ? ' ' + termToNQuads(quad.graph)
294
+ : '';
295
+ return termToNQuads(quad.subject) + ' ' +
296
+ termToNQuads(quad.predicate) + ' ' +
297
+ termToNQuads(quad.object) + g + ' .\n';
298
+ }
299
+
300
+ /** Serialize an iterable of quads to an N-Quads document. */
301
+ function quadsToNQuads(quads) {
302
+ let out = '';
303
+ for (const q of quads) out += quadToNQuads(q);
304
+ return out;
305
+ }
306
+
307
+ // ---------------------------------------------------------------------
308
+ // N-Quads token input.
309
+ //
310
+ // A line tokenizer for the engine's own N-Quads output (and canonical
311
+ // N-Quads generally): one statement per line, terms separated by
312
+ // whitespace, ECHAR/UCHAR escapes inside literals. This is a token
313
+ // reader for a machine-generated regular syntax, not a general RDF
314
+ // parser — user documents in any syntax go through the engine.
315
+ // ---------------------------------------------------------------------
316
+
317
+ const UNESCAPE_MAP = {
318
+ 't': '\t', 'b': '\b', 'n': '\n', 'r': '\r', 'f': '\f',
319
+ '"': '"', "'": "'", '\\': '\\',
320
+ };
321
+
322
+ function unescapeLiteral(s, lineNo) {
323
+ if (s.indexOf('\\') < 0) return s;
324
+ let out = '';
325
+ for (let i = 0; i < s.length; i++) {
326
+ const c = s[i];
327
+ if (c !== '\\') { out += c; continue; }
328
+ const e = s[++i];
329
+ if (e in UNESCAPE_MAP) { out += UNESCAPE_MAP[e]; continue; }
330
+ if (e === 'u') {
331
+ out += String.fromCodePoint(parseInt(s.slice(i + 1, i + 5), 16));
332
+ i += 4;
333
+ continue;
334
+ }
335
+ if (e === 'U') {
336
+ out += String.fromCodePoint(parseInt(s.slice(i + 1, i + 9), 16));
337
+ i += 8;
338
+ continue;
339
+ }
340
+ throw new SyntaxError(
341
+ `N-Quads line ${lineNo}: bad escape '\\${e}'`);
342
+ }
343
+ return out;
344
+ }
345
+
346
+ // Read one term starting at s[i]; returns [term, nextIndex].
347
+ function readTerm(s, i, lineNo, factory) {
348
+ const c = s[i];
349
+ // RDF 1.2 triple term: <<( s p o )>> -> an RDF/JS Quad term
350
+ // (termType 'Quad'). Checked BEFORE the '<' IRI case since a triple
351
+ // term also opens with '<'. This reads the engine's own Mode_12
352
+ // N-Quads serializer output (RDF.NQuads.Serialize) into RDF/JS
353
+ // objects; it is not a conformance parser (that is the F* --rdf12
354
+ // path) — same interop role the rest of this reader plays.
355
+ if (c === '<' && s[i + 1] === '<' && s[i + 2] === '(') {
356
+ let j = skipWs(s, i + 3);
357
+ const [sub, a] = readTerm(s, j, lineNo, factory); j = skipWs(s, a);
358
+ const [pred, b] = readTerm(s, j, lineNo, factory); j = skipWs(s, b);
359
+ const [obj, d] = readTerm(s, j, lineNo, factory); j = skipWs(s, d);
360
+ if (s[j] === ')' && s[j + 1] === '>' && s[j + 2] === '>') {
361
+ return [factory.quad(sub, pred, obj), j + 3];
362
+ }
363
+ throw new SyntaxError(
364
+ `N-Quads line ${lineNo}: unterminated triple term (expected ')>>')`);
365
+ }
366
+ if (c === '<') {
367
+ const end = s.indexOf('>', i + 1);
368
+ if (end < 0) throw new SyntaxError(`N-Quads line ${lineNo}: unclosed IRI`);
369
+ return [factory.namedNode(s.slice(i + 1, end)), end + 1];
370
+ }
371
+ if (c === '_' && s[i + 1] === ':') {
372
+ let j = i + 2;
373
+ while (j < s.length && !/\s/.test(s[j])) j++;
374
+ return [factory.blankNode(s.slice(i + 2, j)), j];
375
+ }
376
+ if (c === '"') {
377
+ // Scan to the closing unescaped quote.
378
+ let j = i + 1;
379
+ for (;;) {
380
+ if (j >= s.length) {
381
+ throw new SyntaxError(`N-Quads line ${lineNo}: unclosed literal`);
382
+ }
383
+ if (s[j] === '\\') { j += 2; continue; }
384
+ if (s[j] === '"') break;
385
+ j++;
386
+ }
387
+ const lex = unescapeLiteral(s.slice(i + 1, j), lineNo);
388
+ j++; // past closing quote
389
+ if (s[j] === '@') {
390
+ let k = j + 1;
391
+ while (k < s.length && !/\s/.test(s[k])) k++;
392
+ return [factory.literal(lex, s.slice(j + 1, k)), k];
393
+ }
394
+ if (s[j] === '^' && s[j + 1] === '^' && s[j + 2] === '<') {
395
+ const end = s.indexOf('>', j + 3);
396
+ if (end < 0) {
397
+ throw new SyntaxError(`N-Quads line ${lineNo}: unclosed datatype IRI`);
398
+ }
399
+ return [
400
+ factory.literal(lex, factory.namedNode(s.slice(j + 3, end))),
401
+ end + 1,
402
+ ];
403
+ }
404
+ return [factory.literal(lex), j];
405
+ }
406
+ throw new SyntaxError(
407
+ `N-Quads line ${lineNo}: unexpected character '${c}' at column ${i + 1}`);
408
+ }
409
+
410
+ function skipWs(s, i) {
411
+ while (i < s.length && (s[i] === ' ' || s[i] === '\t')) i++;
412
+ return i;
413
+ }
414
+
415
+ /**
416
+ * Tokenize one N-Quads statement line into an RDF/JS quad.
417
+ * Returns null for blank/comment lines.
418
+ */
419
+ function nquadsLineToQuad(line, lineNo, factory) {
420
+ const f = factory || dataFactory;
421
+ let i = skipWs(line, 0);
422
+ if (i >= line.length || line[i] === '#') return null;
423
+ const terms = [];
424
+ while (terms.length < 4) {
425
+ const [term, next] = readTerm(line, i, lineNo, f);
426
+ terms.push(term);
427
+ i = skipWs(line, next);
428
+ if (line[i] === '.') break;
429
+ }
430
+ if (line[i] !== '.') {
431
+ throw new SyntaxError(`N-Quads line ${lineNo}: missing terminating '.'`);
432
+ }
433
+ if (terms.length < 3) {
434
+ throw new SyntaxError(`N-Quads line ${lineNo}: fewer than 3 terms`);
435
+ }
436
+ return f.quad(terms[0], terms[1], terms[2], terms[3] || f.defaultGraph());
437
+ }
438
+
439
+ /**
440
+ * Tokenize an engine-emitted N-Quads document into RDF/JS quads.
441
+ *
442
+ * options.blankNodePrefix — prepended to every blank-node label, used
443
+ * by parse() to keep labels from separate parse calls distinct (blank
444
+ * node identity is document-scoped; the prefix is bookkeeping, the
445
+ * semantic per-document renaming lives in F*
446
+ * RDF.Dataset.Merge.rename_dataset_bnodes).
447
+ */
448
+ function nquadsToQuads(text, options) {
449
+ const opts = options || {};
450
+ const factory = opts.factory || dataFactory;
451
+ const f = opts.blankNodePrefix
452
+ ? {
453
+ ...factory,
454
+ blankNode: (label) => factory.blankNode(
455
+ label === undefined || label === null
456
+ ? undefined
457
+ : opts.blankNodePrefix + label),
458
+ }
459
+ : factory;
460
+ const quads = [];
461
+ const lines = String(text).split('\n');
462
+ for (let n = 0; n < lines.length; n++) {
463
+ const q = nquadsLineToQuad(lines[n].replace(/\r$/, ''), n + 1, f);
464
+ if (q) quads.push(q);
465
+ }
466
+ return quads;
467
+ }
468
+
469
+ // ---------------------------------------------------------------------
470
+ // Dataset — a minimal RDF/JS DatasetCore over an in-memory quad array.
471
+ // ---------------------------------------------------------------------
472
+
473
+ // A string that two terms share exactly when equals() holds between them
474
+ // (the fields each equals() above compares). JSON arrays are
475
+ // self-delimiting, so the key of a quad, four term keys in a row, is
476
+ // injective too. The Dataset keeps the keys of its quads in a Set: add()
477
+ // and has() are then one lookup each. Until 2026-10-10 both scanned the
478
+ // quad array, so building a Dataset of n quads cost n^2/2 equals() calls:
479
+ // 12,000 quads took 3.1 s in parse() (issue 713 stage 5).
480
+ function termKey(t) {
481
+ if (!t) return 'null';
482
+ switch (t.termType) {
483
+ case 'Literal':
484
+ return JSON.stringify(['Literal', t.value, t.language, t.datatype ? t.datatype.value : null]);
485
+ case 'DefaultGraph':
486
+ return '["DefaultGraph"]';
487
+ case 'Quad':
488
+ return '["Quad",' + termKey(t.subject) + ',' + termKey(t.predicate) + ',' +
489
+ termKey(t.object) + ',' + termKey(t.graph) + ']';
490
+ default:
491
+ return JSON.stringify([t.termType, t.value]);
492
+ }
493
+ }
494
+
495
+ function quadKey(q) {
496
+ return termKey(q.subject) + termKey(q.predicate) + termKey(q.object) +
497
+ termKey(q.graph || DEFAULT_GRAPH);
498
+ }
499
+
500
+ /**
501
+ * An in-memory RDF/JS DatasetCore over a quad array. The package's Dataset
502
+ * (lib/dataset.mjs) keeps its data in the engine; this class is for callers
503
+ * that build quads in JavaScript, for example to hand to fn.js.
504
+ */
505
+ class DatasetCore {
506
+ constructor(quads, options) {
507
+ this._quads = [];
508
+ // The quadKey() of every quad in _quads, for set semantics in O(1).
509
+ this._keys = new Set();
510
+ if (quads) for (const q of quads) this.add(q);
511
+ const opts = options || {};
512
+ // Own, non-enumerable properties (issue #680/#681): a frozen
513
+ // snapshot of the prefixes/diagnostics the engine reported at
514
+ // parse time, so JSON.stringify()/toArray() (and any caller
515
+ // enumerating own enumerable keys) see only the quads, exactly as
516
+ // before this landed.
517
+ Object.defineProperty(this, 'prefixes', {
518
+ value: Object.freeze({ ...(opts.prefixes || {}) }),
519
+ enumerable: false, writable: false, configurable: false,
520
+ });
521
+ Object.defineProperty(this, 'diagnostics', {
522
+ value: Object.freeze((opts.diagnostics || []).slice()),
523
+ enumerable: false, writable: false, configurable: false,
524
+ });
525
+ }
526
+ get size() {
527
+ return this._quads.length;
528
+ }
529
+ add(quad) {
530
+ const key = quadKey(quad);
531
+ if (!this._keys.has(key)) {
532
+ this._keys.add(key);
533
+ this._quads.push(quad);
534
+ }
535
+ return this;
536
+ }
537
+ delete(quad) {
538
+ if (this._keys.delete(quadKey(quad))) {
539
+ const ix = this._quads.findIndex((q) => q.equals(quad));
540
+ if (ix >= 0) this._quads.splice(ix, 1);
541
+ }
542
+ return this;
543
+ }
544
+ has(quad) {
545
+ return this._keys.has(quadKey(quad));
546
+ }
547
+ match(subject, predicate, object, graph) {
548
+ const out = new DatasetCore();
549
+ for (const q of this._quads) {
550
+ if (subject && !subject.equals(q.subject)) continue;
551
+ if (predicate && !predicate.equals(q.predicate)) continue;
552
+ if (object && !object.equals(q.object)) continue;
553
+ if (graph && !graph.equals(q.graph)) continue;
554
+ out._quads.push(q);
555
+ out._keys.add(quadKey(q));
556
+ }
557
+ return out;
558
+ }
559
+ [Symbol.iterator]() {
560
+ return this._quads[Symbol.iterator]();
561
+ }
562
+ toArray() {
563
+ return this._quads.slice();
564
+ }
565
+ /** N-Quads text — the engine interchange handle. */
566
+ toNQuads() {
567
+ return quadsToNQuads(this._quads);
568
+ }
569
+ toString() {
570
+ return this.toNQuads();
571
+ }
572
+ static fromNQuads(text, options) {
573
+ return new DatasetCore(nquadsToQuads(text, options), options);
574
+ }
575
+ }
576
+
577
+ export {
578
+ dataFactory,
579
+ NamedNode,
580
+ BlankNode,
581
+ Literal,
582
+ Variable,
583
+ DefaultGraph,
584
+ Quad,
585
+ DatasetCore,
586
+ termFromSrj,
587
+ nquadsLineToQuad,
588
+ termToNQuads,
589
+ quadToNQuads,
590
+ quadsToNQuads,
591
+ nquadsToQuads,
592
+ XSD_STRING,
593
+ RDF_LANGSTRING,
594
+ }
package/sample-store.d.ts CHANGED
@@ -1,16 +1,8 @@
1
- /** The collection root of the sample Shardborough store bundled with this
2
- * package: the directory that holds CURRENT. */
3
- export declare function sampleStorePath (): string
4
-
5
- export declare const sampleStoreFacts: Readonly<{
6
- triples: number
7
- blocks: number
8
- layout: string
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;