@rdfc/js-runner 3.0.3 → 3.0.4-remote

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 (45) hide show
  1. package/.claude/settings.local.json +12 -0
  2. package/README.md +37 -1
  3. package/bin/runner.js +7 -1
  4. package/bin/server.js +13 -0
  5. package/examples/echo/.idea/echo.iml +9 -0
  6. package/examples/echo/.idea/misc.xml +6 -0
  7. package/examples/echo/.idea/modules.xml +8 -0
  8. package/examples/echo/.idea/vcs.xml +7 -0
  9. package/examples/echo/.swls/config.json +1 -0
  10. package/examples/echo/package-lock.json +27 -29
  11. package/examples/echo/pipeline.ttl +0 -1
  12. package/examples/echo/processors.ttl +1 -1
  13. package/examples/echo/remote_pipeline.ttl +18 -0
  14. package/examples/echo/server.ttl +5 -0
  15. package/examples/echo/untitled:/types/MyType.ttl +0 -0
  16. package/file:/home/silvius/Projects/mumo-pipeline/ldes/http_3A_2F_2Fdata.mumo.be_2Fstreams_2Fnodes_2Fdefault/root/index.trig +3 -0
  17. package/ldes/http_3A_2F_2Fdata.mumo.be_2Fstreams_2Fnodes_2Fdefault/root/index.trig +3 -0
  18. package/lib/client.d.ts +2 -1
  19. package/lib/client.js +70 -22
  20. package/lib/index.d.ts +2 -0
  21. package/lib/index.js +3 -1
  22. package/lib/jsonld.d.ts +17 -0
  23. package/lib/jsonld.js +135 -0
  24. package/lib/reader.d.ts +4 -1
  25. package/lib/reader.js +11 -3
  26. package/lib/runner.d.ts +6 -1
  27. package/lib/runner.js +43 -15
  28. package/lib/server.d.ts +9 -0
  29. package/lib/server.js +459 -0
  30. package/lib/state.d.ts +32 -0
  31. package/lib/state.js +71 -0
  32. package/lib/testUtils.d.ts +24 -0
  33. package/lib/testUtils.js +150 -0
  34. package/lib/tsconfig.tsbuildinfo +1 -1
  35. package/lib/writer.d.ts +5 -1
  36. package/lib/writer.js +26 -10
  37. package/minimal.ttl +99 -0
  38. package/package.json +12 -11
  39. package/src/client.ts +99 -24
  40. package/src/index.ts +2 -0
  41. package/src/reader.ts +11 -1
  42. package/src/runner.ts +58 -11
  43. package/src/server.ts +545 -0
  44. package/src/state.ts +105 -0
  45. package/src/writer.ts +36 -12
