@archont561/qgis-sdk 0.0.0 → 0.4.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.
@@ -0,0 +1,366 @@
1
+ import {
2
+ HOST_SCHEMA_VERSION2,
3
+ HOST_OPERATIONS2
4
+ } from "./shared/chunk-vqyymknv.js";
5
+ import {
6
+ QgisSdkError2
7
+ } from "./shared/chunk-2hwva3a3.js";
8
+
9
+ // src/testing.ts
10
+ var PROTOCOL = 1;
11
+ var SUBSCRIPTION_CAPACITY = 64;
12
+ function fault(code, message) {
13
+ return Object.freeze({ fault: Object.freeze({ code, message }) });
14
+ }
15
+ function isFault(value) {
16
+ return typeof value === "object" && value !== null && "fault" in value && typeof value.fault === "object";
17
+ }
18
+ var SILENCE = Symbol("qgis-sdk-harness-silence");
19
+
20
+ class QgisSdkBridgeHarnessError extends QgisSdkError2 {
21
+ constructor(message) {
22
+ super(message, "harness_error");
23
+ }
24
+ }
25
+
26
+ class Harness {
27
+ granted;
28
+ plugin;
29
+ listenerSet = new Set;
30
+ expectations = [];
31
+ recorded = [];
32
+ unexpectedCalls = [];
33
+ streams = new Map;
34
+ problems = [];
35
+ outbox = [];
36
+ draining = null;
37
+ streamCounter = 0;
38
+ constructor(options, plugin) {
39
+ this.granted = Object.freeze([...options.granted ?? HOST_OPERATIONS2]);
40
+ this.plugin = plugin;
41
+ }
42
+ get calls() {
43
+ return [...this.recorded];
44
+ }
45
+ get unexpected() {
46
+ return [...this.unexpectedCalls];
47
+ }
48
+ get openSubscriptions() {
49
+ return [...this.streams.values()].filter((stream) => stream.open).map((stream) => stream.id);
50
+ }
51
+ get listeners() {
52
+ return this.listenerSet.size;
53
+ }
54
+ subscribe(listener) {
55
+ this.listenerSet.add(listener);
56
+ return () => {
57
+ this.listenerSet.delete(listener);
58
+ if (this.listenerSet.size === 0) {
59
+ for (const stream of this.streams.values()) {
60
+ stream.open = false;
61
+ }
62
+ }
63
+ };
64
+ }
65
+ send(message) {
66
+ const envelope = this.parseEnvelope(message);
67
+ if (envelope.kind === "unsubscribe") {
68
+ this.closeFromPage(envelope);
69
+ return;
70
+ }
71
+ if (envelope.kind === "handshake") {
72
+ this.answerHandshake(envelope);
73
+ return;
74
+ }
75
+ const expectation = this.take(envelope.kind, envelope.operation);
76
+ if (expectation === undefined) {
77
+ this.unexpectedCalls.push(envelope);
78
+ this.deliverFailure(envelope.callId, "unexpected_call", `no expectation covers ${envelope.kind} ${JSON.stringify(envelope.operation)}`);
79
+ return;
80
+ }
81
+ if (expectation.kind === "invoke") {
82
+ this.answerInvoke(envelope, expectation);
83
+ return;
84
+ }
85
+ this.answerSubscribe(envelope, expectation);
86
+ }
87
+ expectInvoke(operation, handler) {
88
+ this.expectations.push({
89
+ kind: "invoke",
90
+ operation,
91
+ handler
92
+ });
93
+ }
94
+ expectSubscribe(operation, script, options = {}) {
95
+ this.expectations.push({
96
+ kind: "subscribe",
97
+ operation,
98
+ script,
99
+ options
100
+ });
101
+ }
102
+ deliver(raw) {
103
+ this.outbox.push(raw);
104
+ this.drain();
105
+ }
106
+ settled() {
107
+ return this.draining ?? Promise.resolve();
108
+ }
109
+ assertSatisfied() {
110
+ const problems = [...this.problems];
111
+ if (this.expectations.length > 0) {
112
+ const unmet = this.expectations.map((expectation) => `${expectation.kind} ${expectation.operation}`);
113
+ problems.push(`unmet expectations: ${unmet.join(", ")}`);
114
+ }
115
+ if (this.unexpectedCalls.length > 0) {
116
+ const unexpected = this.unexpectedCalls.map((call) => `${call.kind} ${call.operation}`);
117
+ problems.push(`unexpected calls: ${unexpected.join(", ")}`);
118
+ }
119
+ const open = this.openSubscriptions;
120
+ if (open.length > 0) {
121
+ problems.push(`open subscriptions: ${open.join(", ")}`);
122
+ }
123
+ if (problems.length > 0) {
124
+ throw new QgisSdkBridgeHarnessError(problems.join("; "));
125
+ }
126
+ }
127
+ answerHandshake(call) {
128
+ const declared = [
129
+ ...(this.plugin?.actions ?? []).map((action) => action.id),
130
+ ...(this.plugin?.streams ?? []).map((stream) => stream.id)
131
+ ];
132
+ this.deliver({
133
+ protocol: PROTOCOL,
134
+ call_id: call.callId,
135
+ ok: true,
136
+ value: {
137
+ protocol: PROTOCOL,
138
+ generation: 0,
139
+ plugin: this.plugin,
140
+ host_schema_version: HOST_SCHEMA_VERSION2,
141
+ operations: [...declared, ...this.granted].map((id) => ({
142
+ id,
143
+ title: id
144
+ }))
145
+ }
146
+ });
147
+ }
148
+ answerInvoke(call, expectation) {
149
+ this.resolveHandler(call, () => expectation.handler(call.payload ?? {})).then((reply) => {
150
+ if (reply === SILENCE) {
151
+ return;
152
+ }
153
+ if (isFault(reply)) {
154
+ this.deliverFailure(call.callId, reply.fault.code, reply.fault.message);
155
+ return;
156
+ }
157
+ this.deliver({
158
+ protocol: PROTOCOL,
159
+ call_id: call.callId,
160
+ ok: true,
161
+ value: reply
162
+ });
163
+ });
164
+ }
165
+ answerSubscribe(call, expectation) {
166
+ this.streamCounter += 1;
167
+ const open = {
168
+ id: `s${this.streamCounter}`,
169
+ operation: call.operation,
170
+ seq: 0,
171
+ open: false
172
+ };
173
+ const held = [];
174
+ let sink = (frame) => {
175
+ held.push(frame);
176
+ };
177
+ const stream = this.scripted(open, (frame) => sink(frame));
178
+ const ack = expectation.options.ack ?? (() => Promise.resolve());
179
+ ack().then(() => this.resolveHandler(call, () => {
180
+ open.open = true;
181
+ return expectation.script(call.payload ?? {}, stream);
182
+ })).then((outcome) => {
183
+ if (outcome === SILENCE || isFault(outcome)) {
184
+ open.open = false;
185
+ held.length = 0;
186
+ if (isFault(outcome)) {
187
+ this.deliverFailure(call.callId, outcome.fault.code, outcome.fault.message);
188
+ }
189
+ return;
190
+ }
191
+ if (this.listenerSet.size === 0) {
192
+ open.open = false;
193
+ held.length = 0;
194
+ return;
195
+ }
196
+ this.streams.set(open.id, open);
197
+ this.deliver({
198
+ protocol: PROTOCOL,
199
+ call_id: call.callId,
200
+ ok: true,
201
+ value: {
202
+ subscription_id: open.id,
203
+ capacity: SUBSCRIPTION_CAPACITY
204
+ }
205
+ });
206
+ sink = (frame) => this.deliver(frame);
207
+ for (const frame of held) {
208
+ sink(frame);
209
+ }
210
+ held.length = 0;
211
+ });
212
+ }
213
+ resolveHandler(call, run) {
214
+ return new Promise((resolve) => {
215
+ resolve(run());
216
+ }).catch((error) => {
217
+ const message = error instanceof Error ? error.message : String(error);
218
+ this.problems.push(`handler for ${call.kind} ${call.operation} threw: ${message}`);
219
+ return fault("harness_error", message);
220
+ });
221
+ }
222
+ scripted(open, sink) {
223
+ const requireOpen = (verb) => {
224
+ if (!open.open) {
225
+ throw new QgisSdkBridgeHarnessError(`cannot ${verb} on subscription ${open.id}: it is not open`);
226
+ }
227
+ };
228
+ return {
229
+ id: open.id,
230
+ operation: open.operation,
231
+ get open() {
232
+ return open.open;
233
+ },
234
+ emit: (kind, payload) => {
235
+ requireOpen("emit");
236
+ sink({
237
+ protocol: PROTOCOL,
238
+ subscription_id: open.id,
239
+ seq: open.seq,
240
+ event: { kind, payload }
241
+ });
242
+ open.seq += 1;
243
+ },
244
+ end: (terminal) => {
245
+ requireOpen("end");
246
+ open.open = false;
247
+ sink({
248
+ protocol: PROTOCOL,
249
+ subscription_id: open.id,
250
+ seq: open.seq,
251
+ terminal
252
+ });
253
+ open.seq += 1;
254
+ },
255
+ skip: (frames) => {
256
+ requireOpen("skip");
257
+ open.seq += frames;
258
+ }
259
+ };
260
+ }
261
+ closeFromPage(call) {
262
+ const open = call.subscriptionId === undefined ? undefined : this.streams.get(call.subscriptionId);
263
+ const disposed = open?.open === true;
264
+ if (open !== undefined) {
265
+ open.open = false;
266
+ }
267
+ this.deliver({
268
+ protocol: PROTOCOL,
269
+ call_id: call.callId,
270
+ ok: true,
271
+ value: { disposed }
272
+ });
273
+ }
274
+ deliverFailure(callId, code, message) {
275
+ this.deliver({
276
+ protocol: PROTOCOL,
277
+ call_id: callId,
278
+ ok: false,
279
+ error: { code, message }
280
+ });
281
+ }
282
+ drain() {
283
+ if (this.draining !== null) {
284
+ return;
285
+ }
286
+ this.draining = (async () => {
287
+ while (this.outbox.length > 0) {
288
+ await Promise.resolve();
289
+ const message = this.outbox.shift();
290
+ for (const listener of [...this.listenerSet]) {
291
+ listener(message);
292
+ }
293
+ }
294
+ this.draining = null;
295
+ })();
296
+ }
297
+ take(kind, operation) {
298
+ const index = this.expectations.findIndex((expectation) => expectation.kind === kind && expectation.operation === operation);
299
+ if (index === -1) {
300
+ return;
301
+ }
302
+ return this.expectations.splice(index, 1)[0];
303
+ }
304
+ parseEnvelope(message) {
305
+ if (typeof message !== "object" || message === null) {
306
+ throw new QgisSdkBridgeHarnessError("the client sent a non-object");
307
+ }
308
+ const raw = message;
309
+ if (raw.protocol !== PROTOCOL) {
310
+ throw new QgisSdkBridgeHarnessError(`the client speaks protocol ${String(raw.protocol)}; the harness fakes ${PROTOCOL}`);
311
+ }
312
+ if (typeof raw.call_id !== "string" || raw.call_id.length === 0) {
313
+ throw new QgisSdkBridgeHarnessError("the client sent no call_id");
314
+ }
315
+ const callId = raw.call_id;
316
+ if (raw.kind === "unsubscribe") {
317
+ const subscriptionId = raw.subscription_id;
318
+ if (typeof subscriptionId !== "string") {
319
+ throw new QgisSdkBridgeHarnessError(`${callId}: unsubscribe names no subscription_id`);
320
+ }
321
+ const call = {
322
+ callId,
323
+ kind: "unsubscribe",
324
+ operation: this.streams.get(subscriptionId)?.operation ?? "",
325
+ subscriptionId
326
+ };
327
+ this.recorded.push(call);
328
+ return call;
329
+ }
330
+ if (raw.kind === "handshake") {
331
+ const call = { callId, kind: "handshake", operation: "" };
332
+ this.recorded.push(call);
333
+ return call;
334
+ }
335
+ if (raw.kind !== "invoke" && raw.kind !== "subscribe") {
336
+ throw new QgisSdkBridgeHarnessError(`${callId}: ${String(raw.kind)} is not a bridge envelope kind`);
337
+ }
338
+ if (typeof raw.operation !== "string") {
339
+ throw new QgisSdkBridgeHarnessError(`${callId}: operation must be a string`);
340
+ }
341
+ const payload = typeof raw.payload === "object" && raw.payload !== null ? raw.payload : {};
342
+ const call = {
343
+ callId,
344
+ kind: raw.kind,
345
+ operation: raw.operation,
346
+ payload
347
+ };
348
+ this.recorded.push(call);
349
+ return call;
350
+ }
351
+ }
352
+ function createBridgeHarness(first = {}, second = {}) {
353
+ if ("schema_version" in first) {
354
+ return new Harness(second, first);
355
+ }
356
+ return new Harness(first, null);
357
+ }
358
+ export {
359
+ QgisSdkBridgeHarnessError,
360
+ SILENCE,
361
+ createBridgeHarness,
362
+ fault
363
+ };
364
+
365
+ //# debugId=A423121C49C80BCD64756E2164756E21
366
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsic3JjL3Rlc3RpbmcudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbCiAgICAiLyoqXG4gKiBBbiBpbmplY3RlZCBwZXItY2xpZW50IGhhcm5lc3MgZm9yIHRoZSBicmlkZ2UgKFRBU0stMTgsIGRlY2lzaW9uLTIzKS5cbiAqXG4gKiBUaGUgaGFybmVzcyBpcyBhIHtAbGluayBXaXJlVHJhbnNwb3J0fTogYSBwYWdlJ3Mgb3duIGBCcmlkZ2VDbGllbnRgIHNwZWFrcyB0b1xuICogaXQgZXhhY3RseSBhcyBpdCB3b3VsZCB0byBhIFFXZWJDaGFubmVsLCBhbmQgYSB0ZXN0IHNjcmlwdHMgd2hhdCB0aGUgaG9zdFxuICogYW5zd2VycyAtIHR5cGVkIHJlcGxpZXMsIGZhdWx0cywgc2lsZW5jZSwgc3RyZWFtIGV2ZW50cywgdGVybWluYWxzLCBnYXBzIC1cbiAqIHdpdGhvdXQgdG91Y2hpbmcgYSBicm93c2VyIGdsb2JhbCBvciBhIHJ1bm5pbmcgUUdJUy4gVHdvIGhhcm5lc3NlcyBhcmUgdHdvXG4gKiBob3N0cywgc28gaXNvbGF0aW9uIGJldHdlZW4gY2xpZW50cyBpcyBhIGZhY3QgYSB0ZXN0IGNhbiBwcm92ZS5cbiAqXG4gKiBXaGF0IGl0IHByb3ZlcyBpcyBib3VuZGVkLiBBIGdyZWVuIHRlc3QgaGVyZSBzYXlzIHRoZSBwYWdlIGhhbmRsZXMgdGhlXG4gKiBmcmFtZXMgYSBob3N0ICpjb3VsZCogc2VuZDsgaXQgc2F5cyBub3RoaW5nIGFib3V0IHdoYXQgYSBRV2ViRW5naW5lVmlldyBvclxuICogYSByZWFsIGhvc3QgZG9lcy4gVGhhdCBldmlkZW5jZSBsaXZlcyBpbiB0aGUgUHl0aG9uIHN1aXRlIGFuZCBpbiB0aGVcbiAqIHF1YWxpZmljYXRpb24gaGFybmVzc2VzIHJlY29yZGVkIGluIGRvYy0xNC4gS2VlcCB0aGUgdHdvIGFwYXJ0IGluIHJlcG9ydHMuXG4gKlxuICogRXZlcnl0aGluZyB0aGUgaGFybmVzcyBzZW5kcyBpcyBkZWxpdmVyZWQgYXN5bmNocm9ub3VzbHksIG9uZSBtZXNzYWdlIHBlclxuICogbWljcm90YXNrLCBzbyBhIHJlcGx5IG5ldmVyIHJlLWVudGVycyB0aGUgY2xpZW50IGluc2lkZSBpdHMgb3duIGBzZW5kYC5cbiAqL1xuXG5pbXBvcnQgdHlwZSB7XG5cdEJyaWRnZVN0cmVhbVRlcm1pbmFsLFxuXHRTdHJlYW1FdmVudEtpbmQsXG5cdFdpcmVUcmFuc3BvcnQsXG59IGZyb20gXCIuL2JyaWRnZVwiO1xuaW1wb3J0IHsgUWdpc1Nka0Vycm9yIH0gZnJvbSBcIi4vZXJyb3JzXCI7XG5pbXBvcnQge1xuXHRIT1NUX09QRVJBVElPTlMsXG5cdEhPU1RfU0NIRU1BX1ZFUlNJT04sXG5cdHR5cGUgSG9zdE9wZXJhdGlvbklkLFxufSBmcm9tIFwiLi9nZW5lcmF0ZWQvaG9zdFwiO1xuaW1wb3J0IHR5cGUgeyBCcmlkZ2VTY2hlbWEsIE9wZXJhdGlvblNoYXBlLCBTdHJlYW1TaGFwZSB9IGZyb20gXCIuL3NjaGVtYVwiO1xuXG5jb25zdCBQUk9UT0NPTCA9IDE7XG5jb25zdCBTVUJTQ1JJUFRJT05fQ0FQQUNJVFkgPSA2NDtcblxuLyoqIEEgc2NyaXB0ZWQgaG9zdCBmYWlsdXJlLCByZXR1cm5lZCBmcm9tIGFuIGV4cGVjdGF0aW9uJ3MgaGFuZGxlci4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2NyaXB0ZWRGYXVsdCB7XG5cdHJlYWRvbmx5IGZhdWx0OiB7IHJlYWRvbmx5IGNvZGU6IHN0cmluZzsgcmVhZG9ubHkgbWVzc2FnZTogc3RyaW5nIH07XG59XG5cbi8qKiBTY3JpcHQgYSBmYWlsdXJlIHJlcGx5IHdpdGggdGhpcyBjb2RlIGFuZCBtZXNzYWdlLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZhdWx0KGNvZGU6IHN0cmluZywgbWVzc2FnZTogc3RyaW5nKTogU2NyaXB0ZWRGYXVsdCB7XG5cdHJldHVybiBPYmplY3QuZnJlZXplKHsgZmF1bHQ6IE9iamVjdC5mcmVlemUoeyBjb2RlLCBtZXNzYWdlIH0pIH0pO1xufVxuXG5mdW5jdGlvbiBpc0ZhdWx0KHZhbHVlOiB1bmtub3duKTogdmFsdWUgaXMgU2NyaXB0ZWRGYXVsdCB7XG5cdHJldHVybiAoXG5cdFx0dHlwZW9mIHZhbHVlID09PSBcIm9iamVjdFwiICYmXG5cdFx0dmFsdWUgIT09IG51bGwgJiZcblx0XHRcImZhdWx0XCIgaW4gdmFsdWUgJiZcblx0XHR0eXBlb2YgKHZhbHVlIGFzIFNjcmlwdGVkRmF1bHQpLmZhdWx0ID09PSBcIm9iamVjdFwiXG5cdCk7XG59XG5cbi8qKiBSZXR1cm4gdGhpcyBmcm9tIGEgaGFuZGxlciB0byBuZXZlciBhbnN3ZXIsIHNvIHRoZSBjbGllbnQncyB0aW1lb3V0IHNwZWFrcy4gKi9cbmV4cG9ydCBjb25zdCBTSUxFTkNFOiB1bmlxdWUgc3ltYm9sID0gU3ltYm9sKFwicWdpcy1zZGstaGFybmVzcy1zaWxlbmNlXCIpO1xuXG4vKiogQSBzdWJzY3JpcHRpb24gdGhlIHNjcmlwdCB0dXJucyBkb3duOiBhIGZhdWx0IHJlcGx5LCBvciBubyByZXBseSBhdCBhbGwuICovXG5leHBvcnQgdHlwZSBTY3JpcHRlZFJlZnVzYWwgPSBTY3JpcHRlZEZhdWx0IHwgdHlwZW9mIFNJTEVOQ0U7XG5cbi8qKlxuICogQSBzdWJzY3JpYmUgZXhwZWN0YXRpb24ncyBzY3JpcHQ6IGVtaXQgb24gYHN0cmVhbWAgbm93IG9yIGxhdGVyLCBvciByZXR1cm5cbiAqIGEgcmVmdXNhbCBpbnN0ZWFkIG9mIGFja25vd2xlZGdpbmcuXG4gKi9cbmV4cG9ydCB0eXBlIFN1YnNjcmliZVNjcmlwdDxSZXEgZXh0ZW5kcyBvYmplY3Q+ID0gKFxuXHRwYXlsb2FkOiBSZXEsXG5cdHN0cmVhbTogU2NyaXB0ZWRTdHJlYW0sXG5cdC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9Db25mdXNpbmdWb2lkVHlwZTogYSBzY3JpcHQgdGhhdCBvbmx5IGVtaXRzIHJldHVybnMgbm90aGluZ1xuKSA9PiBTY3JpcHRlZFJlZnVzYWwgfCB2b2lkO1xuXG4vKiogV2hhdCBhbiBpbnZva2UgZXhwZWN0YXRpb24gbWF5IGFuc3dlciB3aXRoLiAqL1xuZXhwb3J0IHR5cGUgU2NyaXB0ZWRSZXBseTxSZXM+ID1cblx0fCBSZXNcblx0fCBTY3JpcHRlZEZhdWx0XG5cdHwgdHlwZW9mIFNJTEVOQ0Vcblx0fCBQcm9taXNlPFJlcyB8IFNjcmlwdGVkRmF1bHQgfCB0eXBlb2YgU0lMRU5DRT47XG5cbi8qKiBBIG1lc3NhZ2UgdGhlIGNsaWVudCBzZW50LCBhcyB0aGUgaGFybmVzcyByZWNvcmRlZCBpdC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVjb3JkZWRDYWxsIHtcblx0cmVhZG9ubHkgY2FsbElkOiBzdHJpbmc7XG5cdHJlYWRvbmx5IGtpbmQ6IFwiaW52b2tlXCIgfCBcInN1YnNjcmliZVwiIHwgXCJ1bnN1YnNjcmliZVwiIHwgXCJoYW5kc2hha2VcIjtcblx0LyoqIEVtcHR5IGZvciBhIGhhbmRzaGFrZSwgd2hpY2ggbmFtZXMgbm8gb3BlcmF0aW9uLiAqL1xuXHRyZWFkb25seSBvcGVyYXRpb246IHN0cmluZztcblx0cmVhZG9ubHkgcGF5bG9hZD86IFJlYWRvbmx5PFJlY29yZDxzdHJpbmcsIHVua25vd24+Pjtcblx0cmVhZG9ubHkgc3Vic2NyaXB0aW9uSWQ/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogT25lIHNjcmlwdGVkIHN1YnNjcmlwdGlvbi4gRnJhbWVzIGNhcnJ5IHRoZSBzZXF1ZW5jZSB0aGUga2VybmVsIGNoZWNrcywgc29cbiAqIGBza2lwYCBpcyB0aGUgb25lIHdheSB0byBzY3JpcHQgYSBnYXAuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2NyaXB0ZWRTdHJlYW0ge1xuXHRyZWFkb25seSBpZDogc3RyaW5nO1xuXHRyZWFkb25seSBvcGVyYXRpb246IHN0cmluZztcblx0LyoqIGBmYWxzZWAgb25jZSB0aGUgaG9zdCBlbmRlZCBpdCBvciB0aGUgcGFnZSBjbG9zZWQgaXQuICovXG5cdHJlYWRvbmx5IG9wZW46IGJvb2xlYW47XG5cdGVtaXQoa2luZDogU3RyZWFtRXZlbnRLaW5kLCBwYXlsb2FkOiB1bmtub3duKTogdm9pZDtcblx0ZW5kKHRlcm1pbmFsOiBCcmlkZ2VTdHJlYW1UZXJtaW5hbCk6IHZvaWQ7XG5cdC8qKiBBZHZhbmNlIHRoZSBzZXF1ZW5jZSB3aXRob3V0IHNlbmRpbmcsIHNvIHRoZSBuZXh0IGZyYW1lIGlzIGEgZ2FwLiAqL1xuXHRza2lwKGZyYW1lczogbnVtYmVyKTogdm9pZDtcbn1cblxuLyoqIE9wdGlvbnMgZm9yIGEgc3Vic2NyaWJlIGV4cGVjdGF0aW9uLiAqL1xuZXhwb3J0IGludGVyZmFjZSBTdWJzY3JpYmVPcHRpb25zIHtcblx0LyoqIERlbGF5IHRoZSBhY2tub3dsZWRnZW1lbnQgdW50aWwgdGhpcyBwcm9taXNlIHNldHRsZXMuICovXG5cdHJlYWRvbmx5IGFjaz86ICgpID0+IFByb21pc2U8dm9pZD47XG59XG5cbi8qKiBPcHRpb25zIGZvciB7QGxpbmsgY3JlYXRlQnJpZGdlSGFybmVzc30uICovXG5leHBvcnQgaW50ZXJmYWNlIEhhcm5lc3NPcHRpb25zIHtcblx0LyoqXG5cdCAqIFRoZSBob3N0IG9wZXJhdGlvbiBpZHMgdGhlIHNjcmlwdGVkIGhhbmRzaGFrZSBhZHZlcnRpc2VzOyBldmVyeSBjdXJhdGVkXG5cdCAqIGlkIGJ5IGRlZmF1bHQuIEEgbmFycm93ZWQgbGlzdCBpcyBob3cgYSB0ZXN0IHByb3ZlcyBhIHBhZ2UgcmVzcGVjdHNcblx0ICogYHFnaXMuaG9zdC5ncmFudGVkYCAoVEFTSy02NiBBQyAjNSkuIEEgY2FsbCBvdXRzaWRlIGl0IGlzIHN0aWxsIGFuc3dlcmVkXG5cdCAqIGJ5IHdoYXRldmVyIHRoZSB0ZXN0IHNjcmlwdGVkIC0gdHlwaWNhbGx5IGBmYXVsdChcIm5vdF9hdXRob3JpemVkXCIsIC4uLilgIC1cblx0ICogYmVjYXVzZSB0aGF0IHJlZnVzYWwgaXMgdGhlIGhvc3Qncywgbm90IHRoZSBoYXJuZXNzJ3MuXG5cdCAqL1xuXHRyZWFkb25seSBncmFudGVkPzogcmVhZG9ubHkgSG9zdE9wZXJhdGlvbklkW107XG59XG5cbi8qKlxuICogQSB0ZXN0J3Mgc2NyaXB0IHdlbnQgd3Jvbmc6IGFuIHVubWV0IG9yIHVuZXhwZWN0ZWQgY2FsbCwgYSBsZWFrZWRcbiAqIHN1YnNjcmlwdGlvbiwgYSBoYW5kbGVyIHRoYXQgdGhyZXcsIG9yIGFuIGVudmVsb3BlIHRoYXQgaXMgbm90IHByb3RvY29sIDEuXG4gKi9cbmV4cG9ydCBjbGFzcyBRZ2lzU2RrQnJpZGdlSGFybmVzc0Vycm9yIGV4dGVuZHMgUWdpc1Nka0Vycm9yIHtcblx0cHVibGljIGNvbnN0cnVjdG9yKG1lc3NhZ2U6IHN0cmluZykge1xuXHRcdHN1cGVyKG1lc3NhZ2UsIFwiaGFybmVzc19lcnJvclwiKTtcblx0fVxufVxuXG5pbnRlcmZhY2UgSW52b2tlRXhwZWN0YXRpb24ge1xuXHRyZWFkb25seSBraW5kOiBcImludm9rZVwiO1xuXHRyZWFkb25seSBvcGVyYXRpb246IHN0cmluZztcblx0cmVhZG9ubHkgaGFuZGxlcjogKHBheWxvYWQ6IFJlYWRvbmx5PFJlY29yZDxzdHJpbmcsIHVua25vd24+PikgPT4gdW5rbm93bjtcbn1cblxuaW50ZXJmYWNlIFN1YnNjcmliZUV4cGVjdGF0aW9uIHtcblx0cmVhZG9ubHkga2luZDogXCJzdWJzY3JpYmVcIjtcblx0cmVhZG9ubHkgb3BlcmF0aW9uOiBzdHJpbmc7XG5cdHJlYWRvbmx5IHNjcmlwdDogU3Vic2NyaWJlU2NyaXB0PFJlYWRvbmx5PFJlY29yZDxzdHJpbmcsIHVua25vd24+Pj47XG5cdHJlYWRvbmx5IG9wdGlvbnM6IFN1YnNjcmliZU9wdGlvbnM7XG59XG5cbnR5cGUgRXhwZWN0YXRpb24gPSBJbnZva2VFeHBlY3RhdGlvbiB8IFN1YnNjcmliZUV4cGVjdGF0aW9uO1xuXG5pbnRlcmZhY2UgT3BlblN0cmVhbSB7XG5cdHJlYWRvbmx5IGlkOiBzdHJpbmc7XG5cdHJlYWRvbmx5IG9wZXJhdGlvbjogc3RyaW5nO1xuXHRzZXE6IG51bWJlcjtcblx0b3BlbjogYm9vbGVhbjtcbn1cblxuLyoqIFRoZSBoYXJuZXNzIGEgdGVzdCBob2xkczsgYWxzbyB0aGUgdHJhbnNwb3J0IGl0cyBjbGllbnQgaXMgYnVpbHQgb24uICovXG5leHBvcnQgaW50ZXJmYWNlIEJyaWRnZUhhcm5lc3M8T3AgZXh0ZW5kcyBzdHJpbmcgPSBzdHJpbmc+XG5cdGV4dGVuZHMgV2lyZVRyYW5zcG9ydCB7XG5cdC8qKiBFdmVyeSBtZXNzYWdlIHRoZSBjbGllbnQgc2VudCwgaW4gb3JkZXIuICovXG5cdHJlYWRvbmx5IGNhbGxzOiByZWFkb25seSBSZWNvcmRlZENhbGxbXTtcblx0LyoqIENhbGxzIG5vIGV4cGVjdGF0aW9uIGNvdmVyZWQ7IGVhY2ggd2FzIGFuc3dlcmVkIGB1bmV4cGVjdGVkX2NhbGxgLiAqL1xuXHRyZWFkb25seSB1bmV4cGVjdGVkOiByZWFkb25seSBSZWNvcmRlZENhbGxbXTtcblx0LyoqIFN1YnNjcmlwdGlvbnMgbmVpdGhlciBlbmRlZCBieSBhIHNjcmlwdCBub3IgY2xvc2VkIGJ5IHRoZSBwYWdlLiAqL1xuXHRyZWFkb25seSBvcGVuU3Vic2NyaXB0aW9uczogcmVhZG9ubHkgc3RyaW5nW107XG5cdC8qKiBDbGllbnRzIGN1cnJlbnRseSBhdHRhY2hlZC4gKi9cblx0cmVhZG9ubHkgbGlzdGVuZXJzOiBudW1iZXI7XG5cdC8qKiBBbnN3ZXIgdGhlIG5leHQgYG9wZXJhdGlvbmAgY2FsbCB3aXRoIHdoYXQgYGhhbmRsZXJgIHJldHVybnMuICovXG5cdGV4cGVjdEludm9rZTxcblx0XHRSZXEgZXh0ZW5kcyBvYmplY3QgPSBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4sXG5cdFx0UmVzID0gdW5rbm93bixcblx0PihvcGVyYXRpb246IE9wLCBoYW5kbGVyOiAocGF5bG9hZDogUmVxKSA9PiBTY3JpcHRlZFJlcGx5PFJlcz4pOiB2b2lkO1xuXHQvKipcblx0ICogQWNrbm93bGVkZ2UgdGhlIG5leHQgYG9wZXJhdGlvbmAgc3Vic2NyaXB0aW9uIGFuZCBoYW5kIGBzY3JpcHRgIHRoZVxuXHQgKiBzdHJlYW07IHJldHVybiBhIGZhdWx0IG9yIHtAbGluayBTSUxFTkNFfSBmcm9tIGl0IHRvIHJlZnVzZSBpbnN0ZWFkLlxuXHQgKi9cblx0ZXhwZWN0U3Vic2NyaWJlPFJlcSBleHRlbmRzIG9iamVjdCA9IFJlYWRvbmx5PFJlY29yZDxzdHJpbmcsIHVua25vd24+Pj4oXG5cdFx0b3BlcmF0aW9uOiBPcCxcblx0XHRzY3JpcHQ6IFN1YnNjcmliZVNjcmlwdDxSZXE+LFxuXHRcdG9wdGlvbnM/OiBTdWJzY3JpYmVPcHRpb25zLFxuXHQpOiB2b2lkO1xuXHQvKiogUHVzaCBhbnkgcmF3IG1lc3NhZ2UsIGZvciB3aGF0IG5vIGV4cGVjdGF0aW9uIGNhbiBzY3JpcHQuICovXG5cdGRlbGl2ZXIocmF3OiB1bmtub3duKTogdm9pZDtcblx0LyoqIFJlc29sdmUgb25jZSBldmVyeXRoaW5nIHF1ZXVlZCBzbyBmYXIgaGFzIGJlZW4gZGVsaXZlcmVkLiAqL1xuXHRzZXR0bGVkKCk6IFByb21pc2U8dm9pZD47XG5cdC8qKiBUaHJvdyB1bmxlc3MgZXZlcnkgZXhwZWN0YXRpb24gd2FzIG1ldCBhbmQgbm90aGluZyBsZWFrZWQuICovXG5cdGFzc2VydFNhdGlzZmllZCgpOiB2b2lkO1xufVxuXG4vKipcbiAqIFRoZSBoYXJuZXNzIHtAbGluayBjcmVhdGVCcmlkZ2VIYXJuZXNzfSByZXR1cm5zIGZvciBhIHNjaGVtYTogdGhlIHNhbWVcbiAqIGhhcm5lc3MsIHdpdGggYGV4cGVjdEludm9rZWAgYW5kIGBleHBlY3RTdWJzY3JpYmVgIHR5cGVkIGJ5IHRoZSBzY2hlbWEnc1xuICogYE9wZXJhdGlvbnNgIGFuZCBgU3RyZWFtc2AgLSBhIHBheWxvYWQgaXMgdGhlIGRlY2xhcmVkIHJlcXVlc3QsIGEgcmVwbHkgdGhlXG4gKiBkZWNsYXJlZCByZXN1bHQgLSBhbmQgYnkgdGhlIGN1cmF0ZWQgaG9zdCBpZHMsIHdob3NlIHNoYXBlcyB0aGUgaG9zdCBtb2R1bGVcbiAqIG93bnMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2NoZW1hQnJpZGdlSGFybmVzczxPLCBTPlxuXHRleHRlbmRzIE9taXQ8XG5cdFx0QnJpZGdlSGFybmVzczxFeHRyYWN0PGtleW9mIE8gfCBrZXlvZiBTLCBzdHJpbmc+IHwgSG9zdE9wZXJhdGlvbklkPixcblx0XHRcImV4cGVjdEludm9rZVwiIHwgXCJleHBlY3RTdWJzY3JpYmVcIlxuXHQ+IHtcblx0ZXhwZWN0SW52b2tlPEsgZXh0ZW5kcyBFeHRyYWN0PGtleW9mIE8sIHN0cmluZz4+KFxuXHRcdG9wZXJhdGlvbjogSyxcblx0XHRoYW5kbGVyOiAoXG5cdFx0XHRwYXlsb2FkOiBPW0tdIGV4dGVuZHMgT3BlcmF0aW9uU2hhcGUgPyBPW0tdW1wicmVxdWVzdFwiXSA6IG5ldmVyLFxuXHRcdCkgPT4gU2NyaXB0ZWRSZXBseTxPW0tdIGV4dGVuZHMgT3BlcmF0aW9uU2hhcGUgPyBPW0tdW1wicmVzdWx0XCJdIDogbmV2ZXI+LFxuXHQpOiB2b2lkO1xuXHRleHBlY3RJbnZva2U8XG5cdFx0UmVxIGV4dGVuZHMgb2JqZWN0ID0gUmVhZG9ubHk8UmVjb3JkPHN0cmluZywgdW5rbm93bj4+LFxuXHRcdFJlcyA9IHVua25vd24sXG5cdD4oXG5cdFx0b3BlcmF0aW9uOiBIb3N0T3BlcmF0aW9uSWQsXG5cdFx0aGFuZGxlcjogKHBheWxvYWQ6IFJlcSkgPT4gU2NyaXB0ZWRSZXBseTxSZXM+LFxuXHQpOiB2b2lkO1xuXHRleHBlY3RTdWJzY3JpYmU8SyBleHRlbmRzIEV4dHJhY3Q8a2V5b2YgUywgc3RyaW5nPj4oXG5cdFx0b3BlcmF0aW9uOiBLLFxuXHRcdHNjcmlwdDogU3Vic2NyaWJlU2NyaXB0PFNbS10gZXh0ZW5kcyBTdHJlYW1TaGFwZSA/IFNbS11bXCJyZXF1ZXN0XCJdIDogbmV2ZXI+LFxuXHRcdG9wdGlvbnM/OiBTdWJzY3JpYmVPcHRpb25zLFxuXHQpOiB2b2lkO1xuXHRleHBlY3RTdWJzY3JpYmU8UmVxIGV4dGVuZHMgb2JqZWN0ID0gUmVhZG9ubHk8UmVjb3JkPHN0cmluZywgdW5rbm93bj4+Pihcblx0XHRvcGVyYXRpb246IEhvc3RPcGVyYXRpb25JZCxcblx0XHRzY3JpcHQ6IFN1YnNjcmliZVNjcmlwdDxSZXE+LFxuXHRcdG9wdGlvbnM/OiBTdWJzY3JpYmVPcHRpb25zLFxuXHQpOiB2b2lkO1xufVxuXG5jbGFzcyBIYXJuZXNzPE9wIGV4dGVuZHMgc3RyaW5nPiBpbXBsZW1lbnRzIEJyaWRnZUhhcm5lc3M8T3A+IHtcblx0cHJpdmF0ZSByZWFkb25seSBncmFudGVkOiByZWFkb25seSBIb3N0T3BlcmF0aW9uSWRbXTtcblx0cHJpdmF0ZSByZWFkb25seSBwbHVnaW46IEJyaWRnZVNjaGVtYSB8IG51bGw7XG5cdHByaXZhdGUgcmVhZG9ubHkgbGlzdGVuZXJTZXQgPSBuZXcgU2V0PChtZXNzYWdlOiB1bmtub3duKSA9PiB2b2lkPigpO1xuXHRwcml2YXRlIHJlYWRvbmx5IGV4cGVjdGF0aW9uczogRXhwZWN0YXRpb25bXSA9IFtdO1xuXHRwcml2YXRlIHJlYWRvbmx5IHJlY29yZGVkOiBSZWNvcmRlZENhbGxbXSA9IFtdO1xuXHRwcml2YXRlIHJlYWRvbmx5IHVuZXhwZWN0ZWRDYWxsczogUmVjb3JkZWRDYWxsW10gPSBbXTtcblx0cHJpdmF0ZSByZWFkb25seSBzdHJlYW1zID0gbmV3IE1hcDxzdHJpbmcsIE9wZW5TdHJlYW0+KCk7XG5cdHByaXZhdGUgcmVhZG9ubHkgcHJvYmxlbXM6IHN0cmluZ1tdID0gW107XG5cdHByaXZhdGUgcmVhZG9ubHkgb3V0Ym94OiB1bmtub3duW10gPSBbXTtcblx0cHJpdmF0ZSBkcmFpbmluZzogUHJvbWlzZTx2b2lkPiB8IG51bGwgPSBudWxsO1xuXHRwcml2YXRlIHN0cmVhbUNvdW50ZXIgPSAwO1xuXG5cdHB1YmxpYyBjb25zdHJ1Y3RvcihvcHRpb25zOiBIYXJuZXNzT3B0aW9ucywgcGx1Z2luOiBCcmlkZ2VTY2hlbWEgfCBudWxsKSB7XG5cdFx0dGhpcy5ncmFudGVkID0gT2JqZWN0LmZyZWV6ZShbLi4uKG9wdGlvbnMuZ3JhbnRlZCA/PyBIT1NUX09QRVJBVElPTlMpXSk7XG5cdFx0dGhpcy5wbHVnaW4gPSBwbHVnaW47XG5cdH1cblxuXHRwdWJsaWMgZ2V0IGNhbGxzKCk6IHJlYWRvbmx5IFJlY29yZGVkQ2FsbFtdIHtcblx0XHRyZXR1cm4gWy4uLnRoaXMucmVjb3JkZWRdO1xuXHR9XG5cblx0cHVibGljIGdldCB1bmV4cGVjdGVkKCk6IHJlYWRvbmx5IFJlY29yZGVkQ2FsbFtdIHtcblx0XHRyZXR1cm4gWy4uLnRoaXMudW5leHBlY3RlZENhbGxzXTtcblx0fVxuXG5cdHB1YmxpYyBnZXQgb3BlblN1YnNjcmlwdGlvbnMoKTogcmVhZG9ubHkgc3RyaW5nW10ge1xuXHRcdHJldHVybiBbLi4udGhpcy5zdHJlYW1zLnZhbHVlcygpXVxuXHRcdFx0LmZpbHRlcigoc3RyZWFtKSA9PiBzdHJlYW0ub3Blbilcblx0XHRcdC5tYXAoKHN0cmVhbSkgPT4gc3RyZWFtLmlkKTtcblx0fVxuXG5cdHB1YmxpYyBnZXQgbGlzdGVuZXJzKCk6IG51bWJlciB7XG5cdFx0cmV0dXJuIHRoaXMubGlzdGVuZXJTZXQuc2l6ZTtcblx0fVxuXG5cdHB1YmxpYyBzdWJzY3JpYmUobGlzdGVuZXI6IChtZXNzYWdlOiB1bmtub3duKSA9PiB2b2lkKTogKCkgPT4gdm9pZCB7XG5cdFx0dGhpcy5saXN0ZW5lclNldC5hZGQobGlzdGVuZXIpO1xuXHRcdHJldHVybiAoKSA9PiB7XG5cdFx0XHR0aGlzLmxpc3RlbmVyU2V0LmRlbGV0ZShsaXN0ZW5lcik7XG5cdFx0XHRpZiAodGhpcy5saXN0ZW5lclNldC5zaXplID09PSAwKSB7XG5cdFx0XHRcdC8vIFRoZSBsYXN0IGNsaWVudCBkZXRhY2hlZDogdGhlIHZpZXcgaXMgZ29uZSwgYW5kIGEgaG9zdCBkaXNwb3Nlc1xuXHRcdFx0XHQvLyB0aGUgc3Vic2NyaXB0aW9ucyBvZiBhIHZpZXcgaXQgbG9zdCAoZGVjaXNpb24tMjMpLCBzbyB0aGV5IGFyZVxuXHRcdFx0XHQvLyBubyBsb25nZXIgbGVha3MuXG5cdFx0XHRcdGZvciAoY29uc3Qgc3RyZWFtIG9mIHRoaXMuc3RyZWFtcy52YWx1ZXMoKSkge1xuXHRcdFx0XHRcdHN0cmVhbS5vcGVuID0gZmFsc2U7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9O1xuXHR9XG5cblx0cHVibGljIHNlbmQobWVzc2FnZTogdW5rbm93bik6IHZvaWQge1xuXHRcdGNvbnN0IGVudmVsb3BlID0gdGhpcy5wYXJzZUVudmVsb3BlKG1lc3NhZ2UpO1xuXHRcdGlmIChlbnZlbG9wZS5raW5kID09PSBcInVuc3Vic2NyaWJlXCIpIHtcblx0XHRcdHRoaXMuY2xvc2VGcm9tUGFnZShlbnZlbG9wZSk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdGlmIChlbnZlbG9wZS5raW5kID09PSBcImhhbmRzaGFrZVwiKSB7XG5cdFx0XHR0aGlzLmFuc3dlckhhbmRzaGFrZShlbnZlbG9wZSk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdGNvbnN0IGV4cGVjdGF0aW9uID0gdGhpcy50YWtlKGVudmVsb3BlLmtpbmQsIGVudmVsb3BlLm9wZXJhdGlvbik7XG5cdFx0aWYgKGV4cGVjdGF0aW9uID09PSB1bmRlZmluZWQpIHtcblx0XHRcdHRoaXMudW5leHBlY3RlZENhbGxzLnB1c2goZW52ZWxvcGUpO1xuXHRcdFx0dGhpcy5kZWxpdmVyRmFpbHVyZShcblx0XHRcdFx0ZW52ZWxvcGUuY2FsbElkLFxuXHRcdFx0XHRcInVuZXhwZWN0ZWRfY2FsbFwiLFxuXHRcdFx0XHRgbm8gZXhwZWN0YXRpb24gY292ZXJzICR7ZW52ZWxvcGUua2luZH0gJHtKU09OLnN0cmluZ2lmeShlbnZlbG9wZS5vcGVyYXRpb24pfWAsXG5cdFx0XHQpO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHRpZiAoZXhwZWN0YXRpb24ua2luZCA9PT0gXCJpbnZva2VcIikge1xuXHRcdFx0dGhpcy5hbnN3ZXJJbnZva2UoZW52ZWxvcGUsIGV4cGVjdGF0aW9uKTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0dGhpcy5hbnN3ZXJTdWJzY3JpYmUoZW52ZWxvcGUsIGV4cGVjdGF0aW9uKTtcblx0fVxuXG5cdHB1YmxpYyBleHBlY3RJbnZva2U8UmVxIGV4dGVuZHMgb2JqZWN0LCBSZXM+KFxuXHRcdG9wZXJhdGlvbjogT3AsXG5cdFx0aGFuZGxlcjogKHBheWxvYWQ6IFJlcSkgPT4gU2NyaXB0ZWRSZXBseTxSZXM+LFxuXHQpOiB2b2lkIHtcblx0XHR0aGlzLmV4cGVjdGF0aW9ucy5wdXNoKHtcblx0XHRcdGtpbmQ6IFwiaW52b2tlXCIsXG5cdFx0XHRvcGVyYXRpb24sXG5cdFx0XHRoYW5kbGVyOiBoYW5kbGVyIGFzIEludm9rZUV4cGVjdGF0aW9uW1wiaGFuZGxlclwiXSxcblx0XHR9KTtcblx0fVxuXG5cdHB1YmxpYyBleHBlY3RTdWJzY3JpYmU8UmVxIGV4dGVuZHMgb2JqZWN0Pihcblx0XHRvcGVyYXRpb246IE9wLFxuXHRcdHNjcmlwdDogU3Vic2NyaWJlU2NyaXB0PFJlcT4sXG5cdFx0b3B0aW9uczogU3Vic2NyaWJlT3B0aW9ucyA9IHt9LFxuXHQpOiB2b2lkIHtcblx0XHR0aGlzLmV4cGVjdGF0aW9ucy5wdXNoKHtcblx0XHRcdGtpbmQ6IFwic3Vic2NyaWJlXCIsXG5cdFx0XHRvcGVyYXRpb24sXG5cdFx0XHRzY3JpcHQ6IHNjcmlwdCBhcyBTdWJzY3JpYmVFeHBlY3RhdGlvbltcInNjcmlwdFwiXSxcblx0XHRcdG9wdGlvbnMsXG5cdFx0fSk7XG5cdH1cblxuXHRwdWJsaWMgZGVsaXZlcihyYXc6IHVua25vd24pOiB2b2lkIHtcblx0XHR0aGlzLm91dGJveC5wdXNoKHJhdyk7XG5cdFx0dGhpcy5kcmFpbigpO1xuXHR9XG5cblx0cHVibGljIHNldHRsZWQoKTogUHJvbWlzZTx2b2lkPiB7XG5cdFx0cmV0dXJuIHRoaXMuZHJhaW5pbmcgPz8gUHJvbWlzZS5yZXNvbHZlKCk7XG5cdH1cblxuXHRwdWJsaWMgYXNzZXJ0U2F0aXNmaWVkKCk6IHZvaWQge1xuXHRcdGNvbnN0IHByb2JsZW1zID0gWy4uLnRoaXMucHJvYmxlbXNdO1xuXHRcdGlmICh0aGlzLmV4cGVjdGF0aW9ucy5sZW5ndGggPiAwKSB7XG5cdFx0XHRjb25zdCB1bm1ldCA9IHRoaXMuZXhwZWN0YXRpb25zLm1hcChcblx0XHRcdFx0KGV4cGVjdGF0aW9uKSA9PiBgJHtleHBlY3RhdGlvbi5raW5kfSAke2V4cGVjdGF0aW9uLm9wZXJhdGlvbn1gLFxuXHRcdFx0KTtcblx0XHRcdHByb2JsZW1zLnB1c2goYHVubWV0IGV4cGVjdGF0aW9uczogJHt1bm1ldC5qb2luKFwiLCBcIil9YCk7XG5cdFx0fVxuXHRcdGlmICh0aGlzLnVuZXhwZWN0ZWRDYWxscy5sZW5ndGggPiAwKSB7XG5cdFx0XHRjb25zdCB1bmV4cGVjdGVkID0gdGhpcy51bmV4cGVjdGVkQ2FsbHMubWFwKFxuXHRcdFx0XHQoY2FsbCkgPT4gYCR7Y2FsbC5raW5kfSAke2NhbGwub3BlcmF0aW9ufWAsXG5cdFx0XHQpO1xuXHRcdFx0cHJvYmxlbXMucHVzaChgdW5leHBlY3RlZCBjYWxsczogJHt1bmV4cGVjdGVkLmpvaW4oXCIsIFwiKX1gKTtcblx0XHR9XG5cdFx0Y29uc3Qgb3BlbiA9IHRoaXMub3BlblN1YnNjcmlwdGlvbnM7XG5cdFx0aWYgKG9wZW4ubGVuZ3RoID4gMCkge1xuXHRcdFx0cHJvYmxlbXMucHVzaChgb3BlbiBzdWJzY3JpcHRpb25zOiAke29wZW4uam9pbihcIiwgXCIpfWApO1xuXHRcdH1cblx0XHRpZiAocHJvYmxlbXMubGVuZ3RoID4gMCkge1xuXHRcdFx0dGhyb3cgbmV3IFFnaXNTZGtCcmlkZ2VIYXJuZXNzRXJyb3IocHJvYmxlbXMuam9pbihcIjsgXCIpKTtcblx0XHR9XG5cdH1cblxuXHQvLyAtLSBhbnN3ZXJpbmcgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0LyoqXG5cdCAqIEFuc3dlciB0aGUgaGFuZHNoYWtlIHRoZSB3YXkgYERpc3BhdGNoZXJgIGRvZXM6IHRoZSBwbHVnaW4gZGVzY3JpcHRpb25cblx0ICogdGhlIGhhcm5lc3Mgd2FzIGJ1aWx0IGZyb20gKG9yIG5vbmUpIGFuZCB0aGUgYWR2ZXJ0aXNlZCBvcGVyYXRpb24gaWRzIC1cblx0ICogdGhlIHBsdWdpbidzLCB0aGVuIHRoZSBncmFudGVkIGhvc3QgaWRzLiBObyBleHBlY3RhdGlvbiBpcyBjb25zdW1lZDogYVxuXHQgKiBoYW5kc2hha2UgaXMgdGhlIFNESydzIGZpcnN0IG1lc3NhZ2UsIG5vdCBzb21ldGhpbmcgYSB0ZXN0IHNjcmlwdHMuXG5cdCAqL1xuXHRwcml2YXRlIGFuc3dlckhhbmRzaGFrZShjYWxsOiBSZWNvcmRlZENhbGwpOiB2b2lkIHtcblx0XHRjb25zdCBkZWNsYXJlZCA9IFtcblx0XHRcdC4uLih0aGlzLnBsdWdpbj8uYWN0aW9ucyA/PyBbXSkubWFwKChhY3Rpb24pID0+IGFjdGlvbi5pZCksXG5cdFx0XHQuLi4odGhpcy5wbHVnaW4/LnN0cmVhbXMgPz8gW10pLm1hcCgoc3RyZWFtKSA9PiBzdHJlYW0uaWQpLFxuXHRcdF07XG5cdFx0dGhpcy5kZWxpdmVyKHtcblx0XHRcdHByb3RvY29sOiBQUk9UT0NPTCxcblx0XHRcdGNhbGxfaWQ6IGNhbGwuY2FsbElkLFxuXHRcdFx0b2s6IHRydWUsXG5cdFx0XHR2YWx1ZToge1xuXHRcdFx0XHRwcm90b2NvbDogUFJPVE9DT0wsXG5cdFx0XHRcdGdlbmVyYXRpb246IDAsXG5cdFx0XHRcdHBsdWdpbjogdGhpcy5wbHVnaW4sXG5cdFx0XHRcdGhvc3Rfc2NoZW1hX3ZlcnNpb246IEhPU1RfU0NIRU1BX1ZFUlNJT04sXG5cdFx0XHRcdG9wZXJhdGlvbnM6IFsuLi5kZWNsYXJlZCwgLi4udGhpcy5ncmFudGVkXS5tYXAoKGlkKSA9PiAoe1xuXHRcdFx0XHRcdGlkLFxuXHRcdFx0XHRcdHRpdGxlOiBpZCxcblx0XHRcdFx0fSkpLFxuXHRcdFx0fSxcblx0XHR9KTtcblx0fVxuXG5cdHByaXZhdGUgYW5zd2VySW52b2tlKFxuXHRcdGNhbGw6IFJlY29yZGVkQ2FsbCxcblx0XHRleHBlY3RhdGlvbjogSW52b2tlRXhwZWN0YXRpb24sXG5cdCk6IHZvaWQge1xuXHRcdHRoaXMucmVzb2x2ZUhhbmRsZXIoY2FsbCwgKCkgPT5cblx0XHRcdGV4cGVjdGF0aW9uLmhhbmRsZXIoY2FsbC5wYXlsb2FkID8/IHt9KSxcblx0XHQpLnRoZW4oKHJlcGx5KSA9PiB7XG5cdFx0XHRpZiAocmVwbHkgPT09IFNJTEVOQ0UpIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXHRcdFx0aWYgKGlzRmF1bHQocmVwbHkpKSB7XG5cdFx0XHRcdHRoaXMuZGVsaXZlckZhaWx1cmUoY2FsbC5jYWxsSWQsIHJlcGx5LmZhdWx0LmNvZGUsIHJlcGx5LmZhdWx0Lm1lc3NhZ2UpO1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cdFx0XHR0aGlzLmRlbGl2ZXIoe1xuXHRcdFx0XHRwcm90b2NvbDogUFJPVE9DT0wsXG5cdFx0XHRcdGNhbGxfaWQ6IGNhbGwuY2FsbElkLFxuXHRcdFx0XHRvazogdHJ1ZSxcblx0XHRcdFx0dmFsdWU6IHJlcGx5LFxuXHRcdFx0fSk7XG5cdFx0fSk7XG5cdH1cblxuXHRwcml2YXRlIGFuc3dlclN1YnNjcmliZShcblx0XHRjYWxsOiBSZWNvcmRlZENhbGwsXG5cdFx0ZXhwZWN0YXRpb246IFN1YnNjcmliZUV4cGVjdGF0aW9uLFxuXHQpOiB2b2lkIHtcblx0XHR0aGlzLnN0cmVhbUNvdW50ZXIgKz0gMTtcblx0XHRjb25zdCBvcGVuOiBPcGVuU3RyZWFtID0ge1xuXHRcdFx0aWQ6IGBzJHt0aGlzLnN0cmVhbUNvdW50ZXJ9YCxcblx0XHRcdG9wZXJhdGlvbjogY2FsbC5vcGVyYXRpb24sXG5cdFx0XHRzZXE6IDAsXG5cdFx0XHRvcGVuOiBmYWxzZSxcblx0XHR9O1xuXHRcdC8vIEZyYW1lcyB0aGUgc2NyaXB0IGVtaXRzIGJlZm9yZSB0aGUgYWNrbm93bGVkZ2VtZW50IGlzIGRlY2lkZWQgYXJlIGhlbGRcblx0XHQvLyBiYWNrOiBhIHJlZnVzZWQgc3Vic2NyaXB0aW9uIHNlbmRzIG5vbmUsIGFuIGFjY2VwdGVkIG9uZSBzZW5kcyB0aGVtXG5cdFx0Ly8gYWZ0ZXIgdGhlIGFja25vd2xlZGdlbWVudCwgc28gdGhlIGtlcm5lbCBoYXMgcmVnaXN0ZXJlZCB0aGVcblx0XHQvLyBzdWJzY3JpcHRpb24gYnkgdGhlIHRpbWUgdGhlIGZpcnN0IGZyYW1lIHJlYWNoZXMgaXQuXG5cdFx0Y29uc3QgaGVsZDogdW5rbm93bltdID0gW107XG5cdFx0bGV0IHNpbmsgPSAoZnJhbWU6IHVua25vd24pOiB2b2lkID0+IHtcblx0XHRcdGhlbGQucHVzaChmcmFtZSk7XG5cdFx0fTtcblx0XHRjb25zdCBzdHJlYW0gPSB0aGlzLnNjcmlwdGVkKG9wZW4sIChmcmFtZSkgPT4gc2luayhmcmFtZSkpO1xuXHRcdGNvbnN0IGFjayA9IGV4cGVjdGF0aW9uLm9wdGlvbnMuYWNrID8/ICgoKSA9PiBQcm9taXNlLnJlc29sdmUoKSk7XG5cdFx0YWNrKClcblx0XHRcdC50aGVuKCgpID0+XG5cdFx0XHRcdHRoaXMucmVzb2x2ZUhhbmRsZXIoY2FsbCwgKCkgPT4ge1xuXHRcdFx0XHRcdG9wZW4ub3BlbiA9IHRydWU7XG5cdFx0XHRcdFx0cmV0dXJuIGV4cGVjdGF0aW9uLnNjcmlwdChjYWxsLnBheWxvYWQgPz8ge30sIHN0cmVhbSk7XG5cdFx0XHRcdH0pLFxuXHRcdFx0KVxuXHRcdFx0LnRoZW4oKG91dGNvbWUpID0+IHtcblx0XHRcdFx0aWYgKG91dGNvbWUgPT09IFNJTEVOQ0UgfHwgaXNGYXVsdChvdXRjb21lKSkge1xuXHRcdFx0XHRcdG9wZW4ub3BlbiA9IGZhbHNlO1xuXHRcdFx0XHRcdGhlbGQubGVuZ3RoID0gMDtcblx0XHRcdFx0XHRpZiAoaXNGYXVsdChvdXRjb21lKSkge1xuXHRcdFx0XHRcdFx0dGhpcy5kZWxpdmVyRmFpbHVyZShcblx0XHRcdFx0XHRcdFx0Y2FsbC5jYWxsSWQsXG5cdFx0XHRcdFx0XHRcdG91dGNvbWUuZmF1bHQuY29kZSxcblx0XHRcdFx0XHRcdFx0b3V0Y29tZS5mYXVsdC5tZXNzYWdlLFxuXHRcdFx0XHRcdFx0KTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmICh0aGlzLmxpc3RlbmVyU2V0LnNpemUgPT09IDApIHtcblx0XHRcdFx0XHQvLyBUaGUgdmlldyBkZXRhY2hlZCB3aGlsZSB0aGUgaG9zdCB3YXMgZGVjaWRpbmc6IG5vdGhpbmcgdG9cblx0XHRcdFx0XHQvLyBhY2tub3dsZWRnZSB0bywgbm90aGluZyB0byBrZWVwIG9wZW4uXG5cdFx0XHRcdFx0b3Blbi5vcGVuID0gZmFsc2U7XG5cdFx0XHRcdFx0aGVsZC5sZW5ndGggPSAwO1xuXHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0fVxuXHRcdFx0XHR0aGlzLnN0cmVhbXMuc2V0KG9wZW4uaWQsIG9wZW4pO1xuXHRcdFx0XHR0aGlzLmRlbGl2ZXIoe1xuXHRcdFx0XHRcdHByb3RvY29sOiBQUk9UT0NPTCxcblx0XHRcdFx0XHRjYWxsX2lkOiBjYWxsLmNhbGxJZCxcblx0XHRcdFx0XHRvazogdHJ1ZSxcblx0XHRcdFx0XHR2YWx1ZToge1xuXHRcdFx0XHRcdFx0c3Vic2NyaXB0aW9uX2lkOiBvcGVuLmlkLFxuXHRcdFx0XHRcdFx0Y2FwYWNpdHk6IFNVQlNDUklQVElPTl9DQVBBQ0lUWSxcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHR9KTtcblx0XHRcdFx0c2luayA9IChmcmFtZSkgPT4gdGhpcy5kZWxpdmVyKGZyYW1lKTtcblx0XHRcdFx0Zm9yIChjb25zdCBmcmFtZSBvZiBoZWxkKSB7XG5cdFx0XHRcdFx0c2luayhmcmFtZSk7XG5cdFx0XHRcdH1cblx0XHRcdFx0aGVsZC5sZW5ndGggPSAwO1xuXHRcdFx0fSk7XG5cdH1cblxuXHRwcml2YXRlIHJlc29sdmVIYW5kbGVyKFxuXHRcdGNhbGw6IFJlY29yZGVkQ2FsbCxcblx0XHRydW46ICgpID0+IHVua25vd24sXG5cdCk6IFByb21pc2U8dW5rbm93bj4ge1xuXHRcdHJldHVybiBuZXcgUHJvbWlzZTx1bmtub3duPigocmVzb2x2ZSkgPT4ge1xuXHRcdFx0cmVzb2x2ZShydW4oKSk7XG5cdFx0fSkuY2F0Y2goKGVycm9yOiB1bmtub3duKSA9PiB7XG5cdFx0XHRjb25zdCBtZXNzYWdlID0gZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpO1xuXHRcdFx0dGhpcy5wcm9ibGVtcy5wdXNoKFxuXHRcdFx0XHRgaGFuZGxlciBmb3IgJHtjYWxsLmtpbmR9ICR7Y2FsbC5vcGVyYXRpb259IHRocmV3OiAke21lc3NhZ2V9YCxcblx0XHRcdCk7XG5cdFx0XHRyZXR1cm4gZmF1bHQoXCJoYXJuZXNzX2Vycm9yXCIsIG1lc3NhZ2UpO1xuXHRcdH0pO1xuXHR9XG5cblx0cHJpdmF0ZSBzY3JpcHRlZChcblx0XHRvcGVuOiBPcGVuU3RyZWFtLFxuXHRcdHNpbms6IChmcmFtZTogdW5rbm93bikgPT4gdm9pZCxcblx0KTogU2NyaXB0ZWRTdHJlYW0ge1xuXHRcdGNvbnN0IHJlcXVpcmVPcGVuID0gKHZlcmI6IHN0cmluZyk6IHZvaWQgPT4ge1xuXHRcdFx0aWYgKCFvcGVuLm9wZW4pIHtcblx0XHRcdFx0dGhyb3cgbmV3IFFnaXNTZGtCcmlkZ2VIYXJuZXNzRXJyb3IoXG5cdFx0XHRcdFx0YGNhbm5vdCAke3ZlcmJ9IG9uIHN1YnNjcmlwdGlvbiAke29wZW4uaWR9OiBpdCBpcyBub3Qgb3BlbmAsXG5cdFx0XHRcdCk7XG5cdFx0XHR9XG5cdFx0fTtcblx0XHRyZXR1cm4ge1xuXHRcdFx0aWQ6IG9wZW4uaWQsXG5cdFx0XHRvcGVyYXRpb246IG9wZW4ub3BlcmF0aW9uLFxuXHRcdFx0Z2V0IG9wZW4oKTogYm9vbGVhbiB7XG5cdFx0XHRcdHJldHVybiBvcGVuLm9wZW47XG5cdFx0XHR9LFxuXHRcdFx0ZW1pdDogKGtpbmQsIHBheWxvYWQpID0+IHtcblx0XHRcdFx0cmVxdWlyZU9wZW4oXCJlbWl0XCIpO1xuXHRcdFx0XHRzaW5rKHtcblx0XHRcdFx0XHRwcm90b2NvbDogUFJPVE9DT0wsXG5cdFx0XHRcdFx0c3Vic2NyaXB0aW9uX2lkOiBvcGVuLmlkLFxuXHRcdFx0XHRcdHNlcTogb3Blbi5zZXEsXG5cdFx0XHRcdFx0ZXZlbnQ6IHsga2luZCwgcGF5bG9hZCB9LFxuXHRcdFx0XHR9KTtcblx0XHRcdFx0b3Blbi5zZXEgKz0gMTtcblx0XHRcdH0sXG5cdFx0XHRlbmQ6ICh0ZXJtaW5hbCkgPT4ge1xuXHRcdFx0XHRyZXF1aXJlT3BlbihcImVuZFwiKTtcblx0XHRcdFx0b3Blbi5vcGVuID0gZmFsc2U7XG5cdFx0XHRcdHNpbmsoe1xuXHRcdFx0XHRcdHByb3RvY29sOiBQUk9UT0NPTCxcblx0XHRcdFx0XHRzdWJzY3JpcHRpb25faWQ6IG9wZW4uaWQsXG5cdFx0XHRcdFx0c2VxOiBvcGVuLnNlcSxcblx0XHRcdFx0XHR0ZXJtaW5hbCxcblx0XHRcdFx0fSk7XG5cdFx0XHRcdG9wZW4uc2VxICs9IDE7XG5cdFx0XHR9LFxuXHRcdFx0c2tpcDogKGZyYW1lcykgPT4ge1xuXHRcdFx0XHRyZXF1aXJlT3BlbihcInNraXBcIik7XG5cdFx0XHRcdG9wZW4uc2VxICs9IGZyYW1lcztcblx0XHRcdH0sXG5cdFx0fTtcblx0fVxuXG5cdHByaXZhdGUgY2xvc2VGcm9tUGFnZShjYWxsOiBSZWNvcmRlZENhbGwpOiB2b2lkIHtcblx0XHRjb25zdCBvcGVuID1cblx0XHRcdGNhbGwuc3Vic2NyaXB0aW9uSWQgPT09IHVuZGVmaW5lZFxuXHRcdFx0XHQ/IHVuZGVmaW5lZFxuXHRcdFx0XHQ6IHRoaXMuc3RyZWFtcy5nZXQoY2FsbC5zdWJzY3JpcHRpb25JZCk7XG5cdFx0Y29uc3QgZGlzcG9zZWQgPSBvcGVuPy5vcGVuID09PSB0cnVlO1xuXHRcdGlmIChvcGVuICE9PSB1bmRlZmluZWQpIHtcblx0XHRcdG9wZW4ub3BlbiA9IGZhbHNlO1xuXHRcdH1cblx0XHR0aGlzLmRlbGl2ZXIoe1xuXHRcdFx0cHJvdG9jb2w6IFBST1RPQ09MLFxuXHRcdFx0Y2FsbF9pZDogY2FsbC5jYWxsSWQsXG5cdFx0XHRvazogdHJ1ZSxcblx0XHRcdHZhbHVlOiB7IGRpc3Bvc2VkIH0sXG5cdFx0fSk7XG5cdH1cblxuXHRwcml2YXRlIGRlbGl2ZXJGYWlsdXJlKGNhbGxJZDogc3RyaW5nLCBjb2RlOiBzdHJpbmcsIG1lc3NhZ2U6IHN0cmluZyk6IHZvaWQge1xuXHRcdHRoaXMuZGVsaXZlcih7XG5cdFx0XHRwcm90b2NvbDogUFJPVE9DT0wsXG5cdFx0XHRjYWxsX2lkOiBjYWxsSWQsXG5cdFx0XHRvazogZmFsc2UsXG5cdFx0XHRlcnJvcjogeyBjb2RlLCBtZXNzYWdlIH0sXG5cdFx0fSk7XG5cdH1cblxuXHRwcml2YXRlIGRyYWluKCk6IHZvaWQge1xuXHRcdGlmICh0aGlzLmRyYWluaW5nICE9PSBudWxsKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdHRoaXMuZHJhaW5pbmcgPSAoYXN5bmMgKCkgPT4ge1xuXHRcdFx0d2hpbGUgKHRoaXMub3V0Ym94Lmxlbmd0aCA+IDApIHtcblx0XHRcdFx0YXdhaXQgUHJvbWlzZS5yZXNvbHZlKCk7XG5cdFx0XHRcdGNvbnN0IG1lc3NhZ2UgPSB0aGlzLm91dGJveC5zaGlmdCgpO1xuXHRcdFx0XHRmb3IgKGNvbnN0IGxpc3RlbmVyIG9mIFsuLi50aGlzLmxpc3RlbmVyU2V0XSkge1xuXHRcdFx0XHRcdGxpc3RlbmVyKG1lc3NhZ2UpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHR0aGlzLmRyYWluaW5nID0gbnVsbDtcblx0XHR9KSgpO1xuXHR9XG5cblx0Ly8gLS0gcGFyc2luZyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0cHJpdmF0ZSB0YWtlKFxuXHRcdGtpbmQ6IFwiaW52b2tlXCIgfCBcInN1YnNjcmliZVwiLFxuXHRcdG9wZXJhdGlvbjogc3RyaW5nLFxuXHQpOiBFeHBlY3RhdGlvbiB8IHVuZGVmaW5lZCB7XG5cdFx0Y29uc3QgaW5kZXggPSB0aGlzLmV4cGVjdGF0aW9ucy5maW5kSW5kZXgoXG5cdFx0XHQoZXhwZWN0YXRpb24pID0+XG5cdFx0XHRcdGV4cGVjdGF0aW9uLmtpbmQgPT09IGtpbmQgJiYgZXhwZWN0YXRpb24ub3BlcmF0aW9uID09PSBvcGVyYXRpb24sXG5cdFx0KTtcblx0XHRpZiAoaW5kZXggPT09IC0xKSB7XG5cdFx0XHRyZXR1cm4gdW5kZWZpbmVkO1xuXHRcdH1cblx0XHRyZXR1cm4gdGhpcy5leHBlY3RhdGlvbnMuc3BsaWNlKGluZGV4LCAxKVswXTtcblx0fVxuXG5cdHByaXZhdGUgcGFyc2VFbnZlbG9wZShtZXNzYWdlOiB1bmtub3duKTogUmVjb3JkZWRDYWxsIHtcblx0XHRpZiAodHlwZW9mIG1lc3NhZ2UgIT09IFwib2JqZWN0XCIgfHwgbWVzc2FnZSA9PT0gbnVsbCkge1xuXHRcdFx0dGhyb3cgbmV3IFFnaXNTZGtCcmlkZ2VIYXJuZXNzRXJyb3IoXCJ0aGUgY2xpZW50IHNlbnQgYSBub24tb2JqZWN0XCIpO1xuXHRcdH1cblx0XHRjb25zdCByYXcgPSBtZXNzYWdlIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuXHRcdGlmIChyYXcucHJvdG9jb2wgIT09IFBST1RPQ09MKSB7XG5cdFx0XHR0aHJvdyBuZXcgUWdpc1Nka0JyaWRnZUhhcm5lc3NFcnJvcihcblx0XHRcdFx0YHRoZSBjbGllbnQgc3BlYWtzIHByb3RvY29sICR7U3RyaW5nKHJhdy5wcm90b2NvbCl9OyB0aGUgaGFybmVzcyBmYWtlcyAke1BST1RPQ09MfWAsXG5cdFx0XHQpO1xuXHRcdH1cblx0XHRpZiAodHlwZW9mIHJhdy5jYWxsX2lkICE9PSBcInN0cmluZ1wiIHx8IHJhdy5jYWxsX2lkLmxlbmd0aCA9PT0gMCkge1xuXHRcdFx0dGhyb3cgbmV3IFFnaXNTZGtCcmlkZ2VIYXJuZXNzRXJyb3IoXCJ0aGUgY2xpZW50IHNlbnQgbm8gY2FsbF9pZFwiKTtcblx0XHR9XG5cdFx0Y29uc3QgY2FsbElkID0gcmF3LmNhbGxfaWQ7XG5cdFx0aWYgKHJhdy5raW5kID09PSBcInVuc3Vic2NyaWJlXCIpIHtcblx0XHRcdGNvbnN0IHN1YnNjcmlwdGlvbklkID0gcmF3LnN1YnNjcmlwdGlvbl9pZDtcblx0XHRcdGlmICh0eXBlb2Ygc3Vic2NyaXB0aW9uSWQgIT09IFwic3RyaW5nXCIpIHtcblx0XHRcdFx0dGhyb3cgbmV3IFFnaXNTZGtCcmlkZ2VIYXJuZXNzRXJyb3IoXG5cdFx0XHRcdFx0YCR7Y2FsbElkfTogdW5zdWJzY3JpYmUgbmFtZXMgbm8gc3Vic2NyaXB0aW9uX2lkYCxcblx0XHRcdFx0KTtcblx0XHRcdH1cblx0XHRcdGNvbnN0IGNhbGw6IFJlY29yZGVkQ2FsbCA9IHtcblx0XHRcdFx0Y2FsbElkLFxuXHRcdFx0XHRraW5kOiBcInVuc3Vic2NyaWJlXCIsXG5cdFx0XHRcdG9wZXJhdGlvbjogdGhpcy5zdHJlYW1zLmdldChzdWJzY3JpcHRpb25JZCk/Lm9wZXJhdGlvbiA/PyBcIlwiLFxuXHRcdFx0XHRzdWJzY3JpcHRpb25JZCxcblx0XHRcdH07XG5cdFx0XHR0aGlzLnJlY29yZGVkLnB1c2goY2FsbCk7XG5cdFx0XHRyZXR1cm4gY2FsbDtcblx0XHR9XG5cdFx0aWYgKHJhdy5raW5kID09PSBcImhhbmRzaGFrZVwiKSB7XG5cdFx0XHRjb25zdCBjYWxsOiBSZWNvcmRlZENhbGwgPSB7IGNhbGxJZCwga2luZDogXCJoYW5kc2hha2VcIiwgb3BlcmF0aW9uOiBcIlwiIH07XG5cdFx0XHR0aGlzLnJlY29yZGVkLnB1c2goY2FsbCk7XG5cdFx0XHRyZXR1cm4gY2FsbDtcblx0XHR9XG5cdFx0aWYgKHJhdy5raW5kICE9PSBcImludm9rZVwiICYmIHJhdy5raW5kICE9PSBcInN1YnNjcmliZVwiKSB7XG5cdFx0XHR0aHJvdyBuZXcgUWdpc1Nka0JyaWRnZUhhcm5lc3NFcnJvcihcblx0XHRcdFx0YCR7Y2FsbElkfTogJHtTdHJpbmcocmF3LmtpbmQpfSBpcyBub3QgYSBicmlkZ2UgZW52ZWxvcGUga2luZGAsXG5cdFx0XHQpO1xuXHRcdH1cblx0XHRpZiAodHlwZW9mIHJhdy5vcGVyYXRpb24gIT09IFwic3RyaW5nXCIpIHtcblx0XHRcdHRocm93IG5ldyBRZ2lzU2RrQnJpZGdlSGFybmVzc0Vycm9yKFxuXHRcdFx0XHRgJHtjYWxsSWR9OiBvcGVyYXRpb24gbXVzdCBiZSBhIHN0cmluZ2AsXG5cdFx0XHQpO1xuXHRcdH1cblx0XHRjb25zdCBwYXlsb2FkID1cblx0XHRcdHR5cGVvZiByYXcucGF5bG9hZCA9PT0gXCJvYmplY3RcIiAmJiByYXcucGF5bG9hZCAhPT0gbnVsbFxuXHRcdFx0XHQ/IChyYXcucGF5bG9hZCBhcyBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4pXG5cdFx0XHRcdDoge307XG5cdFx0Y29uc3QgY2FsbDogUmVjb3JkZWRDYWxsID0ge1xuXHRcdFx0Y2FsbElkLFxuXHRcdFx0a2luZDogcmF3LmtpbmQsXG5cdFx0XHRvcGVyYXRpb246IHJhdy5vcGVyYXRpb24sXG5cdFx0XHRwYXlsb2FkLFxuXHRcdH07XG5cdFx0dGhpcy5yZWNvcmRlZC5wdXNoKGNhbGwpO1xuXHRcdHJldHVybiBjYWxsO1xuXHR9XG59XG5cbi8qKlxuICogQ3JlYXRlIGEgaGFybmVzcy5cbiAqXG4gKiBHaXZlbiB0aGUgZ2VuZXJhdGVkIGBicmlkZ2Uuc2NoZW1hLnRzYCBkZWZhdWx0IGV4cG9ydCwgdGhlIGhhcm5lc3MgaXMgdHlwZWRcbiAqIGJ5IGl0OiBgZXhwZWN0SW52b2tlKFwic2l0ZXMuc3VtbWFyeVwiLCAocGF5bG9hZCkgPT4gLi4uKWAgc2VlcyB0aGUgZGVjbGFyZWRcbiAqIHJlcXVlc3QgYW5kIG11c3QgYW5zd2VyIHdpdGggdGhlIGRlY2xhcmVkIHJlc3VsdCwgYW5kIHRoZSBoYW5kc2hha2UgaXRcbiAqIGFuc3dlcnMgYWR2ZXJ0aXNlcyB0aGUgc2NoZW1hJ3Mgb3BlcmF0aW9ucy4gV2l0aG91dCBvbmUsIGBPcGAgbmFycm93cyB0aGVcbiAqIG9wZXJhdGlvbnMgYSB0ZXN0IG1heSBleHBlY3QsIHR5cGljYWxseSBhIGdlbmVyYXRlZCBgT3BlcmF0aW9uSWRgLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQnJpZGdlSGFybmVzczxPcCBleHRlbmRzIHN0cmluZyA9IHN0cmluZz4oXG5cdG9wdGlvbnM/OiBIYXJuZXNzT3B0aW9ucyxcbik6IEJyaWRnZUhhcm5lc3M8T3A+O1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUJyaWRnZUhhcm5lc3M8TywgUz4oXG5cdHNjaGVtYTogQnJpZGdlU2NoZW1hPE8sIFM+LFxuXHRvcHRpb25zPzogSGFybmVzc09wdGlvbnMsXG4pOiBTY2hlbWFCcmlkZ2VIYXJuZXNzPE8sIFM+O1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUJyaWRnZUhhcm5lc3MoXG5cdGZpcnN0OiBIYXJuZXNzT3B0aW9ucyB8IEJyaWRnZVNjaGVtYSA9IHt9LFxuXHRzZWNvbmQ6IEhhcm5lc3NPcHRpb25zID0ge30sXG4pOiBCcmlkZ2VIYXJuZXNzIHwgU2NoZW1hQnJpZGdlSGFybmVzczx1bmtub3duLCB1bmtub3duPiB7XG5cdGlmIChcInNjaGVtYV92ZXJzaW9uXCIgaW4gZmlyc3QpIHtcblx0XHRyZXR1cm4gbmV3IEhhcm5lc3M8c3RyaW5nPihzZWNvbmQsIGZpcnN0KSBhcyBTY2hlbWFCcmlkZ2VIYXJuZXNzPFxuXHRcdFx0dW5rbm93bixcblx0XHRcdHVua25vd25cblx0XHQ+O1xuXHR9XG5cdHJldHVybiBuZXcgSGFybmVzczxzdHJpbmc+KGZpcnN0LCBudWxsKTtcbn1cbiIKICBdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7OztBQStCQSxJQUFNLFdBQVc7QUFDakIsSUFBTSx3QkFBd0I7QUFRdkIsU0FBUyxLQUFLLENBQUMsTUFBYyxTQUFnQztBQUFBLEVBQ25FLE9BQU8sT0FBTyxPQUFPLEVBQUUsT0FBTyxPQUFPLE9BQU8sRUFBRSxNQUFNLFFBQVEsQ0FBQyxFQUFFLENBQUM7QUFBQTtBQUdqRSxTQUFTLE9BQU8sQ0FBQyxPQUF3QztBQUFBLEVBQ3hELE9BQ0Ms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
package/package.json CHANGED
@@ -1,10 +1,64 @@
1
1
  {
2
- "name": "@archont561/qgis-sdk",
3
- "version": "0.0.0",
4
- "description": "OIDC trusted publishing setup package for @archont561/qgis-sdk",
5
- "keywords": [
6
- "oidc",
7
- "trusted-publishing",
8
- "setup"
9
- ]
2
+ "name": "@archont561/qgis-sdk",
3
+ "version": "0.4.0",
4
+ "description": "TypeScript bridge contracts and error primitives for QGIS SDK WebEngine plugin interfaces.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "./bridge": {
16
+ "types": "./dist/bridge.d.ts",
17
+ "import": "./dist/bridge.js",
18
+ "default": "./dist/bridge.js"
19
+ },
20
+ "./host": {
21
+ "types": "./dist/host.d.ts",
22
+ "import": "./dist/host.js",
23
+ "default": "./dist/host.js"
24
+ },
25
+ "./react": {
26
+ "types": "./dist/react.d.ts",
27
+ "import": "./dist/react.js",
28
+ "default": "./dist/react.js"
29
+ },
30
+ "./testing": {
31
+ "types": "./dist/testing.d.ts",
32
+ "import": "./dist/testing.js",
33
+ "default": "./dist/testing.js"
34
+ }
35
+ },
36
+ "files": [
37
+ "dist",
38
+ "README.md",
39
+ "LICENSE"
40
+ ],
41
+ "repository": {
42
+ "type": "git",
43
+ "url": "git+https://github.com/Archont561/qgis-sdk.git",
44
+ "directory": "packages/qgis-sdk-typescript"
45
+ },
46
+ "publishConfig": {
47
+ "access": "public"
48
+ },
49
+ "scripts": {
50
+ "build": "bunup && tsc -p tsconfig.dist.json",
51
+ "test": "bun test",
52
+ "coverage": "bun --cwd=../.. --config=bunfig.toml test --coverage packages/qgis-sdk-typescript/tests",
53
+ "typecheck": "tsc --noEmit",
54
+ "generate:contract-types": "json2ts -i 'tests/contracts/generated/schemas/*.json' -o tests/contracts/generated/types/ && json2ts -i 'tests/contracts/pydantic/generated/schemas/*.json' -o tests/contracts/pydantic/generated/types/"
55
+ },
56
+ "peerDependencies": {
57
+ "react": ">=18"
58
+ },
59
+ "peerDependenciesMeta": {
60
+ "react": {
61
+ "optional": true
62
+ }
63
+ }
10
64
  }