@rdfc/js-runner 2.0.0 → 3.0.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/.editorconfig +9 -0
- package/.github/renovate.json +3 -0
- package/.idea/copilot.data.migration.agent.xml +6 -0
- package/.idea/copilot.data.migration.ask.xml +6 -0
- package/.idea/copilot.data.migration.ask2agent.xml +6 -0
- package/.idea/copilot.data.migration.edit.xml +6 -0
- package/README.md +127 -3
- package/__tests__/channels.test.ts +131 -74
- package/__tests__/echoProcessor.test.ts +132 -0
- package/__tests__/testProcessor.test.ts +69 -0
- package/eslint.config.mjs +1 -1
- package/index.ttl +3 -31
- package/lib/client.js +6 -9
- package/lib/logger.d.ts +2 -2
- package/lib/logger.js +3 -3
- package/lib/reader.d.ts +8 -6
- package/lib/reader.js +135 -25
- package/lib/runner.d.ts +11 -6
- package/lib/runner.js +86 -46
- package/lib/testUtils/duplex.d.ts +25 -0
- package/lib/testUtils/duplex.js +70 -0
- package/lib/testUtils/index.d.ts +51 -0
- package/lib/testUtils/index.js +243 -0
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/writer.d.ts +12 -5
- package/lib/writer.js +66 -13
- package/package.json +22 -22
- package/src/client.ts +8 -11
- package/src/logger.ts +3 -3
- package/src/reader.ts +214 -36
- package/src/runner.ts +129 -67
- package/src/testUtils/duplex.ts +112 -0
- package/src/testUtils/index.ts +430 -0
- package/src/writer.ts +106 -16
- package/lib/jsonld.d.ts +0 -17
- package/lib/jsonld.js +0 -135
- package/lib/testUtils.d.ts +0 -24
- package/lib/testUtils.js +0 -150
- package/src/jsonld.ts +0 -220
- package/src/testUtils.ts +0 -196
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { Duplex } from 'stream'
|
|
2
|
+
import type {
|
|
3
|
+
ClientDuplexStream,
|
|
4
|
+
InterceptingCallInterface,
|
|
5
|
+
} from '@grpc/grpc-js'
|
|
6
|
+
import { AuthContext } from '@grpc/grpc-js/build/src/auth-context'
|
|
7
|
+
|
|
8
|
+
type Matcher<Req, T> = (req: Req) => T | undefined
|
|
9
|
+
type Handler<Req, Res> = (req: Req, send: (res: Res) => void) => void
|
|
10
|
+
|
|
11
|
+
type MatchObject<Req, Res, T> = {
|
|
12
|
+
matcher: Matcher<Req, T>
|
|
13
|
+
handler: Handler<T, Res>
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
let count = 0
|
|
17
|
+
export class MockClientDuplexStream<Req, Res>
|
|
18
|
+
extends Duplex
|
|
19
|
+
implements ClientDuplexStream<Req, Res>
|
|
20
|
+
{
|
|
21
|
+
private capabilities: Array<MatchObject<Req, Res, unknown>> = []
|
|
22
|
+
private onceCapabilities: Array<MatchObject<Req, Res, unknown>> = []
|
|
23
|
+
|
|
24
|
+
public readonly id: number
|
|
25
|
+
|
|
26
|
+
call?: InterceptingCallInterface | undefined
|
|
27
|
+
constructor() {
|
|
28
|
+
super({ objectMode: true })
|
|
29
|
+
this.id = count++
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
getAuthContext(): AuthContext | null {
|
|
33
|
+
return null
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// ---- SurfaceCall stubs ----
|
|
37
|
+
cancel(): void {}
|
|
38
|
+
getPeer(): string {
|
|
39
|
+
return 'mock-peer'
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// ---- ObjectWritable<Req> ----
|
|
43
|
+
_write(
|
|
44
|
+
chunk: Req,
|
|
45
|
+
_encoding: BufferEncoding,
|
|
46
|
+
callback: (error?: Error | null) => void,
|
|
47
|
+
): void {
|
|
48
|
+
let handled = false
|
|
49
|
+
// check registered capabilities
|
|
50
|
+
for (const { matcher, handler } of this.capabilities) {
|
|
51
|
+
const o = matcher(chunk)
|
|
52
|
+
if (o !== undefined) {
|
|
53
|
+
handled = true
|
|
54
|
+
handler(o, (res) => this.send(res))
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const newOnce: typeof this.onceCapabilities = []
|
|
59
|
+
for (const { matcher, handler } of this.onceCapabilities) {
|
|
60
|
+
const o = matcher(chunk)
|
|
61
|
+
if (o !== undefined) {
|
|
62
|
+
handled = true
|
|
63
|
+
handler(o, (res) => this.send(res))
|
|
64
|
+
} else {
|
|
65
|
+
newOnce.push({ matcher, handler })
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
this.onceCapabilities = newOnce
|
|
70
|
+
if (!handled) {
|
|
71
|
+
console.error('Unhandled!', Object.keys(chunk as object))
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
callback()
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// ---- ObjectReadable<Res> ----
|
|
78
|
+
_read(): void {
|
|
79
|
+
// no-op: we push manually with send()
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// ---- gRPC-style helpers ----
|
|
83
|
+
serialize(value: Req): Buffer {
|
|
84
|
+
return Buffer.from(JSON.stringify(value))
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
deserialize(chunk: Buffer): Res {
|
|
88
|
+
return JSON.parse(chunk.toString())
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
send(response: Res): void {
|
|
92
|
+
this.push(response)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
end(): this {
|
|
96
|
+
this.push(null)
|
|
97
|
+
return this
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// ---- Capability registration ----
|
|
101
|
+
register<T>(matcher: Matcher<Req, T>, handler: Handler<T, Res>): void {
|
|
102
|
+
this.capabilities.push({ matcher, handler })
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
registerOnce<T>(matcher: Matcher<Req, T>, handler: Handler<T, Res>): void {
|
|
106
|
+
this.onceCapabilities.push({ matcher, handler })
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
awaitMsg<T>(matcher: Matcher<Req, T>): Promise<T> {
|
|
110
|
+
return new Promise((res) => this.registerOnce(matcher, res))
|
|
111
|
+
}
|
|
112
|
+
}
|
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DataChunk,
|
|
3
|
+
FromRunner,
|
|
4
|
+
LogMessage,
|
|
5
|
+
Processor as ProcConfig,
|
|
6
|
+
ToRunner,
|
|
7
|
+
} from '@rdfc/proto'
|
|
8
|
+
import {} from '../reexports'
|
|
9
|
+
import { extractShapes } from 'rdf-lens'
|
|
10
|
+
import { NamedNode, Parser, Writer as N3Writer } from 'n3'
|
|
11
|
+
import { readFile } from 'fs/promises'
|
|
12
|
+
import winston, { createLogger } from 'winston'
|
|
13
|
+
import { Processor } from '../processor'
|
|
14
|
+
import { FullProc, Runner, Writable } from '../runner'
|
|
15
|
+
import { Quad } from '@rdfjs/types'
|
|
16
|
+
import { createTermNamespace } from '@treecg/types'
|
|
17
|
+
import {
|
|
18
|
+
ReceivingStreamControl,
|
|
19
|
+
SendingStreamControl,
|
|
20
|
+
StreamChunk,
|
|
21
|
+
StreamIdentify,
|
|
22
|
+
} from '@rdfc/proto/lib/generated/common'
|
|
23
|
+
import { MockClientDuplexStream } from './duplex'
|
|
24
|
+
import { promisify } from 'util'
|
|
25
|
+
import { Reader } from '../reader'
|
|
26
|
+
import { Writer } from '../writer'
|
|
27
|
+
|
|
28
|
+
export function channel(runner: Runner, name: string): [Writer, Reader] {
|
|
29
|
+
const n = new NamedNode(name)
|
|
30
|
+
const reader = runner.createReader(n)
|
|
31
|
+
const writer = runner.createWriter(n)
|
|
32
|
+
|
|
33
|
+
return [writer, reader]
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export class StreamMsgMock {
|
|
37
|
+
data: DataChunk[] = []
|
|
38
|
+
|
|
39
|
+
private readonly resolveId: (id: StreamIdentify) => number
|
|
40
|
+
|
|
41
|
+
constructor(resolveId: (id: StreamIdentify) => number) {
|
|
42
|
+
this.resolveId = resolveId
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
sendStreamMessage(): MockClientDuplexStream<
|
|
46
|
+
StreamChunk,
|
|
47
|
+
ReceivingStreamControl
|
|
48
|
+
> {
|
|
49
|
+
const sendingStream = new MockClientDuplexStream<
|
|
50
|
+
StreamChunk,
|
|
51
|
+
ReceivingStreamControl
|
|
52
|
+
>()
|
|
53
|
+
|
|
54
|
+
let at = 0
|
|
55
|
+
sendingStream.register(
|
|
56
|
+
(x) => x.data,
|
|
57
|
+
(d, send) => {
|
|
58
|
+
setTimeout(() => send({ streamSequenceNumber: ++at }), 20)
|
|
59
|
+
this.data.push(d)
|
|
60
|
+
},
|
|
61
|
+
)
|
|
62
|
+
sendingStream.register(
|
|
63
|
+
(x) => x.id,
|
|
64
|
+
(d, send) => send({ streamSequenceNumber: this.resolveId(d) }),
|
|
65
|
+
)
|
|
66
|
+
return sendingStream
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export class OrchestratorMock {
|
|
71
|
+
connectStream: MockClientDuplexStream<FromRunner, ToRunner>
|
|
72
|
+
|
|
73
|
+
streamMsgs: {
|
|
74
|
+
[id: string]: {
|
|
75
|
+
toProducingStream: (id: ReceivingStreamControl) => void
|
|
76
|
+
receivingStream?: MockClientDuplexStream<SendingStreamControl, DataChunk>
|
|
77
|
+
}
|
|
78
|
+
} = {}
|
|
79
|
+
|
|
80
|
+
streamMsgCount = 0
|
|
81
|
+
|
|
82
|
+
connect(): MockClientDuplexStream<FromRunner, ToRunner> {
|
|
83
|
+
const connectStream = new MockClientDuplexStream<FromRunner, ToRunner>()
|
|
84
|
+
// Always bounce processed msgs back to the runner
|
|
85
|
+
connectStream.register(
|
|
86
|
+
(msg) => msg.processed,
|
|
87
|
+
({ channel, globalSequenceNumber }, send) => {
|
|
88
|
+
send({
|
|
89
|
+
processed: { channel, localSequenceNumber: globalSequenceNumber },
|
|
90
|
+
})
|
|
91
|
+
},
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
// Always bounce data msgs back to the runner
|
|
95
|
+
connectStream.register(
|
|
96
|
+
(msg) => msg.msg,
|
|
97
|
+
({ localSequenceNumber, data, channel }, send) => {
|
|
98
|
+
send({
|
|
99
|
+
msg: { globalSequenceNumber: localSequenceNumber, channel, data },
|
|
100
|
+
})
|
|
101
|
+
},
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
// Always bounce close msgs back to the runner
|
|
105
|
+
connectStream.register(
|
|
106
|
+
(msg) => msg.close,
|
|
107
|
+
(close, send) => {
|
|
108
|
+
send({ close })
|
|
109
|
+
},
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
this.connectStream = connectStream
|
|
113
|
+
return connectStream
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
sendStreamMessage(): MockClientDuplexStream<
|
|
117
|
+
StreamChunk,
|
|
118
|
+
ReceivingStreamControl
|
|
119
|
+
> {
|
|
120
|
+
const out = new MockClientDuplexStream<
|
|
121
|
+
StreamChunk,
|
|
122
|
+
ReceivingStreamControl
|
|
123
|
+
>()
|
|
124
|
+
const id = this.streamMsgCount
|
|
125
|
+
this.streamMsgCount++
|
|
126
|
+
|
|
127
|
+
out.registerOnce(
|
|
128
|
+
(x) => x.id,
|
|
129
|
+
({ channel }, toProducingStream) => {
|
|
130
|
+
this.streamMsgs[id] = { toProducingStream }
|
|
131
|
+
|
|
132
|
+
// Notify stream message
|
|
133
|
+
this.connectStream.send({
|
|
134
|
+
streamMsg: { channel, globalSequenceNumber: id },
|
|
135
|
+
})
|
|
136
|
+
},
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
out.register(
|
|
140
|
+
(x) => x.data,
|
|
141
|
+
(data) => {
|
|
142
|
+
// bounce data to receiving stream
|
|
143
|
+
this.streamMsgs[id].receivingStream!.send(data)
|
|
144
|
+
},
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
out.on('end', () => {
|
|
148
|
+
// end receiving stream
|
|
149
|
+
this.streamMsgs[id].receivingStream!.end()
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
return out
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
receiveStreamMessage(): MockClientDuplexStream<
|
|
156
|
+
SendingStreamControl,
|
|
157
|
+
DataChunk
|
|
158
|
+
> {
|
|
159
|
+
const receivingStream = new MockClientDuplexStream<
|
|
160
|
+
SendingStreamControl,
|
|
161
|
+
DataChunk
|
|
162
|
+
>()
|
|
163
|
+
let streamId = 0
|
|
164
|
+
|
|
165
|
+
receivingStream.registerOnce(
|
|
166
|
+
(x) => x.globalSequenceNumber,
|
|
167
|
+
(id) => {
|
|
168
|
+
streamId = id
|
|
169
|
+
this.streamMsgs[id].receivingStream = receivingStream
|
|
170
|
+
this.streamMsgs[id].toProducingStream({ streamSequenceNumber: 0 })
|
|
171
|
+
},
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
receivingStream.register(
|
|
175
|
+
(x) => x.streamSequenceNumber,
|
|
176
|
+
(streamSequenceNumber) => {
|
|
177
|
+
// Bounce processed message to producing stream
|
|
178
|
+
this.streamMsgs[streamId].toProducingStream({ streamSequenceNumber })
|
|
179
|
+
},
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
return receivingStream
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
logStream(): MockClientDuplexStream<LogMessage, null> {
|
|
186
|
+
const logStream = new MockClientDuplexStream<LogMessage, null>()
|
|
187
|
+
logStream.register((x) => x, console.log)
|
|
188
|
+
return logStream
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export function createRunner(uri = 'http://example.com/ns#') {
|
|
193
|
+
const logger = createLogger({
|
|
194
|
+
transports: new winston.transports.Console({
|
|
195
|
+
level: process.env['DEBUG'] || 'info',
|
|
196
|
+
}),
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
// Mock the GRPC
|
|
200
|
+
const client = new OrchestratorMock()
|
|
201
|
+
|
|
202
|
+
// Connect just like client.ts:start()
|
|
203
|
+
const stream = client.connect()
|
|
204
|
+
const writable = promisify(stream.write.bind(stream))
|
|
205
|
+
|
|
206
|
+
const runner = new Runner(
|
|
207
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
208
|
+
client as any, // Type assertion for testing
|
|
209
|
+
writable as Writable,
|
|
210
|
+
uri,
|
|
211
|
+
logger,
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
stream.on('data', (msg: ToRunner) => runner.handleOrchMessage(msg))
|
|
215
|
+
|
|
216
|
+
return runner
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export async function one<T>(iter: AsyncIterable<T>): Promise<T | undefined> {
|
|
220
|
+
for await (const item of iter) {
|
|
221
|
+
return item
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const shapeQuads = `
|
|
226
|
+
@prefix rdfc: <https://w3id.org/rdf-connect#>.
|
|
227
|
+
@prefix xsd: <http://www.w3.org/2001/XMLSchema#>.
|
|
228
|
+
@prefix sh: <http://www.w3.org/ns/shacl#>.
|
|
229
|
+
[ ] a sh:NodeShape;
|
|
230
|
+
sh:targetClass <JsProcessorShape>;
|
|
231
|
+
sh:property [
|
|
232
|
+
sh:path rdfc:entrypoint;
|
|
233
|
+
sh:name "location";
|
|
234
|
+
sh:minCount 1;
|
|
235
|
+
sh:maxCount 1;
|
|
236
|
+
sh:datatype xsd:string;
|
|
237
|
+
], [
|
|
238
|
+
sh:path rdfc:file;
|
|
239
|
+
sh:name "file";
|
|
240
|
+
sh:minCount 1;
|
|
241
|
+
sh:maxCount 1;
|
|
242
|
+
sh:datatype xsd:string;
|
|
243
|
+
], [
|
|
244
|
+
sh:path rdfc:class;
|
|
245
|
+
sh:name "clazz";
|
|
246
|
+
sh:maxCount 1;
|
|
247
|
+
sh:datatype xsd:string;
|
|
248
|
+
].
|
|
249
|
+
`
|
|
250
|
+
export type ConfigType = {
|
|
251
|
+
location: string
|
|
252
|
+
file: string
|
|
253
|
+
clazz: string
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const OWL = createTermNamespace('http://www.w3.org/2002/07/owl#', 'imports')
|
|
257
|
+
const processorShapes = extractShapes(new Parser().parse(shapeQuads))
|
|
258
|
+
const base = 'https://w3id.org/rdf-connect#'
|
|
259
|
+
|
|
260
|
+
export async function importFile(
|
|
261
|
+
file: string,
|
|
262
|
+
content?: string,
|
|
263
|
+
): Promise<Quad[]> {
|
|
264
|
+
const done = new Set<string>()
|
|
265
|
+
|
|
266
|
+
const quads: Quad[] = []
|
|
267
|
+
const todo: URL[] = []
|
|
268
|
+
|
|
269
|
+
const parse = (content: string, baseIRI: URL) => {
|
|
270
|
+
done.add(baseIRI.toString())
|
|
271
|
+
|
|
272
|
+
const extras = new Parser({ baseIRI: baseIRI.toString() }).parse(content)
|
|
273
|
+
|
|
274
|
+
for (const o of extras
|
|
275
|
+
.filter(
|
|
276
|
+
(x) =>
|
|
277
|
+
x.subject.value === baseIRI?.toString() &&
|
|
278
|
+
x.predicate.equals(OWL.imports),
|
|
279
|
+
)
|
|
280
|
+
.map((x) => x.object.value)) {
|
|
281
|
+
todo.push(new URL(o))
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
quads.push(...extras)
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
if (content) {
|
|
288
|
+
parse(content, new URL('file://' + file))
|
|
289
|
+
} else {
|
|
290
|
+
todo.push(new URL('file://' + file))
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
let item = todo.pop()
|
|
294
|
+
while (item !== undefined) {
|
|
295
|
+
if (done.has(item.toString())) {
|
|
296
|
+
item = todo.pop()
|
|
297
|
+
continue
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
if (item.protocol !== 'file:') {
|
|
301
|
+
throw 'No supported protocol ' + item.protocol
|
|
302
|
+
}
|
|
303
|
+
const txt = await readFile(item.pathname, { encoding: 'utf8' })
|
|
304
|
+
parse(txt, item)
|
|
305
|
+
|
|
306
|
+
item = todo.pop()
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
return quads
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Helper class to gradually test your processors.
|
|
314
|
+
* Possible flow:
|
|
315
|
+
* - import the JsRunner index file
|
|
316
|
+
* - import your processor config file
|
|
317
|
+
* - test if the config is as you would expect (from getConfig())
|
|
318
|
+
* - import your processor definition (inline)
|
|
319
|
+
* - build your processor
|
|
320
|
+
* - test your processor
|
|
321
|
+
*/
|
|
322
|
+
export class ProcHelper<T extends Processor<unknown>> {
|
|
323
|
+
runner: Runner
|
|
324
|
+
quads: Quad[] = []
|
|
325
|
+
config: ConfigType
|
|
326
|
+
proc: FullProc<T>
|
|
327
|
+
|
|
328
|
+
constructor(uri?: string) {
|
|
329
|
+
this.runner = createRunner(uri)
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
async importInline(baseIRI: string, config: string) {
|
|
333
|
+
const configQuads = await importFile(baseIRI, config)
|
|
334
|
+
this.quads.push(...configQuads)
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
async importFile(file: string) {
|
|
338
|
+
const configQuads = await importFile(file)
|
|
339
|
+
this.quads.push(...configQuads)
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
getConfig(ty: string | NamedNode): ConfigType {
|
|
343
|
+
const id = typeof ty === 'string' ? new NamedNode(base + ty) : ty
|
|
344
|
+
const procConfig = <ConfigType>processorShapes.lenses[
|
|
345
|
+
'JsProcessorShape'
|
|
346
|
+
].execute({
|
|
347
|
+
id,
|
|
348
|
+
quads: this.quads,
|
|
349
|
+
})
|
|
350
|
+
|
|
351
|
+
this.config = procConfig
|
|
352
|
+
return procConfig
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
async getProcessor(
|
|
356
|
+
uri: string = 'http://example.com/ns#processor',
|
|
357
|
+
): Promise<FullProc<T>> {
|
|
358
|
+
await this.runner.handleOrchMessage({
|
|
359
|
+
pipeline: new N3Writer().quadsToString(this.quads),
|
|
360
|
+
})
|
|
361
|
+
|
|
362
|
+
const proc = await this.runner.addProcessor<T>({
|
|
363
|
+
config: JSON.stringify(this.config),
|
|
364
|
+
arguments: '',
|
|
365
|
+
uri,
|
|
366
|
+
})
|
|
367
|
+
return proc
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* @deprecated use {@link ProcHelper}
|
|
373
|
+
*/
|
|
374
|
+
export async function getProcInline<T extends Processor<unknown>>(
|
|
375
|
+
config: string,
|
|
376
|
+
ty: string,
|
|
377
|
+
runner: Runner,
|
|
378
|
+
baseIRI: string,
|
|
379
|
+
uri = 'http://example.com/ns#processor',
|
|
380
|
+
): Promise<FullProc<T>> {
|
|
381
|
+
const configQuads = await importFile(baseIRI, config)
|
|
382
|
+
const procConfig = <ProcConfig>processorShapes.lenses[
|
|
383
|
+
'JsProcessorShape'
|
|
384
|
+
].execute({
|
|
385
|
+
id: new NamedNode(base + ty),
|
|
386
|
+
quads: configQuads,
|
|
387
|
+
})
|
|
388
|
+
|
|
389
|
+
await runner.handleOrchMessage({
|
|
390
|
+
pipeline: new N3Writer().quadsToString(configQuads),
|
|
391
|
+
})
|
|
392
|
+
|
|
393
|
+
const proc = await runner.addProcessor<T>({
|
|
394
|
+
config: JSON.stringify(procConfig),
|
|
395
|
+
arguments: '',
|
|
396
|
+
uri,
|
|
397
|
+
})
|
|
398
|
+
|
|
399
|
+
return proc
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* @deprecated use {@link ProcHelper}
|
|
404
|
+
*/
|
|
405
|
+
export async function getProc<T extends Processor<unknown>>(
|
|
406
|
+
config: string,
|
|
407
|
+
ty: string,
|
|
408
|
+
runner: Runner,
|
|
409
|
+
configLocation: string,
|
|
410
|
+
uri = 'http://example.com/ns#processor',
|
|
411
|
+
): Promise<FullProc<T>> {
|
|
412
|
+
const configQuads = await importFile(configLocation)
|
|
413
|
+
const procConfig = processorShapes.lenses['JsProcessorShape'].execute({
|
|
414
|
+
id: new NamedNode(base + ty),
|
|
415
|
+
quads: configQuads,
|
|
416
|
+
})
|
|
417
|
+
|
|
418
|
+
configQuads.push(...new Parser().parse(config))
|
|
419
|
+
await runner.handleOrchMessage({
|
|
420
|
+
pipeline: new N3Writer().quadsToString(configQuads),
|
|
421
|
+
})
|
|
422
|
+
|
|
423
|
+
const proc = await runner.addProcessor<T>({
|
|
424
|
+
config: JSON.stringify(procConfig),
|
|
425
|
+
arguments: '',
|
|
426
|
+
uri,
|
|
427
|
+
})
|
|
428
|
+
|
|
429
|
+
return proc
|
|
430
|
+
}
|