@rdfc/js-runner 2.0.0-alpha.9 → 3.0.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 (72) hide show
  1. package/.editorconfig +9 -0
  2. package/.github/renovate.json +3 -0
  3. package/README.md +127 -3
  4. package/__tests__/channels.test.ts +131 -74
  5. package/__tests__/echoProcessor.test.ts +131 -0
  6. package/__tests__/testProcessor.test.ts +69 -0
  7. package/eslint.config.mjs +1 -1
  8. package/examples/echo/.idea/echo.iml +9 -0
  9. package/examples/echo/.idea/misc.xml +6 -0
  10. package/{.idea → examples/echo/.idea}/modules.xml +1 -1
  11. package/examples/echo/.idea/vcs.xml +7 -0
  12. package/examples/echo/.swls/config.json +1 -0
  13. package/examples/echo/index.ttl +3 -0
  14. package/examples/echo/minimal.ttl +90 -0
  15. package/examples/echo/shacl.ttl +9 -0
  16. package/examples/echo/shape.ttl +1339 -0
  17. package/examples/echo/test.ttl +11 -0
  18. package/examples/echo/untitled:/types/MyType.ttl +0 -0
  19. package/file:/home/silvius/Projects/mumo-pipeline/ldes/http_3A_2F_2Fdata.mumo.be_2Fstreams_2Fnodes_2Fdefault/root/index.trig +3 -0
  20. package/index.ttl +3 -31
  21. package/ldes/http_3A_2F_2Fdata.mumo.be_2Fstreams_2Fnodes_2Fdefault/root/index.trig +3 -0
  22. package/lib/client.js +7 -10
  23. package/lib/logger.d.ts +2 -2
  24. package/lib/logger.js +3 -3
  25. package/lib/reader.d.ts +8 -6
  26. package/lib/reader.js +135 -26
  27. package/lib/runner.d.ts +10 -5
  28. package/lib/runner.js +86 -46
  29. package/lib/testUtils/duplex.d.ts +25 -0
  30. package/lib/testUtils/duplex.js +70 -0
  31. package/lib/testUtils/index.d.ts +51 -0
  32. package/lib/testUtils/index.js +243 -0
  33. package/lib/testUtils.d.ts +6 -0
  34. package/lib/testUtils.js +92 -2
  35. package/lib/tsconfig.tsbuildinfo +1 -1
  36. package/lib/writer.d.ts +12 -5
  37. package/lib/writer.js +66 -13
  38. package/minimal.ttl +99 -0
  39. package/package.json +5 -5
  40. package/src/client.ts +9 -12
  41. package/src/logger.ts +3 -3
  42. package/src/reader.ts +207 -30
  43. package/src/runner.ts +128 -65
  44. package/src/testUtils/duplex.ts +112 -0
  45. package/src/testUtils/index.ts +430 -0
  46. package/src/writer.ts +106 -16
  47. package/.idea/LNKD.tech Editor.xml +0 -194
  48. package/.idea/codeStyles/Project.xml +0 -52
  49. package/.idea/codeStyles/codeStyleConfig.xml +0 -5
  50. package/.idea/inspectionProfiles/Project_Default.xml +0 -6
  51. package/.idea/js-runner.iml +0 -12
  52. package/.idea/vcs.xml +0 -6
  53. package/dist/args.d.ts +0 -4
  54. package/dist/args.js +0 -58
  55. package/dist/connectors/file.d.ts +0 -15
  56. package/dist/connectors/file.js +0 -89
  57. package/dist/connectors/http.d.ts +0 -14
  58. package/dist/connectors/http.js +0 -82
  59. package/dist/connectors/kafka.d.ts +0 -48
  60. package/dist/connectors/kafka.js +0 -68
  61. package/dist/connectors/ws.d.ts +0 -10
  62. package/dist/connectors/ws.js +0 -72
  63. package/dist/connectors.d.ts +0 -73
  64. package/dist/connectors.js +0 -168
  65. package/dist/index.cjs +0 -732
  66. package/dist/index.d.ts +0 -42
  67. package/dist/index.js +0 -83
  68. package/dist/tsconfig.tsbuildinfo +0 -1
  69. package/dist/util.d.ts +0 -71
  70. package/dist/util.js +0 -92
  71. package/src/jsonld.ts +0 -220
  72. package/src/testUtils.ts +0 -77
