@archont561/qgis-sdk-bridge 0.1.1 → 0.2.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,207 @@
1
+ // src/index.ts
2
+ var MAX_SAFE_INTEGER2 = 9007199254740991;
3
+ var MIN_SAFE_INTEGER2 = -9007199254740991;
4
+ var PLUGIN_DESCRIPTION_SCHEMA_VERSION2 = 1;
5
+ var STREAM_EVENT_KINDS = [
6
+ "data",
7
+ "progress",
8
+ "state"
9
+ ];
10
+ function isSafeJsonInteger2(value) {
11
+ return typeof value === "number" && Number.isSafeInteger(value);
12
+ }
13
+
14
+ class QgisSdkError2 extends Error {
15
+ code;
16
+ constructor(message, code = "sdk_error") {
17
+ super(message);
18
+ this.name = new.target.name;
19
+ this.code = code;
20
+ }
21
+ }
22
+
23
+ class QgisSdkScopeClosedError2 extends QgisSdkError2 {
24
+ constructor() {
25
+ super("This resource scope has been disposed", "scope_closed");
26
+ }
27
+ }
28
+
29
+ class QgisSdkUnsupportedCapabilityError2 extends QgisSdkError2 {
30
+ capability;
31
+ constructor(capability) {
32
+ super(`Capability ${JSON.stringify(capability)} is unavailable in this runtime`, "unsupported_capability");
33
+ this.capability = capability;
34
+ }
35
+ }
36
+
37
+ class QgisSdkDeclarationError2 extends QgisSdkError2 {
38
+ constructor(message) {
39
+ super(message, "invalid_declaration");
40
+ }
41
+ }
42
+
43
+ class QgisSdkValidationIssue2 {
44
+ path;
45
+ code;
46
+ constructor(path, code) {
47
+ this.path = Object.freeze([...path]);
48
+ this.code = code;
49
+ }
50
+ toJSON() {
51
+ return {
52
+ path: [...this.path],
53
+ code: this.code
54
+ };
55
+ }
56
+ }
57
+
58
+ class QgisSdkContractValidationError2 extends QgisSdkError2 {
59
+ direction;
60
+ issues;
61
+ constructor(direction, issues) {
62
+ const prefix = direction === "request" ? "Request" : "Result";
63
+ super(`${prefix} contract validation failed`, "contract_validation_failed");
64
+ this.direction = direction;
65
+ this.issues = Object.freeze([...issues]);
66
+ }
67
+ toJSON() {
68
+ return {
69
+ code: this.code,
70
+ direction: this.direction,
71
+ issues: this.issues.map((issue) => issue.toJSON())
72
+ };
73
+ }
74
+ }
75
+ var DECLARATION_ID_PATTERN = /^[a-zA-Z][a-zA-Z0-9_.-]*$/;
76
+ var PYTHON_IDENTIFIER_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
77
+ function isPlainRecord2(value) {
78
+ return typeof value === "object" && value !== null && !Array.isArray(value);
79
+ }
80
+ function validateDeclarationId(value, label) {
81
+ if (typeof value !== "string" || !DECLARATION_ID_PATTERN.test(value)) {
82
+ throw new QgisSdkDeclarationError2(`Invalid ${label} id: expected [a-zA-Z][a-zA-Z0-9_.-]*`);
83
+ }
84
+ return value;
85
+ }
86
+ function validateNonBlankTitle(value, id) {
87
+ if (typeof value !== "string" || value.trim().length === 0) {
88
+ throw new QgisSdkDeclarationError2(`${id}: title must be a nonempty string`);
89
+ }
90
+ return value;
91
+ }
92
+ function parseOperationHead(raw, label) {
93
+ if (!isPlainRecord2(raw)) {
94
+ throw new QgisSdkDeclarationError2(`${label[0]?.toUpperCase()}${label.slice(1)} description must be an object`);
95
+ }
96
+ const id = validateDeclarationId(raw.id, label);
97
+ const title = validateNonBlankTitle(raw.title, id);
98
+ if (typeof raw.handler !== "string" || !PYTHON_IDENTIFIER_PATTERN.test(raw.handler)) {
99
+ throw new QgisSdkDeclarationError2(`${id}: handler must be a valid Python identifier`);
100
+ }
101
+ if (!isPlainRecord2(raw.request)) {
102
+ throw new QgisSdkDeclarationError2(`${id}: request schema must be an object`);
103
+ }
104
+ return {
105
+ raw,
106
+ id,
107
+ title,
108
+ handler: raw.handler,
109
+ request: Object.freeze({ ...raw.request })
110
+ };
111
+ }
112
+ function parseActionDescription(raw) {
113
+ const head = parseOperationHead(raw, "action");
114
+ if (!isPlainRecord2(head.raw.result)) {
115
+ throw new QgisSdkDeclarationError2(`${head.id}: result schema must be an object`);
116
+ }
117
+ return Object.freeze({
118
+ id: head.id,
119
+ title: head.title,
120
+ handler: head.handler,
121
+ request: head.request,
122
+ result: Object.freeze({ ...head.raw.result })
123
+ });
124
+ }
125
+ function parseStreamDescription(raw) {
126
+ const head = parseOperationHead(raw, "stream");
127
+ const declared = head.raw.events;
128
+ if (!isPlainRecord2(declared) || Object.keys(declared).length === 0) {
129
+ throw new QgisSdkDeclarationError2(`${head.id}: events must map at least one event kind to a schema`);
130
+ }
131
+ const events = {};
132
+ for (const [kind, schema] of Object.entries(declared)) {
133
+ if (!STREAM_EVENT_KINDS.includes(kind)) {
134
+ throw new QgisSdkDeclarationError2(`${head.id}: ${kind} is not a stream event kind`);
135
+ }
136
+ if (!isPlainRecord2(schema)) {
137
+ throw new QgisSdkDeclarationError2(`${head.id}: events.${kind} schema must be an object`);
138
+ }
139
+ events[kind] = Object.freeze({ ...schema });
140
+ }
141
+ return Object.freeze({
142
+ id: head.id,
143
+ title: head.title,
144
+ handler: head.handler,
145
+ request: head.request,
146
+ events: Object.freeze(events)
147
+ });
148
+ }
149
+ function parsePluginDescription2(input) {
150
+ let parsed = input;
151
+ if (typeof input === "string") {
152
+ try {
153
+ parsed = JSON.parse(input);
154
+ } catch {
155
+ throw new QgisSdkDeclarationError2("Plugin description is not valid JSON");
156
+ }
157
+ }
158
+ if (!isPlainRecord2(parsed)) {
159
+ throw new QgisSdkDeclarationError2("Plugin description must be an object");
160
+ }
161
+ if (parsed.schema_version !== PLUGIN_DESCRIPTION_SCHEMA_VERSION2) {
162
+ throw new QgisSdkDeclarationError2(`Unsupported plugin description schema_version: ${String(parsed.schema_version)}`);
163
+ }
164
+ const id = validateDeclarationId(parsed.id, "plugin");
165
+ const title = validateNonBlankTitle(parsed.title, id);
166
+ if (!Array.isArray(parsed.actions)) {
167
+ throw new QgisSdkDeclarationError2(`${id}: actions must be an array`);
168
+ }
169
+ const declaredStreams = parsed.streams ?? [];
170
+ if (!Array.isArray(declaredStreams)) {
171
+ throw new QgisSdkDeclarationError2(`${id}: streams must be an array`);
172
+ }
173
+ const seenIds = new Set;
174
+ const claim = (operationId, label) => {
175
+ if (seenIds.has(operationId)) {
176
+ throw new QgisSdkDeclarationError2(`${id}: duplicate ${label} id ${operationId}`);
177
+ }
178
+ seenIds.add(operationId);
179
+ };
180
+ const actions = [];
181
+ for (const item of parsed.actions) {
182
+ const action = parseActionDescription(item);
183
+ claim(action.id, "action");
184
+ actions.push(action);
185
+ }
186
+ const streams = [];
187
+ for (const item of declaredStreams) {
188
+ const stream = parseStreamDescription(item);
189
+ claim(stream.id, "stream");
190
+ streams.push(stream);
191
+ }
192
+ const byId = (left, right) => left.id < right.id ? -1 : 1;
193
+ actions.sort(byId);
194
+ streams.sort(byId);
195
+ return Object.freeze({
196
+ schema_version: PLUGIN_DESCRIPTION_SCHEMA_VERSION2,
197
+ id,
198
+ title,
199
+ actions: Object.freeze(actions),
200
+ streams: Object.freeze(streams)
201
+ });
202
+ }
203
+
204
+ export { MAX_SAFE_INTEGER2, MIN_SAFE_INTEGER2, PLUGIN_DESCRIPTION_SCHEMA_VERSION2, isSafeJsonInteger2, QgisSdkError2, QgisSdkScopeClosedError2, QgisSdkUnsupportedCapabilityError2, QgisSdkDeclarationError2, QgisSdkValidationIssue2, QgisSdkContractValidationError2, isPlainRecord2, parsePluginDescription2 };
205
+
206
+ //# debugId=BF5795AE7CCB0B5464756E2164756E21
207
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsic3JjL2luZGV4LnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWwogICAgIi8qKlxuICogUHVibGljIDAuMS4wIGNvbnRyYWN0LCB3aXJlLWxpbWl0LCBhbmQgZXJyb3IgcHJpbWl0aXZlcyBmb3IgdGhlIFFHSVMgU0RLIGJyaWRnZS5cbiAqXG4gKiBNaXJyb3JzIHRoZSBRR0lTLWZyZWUgYHFnaXNfc2RrLm1vZGVsc2AgYW5kIGBxZ2lzX3Nkay5kZWNsYXJhdGlvbnNgXG4gKiAoYHNjaGVtYV92ZXJzaW9uID0gMWApIGNvbnRyYWN0cyB3aXRob3V0IGltcG9ydGluZyBicm93c2VyIG9yIFF0IGdsb2JhbHMuXG4gKi9cblxuZXhwb3J0IGNvbnN0IE1BWF9TQUZFX0lOVEVHRVI6IG51bWJlciA9IDlfMDA3XzE5OV8yNTRfNzQwXzk5MTtcbmV4cG9ydCBjb25zdCBNSU5fU0FGRV9JTlRFR0VSOiBudW1iZXIgPSAtOV8wMDdfMTk5XzI1NF83NDBfOTkxO1xuZXhwb3J0IGNvbnN0IFBMVUdJTl9ERVNDUklQVElPTl9TQ0hFTUFfVkVSU0lPTjogMSA9IDE7XG5cbmV4cG9ydCB0eXBlIFZhbGlkYXRpb25EaXJlY3Rpb24gPSBcInJlcXVlc3RcIiB8IFwicmVzdWx0XCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2VyaWFsaXplZFZhbGlkYXRpb25Jc3N1ZSB7XG5cdHJlYWRvbmx5IHBhdGg6IChzdHJpbmcgfCBudW1iZXIpW107XG5cdHJlYWRvbmx5IGNvZGU6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTZXJpYWxpemVkQ29udHJhY3RWYWxpZGF0aW9uRXJyb3Ige1xuXHRyZWFkb25seSBjb2RlOiBzdHJpbmc7XG5cdHJlYWRvbmx5IGRpcmVjdGlvbjogVmFsaWRhdGlvbkRpcmVjdGlvbjtcblx0cmVhZG9ubHkgaXNzdWVzOiBTZXJpYWxpemVkVmFsaWRhdGlvbklzc3VlW107XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQWN0aW9uRGVzY3JpcHRpb24ge1xuXHRyZWFkb25seSBpZDogc3RyaW5nO1xuXHRyZWFkb25seSB0aXRsZTogc3RyaW5nO1xuXHRyZWFkb25seSBoYW5kbGVyOiBzdHJpbmc7XG5cdHJlYWRvbmx5IHJlcXVlc3Q6IFJlYWRvbmx5PFJlY29yZDxzdHJpbmcsIHVua25vd24+Pjtcblx0cmVhZG9ubHkgcmVzdWx0OiBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj47XG59XG5cbi8qKiBUaGUgZXZlbnQga2luZHMgYSBzdHJlYW0gbWF5IGRlY2xhcmU7IHRoZSBmcmFtZSBjYXJyaWVzIHRoZSBzYW1lIHRocmVlLiAqL1xuZXhwb3J0IHR5cGUgU3RyZWFtRXZlbnRLaW5kID0gXCJkYXRhXCIgfCBcInByb2dyZXNzXCIgfCBcInN0YXRlXCI7XG5cbi8qKlxuICogQSBkZWNsYXJlZCBzdHJlYW0gKGRlY2lzaW9uLTI4KTogYSByZXF1ZXN0IGluLCBvbmUgcGF5bG9hZCBzY2hlbWEgcGVyXG4gKiBkZWNsYXJlZCBldmVudCBraW5kIG91dC4gVGhlcmUgaXMgbm8gYHJlc3VsdGA6IHRoZSByZXBseSB0byBhIHN1YnNjcmlwdGlvbiBpc1xuICogdGhlIHByb3RvY29sJ3MgYWNrbm93bGVkZ2VtZW50LCBub3Qgc29tZXRoaW5nIGFuIGF1dGhvciBkZWNsYXJlcy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTdHJlYW1EZXNjcmlwdGlvbiB7XG5cdHJlYWRvbmx5IGlkOiBzdHJpbmc7XG5cdHJlYWRvbmx5IHRpdGxlOiBzdHJpbmc7XG5cdHJlYWRvbmx5IGhhbmRsZXI6IHN0cmluZztcblx0cmVhZG9ubHkgcmVxdWVzdDogUmVhZG9ubHk8UmVjb3JkPHN0cmluZywgdW5rbm93bj4+O1xuXHRyZWFkb25seSBldmVudHM6IFJlYWRvbmx5PFxuXHRcdFBhcnRpYWw8UmVjb3JkPFN0cmVhbUV2ZW50S2luZCwgUmVhZG9ubHk8UmVjb3JkPHN0cmluZywgdW5rbm93bj4+Pj5cblx0Pjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQbHVnaW5EZXNjcmlwdGlvbiB7XG5cdHJlYWRvbmx5IHNjaGVtYV92ZXJzaW9uOiAxO1xuXHRyZWFkb25seSBpZDogc3RyaW5nO1xuXHRyZWFkb25seSB0aXRsZTogc3RyaW5nO1xuXHRyZWFkb25seSBhY3Rpb25zOiByZWFkb25seSBBY3Rpb25EZXNjcmlwdGlvbltdO1xuXHQvKiogRGVjbGFyZWQgc3RyZWFtczsgYSBkZXNjcmlwdGlvbiBmcm9tIGEgaG9zdCB0aGF0IHByZWRhdGVzIHRoZW0gaXMgZW1wdHkuICovXG5cdHJlYWRvbmx5IHN0cmVhbXM6IHJlYWRvbmx5IFN0cmVhbURlc2NyaXB0aW9uW107XG59XG5cbmNvbnN0IFNUUkVBTV9FVkVOVF9LSU5EUzogcmVhZG9ubHkgU3RyZWFtRXZlbnRLaW5kW10gPSBbXG5cdFwiZGF0YVwiLFxuXHRcInByb2dyZXNzXCIsXG5cdFwic3RhdGVcIixcbl07XG5cbi8qKlxuICogUmV0dXJuIHdoZXRoZXIgYHZhbHVlYCBpcyBhIGZpbml0ZSBpbnRlZ2VyIHdpdGhpbiB0aGUgSmF2YVNjcmlwdC1zYWZlIHdpcmUgcmFuZ2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1NhZmVKc29uSW50ZWdlcih2YWx1ZTogdW5rbm93bik6IHZhbHVlIGlzIG51bWJlciB7XG5cdHJldHVybiB0eXBlb2YgdmFsdWUgPT09IFwibnVtYmVyXCIgJiYgTnVtYmVyLmlzU2FmZUludGVnZXIodmFsdWUpO1xufVxuXG4vKipcbiAqIEJhc2UgY2xhc3MgZm9yIGV4cGVjdGVkIFNESyBlcnJvcnMgYWNyb3NzIHRoZSBicmlkZ2UgYm91bmRhcnkuXG4gKi9cbmV4cG9ydCBjbGFzcyBRZ2lzU2RrRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG5cdHB1YmxpYyByZWFkb25seSBjb2RlOiBzdHJpbmc7XG5cblx0cHVibGljIGNvbnN0cnVjdG9yKG1lc3NhZ2U6IHN0cmluZywgY29kZTogc3RyaW5nID0gXCJzZGtfZXJyb3JcIikge1xuXHRcdHN1cGVyKG1lc3NhZ2UpO1xuXHRcdHRoaXMubmFtZSA9IG5ldy50YXJnZXQubmFtZTtcblx0XHR0aGlzLmNvZGUgPSBjb2RlO1xuXHR9XG59XG5cbi8qKlxuICogQW4gb3BlcmF0aW9uIGF0dGVtcHRlZCB0byB1c2UgYW4gYWxyZWFkeSBkaXNwb3NlZCBvd25lciBzY29wZS5cbiAqL1xuZXhwb3J0IGNsYXNzIFFnaXNTZGtTY29wZUNsb3NlZEVycm9yIGV4dGVuZHMgUWdpc1Nka0Vycm9yIHtcblx0cHVibGljIGNvbnN0cnVjdG9yKCkge1xuXHRcdHN1cGVyKFwiVGhpcyByZXNvdXJjZSBzY29wZSBoYXMgYmVlbiBkaXNwb3NlZFwiLCBcInNjb3BlX2Nsb3NlZFwiKTtcblx0fVxufVxuXG4vKipcbiAqIFRoZSBzZWxlY3RlZCBydW50aW1lIGRvZXMgbm90IG9mZmVyIGFuIGV4cGxpY2l0bHkgcmVxdWVzdGVkIGNhcGFiaWxpdHkuXG4gKi9cbmV4cG9ydCBjbGFzcyBRZ2lzU2RrVW5zdXBwb3J0ZWRDYXBhYmlsaXR5RXJyb3IgZXh0ZW5kcyBRZ2lzU2RrRXJyb3Ige1xuXHRwdWJsaWMgcmVhZG9ubHkgY2FwYWJpbGl0eTogc3RyaW5nO1xuXG5cdHB1YmxpYyBjb25zdHJ1Y3RvcihjYXBhYmlsaXR5OiBzdHJpbmcpIHtcblx0XHRzdXBlcihcblx0XHRcdGBDYXBhYmlsaXR5ICR7SlNPTi5zdHJpbmdpZnkoY2FwYWJpbGl0eSl9IGlzIHVuYXZhaWxhYmxlIGluIHRoaXMgcnVudGltZWAsXG5cdFx0XHRcInVuc3VwcG9ydGVkX2NhcGFiaWxpdHlcIixcblx0XHQpO1xuXHRcdHRoaXMuY2FwYWJpbGl0eSA9IGNhcGFiaWxpdHk7XG5cdH1cbn1cblxuLyoqXG4gKiBBIGRlY2xhcmF0aW9uIGNhbm5vdCBiZSByZXByZXNlbnRlZCBvciBwYXJzZWQgaW4gdGhlIHZlcnNpb25lZCBjb250cmFjdC5cbiAqL1xuZXhwb3J0IGNsYXNzIFFnaXNTZGtEZWNsYXJhdGlvbkVycm9yIGV4dGVuZHMgUWdpc1Nka0Vycm9yIHtcblx0cHVibGljIGNvbnN0cnVjdG9yKG1lc3NhZ2U6IHN0cmluZykge1xuXHRcdHN1cGVyKG1lc3NhZ2UsIFwiaW52YWxpZF9kZWNsYXJhdGlvblwiKTtcblx0fVxufVxuXG4vKipcbiAqIFNhZmUsIHN0cnVjdHVyZWQgbG9jYXRpb24gYW5kIGNhdGVnb3J5IGZvciBhIHJlamVjdGVkIGNvbnRyYWN0IHZhbHVlLlxuICovXG5leHBvcnQgY2xhc3MgUWdpc1Nka1ZhbGlkYXRpb25Jc3N1ZSB7XG5cdHB1YmxpYyByZWFkb25seSBwYXRoOiByZWFkb25seSAoc3RyaW5nIHwgbnVtYmVyKVtdO1xuXHRwdWJsaWMgcmVhZG9ubHkgY29kZTogc3RyaW5nO1xuXG5cdHB1YmxpYyBjb25zdHJ1Y3RvcihwYXRoOiByZWFkb25seSAoc3RyaW5nIHwgbnVtYmVyKVtdLCBjb2RlOiBzdHJpbmcpIHtcblx0XHR0aGlzLnBhdGggPSBPYmplY3QuZnJlZXplKFsuLi5wYXRoXSk7XG5cdFx0dGhpcy5jb2RlID0gY29kZTtcblx0fVxuXG5cdHB1YmxpYyB0b0pTT04oKTogU2VyaWFsaXplZFZhbGlkYXRpb25Jc3N1ZSB7XG5cdFx0cmV0dXJuIHtcblx0XHRcdHBhdGg6IFsuLi50aGlzLnBhdGhdLFxuXHRcdFx0Y29kZTogdGhpcy5jb2RlLFxuXHRcdH07XG5cdH1cbn1cblxuLyoqXG4gKiBBIHJlcXVlc3Qgb3IgcmVzdWx0IGRpZCBub3Qgc2F0aXNmeSBpdHMgZGVjbGFyZWQgd2lyZSBjb250cmFjdC5cbiAqL1xuZXhwb3J0IGNsYXNzIFFnaXNTZGtDb250cmFjdFZhbGlkYXRpb25FcnJvciBleHRlbmRzIFFnaXNTZGtFcnJvciB7XG5cdHB1YmxpYyByZWFkb25seSBkaXJlY3Rpb246IFZhbGlkYXRpb25EaXJlY3Rpb247XG5cdHB1YmxpYyByZWFkb25seSBpc3N1ZXM6IHJlYWRvbmx5IFFnaXNTZGtWYWxpZGF0aW9uSXNzdWVbXTtcblxuXHRwdWJsaWMgY29uc3RydWN0b3IoXG5cdFx0ZGlyZWN0aW9uOiBWYWxpZGF0aW9uRGlyZWN0aW9uLFxuXHRcdGlzc3VlczogcmVhZG9ubHkgUWdpc1Nka1ZhbGlkYXRpb25Jc3N1ZVtdLFxuXHQpIHtcblx0XHRjb25zdCBwcmVmaXggPSBkaXJlY3Rpb24gPT09IFwicmVxdWVzdFwiID8gXCJSZXF1ZXN0XCIgOiBcIlJlc3VsdFwiO1xuXHRcdHN1cGVyKGAke3ByZWZpeH0gY29udHJhY3QgdmFsaWRhdGlvbiBmYWlsZWRgLCBcImNvbnRyYWN0X3ZhbGlkYXRpb25fZmFpbGVkXCIpO1xuXHRcdHRoaXMuZGlyZWN0aW9uID0gZGlyZWN0aW9uO1xuXHRcdHRoaXMuaXNzdWVzID0gT2JqZWN0LmZyZWV6ZShbLi4uaXNzdWVzXSk7XG5cdH1cblxuXHRwdWJsaWMgdG9KU09OKCk6IFNlcmlhbGl6ZWRDb250cmFjdFZhbGlkYXRpb25FcnJvciB7XG5cdFx0cmV0dXJuIHtcblx0XHRcdGNvZGU6IHRoaXMuY29kZSxcblx0XHRcdGRpcmVjdGlvbjogdGhpcy5kaXJlY3Rpb24sXG5cdFx0XHRpc3N1ZXM6IHRoaXMuaXNzdWVzLm1hcCgoaXNzdWUpID0+IGlzc3VlLnRvSlNPTigpKSxcblx0XHR9O1xuXHR9XG59XG5cbmNvbnN0IERFQ0xBUkFUSU9OX0lEX1BBVFRFUk4gPSAvXlthLXpBLVpdW2EtekEtWjAtOV8uLV0qJC87XG5jb25zdCBQWVRIT05fSURFTlRJRklFUl9QQVRURVJOID0gL15bYS16QS1aX11bYS16QS1aMC05X10qJC87XG5cbi8qKlxuICogUmV0dXJuIHdoZXRoZXIgYHZhbHVlYCBpcyBhIG5vbi1udWxsLCBub24tYXJyYXkgb2JqZWN0OiB0aGUgc2hhcGUgZXZlcnkgd2lyZVxuICogZW52ZWxvcGUsIGRlc2NyaXB0aW9uIGFuZCBldmVudCBwYXlsb2FkIG11c3QgaGF2ZSBiZWZvcmUgaXRzIGZpZWxkcyBhcmUgcmVhZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzUGxhaW5SZWNvcmQoXG5cdHZhbHVlOiB1bmtub3duLFxuKTogdmFsdWUgaXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4ge1xuXHRyZXR1cm4gdHlwZW9mIHZhbHVlID09PSBcIm9iamVjdFwiICYmIHZhbHVlICE9PSBudWxsICYmICFBcnJheS5pc0FycmF5KHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gdmFsaWRhdGVEZWNsYXJhdGlvbklkKHZhbHVlOiB1bmtub3duLCBsYWJlbDogc3RyaW5nKTogc3RyaW5nIHtcblx0aWYgKHR5cGVvZiB2YWx1ZSAhPT0gXCJzdHJpbmdcIiB8fCAhREVDTEFSQVRJT05fSURfUEFUVEVSTi50ZXN0KHZhbHVlKSkge1xuXHRcdHRocm93IG5ldyBRZ2lzU2RrRGVjbGFyYXRpb25FcnJvcihcblx0XHRcdGBJbnZhbGlkICR7bGFiZWx9IGlkOiBleHBlY3RlZCBbYS16QS1aXVthLXpBLVowLTlfLi1dKmAsXG5cdFx0KTtcblx0fVxuXHRyZXR1cm4gdmFsdWU7XG59XG5cbmZ1bmN0aW9uIHZhbGlkYXRlTm9uQmxhbmtUaXRsZSh2YWx1ZTogdW5rbm93biwgaWQ6IHN0cmluZyk6IHN0cmluZyB7XG5cdGlmICh0eXBlb2YgdmFsdWUgIT09IFwic3RyaW5nXCIgfHwgdmFsdWUudHJpbSgpLmxlbmd0aCA9PT0gMCkge1xuXHRcdHRocm93IG5ldyBRZ2lzU2RrRGVjbGFyYXRpb25FcnJvcihgJHtpZH06IHRpdGxlIG11c3QgYmUgYSBub25lbXB0eSBzdHJpbmdgKTtcblx0fVxuXHRyZXR1cm4gdmFsdWU7XG59XG5cbmZ1bmN0aW9uIHBhcnNlT3BlcmF0aW9uSGVhZChcblx0cmF3OiB1bmtub3duLFxuXHRsYWJlbDogc3RyaW5nLFxuKToge1xuXHRyZWFkb25seSByYXc6IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuXHRyZWFkb25seSBpZDogc3RyaW5nO1xuXHRyZWFkb25seSB0aXRsZTogc3RyaW5nO1xuXHRyZWFkb25seSBoYW5kbGVyOiBzdHJpbmc7XG5cdHJlYWRvbmx5IHJlcXVlc3Q6IFJlYWRvbmx5PFJlY29yZDxzdHJpbmcsIHVua25vd24+Pjtcbn0ge1xuXHRpZiAoIWlzUGxhaW5SZWNvcmQocmF3KSkge1xuXHRcdHRocm93IG5ldyBRZ2lzU2RrRGVjbGFyYXRpb25FcnJvcihcblx0XHRcdGAke2xhYmVsWzBdPy50b1VwcGVyQ2FzZSgpfSR7bGFiZWwuc2xpY2UoMSl9IGRlc2NyaXB0aW9uIG11c3QgYmUgYW4gb2JqZWN0YCxcblx0XHQpO1xuXHR9XG5cdGNvbnN0IGlkID0gdmFsaWRhdGVEZWNsYXJhdGlvbklkKHJhdy5pZCwgbGFiZWwpO1xuXHRjb25zdCB0aXRsZSA9IHZhbGlkYXRlTm9uQmxhbmtUaXRsZShyYXcudGl0bGUsIGlkKTtcblx0aWYgKFxuXHRcdHR5cGVvZiByYXcuaGFuZGxlciAhPT0gXCJzdHJpbmdcIiB8fFxuXHRcdCFQWVRIT05fSURFTlRJRklFUl9QQVRURVJOLnRlc3QocmF3LmhhbmRsZXIpXG5cdCkge1xuXHRcdHRocm93IG5ldyBRZ2lzU2RrRGVjbGFyYXRpb25FcnJvcihcblx0XHRcdGAke2lkfTogaGFuZGxlciBtdXN0IGJlIGEgdmFsaWQgUHl0aG9uIGlkZW50aWZpZXJgLFxuXHRcdCk7XG5cdH1cblx0aWYgKCFpc1BsYWluUmVjb3JkKHJhdy5yZXF1ZXN0KSkge1xuXHRcdHRocm93IG5ldyBRZ2lzU2RrRGVjbGFyYXRpb25FcnJvcihcblx0XHRcdGAke2lkfTogcmVxdWVzdCBzY2hlbWEgbXVzdCBiZSBhbiBvYmplY3RgLFxuXHRcdCk7XG5cdH1cblx0cmV0dXJuIHtcblx0XHRyYXcsXG5cdFx0aWQsXG5cdFx0dGl0bGUsXG5cdFx0aGFuZGxlcjogcmF3LmhhbmRsZXIsXG5cdFx0cmVxdWVzdDogT2JqZWN0LmZyZWV6ZSh7IC4uLnJhdy5yZXF1ZXN0IH0pLFxuXHR9O1xufVxuXG5mdW5jdGlvbiBwYXJzZUFjdGlvbkRlc2NyaXB0aW9uKHJhdzogdW5rbm93bik6IEFjdGlvbkRlc2NyaXB0aW9uIHtcblx0Y29uc3QgaGVhZCA9IHBhcnNlT3BlcmF0aW9uSGVhZChyYXcsIFwiYWN0aW9uXCIpO1xuXHRpZiAoIWlzUGxhaW5SZWNvcmQoaGVhZC5yYXcucmVzdWx0KSkge1xuXHRcdHRocm93IG5ldyBRZ2lzU2RrRGVjbGFyYXRpb25FcnJvcihcblx0XHRcdGAke2hlYWQuaWR9OiByZXN1bHQgc2NoZW1hIG11c3QgYmUgYW4gb2JqZWN0YCxcblx0XHQpO1xuXHR9XG5cdHJldHVybiBPYmplY3QuZnJlZXplKHtcblx0XHRpZDogaGVhZC5pZCxcblx0XHR0aXRsZTogaGVhZC50aXRsZSxcblx0XHRoYW5kbGVyOiBoZWFkLmhhbmRsZXIsXG5cdFx0cmVxdWVzdDogaGVhZC5yZXF1ZXN0LFxuXHRcdHJlc3VsdDogT2JqZWN0LmZyZWV6ZSh7IC4uLmhlYWQucmF3LnJlc3VsdCB9KSxcblx0fSk7XG59XG5cbmZ1bmN0aW9uIHBhcnNlU3RyZWFtRGVzY3JpcHRpb24ocmF3OiB1bmtub3duKTogU3RyZWFtRGVzY3JpcHRpb24ge1xuXHRjb25zdCBoZWFkID0gcGFyc2VPcGVyYXRpb25IZWFkKHJhdywgXCJzdHJlYW1cIik7XG5cdGNvbnN0IGRlY2xhcmVkID0gaGVhZC5yYXcuZXZlbnRzO1xuXHRpZiAoIWlzUGxhaW5SZWNvcmQoZGVjbGFyZWQpIHx8IE9iamVjdC5rZXlzKGRlY2xhcmVkKS5sZW5ndGggPT09IDApIHtcblx0XHR0aHJvdyBuZXcgUWdpc1Nka0RlY2xhcmF0aW9uRXJyb3IoXG5cdFx0XHRgJHtoZWFkLmlkfTogZXZlbnRzIG11c3QgbWFwIGF0IGxlYXN0IG9uZSBldmVudCBraW5kIHRvIGEgc2NoZW1hYCxcblx0XHQpO1xuXHR9XG5cdGNvbnN0IGV2ZW50czogUGFydGlhbDxcblx0XHRSZWNvcmQ8U3RyZWFtRXZlbnRLaW5kLCBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4+XG5cdD4gPSB7fTtcblx0Zm9yIChjb25zdCBba2luZCwgc2NoZW1hXSBvZiBPYmplY3QuZW50cmllcyhkZWNsYXJlZCkpIHtcblx0XHRpZiAoIVNUUkVBTV9FVkVOVF9LSU5EUy5pbmNsdWRlcyhraW5kIGFzIFN0cmVhbUV2ZW50S2luZCkpIHtcblx0XHRcdHRocm93IG5ldyBRZ2lzU2RrRGVjbGFyYXRpb25FcnJvcihcblx0XHRcdFx0YCR7aGVhZC5pZH06ICR7a2luZH0gaXMgbm90IGEgc3RyZWFtIGV2ZW50IGtpbmRgLFxuXHRcdFx0KTtcblx0XHR9XG5cdFx0aWYgKCFpc1BsYWluUmVjb3JkKHNjaGVtYSkpIHtcblx0XHRcdHRocm93IG5ldyBRZ2lzU2RrRGVjbGFyYXRpb25FcnJvcihcblx0XHRcdFx0YCR7aGVhZC5pZH06IGV2ZW50cy4ke2tpbmR9IHNjaGVtYSBtdXN0IGJlIGFuIG9iamVjdGAsXG5cdFx0XHQpO1xuXHRcdH1cblx0XHRldmVudHNba2luZCBhcyBTdHJlYW1FdmVudEtpbmRdID0gT2JqZWN0LmZyZWV6ZSh7IC4uLnNjaGVtYSB9KTtcblx0fVxuXHRyZXR1cm4gT2JqZWN0LmZyZWV6ZSh7XG5cdFx0aWQ6IGhlYWQuaWQsXG5cdFx0dGl0bGU6IGhlYWQudGl0bGUsXG5cdFx0aGFuZGxlcjogaGVhZC5oYW5kbGVyLFxuXHRcdHJlcXVlc3Q6IGhlYWQucmVxdWVzdCxcblx0XHRldmVudHM6IE9iamVjdC5mcmVlemUoZXZlbnRzKSxcblx0fSk7XG59XG5cbi8qKlxuICogUGFyc2UgYW5kIHZhbGlkYXRlIGEgdmVyc2lvbiAxIGBQbHVnaW5EZXNjcmlwdGlvbmAgZW1pdHRlZCBieSBgZGVzY3JpYmVfcGx1Z2luYC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlUGx1Z2luRGVzY3JpcHRpb24oXG5cdGlucHV0OiBzdHJpbmcgfCBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4sXG4pOiBQbHVnaW5EZXNjcmlwdGlvbiB7XG5cdGxldCBwYXJzZWQ6IHVua25vd24gPSBpbnB1dDtcblx0aWYgKHR5cGVvZiBpbnB1dCA9PT0gXCJzdHJpbmdcIikge1xuXHRcdHRyeSB7XG5cdFx0XHRwYXJzZWQgPSBKU09OLnBhcnNlKGlucHV0KTtcblx0XHR9IGNhdGNoIHtcblx0XHRcdHRocm93IG5ldyBRZ2lzU2RrRGVjbGFyYXRpb25FcnJvcihcIlBsdWdpbiBkZXNjcmlwdGlvbiBpcyBub3QgdmFsaWQgSlNPTlwiKTtcblx0XHR9XG5cdH1cblx0aWYgKCFpc1BsYWluUmVjb3JkKHBhcnNlZCkpIHtcblx0XHR0aHJvdyBuZXcgUWdpc1Nka0RlY2xhcmF0aW9uRXJyb3IoXCJQbHVnaW4gZGVzY3JpcHRpb24gbXVzdCBiZSBhbiBvYmplY3RcIik7XG5cdH1cblx0aWYgKHBhcnNlZC5zY2hlbWFfdmVyc2lvbiAhPT0gUExVR0lOX0RFU0NSSVBUSU9OX1NDSEVNQV9WRVJTSU9OKSB7XG5cdFx0dGhyb3cgbmV3IFFnaXNTZGtEZWNsYXJhdGlvbkVycm9yKFxuXHRcdFx0YFVuc3VwcG9ydGVkIHBsdWdpbiBkZXNjcmlwdGlvbiBzY2hlbWFfdmVyc2lvbjogJHtTdHJpbmcocGFyc2VkLnNjaGVtYV92ZXJzaW9uKX1gLFxuXHRcdCk7XG5cdH1cblx0Y29uc3QgaWQgPSB2YWxpZGF0ZURlY2xhcmF0aW9uSWQocGFyc2VkLmlkLCBcInBsdWdpblwiKTtcblx0Y29uc3QgdGl0bGUgPSB2YWxpZGF0ZU5vbkJsYW5rVGl0bGUocGFyc2VkLnRpdGxlLCBpZCk7XG5cdGlmICghQXJyYXkuaXNBcnJheShwYXJzZWQuYWN0aW9ucykpIHtcblx0XHR0aHJvdyBuZXcgUWdpc1Nka0RlY2xhcmF0aW9uRXJyb3IoYCR7aWR9OiBhY3Rpb25zIG11c3QgYmUgYW4gYXJyYXlgKTtcblx0fVxuXHRjb25zdCBkZWNsYXJlZFN0cmVhbXMgPSBwYXJzZWQuc3RyZWFtcyA/PyBbXTtcblx0aWYgKCFBcnJheS5pc0FycmF5KGRlY2xhcmVkU3RyZWFtcykpIHtcblx0XHR0aHJvdyBuZXcgUWdpc1Nka0RlY2xhcmF0aW9uRXJyb3IoYCR7aWR9OiBzdHJlYW1zIG11c3QgYmUgYW4gYXJyYXlgKTtcblx0fVxuXHQvLyBBY3Rpb25zIGFuZCBzdHJlYW1zIHNoYXJlIG9uZSBpZCBuYW1lc3BhY2UgKGRlY2lzaW9uLTI4KS5cblx0Y29uc3Qgc2VlbklkcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuXHRjb25zdCBjbGFpbSA9IChvcGVyYXRpb25JZDogc3RyaW5nLCBsYWJlbDogc3RyaW5nKTogdm9pZCA9PiB7XG5cdFx0aWYgKHNlZW5JZHMuaGFzKG9wZXJhdGlvbklkKSkge1xuXHRcdFx0dGhyb3cgbmV3IFFnaXNTZGtEZWNsYXJhdGlvbkVycm9yKFxuXHRcdFx0XHRgJHtpZH06IGR1cGxpY2F0ZSAke2xhYmVsfSBpZCAke29wZXJhdGlvbklkfWAsXG5cdFx0XHQpO1xuXHRcdH1cblx0XHRzZWVuSWRzLmFkZChvcGVyYXRpb25JZCk7XG5cdH07XG5cdGNvbnN0IGFjdGlvbnM6IEFjdGlvbkRlc2NyaXB0aW9uW10gPSBbXTtcblx0Zm9yIChjb25zdCBpdGVtIG9mIHBhcnNlZC5hY3Rpb25zKSB7XG5cdFx0Y29uc3QgYWN0aW9uID0gcGFyc2VBY3Rpb25EZXNjcmlwdGlvbihpdGVtKTtcblx0XHRjbGFpbShhY3Rpb24uaWQsIFwiYWN0aW9uXCIpO1xuXHRcdGFjdGlvbnMucHVzaChhY3Rpb24pO1xuXHR9XG5cdGNvbnN0IHN0cmVhbXM6IFN0cmVhbURlc2NyaXB0aW9uW10gPSBbXTtcblx0Zm9yIChjb25zdCBpdGVtIG9mIGRlY2xhcmVkU3RyZWFtcykge1xuXHRcdGNvbnN0IHN0cmVhbSA9IHBhcnNlU3RyZWFtRGVzY3JpcHRpb24oaXRlbSk7XG5cdFx0Y2xhaW0oc3RyZWFtLmlkLCBcInN0cmVhbVwiKTtcblx0XHRzdHJlYW1zLnB1c2goc3RyZWFtKTtcblx0fVxuXHRjb25zdCBieUlkID0gKFxuXHRcdGxlZnQ6IHsgcmVhZG9ubHkgaWQ6IHN0cmluZyB9LFxuXHRcdHJpZ2h0OiB7IHJlYWRvbmx5IGlkOiBzdHJpbmcgfSxcblx0KTogbnVtYmVyID0+IChsZWZ0LmlkIDwgcmlnaHQuaWQgPyAtMSA6IDEpO1xuXHRhY3Rpb25zLnNvcnQoYnlJZCk7XG5cdHN0cmVhbXMuc29ydChieUlkKTtcblx0cmV0dXJuIE9iamVjdC5mcmVlemUoe1xuXHRcdHNjaGVtYV92ZXJzaW9uOiBQTFVHSU5fREVTQ1JJUFRJT05fU0NIRU1BX1ZFUlNJT04sXG5cdFx0aWQsXG5cdFx0dGl0bGUsXG5cdFx0YWN0aW9uczogT2JqZWN0LmZyZWV6ZShhY3Rpb25zKSxcblx0XHRzdHJlYW1zOiBPYmplY3QuZnJlZXplKHN0cmVhbXMpLFxuXHR9KTtcbn1cbiIKICBdLAogICJtYXBwaW5ncyI6ICI7QUFPTyxJQUFNLG9CQUEyQjtBQUNqQyxJQUFNLG9CQUEyQjtBQUNqQyxJQUFNLHFDQUF1QztBQWtEcEQsSUFBTSxxQkFBaUQ7QUFBQSxFQUN0RDtBQUFBLEVBQ0E7QUFBQSxFQUNBO0FBQ0Q7QUFLTyxTQUFTLGtCQUFpQixDQUFDLE9BQWlDO0FBQUEsRUFDbEUsT0FBTyxPQUFPLFVBQVUsWUFBWSxPQUFPLGNBQWMsS0FBSztBQUFBO0FBQUE7QUFNeEQsTUFBTSxzQkFBcUIsTUFBTTtBQUFBLEVBQ3ZCO0FBQUEsRUFFVCxXQUFXLENBQUMsU0FBaUIsT0FBZSxhQUFhO0FBQUEsSUFDL0QsTUFBTSxPQUFPO0FBQUEsSUFDYixLQUFLLE9BQU8sV0FBVztBQUFBLElBQ3ZCLEtBQUssT0FBTztBQUFBO0FBRWQ7QUFBQTtBQUtPLE1BQU0saUNBQWdDLGNBQWE7QUFBQSxFQUNsRCxXQUFXLEdBQUc7QUFBQSxJQUNwQixNQUFNLHlDQUF5QyxjQUFjO0FBQUE7QUFFL0Q7QUFBQTtBQUtPLE1BQU0sMkNBQTBDLGNBQWE7QUFBQSxFQUNuRDtBQUFBLEVBRVQsV0FBVyxDQUFDLFlBQW9CO0FBQUEsSUFDdEMsTUFDQyxjQUFjLEtBQUssVUFBVSxVQUFVLG9DQUN2Qyx3QkFDRDtBQUFBLElBQ0EsS0FBSyxhQUFhO0FBQUE7QUFFcEI7QUFBQTtBQUtPLE1BQU0saUNBQWdDLGNBQWE7QUFBQSxFQUNsRCxXQUFXLENBQUMsU0FBaUI7QUFBQSxJQUNuQyxNQUFNLFNBQVMscUJBQXFCO0FBQUE7QUFFdEM7QUFBQTtBQUtPLE1BQU0sd0JBQXVCO0FBQUEsRUFDbkI7QUFBQSxFQUNBO0FBQUEsRUFFVCxXQUFXLENBQUMsTUFBb0MsTUFBYztBQUFBLElBQ3BFLEtBQUssT0FBTyxPQUFPLE9BQU8sQ0FBQyxHQUFHLElB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QUssTUFBTTtBQUFBLEVBQ3BCO0FBQUEsRUFDQSxNQUFNLFVBQStCLENBQUM7QUFBQSxFQUN0QyxXQUFXLFFBQVEsaUJBQWlCO0FBQUEsSUFDbkMsTUFBTSxTQUFTLHVCQUF1QixJQUFJO0FBQUEsSUFDMUMsTUFBTSxPQUFPLElBQUksUUFBUTtBQUFBLElBQ3pCLFFBQVEsS0FBSyxNQUFNO0FBQUEsRUFDcEI7QUFBQSxFQUNBLE1BQU0sT0FBTyxDQUNaLE1BQ0EsVUFDYSxLQUFLLEtBQUssTUFBTSxLQUFLLEtBQUs7QUFBQSxFQUN4QyxRQUFRLEtBQUssSUFBSTtBQUFBLEVBQ2pCLFFBQVEsS0FBSyxJQUFJO0FBQUEsRUFDakIsT0FBTyxPQUFPLE9BQU87QUFBQSxJQUNwQixnQkFBZ0I7QUFBQSxJQUNoQjtBQUFBLElBQ0E7QUFBQSxJQUNBLFNBQVMsT0FBTyxPQUFPLE9BQU87QUFBQSxJQUM5QixTQUFTLE9BQU8sT0FBTyxPQUFPO0FBQUEsRUFDL0IsQ0FBQztBQUFBOyIsCiAgImRlYnVnSWQiOiAiQkY1Nzk1QUU3Q0NCMEI1NDY0NzU2RTIxNjQ3NTZFMjEiLAogICJuYW1lcyI6IFtdCn0=