@factoidal/core 0.13.0 → 0.15.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 +23 -0
- package/README.md +58 -8
- package/bin/factoidal.mjs +6 -6
- package/browser.d.ts +10 -0
- package/browser.js +17 -0
- package/index.d.ts +279 -11
- package/index.mjs +26 -0
- package/l4-assets/l4factoidal.js +1 -1
- package/l4-assets/l4factoidal.mjs +1 -1
- package/l4-assets/l4factoidal.wasm +0 -0
- package/l4-assets/version.json +6 -6
- package/lib/api.mjs +55 -3
- package/lib/dataset.mjs +8 -0
- package/lib/evidence.mjs +93 -0
- package/lib/nodes.mjs +274 -0
- package/lib/sbm11-lws.mjs +200 -0
- package/lib/sbm11-node.mjs +61 -0
- package/lib/sbm11.mjs +155 -0
- package/lib/sync-http-node.mjs +71 -0
- package/lib/version.mjs +1 -1
- package/package.json +1 -1
- package/sample-store.mjs +1 -1
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// A synchronous HTTP GET for Node, for the readers of lib/sbm11.mjs that read
|
|
2
|
+
// over HTTP (lib/sbm11-lws.mjs; https://github.com/danbri/factoidal/issues/1010).
|
|
3
|
+
// The engine is inside WebAssembly and asks for bytes synchronously; Node's
|
|
4
|
+
// fetch is asynchronous. A worker thread makes the fetch; this thread waits
|
|
5
|
+
// on a shared Int32Array (Atomics.wait) and takes the answer with
|
|
6
|
+
// receiveMessageOnPort. Pure I/O: no header is read here, no status judged.
|
|
7
|
+
//
|
|
8
|
+
// The thread that calls the transport is blocked until the answer comes, so
|
|
9
|
+
// the server must not run on that thread (start it in another process or
|
|
10
|
+
// worker).
|
|
11
|
+
|
|
12
|
+
import { Worker, MessageChannel, receiveMessageOnPort } from 'node:worker_threads'
|
|
13
|
+
|
|
14
|
+
const WORKER = `
|
|
15
|
+
const { workerData } = require('node:worker_threads')
|
|
16
|
+
const { port, signal } = workerData
|
|
17
|
+
const flag = new Int32Array(signal)
|
|
18
|
+
port.on('message', async (req) => {
|
|
19
|
+
let out
|
|
20
|
+
try {
|
|
21
|
+
const r = await fetch(req.url, { headers: req.headers, redirect: 'follow' })
|
|
22
|
+
const headers = {}
|
|
23
|
+
r.headers.forEach((v, k) => { headers[k] = v })
|
|
24
|
+
out = { status: r.status, headers, bytes: new Uint8Array(await r.arrayBuffer()) }
|
|
25
|
+
} catch (e) {
|
|
26
|
+
out = { error: String(e && e.message ? e.message : e) }
|
|
27
|
+
}
|
|
28
|
+
port.postMessage(out)
|
|
29
|
+
Atomics.store(flag, 0, 1)
|
|
30
|
+
Atomics.notify(flag, 0)
|
|
31
|
+
})
|
|
32
|
+
`
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* A synchronous transport `(url, headers) -> { status, header(name), bytes }`
|
|
36
|
+
* with a `close()` that stops its worker.
|
|
37
|
+
*
|
|
38
|
+
* @param {object} [opts]
|
|
39
|
+
* @param {number} [opts.timeoutMs] the most one request may take (default 60000)
|
|
40
|
+
*/
|
|
41
|
+
export function nodeSyncTransport (opts = {}) {
|
|
42
|
+
const timeoutMs = typeof opts.timeoutMs === 'number' ? opts.timeoutMs : 60000
|
|
43
|
+
const signal = new SharedArrayBuffer(4)
|
|
44
|
+
const flag = new Int32Array(signal)
|
|
45
|
+
const { port1, port2 } = new MessageChannel()
|
|
46
|
+
const worker = new Worker(WORKER, { eval: true, workerData: { port: port2, signal }, transferList: [port2] })
|
|
47
|
+
worker.unref()
|
|
48
|
+
port1.unref()
|
|
49
|
+
let closed = false
|
|
50
|
+
function transport (url, headers) {
|
|
51
|
+
if (closed) throw new Error('the transport is closed')
|
|
52
|
+
Atomics.store(flag, 0, 0)
|
|
53
|
+
port1.postMessage({ url: String(url), headers: { ...headers } })
|
|
54
|
+
if (Atomics.wait(flag, 0, 0, timeoutMs) === 'timed-out') {
|
|
55
|
+
throw new Error(`GET ${url}: no answer in ${timeoutMs} ms`)
|
|
56
|
+
}
|
|
57
|
+
const got = receiveMessageOnPort(port1)
|
|
58
|
+
if (!got) throw new Error(`GET ${url}: no answer from the transport worker`)
|
|
59
|
+
const m = got.message
|
|
60
|
+
if (m.error) throw new Error(m.error)
|
|
61
|
+
const h = m.headers
|
|
62
|
+
return { status: m.status, header: (name) => (Object.hasOwn(h, name.toLowerCase()) ? h[name.toLowerCase()] : null), bytes: m.bytes }
|
|
63
|
+
}
|
|
64
|
+
transport.close = () => {
|
|
65
|
+
if (closed) return
|
|
66
|
+
closed = true
|
|
67
|
+
port1.close()
|
|
68
|
+
worker.terminate()
|
|
69
|
+
}
|
|
70
|
+
return transport
|
|
71
|
+
}
|
package/lib/version.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@factoidal/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "RDF parsing and writing (Turtle, TriG, N-Triples, N-Quads, RDF/XML, JSON-LD), SPARQL 1.1 and 1.2, RDFS and OWL reasoning, SHACL and ShEx validation, CSVW and RML mapping, RDFC-1.0, and SPARQL, LWS and Solid servers, for Node, Deno and browsers.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sparql",
|
package/sample-store.mjs
CHANGED
|
@@ -27,7 +27,7 @@ ex:c3 a skos:Concept ; skos:inScheme ex:scheme ; skos:prefLabel "SECAM"@en ; sko
|
|
|
27
27
|
export const sampleStoreFacts = Object.freeze({
|
|
28
28
|
triples: 15,
|
|
29
29
|
source: 'SAMPLE_TURTLE in sample-store.mjs (written for this package)',
|
|
30
|
-
layout: '
|
|
30
|
+
layout: 'ibk5'
|
|
31
31
|
})
|
|
32
32
|
|
|
33
33
|
/**
|