@@ -0,0 +1,243 @@
1
+ import { extractShapes } from 'rdf-lens';
2
+ import { NamedNode, Parser, Writer as N3Writer } from 'n3';
3
+ import { readFile } from 'fs/promises';
4
+ import winston, { createLogger } from 'winston';
5
+ import { Runner } from '../runner.js';
6
+ import { createTermNamespace } from '@treecg/types';
7
+ import { MockClientDuplexStream } from './duplex.js';
8
+ import { promisify } from 'util';
9
+ export function channel(runner, name) {
10
+ const n = new NamedNode(name);
11
+ const reader = runner.createReader(n);
12
+ const writer = runner.createWriter(n);
13
+ return [writer, reader];
14
+ }
15
+ export class StreamMsgMock {
16
+ data = [];
17
+ resolveId;
18
+ constructor(resolveId) {
19
+ this.resolveId = resolveId;
20
+ }
21
+ sendStreamMessage() {
22
+ const sendingStream = new MockClientDuplexStream();
23
+ let at = 0;
24
+ sendingStream.register((x) => x.data, (d, send) => {
25
+ setTimeout(() => send({ streamSequenceNumber: ++at }), 20);
26
+ this.data.push(d);
27
+ });
28
+ sendingStream.register((x) => x.id, (d, send) => send({ streamSequenceNumber: this.resolveId(d) }));
29
+ return sendingStream;
30
+ }
31
+ }
32
+ export class OrchestratorMock {
33
+ connectStream;
34
+ streamMsgs = {};
35
+ streamMsgCount = 0;
36
+ connect() {
37
+ const connectStream = new MockClientDuplexStream();
38
+ connectStream.register((msg) => msg.processed, ({ channel, globalSequenceNumber }, send) => {
39
+ send({
40
+ processed: { channel, localSequenceNumber: globalSequenceNumber },
41
+ });
42
+ });
43
+ connectStream.register((msg) => msg.msg, ({ localSequenceNumber, data, channel }, send) => {
44
+ send({
45
+ msg: { globalSequenceNumber: localSequenceNumber, channel, data },
46
+ });
47
+ });
48
+ connectStream.register((msg) => msg.close, (close, send) => {
49
+ send({ close });
50
+ });
51
+ this.connectStream = connectStream;
52
+ return connectStream;
53
+ }
54
+ sendStreamMessage() {
55
+ const out = new MockClientDuplexStream();
56
+ const id = this.streamMsgCount;
57
+ this.streamMsgCount++;
58
+ out.registerOnce((x) => x.id, ({ channel }, toProducingStream) => {
59
+ this.streamMsgs[id] = { toProducingStream };
60
+ this.connectStream.send({
61
+ streamMsg: { channel, globalSequenceNumber: id },
62
+ });
63
+ });
64
+ out.register((x) => x.data, (data) => {
65
+ this.streamMsgs[id].receivingStream.send(data);
66
+ });
67
+ out.on('end', () => {
68
+ this.streamMsgs[id].receivingStream.end();
69
+ });
70
+ return out;
71
+ }
72
+ receiveStreamMessage() {
73
+ const receivingStream = new MockClientDuplexStream();
74
+ let streamId = 0;
75
+ receivingStream.registerOnce((x) => x.globalSequenceNumber, (id) => {
76
+ streamId = id;
77
+ this.streamMsgs[id].receivingStream = receivingStream;
78
+ this.streamMsgs[id].toProducingStream({ streamSequenceNumber: 0 });
79
+ });
80
+ receivingStream.register((x) => x.streamSequenceNumber, (streamSequenceNumber) => {
81
+ this.streamMsgs[streamId].toProducingStream({ streamSequenceNumber });
82
+ });
83
+ return receivingStream;
84
+ }
85
+ logStream() {
86
+ const logStream = new MockClientDuplexStream();
87
+ logStream.register((x) => x, console.log);
88
+ return logStream;
89
+ }
90
+ }
91
+ export function createRunner(uri = 'http://example.com/ns#') {
92
+ const logger = createLogger({
93
+ transports: new winston.transports.Console({
94
+ level: process.env['DEBUG'] || 'info',
95
+ }),
96
+ });
97
+ const client = new OrchestratorMock();
98
+ const stream = client.connect();
99
+ const writable = promisify(stream.write.bind(stream));
100
+ const runner = new Runner(client, writable, uri, logger);
101
+ stream.on('data', (msg) => runner.handleOrchMessage(msg));
102
+ return runner;
103
+ }
104
+ export async function one(iter) {
105
+ for await (const item of iter) {
106
+ return item;
107
+ }
108
+ }
109
+ const shapeQuads = `
110
+ @prefix rdfc: <https://w3id.org/rdf-connect#>.
111
+ @prefix xsd: <http://www.w3.org/2001/XMLSchema#>.
112
+ @prefix sh: <http://www.w3.org/ns/shacl#>.
113
+ [ ] a sh:NodeShape;
114
+ sh:targetClass <JsProcessorShape>;
115
+ sh:property [
116
+ sh:path rdfc:entrypoint;
117
+ sh:name "location";
118
+ sh:minCount 1;
119
+ sh:maxCount 1;
120
+ sh:datatype xsd:string;
121
+ ], [
122
+ sh:path rdfc:file;
123
+ sh:name "file";
124
+ sh:minCount 1;
125
+ sh:maxCount 1;
126
+ sh:datatype xsd:string;
127
+ ], [
128
+ sh:path rdfc:class;
129
+ sh:name "clazz";
130
+ sh:maxCount 1;
131
+ sh:datatype xsd:string;
132
+ ].
133
+ `;
134
+ const OWL = createTermNamespace('http://www.w3.org/2002/07/owl#', 'imports');
135
+ const processorShapes = extractShapes(new Parser().parse(shapeQuads));
136
+ const base = 'https://w3id.org/rdf-connect#';
137
+ export async function importFile(file, content) {
138
+ const done = new Set();
139
+ const quads = [];
140
+ const todo = [];
141
+ const parse = (content, baseIRI) => {
142
+ done.add(baseIRI.toString());
143
+ const extras = new Parser({ baseIRI: baseIRI.toString() }).parse(content);
144
+ for (const o of extras
145
+ .filter((x) => x.subject.value === baseIRI?.toString() &&
146
+ x.predicate.equals(OWL.imports))
147
+ .map((x) => x.object.value)) {
148
+ todo.push(new URL(o));
149
+ }
150
+ quads.push(...extras);
151
+ };
152
+ if (content) {
153
+ parse(content, new URL('file://' + file));
154
+ }
155
+ else {
156
+ todo.push(new URL('file://' + file));
157
+ }
158
+ let item = todo.pop();
159
+ while (item !== undefined) {
160
+ if (done.has(item.toString())) {
161
+ item = todo.pop();
162
+ continue;
163
+ }
164
+ if (item.protocol !== 'file:') {
165
+ throw 'No supported protocol ' + item.protocol;
166
+ }
167
+ const txt = await readFile(item.pathname, { encoding: 'utf8' });
168
+ parse(txt, item);
169
+ item = todo.pop();
170
+ }
171
+ return quads;
172
+ }
173
+ export class ProcHelper {
174
+ runner;
175
+ quads = [];
176
+ config;
177
+ proc;
178
+ constructor(uri) {
179
+ this.runner = createRunner(uri);
180
+ }
181
+ async importInline(baseIRI, config) {
182
+ const configQuads = await importFile(baseIRI, config);
183
+ this.quads.push(...configQuads);
184
+ }
185
+ async importFile(file) {
186
+ const configQuads = await importFile(file);
187
+ this.quads.push(...configQuads);
188
+ }
189
+ getConfig(ty) {
190
+ const id = typeof ty === 'string' ? new NamedNode(base + ty) : ty;
191
+ const procConfig = processorShapes.lenses['JsProcessorShape'].execute({
192
+ id,
193
+ quads: this.quads,
194
+ });
195
+ this.config = procConfig;
196
+ return procConfig;
197
+ }
198
+ async getProcessor(uri = 'http://example.com/ns#processor') {
199
+ await this.runner.handleOrchMessage({
200
+ pipeline: new N3Writer().quadsToString(this.quads),
201
+ });
202
+ const proc = await this.runner.addProcessor({
203
+ config: JSON.stringify(this.config),
204
+ arguments: '',
205
+ uri,
206
+ });
207
+ return proc;
208
+ }
209
+ }
210
+ export async function getProcInline(config, ty, runner, baseIRI, uri = 'http://example.com/ns#processor') {
211
+ const configQuads = await importFile(baseIRI, config);
212
+ const procConfig = processorShapes.lenses['JsProcessorShape'].execute({
213
+ id: new NamedNode(base + ty),
214
+ quads: configQuads,
215
+ });
216
+ await runner.handleOrchMessage({
217
+ pipeline: new N3Writer().quadsToString(configQuads),
218
+ });
219
+ const proc = await runner.addProcessor({
220
+ config: JSON.stringify(procConfig),
221
+ arguments: '',
222
+ uri,
223
+ });
224
+ return proc;
225
+ }
226
+ export async function getProc(config, ty, runner, configLocation, uri = 'http://example.com/ns#processor') {
227
+ const configQuads = await importFile(configLocation);
228
+ const procConfig = processorShapes.lenses['JsProcessorShape'].execute({
229
+ id: new NamedNode(base + ty),
230
+ quads: configQuads,
231
+ });
232
+ configQuads.push(...new Parser().parse(config));
233
+ await runner.handleOrchMessage({
234
+ pipeline: new N3Writer().quadsToString(configQuads),
235
+ });
236
+ const proc = await runner.addProcessor({
237
+ config: JSON.stringify(procConfig),
238
+ arguments: '',
239
+ uri,
240
+ });
241
+ return proc;
242
+ }
243
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdGVzdFV0aWxzL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQVFBLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxVQUFVLENBQUE7QUFDeEMsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsTUFBTSxJQUFJLFFBQVEsRUFBRSxNQUFNLElBQUksQ0FBQTtBQUMxRCxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sYUFBYSxDQUFBO0FBQ3RDLE9BQU8sT0FBTyxFQUFFLEVBQUUsWUFBWSxFQUFFLE1BQU0sU0FBUyxDQUFBO0FBRS9DLE9BQU8sRUFBWSxNQUFNLEVBQVksTUFBTSxXQUFXLENBQUE7QUFFdEQsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sZUFBZSxDQUFBO0FBT25ELE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLFVBQVUsQ0FBQTtBQUNqRCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sTUFBTSxDQUFBO0FBSWhDLE1BQU0sVUFBVSxPQUFPLENBQUMsTUFBYyxFQUFFLElBQVk7SUFDbEQsTUFBTSxDQUFDLEdBQUcsSUFBSSxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUE7SUFDN0IsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQTtJQUNyQyxNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFBO0lBRXJDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUE7QUFDekIsQ0FBQztBQUVELE1BQU0sT0FBTyxhQUFhO0lBQ3hCLElBQUksR0FBZ0IsRUFBRSxDQUFBO0lBRUwsU0FBUyxDQUFnQztJQUUxRCxZQUFZLFNBQXlDO1FBQ25ELElBQUksQ0FBQyxTQUFTLEdBQUcsU0FBUyxDQUFBO0lBQzVCLENBQUM7SUFFRCxpQkFBaUI7UUFJZixNQUFNLGFBQWEsR0FBRyxJ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RUFBVSxFQUNWLE1BQWMsRUFDZCxjQUFzQixFQUN0QixHQUFHLEdBQUcsaUNBQWlDO0lBRXZDLE1BQU0sV0FBVyxHQUFHLE1BQU0sVUFBVSxDQUFDLGNBQWMsQ0FBQyxDQUFBO0lBQ3BELE1BQU0sVUFBVSxHQUFHLGVBQWUsQ0FBQyxNQUFNLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxPQUFPLENBQUM7UUFDcEUsRUFBRSxFQUFFLElBQUksU0FBUyxDQUFDLElBQUksR0FBRyxFQUFFLENBQUM7UUFDNUIsS0FBSyxFQUFFLFdBQVc7S0FDbkIsQ0FBQyxDQUFBO0lBRUYsV0FBVyxDQUFDLElBQUksQ0FBQyxHQUFHLElBQUksTUFBTSxFQUFFLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUE7SUFDL0MsTUFBTSxNQUFNLENBQUMsaUJBQWlCLENBQUM7UUFDN0IsUUFBUSxFQUFFLElBQUksUUFBUSxFQUFFLENBQUMsYUFBYSxDQUFDLFdBQVcsQ0FBQztLQUNwRCxDQUFDLENBQUE7SUFFRixNQUFNLElBQUksR0FBRyxNQUFNLE1BQU0sQ0FBQyxZQUFZLENBQUk7UUFDeEMsTUFBTSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDO1FBQ2xDLFNBQVMsRUFBRSxFQUFFO1FBQ2IsR0FBRztLQUNKLENBQUMsQ0FBQTtJQUVGLE9BQU8sSUFBSSxDQUFBO0FBQ2IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIERhdGFDaHVuayxcbiAgRnJvbVJ1bm5lcixcbiAgTG9nTWVzc2FnZSxcbiAgUHJvY2Vzc29yIGFzIFByb2NDb25maWcsXG4gIFRvUnVubmVyLFxufSBmcm9tICdAcmRmYy9wcm90bydcbmltcG9ydCB7fSBmcm9tICcuLi9yZWV4cG9ydHMnXG5pbXBvcnQgeyBleHRyYWN0U2hhcGVzIH0gZnJvbSAncmRmLWxlbnMnXG5pbXBvcnQgeyBOYW1lZE5vZGUsIFBhcnNlciwgV3JpdGVyIGFzIE4zV3JpdGVyIH0gZnJvbSAnbjMnXG5pbXBvcnQgeyByZWFkRmlsZSB9IGZyb20gJ2ZzL3Byb21pc2VzJ1xuaW1wb3J0IHdpbnN0b24sIHsgY3JlYXRlTG9nZ2VyIH0gZnJvbSAnd2luc3RvbidcbmltcG9ydCB7IFByb2Nlc3NvciB9IGZyb20gJy4uL3Byb2Nlc3NvcidcbmltcG9ydCB7IEZ1bGxQcm9jLCBSdW5uZXIsIFdyaXRhYmxlIH0gZnJvbSAnLi4vcnVubmVyJ1xuaW1wb3J0IHsgUXVhZCB9IGZyb20gJ0ByZGZqcy90eXBlcydcbmltcG9ydCB7IGNyZWF0ZVRlcm1OYW1lc3BhY2UgfSBmcm9tICdAdHJlZWNnL3R5cGVzJ1xuaW1wb3J0IHtcbiAgUmVjZWl2aW5nU3RyZWFtQ29udHJvbCxcbiAgU2VuZGluZ1N0cmVhbUNvbnRyb2wsXG4gIFN0cmVhbUNodW5rLFxuICBTdHJlYW1JZGVudGlmeSxcbn0gZnJvbSAnQHJkZmMvcHJvdG8vbGliL2dlbmVyYXRlZC9jb21tb24nXG5pbXBvcnQgeyBNb2NrQ2xpZW50RHVwbGV4U3RyZWFtIH0gZnJvbSAnLi9kdXBsZXgnXG5pbXBvcnQgeyBwcm9taXNpZnkgfSBmcm9tICd1dGlsJ1xuaW1wb3J0IHsgUmVhZGVyIH0gZnJvbSAnLi4vcmVhZGVyJ1xuaW1wb3J0IHsgV3JpdGVyIH0gZnJvbSAnLi4vd3JpdGVyJ1xuXG5leHBvcnQgZnVuY3Rpb24gY2hhbm5lbChydW5uZXI6IFJ1bm5lciwgbmFtZTogc3RyaW5nKTogW1dyaXRlciwgUmVhZGVyXSB7XG4gIGNvbnN0IG4gPSBuZXcgTmFtZWROb2RlKG5hbWUpXG4gIGNvbnN0IHJlYWRlciA9IHJ1bm5lci5jcmVhdGVSZWFkZXIobilcbiAgY29uc3Qgd3JpdGVyID0gcnVubmVyLmNyZWF0ZVdyaXRlcihuKVxuXG4gIHJldHVybiBbd3JpdGVyLCByZWFkZXJdXG59XG5cbmV4cG9ydCBjbGFzcyBTdHJlYW1Nc2dNb2NrIHtcbiAgZGF0YTogRGF0YUNodW5rW10gPSBbXVxuXG4gIHByaXZhdGUgcmVhZG9ubHkgcmVzb2x2ZUlkOiAoaWQ6IFN0cmVhbUlkZW50aWZ5KSA9PiBudW1iZXJcblxuICBjb25zdHJ1Y3RvcihyZXNvbHZlSWQ6IChpZDogU3RyZWFtSWRlbnRpZnkpID0+IG51bWJlcikge1xuICAgIHRoaXMucmVzb2x2ZUlkID0gcmVzb2x2ZUlkXG4gIH1cblxuICBzZW5kU3RyZWFtTWVzc2FnZSgpOiBNb2NrQ2xpZW50RHVwbGV4U3RyZWFtPFxuICAgIFN0cmVhbUNodW5rLFxuICAgIFJlY2VpdmluZ1N0cmVhbUNvbnRyb2xcbiAgPiB7XG4gICAgY29uc3Qgc2VuZGluZ1N0cmVhbSA9IG5ldyBNb2NrQ2xpZW50RHVwbGV4U3RyZWFtPFxuICAgICAgU3RyZWFtQ2h1bmssXG4gICAgICBSZWNlaXZpbmdTdHJlYW1Db250cm9sXG4gICAgPigpXG5cbiAgICBsZXQgYXQgPSAwXG4gICAgc2VuZGluZ1N0cmVhbS5yZWdpc3RlcihcbiAgICAgICh4KSA9PiB4LmRhdGEsXG4gICAgICAoZCwgc2VuZCkgPT4ge1xuICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHNlbmQoeyBzdHJlYW1TZXF1ZW5jZU51bWJlcjogKythdCB9KSwgMjApXG4gICAgICAgIHRoaXMuZGF0YS5wdXNoKGQpXG4gICAgICB9LFxuICAgIClcbiAgICBzZW5kaW5nU3RyZWFtLnJlZ2lzdGVyKFxuICAgICAgKHgpID0+IHguaWQsXG4gICAgICAoZCwgc2VuZCkgPT4gc2VuZCh7IHN0cmVhbVNlcXVlbmNlTnVtYmVyOiB0aGlzLnJlc29sdmVJZChkKSB9KSxcbiAgICApXG4gICAgcmV0dXJuIHNlbmRpbmdTdHJlYW1cbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgT3JjaGVzdHJhdG9yTW9jayB7XG4gIGNvbm5lY3RTdHJlYW06IE1vY2tDbGllbnREdXBsZXhTdHJlYW08RnJvbVJ1bm5lciwgVG9SdW5uZXI+XG5cbiAgc3RyZWFtTXNnczoge1xuICAgIFtpZDogc3RyaW5nXToge1xuICAgICAgdG9Qcm9kdWNpbmdTdHJlYW06IChpZDogUmVjZWl2aW5nU3RyZWFtQ29udHJvbCkgPT4gdm9pZFxuICAgICAgcmVjZWl2aW5nU3RyZWFtPzogTW9ja0NsaWVudER1cGxleFN0cmVhbTxTZW5kaW5nU3RyZWFtQ29udHJvbCwgRGF0YUNodW5rPlxuICAgIH1cbiAgfSA9IHt9XG5cbiAgc3RyZWFtTXNnQ291bnQgPSAwXG5cbiAgY29ubmVjdCgpOiBNb2NrQ2xpZW50RHVwbGV4U3RyZWFtPEZyb21SdW5uZXIsIFRvUnVubmVyPiB7XG4gICAgY29uc3QgY29ubmVjdFN0cmVhbSA9IG5ldyBNb2NrQ2xpZW50RHVwbGV4U3RyZWFtPEZyb21SdW5uZXIsIFRvUnVubmVyPigpXG4gICAgLy8gQWx3YXlzIGJvdW5jZSBwcm9jZXNzZWQgbXNncyBiYWNrIHRvIHRoZSBydW5uZXJcbiAgICBjb25uZWN0U3RyZWFtLnJlZ2lzdGVyKFxuICAgICAgKG1zZykgPT4gbXNnLnByb2Nlc3NlZCxcbiAgICAgICh7IGNoYW5uZWwsIGdsb2JhbFNlcXVlbmNlTnVtYmVyIH0sIHNlbmQpID0+IHtcbiAgICAgICAgc2VuZCh7XG4gICAgICAgICAgcHJvY2Vzc2VkOiB7IGNoYW5uZWwsIGxvY2FsU2VxdWVuY2VOdW1iZXI6IGdsb2JhbFNlcXVlbmNlTnVtYmVyIH0sXG4gICAgICAgIH0pXG4gICAgICB9LFxuICAgIClcblxuICAgIC8vIEFsd2F5cyBib3VuY2UgZGF0YSBtc2dzIGJhY2sgdG8gdGhlIHJ1bm5lclxuICAgIGNvbm5lY3RTdHJlYW0ucmVnaXN0ZXIoXG4gICAgICAobXNnKSA9PiBtc2cubXNnLFxuICAgICAgKHsgbG9jYWxTZXF1ZW5jZU51bWJlciwgZGF0YSwgY2hhbm5lbCB9LCBzZW5kKSA9PiB7XG4gICAgICAgIHNlbmQoe1xuICAgICAgICAgIG1zZzogeyBnbG9iYWxTZXF1ZW5jZU51bWJlcjogbG9jYWxTZXF1ZW5jZU51bWJlciwgY2hhbm5lbCwgZGF0YSB9LFxuICAgICAgICB9KVxuICAgICAgfSxcbiAgICApXG5cbiAgICAvLyBBbHdheXMgYm91bmNlIGNsb3NlIG1zZ3MgYmFjayB0byB0aGUgcnVubmVyXG4gICAgY29ubmVjdFN0cmVhbS5yZWdpc3RlcihcbiAgICAgIChtc2cpID0+IG1zZy5jbG9zZSxcbiAgICAgIChjbG9zZSwgc2VuZCkgPT4ge1xuICAgICAgICBzZW5kKHsgY2xvc2UgfSlcbiAgICAgIH0sXG4gICAgKVxuXG4gICAgdGhpcy5jb25uZWN0U3RyZWFtID0gY29ubmVjdFN0cmVhbVxuICAgIHJldHVybiBjb25uZWN0U3RyZWFtXG4gIH1cblxuICBzZW5kU3RyZWFtTWVzc2FnZSgpOiBNb2NrQ2xpZW50RHVwbGV4U3RyZWFtPFxuICAgIFN0cmVhbUNodW5rLFxuICAgIFJlY2VpdmluZ1N0cmVhbUNvbnRyb2xcbiAgPiB7XG4gICAgY29uc3Qgb3V0ID0gbmV3IE1vY2tDbGllbnREdXBsZXhTdHJlYW08XG4gICAgICBTdHJlYW1DaHVuayxcbiAgICAgIFJlY2VpdmluZ1N0cmVhbUNvbnRyb2xcbiAgICA+KClcbiAgICBjb25zdCBpZCA9IHRoaXMuc3RyZWFtTXNnQ291bnRcbiAgICB0aGlzLnN0cmVhbU1zZ0NvdW50KytcblxuICAgIG91dC5yZWdpc3Rlck9uY2UoXG4gICAgICAoeCkgPT4geC5pZCxcbiAgICAgICh7IGNoYW5uZWwgfSwgdG9Qcm9kdWNpbmdTdHJlYW0pID0+IHtcbiAgICAgICAgdGhpcy5zdHJlYW1Nc2dzW2lkXSA9IHsgdG9Qcm9kdWNpbmdTdHJlYW0gfVxuXG4gICAgICAgIC8vIE5vdGlmeSBzdHJlYW0gbWVzc2FnZVxuICAgICAgICB0aGlzLmNvbm5lY3RTdHJlYW0uc2VuZCh7XG4gICAgICAgICAgc3RyZWFtTXNnOiB7IGNoYW5uZWwsIGdsb2JhbFNlcXVlbmNlTnVtYmVyOiBpZCB9LFxuICAgICAgICB9KVxuICAgICAgfSxcbiAgICApXG5cbiAgICBvdXQucmVnaXN0ZXIoXG4gICAgICAoeCkgPT4geC5kYXRhLFxuICAgICAgKGRhdGEpID0+IHtcbiAgICAgICAgLy8gYm91bmNlIGRhdGEgdG8gcmVjZWl2aW5nIHN0cmVhbVxuICAgICAgICB0aGlzLnN0cmVhbU1zZ3NbaWRdLnJlY2VpdmluZ1N0cmVhbSEuc2VuZChkYXRhKVxuICAgICAgfSxcbiAgICApXG5cbiAgICBvdXQub24oJ2VuZCcsICgpID0+IHtcbiAgICAgIC8vIGVuZCByZWNlaXZpbmcgc3RyZWFtXG4gICAgICB0aGlzLnN0cmVhbU1zZ3NbaWRdLnJlY2VpdmluZ1N0cmVhbSEuZW5kKClcbiAgICB9KVxuXG4gICAgcmV0dXJuIG91dFxuICB9XG5cbiAgcmVjZWl2ZVN0cmVhbU1lc3NhZ2UoKTogTW9ja0NsaWVudER1cGxleFN0cmVhbTxcbiAgICBTZW5kaW5nU3RyZWFtQ29udHJvbCxcbiAgICBEYXRhQ2h1bmtcbiAgPiB7XG4gICAgY29uc3QgcmVjZWl2aW5nU3RyZWFtID0gbmV3IE1vY2tDbGllbnREdXBsZXhTdHJlYW08XG4gICAgICBTZW5kaW5nU3RyZWFtQ29udHJvbCxcbiAgICAgIERhdGFDaHVua1xuICAgID4oKVxuICAgIGxldCBzdHJlYW1JZCA9IDBcblxuICAgIHJlY2VpdmluZ1N0cmVhbS5yZWdpc3Rlck9uY2UoXG4gICAgICAoeCkgPT4geC5nbG9iYWxTZXF1ZW5jZU51bWJlcixcbiAgICAgIChpZCkgPT4ge1xuICAgICAgICBzdHJlYW1JZCA9IGlkXG4gICAgICAgIHRoaXMuc3RyZWFtTXNnc1tpZF0ucmVjZWl2aW5nU3RyZWFtID0gcmVjZWl2aW5nU3RyZWFtXG4gICAgICAgIHRoaXMuc3RyZWFtTXNnc1tpZF0udG9Qcm9kdWNpbmdTdHJlYW0oeyBzdHJlYW1TZXF1ZW5jZU51bWJlcjogMCB9KVxuICAgICAgfSxcbiAgICApXG5cbiAgICByZWNlaXZpbmdTdHJlYW0ucmVnaXN0ZXIoXG4gICAgICAoeCkgPT4geC5zdHJlYW1TZXF1ZW5jZU51bWJlcixcbiAgICAgIChzdHJlYW1TZXF1ZW5jZU51bWJlcikgPT4ge1xuICAgICAgICAvLyBCb3VuY2UgcHJvY2Vzc2VkIG1lc3NhZ2UgdG8gcHJvZHVjaW5nIHN0cmVhbVxuICAgICAgICB0aGlzLnN0cmVhbU1zZ3Nbc3RyZWFtSWRdLnRvUHJvZHVjaW5nU3RyZWFtKHsgc3RyZWFtU2VxdWVuY2VOdW1iZXIgfSlcbiAgICAgIH0sXG4gICAgKVxuXG4gICAgcmV0dXJuIHJlY2VpdmluZ1N0cmVhbVxuICB9XG5cbiAgbG9nU3RyZWFtKCk6IE1vY2tDbGllbnREdXBsZXhTdHJlYW08TG9nTWVzc2FnZSwgbnVsbD4ge1xuICAgIGNvbnN0IGxvZ1N0cmVhbSA9IG5ldyBNb2NrQ2xpZW50RHVwbGV4U3RyZWFtPExvZ01lc3NhZ2UsIG51bGw+KClcbiAgICBsb2dTdHJlYW0ucmVnaXN0ZXIoKHgpID0+IHgsIGNvbnNvbGUubG9nKVxuICAgIHJldHVybiBsb2dTdHJlYW1cbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlUnVubmVyKHVyaSA9ICdodHRwOi8vZXhhbXBsZS5jb20vbnMjJykge1xuICBjb25zdCBsb2dnZXIgPSBjcmVhdGVMb2dnZXIoe1xuICAgIHRyYW5zcG9ydHM6IG5ldyB3aW5zdG9uLnRyYW5zcG9ydHMuQ29uc29sZSh7XG4gICAgICBsZXZlbDogcHJvY2Vzcy5lbnZbJ0RFQlVHJ10gfHwgJ2luZm8nLFxuICAgIH0pLFxuICB9KVxuXG4gIC8vIE1vY2sgdGhlIEdSUENcbiAgY29uc3QgY2xpZW50ID0gbmV3IE9yY2hlc3RyYXRvck1vY2soKVxuXG4gIC8vIENvbm5lY3QganVzdCBsaWtlIGNsaWVudC50czpzdGFydCgpXG4gIGNvbnN0IHN0cmVhbSA9IGNsaWVudC5jb25uZWN0KClcbiAgY29uc3Qgd3JpdGFibGUgPSBwcm9taXNpZnkoc3RyZWFtLndyaXRlLmJpbmQoc3RyZWFtKSlcblxuICBjb25zdCBydW5uZXIgPSBuZXcgUnVubmVyKFxuICAgIC8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnkgKi9cbiAgICBjbGllbnQgYXMgYW55LCAvLyBUeXBlIGFzc2VydGlvbiBmb3IgdGVzdGluZ1xuICAgIHdyaXRhYmxlIGFzIFdyaXRhYmxlLFxuICAgIHVyaSxcbiAgICBsb2dnZXIsXG4gIClcblxuICBzdHJlYW0ub24oJ2RhdGEnLCAobXNnOiBUb1J1bm5lcikgPT4gcnVubmVyLmhhbmRsZU9yY2hNZXNzYWdlKG1zZykpXG5cbiAgcmV0dXJuIHJ1bm5lclxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gb25lPFQ+KGl0ZXI6IEFzeW5jSXRlcmFibGU8VD4pOiBQcm9taXNlPFQgfCB1bmRlZmluZWQ+IHtcbiAgZm9yIGF3YWl0IChjb25zdCBpdGVtIG9mIGl0ZXIpIHtcbiAgICByZXR1cm4gaXRlbVxuICB9XG59XG5cbmNvbnN0IHNoYXBlUXVhZHMgPSBgXG5AcHJlZml4IHJkZmM6IDxodHRwczovL3czaWQub3JnL3JkZi1jb25uZWN0Iz4uXG5AcHJlZml4IHhzZDogPGh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hIz4uXG5AcHJlZml4IHNoOiA8aHR0cDovL3d3dy53My5vcmcvbnMvc2hhY2wjPi5cblsgXSBhIHNoOk5vZGVTaGFwZTtcbiAgc2g6dGFyZ2V0Q2xhc3MgPEpzUHJvY2Vzc29yU2hhcGU+O1xuICBzaDpwcm9wZXJ0eSBbXG4gICAgc2g6cGF0aCByZGZjOmVudHJ5cG9pbnQ7XG4gICAgc2g6bmFtZSBcImxvY2F0aW9uXCI7XG4gICAgc2g6bWluQ291bnQgMTtcbiAgICBzaDptYXhDb3VudCAxO1xuICAgIHNoOmRhdGF0eXBlIHhzZDpzdHJpbmc7XG4gIF0sIFtcbiAgICBzaDpwYXRoIHJkZmM6ZmlsZTtcbiAgICBzaDpuYW1lIFwiZmlsZVwiO1xuICAgIHNoOm1pbkNvdW50IDE7XG4gICAgc2g6bWF4Q291bnQgMTtcbiAgICBzaDpkYXRhdHlwZSB4c2Q6c3RyaW5nO1xuICBdLCBbXG4gICAgc2g6cGF0aCByZGZjOmNsYXNzO1xuICAgIHNoOm5hbWUgXCJjbGF6elwiO1xuICAgIHNoOm1heENvdW50IDE7XG4gICAgc2g6ZGF0YXR5cGUgeHNkOnN0cmluZztcbiAgXS5cbmBcbmV4cG9ydCB0eXBlIENvbmZpZ1R5cGUgPSB7XG4gIGxvY2F0aW9uOiBzdHJpbmdcbiAgZmlsZTogc3RyaW5nXG4gIGNsYXp6OiBzdHJpbmdcbn1cblxuY29uc3QgT1dMID0gY3JlYXRlVGVybU5hbWVzcGFjZSgnaHR0cDovL3d3dy53My5vcmcvMjAwMi8wNy9vd2wjJywgJ2ltcG9ydHMnKVxuY29uc3QgcHJvY2Vzc29yU2hhcGVzID0gZXh0cmFjdFNoYXBlcyhuZXcgUGFyc2VyKCkucGFyc2Uoc2hhcGVRdWFkcykpXG5jb25zdCBiYXNlID0gJ2h0dHBzOi8vdzNpZC5vcmcvcmRmLWNvbm5lY3QjJ1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaW1wb3J0RmlsZShcbiAgZmlsZTogc3RyaW5nLFxuICBjb250ZW50Pzogc3RyaW5nLFxuKTogUHJvbWlzZTxRdWFkW10+IHtcbiAgY29uc3QgZG9uZSA9IG5ldyBTZXQ8c3RyaW5nPigpXG5cbiAgY29uc3QgcXVhZHM6IFF1YWRbXSA9IFtdXG4gIGNvbnN0IHRvZG86IFVSTFtdID0gW11cblxuICBjb25zdCBwYXJzZSA9IChjb250ZW50OiBzdHJpbmcsIGJhc2VJUkk6IFVSTCkgPT4ge1xuICAgIGRvbmUuYWRkKGJhc2VJUkkudG9TdHJpbmcoKSlcblxuICAgIGNvbnN0IGV4dHJhcyA9IG5ldyBQYXJzZXIoeyBiYXNlSVJJOiBiYXNlSVJJLnRvU3RyaW5nKCkgfSkucGFyc2UoY29udGVudClcblxuICAgIGZvciAoY29uc3QgbyBvZiBleHRyYXNcbiAgICAgIC5maWx0ZXIoXG4gICAgICAgICh4KSA9PlxuICAgICAgICAgIHguc3ViamVjdC52YWx1ZSA9PT0gYmFzZUlSST8udG9TdHJpbmcoKSAmJlxuICAgICAgICAgIHgucHJlZGljYXRlLmVxdWFscyhPV0wuaW1wb3J0cyksXG4gICAgICApXG4gICAgICAubWFwKCh4KSA9PiB4Lm9iamVjdC52YWx1ZSkpIHtcbiAgICAgIHRvZG8ucHVzaChuZXcgVVJMKG8pKVxuICAgIH1cblxuICAgIHF1YWRzLnB1c2goLi4uZXh0cmFzKVxuICB9XG5cbiAgaWYgKGNvbnRlbnQpIHtcbiAgICBwYXJzZShjb250ZW50LCBuZXcgVVJMKCdmaWxlOi8vJyArIGZpbGUpKVxuICB9IGVsc2Uge1xuICAgIHRvZG8ucHVzaChuZXcgVVJMKCdmaWxlOi8vJyArIGZpbGUpKVxuICB9XG5cbiAgbGV0IGl0ZW0gPSB0b2RvLnBvcCgpXG4gIHdoaWxlIChpdGVtICE9PSB1bmRlZmluZWQpIHtcbiAgICBpZiAoZG9uZS5oYXMoaXRlbS50b1N0cmluZygpKSkge1xuICAgICAgaXRlbSA9IHRvZG8ucG9wKClcbiAgICAgIGNvbnRpbnVlXG4gICAgfVxuXG4gICAgaWYgKGl0ZW0ucHJvdG9jb2wgIT09ICdmaWxlOicpIHtcbiAgICAgIHRocm93ICdObyBzdXBwb3J0ZWQgcHJvdG9jb2wgJyArIGl0ZW0ucHJvdG9jb2xcbiAgICB9XG4gICAgY29uc3QgdHh0ID0gYXdhaXQgcmVhZEZpbGUoaXRlbS5wYXRobmFtZSwgeyBlbmNvZGluZzogJ3V0ZjgnIH0pXG4gICAgcGFyc2UodHh0LCBpdGVtKVxuXG4gICAgaXRlbSA9IHRvZG8ucG9wKClcbiAgfVxuXG4gIHJldHVybiBxdWFkc1xufVxuXG4vKipcbiAqIEhlbHBlciBjbGFzcyB0byBncmFkdWFsbHkgdGVzdCB5b3VyIHByb2Nlc3NvcnMuXG4gKiBQb3NzaWJsZSBmbG93OlxuICogLSBpbXBvcnQgdGhlIEpzUnVubmVyIGluZGV4IGZpbGVcbiAqIC0gaW1wb3J0IHlvdXIgcHJvY2Vzc29yIGNvbmZpZyBmaWxlXG4gKiAtIHRlc3QgaWYgdGhlIGNvbmZpZyBpcyBhcyB5b3Ugd291bGQgZXhwZWN0IChmcm9tIGdldENvbmZpZygpKVxuICogLSBpbXBvcnQgeW91ciBwcm9jZXNzb3IgZGVmaW5pdGlvbiAoaW5saW5lKVxuICogLSBidWlsZCB5b3VyIHByb2Nlc3NvclxuICogLSB0ZXN0IHlvdXIgcHJvY2Vzc29yXG4gKi9cbmV4cG9ydCBjbGFzcyBQcm9jSGVscGVyPFQgZXh0ZW5kcyBQcm9jZXNzb3I8dW5rbm93bj4+IHtcbiAgcnVubmVyOiBSdW5uZXJcbiAgcXVhZHM6IFF1YWRbXSA9IFtdXG4gIGNvbmZpZzogQ29uZmlnVHlwZVxuICBwcm9jOiBGdWxsUHJvYzxUPlxuXG4gIGNvbnN0cnVjdG9yKHVyaT86IHN0cmluZykge1xuICAgIHRoaXMucnVubmVyID0gY3JlYXRlUnVubmVyKHVyaSlcbiAgfVxuXG4gIGFzeW5jIGltcG9ydElubGluZShiYXNlSVJJOiBzdHJpbmcsIGNvbmZpZzogc3RyaW5nKSB7XG4gICAgY29uc3QgY29uZmlnUXVhZHMgPSBhd2FpdCBpbXBvcnRGaWxlKGJhc2VJUkksIGNvbmZpZylcbiAgICB0aGlzLnF1YWRzLnB1c2goLi4uY29uZmlnUXVhZHMpXG4gIH1cblxuICBhc3luYyBpbXBvcnRGaWxlKGZpbGU6IHN0cmluZykge1xuICAgIGNvbnN0IGNvbmZpZ1F1YWRzID0gYXdhaXQgaW1wb3J0RmlsZShmaWxlKVxuICAgIHRoaXMucXVhZHMucHVzaCguLi5jb25maWdRdWFkcylcbiAgfVxuXG4gIGdldENvbmZpZyh0eTogc3RyaW5nIHwgTmFtZWROb2RlKTogQ29uZmlnVHlwZSB7XG4gICAgY29uc3QgaWQgPSB0eXBlb2YgdHkgPT09ICdzdHJpbmcnID8gbmV3IE5hbWVkTm9kZShiYXNlICsgdHkpIDogdHlcbiAgICBjb25zdCBwcm9jQ29uZmlnID0gPENvbmZpZ1R5cGU+cHJvY2Vzc29yU2hhcGVzLmxlbnNlc1tcbiAgICAgICdKc1Byb2Nlc3NvclNoYXBlJ1xuICAgIF0uZXhlY3V0ZSh7XG4gICAgICBpZCxcbiAgICAgIHF1YWRzOiB0aGlzLnF1YWRzLFxuICAgIH0pXG5cbiAgICB0aGlzLmNvbmZpZyA9IHByb2NDb25maWdcbiAgICByZXR1cm4gcHJvY0NvbmZpZ1xuICB9XG5cbiAgYXN5bmMgZ2V0UHJvY2Vzc29yKFxuICAgIHVyaTogc3RyaW5nID0gJ2h0dHA6Ly9leGFtcGxlLmNvbS9ucyNwcm9jZXNzb3InLFxuICApOiBQcm9taXNlPEZ1bGxQcm9jPFQ+PiB7XG4gICAgYXdhaXQgdGhpcy5ydW5uZXIuaGFuZGxlT3JjaE1lc3NhZ2Uoe1xuICAgICAgcGlwZWxpbmU6IG5ldyBOM1dyaXRlcigpLnF1YWRzVG9TdHJpbmcodGhpcy5xdWFkcyksXG4gICAgfSlcblxuICAgIGNvbnN0IHByb2MgPSBhd2FpdCB0aGlzLnJ1bm5lci5hZGRQcm9jZXNzb3I8VD4oe1xuICAgICAgY29uZmlnOiBKU09OLnN0cmluZ2lmeSh0aGlzLmNvbmZpZyksXG4gICAgICBhcmd1bWVudHM6ICcnLFxuICAgICAgdXJpLFxuICAgIH0pXG4gICAgcmV0dXJuIHByb2NcbiAgfVxufVxuXG4vKipcbiAqIEBkZXByZWNhdGVkIHVzZSB7QGxpbmsgUHJvY0hlbHBlcn1cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldFByb2NJbmxpbmU8VCBleHRlbmRzIFByb2Nlc3Nvcjx1bmtub3duPj4oXG4gIGNvbmZpZzogc3RyaW5nLFxuICB0eTogc3RyaW5nLFxuICBydW5uZXI6IFJ1bm5lcixcbiAgYmFzZUlSSTogc3RyaW5nLFxuICB1cmkgPSAnaHR0cDovL2V4YW1wbGUuY29tL25zI3Byb2Nlc3NvcicsXG4pOiBQcm9taXNlPEZ1bGxQcm9jPFQ+PiB7XG4gIGNvbnN0IGNvbmZpZ1F1YWRzID0gYXdhaXQgaW1wb3J0RmlsZShiYXNlSVJJLCBjb25maWcpXG4gIGNvbnN0IHByb2NDb25maWcgPSA8UHJvY0NvbmZpZz5wcm9jZXNzb3JTaGFwZXMubGVuc2VzW1xuICAgICdKc1Byb2Nlc3NvclNoYXBlJ1xuICBdLmV4ZWN1dGUoe1xuICAgIGlkOiBuZXcgTmFtZWROb2RlKGJhc2UgKyB0eSksXG4gICAgcXVhZHM6IGNvbmZpZ1F1YWRzLFxuICB9KVxuXG4gIGF3YWl0IHJ1bm5lci5oYW5kbGVPcmNoTWVzc2FnZSh7XG4gICAgcGlwZWxpbmU6IG5ldyBOM1dyaXRlcigpLnF1YWRzVG9TdHJpbmcoY29uZmlnUXVhZHMpLFxuICB9KVxuXG4gIGNvbnN0IHByb2MgPSBhd2FpdCBydW5uZXIuYWRkUHJvY2Vzc29yPFQ+KHtcbiAgICBjb25maWc6IEpTT04uc3RyaW5naWZ5KHByb2NDb25maWcpLFxuICAgIGFyZ3VtZW50czogJycsXG4gICAgdXJpLFxuICB9KVxuXG4gIHJldHVybiBwcm9jXG59XG5cbi8qKlxuICogQGRlcHJlY2F0ZWQgdXNlIHtAbGluayBQcm9jSGVscGVyfVxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0UHJvYzxUIGV4dGVuZHMgUHJvY2Vzc29yPHVua25vd24+PihcbiAgY29uZmlnOiBzdHJpbmcsXG4gIHR5OiBzdHJpbmcsXG4gIHJ1bm5lcjogUnVubmVyLFxuICBjb25maWdMb2NhdGlvbjogc3RyaW5nLFxuICB1cmkgPSAnaHR0cDovL2V4YW1wbGUuY29tL25zI3Byb2Nlc3NvcicsXG4pOiBQcm9taXNlPEZ1bGxQcm9jPFQ+PiB7XG4gIGNvbnN0IGNvbmZpZ1F1YWRzID0gYXdhaXQgaW1wb3J0RmlsZShjb25maWdMb2NhdGlvbilcbiAgY29uc3QgcHJvY0NvbmZpZyA9IHByb2Nlc3NvclNoYXBlcy5sZW5zZXNbJ0pzUHJvY2Vzc29yU2hhcGUnXS5leGVjdXRlKHtcbiAgICBpZDogbmV3IE5hbWVkTm9kZShiYXNlICsgdHkpLFxuICAgIHF1YWRzOiBjb25maWdRdWFkcyxcbiAgfSlcblxuICBjb25maWdRdWFkcy5wdXNoKC4uLm5ldyBQYXJzZXIoKS5wYXJzZShjb25maWcpKVxuICBhd2FpdCBydW5uZXIuaGFuZGxlT3JjaE1lc3NhZ2Uoe1xuICAgIHBpcGVsaW5lOiBuZXcgTjNXcml0ZXIoKS5xdWFkc1RvU3RyaW5nKGNvbmZpZ1F1YWRzKSxcbiAgfSlcblxuICBjb25zdCBwcm9jID0gYXdhaXQgcnVubmVyLmFkZFByb2Nlc3NvcjxUPih7XG4gICAgY29uZmlnOiBKU09OLnN0cmluZ2lmeShwcm9jQ29uZmlnKSxcbiAgICBhcmd1bWVudHM6ICcnLFxuICAgIHVyaSxcbiAgfSlcblxuICByZXR1cm4gcHJvY1xufVxuIl19
@@ -3,6 +3,9 @@ import { ClientReadableStream } from '@grpc/grpc-js';
3
3
  import winston from 'winston';