package/lib/writer.js CHANGED
@@ -9,16 +9,23 @@ export class WriterInstance {
9
9
  awaitingProcessed = [];
10
10
  openStreams = 0;
11
11
  shouldClose = [];
12
+ hasClosed = false;
13
+ remoteCloseReceived = false;
12
14
  runnerId;
13
- constructor(uri, client, notifyOrchestrator, runnerId, logger) {
15
+ tracker;
16
+ constructor(uri, client, notifyOrchestrator, runnerId, logger, tracker) {
14
17
  this.client = client;
15
18
  this.notifyOrchestrator = notifyOrchestrator;
16
19
  this.uri = uri;
17
20
  this.logger = logger;
18
21
  this.runnerId = runnerId;
22
+ this.tracker = tracker;
19
23
  }
20
- awaitProcessed() {
21
- return new Promise((res) => this.awaitingProcessed.push(res));
24
+ awaitProcessed(bytes) {
25
+ const startMs = Date.now();
26
+ return new Promise((resolve) => {
27
+ this.awaitingProcessed.push({ resolve, startMs, bytes });
28
+ });
22
29
  }
23
30
  async any(any) {
24
31
  if ('stream' in any) {
@@ -34,7 +41,7 @@ export class WriterInstance {
34
41
  async buffer(buffer) {
35
42
  this.logger.debug(`${this.uri} sends buffer ${buffer.length} bytes`);
36
43
  const localSequenceNumber = this.localSequenceNumber++;
37
- const handledPromise = this.awaitProcessed();
44
+ const handledPromise = this.awaitProcessed(buffer.length);
38
45
  await this.notifyOrchestrator({
39
46
  msg: { data: buffer, channel: this.uri, localSequenceNumber },
40
47
  });
@@ -44,7 +51,7 @@ export class WriterInstance {
44
51
  this.openStreams += 1;
45
52
  const t = transform || ((x) => x);
46
53
  const stream = this.client.sendStreamMessage();
47
- const handledPromise = this.awaitProcessed();
54
+ const handledPromise = this.awaitProcessed(0);
48
55
  const writeStreamMessageChunk = promisify(stream.write.bind(stream));
49
56
  const localSequenceNumber = this.localSequenceNumber++;
50
57
  await writeStreamMessageChunk({
@@ -70,10 +77,11 @@ export class WriterInstance {
70
77
  async string(msg) {
71
78
  this.logger.debug(`${this.uri} sends string ${msg.length} characters`);
72
79
  const localSequenceNumber = this.localSequenceNumber++;
73
- const handledPromise = this.awaitProcessed();
80
+ const encoded = encoder.encode(msg);
81
+ const handledPromise = this.awaitProcessed(encoded.length);
74
82
  await this.notifyOrchestrator({
75
83
  msg: {
76
- data: encoder.encode(msg),
84
+ data: encoded,
77
85
  channel: this.uri,
78
86
  localSequenceNumber,
79
87
  },
@@ -81,12 +89,17 @@ export class WriterInstance {
81
89
  await handledPromise;
82
90
  }
83
91
  async close(issued = false) {
92
+ if (issued)
93
+ this.remoteCloseReceived = true;
84
94
  if (this.openStreams !== 0) {
85
95
  await new Promise((resolve) => this.shouldClose.push(resolve));
86
96
  return;
87
97
  }
98
+ if (this.hasClosed)
99
+ return;
100
+ this.hasClosed = true;
88
101
  this.logger.debug(`${this.uri} closes stream`);
89
- if (!issued) {
102
+ if (!this.remoteCloseReceived) {
90
103
  await this.notifyOrchestrator({
91
104
  close: { channel: this.uri },
92
105
  });
@@ -99,7 +112,10 @@ export class WriterInstance {
99
112
  }
100
113
  handled() {
101
114
  if (this.awaitingProcessed.length > 0) {
102
- this.awaitingProcessed.shift()();
115
+ const { resolve, startMs, bytes } = this.awaitingProcessed.shift();
116
+ const latencyMs = Date.now() - startMs;
117
+ this.tracker?.recordMessage(bytes, latencyMs);
118
+ resolve();
103
119
  }
104
120
  else {
105
121
  this.logger.error('Expected to be waiting for a message to be processed, but this is not the case ' +
@@ -107,4 +123,4 @@ export class WriterInstance {
107
123
  }
108
124
  }
109
125
  }
110
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid3JpdGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3dyaXRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sTUFBTSxDQUFBO0FBbUJoQyxNQUFNLE9BQU8sR0FBRyxJQUFJLFdBQVcsRUFBRSxDQUFBO0FBQ2pDLE1BQU0sT0FBTyxjQUFjO0lBQ2hCLEdBQUcsQ0FBUTtJQUNwQixtQkFBbUIsR0FBVyxDQUFDLENBQUE7SUFDZCxNQUFNLENBQWM7SUFDcEIsa0JBQWtCLENBQVU7SUFDNUIsTUFBTSxDQUFRO0lBRXZCLGlCQUFpQixHQUFzQixFQUFFLENBQUE7SUFFekMsV0FBVyxHQUFXLENBQUMsQ0FBQTtJQUN2QixXQUFXLEdBQXNCLEVBQUUsQ0FBQTtJQUUxQixRQUFRLENBQVE7SUFFakMsWUFDRSxHQUFXLEVBQ1gsTUFBb0IsRUFDcEIsa0JBQTRCLEVBQzVCLFFBQWdCLEVBQ2hCLE1BQWM7UUFFZCxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQTtRQUNwQixJQUFJLENBQUMsa0JBQWtCLEdBQUcsa0JBQWtCLENBQUE7UUFDNUMsSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUE7UUFDZCxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQTtRQUNwQixJQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQTtJQUMxQixDQUFDO0lBRU8sY0FBYztRQUNwQixPQUFPLElBQUksT0FBTyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUE7SUFDL0QsQ0FBQztJQUVELEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBUTtRQUNoQixJQUFJLFFBQVEsSUFBSSxHQUFHLEVBQUUsQ0FBQztZQUNwQixNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFBO1FB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R0FBRyxFQUFFLENBQUE7UUFDcEMsT0FBTyxPQUFPLEVBQUUsQ0FBQztZQUNmLE9BQU8sRUFBRSxDQUFBO1lBQ1QsT0FBTyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxFQUFFLENBQUE7UUFDbEMsQ0FBQztJQUNILENBQUM7SUFLRCxPQUFPO1FBQ0wsSUFBSSxJQUFJLENBQUMsaUJBQWlCLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3RDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLEVBQUcsRUFBRSxDQUFBO1FBQ25DLENBQUM7YUFBTSxDQUFDO1lBQ04sSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQ2YsaUZBQWlGO2dCQUMvRSxJQUFJLENBQUMsR0FBRyxDQUNYLENBQUE7UUFDSCxDQUFDO0lBQ0gsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRnJvbVJ1bm5lciwgUnVubmVyQ2xpZW50IH0gZnJvbSAnQHJkZmMvcHJvdG8nXG5pbXBvcnQgeyBwcm9taXNpZnkgfSBmcm9tICd1dGlsJ1xuaW1wb3J0IHsgTG9nZ2VyIH0gZnJvbSAnd2luc3RvbidcbmltcG9ydCB7IEFueSB9IGZyb20gJy4vcmVhZGVyJ1xuXG50eXBlIFdyaXRhYmxlID0gKG1zZzogRnJvbVJ1bm5lcikgPT4gUHJvbWlzZTx1bmtub3duPlxuZXhwb3J0IGludGVyZmFjZSBXcml0ZXIge1xuICByZWFkb25seSB1cmk6IHN0cmluZ1xuICBidWZmZXIoYnVmZmVyOiBVaW50OEFycmF5KTogUHJvbWlzZTx2b2lkPlxuXG4gIHN0cmVhbShidWZmZXI6IEFzeW5jSXRlcmFibGU8VWludDhBcnJheT4pOiBQcm9taXNlPHZvaWQ+XG4gIHN0cmVhbTxUPihcbiAgICBidWZmZXI6IEFzeW5jSXRlcmFibGU8VD4sXG4gICAgdHJhbnNmb3JtOiAoeDogVCkgPT4gVWludDhBcnJheSxcbiAgKTogUHJvbWlzZTx2b2lkPlxuXG4gIHN0cmluZyhidWZmZXI6IHN0cmluZyk6IFByb21pc2U8dm9pZD5cbiAgYW55KGFueTogQW55KTogUHJvbWlzZTx2b2lkPlxuICBjbG9zZSgpOiBQcm9taXNlPHZvaWQ+XG59XG5jb25zdCBlbmNvZGVyID0gbmV3IFRleHRFbmNvZGVyKClcbmV4cG9ydCBjbGFzcyBXcml0ZXJJbnN0YW5jZSBpbXBsZW1lbnRzIFdyaXRlciB7XG4gIHJlYWRvbmx5IHVyaTogc3RyaW5nXG4gIGxvY2FsU2VxdWVuY2VOdW1iZXI6IG51bWJlciA9IDFcbiAgcHJpdmF0ZSByZWFkb25seSBjbGllbnQ6IFJ1bm5lckNsaWVudFxuICBwcml2YXRlIHJlYWRvbmx5IG5vdGlmeU9yY2hlc3RyYXRvcjogV3JpdGFibGVcbiAgcHJpdmF0ZSByZWFkb25seSBsb2dnZXI6IExvZ2dlclxuXG4gIHByaXZhdGUgYXdhaXRpbmdQcm9jZXNzZWQ6IEFycmF5PCgpID0+IHZvaWQ+ID0gW11cblxuICBwcml2YXRlIG9wZW5TdHJlYW1zOiBudW1iZXIgPSAwXG4gIHByaXZhdGUgc2hvdWxkQ2xvc2U6IEFycmF5PCgpID0+IHZvaWQ+ID0gW11cblxuICBwcml2YXRlIHJlYWRvbmx5IHJ1bm5lcklkOiBzdHJpbmdcblxuICBjb25zdHJ1Y3RvcihcbiAgICB1cmk6IHN0cmluZyxcbiAgICBjbGllbnQ6IFJ1bm5lckNsaWVudCxcbiAgICBub3RpZnlPcmNoZXN0cmF0b3I6IFdyaXRhYmxlLFxuICAgIHJ1bm5lcklkOiBzdHJpbmcsXG4gICAgbG9nZ2VyOiBMb2dnZXIsXG4gICkge1xuICAgIHRoaXMuY2xpZW50ID0gY2xpZW50XG4gICAgdGhpcy5ub3RpZnlPcmNoZXN0cmF0b3IgPSBub3RpZnlPcmNoZXN0cmF0b3JcbiAgICB0aGlzLnVyaSA9IHVyaVxuICAgIHRoaXMubG9nZ2VyID0gbG9nZ2VyXG4gICAgdGhpcy5ydW5uZXJJZCA9IHJ1bm5lcklkXG4gIH1cblxuICBwcml2YXRlIGF3YWl0UHJvY2Vzc2VkKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzKSA9PiB0aGlzLmF3YWl0aW5nUHJvY2Vzc2VkLnB1c2gocmVzKSlcbiAgfVxuXG4gIGFzeW5jIGFueShhbnk6IEFueSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICgnc3RyZWFtJyBpbiBhbnkpIHtcbiAgICAgIGF3YWl0IHRoaXMuc3RyZWFtKGFueS5zdHJlYW0pXG4gICAgfVxuICAgIGlmICgnYnVmZmVyJyBpbiBhbnkpIHtcbiAgICAgIGF3YWl0IHRoaXMuYnVmZmVyKGFueS5idWZmZXIpXG4gICAgfVxuICAgIGlmICgnc3RyaW5nJyBpbiBhbnkpIHtcbiAgICAgIGF3YWl0IHRoaXMuc3RyaW5nKGFueS5zdHJpbmcpXG4gICAgfVxuICB9XG5cbiAgYXN5bmMgYnVmZmVyKGJ1ZmZlcjogVWludDhBcnJheSk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMubG9nZ2VyLmRlYnVnKGAke3RoaXMudXJpfSBzZW5kcyBidWZmZXIgJHtidWZmZXIubGVuZ3RofSBieXRlc2ApXG4gICAgY29uc3QgbG9jYWxTZXF1ZW5jZU51bWJlciA9IHRoaXMubG9jYWxTZXF1ZW5jZU51bWJlcisrXG4gICAgY29uc3QgaGFuZGxlZFByb21pc2UgPSB0aGlzLmF3YWl0UHJvY2Vzc2VkKClcblxuICAgIGF3YWl0IHRoaXMubm90aWZ5T3JjaGVzdHJhdG9yKHtcbiAgICAgIG1zZzogeyBkYXRhOiBidWZmZXIsIGNoYW5uZWw6IHRoaXMudXJpLCBsb2NhbFNlcXVlbmNlTnVtYmVyIH0sXG4gICAgfSlcbiAgICBhd2FpdCBoYW5kbGVkUHJvbWlzZVxuICB9XG5cbiAgYXN5bmMgc3RyZWFtPFQgPSBVaW50OEFycmF5PihcbiAgICBidWZmZXI6IEFzeW5jSXRlcmFibGU8VD4sXG4gICAgdHJhbnNmb3JtPzogKHg6IFQpID0+IFVpbnQ4QXJyYXksXG4gICkge1xuICAgIHRoaXMub3BlblN0cmVhbXMgKz0gMVxuICAgIGNvbnN0IHQgPSB0cmFuc2Zvcm0gfHwgKCh4OiB1bmtub3duKSA9PiA8VWludDhBcnJheT54KVxuICAgIGNvbnN0IHN0cmVhbSA9IHRoaXMuY2xpZW50LnNlbmRTdHJlYW1NZXNzYWdlKClcblxuICAgIGNvbnN0IGhhbmRsZWRQcm9taXNlID0gdGhpcy5hd2FpdFByb2Nlc3NlZCgpXG4gICAgY29uc3Qgd3JpdGVTdHJlYW1NZXNzYWdlQ2h1bmsgPSBwcm9taXNpZnkoc3RyZWFtLndyaXRlLmJpbmQoc3RyZWFtKSlcbiAgICBjb25zdCBsb2NhbFNlcXVlbmNlTnVtYmVyID0gdGhpcy5sb2NhbFNlcXVlbmNlTnVtYmVyKytcbiAgICBhd2FpdCB3cml0ZVN0cmVhbU1lc3NhZ2VDaHVuayh7XG4gICAgICBpZDoge1xuICAgICAgICBjaGFubmVsOiB0aGlzLnVyaSxcbiAgICAgICAgbG9jYWxTZXF1ZW5jZU51bWJlcixcbiAgICAgICAgcnVubmVyOiB0aGlzLnJ1bm5lcklkLFxuICAgICAgfSxcbiAgICB9KVxuXG4gICAgY29uc3QgaWQgPSBhd2FpdCBuZXcgUHJvbWlzZSgocmVzKSA9PiBzdHJlYW0ub25jZSgnZGF0YScsIHJlcykpXG5cbiAgICB0aGlzLmxvZ2dlci5kZWJ1ZyhcbiAgICAgIGAke3RoaXMudXJpfSBzdHJlYW1zIG1lc3NhZ2Ugd2l0aCBpZCAke0pTT04uc3RyaW5naWZ5KGlkKX1gLFxuICAgIClcblxuICAgIGZvciBhd2FpdCAoY29uc3QgbXNnIG9mIGJ1ZmZlcikge1xuICAgICAgY29uc3QgcHJvY2Vzc2VkUHJvbWlzZSA9IG5ldyBQcm9taXNlKChyZXMpID0+IHN0cmVhbS5vbmNlKCdkYXRhJywgcmVzKSlcbiAgICAgIGF3YWl0IHdyaXRlU3RyZWFtTWVzc2FnZUNodW5rKHsgZGF0YTogeyBkYXRhOiB0KG1zZykgfSB9KVxuICAgICAgLy8gQXdhaXQgYSBtZXNzYWdlIG9uIHRoZSBzdHJlYW0sIGluZGljYXRpbmcgdGhhdCB0aGUgY2h1bmsgaGFzIGJlZW4gcHJvY2Vzc2VkXG4gICAgICBhd2FpdCBwcm9jZXNzZWRQcm9taXNlXG4gICAgfVxuXG4gICAgc3RyZWFtLmVuZCgpXG5cbiAgICBhd2FpdCBoYW5kbGVkUHJvbWlzZVxuXG4gICAgdGhpcy5vcGVuU3RyZWFtcyAtPSAxXG5cbiAgICBpZiAodGhpcy5zaG91bGRDbG9zZS5sZW5ndGggPiAwKSBhd2FpdCB0aGlzLmNsb3NlKClcbiAgfVxuXG4gIGFzeW5jIHN0cmluZyhtc2c6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMubG9nZ2VyLmRlYnVnKGAke3RoaXMudXJpfSBzZW5kcyBzdHJpbmcgJHttc2cubGVuZ3RofSBjaGFyYWN0ZXJzYClcbiAgICBjb25zdCBsb2NhbFNlcXVlbmNlTnVtYmVyID0gdGhpcy5sb2NhbFNlcXVlbmNlTnVtYmVyKytcbiAgICBjb25zdCBoYW5kbGVkUHJvbWlzZSA9IHRoaXMuYXdhaXRQcm9jZXNzZWQoKVxuXG4gICAgYXdhaXQgdGhpcy5ub3RpZnlPcmNoZXN0cmF0b3Ioe1xuICAgICAgbXNnOiB7XG4gICAgICAgIGRhdGE6IGVuY29kZXIuZW5jb2RlKG1zZyksXG4gICAgICAgIGNoYW5uZWw6IHRoaXMudXJpLFxuICAgICAgICBsb2NhbFNlcXVlbmNlTnVtYmVyLFxuICAgICAgfSxcbiAgICB9KVxuXG4gICAgYXdhaXQgaGFuZGxlZFByb21pc2VcbiAgfVxuXG4gIC8qKlxuICAgKiBHcmFjZWZ1bGx5IGNsb3NlcyB0aGlzIGNoYW5uZWwuXG4gICAqXG4gICAqIEJlaGF2aW9yOlxuICAgKiAtIElmIHRoZXJlIGFyZSBzdGlsbCBhY3RpdmUgc3RyZWFtcywgY2xvc2luZyBpcyBkZWZlcnJlZCB1bnRpbCB0aGV5IGNvbXBsZXRlLlxuICAgKiAtIElmIG11bHRpcGxlIGNhbGxlcnMgaW52b2tlIGBjbG9zZSgpYCB3aGlsZSB3YWl0aW5nLCB0aGVpciBQcm9taXNlcyBhcmUgcXVldWVkIGFuZFxuICAgKiAgIHJlc29sdmVkIG9uY2UgdGhlIGNoYW5uZWwgYWN0dWFsbHkgY2xvc2VzLlxuICAgKiAtIElmIHRoaXMgc2lkZSBpbml0aWF0ZWQgdGhlIGNsb3NlIChgaXNzdWVkID0gZmFsc2VgKSwgYSBjbG9zZSBtZXNzYWdlIGlzIHNlbnQgdG8gdGhlIHJlbW90ZS5cbiAgICpcbiAgICogQHBhcmFtIGlzc3VlZCAtIElmIHRydWUsIGluZGljYXRlcyB0aGUgY2xvc2UgcmVxdWVzdCBvcmlnaW5hdGVkIHJlbW90ZWx5XG4gICAqL1xuICBhc3luYyBjbG9zZShpc3N1ZWQgPSBmYWxzZSk6IFByb21pc2U8dm9pZD4ge1xuICAgIC8vIENhc2UgMTogQWN0aXZlIHN0cmVhbXMgc3RpbGwgcnVubmluZyDihpIgd2FpdCB1bnRpbCB0aGV5IGZpbmlzaFxuICAgIGlmICh0aGlzLm9wZW5TdHJlYW1zICE9PSAwKSB7XG4gICAgICBhd2FpdCBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSkgPT4gdGhpcy5zaG91bGRDbG9zZS5wdXNoKHJlc29sdmUpKVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgLy8gQ2FzZSAyOiBObyBhY3RpdmUgc3RyZWFtcyDihpIgcGVyZm9ybSBhY3R1YWwgY2xvc2VcbiAgICB0aGlzLmxvZ2dlci5kZWJ1ZyhgJHt0aGlzLnVyaX0gY2xvc2VzIHN0cmVhbWApXG4gICAgaWYgKCFpc3N1ZWQpIHtcbiAgICAgIGF3YWl0IHRoaXMubm90aWZ5T3JjaGVzdHJhdG9yKHtcbiAgICAgICAgY2xvc2U6IHsgY2hhbm5lbDogdGhpcy51cmkgfSxcbiAgICAgIH0pXG4gICAgfVxuXG4gICAgbGV0IHJlc29sdmUgPSB0aGlzLnNob3VsZENsb3NlLnBvcCgpXG4gICAgd2hpbGUgKHJlc29sdmUpIHtcbiAgICAgIHJlc29sdmUoKVxuICAgICAgcmVzb2x2ZSA9IHRoaXMuc2hvdWxkQ2xvc2UucG9wKClcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQSBtZXNzYWdlIGlzIGhhbmRsZWQsIGxldCdzIG5vdGlmeSB0aGUgZmlmbyB7QGxpbmsgYXdhaXRQcm9jZXNzZWR9XG4gICAqL1xuICBoYW5kbGVkKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmF3YWl0aW5nUHJvY2Vzc2VkLmxlbmd0aCA+IDApIHtcbiAgICAgIHRoaXMuYXdhaXRpbmdQcm9jZXNzZWQuc2hpZnQoKSEoKVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmxvZ2dlci5lcnJvcihcbiAgICAgICAgJ0V4cGVjdGVkIHRvIGJlIHdhaXRpbmcgZm9yIGEgbWVzc2FnZSB0byBiZSBwcm9jZXNzZWQsIGJ1dCB0aGlzIGlzIG5vdCB0aGUgY2FzZSAnICtcbiAgICAgICAgICB0aGlzLnVyaSxcbiAgICAgIClcbiAgICB9XG4gIH1cbn1cbiJdfQ==
126
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid3JpdGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3dyaXRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sTUFBTSxDQUFBO0FBb0JoQyxNQUFNLE9BQU8sR0FBRyxJQUFJLFdBQVcsRUFBRSxDQUFBO0FBQ2pDLE1BQU0sT0FBTyxjQUFjO0lBQ2hCLEdBQUcsQ0FBUTtJQUNwQixtQkFBbUIsR0FBVyxDQUFDLENBQUE7SUFDZCxNQUFNLENBQWM7SUFDcEIsa0JBQWtCLENBQVU7SUFDNUIsTUFBTSxDQUFRO0lBRXZCLGlCQUFpQixHQUlwQixFQUFFLENBQUE7SUFFQyxXQUFXLEdBQVcsQ0FBQyxDQUFBO0lBQ3ZCLFdBQVcsR0FBc0IsRUFBRSxDQUFBO0lBQ25DLFNBQVMsR0FBRyxLQUFLLENBQUE7SUFDakIsbUJBQW1CLEdBQUcsS0FBSyxDQUFBO0lBRWxCLFFBQVEsQ0FBUTtJQUNoQixPQUFPLENBQTRCO0lBRXBELFlBQ0UsR0FBVyxFQUNYLE1BQW9CLEVBQ3BCLGtCQUE0QixFQUM1QixRQUFnQixFQUNoQixNQUFjLEVBQ2QsT0FBd0I7UUFFeEIsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUE7UUFDcEIsSUFBSSxDQUFDLGtCQUFrQixHQUFHLGtCQUFrQixDQUFBO1FBQzVDLElBQUksQ0FBQyxHQUFHLEdBQUcsR0FBRyxDQUFBO1FBQ2QsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUE7UUFDcEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUE7UUFDeEIsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUE7SUFDeEIsQ0FBQztJQUVPLGNBQWMsQ0FBQyxLQUFhO1FBQ2xDLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQTtRQUMxQixPQUFPLElBQUksT0FBTyxDQUFPLENBQUMsT0FBTyxFQUFFLEVBQUU7WUFDbkMsSUFBSSxDQUFDLGlC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QU0sQ0FBQyxLQUFLLENBQ2YsaUZBQWlGO2dCQUMvRSxJQUFJLENBQUMsR0FBRyxDQUNYLENBQUE7UUFDSCxDQUFDO0lBQ0gsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRnJvbVJ1bm5lciwgUnVubmVyQ2xpZW50IH0gZnJvbSAnQHJkZmMvcHJvdG8nXG5pbXBvcnQgeyBwcm9taXNpZnkgfSBmcm9tICd1dGlsJ1xuaW1wb3J0IHsgTG9nZ2VyIH0gZnJvbSAnd2luc3RvbidcbmltcG9ydCB7IEFueSB9IGZyb20gJy4vcmVhZGVyJ1xuaW1wb3J0IHsgQ2hhbm5lbFRyYWNrZXIgfSBmcm9tICcuL3N0YXRlJ1xuXG50eXBlIFdyaXRhYmxlID0gKG1zZzogRnJvbVJ1bm5lcikgPT4gUHJvbWlzZTx1bmtub3duPlxuZXhwb3J0IGludGVyZmFjZSBXcml0ZXIge1xuICByZWFkb25seSB1cmk6IHN0cmluZ1xuICBidWZmZXIoYnVmZmVyOiBVaW50OEFycmF5KTogUHJvbWlzZTx2b2lkPlxuXG4gIHN0cmVhbShidWZmZXI6IEFzeW5jSXRlcmFibGU8VWludDhBcnJheT4pOiBQcm9taXNlPHZvaWQ+XG4gIHN0cmVhbTxUPihcbiAgICBidWZmZXI6IEFzeW5jSXRlcmFibGU8VD4sXG4gICAgdHJhbnNmb3JtOiAoeDogVCkgPT4gVWludDhBcnJheSxcbiAgKTogUHJvbWlzZTx2b2lkPlxuXG4gIHN0cmluZyhidWZmZXI6IHN0cmluZyk6IFByb21pc2U8dm9pZD5cbiAgYW55KGFueTogQW55KTogUHJvbWlzZTx2b2lkPlxuICBjbG9zZSgpOiBQcm9taXNlPHZvaWQ+XG59XG5jb25zdCBlbmNvZGVyID0gbmV3IFRleHRFbmNvZGVyKClcbmV4cG9ydCBjbGFzcyBXcml0ZXJJbnN0YW5jZSBpbXBsZW1lbnRzIFdyaXRlciB7XG4gIHJlYWRvbmx5IHVyaTogc3RyaW5nXG4gIGxvY2FsU2VxdWVuY2VOdW1iZXI6IG51bWJlciA9IDFcbiAgcHJpdmF0ZSByZWFkb25seSBjbGllbnQ6IFJ1bm5lckNsaWVudFxuICBwcml2YXRlIHJlYWRvbmx5IG5vdGlmeU9yY2hlc3RyYXRvcjogV3JpdGFibGVcbiAgcHJpdmF0ZSByZWFkb25seSBsb2dnZXI6IExvZ2dlclxuXG4gIHByaXZhdGUgYXdhaXRpbmdQcm9jZXNzZWQ6IEFycmF5PHtcbiAgICByZXNvbHZlOiAoKSA9PiB2b2lkXG4gICAgc3RhcnRNczogbnVtYmVyXG4gICAgYnl0ZXM6IG51bWJlclxuICB9PiA9IFtdXG5cbiAgcHJpdmF0ZSBvcGVuU3RyZWFtczogbnVtYmVyID0gMFxuICBwcml2YXRlIHNob3VsZENsb3NlOiBBcnJheTwoKSA9PiB2b2lkPiA9IFtdXG4gIHByaXZhdGUgaGFzQ2xvc2VkID0gZmFsc2VcbiAgcHJpdmF0ZSByZW1vdGVDbG9zZVJlY2VpdmVkID0gZmFsc2VcblxuICBwcml2YXRlIHJlYWRvbmx5IHJ1bm5lcklkOiBzdHJpbmdcbiAgcHJpdmF0ZSByZWFkb25seSB0cmFja2VyOiBDaGFubmVsVHJhY2tlciB8IHVuZGVmaW5lZFxuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHVyaTogc3RyaW5nLFxuICAgIGNsaWVudDogUnVubmVyQ2xpZW50LFxuICAgIG5vdGlmeU9yY2hlc3RyYXRvcjogV3JpdGFibGUsXG4gICAgcnVubmVySWQ6IHN0cmluZyxcbiAgICBsb2dnZXI6IExvZ2dlcixcbiAgICB0cmFja2VyPzogQ2hhbm5lbFRyYWNrZXIsXG4gICkge1xuICAgIHRoaXMuY2xpZW50ID0gY2xpZW50XG4gICAgdGhpcy5ub3RpZnlPcmNoZXN0cmF0b3IgPSBub3RpZnlPcmNoZXN0cmF0b3JcbiAgICB0aGlzLnVyaSA9IHVyaVxuICAgIHRoaXMubG9nZ2VyID0gbG9nZ2VyXG4gICAgdGhpcy5ydW5uZXJJZCA9IHJ1bm5lcklkXG4gICAgdGhpcy50cmFja2VyID0gdHJhY2tlclxuICB9XG5cbiAgcHJpdmF0ZSBhd2FpdFByb2Nlc3NlZChieXRlczogbnVtYmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3Qgc3RhcnRNcyA9IERhdGUubm93KClcbiAgICByZXR1cm4gbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUpID0+IHtcbiAgICAgIHRoaXMuYXdhaXRpbmdQcm9jZXNzZWQucHVzaCh7IHJlc29sdmUsIHN0YXJ0TXMsIGJ5dGVzIH0pXG4gICAgfSlcbiAgfVxuXG4gIGFzeW5jIGFueShhbnk6IEFueSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICgnc3RyZWFtJyBpbiBhbnkpIHtcbiAgICAgIGF3YWl0IHRoaXMuc3RyZWFtKGFueS5zdHJlYW0pXG4gICAgfVxuICAgIGlmICgnYnVmZmVyJyBpbiBhbnkpIHtcbiAgICAgIGF3YWl0IHRoaXMuYnVmZmVyKGFueS5idWZmZXIpXG4gICAgfVxuICAgIGlmICgnc3RyaW5nJyBpbiBhbnkpIHtcbiAgICAgIGF3YWl0IHRoaXMuc3RyaW5nKGFueS5zdHJpbmcpXG4gICAgfVxuICB9XG5cbiAgYXN5bmMgYnVmZmVyKGJ1ZmZlcjogVWludDhBcnJheSk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMubG9nZ2VyLmRlYnVnKGAke3RoaXMudXJpfSBzZW5kcyBidWZmZXIgJHtidWZmZXIubGVuZ3RofSBieXRlc2ApXG4gICAgY29uc3QgbG9jYWxTZXF1ZW5jZU51bWJlciA9IHRoaXMubG9jYWxTZXF1ZW5jZU51bWJlcisrXG4gICAgY29uc3QgaGFuZGxlZFByb21pc2UgPSB0aGlzLmF3YWl0UHJvY2Vzc2VkKGJ1ZmZlci5sZW5ndGgpXG5cbiAgICBhd2FpdCB0aGlzLm5vdGlmeU9yY2hlc3RyYXRvcih7XG4gICAgICBtc2c6IHsgZGF0YTogYnVmZmVyLCBjaGFubmVsOiB0aGlzLnVyaSwgbG9jYWxTZXF1ZW5jZU51bWJlciB9LFxuICAgIH0pXG4gICAgYXdhaXQgaGFuZGxlZFByb21pc2VcbiAgfVxuXG4gIGFzeW5jIHN0cmVhbTxUID0gVWludDhBcnJheT4oXG4gICAgYnVmZmVyOiBBc3luY0l0ZXJhYmxlPFQ+LFxuICAgIHRyYW5zZm9ybT86ICh4OiBUKSA9PiBVaW50OEFycmF5LFxuICApIHtcbiAgICB0aGlzLm9wZW5TdHJlYW1zICs9IDFcbiAgICBjb25zdCB0ID0gdHJhbnNmb3JtIHx8ICgoeDogdW5rbm93bikgPT4gPFVpbnQ4QXJyYXk+eClcbiAgICBjb25zdCBzdHJlYW0gPSB0aGlzLmNsaWVudC5zZW5kU3RyZWFtTWVzc2FnZSgpXG5cbiAgICBjb25zdCBoYW5kbGVkUHJvbWlzZSA9IHRoaXMuYXdhaXRQcm9jZXNzZWQoMCkgLy8gYnl0ZXMgdW5rbm93biBmb3Igc3RyZWFtc1xuICAgIGNvbnN0IHdyaXRlU3RyZWFtTWVzc2FnZUNodW5rID0gcHJvbWlzaWZ5KHN0cmVhbS53cml0ZS5iaW5kKHN0cmVhbSkpXG4gICAgY29uc3QgbG9jYWxTZXF1ZW5jZU51bWJlciA9IHRoaXMubG9jYWxTZXF1ZW5jZU51bWJlcisrXG4gICAgYXdhaXQgd3JpdGVTdHJlYW1NZXNzYWdlQ2h1bmsoe1xuICAgICAgaWQ6IHtcbiAgICAgICAgY2hhbm5lbDogdGhpcy51cmksXG4gICAgICAgIGxvY2FsU2VxdWVuY2VOdW1iZXIsXG4gICAgICAgIHJ1bm5lcjogdGhpcy5ydW5uZXJJZCxcbiAgICAgIH0sXG4gICAgfSlcblxuICAgIGNvbnN0IGlkID0gYXdhaXQgbmV3IFByb21pc2UoKHJlcykgPT4gc3RyZWFtLm9uY2UoJ2RhdGEnLCByZXMpKVxuXG4gICAgdGhpcy5sb2dnZXIuZGVidWcoXG4gICAgICBgJHt0aGlzLnVyaX0gc3RyZWFtcyBtZXNzYWdlIHdpdGggaWQgJHtKU09OLnN0cmluZ2lmeShpZCl9YCxcbiAgICApXG5cbiAgICBmb3IgYXdhaXQgKGNvbnN0IG1zZyBvZiBidWZmZXIpIHtcbiAgICAgIGNvbnN0IHByb2Nlc3NlZFByb21pc2UgPSBuZXcgUHJvbWlzZSgocmVzKSA9PiBzdHJlYW0ub25jZSgnZGF0YScsIHJlcykpXG4gICAgICBhd2FpdCB3cml0ZVN0cmVhbU1lc3NhZ2VDaHVuayh7IGRhdGE6IHsgZGF0YTogdChtc2cpIH0gfSlcbiAgICAgIC8vIEF3YWl0IGEgbWVzc2FnZSBvbiB0aGUgc3RyZWFtLCBpbmRpY2F0aW5nIHRoYXQgdGhlIGNodW5rIGhhcyBiZWVuIHByb2Nlc3NlZFxuICAgICAgYXdhaXQgcHJvY2Vzc2VkUHJvbWlzZVxuICAgIH1cblxuICAgIHN0cmVhbS5lbmQoKVxuXG4gICAgYXdhaXQgaGFuZGxlZFByb21pc2VcblxuICAgIHRoaXMub3BlblN0cmVhbXMgLT0gMVxuXG4gICAgaWYgKHRoaXMuc2hvdWxkQ2xvc2UubGVuZ3RoID4gMCkgYXdhaXQgdGhpcy5jbG9zZSgpXG4gIH1cblxuICBhc3luYyBzdHJpbmcobXNnOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0aGlzLmxvZ2dlci5kZWJ1ZyhgJHt0aGlzLnVyaX0gc2VuZHMgc3RyaW5nICR7bXNnLmxlbmd0aH0gY2hhcmFjdGVyc2ApXG4gICAgY29uc3QgbG9jYWxTZXF1ZW5jZU51bWJlciA9IHRoaXMubG9jYWxTZXF1ZW5jZU51bWJlcisrXG4gICAgY29uc3QgZW5jb2RlZCA9IGVuY29kZXIuZW5jb2RlKG1zZylcbiAgICBjb25zdCBoYW5kbGVkUHJvbWlzZSA9IHRoaXMuYXdhaXRQcm9jZXNzZWQoZW5jb2RlZC5sZW5ndGgpXG5cbiAgICBhd2FpdCB0aGlzLm5vdGlmeU9yY2hlc3RyYXRvcih7XG4gICAgICBtc2c6IHtcbiAgICAgICAgZGF0YTogZW5jb2RlZCxcbiAgICAgICAgY2hhbm5lbDogdGhpcy51cmksXG4gICAgICAgIGxvY2FsU2VxdWVuY2VOdW1iZXIsXG4gICAgICB9LFxuICAgIH0pXG5cbiAgICBhd2FpdCBoYW5kbGVkUHJvbWlzZVxuICB9XG5cbiAgLyoqXG4gICAqIEdyYWNlZnVsbHkgY2xvc2VzIHRoaXMgY2hhbm5lbC5cbiAgICpcbiAgICogQmVoYXZpb3I6XG4gICAqIC0gSWYgdGhlcmUgYXJlIHN0aWxsIGFjdGl2ZSBzdHJlYW1zLCBjbG9zaW5nIGlzIGRlZmVycmVkIHVudGlsIHRoZXkgY29tcGxldGUuXG4gICAqIC0gSWYgbXVsdGlwbGUgY2FsbGVycyBpbnZva2UgYGNsb3NlKClgIHdoaWxlIHdhaXRpbmcsIHRoZWlyIFByb21pc2VzIGFyZSBxdWV1ZWQgYW5kXG4gICAqICAgcmVzb2x2ZWQgb25jZSB0aGUgY2hhbm5lbCBhY3R1YWxseSBjbG9zZXMuXG4gICAqIC0gQSBjbG9zZSBtZXNzYWdlIGlzIHNlbnQgdG8gdGhlIHJlbW90ZSBvbmx5IGlmIHRoZSBjbG9zZSB3YXMgbG9jYWxseSBpbml0aWF0ZWQgYW5kXG4gICAqICAgdGhlIHJlbW90ZSBoYXMgbm90IGFscmVhZHkgc2VudCBhIGNsb3NlLlxuICAgKlxuICAgKiBAcGFyYW0gaXNzdWVkIC0gSWYgdHJ1ZSwgaW5kaWNhdGVzIHRoZSBjbG9zZSByZXF1ZXN0IG9yaWdpbmF0ZWQgcmVtb3RlbHlcbiAgICovXG4gIGFzeW5jIGNsb3NlKGlzc3VlZCA9IGZhbHNlKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKGlzc3VlZCkgdGhpcy5yZW1vdGVDbG9zZVJlY2VpdmVkID0gdHJ1ZVxuXG4gICAgLy8gQ2FzZSAxOiBBY3RpdmUgc3RyZWFtcyBzdGlsbCBydW5uaW5nIOKGkiBkZWZlciB1bnRpbCB0aGV5IGZpbmlzaFxuICAgIGlmICh0aGlzLm9wZW5TdHJlYW1zICE9PSAwKSB7XG4gICAgICBhd2FpdCBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSkgPT4gdGhpcy5zaG91bGRDbG9zZS5wdXNoKHJlc29sdmUpKVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgLy8gQ2FzZSAyOiBBbHJlYWR5IGNsb3NlZCDigJQgbm90aGluZyB0byBkb1xuICAgIGlmICh0aGlzLmhhc0Nsb3NlZCkgcmV0dXJuXG4gICAgdGhpcy5oYXNDbG9zZWQgPSB0cnVlXG5cbiAgICAvLyBDYXNlIDM6IE5vIGFjdGl2ZSBzdHJlYW1zIOKGkiBwZXJmb3JtIGFjdHVhbCBjbG9zZVxuICAgIHRoaXMubG9nZ2VyLmRlYnVnKGAke3RoaXMudXJpfSBjbG9zZXMgc3RyZWFtYClcbiAgICBpZiAoIXRoaXMucmVtb3RlQ2xvc2VSZWNlaXZlZCkge1xuICAgICAgYXdhaXQgdGhpcy5ub3RpZnlPcmNoZXN0cmF0b3Ioe1xuICAgICAgICBjbG9zZTogeyBjaGFubmVsOiB0aGlzLnVyaSB9LFxuICAgICAgfSlcbiAgICB9XG5cbiAgICBsZXQgcmVzb2x2ZSA9IHRoaXMuc2hvdWxkQ2xvc2UucG9wKClcbiAgICB3aGlsZSAocmVzb2x2ZSkge1xuICAgICAgcmVzb2x2ZSgpXG4gICAgICByZXNvbHZlID0gdGhpcy5zaG91bGRDbG9zZS5wb3AoKVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBIG1lc3NhZ2UgaXMgaGFuZGxlZCwgbGV0J3Mgbm90aWZ5IHRoZSBmaWZvIHtAbGluayBhd2FpdFByb2Nlc3NlZH1cbiAgICovXG4gIGhhbmRsZWQoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuYXdhaXRpbmdQcm9jZXNzZWQubGVuZ3RoID4gMCkge1xuICAgICAgY29uc3QgeyByZXNvbHZlLCBzdGFydE1zLCBieXRlcyB9ID0gdGhpcy5hd2FpdGluZ1Byb2Nlc3NlZC5zaGlmdCgpIVxuICAgICAgY29uc3QgbGF0ZW5jeU1zID0gRGF0ZS5ub3coKSAtIHN0YXJ0TXNcbiAgICAgIHRoaXMudHJhY2tlcj8ucmVjb3JkTWVzc2FnZShieXRlcywgbGF0ZW5jeU1zKVxuICAgICAgcmVzb2x2ZSgpXG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubG9nZ2VyLmVycm9yKFxuICAgICAgICAnRXhwZWN0ZWQgdG8gYmUgd2FpdGluZyBmb3IgYSBtZXNzYWdlIHRvIGJlIHByb2Nlc3NlZCwgYnV0IHRoaXMgaXMgbm90IHRoZSBjYXNlICcgK1xuICAgICAgICAgIHRoaXMudXJpLFxuICAgICAgKVxuICAgIH1cbiAgfVxufVxuIl19
package/minimal.ttl ADDED
@@ -0,0 +1,99 @@
1
+ @prefix prov: <http://www.w3.org/ns/prov#>.
2
+ @prefix sds: <https://w3id.org/sds#>.
3
+ @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
4
+ @prefix owl: <http://www.w3.org/2002/07/owl#>.
5
+ @prefix xsd: <http://www.w3.org/2001/XMLSchema#>.
6
+ @prefix sh: <http://www.w3.org/ns/shacl#>.
7
+ @prefix rdfc: <https://w3id.org/rdf-connect#>.
8
+
9
+ ############################################################
10
+ # General statements #
11
+ ############################################################
12
+ # sds:Activity is a prov:Activity
13
+ sds:Activity rdfs:subClassOf prov:Activity.
14
+
15
+ # rdfc:Processor too
16
+ rdfc:Processor rdfs:subClassOf sds:Activity.
17
+
18
+ # sds:implementationOf is subClassOf
19
+ sds:implementationOf rdfs:subPropertyOf rdfs:subClassOf.
20
+
21
+ ############################################################
22
+ # Javascript statements #
23
+ ############################################################
24
+ # specialized for js too
25
+ rdfc:jsImplementationOf rdfs:subPropertyOf sds:implementationOf.
26
+
27
+ # A node runner, runs things that are rdfc:jsImplementationOf rdfc:Processor (aka, rdfs:subClassOf prov:Activity)
28
+ rdfc:NodeRunner a rdfc:Runner;
29
+ rdfc:handlesSubjectsOf rdfc:jsImplementationOf;
30
+ rdfc:command "npx js-runner".
31
+
32
+ # This shouldn't be necessary, should work with sh:targetSubjectsOf
33
+ # rdfc:processor_definition <JsProcessorShape>.
34
+ #
35
+ # Shape that a Js Processor should fulfil;
36
+ [ ] a sh:NodeShape;
37
+ # This shouldn't be necessary,should work with sh:targetSubjectsOf and this isn't a real Class
38
+ sh:targetClass <JsProcessorShape>;
39
+ # We target it with jsImplementationOf
40
+ sh:targetSubjectsOf rdfc:jsImplementationOf;
41
+ sh:property [
42
+ sh:path rdfc:entrypoint;
43
+ sh:name "location";
44
+ sh:minCount 1;
45
+ sh:maxCount 1;
46
+ sh:datatype xsd:iri;
47
+ ], [
48
+ sh:path rdfc:file;
49
+ sh:name "file";
50
+ sh:minCount 1;
51
+ sh:maxCount 1;
52
+ sh:datatype xsd:iri;
53
+ ], [
54
+ sh:path rdfc:class;
55
+ sh:name "clazz";
56
+ sh:maxCount 1;
57
+ sh:datatype xsd:string;
58
+ ].
59
+
60
+ ############################################################
61
+ # Processor statements #
62
+ ############################################################
63
+ rdfc:FooBarProcessor a owl:Class;
64
+ rdfs:label "My Epic FooBar Processor";
65
+ rdfs:description "FooBars everything!";
66
+ rdfc:jsImplementationOf rdfc:Processor;
67
+ rdfc:entrypoint <./>;
68
+ rdfc:file <./lib/processors.js>;
69
+ rdfc:class "FooBarProcessor".
70
+
71
+ [ ] a sh:NodeShape;
72
+ sh:targetClass rdfc:FooBarProcessor;
73
+ sh:property [
74
+ sh:path rdfc:reader;
75
+ sh:name "reader";
76
+ sh:minCount 1;
77
+ sh:maxCount 1;
78
+ sh:class rdfc:Reader;
79
+ ], [
80
+ sh:path rdfc:writer;
81
+ sh:name "writer";
82
+ sh:maxCount 1;
83
+ sh:class rdfc:Writer;
84
+ ].
85
+
86
+ ############################################################
87
+ # Pipeline statements #
88
+ ############################################################
89
+ <> a rdfc:Pipeline;
90
+ rdfc:consistsOf [
91
+ rdfc:instantiates rdfc:NodeRunner;
92
+ rdfc:processor <foobar>;
93
+ ].
94
+
95
+ <incomingMessages> a rdfc:Reader, rdfc:Writer.
96
+ <foobar> a rdfc:FooBarProcessor;
97
+ rdfc:reader <incomingMessages>;
98
+ rdfc:writer <incomingMessages>.
99
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rdfc/js-runner",
3
- "version": "3.0.3",
3
+ "version": "3.0.4-remote",
4
4
  "main": "lib/index.js",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -11,7 +11,8 @@
11
11
  "prepare": "husky"
12
12
  },
13
13
  "bin": {
14
- "js-runner": "./bin/runner.js"
14
+ "js-runner": "./bin/runner.js",
15
+ "js-runner-server": "./bin/server.js"
15
16
  },
16
17
  "husky": {
17
18
  "hooks": {
@@ -37,21 +38,21 @@
37
38
  "@rdfjs/types": "^2.0.1",
38
39
  "@types/jsonld": "^1.5.15",
39
40
  "@types/n3": "^1.26.1",
40
- "@types/node": "^25.3.3",
41
- "@typescript-eslint/eslint-plugin": "^8.56.1",
42
- "@typescript-eslint/parser": "^8.56.1",
43
- "@vitest/coverage-v8": "^4.0.18",
41
+ "@types/node": "^25.5.0",
42
+ "@typescript-eslint/eslint-plugin": "^8.57.1",
43
+ "@typescript-eslint/parser": "^8.57.1",
44
+ "@vitest/coverage-v8": "^4.1.0",
44
45
  "eslint": "^10.0.2",
45
46
  "eslint-config-prettier": "^10.1.8",
46
47
  "eslint-plugin-prettier": "^5.5.5",
47
- "globals": "^17.3.0",
48
+ "globals": "^17.4.0",
48
49
  "husky": "^9.1.7",
49
- "lint-staged": "^16.3.0",
50
+ "lint-staged": "^16.4.0",
50
51
  "prettier": "^3.8.1",
51
52
  "tsc-alias": "^1.8.16",
52
53
  "typescript": "^5.9.3",
53
- "typescript-eslint": "^8.56.1",
54
- "vitest": "^4.0.18"
54
+ "typescript-eslint": "^8.57.1",
55
+ "vitest": "^4.1.0"
55
56
  },
56
57
  "dependencies": {
57
58
  "@grpc/grpc-js": "^1.14.3",
@@ -59,7 +60,7 @@
59
60
  "@treecg/types": "^0.4.6",
60
61
  "jsonld": "^9.0.0",
61
62
  "jsonld-streaming-parser": "^5.0.1",
62
- "n3": "^2.0.1",
63
+ "n3": "^2.0.3",
63
64
  "rdf-lens": "^1.3.6",
64
65
  "winston": "^3.19.0",
65
66
  "winston-transport": "^4.9.0"
package/src/client.ts CHANGED
@@ -4,46 +4,121 @@ import { RunnerClient, ToRunner } from '@rdfc/proto'
4
4
  import { createLogger } from 'winston'
5
5
  import { RpcTransport } from './logger'
6
6
  import { Runner } from './runner'
7
+ import { State } from './state'
7
8
 
8
- export async function start(addr: string, uri: string) {
9
+ const GRPC_STATE_NAMES = [
10
+ 'IDLE',
11
+ 'CONNECTING',
12
+ 'READY',
13
+ 'TRANSIENT_FAILURE',
14
+ 'SHUTDOWN',
15
+ ] as const
16
+
17
+ function watchGrpcState(
18
+ client: RunnerClient,
19
+ state: State,
20
+ runnerId: string,
21
+ signal: AbortSignal,
22
+ ): void {
23
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
24
+ const ch = (client as any).getChannel() as grpc.Channel
25
+
26
+ const update = () => {
27
+ if (signal.aborted) return
28
+ const s = ch.getConnectivityState(false)
29
+ state.setGrpcState(runnerId, GRPC_STATE_NAMES[s] ?? String(s))
30
+ if (s === grpc.connectivityState.SHUTDOWN) return
31
+ // Watch for the next state change (1-hour deadline)
32
+ ch.watchConnectivityState(s, new Date(Date.now() + 3_600_000), update)
33
+ }
34
+
35
+ update()
36
+ }
37
+
38
+ export async function start(
39
+ addr: string,
40
+ uri: string,
41
+ configPath?: string,
42
+ signal?: AbortSignal,
43
+ state?: State,
44
+ runnerId?: string,
45
+ ) {
9
46
  const client = new RunnerClient(addr, grpc.credentials.createInsecure())
10
47
 
48
+ const logStream = client.logStream(() => {})
49
+
11
50
  const logger = createLogger({
12
51
  transports: [
13
52
  new RpcTransport({
14
53
  entities: [uri, 'cli'],
15
- stream: client.logStream(() => {}),
54
+ stream: logStream,
16
55
  }),
17
56
  ],
18
57
  })
19
58
 
20
59
  const stream = client.connect()
21
60
 
22
- logger.info('Connected with server ' + addr)
23
- const writable = promisify(stream.write.bind(stream))
24
- const runner = new Runner(client, writable, uri, logger)
61
+ const closeConnection = () => {
62
+ stream.end()
63
+ logStream.end()
64
+ client.close()
65
+ }
25
66
 
26
- await writable({ identify: { uri } })
67
+ const abortCtrl = signal ?? new AbortController().signal
68
+ abortCtrl.addEventListener('abort', closeConnection, { once: true })
27
69
 
28
- /* eslint-disable no-async-promise-executor */
29
- await new Promise(async (res) => {
30
- for await (const chunk of stream) {
31
- const msg: ToRunner = chunk
32
- if (msg.proc) {
33
- await runner.addProcessor(msg.proc)
34
- }
35
- if (msg.start) {
36
- runner.start().then(res)
37
- }
70
+ if (state && runnerId) {
71
+ watchGrpcState(client, state, runnerId, abortCtrl)
72
+ }
38
73
 
39
- await runner.handleOrchMessage(msg)
40
- }
74
+ try {
75
+ logger.info('Connected with server ' + addr)
76
+ const writable = promisify(stream.write.bind(stream))
77
+ const runner = new Runner(
78
+ client,
79
+ writable,
80
+ uri,
81
+ logger,
82
+ configPath,
83
+ state,
84
+ runnerId,
85
+ )
41
86
 
42
- logger.error('Stream ended')
43
- })
87
+ await writable({ identify: { uri } })
88
+
89
+ let runnerDone = false
90
+ /* eslint-disable no-async-promise-executor */
91
+ await new Promise(async (res, rej) => {
92
+ try {
93
+ for await (const chunk of stream) {
94
+ const msg: ToRunner = chunk
95
+ if (msg.proc) {
96
+ await runner.addProcessor(msg.proc)
97
+ }
98
+ if (msg.start) {
99
+ if (state && runnerId) state.setStatus(runnerId, 'running')
100
+ runner.start().then(() => {
101
+ runnerDone = true
102
+ res(undefined)
103
+ })
104
+ }
105
+
106
+ await runner.handleOrchMessage(msg)
107
+ }
108
+
109
+ logger.error('Stream ended')
110
+ } catch (err) {
111
+ if (runnerDone) {
112
+ // Stream error after runner finished (e.g. connection dropped during cleanup) — safe to ignore
113
+ return
114
+ }
115
+ rej(err)
116
+ }
117
+ })
44
118
 
45
- logger.info('All processors are finished')
46
- stream.end()
47
- client.close()
48
- setTimeout(() => process.exit(0), 500)
119
+ logger.info('All processors are finished')
120
+ } finally {
121
+ abortCtrl.removeEventListener('abort', closeConnection)
122
+ closeConnection()
123
+ }
49
124
  }
package/src/index.ts CHANGED
@@ -4,5 +4,7 @@ export * from './reader'
4
4
  export * from './processor'
5
5
  export * from './runner'
6
6
  export * from './logger'
7
+ export * from './state'
7
8
 
8
9
  export * as reexports from './reexports'
10
+ export * from './server'
package/src/reader.ts CHANGED
@@ -15,6 +15,7 @@ import {
15
15
  } from './convertor'
16
16
  import { Writable } from './runner'
17
17
  import { promisify } from 'util'
18
+ import { ChannelTracker } from './state'
18
19
 
19
20
  export type Any =
20
21
  | {
@@ -106,6 +107,7 @@ export class ReaderInstance implements Reader {
106
107
  readonly uri: string
107
108
  private logger: Logger
108
109
  private readonly notifyOrchestrator: Writable
110
+ private readonly tracker: ChannelTracker | undefined
109
111
 
110
112
  private consumers: MyIter<unknown>[] = []
111
113
 
@@ -114,11 +116,13 @@ export class ReaderInstance implements Reader {
114
116
  client: RunnerClient,
115
117
  notifyOrchestrator: Writable,
116
118
  logger: Logger,
119
+ tracker?: ChannelTracker,
117
120
  ) {
118
121
  this.uri = uri
119
122
  this.client = client
120
123
  this.logger = logger
121
124
  this.notifyOrchestrator = notifyOrchestrator
125
+ this.tracker = tracker
122
126
  }
123
127
 
124
128
  anys(): AsyncIterable<Any> {
@@ -147,6 +151,7 @@ export class ReaderInstance implements Reader {
147
151
 
148
152
  handleMsg(msg: ReceivingMessage) {
149
153
  this.logger.debug(`${this.uri} handling message`)
154
+ this.tracker?.recordMessage(msg.data.length)
150
155
 
151
156
  const promises = []
152
157
  for (const iter of this.consumers) {
@@ -163,7 +168,11 @@ export class ReaderInstance implements Reader {
163
168
  )
164
169
  }
165
170
 
171
+ private hasClosed = false
172
+
166
173
  close() {
174
+ if (this.hasClosed) return
175
+ this.hasClosed = true
167
176
  for (const iter of this.consumers) {
168
177
  iter.close(() => {})
169
178
  }
@@ -175,6 +184,7 @@ export class ReaderInstance implements Reader {
175
184
  globalSequenceNumber,
176
185
  }: ReceivingStreamMessage) {
177
186
  this.logger.debug(`${this.uri} handling streaming message`)
187
+ this.tracker?.recordMessage(0)
178
188
 
179
189
  const chunks = this.client.receiveStreamMessage()
180
190
  const writeControlMessage = promisify(chunks.write.bind(chunks))
@@ -201,7 +211,7 @@ export class ReaderInstance implements Reader {
201
211
  await writeControlMessage({ globalSequenceNumber })
202
212
 
203
213
  Promise.all(consumersConsumed).then(() => {
204
- console.log('Writing processed for streaming message')
214
+ chunks.end()
205
215
  this.notifyOrchestrator({ processed: { globalSequenceNumber, channel } })
206
216
  })
207
217
  }
package/src/runner.ts CHANGED
@@ -8,16 +8,18 @@ import {
8
8
  ReceivingMessage,
9
9
  ReceivingStreamMessage,
10
10
  } from '@rdfc/proto'
11
+ import { pathToFileURL } from 'node:url'
11
12
  import { Reader, ReaderInstance } from './reader'
12
13
  import { Writer, WriterInstance } from './writer'
13
14
  import { Processor as Proc } from './processor'
14
- import { createLogger, Logger } from 'winston'
15
+ import { Logger } from 'winston'
15
16
 
16
- import { RpcTransport } from './logger'
17
+ import { extendLogger } from './logger'
17
18
  import { Cont, empty, extractShapes, Shapes } from 'rdf-lens'
18
19
  import { NamedNode, Parser } from 'n3'
19
20
  import { createNamespace, createUriAndTermNamespace, RDF } from '@treecg/types'
20
21
  import { Quad, Term } from '@rdfjs/types'
22
+ import { State } from './state'
21
23
 
22
24
  const RDFL = createUriAndTermNamespace(
23
25
  'https://w3id.org/rdf-lens/ontology#',
@@ -61,30 +63,64 @@ export class Runner {
61
63
 
62
64
  private readonly processors: Proc<unknown>[] = []
63
65
  private readonly processorTransforms: Promise<unknown>[] = []
66
+ private readonly configPath?: string
67
+ private readonly state?: State
68
+ private readonly runnerId?: string
64
69
 
65
70
  constructor(
66
71
  client: RunnerClient,
67
72
  notifyOrchestrator: Writable,
68
73
  uri: string,
69
74
  logger: Logger,
75
+ configPath?: string,
76
+ state?: State,
77
+ runnerId?: string,
70
78
  ) {
71
79
  this.client = client
72
80
  this.notifyOrchestrator = notifyOrchestrator
73
81
  this.uri = uri
74
82
  this.logger = logger
83
+ this.configPath = configPath
84
+ this.state = state
85
+ this.runnerId = runnerId
86
+ }
87
+
88
+ makeRelative(target: string, base: string): string {
89
+ if (!this.configPath) return target
90
+
91
+ const targetUrl = new URL(target)
92
+ const baseUrl = new URL(base)
93
+
94
+ const targetParts = targetUrl.pathname.split('/')
95
+ const baseParts = baseUrl.pathname.split('/')
96
+
97
+ // Remove filename from base (treat as directory)
98
+ baseParts.pop()
99
+
100
+ // Find common path
101
+ let i = 0
102
+ while (
103
+ i < targetParts.length &&
104
+ i < baseParts.length &&
105
+ targetParts[i] === baseParts[i]
106
+ ) {
107
+ i++
108
+ }
109
+
110
+ const up = baseParts.slice(i).map(() => '..')
111
+ const down = targetParts.slice(i)
112
+
113
+ const thing = './' + [...up, ...down].join('/')
114
+ const configPath = this.configPath && pathToFileURL(this.configPath)
115
+ console.log({ configPath, thing, base, target })
116
+ const final = new URL(thing, configPath)
117
+ return final.href
75
118
  }
76
119
 
77
120
  async createProcessor<P extends Proc<unknown>>(
78
121
  proc: Processor,
79
122
  ): Promise<FullProc<P>> {
80
- const procLogger = createLogger({
81
- transports: [
82
- new RpcTransport({
83
- entities: [proc.uri, this.uri],
84
- stream: this.client.logStream(() => {}),
85
- }),
86
- ],
87
- })
123
+ const procLogger = extendLogger(this.logger, proc.uri)
88
124
 
89
125
  const ty = this.quads
90
126
  .filter(
@@ -102,7 +138,7 @@ export class Runner {
102
138
  })
103
139
 
104
140
  const config: ProcessorConfig = JSON.parse(proc.config)
105
- const jsProgram = await import(config.file)
141
+ const jsProgram = await import(this.makeRelative(config.file, this.uri))
106
142
  const clazz = jsProgram[config.clazz || 'default']
107
143
  const instance: Proc<unknown> = new clazz(args, procLogger)
108
144
 
@@ -112,6 +148,7 @@ export class Runner {
112
148
  async addProcessor<P extends Proc<unknown>>(
113
149
  proc: Processor,
114
150
  ): Promise<FullProc<P>> {
151
+ this.logger.info(JSON.stringify(proc))
115
152
  const instance = await this.createProcessor<P>(proc)
116
153
 
117
154
  await instance.init()
@@ -141,12 +178,17 @@ export class Runner {
141
178
  if (this.writers[id] !== undefined) {
142
179
  return this.writers[id]
143
180
  }
181
+ const tracker =
182
+ this.runnerId !== undefined
183
+ ? this.state?.trackChannel(this.runnerId, id, 'writer')
184
+ : undefined
144
185
  const writer = new WriterInstance(
145
186
  id,
146
187
  this.client,
147
188
  this.notifyOrchestrator,
148
189
  this.uri,
149
190
  this.logger,
191
+ tracker,
150
192
  )
151
193
  this.writers[id] = writer
152
194
  return writer
@@ -158,11 +200,16 @@ export class Runner {
158
200
  if (this.readers[ids] !== undefined) {
159
201
  return this.readers[ids]
160
202
  }
203
+ const tracker =
204
+ this.runnerId !== undefined
205
+ ? this.state?.trackChannel(this.runnerId, ids, 'reader')
206
+ : undefined
161
207
  const reader = new ReaderInstance(
162
208
  ids,
163
209
  this.client,
164
210
  this.notifyOrchestrator,
165
211
  this.logger,
212
+ tracker,
166
213
  )
167
214
  this.readers[ids] = reader
168
215
  return reader