@blinkk/root-cms 1.0.0-beta.9 → 1.0.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.js +93 -136
- package/dist/cli.js +59 -52
- package/dist/client.d.ts +186 -0
- package/dist/client.js +334 -0
- package/dist/core.d.ts +35 -21
- package/dist/core.js +495 -67
- package/dist/functions.d.ts +13 -0
- package/dist/functions.js +261 -0
- package/dist/plugin.d.ts +20 -3
- package/dist/plugin.js +386 -34
- package/dist/project.d.ts +1 -1
- package/dist/project.js +4 -1
- package/dist/{schema-e7beb758.d.ts → schema-49de9659.d.ts} +70 -48
- package/dist/ui/signin.css +10 -3
- package/dist/ui/signin.js +1401 -764
- package/dist/ui/ui.css +525 -192
- package/dist/ui/ui.js +15674 -11422
- package/package.json +52 -31
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as firebase_functions_v2_scheduler from 'firebase-functions/v2/scheduler';
|
|
2
|
+
import { ScheduleOptions } from 'firebase-functions/v2/scheduler';
|
|
3
|
+
|
|
4
|
+
interface CronOptions {
|
|
5
|
+
rootDir?: string;
|
|
6
|
+
scheduleOptions?: Partial<ScheduleOptions>;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Runs offline CMS tasks, such as publishing of scheduled docs.
|
|
10
|
+
*/
|
|
11
|
+
declare function cron(options?: CronOptions): firebase_functions_v2_scheduler.ScheduleFunction;
|
|
12
|
+
|
|
13
|
+
export { CronOptions, cron };
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
// core/functions.ts
|
|
2
|
+
import path3 from "node:path";
|
|
3
|
+
import { loadRootConfig } from "@blinkk/root/node";
|
|
4
|
+
import { onSchedule } from "firebase-functions/v2/scheduler";
|
|
5
|
+
|
|
6
|
+
// core/runtime.ts
|
|
7
|
+
import {
|
|
8
|
+
FieldValue as FieldValue2,
|
|
9
|
+
getFirestore as getFirestore2
|
|
10
|
+
} from "firebase-admin/firestore";
|
|
11
|
+
|
|
12
|
+
// core/client.ts
|
|
13
|
+
import path from "node:path";
|
|
14
|
+
import { viteSsrLoadModule } from "@blinkk/root/node";
|
|
15
|
+
import {
|
|
16
|
+
FieldValue,
|
|
17
|
+
Timestamp,
|
|
18
|
+
getFirestore
|
|
19
|
+
} from "firebase-admin/firestore";
|
|
20
|
+
function getCmsPlugin(rootConfig) {
|
|
21
|
+
const plugins = rootConfig.plugins || [];
|
|
22
|
+
const plugin = plugins.find((plugin2) => plugin2.name === "root-cms");
|
|
23
|
+
if (!plugin) {
|
|
24
|
+
throw new Error("could not find root-cms plugin config in root.config.ts");
|
|
25
|
+
}
|
|
26
|
+
return plugin;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// core/runtime.ts
|
|
30
|
+
async function publishScheduledDocs(rootConfig) {
|
|
31
|
+
const cmsPlugin = getCmsPlugin(rootConfig);
|
|
32
|
+
const cmsPluginOptions = cmsPlugin.getConfig();
|
|
33
|
+
const projectId = cmsPluginOptions.id || "default";
|
|
34
|
+
const app = cmsPlugin.getFirebaseApp();
|
|
35
|
+
const db = getFirestore2(app);
|
|
36
|
+
const projectCollectionsPath = `Projects/${projectId}/Collections`;
|
|
37
|
+
const now = Math.ceil((/* @__PURE__ */ new Date()).getTime());
|
|
38
|
+
const snapshot = await db.collectionGroup("Scheduled").get();
|
|
39
|
+
const docs = snapshot.docs.filter((d) => {
|
|
40
|
+
var _a;
|
|
41
|
+
if (!d.ref.path.startsWith(projectCollectionsPath)) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
const data = d.data() || {};
|
|
45
|
+
const scheduledAt = (_a = data.sys) == null ? void 0 : _a.scheduledAt;
|
|
46
|
+
return scheduledAt && scheduledAt.toMillis && scheduledAt.toMillis() <= now;
|
|
47
|
+
}).map((d) => {
|
|
48
|
+
const dbPath = d.ref.path;
|
|
49
|
+
const segments = dbPath.split("/");
|
|
50
|
+
const slug = segments.at(-1);
|
|
51
|
+
const collection = segments.at(-3);
|
|
52
|
+
const id = `${collection}/${slug}`;
|
|
53
|
+
return {
|
|
54
|
+
data: d.data(),
|
|
55
|
+
id,
|
|
56
|
+
collection,
|
|
57
|
+
slug
|
|
58
|
+
};
|
|
59
|
+
});
|
|
60
|
+
if (docs.length === 0) {
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
let batchCount = 0;
|
|
64
|
+
const batch = db.batch();
|
|
65
|
+
const publishedDocs = [];
|
|
66
|
+
for (const doc of docs) {
|
|
67
|
+
const { id, collection, slug, data } = doc;
|
|
68
|
+
const draftRef = db.doc(
|
|
69
|
+
`${projectCollectionsPath}/${collection}/Drafts/${slug}`
|
|
70
|
+
);
|
|
71
|
+
const scheduledRef = db.doc(
|
|
72
|
+
`${projectCollectionsPath}/${collection}/Scheduled/${slug}`
|
|
73
|
+
);
|
|
74
|
+
const publishedRef = db.doc(
|
|
75
|
+
`${projectCollectionsPath}/${collection}/Published/${slug}`
|
|
76
|
+
);
|
|
77
|
+
const { scheduledAt, scheduledBy, ...sys } = data.sys || {};
|
|
78
|
+
const firstPublishedAt = sys.firstPublishedAt ?? scheduledAt;
|
|
79
|
+
const firstPublishedBy = sys.firstPublishedBy ?? (scheduledBy || "");
|
|
80
|
+
batch.set(publishedRef, {
|
|
81
|
+
id,
|
|
82
|
+
collection,
|
|
83
|
+
slug,
|
|
84
|
+
fields: data.fields || {},
|
|
85
|
+
sys: {
|
|
86
|
+
...sys,
|
|
87
|
+
firstPublishedAt,
|
|
88
|
+
firstPublishedBy,
|
|
89
|
+
publishedAt: FieldValue2.serverTimestamp(),
|
|
90
|
+
publishedBy: scheduledBy || ""
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
batchCount += 1;
|
|
94
|
+
batch.delete(scheduledRef);
|
|
95
|
+
batchCount += 1;
|
|
96
|
+
batch.update(draftRef, {
|
|
97
|
+
"sys.scheduledAt": FieldValue2.delete(),
|
|
98
|
+
"sys.scheduledBy": FieldValue2.delete(),
|
|
99
|
+
"sys.firstPublishedAt": firstPublishedAt,
|
|
100
|
+
"sys.firstPublishedBy": firstPublishedBy,
|
|
101
|
+
"sys.publishedAt": FieldValue2.serverTimestamp(),
|
|
102
|
+
"sys.publishedBy": scheduledBy || ""
|
|
103
|
+
});
|
|
104
|
+
batchCount += 1;
|
|
105
|
+
publishedDocs.push(doc);
|
|
106
|
+
if (batchCount >= 498) {
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
await batch.commit();
|
|
111
|
+
console.log(`published ${publishedDocs.length} docs!`);
|
|
112
|
+
return publishedDocs;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// core/versions.ts
|
|
116
|
+
import path2 from "node:path";
|
|
117
|
+
import {
|
|
118
|
+
Timestamp as Timestamp3,
|
|
119
|
+
getFirestore as getFirestore3
|
|
120
|
+
} from "firebase-admin/firestore";
|
|
121
|
+
import glob from "tiny-glob";
|
|
122
|
+
var DOCUMENT_SAVE_OFFSET = 5 * 60 * 1e3;
|
|
123
|
+
var VersionsService = class {
|
|
124
|
+
constructor(rootConfig) {
|
|
125
|
+
this.rootConfig = rootConfig;
|
|
126
|
+
const cmsPlugin = getCmsPlugin(rootConfig);
|
|
127
|
+
const cmsPluginOptions = cmsPlugin.getConfig();
|
|
128
|
+
const projectId = cmsPluginOptions.id || "default";
|
|
129
|
+
this.projectId = projectId;
|
|
130
|
+
const app = cmsPlugin.getFirebaseApp();
|
|
131
|
+
this.db = getFirestore3(app);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Saves a version of all documents that have been edited since the last run.
|
|
135
|
+
*/
|
|
136
|
+
async saveVersions() {
|
|
137
|
+
const lastRun = await this.getLastRun();
|
|
138
|
+
const lastRunWithOffset = lastRun === 0 ? lastRun : lastRun - DOCUMENT_SAVE_OFFSET;
|
|
139
|
+
const changedDocs = await this.getDocsModifiedAfter(lastRunWithOffset);
|
|
140
|
+
const now = Timestamp3.now().toMillis();
|
|
141
|
+
const versions = changedDocs.filter((doc) => {
|
|
142
|
+
const modifiedAt = doc.sys.modifiedAt.toMillis();
|
|
143
|
+
return modifiedAt <= now - DOCUMENT_SAVE_OFFSET;
|
|
144
|
+
});
|
|
145
|
+
if (versions.length > 0) {
|
|
146
|
+
this.saveVersionsToFirestore(versions);
|
|
147
|
+
}
|
|
148
|
+
this.saveLastRun(now);
|
|
149
|
+
}
|
|
150
|
+
async saveVersionsToFirestore(versions) {
|
|
151
|
+
const batch = this.db.batch();
|
|
152
|
+
versions.forEach((version) => {
|
|
153
|
+
var _a;
|
|
154
|
+
if (!version.collection || !version.slug || !((_a = version.sys) == null ? void 0 : _a.modifiedAt)) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
const modifiedAtMillis = version.sys.modifiedAt.toMillis();
|
|
158
|
+
const versionPath = `Projects/${this.projectId}/Collections/${version.collection}/Drafts/${version.slug}/Versions/${modifiedAtMillis}`;
|
|
159
|
+
console.log(versionPath);
|
|
160
|
+
const versionRef = this.db.doc(versionPath);
|
|
161
|
+
batch.set(versionRef, version);
|
|
162
|
+
});
|
|
163
|
+
await batch.commit();
|
|
164
|
+
console.log(`versions: saved ${versions.length} versions`);
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Returns the last time (in millis) saveVersions() was run, or 0 if has
|
|
168
|
+
* never been run.
|
|
169
|
+
*/
|
|
170
|
+
async getLastRun() {
|
|
171
|
+
const projectDocRef = this.db.collection("Projects").doc(this.projectId);
|
|
172
|
+
const projectDoc = await projectDocRef.get();
|
|
173
|
+
if (projectDoc.exists) {
|
|
174
|
+
const data = projectDoc.data() || {};
|
|
175
|
+
const ts = data.versionsLastRun;
|
|
176
|
+
if (ts) {
|
|
177
|
+
return ts.toMillis();
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return 0;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Saves {versionLastRun: <timestamp>} to the Projects/<projectId> doc.
|
|
184
|
+
*/
|
|
185
|
+
async saveLastRun(millis) {
|
|
186
|
+
const ts = Timestamp3.fromMillis(millis);
|
|
187
|
+
const projectDocRef = this.db.collection("Projects").doc(this.projectId);
|
|
188
|
+
await projectDocRef.set({ versionsLastRun: ts }, { merge: true });
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Returns a list of all docs that were edited after a certain time.
|
|
192
|
+
*/
|
|
193
|
+
async getDocsModifiedAfter(millis) {
|
|
194
|
+
const ts = Timestamp3.fromMillis(millis);
|
|
195
|
+
const results = [];
|
|
196
|
+
const collectionIds = await this.listCollections();
|
|
197
|
+
for (const collectionId of collectionIds) {
|
|
198
|
+
const collectionPath = `Projects/${this.projectId}/Collections/${collectionId}/Drafts`;
|
|
199
|
+
const query = this.db.collection(collectionPath).where("sys.modifiedAt", ">=", ts);
|
|
200
|
+
const querySnapshot = await query.get();
|
|
201
|
+
querySnapshot.forEach((doc) => {
|
|
202
|
+
results.push(doc.data());
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
return results;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Returns a list of collection ids for the Root project.
|
|
209
|
+
*/
|
|
210
|
+
async listCollections() {
|
|
211
|
+
const collectionIds = [];
|
|
212
|
+
const collectionFileNames = await glob("*.schema.ts", {
|
|
213
|
+
cwd: path2.join(this.rootConfig.rootDir, "collections")
|
|
214
|
+
});
|
|
215
|
+
collectionFileNames.forEach((filename) => {
|
|
216
|
+
collectionIds.push(filename.slice(0, -10));
|
|
217
|
+
});
|
|
218
|
+
return collectionIds;
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
// core/cron.ts
|
|
223
|
+
async function runCronJobs(rootConfig) {
|
|
224
|
+
await Promise.all([
|
|
225
|
+
runCronJob("publishScheduledDocs", runPublishScheduledDocs, rootConfig),
|
|
226
|
+
runCronJob("saveVersions", runSaveVersions, rootConfig)
|
|
227
|
+
]);
|
|
228
|
+
}
|
|
229
|
+
async function runCronJob(name, fn, ...args) {
|
|
230
|
+
try {
|
|
231
|
+
await fn(...args);
|
|
232
|
+
} catch (err) {
|
|
233
|
+
console.log(`cron failed: ${name}`);
|
|
234
|
+
console.error(String(err.stack || err));
|
|
235
|
+
throw err;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
async function runPublishScheduledDocs(rootConfig) {
|
|
239
|
+
await publishScheduledDocs(rootConfig);
|
|
240
|
+
}
|
|
241
|
+
async function runSaveVersions(rootConfig) {
|
|
242
|
+
const service = new VersionsService(rootConfig);
|
|
243
|
+
await service.saveVersions();
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// core/functions.ts
|
|
247
|
+
function cron(options) {
|
|
248
|
+
const rootDir = path3.resolve((options == null ? void 0 : options.rootDir) || process.cwd());
|
|
249
|
+
const scheduleOptions = {
|
|
250
|
+
schedule: "every 1 mins",
|
|
251
|
+
...options == null ? void 0 : options.scheduleOptions
|
|
252
|
+
};
|
|
253
|
+
return onSchedule(scheduleOptions, async () => {
|
|
254
|
+
const rootConfig = await loadRootConfig(rootDir, { command: "cms-cron" });
|
|
255
|
+
await runCronJobs(rootConfig);
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
export {
|
|
259
|
+
cron
|
|
260
|
+
};
|
|
261
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vY29yZS9mdW5jdGlvbnMudHMiLCAiLi4vY29yZS9ydW50aW1lLnRzIiwgIi4uL2NvcmUvY2xpZW50LnRzIiwgIi4uL2NvcmUvdmVyc2lvbnMudHMiLCAiLi4vY29yZS9jcm9uLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyJpbXBvcnQgcGF0aCBmcm9tICdub2RlOnBhdGgnO1xuaW1wb3J0IHtsb2FkUm9vdENvbmZpZ30gZnJvbSAnQGJsaW5ray9yb290L25vZGUnO1xuaW1wb3J0IHtTY2hlZHVsZU9wdGlvbnMsIG9uU2NoZWR1bGV9IGZyb20gJ2ZpcmViYXNlLWZ1bmN0aW9ucy92Mi9zY2hlZHVsZXInO1xuaW1wb3J0IHtydW5Dcm9uSm9ic30gZnJvbSAnLi9jcm9uLmpzJztcblxuZXhwb3J0IGludGVyZmFjZSBDcm9uT3B0aW9ucyB7XG4gIHJvb3REaXI/OiBzdHJpbmc7XG4gIHNjaGVkdWxlT3B0aW9ucz86IFBhcnRpYWw8U2NoZWR1bGVPcHRpb25zPjtcbn1cblxuLyoqXG4gKiBSdW5zIG9mZmxpbmUgQ01TIHRhc2tzLCBzdWNoIGFzIHB1Ymxpc2hpbmcgb2Ygc2NoZWR1bGVkIGRvY3MuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcm9uKG9wdGlvbnM/OiBDcm9uT3B0aW9ucykge1xuICBjb25zdCByb290RGlyID0gcGF0aC5yZXNvbHZlKG9wdGlvbnM/LnJvb3REaXIgfHwgcHJvY2Vzcy5jd2QoKSk7XG4gIGNvbnN0IHNjaGVkdWxlT3B0aW9uczogU2NoZWR1bGVPcHRpb25zID0ge1xuICAgIHNjaGVkdWxlOiAnZXZlcnkgMSBtaW5zJyxcbiAgICAuLi5vcHRpb25zPy5zY2hlZHVsZU9wdGlvbnMsXG4gIH07XG4gIHJldHVybiBvblNjaGVkdWxlKHNjaGVkdWxlT3B0aW9ucywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHJvb3RDb25maWcgPSBhd2FpdCBsb2FkUm9vdENvbmZpZyhyb290RGlyLCB7Y29tbWFuZDogJ2Ntcy1jcm9uJ30pO1xuICAgIGF3YWl0IHJ1bkNyb25Kb2JzKHJvb3RDb25maWcpO1xuICB9KTtcbn1cbiIsICIvKiogQGRlcHJlY2F0ZWQgVXNlIGNsaWVudC50cyBpbnN0ZWFkLiAqL1xuXG5pbXBvcnQge1Jvb3RDb25maWd9IGZyb20gJ0BibGlua2svcm9vdCc7XG5pbXBvcnQge1xuICBGaWVsZFZhbHVlLFxuICBRdWVyeSxcbiAgVGltZXN0YW1wLFxuICBnZXRGaXJlc3RvcmUsXG59IGZyb20gJ2ZpcmViYXNlLWFkbWluL2ZpcmVzdG9yZSc7XG5pbXBvcnQge2dldENtc1BsdWdpbiwgdW5tYXJzaGFsRGF0YX0gZnJvbSAnLi9jbGllbnQuanMnO1xuXG4vKipcbiAqIFJldHJpZXZlcyBhIGRvYyBmcm9tIFJvb3QuanMgQ01TLlxuICogQGRlcHJlY2F0ZWQgVXNlIFJvb3RDTVNDbGllbnQuZ2V0RG9jKCkgaW5zdGVhZC5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldERvYzxUPihcbiAgcm9vdENvbmZpZzogUm9vdENvbmZpZyxcbiAgY29sbGVjdGlvbklkOiBzdHJpbmcsXG4gIHNsdWc6IHN0cmluZyxcbiAgb3B0aW9uczoge1xuICAgIG1vZGU6ICdkcmFmdCcgfCAncHVibGlzaGVkJztcbiAgfVxuKTogUHJvbWlzZTxUIHwgbnVsbD4ge1xuICBjb25zdCBjbXNQbHVnaW4gPSBnZXRDbXNQbHVnaW4ocm9vdENvbmZpZyk7XG4gIGNvbnN0IGNtc1BsdWdpbk9wdGlvbnMgPSBjbXNQbHVnaW4uZ2V0Q29uZmlnKCk7XG4gIGNvbnN0IHByb2plY3RJZCA9IGNtc1BsdWdpbk9wdGlvbnMuaWQgfHwgJ2RlZmF1bHQnO1xuICBjb25zdCBtb2RlID0gb3B0aW9ucy5tb2RlO1xuICBjb25zdCBtb2RlQ29sbGVjdGlvbiA9IG1vZGUgPT09ICdkcmFmdCcgPyAnRHJhZnRzJyA6ICdQdWJsaXNoZWQnO1xuICBjb25zdCBhcHAgPSBjbXNQbHVnaW4uZ2V0RmlyZWJhc2VBcHAoKTtcbiAgY29uc3QgZGIgPSBnZXRGaXJlc3RvcmUoYXBwKTtcbiAgLy8gU2x1Z3Mgd2l0aCBzbGFzaGVzIGFyZSBlbmNvZGVkIGFzIGAtLWAgaW4gdGhlIERCLlxuICBzbHVnID0gc2x1Zy5yZXBsYWNlQWxsKCcvJywgJy0tJyk7XG4gIGNvbnN0IGRiUGF0aCA9IGBQcm9qZWN0cy8ke3Byb2plY3RJZH0vQ29sbGVjdGlvbnMvJHtjb2xsZWN0aW9uSWR9LyR7bW9kZUNvbGxlY3Rpb259LyR7c2x1Z31gO1xuICBjb25zdCBkb2NSZWYgPSBkYi5kb2MoZGJQYXRoKTtcbiAgY29uc3QgZG9jID0gYXdhaXQgZG9jUmVmLmdldCgpO1xuICBpZiAoZG9jLmV4aXN0cykge1xuICAgIGNvbnN0IGRhdGEgPSBkb2MuZGF0YSgpO1xuICAgIHJldHVybiB1bm1hcnNoYWxEYXRhKGRhdGEpIGFzIFQ7XG4gIH1cbiAgY29uc29sZS5sb2coYGRvYyBub3QgZm91bmQ6ICR7ZGJQYXRofWApO1xuICByZXR1cm4gbnVsbDtcbn1cblxuLyoqXG4gKiBMaXN0cyBkb2NzIGZyb20gYSBSb290LmpzIENNUyBjb2xsZWN0aW9uLlxuICogQGRlcHJlY2F0ZWQgVXNlIFJvb3RDTVNDbGllbnQubGlzdERvY3MoKSBpbnN0ZWFkLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbGlzdERvY3M8VD4oXG4gIHJvb3RDb25maWc6IFJvb3RDb25maWcsXG4gIGNvbGxlY3Rpb25JZDogc3RyaW5nLFxuICBvcHRpb25zOiB7XG4gICAgbW9kZTogJ2RyYWZ0JyB8ICdwdWJsaXNoZWQnO1xuICAgIG9mZnNldD86IG51bWJlcjtcbiAgICBsaW1pdD86IG51bWJlcjtcbiAgICBvcmRlckJ5Pzogc3RyaW5nO1xuICAgIG9yZGVyQnlEaXJlY3Rpb24/OiAnYXNjJyB8ICdkZXNjJztcbiAgICBxdWVyeT86IChxdWVyeTogUXVlcnkpID0+IFF1ZXJ5O1xuICB9XG4pOiBQcm9taXNlPHtkb2NzOiBUW119PiB7XG4gIGNvbnN0IGNtc1BsdWdpbiA9IGdldENtc1BsdWdpbihyb290Q29uZmlnKTtcbiAgY29uc3QgY21zUGx1Z2luT3B0aW9ucyA9IGNtc1BsdWdpbi5nZXRDb25maWcoKTtcbiAgY29uc3QgcHJvamVjdElkID0gY21zUGx1Z2luT3B0aW9ucy5pZCB8fCAnZGVmYXVsdCc7XG4gIGNvbnN0IG1vZGUgPSBvcHRpb25zLm1vZGU7XG4gIGNvbnN0IG1vZGVDb2xsZWN0aW9uID0gbW9kZSA9PT0gJ2RyYWZ0JyA/ICdEcmFmdHMnIDogJ1B1Ymxpc2hlZCc7XG4gIGNvbnN0IGFwcCA9IGNtc1BsdWdpbi5nZXRGaXJlYmFzZUFwcCgpO1xuICBjb25zdCBkYiA9IGdldEZpcmVzdG9yZShhcHApO1xuICBjb25zdCBkYlBhdGggPSBgUHJvamVjdHMvJHtwcm9qZWN0SWR9L0NvbGxlY3Rpb25zLyR7Y29sbGVjdGlvbklkfS8ke21vZGVDb2xsZWN0aW9ufWA7XG4gIGxldCBxdWVyeTogUXVlcnkgPSBkYi5jb2xsZWN0aW9uKGRiUGF0aCk7XG4gIGlmIChvcHRpb25zLmxpbWl0KSB7XG4gICAgcXVlcnkgPSBxdWVyeS5saW1pdChvcHRpb25zLmxpbWl0KTtcbiAgfVxuICBpZiAob3B0aW9ucy5vZmZzZXQpIHtcbiAgICBxdWVyeSA9IHF1ZXJ5Lm9mZnNldChvcHRpb25zLm9mZnNldCk7XG4gIH1cbiAgaWYgKG9wdGlvbnMub3JkZXJCeSkge1xuICAgIHF1ZXJ5ID0gcXVlcnkub3JkZXJCeShvcHRpb25zLm9yZGVyQnksIG9wdGlvbnMub3JkZXJCeURpcmVjdGlvbik7XG4gIH1cbiAgaWYgKG9wdGlvbnMucXVlcnkpIHtcbiAgICBxdWVyeSA9IG9wdGlvbnMucXVlcnkocXVlcnkpO1xuICB9XG4gIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCBxdWVyeS5nZXQoKTtcbiAgY29uc3QgZG9jczogVFtdID0gW107XG4gIHJlc3VsdHMuZm9yRWFjaCgocmVzdWx0KSA9PiB7XG4gICAgY29uc3QgZG9jID0gdW5tYXJzaGFsRGF0YShyZXN1bHQuZGF0YSgpKSBhcyBUO1xuICAgIGRvY3MucHVzaChkb2MpO1xuICB9KTtcbiAgcmV0dXJuIHtkb2NzfTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBudW1iZXIgb2YgZG9jcyBpbiBhIFJvb3QuanMgQ01TIGNvbGxlY3Rpb24uXG4gKiBAZGVwcmVjYXRlZCBVc2UgUm9vdENNU0NsaWVudC5nZXREb2NzQ291bnQoKSBpbnN0ZWFkLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbnVtRG9jcyhcbiAgcm9vdENvbmZpZzogUm9vdENvbmZpZyxcbiAgY29sbGVjdGlvbklkOiBzdHJpbmcsXG4gIG9wdGlvbnM6IHtcbiAgICBtb2RlOiAnZHJhZnQnIHwgJ3B1Ymxpc2hlZCc7XG4gICAgcXVlcnk/OiAocXVlcnk6IFF1ZXJ5KSA9PiBRdWVyeTtcbiAgfVxuKSB7XG4gIGNvbnN0IGNtc1BsdWdpbiA9IGdldENtc1BsdWdpbihyb290Q29uZmlnKTtcbiAgY29uc3QgY21zUGx1Z2luT3B0aW9ucyA9IGNtc1BsdWdpbi5nZXRDb25maWcoKTtcbiAgY29uc3QgcHJvamVjdElkID0gY21zUGx1Z2luT3B0aW9ucy5pZCB8fCAnZGVmYXVsdCc7XG4gIGNvbnN0IG1vZGUgPSBvcHRpb25zLm1vZGU7XG4gIGNvbnN0IG1vZGVDb2xsZWN0aW9uID0gbW9kZSA9PT0gJ2RyYWZ0JyA/ICdEcmFmdHMnIDogJ1B1Ymxpc2hlZCc7XG4gIGNvbnN0IGFwcCA9IGNtc1BsdWdpbi5nZXRGaXJlYmFzZUFwcCgpO1xuICBjb25zdCBkYiA9IGdldEZpcmVzdG9yZShhcHApO1xuICBjb25zdCBkYlBhdGggPSBgUHJvamVjdHMvJHtwcm9qZWN0SWR9L0NvbGxlY3Rpb25zLyR7Y29sbGVjdGlvbklkfS8ke21vZGVDb2xsZWN0aW9ufWA7XG4gIGxldCBxdWVyeTogUXVlcnkgPSBkYi5jb2xsZWN0aW9uKGRiUGF0aCk7XG4gIGlmIChvcHRpb25zLnF1ZXJ5KSB7XG4gICAgcXVlcnkgPSBvcHRpb25zLnF1ZXJ5KHF1ZXJ5KTtcbiAgfVxuICBjb25zdCByZXN1bHRzID0gYXdhaXQgcXVlcnkuY291bnQoKS5nZXQoKTtcbiAgY29uc3QgY291bnQgPSByZXN1bHRzLmRhdGEoKS5jb3VudDtcbiAgcmV0dXJuIGNvdW50O1xufVxuXG4vKipcbiAqIFB1Ymxpc2hlcyBzY2hlZHVsZWQgZG9jcy5cbiAqIEBkZXByZWNhdGVkIFVzZSBSb290Q01TQ2xpZW50LnB1Ymxpc2hTY2hlZHVsZWREb2NzKCkgaW5zdGVhZC5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHB1Ymxpc2hTY2hlZHVsZWREb2NzKHJvb3RDb25maWc6IFJvb3RDb25maWcpIHtcbiAgY29uc3QgY21zUGx1Z2luID0gZ2V0Q21zUGx1Z2luKHJvb3RDb25maWcpO1xuICBjb25zdCBjbXNQbHVnaW5PcHRpb25zID0gY21zUGx1Z2luLmdldENvbmZpZygpO1xuICBjb25zdCBwcm9qZWN0SWQgPSBjbXNQbHVnaW5PcHRpb25zLmlkIHx8ICdkZWZhdWx0JztcbiAgY29uc3QgYXBwID0gY21zUGx1Z2luLmdldEZpcmViYXNlQXBwKCk7XG4gIGNvbnN0IGRiID0gZ2V0RmlyZXN0b3JlKGFwcCk7XG5cbiAgY29uc3QgcHJvamVjdENvbGxlY3Rpb25zUGF0aCA9IGBQcm9qZWN0cy8ke3Byb2plY3RJZH0vQ29sbGVjdGlvbnNgO1xuICBjb25zdCBub3cgPSBNYXRoLmNlaWwobmV3IERhdGUoKS5nZXRUaW1lKCkpO1xuXG4gIGNvbnN0IHNuYXBzaG90ID0gYXdhaXQgZGIuY29sbGVjdGlvbkdyb3VwKCdTY2hlZHVsZWQnKS5nZXQoKTtcbiAgY29uc3QgZG9jcyA9IHNuYXBzaG90LmRvY3NcbiAgICAuZmlsdGVyKChkKSA9PiB7XG4gICAgICAvLyBGaWx0ZXIgZG9jcyBieSBwcm9qZWN0LlxuICAgICAgaWYgKCFkLnJlZi5wYXRoLnN0YXJ0c1dpdGgocHJvamVjdENvbGxlY3Rpb25zUGF0aCkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgLy8gRmlsdGVyIGRvY3Mgd2hlcmUgc2NoZWR1bGVkQXQgaXMgaW4gdGhlIHBhc3QuXG4gICAgICAvLyBOT1RFKHN0ZXZlbmxlKTogdGhlIGZpbHRlcmluZyBpcyBkb25lIG1hbnVhbGx5IGluc3RlYWQgb2YgdXNpbmcgYSBxdWVyeVxuICAgICAgLy8gdG8gYXZvaWQgaGF2aW5nIHRvIGNyZWF0ZSBhbiBpbmRleCBpbiBmaXJlc3RvcmUuXG4gICAgICBjb25zdCBkYXRhID0gZC5kYXRhKCkgfHwge307XG4gICAgICBjb25zdCBzY2hlZHVsZWRBdDogVGltZXN0YW1wIHwgdW5kZWZpbmVkID0gZGF0YS5zeXM/LnNjaGVkdWxlZEF0O1xuICAgICAgcmV0dXJuIChcbiAgICAgICAgc2NoZWR1bGVkQXQgJiYgc2NoZWR1bGVkQXQudG9NaWxsaXMgJiYgc2NoZWR1bGVkQXQudG9NaWxsaXMoKSA8PSBub3dcbiAgICAgICk7XG4gICAgfSlcbiAgICAubWFwKChkKSA9PiB7XG4gICAgICBjb25zdCBkYlBhdGggPSBkLnJlZi5wYXRoO1xuICAgICAgY29uc3Qgc2VnbWVudHMgPSBkYlBhdGguc3BsaXQoJy8nKTtcbiAgICAgIGNvbnN0IHNsdWcgPSBzZWdtZW50cy5hdCgtMSk7XG4gICAgICBjb25zdCBjb2xsZWN0aW9uID0gc2VnbWVudHMuYXQoLTMpO1xuICAgICAgY29uc3QgaWQgPSBgJHtjb2xsZWN0aW9ufS8ke3NsdWd9YDtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGRhdGE6IGQuZGF0YSgpLFxuICAgICAgICBpZCxcbiAgICAgICAgY29sbGVjdGlvbixcbiAgICAgICAgc2x1ZyxcbiAgICAgIH07XG4gICAgfSk7XG5cbiAgaWYgKGRvY3MubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgLy8gRWFjaCB0cmFuc2FjdGlvbiBvciBiYXRjaCBjYW4gd3JpdGUgYSBtYXggb2YgNTAwIG9wcy5cbiAgLy8gaHR0cHM6Ly9maXJlYmFzZS5nb29nbGUuY29tL2RvY3MvZmlyZXN0b3JlL21hbmFnZS1kYXRhL3RyYW5zYWN0aW9uc1xuICBsZXQgYmF0Y2hDb3VudCA9IDA7XG4gIGNvbnN0IGJhdGNoID0gZGIuYmF0Y2goKTtcbiAgY29uc3QgcHVibGlzaGVkRG9jczogYW55W10gPSBbXTtcbiAgZm9yIChjb25zdCBkb2Mgb2YgZG9jcykge1xuICAgIGNvbnN0IHtpZCwgY29sbGVjdGlvbiwgc2x1ZywgZGF0YX0gPSBkb2M7XG4gICAgY29uc3QgZHJhZnRSZWYgPSBkYi5kb2MoXG4gICAgICBgJHtwcm9qZWN0Q29sbGVjdGlvbnNQYXRofS8ke2NvbGxlY3Rpb259L0RyYWZ0cy8ke3NsdWd9YFxuICAgICk7XG4gICAgY29uc3Qgc2NoZWR1bGVkUmVmID0gZGIuZG9jKFxuICAgICAgYCR7cHJvamVjdENvbGxlY3Rpb25zUGF0aH0vJHtjb2xsZWN0aW9ufS9TY2hlZHVsZWQvJHtzbHVnfWBcbiAgICApO1xuICAgIGNvbnN0IHB1Ymxpc2hlZFJlZiA9IGRiLmRvYyhcbiAgICAgIGAke3Byb2plY3RDb2xsZWN0aW9uc1BhdGh9LyR7Y29sbGVjdGlvbn0vUHVibGlzaGVkLyR7c2x1Z31gXG4gICAgKTtcbiAgICBjb25zdCB7c2NoZWR1bGVkQXQsIHNjaGVkdWxlZEJ5LCAuLi5zeXN9ID0gZGF0YS5zeXMgfHwge307XG5cbiAgICAvLyBPbmx5IHVwZGF0ZSBgZmlyc3RQdWJsaXNoZWRgIGlmIGl0IGRvZXNuJ3QgYWxyZWFkeSBleGlzdC5cbiAgICBjb25zdCBmaXJzdFB1Ymxpc2hlZEF0ID0gc3lzLmZpcnN0UHVibGlzaGVkQXQgPz8gc2NoZWR1bGVkQXQ7XG4gICAgY29uc3QgZmlyc3RQdWJsaXNoZWRCeSA9IHN5cy5maXJzdFB1Ymxpc2hlZEJ5ID8/IChzY2hlZHVsZWRCeSB8fCAnJyk7XG5cbiAgICAvLyBTYXZlIHB1Ymxpc2hlZCBkb2MuXG4gICAgYmF0Y2guc2V0KHB1Ymxpc2hlZFJlZiwge1xuICAgICAgaWQsXG4gICAgICBjb2xsZWN0aW9uLFxuICAgICAgc2x1ZyxcbiAgICAgIGZpZWxkczogZGF0YS5maWVsZHMgfHwge30sXG4gICAgICBzeXM6IHtcbiAgICAgICAgLi4uc3lzLFxuICAgICAgICBmaXJzdFB1Ymxpc2hlZEF0OiBmaXJzdFB1Ymxpc2hlZEF0LFxuICAgICAgICBmaXJzdFB1Ymxpc2hlZEJ5OiBmaXJzdFB1Ymxpc2hlZEJ5LFxuICAgICAgICBwdWJsaXNoZWRBdDogRmllbGRWYWx1ZS5zZXJ2ZXJUaW1lc3RhbXAoKSxcbiAgICAgICAgcHVibGlzaGVkQnk6IHNjaGVkdWxlZEJ5IHx8ICcnLFxuICAgICAgfSxcbiAgICB9KTtcbiAgICBiYXRjaENvdW50ICs9IDE7XG5cbiAgICAvLyBSZW1vdmUgcHVibGlzaGVkIGRvYy5cbiAgICBiYXRjaC5kZWxldGUoc2NoZWR1bGVkUmVmKTtcbiAgICBiYXRjaENvdW50ICs9IDE7XG5cbiAgICAvLyBVcGRhdGUgdGhlIGRyYWZ0IGRvYyB0byByZW1vdmUgYHNjaGVkdWxlZEF0YCBhbmQgYHNjaGVkdWxlZEJ5YCBmaWVsZHNcbiAgICAvLyBhbmQgdXBkYXRlIHRoZSBgcHVibGlzaGVkQXRgIGFuZCBgcHVibGlzaGVkQnlgIGZpZWxkcy5cbiAgICBiYXRjaC51cGRhdGUoZHJhZnRSZWYsIHtcbiAgICAgICdzeXMuc2NoZWR1bGVkQXQnOiBGaWVsZFZhbHVlLmRlbGV0ZSgpLFxuICAgICAgJ3N5cy5zY2hlZHVsZWRCeSc6IEZpZWxkVmFsdWUuZGVsZXRlKCksXG4gICAgICAnc3lzLmZpcnN0UHVibGlzaGVkQXQnOiBmaXJzdFB1Ymxpc2hlZEF0LFxuICAgICAgJ3N5cy5maXJzdFB1Ymxpc2hlZEJ5JzogZmlyc3RQdWJsaXNoZWRCeSxcbiAgICAgICdzeXMucHVibGlzaGVkQXQnOiBGaWVsZFZhbHVlLnNlcnZlclRpbWVzdGFtcCgpLFxuICAgICAgJ3N5cy5wdWJsaXNoZWRCeSc6IHNjaGVkdWxlZEJ5IHx8ICcnLFxuICAgIH0pO1xuICAgIGJhdGNoQ291bnQgKz0gMTtcblxuICAgIHB1Ymxpc2hlZERvY3MucHVzaChkb2MpO1xuXG4gICAgaWYgKGJhdGNoQ291bnQgPj0gNDk4KSB7XG4gICAgICBicmVhaztcbiAgICB9XG4gIH1cblxuICBhd2FpdCBiYXRjaC5jb21taXQoKTtcbiAgY29uc29sZS5sb2coYHB1Ymxpc2hlZCAke3B1Ymxpc2hlZERvY3MubGVuZ3RofSBkb2NzIWApO1xuICByZXR1cm4gcHVibGlzaGVkRG9jcztcbn1cbiIsICJpbXBvcnQgcGF0aCBmcm9tICdub2RlOnBhdGgnO1xuaW1wb3J0IHtQbHVnaW4sIFJvb3RDb25maWd9IGZyb20gJ0BibGlua2svcm9vdCc7XG5pbXBvcnQge3ZpdGVTc3JMb2FkTW9kdWxlfSBmcm9tICdAYmxpbmtrL3Jvb3Qvbm9kZSc7XG5pbXBvcnQge0FwcH0gZnJvbSAnZmlyZWJhc2UtYWRtaW4vYXBwJztcbmltcG9ydCB7XG4gIEZpZWxkVmFsdWUsXG4gIEZpcmVzdG9yZSxcbiAgUXVlcnksXG4gIFRpbWVzdGFtcCxcbiAgZ2V0RmlyZXN0b3JlLFxufSBmcm9tICdmaXJlYmFzZS1hZG1pbi9maXJlc3RvcmUnO1xuaW1wb3J0IHtDTVNQbHVnaW59IGZyb20gJy4vcGx1Z2luLmpzJztcbmltcG9ydCB7U2NoZW1hfSBmcm9tICcuL3NjaGVtYS5qcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgRG9jPEZpZWxkcyA9IGFueT4ge1xuICAvKiogVGhlIGlkIG9mIHRoZSBkb2MsIGUuZy4gXCJQYWdlcy9mb28tYmFyXCIuICovXG4gIGlkOiBzdHJpbmc7XG4gIC8qKiBUaGUgY29sbGVjdGlvbiBpZCBvZiB0aGUgZG9jLCBlLmcuIFwiUGFnZXNcIi4gKi9cbiAgY29sbGVjdGlvbklkOiBzdHJpbmc7XG4gIC8qKiBUaGUgc2x1ZyBvZiB0aGUgZG9jLCBlLmcuIFwiZm9vLWJhclwiLiAqL1xuICBzbHVnOiBzdHJpbmc7XG4gIHN5czoge1xuICAgIGNyZWF0ZWRBdDogbnVtYmVyO1xuICAgIGNyZWF0ZWRCeTogc3RyaW5nO1xuICAgIG1vZGlmaWVkQXQ6IG51bWJlcjtcbiAgICBtb2RpZmllZEJ5OiBzdHJpbmc7XG4gICAgZmlyc3RQdWJsaXNoZWRBdD86IG51bWJlcjtcbiAgICBmaXJzdFB1Ymxpc2hlZEJ5Pzogc3RyaW5nO1xuICAgIHB1Ymxpc2hlZEF0PzogbnVtYmVyO1xuICAgIHB1Ymxpc2hlZEJ5Pzogc3RyaW5nO1xuICAgIGxvY2FsZXM/OiBzdHJpbmdbXTtcbiAgfTtcbiAgZmllbGRzOiBGaWVsZHM7XG59XG5cbmV4cG9ydCB0eXBlIERvY01vZGUgPSAnZHJhZnQnIHwgJ3B1Ymxpc2hlZCc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgR2V0RG9jT3B0aW9ucyB7XG4gIC8qKiBNb2RlLCBlaXRoZXIgXCJkcmFmdFwiIG9yIFwicHVibGlzaGVkXCIuICovXG4gIG1vZGU6IERvY01vZGU7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2V0RG9jT3B0aW9ucyB7XG4gIC8qKiBNb2RlLCBlaXRoZXIgXCJkcmFmdFwiIG9yIFwicHVibGlzaGVkXCIuICovXG4gIG1vZGU6IERvY01vZGU7XG4gIC8qKlxuICAgKiBFbWFpbCBvZiB1c2VyIG1vZGlmeWluZyB0aGUgZG9jLiBJZiBibGFuaywgZGVmYXVsdHMgdG8gYHJvb3QtY21zLWNsaWVudGAuXG4gICAqL1xuICBtb2RpZmllZEJ5Pzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIExpc3REb2NzT3B0aW9ucyB7XG4gIG1vZGU6IERvY01vZGU7XG4gIG9mZnNldD86IG51bWJlcjtcbiAgbGltaXQ/OiBudW1iZXI7XG4gIG9yZGVyQnk/OiBzdHJpbmc7XG4gIG9yZGVyQnlEaXJlY3Rpb24/OiAnYXNjJyB8ICdkZXNjJztcbiAgcXVlcnk/OiAocXVlcnk6IFF1ZXJ5KSA9PiBRdWVyeTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBHZXRDb3VudE9wdGlvbnMge1xuICBtb2RlOiBEb2NNb2RlO1xuICBxdWVyeT86IChxdWVyeTogUXVlcnkpID0+IFF1ZXJ5O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFRyYW5zbGF0aW9uIHtcbiAgW2xvY2FsZTogc3RyaW5nXTogc3RyaW5nO1xuICBzb3VyY2U6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBUcmFuc2xhdGlvbnNNYXAge1xuICBbaGFzaDogc3RyaW5nXTogVHJhbnNsYXRpb247XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTG9jYWxlVHJhbnNsYXRpb25zIHtcbiAgW3NvdXJjZTogc3RyaW5nXTogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIExvYWRUcmFuc2xhdGlvbnNPcHRpb25zIHtcbiAgdGFncz86IHN0cmluZ1tdO1xufVxuXG5leHBvcnQgY2xhc3MgUm9vdENNU0NsaWVudCB7XG4gIHByaXZhdGUgcmVhZG9ubHkgcm9vdENvbmZpZzogUm9vdENvbmZpZztcbiAgcHJpdmF0ZSByZWFkb25seSBjbXNQbHVnaW46IENNU1BsdWdpbjtcbiAgcHJpdmF0ZSByZWFkb25seSBwcm9qZWN0SWQ6IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBhcHA6IEFwcDtcbiAgcHJpdmF0ZSByZWFkb25seSBkYjogRmlyZXN0b3JlO1xuXG4gIGNvbnN0cnVjdG9yKHJvb3RDb25maWc6IFJvb3RDb25maWcpIHtcbiAgICB0aGlzLnJvb3RDb25maWcgPSByb290Q29uZmlnO1xuICAgIHRoaXMuY21zUGx1Z2luID0gZ2V0Q21zUGx1Z2luKHJvb3RDb25maWcpO1xuXG4gICAgY29uc3QgY21zUGx1Z2luT3B0aW9ucyA9IHRoaXMuY21zUGx1Z2luLmdldENvbmZpZygpO1xuICAgIHRoaXMucHJvamVjdElkID0gY21zUGx1Z2luT3B0aW9ucy5pZCB8fCAnZGVmYXVsdCc7XG4gICAgdGhpcy5hcHAgPSB0aGlzLmNtc1BsdWdpbi5nZXRGaXJlYmFzZUFwcCgpO1xuICAgIHRoaXMuZGIgPSBnZXRGaXJlc3RvcmUodGhpcy5hcHApO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXZlcyBkb2MgZGF0YSBmcm9tIFJvb3QuanMgQ01TLlxuICAgKi9cbiAgYXN5bmMgZ2V0RG9jPEZpZWxkcyA9IGFueT4oXG4gICAgY29sbGVjdGlvbklkOiBzdHJpbmcsXG4gICAgc2x1Zzogc3RyaW5nLFxuICAgIG9wdGlvbnM6IEdldERvY09wdGlvbnNcbiAgKTogUHJvbWlzZTxEb2M8RmllbGRzPiB8IG51bGw+IHtcbiAgICBjb25zdCByYXdEYXRhID0gYXdhaXQgdGhpcy5nZXRSYXdEb2MoY29sbGVjdGlvbklkLCBzbHVnLCBvcHRpb25zKTtcbiAgICBpZiAocmF3RGF0YSkge1xuICAgICAgcmV0dXJuIHVubWFyc2hhbERhdGEocmF3RGF0YSkgYXMgRG9jPEZpZWxkcz47XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXZlcyByYXcgZG9jIGRhdGEgYXMgc3RvcmVkIGluIHRoZSBkYXRhYmFzZS4gT25seSB1c2UgdGhpcyBpZiB5b3Uga25vd1xuICAgKiB3aGF0IHlvdSBhcmUgZG9pbmcuXG4gICAqL1xuICBhc3luYyBnZXRSYXdEb2MoXG4gICAgY29sbGVjdGlvbklkOiBzdHJpbmcsXG4gICAgc2x1Zzogc3RyaW5nLFxuICAgIG9wdGlvbnM6IEdldERvY09wdGlvbnNcbiAgKTogUHJvbWlzZTxhbnkgfCBudWxsPiB7XG4gICAgY29uc3QgbW9kZSA9IG9wdGlvbnMubW9kZTtcbiAgICBjb25zdCBtb2RlQ29sbGVjdGlvbiA9IG1vZGUgPT09ICdkcmFmdCcgPyAnRHJhZnRzJyA6ICdQdWJsaXNoZWQnO1xuICAgIC8vIFNsdWdzIHdpdGggc2xhc2hlcyBhcmUgZW5jb2RlZCBhcyBgLS1gIGluIHRoZSBEQi5cbiAgICBzbHVnID0gc2x1Zy5yZXBsYWNlQWxsKCcvJywgJy0tJyk7XG4gICAgY29uc3QgZGJQYXRoID0gYFByb2plY3RzLyR7dGhpcy5wcm9qZWN0SWR9L0NvbGxlY3Rpb25zLyR7Y29sbGVjdGlvbklkfS8ke21vZGVDb2xsZWN0aW9ufS8ke3NsdWd9YDtcbiAgICBjb25zdCBkb2NSZWYgPSB0aGlzLmRiLmRvYyhkYlBhdGgpO1xuICAgIGNvbnN0IGRvYyA9IGF3YWl0IGRvY1JlZi5nZXQoKTtcbiAgICBpZiAoZG9jLmV4aXN0cykge1xuICAgICAgcmV0dXJuIGRvYy5kYXRhKCk7XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgZGF0YSBmb3IgYSBkb2MuXG4gICAqL1xuICBhc3luYyBzZXREb2MoXG4gICAgY29sbGVjdGlvbklkOiBzdHJpbmcsXG4gICAgc2x1Zzogc3RyaW5nLFxuICAgIGRhdGE6IERvYyxcbiAgICBvcHRpb25zOiBTZXREb2NPcHRpb25zXG4gICkge1xuICAgIGNvbnN0IHNjaGVtYSA9IGF3YWl0IHRoaXMuZ2V0U2NoZW1hKGNvbGxlY3Rpb25JZCk7XG4gICAgaWYgKCFzY2hlbWEpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgc2NoZW1hIG5vdCBmb3VuZCBmb3I6ICR7Y29sbGVjdGlvbklkfWApO1xuICAgIH1cbiAgICBjb25zdCByYXdEYXRhID0gbWFyc2hhbERhdGEoZGF0YSwgc2NoZW1hKTtcbiAgICBjb25zdCBtb2RpZmllZEJ5ID0gb3B0aW9ucy5tb2RpZmllZEJ5IHx8ICdyb290LWNtcy1jbGllbnQnO1xuXG4gICAgLy8gVXBkYXRlIHN5cyBjcmVhdGVkL21vZGlmaWVkIHRpbWVzLlxuICAgIGlmICghcmF3RGF0YS5zeXMpIHtcbiAgICAgIGNvbnN0IGN1cnJlbnREYXRhID0gYXdhaXQgdGhpcy5nZXRSYXdEb2MoY29sbGVjdGlvbklkLCBzbHVnLCB7XG4gICAgICAgIG1vZGU6IG9wdGlvbnMubW9kZSxcbiAgICAgIH0pO1xuICAgICAgaWYgKGN1cnJlbnREYXRhKSB7XG4gICAgICAgIHJhd0RhdGEuc3lzID0gY3VycmVudERhdGE/LnN5cyB8fCB7fTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJhd0RhdGEuc3lzLmNyZWF0ZWRBdCA9IFRpbWVzdGFtcC5ub3coKTtcbiAgICAgICAgcmF3RGF0YS5zeXMuY3JlYXRlZEJ5ID0gbW9kaWZpZWRCeTtcbiAgICAgICAgcmF3RGF0YS5zeXMubG9jYWxlcyA9IFsnZW4nXTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmF3RGF0YS5zeXMubW9kaWZpZWRBdCA9IFRpbWVzdGFtcC5ub3coKTtcbiAgICByYXdEYXRhLnN5cy5tb2RpZmllZEJ5ID0gbW9kaWZpZWRCeTtcblxuICAgIGF3YWl0IHRoaXMuc2V0UmF3RG9jKGNvbGxlY3Rpb25JZCwgc2x1ZywgcmF3RGF0YSwgb3B0aW9ucyk7XG4gIH1cblxuICBhc3luYyBzZXRSYXdEb2MoXG4gICAgY29sbGVjdGlvbklkOiBzdHJpbmcsXG4gICAgc2x1Zzogc3RyaW5nLFxuICAgIGRhdGE6IGFueSxcbiAgICBvcHRpb25zOiBTZXREb2NPcHRpb25zXG4gICkge1xuICAgIGNvbnN0IG1vZGUgPSBvcHRpb25zLm1vZGU7XG4gICAgY29uc3QgbW9kZUNvbGxlY3Rpb24gPSBtb2RlID09PSAnZHJhZnQnID8gJ0RyYWZ0cycgOiAnUHVibGlzaGVkJztcbiAgICBjb25zdCBkYlBhdGggPSBgUHJvamVjdHMvJHt0aGlzLnByb2plY3RJZH0vQ29sbGVjdGlvbnMvJHtjb2xsZWN0aW9uSWR9LyR7bW9kZUNvbGxlY3Rpb259LyR7c2x1Z31gO1xuICAgIGNvbnN0IGRvY1JlZiA9IHRoaXMuZGIuZG9jKGRiUGF0aCk7XG4gICAgYXdhaXQgZG9jUmVmLnNldChkYXRhKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMaXN0cyBkb2NzIGZyb20gYSBSb290LmpzIENNUyBjb2xsZWN0aW9uLlxuICAgKi9cbiAgYXN5bmMgbGlzdERvY3M8VD4oXG4gICAgY29sbGVjdGlvbklkOiBzdHJpbmcsXG4gICAgb3B0aW9uczogTGlzdERvY3NPcHRpb25zXG4gICk6IFByb21pc2U8e2RvY3M6IFRbXX0+IHtcbiAgICBjb25zdCBtb2RlID0gb3B0aW9ucy5tb2RlO1xuICAgIGNvbnN0IG1vZGVDb2xsZWN0aW9uID0gbW9kZSA9PT0gJ2RyYWZ0JyA/ICdEcmFmdHMnIDogJ1B1Ymxpc2hlZCc7XG4gICAgY29uc3QgZGJQYXRoID0gYFByb2plY3RzLyR7dGhpcy5wcm9qZWN0SWR9L0NvbGxlY3Rpb25zLyR7Y29sbGVjdGlvbklkfS8ke21vZGVDb2xsZWN0aW9ufWA7XG4gICAgbGV0IHF1ZXJ5OiBRdWVyeSA9IHRoaXMuZGIuY29sbGVjdGlvbihkYlBhdGgpO1xuICAgIGlmIChvcHRpb25zLmxpbWl0KSB7XG4gICAgICBxdWVyeSA9IHF1ZXJ5LmxpbWl0KG9wdGlvbnMubGltaXQpO1xuICAgIH1cbiAgICBpZiAob3B0aW9ucy5vZmZzZXQpIHtcbiAgICAgIHF1ZXJ5ID0gcXVlcnkub2Zmc2V0KG9wdGlvbnMub2Zmc2V0KTtcbiAgICB9XG4gICAgaWYgKG9wdGlvbnMub3JkZXJCeSkge1xuICAgICAgcXVlcnkgPSBxdWVyeS5vcmRlckJ5KG9wdGlvbnMub3JkZXJCeSwgb3B0aW9ucy5vcmRlckJ5RGlyZWN0aW9uKTtcbiAgICB9XG4gICAgaWYgKG9wdGlvbnMucXVlcnkpIHtcbiAgICAgIHF1ZXJ5ID0gb3B0aW9ucy5xdWVyeShxdWVyeSk7XG4gICAgfVxuICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCBxdWVyeS5nZXQoKTtcbiAgICBjb25zdCBkb2NzOiBUW10gPSBbXTtcbiAgICByZXN1bHRzLmZvckVhY2goKHJlc3VsdCkgPT4ge1xuICAgICAgY29uc3QgZG9jID0gdW5tYXJzaGFsRGF0YShyZXN1bHQuZGF0YSgpKSBhcyBUO1xuICAgICAgZG9jcy5wdXNoKGRvYyk7XG4gICAgfSk7XG4gICAgcmV0dXJuIHtkb2NzfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBudW1iZXIgb2YgZG9jcyBpbiBhIFJvb3QuanMgQ01TIGNvbGxlY3Rpb24uXG4gICAqL1xuICBhc3luYyBnZXREb2NzQ291bnQoY29sbGVjdGlvbklkOiBzdHJpbmcsIG9wdGlvbnM6IEdldENvdW50T3B0aW9ucykge1xuICAgIGNvbnN0IG1vZGUgPSBvcHRpb25zLm1vZGU7XG4gICAgY29uc3QgbW9kZUNvbGxlY3Rpb24gPSBtb2RlID09PSAnZHJhZnQnID8gJ0RyYWZ0cycgOiAnUHVibGlzaGVkJztcbiAgICBjb25zdCBkYlBhdGggPSBgUHJvamVjdHMvJHt0aGlzLnByb2plY3RJZH0vQ29sbGVjdGlvbnMvJHtjb2xsZWN0aW9uSWR9LyR7bW9kZUNvbGxlY3Rpb259YDtcbiAgICBsZXQgcXVlcnk6IFF1ZXJ5ID0gdGhpcy5kYi5jb2xsZWN0aW9uKGRiUGF0aCk7XG4gICAgaWYgKG9wdGlvbnMucXVlcnkpIHtcbiAgICAgIHF1ZXJ5ID0gb3B0aW9ucy5xdWVyeShxdWVyeSk7XG4gICAgfVxuICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCBxdWVyeS5jb3VudCgpLmdldCgpO1xuICAgIGNvbnN0IGNvdW50ID0gcmVzdWx0cy5kYXRhKCkuY291bnQ7XG4gICAgcmV0dXJuIGNvdW50O1xuICB9XG5cbiAgLyoqXG4gICAqIFB1Ymxpc2hlcyBzY2hlZHVsZWQgZG9jcy5cbiAgICovXG4gIGFzeW5jIHB1Ymxpc2hTY2hlZHVsZWREb2NzKCkge1xuICAgIGNvbnN0IHByb2plY3RDb2xsZWN0aW9uc1BhdGggPSBgUHJvamVjdHMvJHt0aGlzLnByb2plY3RJZH0vQ29sbGVjdGlvbnNgO1xuICAgIGNvbnN0IG5vdyA9IE1hdGguY2VpbChuZXcgRGF0ZSgpLmdldFRpbWUoKSk7XG5cbiAgICBjb25zdCBzbmFwc2hvdCA9IGF3YWl0IHRoaXMuZGIuY29sbGVjdGlvbkdyb3VwKCdTY2hlZHVsZWQnKS5nZXQoKTtcbiAgICBjb25zdCBkb2NzID0gc25hcHNob3QuZG9jc1xuICAgICAgLmZpbHRlcigoZCkgPT4ge1xuICAgICAgICAvLyBGaWx0ZXIgZG9jcyBieSBwcm9qZWN0LlxuICAgICAgICBpZiAoIWQucmVmLnBhdGguc3RhcnRzV2l0aChwcm9qZWN0Q29sbGVjdGlvbnNQYXRoKSkge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICAvLyBGaWx0ZXIgZG9jcyB3aGVyZSBzY2hlZHVsZWRBdCBpcyBpbiB0aGUgcGFzdC5cbiAgICAgICAgLy8gTk9URShzdGV2ZW5sZSk6IHRoZSBmaWx0ZXJpbmcgaXMgZG9uZSBtYW51YWxseSBpbnN0ZWFkIG9mIHVzaW5nIGEgcXVlcnlcbiAgICAgICAgLy8gdG8gYXZvaWQgaGF2aW5nIHRvIGNyZWF0ZSBhbiBpbmRleCBpbiBmaXJlc3RvcmUuXG4gICAgICAgIGNvbnN0IGRhdGEgPSBkLmRhdGEoKSB8fCB7fTtcbiAgICAgICAgY29uc3Qgc2NoZWR1bGVkQXQ6IFRpbWVzdGFtcCB8IHVuZGVmaW5lZCA9IGRhdGEuc3lzPy5zY2hlZHVsZWRBdDtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICBzY2hlZHVsZWRBdCAmJiBzY2hlZHVsZWRBdC50b01pbGxpcyAmJiBzY2hlZHVsZWRBdC50b01pbGxpcygpIDw9IG5vd1xuICAgICAgICApO1xuICAgICAgfSlcbiAgICAgIC5tYXAoKGQpID0+IHtcbiAgICAgICAgY29uc3QgZGJQYXRoID0gZC5yZWYucGF0aDtcbiAgICAgICAgY29uc3Qgc2VnbWVudHMgPSBkYlBhdGguc3BsaXQoJy8nKTtcbiAgICAgICAgY29uc3Qgc2x1ZyA9IHNlZ21lbnRzLmF0KC0xKTtcbiAgICAgICAgY29uc3QgY29sbGVjdGlvbiA9IHNlZ21lbnRzLmF0KC0zKTtcbiAgICAgICAgY29uc3QgaWQgPSBgJHtjb2xsZWN0aW9ufS8ke3NsdWd9YDtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBkYXRhOiBkLmRhdGEoKSxcbiAgICAgICAgICBpZCxcbiAgICAgICAgICBjb2xsZWN0aW9uLFxuICAgICAgICAgIHNsdWcsXG4gICAgICAgIH07XG4gICAgICB9KTtcblxuICAgIGlmIChkb2NzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgY29uc29sZS5sb2coJ25vIGRvY3MgdG8gc2NoZWR1bGUnKTtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9XG5cbiAgICAvLyBFYWNoIHRyYW5zYWN0aW9uIG9yIGJhdGNoIGNhbiB3cml0ZSBhIG1heCBvZiA1MDAgb3BzLlxuICAgIC8vIGh0dHBzOi8vZmlyZWJhc2UuZ29vZ2xlLmNvbS9kb2NzL2ZpcmVzdG9yZS9tYW5hZ2UtZGF0YS90cmFuc2FjdGlvbnNcbiAgICBsZXQgYmF0Y2hDb3VudCA9IDA7XG4gICAgY29uc3QgYmF0Y2ggPSB0aGlzLmRiLmJhdGNoKCk7XG4gICAgY29uc3QgcHVibGlzaGVkRG9jczogYW55W10gPSBbXTtcbiAgICBmb3IgKGNvbnN0IGRvYyBvZiBkb2NzKSB7XG4gICAgICBjb25zdCB7aWQsIGNvbGxlY3Rpb24sIHNsdWcsIGRhdGF9ID0gZG9jO1xuICAgICAgY29uc3QgZHJhZnRSZWYgPSB0aGlzLmRiLmRvYyhcbiAgICAgICAgYCR7cHJvamVjdENvbGxlY3Rpb25zUGF0aH0vJHtjb2xsZWN0aW9ufS9EcmFmdHMvJHtzbHVnfWBcbiAgICAgICk7XG4gICAgICBjb25zdCBzY2hlZHVsZWRSZWYgPSB0aGlzLmRiLmRvYyhcbiAgICAgICAgYCR7cHJvamVjdENvbGxlY3Rpb25zUGF0aH0vJHtjb2xsZWN0aW9ufS9TY2hlZHVsZWQvJHtzbHVnfWBcbiAgICAgICk7XG4gICAgICBjb25zdCBwdWJsaXNoZWRSZWYgPSB0aGlzLmRiLmRvYyhcbiAgICAgICAgYCR7cHJvamVjdENvbGxlY3Rpb25zUGF0aH0vJHtjb2xsZWN0aW9ufS9QdWJsaXNoZWQvJHtzbHVnfWBcbiAgICAgICk7XG4gICAgICBjb25zdCB7c2NoZWR1bGVkQXQsIHNjaGVkdWxlZEJ5LCAuLi5zeXN9ID0gZGF0YS5zeXMgfHwge307XG5cbiAgICAgIC8vIE9ubHkgdXBkYXRlIGBmaXJzdFB1Ymxpc2hlZGAgaWYgaXQgZG9lc24ndCBhbHJlYWR5IGV4aXN0LlxuICAgICAgY29uc3QgZmlyc3RQdWJsaXNoZWRBdCA9IHN5cy5maXJzdFB1Ymxpc2hlZEF0ID8/IHNjaGVkdWxlZEF0O1xuICAgICAgY29uc3QgZmlyc3RQdWJsaXNoZWRCeSA9IHN5cy5maXJzdFB1Ymxpc2hlZEJ5ID8/IChzY2hlZHVsZWRCeSB8fCAnJyk7XG5cbiAgICAgIC8vIFNhdmUgcHVibGlzaGVkIGRvYy5cbiAgICAgIGJhdGNoLnNldChwdWJsaXNoZWRSZWYsIHtcbiAgICAgICAgaWQsXG4gICAgICAgIGNvbGxlY3Rpb24sXG4gICAgICAgIHNsdWcsXG4gICAgICAgIGZpZWxkczogZGF0YS5maWVsZHMgfHwge30sXG4gICAgICAgIHN5czoge1xuICAgICAgICAgIC4uLnN5cyxcbiAgICAgICAgICBmaXJzdFB1Ymxpc2hlZEF0OiBmaXJzdFB1Ymxpc2hlZEF0LFxuICAgICAgICAgIGZpcnN0UHVibGlzaGVkQnk6IGZpcnN0UHVibGlzaGVkQnksXG4gICAgICAgICAgcHVibGlzaGVkQXQ6IEZpZWxkVmFsdWUuc2VydmVyVGltZXN0YW1wKCksXG4gICAgICAgICAgcHVibGlzaGVkQnk6IHNjaGVkdWxlZEJ5IHx8ICcnLFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgICBiYXRjaENvdW50ICs9IDE7XG5cbiAgICAgIC8vIFJlbW92ZSBwdWJsaXNoZWQgZG9jLlxuICAgICAgYmF0Y2guZGVsZXRlKHNjaGVkdWxlZFJlZik7XG4gICAgICBiYXRjaENvdW50ICs9IDE7XG5cbiAgICAgIC8vIFVwZGF0ZSB0aGUgZHJhZnQgZG9jIHRvIHJlbW92ZSBgc2NoZWR1bGVkQXRgIGFuZCBgc2NoZWR1bGVkQnlgIGZpZWxkc1xuICAgICAgLy8gYW5kIHVwZGF0ZSB0aGUgYHB1Ymxpc2hlZEF0YCBhbmQgYHB1Ymxpc2hlZEJ5YCBmaWVsZHMuXG4gICAgICBiYXRjaC51cGRhdGUoZHJhZnRSZWYsIHtcbiAgICAgICAgJ3N5cy5zY2hlZHVsZWRBdCc6IEZpZWxkVmFsdWUuZGVsZXRlKCksXG4gICAgICAgICdzeXMuc2NoZWR1bGVkQnknOiBGaWVsZFZhbHVlLmRlbGV0ZSgpLFxuICAgICAgICAnc3lzLmZpcnN0UHVibGlzaGVkQXQnOiBmaXJzdFB1Ymxpc2hlZEF0LFxuICAgICAgICAnc3lzLmZpcnN0UHVibGlzaGVkQnknOiBmaXJzdFB1Ymxpc2hlZEJ5LFxuICAgICAgICAnc3lzLnB1Ymxpc2hlZEF0JzogRmllbGRWYWx1ZS5zZXJ2ZXJUaW1lc3RhbXAoKSxcbiAgICAgICAgJ3N5cy5wdWJsaXNoZWRCeSc6IHNjaGVkdWxlZEJ5IHx8ICcnLFxuICAgICAgfSk7XG4gICAgICBiYXRjaENvdW50ICs9IDE7XG5cbiAgICAgIHB1Ymxpc2hlZERvY3MucHVzaChkb2MpO1xuXG4gICAgICBpZiAoYmF0Y2hDb3VudCA+PSA0OTgpIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgYXdhaXQgYmF0Y2guY29tbWl0KCk7XG4gICAgY29uc29sZS5sb2coYHB1Ymxpc2hlZCAke3B1Ymxpc2hlZERvY3MubGVuZ3RofSBkb2NzIWApO1xuICAgIHJldHVybiBwdWJsaXNoZWREb2NzO1xuICB9XG5cbiAgLyoqXG4gICAqIExvYWRzIHRyYW5zbGF0aW9ucyBzYXZlZCBpbiB0aGUgdHJhbnNsYXRpb25zIGNvbGxlY3Rpb24sIG9wdGlvbmFsbHlcbiAgICogZmlsdGVyZWQgYnkgdGFnLlxuICAgKlxuICAgKiBSZXR1cm5zIGEgbWFwIGxpa2U6XG4gICAqIGBgYFxuICAgKiB7XG4gICAqICAgXCI8aGFzaD5cIjoge1wic291cmNlXCI6IFwiSGVsbG9cIiwgXCJlc1wiOiBcIkhvbGFcIiwgXCJmclwiOiBcIkJvbmpvdXJcIn0sXG4gICAqIH1cbiAgICogYGBgXG4gICAqL1xuICBhc3luYyBsb2FkVHJhbnNsYXRpb25zKFxuICAgIG9wdGlvbnM/OiBMb2FkVHJhbnNsYXRpb25zT3B0aW9uc1xuICApOiBQcm9taXNlPFRyYW5zbGF0aW9uc01hcD4ge1xuICAgIGNvbnN0IGRiUGF0aCA9IGBQcm9qZWN0cy8ke3RoaXMucHJvamVjdElkfS9UcmFuc2xhdGlvbnNgO1xuICAgIGxldCBxdWVyeTogUXVlcnkgPSB0aGlzLmRiLmNvbGxlY3Rpb24oZGJQYXRoKTtcbiAgICBpZiAob3B0aW9ucz8udGFncykge1xuICAgICAgcXVlcnkgPSBxdWVyeS53aGVyZSgndGFncycsICdhcnJheS1jb250YWlucy1hbnknLCBvcHRpb25zLnRhZ3MpO1xuICAgIH1cblxuICAgIGNvbnN0IHF1ZXJ5U25hcHNob3QgPSBhd2FpdCBxdWVyeS5nZXQoKTtcbiAgICBjb25zdCB0cmFuc2xhdGlvbnNNYXA6IFRyYW5zbGF0aW9uc01hcCA9IHt9O1xuICAgIHF1ZXJ5U25hcHNob3QuZm9yRWFjaCgoZG9jKSA9PiB7XG4gICAgICBjb25zdCBoYXNoID0gZG9jLmlkO1xuICAgICAgdHJhbnNsYXRpb25zTWFwW2hhc2hdID0gZG9jLmRhdGEoKSBhcyBUcmFuc2xhdGlvbjtcbiAgICB9KTtcbiAgICByZXR1cm4gdHJhbnNsYXRpb25zTWFwO1xuICB9XG5cbiAgLyoqXG4gICAqIExvYWRzIHRyYW5zbGF0aW9ucyBmb3IgYSBwYXJ0aWN1bGFyIGxvY2FsZS5cbiAgICpcbiAgICogUmV0dXJucyBhIG1hcCBsaWtlOlxuICAgKiBgYGBcbiAgICoge1xuICAgKiAgIFwiSGVsbG9cIjogXCJCb25qb3VyXCIsXG4gICAqIH1cbiAgICogYGBgXG4gICAqL1xuICBhc3luYyBsb2FkVHJhbnNsYXRpb25zRm9yTG9jYWxlKFxuICAgIGxvY2FsZTogc3RyaW5nLFxuICAgIG9wdGlvbnM/OiBMb2FkVHJhbnNsYXRpb25zT3B0aW9uc1xuICApOiBQcm9taXNlPExvY2FsZVRyYW5zbGF0aW9ucz4ge1xuICAgIGNvbnN0IHRyYW5zbGF0aW9uc01hcCA9IGF3YWl0IHRoaXMubG9hZFRyYW5zbGF0aW9ucyhvcHRpb25zKTtcbiAgICByZXR1cm4gdHJhbnNsYXRpb25zRm9yTG9jYWxlKHRyYW5zbGF0aW9uc01hcCwgbG9jYWxlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMb2FkcyB0aGUgc2NoZW1hIGZvciBhIGdpdmVuIGNvbGxlY3Rpb24uXG4gICAqL1xuICBhc3luYyBnZXRTY2hlbWEoY29sbGVjdGlvbklkOiBzdHJpbmcpOiBQcm9taXNlPFNjaGVtYSB8IG51bGw+IHtcbiAgICBjb25zdCBzY2hlbWFGaWxlID0gcGF0aC5qb2luKCcvY29sbGVjdGlvbnMnLCBgJHtjb2xsZWN0aW9uSWR9LnNjaGVtYS50c2ApO1xuICAgIGNvbnN0IHNjaGVtYU1vZHVsZSA9IGF3YWl0IHZpdGVTc3JMb2FkTW9kdWxlKHRoaXMucm9vdENvbmZpZywgc2NoZW1hRmlsZSk7XG4gICAgcmV0dXJuIHNjaGVtYU1vZHVsZT8uZGVmYXVsdCB8fCBudWxsO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRDbXNQbHVnaW4ocm9vdENvbmZpZzogUm9vdENvbmZpZyk6IENNU1BsdWdpbiB7XG4gIGNvbnN0IHBsdWdpbnM6IFBsdWdpbltdID0gcm9vdENvbmZpZy5wbHVnaW5zIHx8IFtdO1xuICBjb25zdCBwbHVnaW4gPSBwbHVnaW5zLmZpbmQoKHBsdWdpbikgPT4gcGx1Z2luLm5hbWUgPT09ICdyb290LWNtcycpO1xuICBpZiAoIXBsdWdpbikge1xuICAgIHRocm93IG5ldyBFcnJvcignY291bGQgbm90IGZpbmQgcm9vdC1jbXMgcGx1Z2luIGNvbmZpZyBpbiByb290LmNvbmZpZy50cycpO1xuICB9XG4gIHJldHVybiBwbHVnaW4gYXMgQ01TUGx1Z2luO1xufVxuXG4vKipcbiAqIFdhbGtzIHRoZSBkYXRhIHRyZWUgYW5kIGNvbnZlcnRzIGFueSBUaW1lc3RhbXAgb2JqZWN0cyB0byBtaWxsaXMgYW5kIGFueVxuICogX2FycmF5IG1hcHMgdG8gbm9ybWFsIGFycmF5cy5cbiAqXG4gKiBFLmcuOlxuICpcbiAqIG5vcm1hbGl6ZURhdGEoe1xuICogICBzeXM6IHttb2RpZmllZEF0OiBUaW1lc3RhbXAoMTIzKX0sXG4gKiAgIGZpZWxkczoge1xuICogICAgIF9hcnJheTogWydhc2RmJ10sXG4gKiAgICAgYXNkZjoge3RpdGxlOiAnaGVsbG8nfVxuICogICB9XG4gKiB9KVxuICogLy8gPT4ge3N5czoge21vZGlmaWVkQXQ6IDEyM30sIGZpZWxkczoge2ZvbzogW3t0aXRsZTogJ2hlbGxvJ31dfX1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVubWFyc2hhbERhdGEoZGF0YTogYW55KTogYW55IHtcbiAgY29uc3QgcmVzdWx0OiBhbnkgPSB7fTtcbiAgZm9yIChjb25zdCBrZXkgaW4gZGF0YSkge1xuICAgIGNvbnN0IHZhbCA9IGRhdGFba2V5XTtcbiAgICBpZiAoaXNPYmplY3QodmFsKSkge1xuICAgICAgaWYgKHZhbC50b01pbGxpcykge1xuICAgICAgICByZXN1bHRba2V5XSA9IHZhbC50b01pbGxpcygpO1xuICAgICAgfSBlbHNlIGlmIChPYmplY3QuaGFzT3duKHZhbCwgJ19hcnJheScpICYmIEFycmF5LmlzQXJyYXkodmFsLl9hcnJheSkpIHtcbiAgICAgICAgY29uc3QgYXJyID0gdmFsLl9hcnJheS5tYXAoKGs6IHN0cmluZykgPT4gdW5tYXJzaGFsRGF0YSh2YWxba10gfHwge30pKTtcbiAgICAgICAgcmVzdWx0W2tleV0gPSBhcnI7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXN1bHRba2V5XSA9IHVubWFyc2hhbERhdGEodmFsKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgcmVzdWx0W2tleV0gPSB2YWw7XG4gICAgfVxuICB9XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbi8qKiBAZGVwcmVjYXRlZCBVc2UgYHVubWFyc2hhbERhdGEoKWAgaW5zdGVhZC4gKi9cbmV4cG9ydCBmdW5jdGlvbiBub3JtYWxpemVEYXRhKGRhdGE6IGFueSk6IGFueSB7XG4gIHJldHVybiB1bm1hcnNoYWxEYXRhKGRhdGEpO1xufVxuXG4vKipcbiAqIFNlcmlhbGl6ZXMgZGF0YSBmb3Igc3RvcmFnZSBpbiB0aGUgZGF0YWJhc2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtYXJzaGFsRGF0YShkYXRhOiBhbnksIHNjaGVtYTogU2NoZW1hKTogYW55IHtcbiAgLy8gVE9ETyhzdGV2ZW5sZSk6IGltcGwuXG4gIHJldHVybiBkYXRhO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEFycmF5T2JqZWN0IHtcbiAgW2tleTogc3RyaW5nXTogYW55O1xuICBfYXJyYXk6IHN0cmluZ1tdO1xufVxuXG4vKipcbiAqIFNlcmlhbGl6ZXMgYW4gYXJyYXkgaW50byBhbiBgQXJyYXlPYmplY3RgLCBlLmcuOlxuICpcbiAqIGBgYFxuICogbWFyc2hhbEFycmF5KFsxLCAyLCAzXSlcbiAqIC8vID0+IHthOiAxLCBiOiAyLCBjOiAzLCBfYXJyYXk6IFsnYScsICdiJywgJ2MnXX1cbiAqIGBgYFxuICpcbiAqIFRoaXMgZGF0YWJhc2Ugc3RvcmFnZSBtZXRob2QgbWFrZXMgaXQgZWFzaWVyIHRvIHVwZGF0ZSBhIHNpbmdsZSBmaWVsZCBpbiBhXG4gKiBkZWVwbHkgbmVzdGVkIGFycmF5IG9iamVjdC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1hcnNoYWxBcnJheShhcnI6IGFueVtdKTogQXJyYXlPYmplY3Qge1xuICBpZiAoIUFycmF5LmlzQXJyYXkoYXJyKSkge1xuICAgIHJldHVybiBhcnI7XG4gIH1cbiAgY29uc3QgYXJyT2JqZWN0OiBBcnJheU9iamVjdCA9IHtfYXJyYXk6IFtdfTtcbiAgZm9yIChjb25zdCBpdGVtIG9mIGFycikge1xuICAgIGNvbnN0IGtleSA9IHJhbmRTdHJpbmcoNik7XG4gICAgYXJyT2JqZWN0W2tleV0gPSBpdGVtO1xuICAgIGFyck9iamVjdC5fYXJyYXkucHVzaChrZXkpO1xuICB9XG4gIHJldHVybiBhcnJPYmplY3Q7XG59XG5cbi8qKlxuICogQ29udmVydHMgYW4gYEFycmF5T2JqZWN0YCB0byBhIG5vcm1hbCBhcnJheS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVubWFyc2hhbEFycmF5KGFyck9iamVjdDogQXJyYXlPYmplY3QpOiBhbnlbXSB7XG4gIGlmICghQXJyYXkuaXNBcnJheShhcnJPYmplY3Q/Ll9hcnJheSkpIHtcbiAgICByZXR1cm4gW107XG4gIH1cbiAgY29uc3QgYXJyID0gYXJyT2JqZWN0Ll9hcnJheS5tYXAoKGs6IHN0cmluZykgPT4gYXJyT2JqZWN0W2tdKTtcbiAgcmV0dXJuIGFycjtcbn1cblxuZnVuY3Rpb24gaXNPYmplY3QoZGF0YTogYW55KTogYm9vbGVhbiB7XG4gIHJldHVybiB0eXBlb2YgZGF0YSA9PT0gJ29iamVjdCcgJiYgIUFycmF5LmlzQXJyYXkoZGF0YSkgJiYgZGF0YSAhPT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gcmFuZFN0cmluZyhsZW46IG51bWJlcik6IHN0cmluZyB7XG4gIGNvbnN0IHJlc3VsdCA9IFtdO1xuICBjb25zdCBjaGFycyA9XG4gICAgJ0FCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5JztcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgIGNvbnN0IHJhbmQgPSBNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiBjaGFycy5sZW5ndGgpO1xuICAgIHJlc3VsdC5wdXNoKGNoYXJzLmNoYXJBdChyYW5kKSk7XG4gIH1cbiAgcmV0dXJuIHJlc3VsdC5qb2luKCcnKTtcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBhIHRyYW5zbGF0aW9ucyBtYXAgZnJvbSBgbG9hZFRyYW5zbGF0aW9ucygpYCB0byBhIG1hcCBvZiBzb3VyY2UgdG9cbiAqIHRyYW5zbGF0ZWQgc3RyaW5nIGZvciBhIHBhcnRpY3VsYXIgbG9jYWxlLlxuICpcbiAqIFJldHVybnMgYSBtYXAgbGlrZTpcbiAqIGBgYFxuICoge1xuICogICBcIkhlbGxvXCI6IFwiQm9uam91clwiLFxuICogfVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0cmFuc2xhdGlvbnNGb3JMb2NhbGUoXG4gIHRyYW5zbGF0aW9uc01hcDogVHJhbnNsYXRpb25zTWFwLFxuICBsb2NhbGU6IHN0cmluZ1xuKSB7XG4gIGNvbnN0IGxvY2FsZVRyYW5zbGF0aW9uczogTG9jYWxlVHJhbnNsYXRpb25zID0ge307XG4gIE9iamVjdC52YWx1ZXModHJhbnNsYXRpb25zTWFwKS5mb3JFYWNoKChzdHJpbmcpID0+IHtcbiAgICBjb25zdCBzb3VyY2UgPSBzdHJpbmcuc291cmNlO1xuICAgIGNvbnN0IHRyYW5zbGF0aW9uID0gc3RyaW5nW2xvY2FsZV0gfHwgc3RyaW5nLmVuIHx8IHN0cmluZy5zb3VyY2U7XG4gICAgbG9jYWxlVHJhbnNsYXRpb25zW3NvdXJjZV0gPSB0cmFuc2xhdGlvbjtcbiAgfSk7XG4gIHJldHVybiBsb2NhbGVUcmFuc2xhdGlvbnM7XG59XG4iLCAiLyoqXG4gKiBEb2N1bWVudCB2ZXJpb24gaGlzdG9yeS5cbiAqXG4gKiBWZXJpb25zIHNhdmUgdGhlIHN0YXRlIG9mIGEgZG9jdW1lbnQgYXQgZGlmZmVyZW50IG1vbWVudHMgaW4gdGltZSwgYWxsb3dpbmdcbiAqIHVzZXJzIHRvIHJldmVydCBiYWNrIHRvIGEgdmVyc2lvbiBpZi93aGVuIG5lZWRlZC5cbiAqXG4gKiBUaGUgc2F2ZVZlcnNpb25zKCkgZnVuY3Rpb24gaXMgbWVhbnQgdG8gYmUgcnVuIHdpdGhpbiBhIGNyb24gam9iIChlLmcgdXNpbmdcbiAqIGZpcmViYXNlIGZ1bmN0aW9ucykuIEV2ZXJ5IG1pbnV0ZSwgdGhlIHJ1bm5lciBjaGVja3MgZm9yIGFsbCBkb2N1bWVudHMgdGhhdFxuICogaGF2ZSBiZWVuIGVkaXRlZCBzaW5jZSB0aGUgbGFzdCBydW4uIFRvIGF2b2lkIHNhdmluZyBcInBhcnRpYWxcIiB2ZXJzaW9uc1xuICogKHdoZW4gdGhlIHVzZXIgbWlnaHQgYmUgaW4gdGhlIG1pZGRsZSBvZiBlZGl0aW5nIGEgZG9jdW1lbnQpLCB2ZXJzaW9ucyBvbmx5XG4gKiBydW4gb24gZG9jdW1lbnRzIHRoYXQgaGF2ZW4ndCBiZWVuIGVkaXRlZCB3aXRoaW4gdGhlIGxhc3QgNSBtaW5zIHRvIGVuc3VyZVxuICogdGhhdCB2ZXJzaW9uIGlzIFwic3RhYmxlXCIuXG4gKlxuICogSW4gdGhlIGRhdGFiYXNlLCB2ZXJzaW9ucyBhcmUgc3RvcmVkIGFzOlxuICogL1Byb2plY3RzLzxwcm9qZWN0SWQ+L0NvbGxlY3Rpb25zLzxjb2xsZWN0aW9uSWQ+L0RyYWZ0cy88ZG9jSWQ+L1ZlcnNpb25zLzx0aW1lc3RhbXA+XG4gKlxuICogV2hlcmUgPHRpbWVzdGFtcD4gaXMgdGhlIHVuaXggdGltZXN0YW1wIChtaWxsaXMpIHRoYXQgdGhlIGRvY3VtZW50IHdhcyBsYXN0XG4gKiBlZGl0ZWQuXG4gKi9cblxuaW1wb3J0IHBhdGggZnJvbSAnbm9kZTpwYXRoJztcbmltcG9ydCB7Um9vdENvbmZpZ30gZnJvbSAnQGJsaW5ray9yb290JztcbmltcG9ydCB7XG4gIEZpcmVzdG9yZSxcbiAgUXVlcnksXG4gIFRpbWVzdGFtcCxcbiAgZ2V0RmlyZXN0b3JlLFxufSBmcm9tICdmaXJlYmFzZS1hZG1pbi9maXJlc3RvcmUnO1xuaW1wb3J0IGdsb2IgZnJvbSAndGlueS1nbG9iJztcbmltcG9ydCB7Z2V0Q21zUGx1Z2lufSBmcm9tICcuL2NsaWVudC5qcyc7XG5cbi8vIFRvIGF2b2lkIHNhdmluZyBcInBhcnRpYWxcIiB2ZXJzaW9ucyAod2hlbiB0aGUgdXNlciBtaWdodCBiZSBpbiB0aGUgbWlkZGxlIG9mXG4vLyBlZGl0aW5nIGEgZG9jdW1lbnQpLCB2ZXJzaW9ucyBvbmx5IHJ1biBvbiBkb2N1bWVudHMgdGhhdCBoYXZlbid0IGJlZW4gZWRpdGVkXG4vLyB3aXRoaW4gdGhlIGxhc3QgNSBtaW5zIHRvIGVuc3VyZSB0aGF0IHZlcnNpb24gaXMgXCJzdGFibGVcIi5cbmNvbnN0IERPQ1VNRU5UX1NBVkVfT0ZGU0VUID0gNSAqIDYwICogMTAwMDtcblxuaW50ZXJmYWNlIFBhcnRpYWxDTVNEb2Mge1xuICBba2V5OiBzdHJpbmddOiBhbnk7XG4gIGlkOiBzdHJpbmc7XG4gIGNvbGxlY3Rpb246IHN0cmluZztcbiAgc2x1Zzogc3RyaW5nO1xuICBzeXM6IHtcbiAgICBtb2RpZmllZEF0OiBUaW1lc3RhbXA7XG4gICAgbW9kaWZpZWRCeTogc3RyaW5nO1xuICB9O1xufVxuXG5leHBvcnQgY2xhc3MgVmVyc2lvbnNTZXJ2aWNlIHtcbiAgcHJpdmF0ZSByZWFkb25seSByb290Q29uZmlnOiBSb290Q29uZmlnO1xuICBwcml2YXRlIHJlYWRvbmx5IHByb2plY3RJZDogc3RyaW5nO1xuICBwcml2YXRlIHJlYWRvbmx5IGRiOiBGaXJlc3RvcmU7XG5cbiAgY29uc3RydWN0b3Iocm9vdENvbmZpZzogUm9vdENvbmZpZykge1xuICAgIHRoaXMucm9vdENvbmZpZyA9IHJvb3RDb25maWc7XG4gICAgY29uc3QgY21zUGx1Z2luID0gZ2V0Q21zUGx1Z2luKHJvb3RDb25maWcpO1xuICAgIGNvbnN0IGNtc1BsdWdpbk9wdGlvbnMgPSBjbXNQbHVnaW4uZ2V0Q29uZmlnKCk7XG4gICAgY29uc3QgcHJvamVjdElkID0gY21zUGx1Z2luT3B0aW9ucy5pZCB8fCAnZGVmYXVsdCc7XG4gICAgdGhpcy5wcm9qZWN0SWQgPSBwcm9qZWN0SWQ7XG4gICAgY29uc3QgYXBwID0gY21zUGx1Z2luLmdldEZpcmViYXNlQXBwKCk7XG4gICAgdGhpcy5kYiA9IGdldEZpcmVzdG9yZShhcHApO1xuICB9XG5cbiAgLyoqXG4gICAqIFNhdmVzIGEgdmVyc2lvbiBvZiBhbGwgZG9jdW1lbnRzIHRoYXQgaGF2ZSBiZWVuIGVkaXRlZCBzaW5jZSB0aGUgbGFzdCBydW4uXG4gICAqL1xuICBhc3luYyBzYXZlVmVyc2lvbnMoKSB7XG4gICAgLy8gT2Zmc2V0IHRoZSBcImxhc3QgcnVuXCIgdGltZSBieSA1IG1pbnMuIFZlcnNpb25zIGlnbm9yZSBkb2NzIHRoYXQgd2VyZVxuICAgIC8vIGVkaXRlZCB3aXRoaW4gdGhlIGxhc3QgNSBtaW5zIHRvIGF2b2lkIHBvdGVudGlhbCBcInBhcnRpYWxcIiB2ZXJzaW9ucyB3aGVuXG4gICAgLy8gdXNlciBpcyBpbiB0aGUgbWlkZGxlIG9mIGVkaXRpbmcgYSBkb2N1bWVudC5cbiAgICBjb25zdCBsYXN0UnVuID0gYXdhaXQgdGhpcy5nZXRMYXN0UnVuKCk7XG4gICAgY29uc3QgbGFzdFJ1bldpdGhPZmZzZXQgPVxuICAgICAgbGFzdFJ1biA9PT0gMCA/IGxhc3RSdW4gOiBsYXN0UnVuIC0gRE9DVU1FTlRfU0FWRV9PRkZTRVQ7XG4gICAgY29uc3QgY2hhbmdlZERvY3MgPSBhd2FpdCB0aGlzLmdldERvY3NNb2RpZmllZEFmdGVyKGxhc3RSdW5XaXRoT2Zmc2V0KTtcbiAgICBjb25zdCBub3cgPSBUaW1lc3RhbXAubm93KCkudG9NaWxsaXMoKTtcbiAgICBjb25zdCB2ZXJzaW9ucyA9IGNoYW5nZWREb2NzLmZpbHRlcigoZG9jKSA9PiB7XG4gICAgICBjb25zdCBtb2RpZmllZEF0ID0gZG9jLnN5cy5tb2RpZmllZEF0LnRvTWlsbGlzKCk7XG4gICAgICByZXR1cm4gbW9kaWZpZWRBdCA8PSBub3cgLSBET0NVTUVOVF9TQVZFX09GRlNFVDtcbiAgICB9KTtcbiAgICBpZiAodmVyc2lvbnMubGVuZ3RoID4gMCkge1xuICAgICAgdGhpcy5zYXZlVmVyc2lvbnNUb0ZpcmVzdG9yZSh2ZXJzaW9ucyk7XG4gICAgfVxuICAgIHRoaXMuc2F2ZUxhc3RSdW4obm93KTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgc2F2ZVZlcnNpb25zVG9GaXJlc3RvcmUodmVyc2lvbnM6IFBhcnRpYWxDTVNEb2NbXSkge1xuICAgIGNvbnN0IGJhdGNoID0gdGhpcy5kYi5iYXRjaCgpO1xuICAgIHZlcnNpb25zLmZvckVhY2goKHZlcnNpb24pID0+IHtcbiAgICAgIGlmICghdmVyc2lvbi5jb2xsZWN0aW9uIHx8ICF2ZXJzaW9uLnNsdWcgfHwgIXZlcnNpb24uc3lzPy5tb2RpZmllZEF0KSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGNvbnN0IG1vZGlmaWVkQXRNaWxsaXMgPSB2ZXJzaW9uLnN5cy5tb2RpZmllZEF0LnRvTWlsbGlzKCk7XG4gICAgICBjb25zdCB2ZXJzaW9uUGF0aCA9IGBQcm9qZWN0cy8ke3RoaXMucHJvamVjdElkfS9Db2xsZWN0aW9ucy8ke3ZlcnNpb24uY29sbGVjdGlvbn0vRHJhZnRzLyR7dmVyc2lvbi5zbHVnfS9WZXJzaW9ucy8ke21vZGlmaWVkQXRNaWxsaXN9YDtcbiAgICAgIGNvbnNvbGUubG9nKHZlcnNpb25QYXRoKTtcbiAgICAgIGNvbnN0IHZlcnNpb25SZWYgPSB0aGlzLmRiLmRvYyh2ZXJzaW9uUGF0aCk7XG4gICAgICBiYXRjaC5zZXQodmVyc2lvblJlZiwgdmVyc2lvbik7XG4gICAgfSk7XG4gICAgYXdhaXQgYmF0Y2guY29tbWl0KCk7XG4gICAgY29uc29sZS5sb2coYHZlcnNpb25zOiBzYXZlZCAke3ZlcnNpb25zLmxlbmd0aH0gdmVyc2lvbnNgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBsYXN0IHRpbWUgKGluIG1pbGxpcykgc2F2ZVZlcnNpb25zKCkgd2FzIHJ1biwgb3IgMCBpZiBoYXNcbiAgICogbmV2ZXIgYmVlbiBydW4uXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGdldExhc3RSdW4oKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICBjb25zdCBwcm9qZWN0RG9jUmVmID0gdGhpcy5kYi5jb2xsZWN0aW9uKCdQcm9qZWN0cycpLmRvYyh0aGlzLnByb2plY3RJZCk7XG4gICAgY29uc3QgcHJvamVjdERvYyA9IGF3YWl0IHByb2plY3REb2NSZWYuZ2V0KCk7XG4gICAgaWYgKHByb2plY3REb2MuZXhpc3RzKSB7XG4gICAgICBjb25zdCBkYXRhID0gcHJvamVjdERvYy5kYXRhKCkgfHwge307XG4gICAgICBjb25zdCB0cyA9IGRhdGEudmVyc2lvbnNMYXN0UnVuIGFzIFRpbWVzdGFtcDtcbiAgICAgIGlmICh0cykge1xuICAgICAgICByZXR1cm4gdHMudG9NaWxsaXMoKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIDA7XG4gIH1cblxuICAvKipcbiAgICogU2F2ZXMge3ZlcnNpb25MYXN0UnVuOiA8dGltZXN0YW1wPn0gdG8gdGhlIFByb2plY3RzLzxwcm9qZWN0SWQ+IGRvYy5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgc2F2ZUxhc3RSdW4obWlsbGlzOiBudW1iZXIpIHtcbiAgICBjb25zdCB0cyA9IFRpbWVzdGFtcC5mcm9tTWlsbGlzKG1pbGxpcyk7XG4gICAgY29uc3QgcHJvamVjdERvY1JlZiA9IHRoaXMuZGIuY29sbGVjdGlvbignUHJvamVjdHMnKS5kb2ModGhpcy5wcm9qZWN0SWQpO1xuICAgIGF3YWl0IHByb2plY3REb2NSZWYuc2V0KHt2ZXJzaW9uc0xhc3RSdW46IHRzfSwge21lcmdlOiB0cnVlfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhIGxpc3Qgb2YgYWxsIGRvY3MgdGhhdCB3ZXJlIGVkaXRlZCBhZnRlciBhIGNlcnRhaW4gdGltZS5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgZ2V0RG9jc01vZGlmaWVkQWZ0ZXIobWlsbGlzOiBudW1iZXIpOiBQcm9taXNlPFBhcnRpYWxDTVNEb2NbXT4ge1xuICAgIGNvbnN0IHRzID0gVGltZXN0YW1wLmZyb21NaWxsaXMobWlsbGlzKTtcbiAgICBjb25zdCByZXN1bHRzOiBQYXJ0aWFsQ01TRG9jW10gPSBbXTtcbiAgICBjb25zdCBjb2xsZWN0aW9uSWRzID0gYXdhaXQgdGhpcy5saXN0Q29sbGVjdGlvbnMoKTtcbiAgICAvLyBOT1RFOiBJbmRpdmlkdWFsIGNvbGxlY3Rpb25zIGFyZSBxdWVyaWVkIGluc3RlYWQgb2YgdXNpbmcgYVxuICAgIC8vIGNvbGxlY3Rpb25Hcm91cCBxdWVyeSBiZWNhdXNlIHRoZSBsYXR0ZXIgcmVxdWlyZXMgYSBmaXJlc3RvcmUgaW5kZXggdG8gYmVcbiAgICAvLyBzZXQgdXAuXG4gICAgZm9yIChjb25zdCBjb2xsZWN0aW9uSWQgb2YgY29sbGVjdGlvbklkcykge1xuICAgICAgY29uc3QgY29sbGVjdGlvblBhdGggPSBgUHJvamVjdHMvJHt0aGlzLnByb2plY3RJZH0vQ29sbGVjdGlvbnMvJHtjb2xsZWN0aW9uSWR9L0RyYWZ0c2A7XG4gICAgICBjb25zdCBxdWVyeTogUXVlcnkgPSB0aGlzLmRiXG4gICAgICAgIC5jb2xsZWN0aW9uKGNvbGxlY3Rpb25QYXRoKVxuICAgICAgICAud2hlcmUoJ3N5cy5tb2RpZmllZEF0JywgJz49JywgdHMpO1xuICAgICAgY29uc3QgcXVlcnlTbmFwc2hvdCA9IGF3YWl0IHF1ZXJ5LmdldCgpO1xuICAgICAgcXVlcnlTbmFwc2hvdC5mb3JFYWNoKChkb2MpID0+IHtcbiAgICAgICAgcmVzdWx0cy5wdXNoKGRvYy5kYXRhKCkgYXMgUGFydGlhbENNU0RvYyk7XG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdHM7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhIGxpc3Qgb2YgY29sbGVjdGlvbiBpZHMgZm9yIHRoZSBSb290IHByb2plY3QuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGxpc3RDb2xsZWN0aW9ucygpOiBQcm9taXNlPHN0cmluZ1tdPiB7XG4gICAgY29uc3QgY29sbGVjdGlvbklkczogc3RyaW5nW10gPSBbXTtcbiAgICBjb25zdCBjb2xsZWN0aW9uRmlsZU5hbWVzID0gYXdhaXQgZ2xvYignKi5zY2hlbWEudHMnLCB7XG4gICAgICBjd2Q6IHBhdGguam9pbih0aGlzLnJvb3RDb25maWcucm9vdERpciwgJ2NvbGxlY3Rpb25zJyksXG4gICAgfSk7XG4gICAgY29sbGVjdGlvbkZpbGVOYW1lcy5mb3JFYWNoKChmaWxlbmFtZSkgPT4ge1xuICAgICAgY29sbGVjdGlvbklkcy5wdXNoKGZpbGVuYW1lLnNsaWNlKDAsIC0xMCkpO1xuICAgIH0pO1xuICAgIHJldHVybiBjb2xsZWN0aW9uSWRzO1xuICB9XG59XG4iLCAiaW1wb3J0IHtSb290Q29uZmlnfSBmcm9tICdAYmxpbmtrL3Jvb3QnO1xuaW1wb3J0IHtwdWJsaXNoU2NoZWR1bGVkRG9jc30gZnJvbSAnLi9ydW50aW1lLmpzJztcbmltcG9ydCB7VmVyc2lvbnNTZXJ2aWNlfSBmcm9tICcuL3ZlcnNpb25zLmpzJztcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJ1bkNyb25Kb2JzKHJvb3RDb25maWc6IFJvb3RDb25maWcpIHtcbiAgYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgIHJ1bkNyb25Kb2IoJ3B1Ymxpc2hTY2hlZHVsZWREb2NzJywgcnVuUHVibGlzaFNjaGVkdWxlZERvY3MsIHJvb3RDb25maWcpLFxuICAgIHJ1bkNyb25Kb2IoJ3NhdmVWZXJzaW9ucycsIHJ1blNhdmVWZXJzaW9ucywgcm9vdENvbmZpZyksXG4gIF0pO1xufVxuXG5hc3luYyBmdW5jdGlvbiBydW5Dcm9uSm9iKFxuICBuYW1lOiBzdHJpbmcsXG4gIGZuOiAoLi4uYXJnczogYW55W10pID0+IGFueSxcbiAgLi4uYXJnczogYW55W11cbikge1xuICB0cnkge1xuICAgIGF3YWl0IGZuKC4uLmFyZ3MpO1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICBjb25zb2xlLmxvZyhgY3JvbiBmYWlsZWQ6ICR7bmFtZX1gKTtcbiAgICBjb25zb2xlLmVycm9yKFN0cmluZyhlcnIuc3RhY2sgfHwgZXJyKSk7XG4gICAgdGhyb3cgZXJyO1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJ1blB1Ymxpc2hTY2hlZHVsZWREb2NzKHJvb3RDb25maWc6IFJvb3RDb25maWcpIHtcbiAgYXdhaXQgcHVibGlzaFNjaGVkdWxlZERvY3Mocm9vdENvbmZpZyk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJ1blNhdmVWZXJzaW9ucyhyb290Q29uZmlnOiBSb290Q29uZmlnKSB7XG4gIGNvbnN0IHNlcnZpY2UgPSBuZXcgVmVyc2lvbnNTZXJ2aWNlKHJvb3RDb25maWcpO1xuICBhd2FpdCBzZXJ2aWNlLnNhdmVWZXJzaW9ucygpO1xufVxuIl0sCiAgIm1hcHBpbmdzIjogIjtBQUFBLE9BQU9BLFdBQVU7QUFDakIsU0FBUSxzQkFBcUI7QUFDN0IsU0FBeUIsa0JBQWlCOzs7QUNDMUM7QUFBQSxFQUNFLGNBQUFDO0FBQUEsRUFHQSxnQkFBQUM7QUFBQSxPQUNLOzs7QUNSUCxPQUFPLFVBQVU7QUFFakIsU0FBUSx5QkFBd0I7QUFFaEM7QUFBQSxFQUNFO0FBQUEsRUFHQTtBQUFBLEVBQ0E7QUFBQSxPQUNLO0FBbVlBLFNBQVMsYUFBYSxZQUFtQztBQUM5RCxRQUFNLFVBQW9CLFdBQVcsV0FBVyxDQUFDO0FBQ2pELFFBQU0sU0FBUyxRQUFRLEtBQUssQ0FBQ0MsWUFBV0EsUUFBTyxTQUFTLFVBQVU7QUFDbEUsTUFBSSxDQUFDLFFBQVE7QUFDWCxVQUFNLElBQUksTUFBTSx5REFBeUQ7QUFBQSxFQUMzRTtBQUNB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Q2xDLFlBQVEsTUFBTSxPQUFPLElBQUksU0FBUyxHQUFHLENBQUM7QUFDdEMsVUFBTTtBQUFBLEVBQ1I7QUFDRjtBQUVBLGVBQWUsd0JBQXdCLFlBQXdCO0FBQzdELFFBQU0scUJBQXFCLFVBQVU7QUFDdkM7QUFFQSxlQUFlLGdCQUFnQixZQUF3QjtBQUNyRCxRQUFNLFVBQVUsSUFBSSxnQkFBZ0IsVUFBVTtBQUM5QyxRQUFNLFFBQVEsYUFBYTtBQUM3Qjs7O0FKbkJPLFNBQVMsS0FBSyxTQUF1QjtBQUMxQyxRQUFNLFVBQVVDLE1BQUssU0FBUSxtQ0FBUyxZQUFXLFFBQVEsSUFBSSxDQUFDO0FBQzlELFFBQU0sa0JBQW1DO0FBQUEsSUFDdkMsVUFBVTtBQUFBLElBQ1YsR0FBRyxtQ0FBUztBQUFBLEVBQ2Q7QUFDQSxTQUFPLFdBQVcsaUJBQWlCLFlBQVk7QUFDN0MsVUFBTSxhQUFhLE1BQU0sZUFBZSxTQUFTLEVBQUMsU0FBUyxXQUFVLENBQUM7QUFDdEUsVUFBTSxZQUFZLFVBQVU7QUFBQSxFQUM5QixDQUFDO0FBQ0g7IiwKICAibmFtZXMiOiBbInBhdGgiLCAiRmllbGRWYWx1ZSIsICJnZXRGaXJlc3RvcmUiLCAicGx1Z2luIiwgImdldEZpcmVzdG9yZSIsICJGaWVsZFZhbHVlIiwgInBhdGgiLCAiVGltZXN0YW1wIiwgImdldEZpcmVzdG9yZSIsICJnZXRGaXJlc3RvcmUiLCAiVGltZXN0YW1wIiwgInBhdGgiLCAicGF0aCJdCn0K
|
package/dist/plugin.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Request, Plugin } from '@blinkk/root';
|
|
2
|
+
import { App } from 'firebase-admin/app';
|
|
2
3
|
import { DecodedIdToken } from 'firebase-admin/auth';
|
|
3
4
|
|
|
4
5
|
type CMSUser = DecodedIdToken;
|
|
@@ -26,20 +27,36 @@ type CMSPluginOptions = {
|
|
|
26
27
|
messagingSenderId: string;
|
|
27
28
|
appId: string;
|
|
28
29
|
};
|
|
29
|
-
/**
|
|
30
|
+
/**
|
|
31
|
+
* Secret value(s) used for signing the user authentication cookie.
|
|
32
|
+
* @deprecated This is now handled directly by root's sessionMiddleware under
|
|
33
|
+
* `server.sessionCookieSecret` in root.config.ts.
|
|
34
|
+
*/
|
|
30
35
|
cookieSecret?: string | string[];
|
|
31
36
|
/** Function called to check if a user should have access to the CMS. */
|
|
32
37
|
isUserAuthorized?: (req: Request, user: CMSUser) => boolean | Promise<boolean>;
|
|
33
38
|
/**
|
|
34
39
|
* URL to GCI service for transforming uploaded GCS images to a Google App
|
|
35
|
-
* Engine Images API serving URL.
|
|
36
|
-
*
|
|
40
|
+
* Engine Images API serving URL.
|
|
41
|
+
*
|
|
42
|
+
* Setting this to `true` uses the default hosted service at
|
|
43
|
+
* https://gci.rootjs.dev.
|
|
44
|
+
*
|
|
45
|
+
* To set up GCI:
|
|
46
|
+
*
|
|
47
|
+
* - Create a GCS bucket with fine-grained permissions
|
|
48
|
+
* - Share owner access to the bucket with the service account returned in
|
|
49
|
+
* https://gci.rootjs.dev/_/service_account
|
|
50
|
+
*
|
|
51
|
+
* To disable GCI, leave this value empty or set to `false`, which which will
|
|
52
|
+
* serve images directly from GCS instead.
|
|
37
53
|
*/
|
|
38
54
|
gci?: string | boolean;
|
|
39
55
|
};
|
|
40
56
|
type CMSPlugin = Plugin & {
|
|
41
57
|
name: 'root-cms';
|
|
42
58
|
getConfig: () => CMSPluginOptions;
|
|
59
|
+
getFirebaseApp: () => App;
|
|
43
60
|
};
|
|
44
61
|
declare function cmsPlugin(options: CMSPluginOptions): CMSPlugin;
|
|
45
62
|
|