4
4
  import { WriterInstance } from './writer.js';
5
5
  import { ReaderInstance } from './reader.js';
6
+ import { Processor } from './processor.js';
7
+ import { FullProc } from './runner.js';
8
+ import { Quad } from '@rdfjs/types';
6
9
  export declare function getProcessorShape(baseIRI?: string): Promise<import("rdf-lens").Shapes>;
7
10
  export declare class TestClient extends RunnerClient {
8
11
  next: (stream: ClientReadableStream<DataChunk>) => unknown;
@@ -16,3 +19,6 @@ export declare const uri = "someUri";
16
19
  export declare const logger: winston.Logger;
17
20
  export declare function createWriter(iri?: string): [WriterInstance, ReaderInstance];
18
21
  export declare function createReader(iri?: string): ReaderInstance;
22
+ export declare function importFile(file: string): Promise<Quad[]>;
23
+ export declare function getProc<T extends Processor<unknown>>(config: string, ty: string, configLocation: string, uri?: string): Promise<FullProc<T>>;
24
+ export declare function checkProcDefinition(file: string, n: string): Promise<void>;
package/lib/testUtils.js CHANGED
@@ -2,11 +2,14 @@ import { RunnerClient } from '@rdfc/proto';
2
2
  import * as grpc from '@grpc/grpc-js';
3
3
  import { ClientReadableStreamImpl } from './reexports.js';
4
4
  import { extractShapes } from 'rdf-lens';
5
- import { Parser } from 'n3';
5
+ import { NamedNode, Parser, Writer } from 'n3';
6
6
  import { readFile } from 'fs/promises';
7
7
  import winston, { createLogger } from 'winston';
8
8
  import { WriterInstance } from './writer.js';
9
9
  import { ReaderInstance } from './reader.js';
10
+ import { Runner } from './runner.js';
11
+ import { createTermNamespace } from '@treecg/types';
12
+ import { expect } from 'vitest';
10
13
  export async function getProcessorShape(baseIRI = process.cwd() + '/node_modules/@rdfc/js-runner/index.ttl') {
11
14
  const configFile = await readFile(baseIRI, { encoding: 'utf8' });
12
15
  const configQuads = new Parser().parse(configFile);
@@ -57,4 +60,91 @@ export function createReader(iri = uri) {
57
60
  const reader = new ReaderInstance(iri, client, logger);
58
61
  return reader;
59
62
  }
60
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdFV0aWxzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3Rlc3RVdGlscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQWEsWUFBWSxFQUFFLE1BQU0sYUFBYSxDQUFBO0FBRXJELE9BQU8sS0FBSyxJQUFJLE1BQU0sZUFBZSxDQUFBO0FBQ3JDLE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxNQUFNLGFBQWEsQ0FBQTtBQUN0RCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sVUFBVSxDQUFBO0FBQ3hDLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxJQUFJLENBQUE7QUFDM0IsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGFBQWEsQ0FBQTtBQUN0QyxPQUFPLE9BQU8sRUFBRSxFQUFFLFlBQVksRUFBRSxNQUFNLFNBQVMsQ0FBQTtBQUMvQyxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sVUFBVSxDQUFBO0FBQ3pDLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxVQUFVLENBQUE7QUFFekMsTUFBTSxDQUFDLEtBQUssVUFBVSxpQkFBaUIsQ0FDckMsT0FBTyxHQUFHLE9BQU8sQ0FBQyxHQUFHLEVBQUUsR0FBRyx5Q0FBeUM7SUFFbkUsTUFBTSxVQUFVLEdBQUcsTUFBTSxRQUFRLENBQUMsT0FBTyxFQUFFLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUE7SUFDaEUsTUFBTSxXQUFXLEdBQUcsSUFBSSxNQUFNLEVBQUUsQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLENBQUE7SUFDbEQsTUFBTSxNQUFNLEdBQUcsYUFBYSxDQUFDLFdBQVcsQ0FBQyxDQUFBO0lBRXpDLE9BQU8sTUFBTSxDQUFBO0FBQ2YsQ0FBQztBQUVELE1BQU0sT0FBTyxVQUFXLFNBQVEsWUFBWTtJQUMxQyxJQUFJLENBQXNEO0lBRTFEO1FBQ0UsS0FBSyxDQUFDLGdCQUFnQixFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsY0FBYyxFQUFFLENBQUMsQ0FBQTtJQUM1RCxDQUFDO0lBRUQsVUFBVTtRQUNSLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFBO0lBQ2hELENBQUM7SUFFRCxvQkFBb0I7UUFDbEIsTUFBTSxNQUFNLEdBQUcsSUFBSSx3QkFBd0IsQ0FBWSxDQUFDLElBQVksRUFBRSxFQUFFO1lBQ3RFLE9BQU8sRUFBRSxJQUFJLEVBQUUsQ0FBQTtRQUNqQixDQUFDLENBQUMsQ0FBQTtRQUNGLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUE7UUFDakIsT0FBTyxNQUFNLENBQUE7SUFDZixDQUFDO0NBQ0Y7QUFFRCxNQUFNLENBQUMsS0FBSyxVQUFVLEdBQUcsQ0FBSSxJQUFzQjtJQUNqRCxJQUFJLEtBQUssRUFBRSxNQUFNLElBQUksSUFBSSxJQUFJLEVBQUUsQ0FBQztRQUM5QixPQUFPLElBQUksQ0FBQTtJQUNiLENBQUM7QUFDSCxDQUFDO0FBRUQsTUFBTSxDQUFDLE1BQU0sTUFBTSxHQUFHLElBQUksVUFBVSxFQUFFLENBQUE7QUFDdEMsTUFBTSxDQUFDLE1BQU0sR0FBRyxHQUFHLFNBQVMsQ0FBQTtBQUM1QixNQUFNLENBQUMsTUFBTSxNQUFNLEdBQUcsWUFBWSxDQUFDO0lBQ2pDLFVBQVUsRUFBRSxJQUFJLE9BQU8sQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDO1FBQ3pDLEtBQUssRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxJQUFJLE1BQU07S0FDdEMsQ0FBQztDQUNILENBQUMsQ0FBQTtBQUVGLE1BQU0sVUFBVSxZQUFZLENBQUMsR0FBRyxHQUFHLEdBQUc7SUFDcEMsTUFBTSxNQUFNLEdBQUcsWUFBWSxDQUFDLEdBQUcsQ0FBQyxDQUFBO0lBQ2hDLE1BQU0sV0FBVyxHQUFHLElBQUksY0FBYyxDQUNwQyxHQUFHLEVBQ0gsTUFBTSxFQUNOLEtBQUssRUFBRSxHQUFHLEVBQUUsRUFBRTtRQUNaLElBQUksR0FBRyxDQUFDLEdBQUcsRUFBRSxDQUFDO1lBQ1osTUFBTSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUE7UUFDM0IsQ0FBQztRQUNELElBQUksR0FBRyxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ2QsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFBO1FBQ2hCLENBQUM7SUFDSCxDQUFDLEVBQ0QsTUFBTSxDQUNQLENBQUE7SUFDRCxPQUFPLENBQUMsV0FBVyxFQUFFLE1BQU0sQ0FBQyxDQUFBO0FBQzlCLENBQUM7QUFFRCxNQUFNLFVBQVUsWUFBWSxDQUFDLEdBQUcsR0FBRyxHQUFHO0lBQ3BDLE1BQU0sTUFBTSxHQUFHLElBQUksY0FBYyxDQUFDLEdBQUcsRUFBRSxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUE7SUFDdEQsT0FBTyxNQUFNLENBQUE7QUFDZixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRGF0YUNodW5rLCBSdW5uZXJDbGllbnQgfSBmcm9tICdAcmRmYy9wcm90bydcbmltcG9ydCB7IENsaWVudFJlYWRhYmxlU3RyZWFtIH0gZnJvbSAnQGdycGMvZ3JwYy1qcydcbmltcG9ydCAqIGFzIGdycGMgZnJvbSAnQGdycGMvZ3JwYy1qcydcbmltcG9ydCB7IENsaWVudFJlYWRhYmxlU3RyZWFtSW1wbCB9IGZyb20gJy4vcmVleHBvcnRzJ1xuaW1wb3J0IHsgZXh0cmFjdFNoYXBlcyB9IGZyb20gJ3JkZi1sZW5zJ1xuaW1wb3J0IHsgUGFyc2VyIH0gZnJvbSAnbjMnXG5pbXBvcnQgeyByZWFkRmlsZSB9IGZyb20gJ2ZzL3Byb21pc2VzJ1xuaW1wb3J0IHdpbnN0b24sIHsgY3JlYXRlTG9nZ2VyIH0gZnJvbSAnd2luc3RvbidcbmltcG9ydCB7IFdyaXRlckluc3RhbmNlIH0gZnJvbSAnLi93cml0ZXInXG5pbXBvcnQgeyBSZWFkZXJJbnN0YW5jZSB9IGZyb20gJy4vcmVhZGVyJ1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0UHJvY2Vzc29yU2hhcGUoXG4gIGJhc2VJUkkgPSBwcm9jZXNzLmN3ZCgpICsgJy9ub2RlX21vZHVsZXMvQHJkZmMvanMtcnVubmVyL2luZGV4LnR0bCcsXG4pIHtcbiAgY29uc3QgY29uZmlnRmlsZSA9IGF3YWl0IHJlYWRGaWxlKGJhc2VJUkksIHsgZW5jb2Rpbmc6ICd1dGY4JyB9KVxuICBjb25zdCBjb25maWdRdWFkcyA9IG5ldyBQYXJzZXIoKS5wYXJzZShjb25maWdGaWxlKVxuICBjb25zdCBzaGFwZXMgPSBleHRyYWN0U2hhcGVzKGNvbmZpZ1F1YWRzKVxuXG4gIHJldHVybiBzaGFwZXNcbn1cblxuZXhwb3J0IGNsYXNzIFRlc3RDbGllbnQgZXh0ZW5kcyBSdW5uZXJDbGllbnQge1xuICBuZXh0OiAoc3RyZWFtOiBDbGllbnRSZWFkYWJsZVN0cmVhbTxEYXRhQ2h1bms+KSA9PiB1bmtub3duXG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoJ2xvY2FsaG9zdDo1NDAwJywgZ3JwYy5jcmVkZW50aWFscy5jcmVhdGVJbnNlY3VyZSgpKVxuICB9XG5cbiAgbmV4dFN0cmVhbSgpOiBQcm9taXNlPENsaWVudFJlYWRhYmxlU3RyZWFtPERhdGFDaHVuaz4+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlcykgPT4gKHRoaXMubmV4dCA9IHJlcykpXG4gIH1cblxuICByZWNlaXZlU3RyZWFtTWVzc2FnZSgpOiBDbGllbnRSZWFkYWJsZVN0cmVhbTxEYXRhQ2h1bms+IHtcbiAgICBjb25zdCBzdHJlYW0gPSBuZXcgQ2xpZW50UmVhZGFibGVTdHJlYW1JbXBsPERhdGFDaHVuaz4oKGRhdGE6IEJ1ZmZlcikgPT4ge1xuICAgICAgcmV0dXJuIHsgZGF0YSB9XG4gICAgfSlcbiAgICB0aGlzLm5leHQoc3RyZWFtKVxuICAgIHJldHVybiBzdHJlYW1cbiAgfVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gb25lPFQ+KGl0ZXI6IEFzeW5jSXRlcmFibGU8VD4pOiBQcm9taXNlPFQgfCB1bmRlZmluZWQ+IHtcbiAgZm9yIGF3YWl0IChjb25zdCBpdGVtIG9mIGl0ZXIpIHtcbiAgICByZXR1cm4gaXRlbVxuICB9XG59XG5cbmV4cG9ydCBjb25zdCBjbGllbnQgPSBuZXcgVGVzdENsaWVudCgpXG5leHBvcnQgY29uc3QgdXJpID0gJ3NvbWVVcmknXG5leHBvcnQgY29uc3QgbG9nZ2VyID0gY3JlYXRlTG9nZ2VyKHtcbiAgdHJhbnNwb3J0czogbmV3IHdpbnN0b24udHJhbnNwb3J0cy5Db25zb2xlKHtcbiAgICBsZXZlbDogcHJvY2Vzcy5lbnZbJ0RFQlVHJ10gfHwgJ2luZm8nLFxuICB9KSxcbn0pXG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVXcml0ZXIoaXJpID0gdXJpKTogW1dyaXRlckluc3RhbmNlLCBSZWFkZXJJbnN0YW5jZV0ge1xuICBjb25zdCByZWFkZXIgPSBjcmVhdGVSZWFkZXIoaXJpKVxuICBjb25zdCB3cml0ZVN0cmVhbSA9IG5ldyBXcml0ZXJJbnN0YW5jZShcbiAgICBpcmksXG4gICAgY2xpZW50LFxuICAgIGFzeW5jIChtc2cpID0+IHtcbiAgICAgIGlmIChtc2cubXNnKSB7XG4gICAgICAgIHJlYWRlci5oYW5kbGVNc2cobXNnLm1zZylcbiAgICAgIH1cbiAgICAgIGlmIChtc2cuY2xvc2UpIHtcbiAgICAgICAgcmVhZGVyLmNsb3NlKClcbiAgICAgIH1cbiAgICB9LFxuICAgIGxvZ2dlcixcbiAgKVxuICByZXR1cm4gW3dyaXRlU3RyZWFtLCByZWFkZXJdXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVSZWFkZXIoaXJpID0gdXJpKTogUmVhZGVySW5zdGFuY2Uge1xuICBjb25zdCByZWFkZXIgPSBuZXcgUmVhZGVySW5zdGFuY2UoaXJpLCBjbGllbnQsIGxvZ2dlcilcbiAgcmV0dXJuIHJlYWRlclxufVxuIl19
63
+ const shapeQuads = `
64
+ @prefix rdfc: <https://w3id.org/rdf-connect#>.
65
+ @prefix xsd: <http://www.w3.org/2001/XMLSchema#>.
66
+ @prefix sh: <http://www.w3.org/ns/shacl#>.
67
+ [ ] a sh:NodeShape;
68
+ sh:targetClass <JsProcessorShape>;
69
+ sh:property [
70
+ sh:path rdfc:entrypoint;
71
+ sh:name "location";
72
+ sh:minCount 1;
73
+ sh:maxCount 1;
74
+ sh:datatype xsd:string;
75
+ ], [
76
+ sh:path rdfc:file;
77
+ sh:name "file";
78
+ sh:minCount 1;
79
+ sh:maxCount 1;
80
+ sh:datatype xsd:string;
81
+ ], [
82
+ sh:path rdfc:class;
83
+ sh:name "clazz";
84
+ sh:maxCount 1;
85
+ sh:datatype xsd:string;
86
+ ].
87
+ `;
88
+ const OWL = createTermNamespace('http://www.w3.org/2002/07/owl#', 'imports');
89
+ const processorShapes = extractShapes(new Parser().parse(shapeQuads));
90
+ const base = 'https://w3id.org/rdf-connect#';
91
+ export async function importFile(file) {
92
+ const done = new Set();
93
+ const todo = [new URL('file://' + file)];
94
+ const quads = [];
95
+ let item = todo.pop();
96
+ while (item !== undefined) {
97
+ if (done.has(item.toString())) {
98
+ item = todo.pop();
99
+ continue;
100
+ }
101
+ done.add(item.toString());
102
+ if (item.protocol !== 'file:') {
103
+ throw 'No supported protocol ' + item.protocol;
104
+ }
105
+ const txt = await readFile(item.pathname, { encoding: 'utf8' });
106
+ const extras = new Parser({ baseIRI: item.toString() }).parse(txt);
107
+ for (const o of extras
108
+ .filter((x) => x.subject.value === item?.toString() &&
109
+ x.predicate.equals(OWL.imports))
110
+ .map((x) => x.object.value)) {
111
+ todo.push(new URL(o));
112
+ }
113
+ quads.push(...extras);
114
+ item = todo.pop();
115
+ }
116
+ return quads;
117
+ }
118
+ export async function getProc(config, ty, configLocation, uri = 'http://example.com/ns#processor') {
119
+ const configQuads = await importFile(configLocation);
120
+ const procConfig = processorShapes.lenses['JsProcessorShape'].execute({
121
+ id: new NamedNode(base + ty),
122
+ quads: configQuads,
123
+ });
124
+ const msgs = [];
125
+ const write = async (x) => {
126
+ msgs.push(x);
127
+ };
128
+ const runner = new Runner(new TestClient(), write, 'http://example.com/ns#', logger);
129
+ configQuads.push(...new Parser().parse(config));
130
+ await runner.handleOrchMessage({
131
+ pipeline: new Writer().quadsToString(configQuads),
132
+ });
133
+ const proc = await runner.addProcessor({
134
+ config: JSON.stringify(procConfig),
135
+ arguments: '',
136
+ uri,
137
+ });
138
+ return proc;
139
+ }
140
+ export async function checkProcDefinition(file, n) {
141
+ const quads = await importFile(file);
142
+ const procConfig = (processorShapes.lenses['JsProcessorShape'].execute({
143
+ id: new NamedNode(base + n),
144
+ quads: quads,
145
+ }));
146
+ expect(procConfig.file, n + ' has file').toBeDefined();
147
+ expect(procConfig.location, n + ' has location').toBeDefined();
148
+ expect(procConfig.clazz, n + ' has clazz').toBeDefined();
149
+ }
150
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdFV0aWxzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3Rlc3RVdGlscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQWEsWUFBWSxFQUFFLE1BQU0sYUFBYSxDQUFBO0FBQ3JELE9BQU8sS0FBSyxJQUFJLE1BQU0sZUFBZSxDQUFBO0FBRXJDLE9BQU8sRUFBRSx3QkFBd0IsRUFBdUIsTUFBTSxhQUFhLENBQUE7QUFDM0UsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLFVBQVUsQ0FBQTtBQUN4QyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsTUFBTSxJQUFJLENBQUE7QUFDOUMsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGFBQWEsQ0FBQTtBQUN0QyxPQUFPLE9BQU8sRUFBRSxFQUFFLFlBQVksRUFBRSxNQUFNLFNBQVMsQ0FBQTtBQUMvQyxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sVUFBVSxDQUFBO0FBQ3pDLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxVQUFVLENBQUE7QUFFekMsT0FBTyxFQUFZLE1BQU0sRUFBRSxNQUFNLFVBQVUsQ0FBQTtBQUUzQyxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxlQUFlLENBQUE7QUFDbkQsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLFFBQVEsQ0FBQTtBQUUvQixNQUFNLENBQUMsS0FBSyxVQUFVLGlCQUFpQixDQUNyQyxPQUFPLEdBQUcsT0FBTyxDQUFDLEdBQUcsRUFBRSxHQUFHLHlDQUF5QztJQUVuRSxNQUFNLFVBQVUsR0FBRyxNQUFNLFFBQVEsQ0FBQyxPQUFPLEVBQUUsRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQTtJQUNoRSxNQUFNLFdBQVcsR0FBRyxJQUFJLE1BQU0sRUFBRSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQTtJQUNsRCxNQUFNLE1BQU0sR0FBRyxhQUFhLENBQUMsV0FBVyxDQUFDLENB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SSxHQUFHLE1BQU0sTUFBTSxDQUFDLFlBQVksQ0FBSTtRQUN4QyxNQUFNLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUM7UUFDbEMsU0FBUyxFQUFFLEVBQUU7UUFDYixHQUFHO0tBQ0osQ0FBQyxDQUFBO0lBRUYsT0FBTyxJQUFJLENBQUE7QUFDYixDQUFDO0FBRUQsTUFBTSxDQUFDLEtBQUssVUFBVSxtQkFBbUIsQ0FBQyxJQUFZLEVBQUUsQ0FBUztJQUMvRCxNQUFNLEtBQUssR0FBRyxNQUFNLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQTtJQUNwQyxNQUFNLFVBQVUsR0FBb0QsQ0FDbEUsZUFBZSxDQUFDLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLE9BQU8sQ0FBQztRQUNqRCxFQUFFLEVBQUUsSUFBSSxTQUFTLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQztRQUMzQixLQUFLLEVBQUUsS0FBSztLQUNiLENBQUMsQ0FDSCxDQUFBO0lBQ0QsTUFBTSxDQUFDLFVBQVUsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxHQUFHLFdBQVcsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFBO0lBQ3RELE1BQU0sQ0FBQyxVQUFVLENBQUMsUUFBUSxFQUFFLENBQUMsR0FBRyxlQUFlLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQTtJQUM5RCxNQUFNLENBQUMsVUFBVSxDQUFDLEtBQUssRUFBRSxDQUFDLEdBQUcsWUFBWSxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUE7QUFDMUQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IERhdGFDaHVuaywgUnVubmVyQ2xpZW50IH0gZnJvbSAnQHJkZmMvcHJvdG8nXG5pbXBvcnQgKiBhcyBncnBjIGZyb20gJ0BncnBjL2dycGMtanMnXG5pbXBvcnQgeyBDbGllbnRSZWFkYWJsZVN0cmVhbSB9IGZyb20gJ0BncnBjL2dycGMtanMnXG5pbXBvcnQgeyBDbGllbnRSZWFkYWJsZVN0cmVhbUltcGwsIE9yY2hlc3RyYXRvck1lc3NhZ2UgfSBmcm9tICcuL3JlZXhwb3J0cydcbmltcG9ydCB7IGV4dHJhY3RTaGFwZXMgfSBmcm9tICdyZGYtbGVucydcbmltcG9ydCB7IE5hbWVkTm9kZSwgUGFyc2VyLCBXcml0ZXIgfSBmcm9tICduMydcbmltcG9ydCB7IHJlYWRGaWxlIH0gZnJvbSAnZnMvcHJvbWlzZXMnXG5pbXBvcnQgd2luc3RvbiwgeyBjcmVhdGVMb2dnZXIgfSBmcm9tICd3aW5zdG9uJ1xuaW1wb3J0IHsgV3JpdGVySW5zdGFuY2UgfSBmcm9tICcuL3dyaXRlcidcbmltcG9ydCB7IFJlYWRlckluc3RhbmNlIH0gZnJvbSAnLi9yZWFkZXInXG5pbXBvcnQgeyBQcm9jZXNzb3IgfSBmcm9tICcuL3Byb2Nlc3NvcidcbmltcG9ydCB7IEZ1bGxQcm9jLCBSdW5uZXIgfSBmcm9tICcuL3J1bm5lcidcbmltcG9ydCB7IFF1YWQsIFRlcm0gfSBmcm9tICdAcmRmanMvdHlwZXMnXG5pbXBvcnQgeyBjcmVhdGVUZXJtTmFtZXNwYWNlIH0gZnJvbSAnQHRyZWVjZy90eXBlcydcbmltcG9ydCB7IGV4cGVjdCB9IGZyb20gJ3ZpdGVzdCdcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldFByb2Nlc3NvclNoYXBlKFxuICBiYXNlSVJJID0gcHJvY2Vzcy5jd2QoKSArICcvbm9kZV9tb2R1bGVzL0ByZGZjL2pzLXJ1bm5lci9pbmRleC50dGwnLFxuKSB7XG4gIGNvbnN0IGNvbmZpZ0ZpbGUgPSBhd2FpdCByZWFkRmlsZShiYXNlSVJJLCB7IGVuY29kaW5nOiAndXRmOCcgfSlcbiAgY29uc3QgY29uZmlnUXVhZHMgPSBuZXcgUGFyc2VyKCkucGFyc2UoY29uZmlnRmlsZSlcbiAgY29uc3Qgc2hhcGVzID0gZXh0cmFjdFNoYXBlcyhjb25maWdRdWFkcylcblxuICByZXR1cm4gc2hhcGVzXG59XG5cbmV4cG9ydCBjbGFzcyBUZXN0Q2xpZW50IGV4dGVuZHMgUnVubmVyQ2xpZW50IHtcbiAgbmV4dDogKHN0cmVhbTogQ2xpZW50UmVhZGFibGVTdHJlYW08RGF0YUNodW5rPikgPT4gdW5rbm93blxuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCdsb2NhbGhvc3Q6NTQwMCcsIGdycGMuY3JlZGVudGlhbHMuY3JlYXRlSW5zZWN1cmUoKSlcbiAgfVxuXG4gIG5leHRTdHJlYW0oKTogUHJvbWlzZTxDbGllbnRSZWFkYWJsZVN0cmVhbTxEYXRhQ2h1bms+PiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXMpID0+ICh0aGlzLm5leHQgPSByZXMpKVxuICB9XG5cbiAgcmVjZWl2ZVN0cmVhbU1lc3NhZ2UoKTogQ2xpZW50UmVhZGFibGVTdHJlYW08RGF0YUNodW5rPiB7XG4gICAgY29uc3Qgc3RyZWFtID0gbmV3IENsaWVudFJlYWRhYmxlU3RyZWFtSW1wbDxEYXRhQ2h1bms+KChkYXRhOiBCdWZmZXIpID0+IHtcbiAgICAgIHJldHVybiB7IGRhdGEgfVxuICAgIH0pXG4gICAgdGhpcy5uZXh0KHN0cmVhbSlcbiAgICByZXR1cm4gc3RyZWFtXG4gIH1cbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIG9uZTxUPihpdGVyOiBBc3luY0l0ZXJhYmxlPFQ+KTogUHJvbWlzZTxUIHwgdW5kZWZpbmVkPiB7XG4gIGZvciBhd2FpdCAoY29uc3QgaXRlbSBvZiBpdGVyKSB7XG4gICAgcmV0dXJuIGl0ZW1cbiAgfVxufVxuXG5leHBvcnQgY29uc3QgY2xpZW50ID0gbmV3IFRlc3RDbGllbnQoKVxuZXhwb3J0IGNvbnN0IHVyaSA9ICdzb21lVXJpJ1xuZXhwb3J0IGNvbnN0IGxvZ2dlciA9IGNyZWF0ZUxvZ2dlcih7XG4gIHRyYW5zcG9ydHM6IG5ldyB3aW5zdG9uLnRyYW5zcG9ydHMuQ29uc29sZSh7XG4gICAgbGV2ZWw6IHByb2Nlc3MuZW52WydERUJVRyddIHx8ICdpbmZvJyxcbiAgfSksXG59KVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlV3JpdGVyKGlyaSA9IHVyaSk6IFtXcml0ZXJJbnN0YW5jZSwgUmVhZGVySW5zdGFuY2VdIHtcbiAgY29uc3QgcmVhZGVyID0gY3JlYXRlUmVhZGVyKGlyaSlcbiAgY29uc3Qgd3JpdGVTdHJlYW0gPSBuZXcgV3JpdGVySW5zdGFuY2UoXG4gICAgaXJpLFxuICAgIGNsaWVudCxcbiAgICBhc3luYyAobXNnKSA9PiB7XG4gICAgICBpZiAobXNnLm1zZykge1xuICAgICAgICByZWFkZXIuaGFuZGxlTXNnKG1zZy5tc2cpXG4gICAgICB9XG4gICAgICBpZiAobXNnLmNsb3NlKSB7XG4gICAgICAgIHJlYWRlci5jbG9zZSgpXG4gICAgICB9XG4gICAgfSxcbiAgICBsb2dnZXIsXG4gIClcbiAgcmV0dXJuIFt3cml0ZVN0cmVhbSwgcmVhZGVyXVxufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlUmVhZGVyKGlyaSA9IHVyaSk6IFJlYWRlckluc3RhbmNlIHtcbiAgY29uc3QgcmVhZGVyID0gbmV3IFJlYWRlckluc3RhbmNlKGlyaSwgY2xpZW50LCBsb2dnZXIpXG4gIHJldHVybiByZWFkZXJcbn1cblxuY29uc3Qgc2hhcGVRdWFkcyA9IGBcbkBwcmVmaXggcmRmYzogPGh0dHBzOi8vdzNpZC5vcmcvcmRmLWNvbm5lY3QjPi5cbkBwcmVmaXggeHNkOiA8aHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEjPi5cbkBwcmVmaXggc2g6IDxodHRwOi8vd3d3LnczLm9yZy9ucy9zaGFjbCM+LlxuWyBdIGEgc2g6Tm9kZVNoYXBlO1xuICBzaDp0YXJnZXRDbGFzcyA8SnNQcm9jZXNzb3JTaGFwZT47XG4gIHNoOnByb3BlcnR5IFtcbiAgICBzaDpwYXRoIHJkZmM6ZW50cnlwb2ludDtcbiAgICBzaDpuYW1lIFwibG9jYXRpb25cIjtcbiAgICBzaDptaW5Db3VudCAxO1xuICAgIHNoOm1heENvdW50IDE7XG4gICAgc2g6ZGF0YXR5cGUgeHNkOnN0cmluZztcbiAgXSwgW1xuICAgIHNoOnBhdGggcmRmYzpmaWxlO1xuICAgIHNoOm5hbWUgXCJmaWxlXCI7XG4gICAgc2g6bWluQ291bnQgMTtcbiAgICBzaDptYXhDb3VudCAxO1xuICAgIHNoOmRhdGF0eXBlIHhzZDpzdHJpbmc7XG4gIF0sIFtcbiAgICBzaDpwYXRoIHJkZmM6Y2xhc3M7XG4gICAgc2g6bmFtZSBcImNsYXp6XCI7XG4gICAgc2g6bWF4Q291bnQgMTtcbiAgICBzaDpkYXRhdHlwZSB4c2Q6c3RyaW5nO1xuICBdLlxuYFxuY29uc3QgT1dMID0gY3JlYXRlVGVybU5hbWVzcGFjZSgnaHR0cDovL3d3dy53My5vcmcvMjAwMi8wNy9vd2wjJywgJ2ltcG9ydHMnKVxuY29uc3QgcHJvY2Vzc29yU2hhcGVzID0gZXh0cmFjdFNoYXBlcyhuZXcgUGFyc2VyKCkucGFyc2Uoc2hhcGVRdWFkcykpXG5jb25zdCBiYXNlID0gJ2h0dHBzOi8vdzNpZC5vcmcvcmRmLWNvbm5lY3QjJ1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaW1wb3J0RmlsZShmaWxlOiBzdHJpbmcpOiBQcm9taXNlPFF1YWRbXT4ge1xuICBjb25zdCBkb25lID0gbmV3IFNldDxzdHJpbmc+KClcbiAgY29uc3QgdG9kbyA9IFtuZXcgVVJMKCdmaWxlOi8vJyArIGZpbGUpXVxuICBjb25zdCBxdWFkczogUXVhZFtdID0gW11cblxuICBsZXQgaXRlbSA9IHRvZG8ucG9wKClcbiAgd2hpbGUgKGl0ZW0gIT09IHVuZGVmaW5lZCkge1xuICAgIGlmIChkb25lLmhhcyhpdGVtLnRvU3RyaW5nKCkpKSB7XG4gICAgICBpdGVtID0gdG9kby5wb3AoKVxuICAgICAgY29udGludWVcbiAgICB9XG4gICAgZG9uZS5hZGQoaXRlbS50b1N0cmluZygpKVxuICAgIGlmIChpdGVtLnByb3RvY29sICE9PSAnZmlsZTonKSB7XG4gICAgICB0aHJvdyAnTm8gc3VwcG9ydGVkIHByb3RvY29sICcgKyBpdGVtLnByb3RvY29sXG4gICAgfVxuXG4gICAgY29uc3QgdHh0ID0gYXdhaXQgcmVhZEZpbGUoaXRlbS5wYXRobmFtZSwgeyBlbmNvZGluZzogJ3V0ZjgnIH0pXG4gICAgY29uc3QgZXh0cmFzID0gbmV3IFBhcnNlcih7IGJhc2VJUkk6IGl0ZW0udG9TdHJpbmcoKSB9KS5wYXJzZSh0eHQpXG5cbiAgICBmb3IgKGNvbnN0IG8gb2YgZXh0cmFzXG4gICAgICAuZmlsdGVyKFxuICAgICAgICAoeCkgPT5cbiAgICAgICAgICB4LnN1YmplY3QudmFsdWUgPT09IGl0ZW0/LnRvU3RyaW5nKCkgJiZcbiAgICAgICAgICB4LnByZWRpY2F0ZS5lcXVhbHMoT1dMLmltcG9ydHMpLFxuICAgICAgKVxuICAgICAgLm1hcCgoeCkgPT4geC5vYmplY3QudmFsdWUpKSB7XG4gICAgICB0b2RvLnB1c2gobmV3IFVSTChvKSlcbiAgICB9XG4gICAgcXVhZHMucHVzaCguLi5leHRyYXMpXG5cbiAgICBpdGVtID0gdG9kby5wb3AoKVxuICB9XG5cbiAgcmV0dXJuIHF1YWRzXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRQcm9jPFQgZXh0ZW5kcyBQcm9jZXNzb3I8dW5rbm93bj4+KFxuICBjb25maWc6IHN0cmluZyxcbiAgdHk6IHN0cmluZyxcbiAgY29uZmlnTG9jYXRpb246IHN0cmluZyxcbiAgdXJpID0gJ2h0dHA6Ly9leGFtcGxlLmNvbS9ucyNwcm9jZXNzb3InLFxuKTogUHJvbWlzZTxGdWxsUHJvYzxUPj4ge1xuICBjb25zdCBjb25maWdRdWFkcyA9IGF3YWl0IGltcG9ydEZpbGUoY29uZmlnTG9jYXRpb24pXG4gIGNvbnN0IHByb2NDb25maWcgPSBwcm9jZXNzb3JTaGFwZXMubGVuc2VzWydKc1Byb2Nlc3NvclNoYXBlJ10uZXhlY3V0ZSh7XG4gICAgaWQ6IG5ldyBOYW1lZE5vZGUoYmFzZSArIHR5KSxcbiAgICBxdWFkczogY29uZmlnUXVhZHMsXG4gIH0pXG5cbiAgY29uc3QgbXNnczogT3JjaGVzdHJhdG9yTWVzc2FnZVtdID0gW11cbiAgY29uc3Qgd3JpdGUgPSBhc3luYyAoeDogT3JjaGVzdHJhdG9yTWVzc2FnZSkgPT4ge1xuICAgIG1zZ3MucHVzaCh4KVxuICB9XG4gIGNvbnN0IHJ1bm5lciA9IG5ldyBSdW5uZXIoXG4gICAgbmV3IFRlc3RDbGllbnQoKSxcbiAgICB3cml0ZSxcbiAgICAnaHR0cDovL2V4YW1wbGUuY29tL25zIycsXG4gICAgbG9nZ2VyLFxuICApXG4gIGNvbmZpZ1F1YWRzLnB1c2goLi4ubmV3IFBhcnNlcigpLnBhcnNlKGNvbmZpZykpXG4gIGF3YWl0IHJ1bm5lci5oYW5kbGVPcmNoTWVzc2FnZSh7XG4gICAgcGlwZWxpbmU6IG5ldyBXcml0ZXIoKS5xdWFkc1RvU3RyaW5nKGNvbmZpZ1F1YWRzKSxcbiAgfSlcblxuICBjb25zdCBwcm9jID0gYXdhaXQgcnVubmVyLmFkZFByb2Nlc3NvcjxUPih7XG4gICAgY29uZmlnOiBKU09OLnN0cmluZ2lmeShwcm9jQ29uZmlnKSxcbiAgICBhcmd1bWVudHM6ICcnLFxuICAgIHVyaSxcbiAgfSlcblxuICByZXR1cm4gcHJvY1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY2hlY2tQcm9jRGVmaW5pdGlvbihmaWxlOiBzdHJpbmcsIG46IHN0cmluZykge1xuICBjb25zdCBxdWFkcyA9IGF3YWl0IGltcG9ydEZpbGUoZmlsZSlcbiAgY29uc3QgcHJvY0NvbmZpZyA9IDx7IGZpbGU6IFRlcm07IGxvY2F0aW9uOiBzdHJpbmc7IGNsYXp6OiBzdHJpbmcgfT4oXG4gICAgcHJvY2Vzc29yU2hhcGVzLmxlbnNlc1snSnNQcm9jZXNzb3JTaGFwZSddLmV4ZWN1dGUoe1xuICAgICAgaWQ6IG5ldyBOYW1lZE5vZGUoYmFzZSArIG4pLFxuICAgICAgcXVhZHM6IHF1YWRzLFxuICAgIH0pXG4gIClcbiAgZXhwZWN0KHByb2NDb25maWcuZmlsZSwgbiArICcgaGFzIGZpbGUnKS50b0JlRGVmaW5lZCgpXG4gIGV4cGVjdChwcm9jQ29uZmlnLmxvY2F0aW9uLCBuICsgJyBoYXMgbG9jYXRpb24nKS50b0JlRGVmaW5lZCgpXG4gIGV4cGVjdChwcm9jQ29uZmlnLmNsYXp6LCBuICsgJyBoYXMgY2xhenonKS50b0JlRGVmaW5lZCgpXG59XG4iXX0=