@nlabs/reaktor 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (198) hide show
  1. package/.eslintrc +10 -0
  2. package/.prettierrc.js +4 -0
  3. package/README.md +1 -1
  4. package/coverage/actions/groups.ts.html +1039 -0
  5. package/coverage/actions/images.ts.html +2500 -0
  6. package/coverage/actions/index.html +131 -0
  7. package/coverage/actions/tags.ts.html +1000 -0
  8. package/coverage/adapters/arangoAdapter.ts.html +151 -0
  9. package/coverage/adapters/index.html +146 -0
  10. package/coverage/adapters/reaktorAdapter.ts.html +127 -0
  11. package/coverage/adapters/tagAdapter.ts.html +160 -0
  12. package/coverage/base.css +224 -0
  13. package/coverage/block-navigation.js +87 -0
  14. package/coverage/clover.xml +6 -0
  15. package/coverage/coverage-final.json +1 -0
  16. package/coverage/favicon.png +0 -0
  17. package/coverage/index.html +176 -0
  18. package/coverage/lcov-report/base.css +224 -0
  19. package/coverage/lcov-report/block-navigation.js +87 -0
  20. package/coverage/lcov-report/favicon.png +0 -0
  21. package/coverage/lcov-report/index.html +101 -0
  22. package/coverage/lcov-report/prettify.css +1 -0
  23. package/coverage/lcov-report/prettify.js +2 -0
  24. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  25. package/coverage/lcov-report/sorter.js +196 -0
  26. package/coverage/lcov.info +0 -0
  27. package/coverage/mocks/file.ts.html +118 -0
  28. package/coverage/mocks/group.ts.html +145 -0
  29. package/coverage/mocks/image.ts.html +136 -0
  30. package/coverage/mocks/index.html +146 -0
  31. package/coverage/mocks/post.ts.html +169 -0
  32. package/coverage/mocks/tag.ts.html +121 -0
  33. package/coverage/mocks/user.ts.html +268 -0
  34. package/coverage/prettify.css +1 -0
  35. package/coverage/prettify.js +2 -0
  36. package/coverage/sort-arrow-sprite.png +0 -0
  37. package/coverage/sorter.js +196 -0
  38. package/coverage/types/error.ts.html +145 -0
  39. package/coverage/types/index.html +116 -0
  40. package/coverage/utils/adapterUtils.ts.html +151 -0
  41. package/coverage/utils/analyticsUtils.ts.html +292 -0
  42. package/coverage/utils/arangodbUtils.ts.html +463 -0
  43. package/coverage/utils/index.html +146 -0
  44. package/jest.setup.js +0 -0
  45. package/jpg:- +0 -0
  46. package/lib/actions/apps.d.ts +25 -0
  47. package/lib/actions/apps.js +252 -0
  48. package/lib/actions/conversations.d.ts +14 -0
  49. package/lib/actions/conversations.js +131 -126
  50. package/lib/actions/dynamodb.d.ts +8 -0
  51. package/lib/actions/dynamodb.js +35 -32
  52. package/lib/actions/email.d.ts +5 -0
  53. package/lib/actions/email.js +23 -53
  54. package/lib/actions/files.d.ts +19 -0
  55. package/lib/actions/files.js +188 -202
  56. package/lib/actions/groups.d.ts +14 -0
  57. package/lib/actions/groups.js +38 -36
  58. package/lib/actions/images.d.ts +26 -0
  59. package/lib/actions/images.js +236 -229
  60. package/lib/actions/index.d.ts +21 -0
  61. package/lib/actions/index.js +3 -1
  62. package/lib/actions/ios.d.ts +7 -0
  63. package/lib/actions/ios.js +11 -10
  64. package/lib/actions/locations.d.ts +5 -0
  65. package/lib/actions/locations.js +29 -37
  66. package/lib/actions/messages.d.ts +13 -0
  67. package/lib/actions/messages.js +10 -10
  68. package/lib/actions/notifications.d.ts +5 -0
  69. package/lib/actions/notifications.js +1 -1
  70. package/lib/actions/payments.d.ts +10 -0
  71. package/lib/actions/payments.js +27 -26
  72. package/lib/actions/posts.d.ts +19 -0
  73. package/lib/actions/posts.js +176 -156
  74. package/lib/actions/reactions.d.ts +30 -0
  75. package/lib/actions/reactions.js +30 -28
  76. package/lib/actions/s3.d.ts +7 -0
  77. package/lib/actions/s3.js +37 -32
  78. package/lib/actions/search.d.ts +3 -0
  79. package/lib/actions/search.js +11 -9
  80. package/lib/actions/sms.d.ts +3 -0
  81. package/lib/actions/sms.js +58 -34
  82. package/lib/actions/statistics.d.ts +3 -0
  83. package/lib/actions/statistics.js +21 -18
  84. package/lib/actions/subscription.d.ts +7 -0
  85. package/lib/actions/subscription.js +24 -21
  86. package/lib/actions/tags.d.ts +29 -0
  87. package/lib/actions/tags.js +129 -198
  88. package/lib/actions/users.d.ts +47 -0
  89. package/lib/actions/users.js +188 -194
  90. package/lib/actions/websockets.d.ts +19 -0
  91. package/lib/actions/websockets.js +60 -34
  92. package/lib/adapters/arangoAdapter.d.ts +2 -0
  93. package/lib/adapters/arangoAdapter.js +46 -0
  94. package/lib/adapters/fileAdapter.d.ts +3 -0
  95. package/lib/adapters/fileAdapter.js +76 -0
  96. package/lib/adapters/postAdapter.d.ts +2 -0
  97. package/lib/adapters/postAdapter.js +70 -0
  98. package/lib/adapters/reaktorAdapter.d.ts +6 -0
  99. package/lib/adapters/reaktorAdapter.js +44 -0
  100. package/lib/adapters/tagAdapter.d.ts +2 -0
  101. package/lib/adapters/tagAdapter.js +50 -0
  102. package/lib/adapters/userAdapter.d.ts +2 -0
  103. package/lib/adapters/userAdapter.js +110 -0
  104. package/lib/config.d.ts +20 -0
  105. package/lib/config.js +14 -15
  106. package/lib/index.d.ts +5 -0
  107. package/lib/lambdas/actions/websockets.d.ts +6 -0
  108. package/lib/lambdas/actions/websockets.js +7 -7
  109. package/lib/lambdas/authorizer.d.ts +20 -0
  110. package/lib/lambdas/authorizer.js +1 -1
  111. package/lib/lambdas/connection.d.ts +12 -0
  112. package/lib/lambdas/connection.js +5 -4
  113. package/lib/lambdas/utils/message.d.ts +1 -0
  114. package/lib/lambdas/utils/websocket.d.ts +7 -0
  115. package/lib/lambdas/utils/websocket.js +8 -6
  116. package/lib/mocks/conversation.d.ts +8 -0
  117. package/lib/mocks/conversation.js +35 -0
  118. package/lib/mocks/file.d.ts +11 -0
  119. package/lib/mocks/file.js +38 -0
  120. package/lib/mocks/group.d.ts +17 -0
  121. package/lib/mocks/group.js +47 -0
  122. package/lib/mocks/image.d.ts +3 -0
  123. package/lib/mocks/image.js +43 -0
  124. package/lib/mocks/nlabs.png +0 -0
  125. package/lib/mocks/post.d.ts +38 -0
  126. package/lib/mocks/post.js +55 -0
  127. package/lib/mocks/tag.d.ts +2 -0
  128. package/lib/mocks/tag.js +37 -0
  129. package/lib/mocks/user.d.ts +4 -0
  130. package/lib/mocks/user.js +88 -0
  131. package/lib/templates/email/layout.d.ts +2 -0
  132. package/lib/templates/email/passwordForgot.d.ts +2 -0
  133. package/lib/templates/email/passwordRecovery.d.ts +2 -0
  134. package/lib/templates/email/verifyEmail.d.ts +2 -0
  135. package/lib/templates/email/welcome.d.ts +2 -0
  136. package/lib/templates/sms/passwordForgot.d.ts +2 -0
  137. package/lib/templates/sms/passwordRecovery.d.ts +2 -0
  138. package/lib/templates/sms/verifyEmail.d.ts +2 -0
  139. package/lib/templates/sms/verifyPhone.d.ts +2 -0
  140. package/lib/templates/sms/welcome.d.ts +2 -0
  141. package/lib/types/apps.d.ts +46 -0
  142. package/lib/types/apps.js +17 -1
  143. package/lib/types/arangodb.d.ts +30 -0
  144. package/lib/types/arangodb.js +1 -1
  145. package/lib/types/auth.d.ts +7 -0
  146. package/lib/types/auth.js +1 -1
  147. package/lib/types/connections.d.ts +7 -0
  148. package/lib/types/connections.js +1 -1
  149. package/lib/types/conversations.d.ts +29 -0
  150. package/lib/types/conversations.js +1 -1
  151. package/lib/types/email.d.ts +13 -0
  152. package/lib/types/email.js +1 -1
  153. package/lib/types/error.d.ts +20 -0
  154. package/lib/types/error.js +44 -0
  155. package/lib/types/files.d.ts +26 -0
  156. package/lib/types/files.js +1 -1
  157. package/lib/types/google.d.ts +29 -0
  158. package/lib/types/google.js +1 -1
  159. package/lib/types/groups.d.ts +21 -0
  160. package/lib/types/groups.js +1 -1
  161. package/lib/types/images.d.ts +51 -0
  162. package/lib/types/images.js +1 -1
  163. package/lib/types/index.d.ts +18 -0
  164. package/lib/types/locations.d.ts +20 -0
  165. package/lib/types/locations.js +1 -1
  166. package/lib/types/messages.d.ts +16 -0
  167. package/lib/types/messages.js +1 -1
  168. package/lib/types/notifications.d.ts +17 -0
  169. package/lib/types/notifications.js +1 -1
  170. package/lib/types/payments.d.ts +112 -0
  171. package/lib/types/payments.js +1 -1
  172. package/lib/types/posts.d.ts +31 -0
  173. package/lib/types/posts.js +1 -1
  174. package/lib/types/statistics.d.ts +3 -0
  175. package/lib/types/statistics.js +1 -1
  176. package/lib/types/tags.d.ts +10 -0
  177. package/lib/types/tags.js +1 -1
  178. package/lib/types/users.d.ts +76 -0
  179. package/lib/types/users.js +1 -1
  180. package/lib/types/websocket.d.ts +13 -0
  181. package/lib/types/websocket.js +1 -1
  182. package/lib/utils/adapterUtils.d.ts +1 -0
  183. package/lib/utils/adapterUtils.js +45 -0
  184. package/lib/utils/analyticsUtils.d.ts +21 -0
  185. package/lib/utils/analyticsUtils.js +72 -0
  186. package/lib/utils/arangodbUtils.d.ts +65 -0
  187. package/lib/utils/arangodbUtils.js +144 -0
  188. package/lib/utils/auth.d.ts +20 -0
  189. package/lib/utils/auth.js +13 -30
  190. package/lib/utils/index.d.ts +5 -0
  191. package/lib/utils/index.js +7 -9
  192. package/lib/utils/session.d.ts +16 -0
  193. package/lib/utils/session.js +11 -2
  194. package/package.json +12 -5
  195. package/lib/utils/analytics.js +0 -88
  196. package/lib/utils/arangodb.js +0 -118
  197. package/lib/utils/graphql.js +0 -46
  198. package/lib/utils/objects.js +0 -59
@@ -37,6 +37,7 @@ __export(users_exports, {
37
37
  getDisplayName: () => getDisplayName,
38
38
  getSessionUser: () => getSessionUser,
39
39
  getUser: () => getUser,
40
+ getUserByToken: () => getUserByToken,
40
41
  getUserOptional: () => getUserOptional,
41
42
  getUsers: () => getUsers,
42
43
  getUsersByLatest: () => getUsersByLatest,
@@ -54,10 +55,13 @@ var import_arangojs = require("arangojs");
54
55
  var import_luxon = require("luxon");
55
56
  var import_stripe = __toESM(require("stripe"));
56
57
  var import_config = require("../config");
57
- var import_utils2 = require("../utils");
58
+ var import_analyticsUtils = require("../utils/analyticsUtils");
59
+ var import_arangodbUtils = require("../utils/arangodbUtils");
58
60
  var import_session = require("../utils/session");
61
+ var import_error = require("../types/error");
62
+ var import_userAdapter = require("../adapters/userAdapter");
59
63
  const eventCategory = "users";
60
- const apiVersion = "2020-03-02";
64
+ const STRIPE_API_VERSION = "2020-03-02";
61
65
  var UserAccess = /* @__PURE__ */ ((UserAccess2) => {
62
66
  UserAccess2[UserAccess2["DEACTIVATED"] = 0] = "DEACTIVATED";
63
67
  UserAccess2[UserAccess2["ACTIVE"] = 1] = "ACTIVE";
@@ -66,9 +70,9 @@ var UserAccess = /* @__PURE__ */ ((UserAccess2) => {
66
70
  UserAccess2[UserAccess2["ADMIN"] = 4] = "ADMIN";
67
71
  return UserAccess2;
68
72
  })(UserAccess || {});
69
- const createToken = (userId, username, userAccess, expires = 15) => {
73
+ const createToken = (userId, username, userAccess, expiresInMinutes = 15) => {
70
74
  const now = import_luxon.DateTime.local();
71
- const sessionExpires = now.plus({ minutes: expires });
75
+ const sessionExpires = now.plus({ minutes: expiresInMinutes });
72
76
  const iat = Math.floor(now.toSeconds());
73
77
  const exp = Math.floor(sessionExpires.toSeconds());
74
78
  const token = (0, import_session.setSession)({
@@ -86,7 +90,7 @@ const createToken = (userId, username, userAccess, expires = 15) => {
86
90
  };
87
91
  const getUserOptional = (fields = []) => fields.reduce((selects, field) => {
88
92
  if (field.includes("Count")) {
89
- return (0, import_utils2.selectReactionCountByType)("users", "u", field, selects);
93
+ return (0, import_arangodbUtils.selectReactionCountByType)("users", "u", field, selects);
90
94
  }
91
95
  return selects;
92
96
  }, { objects: [], queries: [] });
@@ -95,27 +99,27 @@ const parseUserOptions = (options = {}) => {
95
99
  from = 0,
96
100
  to = 30
97
101
  } = options;
102
+ const limit = (0, import_arangodbUtils.getLimit)(from, to);
98
103
  return {
99
104
  ...options,
100
- limit: (0, import_utils2.getLimit)(from, to)
105
+ limit
101
106
  };
102
107
  };
103
- const addUser = async (context, args) => {
108
+ const addUser = async (context, user) => {
104
109
  const action = "addUser";
105
110
  const { database } = context;
106
- const { user } = args;
107
- const { email, password, phone, username } = user;
111
+ const { email, password, phone, username } = (0, import_userAdapter.parseUser)(user);
108
112
  const salt = (0, import_utils.createHash)(`${username}${password}`, null);
109
113
  const encryptedPassword = (0, import_utils.createPassword)(password, salt);
110
114
  const formatUsername = (0, import_utils.parseUsername)(username);
111
115
  const formatEmail = (0, import_utils.parseEmail)(email);
112
116
  const formatPhone = (0, import_utils.parsePhone)(phone);
113
117
  if (!formatUsername || !password || !formatPhone && !formatEmail) {
114
- return (0, import_utils2.logException)({
118
+ return (0, import_analyticsUtils.logException)({
115
119
  action,
116
- args: { username },
117
120
  category: eventCategory,
118
- value: import_utils2.ErrorTypes.INVALID_ARGUMENTS
121
+ params: { username },
122
+ value: import_error.ErrorTypes.INVALID_ARGUMENTS
119
123
  }, context);
120
124
  }
121
125
  const filters = [`u.username == "${formatUsername}"`];
@@ -127,22 +131,25 @@ const addUser = async (context, args) => {
127
131
  }
128
132
  const checkQuery = `FOR u IN users
129
133
  FILTER ${filters.join(" || ")}
134
+ LIMIT 1
130
135
  RETURN u`;
131
- const existingUsers = await database.query(checkQuery).then((cursor) => cursor.all()).catch(
132
- (error) => (0, import_utils2.logError)({
133
- action,
134
- args: { username },
135
- category: eventCategory,
136
- label: import_utils2.ErrorTypes.DATABASE_ERROR
137
- }, error, context).then(() => null)
138
- );
139
- if (existingUsers.length) {
140
- return (0, import_utils2.logException)({
136
+ try {
137
+ const existingUsers = await database.query(checkQuery).then((cursor) => cursor.all());
138
+ if (existingUsers.length) {
139
+ return (0, import_analyticsUtils.logException)({
140
+ action,
141
+ category: eventCategory,
142
+ params: { username },
143
+ value: import_error.ErrorTypes.EXISTING_ITEM
144
+ }, context);
145
+ }
146
+ } catch (error) {
147
+ return (0, import_analyticsUtils.logError)({
141
148
  action,
142
- args: { username },
143
149
  category: eventCategory,
144
- value: import_utils2.ErrorTypes.EXISTING_USERNAME
145
- }, context);
150
+ params: { username },
151
+ value: import_error.ErrorTypes.DATABASE_ERROR
152
+ }, error, context);
146
153
  }
147
154
  const verifiedEmailCode = Math.floor(1e5 + Math.random() * 9e5);
148
155
  const verifiedPhoneCode = Math.floor(1e5 + Math.random() * 9e5);
@@ -162,66 +169,66 @@ const addUser = async (context, args) => {
162
169
  verifiedPhoneCode
163
170
  };
164
171
  const insertQuery = import_arangojs.aql`INSERT ${insert} IN users RETURN NEW`;
165
- return await database.query(insertQuery).then((cursor) => cursor.next() || {}).catch(
166
- (error) => (0, import_utils2.logError)({
167
- action,
168
- args: { username },
169
- category: eventCategory,
170
- label: import_utils2.ErrorTypes.DATABASE_ERROR
171
- }, error, context).then(() => null)
172
- );
172
+ return await database.query(insertQuery).then((cursor) => cursor.next()).catch((error) => (0, import_analyticsUtils.logError)({
173
+ action,
174
+ category: eventCategory,
175
+ params: { username },
176
+ value: import_error.ErrorTypes.DATABASE_ERROR
177
+ }, error, context));
173
178
  };
174
179
  const updateUser = async (context, user) => {
175
180
  const action = "updateUser";
176
- const { database } = context;
177
- const { _key, _id, id, tags = [], userId, ...updated } = user;
178
- let userDocId;
179
- if (_id || id) {
180
- userDocId = _id || id;
181
- } else if (_key || userId) {
182
- userDocId = `users/${_key || userId}`;
181
+ const { database, session } = context;
182
+ const { _key, _id, id, tags = [], userId, ...updated } = (0, import_userAdapter.parseUser)(user);
183
+ if (!(0, import_session.isAdminUser)(session) && session?.userId !== userId) {
184
+ return (0, import_analyticsUtils.logException)({
185
+ action,
186
+ category: eventCategory,
187
+ params: { session },
188
+ value: import_error.ErrorTypes.INVALID_SESSION
189
+ }, context);
183
190
  }
184
- const userQuery = import_arangojs.aql`LET u = DOCUMENT(${userDocId})
191
+ const userQuery = import_arangojs.aql`LET u = DOCUMENT(${id})
185
192
  UPDATE u WITH ${updated} IN users
186
193
  RETURN NEW`;
187
- const updatedUser = await database.query(userQuery).then((cursor) => cursor.next()).catch((error) => {
188
- console.log(error);
189
- throw error;
190
- });
191
- const tagCollection = database.collection("isTagged");
192
- await Promise.all(tags.map(({ id: tagDocId, name }) => {
193
- const edge = {
194
- _from: tagDocId,
195
- _key: (0, import_utils.createHash)(`isTagged-${tagDocId}-${userDocId}`),
196
- _to: userDocId,
197
- added: Date.now(),
198
- name
199
- };
200
- const tagQuery = import_arangojs.aql`FOR it IN isTagged
201
- FILTER it._from == ${tagDocId} && it._to == ${userDocId} && it.name == ${name}
202
- LIMIT 1
203
- RETURN it`;
204
- return database.query(tagQuery).then((cursor) => cursor.next()).then((tagEdge) => {
205
- if (!!tagEdge) {
206
- return tagEdge;
207
- }
208
- return tagCollection.save(edge, { returnNew: true }).then(() => edge);
209
- }).catch((error) => (0, import_utils2.logError)({
194
+ try {
195
+ const updatedUser = await database.query(userQuery).then((cursor) => cursor.next());
196
+ const tagCollection = database.collection("isTagged");
197
+ await Promise.all(tags.map(({ id: tagDocId, name }) => {
198
+ const tagQuery = import_arangojs.aql`FOR it IN isTagged
199
+ FILTER it._from == ${tagDocId} && it._to == ${id} && it.name == ${name}
200
+ LIMIT 1
201
+ RETURN it`;
202
+ return database.query(tagQuery).then((cursor) => cursor.next()).then((tagEdge) => {
203
+ if (!!tagEdge) {
204
+ return tagEdge;
205
+ }
206
+ const edge = {
207
+ _from: tagDocId,
208
+ _key: (0, import_utils.createHash)(`isTagged-${tagDocId}-${id}`),
209
+ _to: id,
210
+ added: Date.now(),
211
+ name
212
+ };
213
+ return tagCollection.save(edge, { returnNew: true }).then(() => edge);
214
+ });
215
+ }));
216
+ return updatedUser;
217
+ } catch (error) {
218
+ return (0, import_analyticsUtils.logError)({
210
219
  action,
211
220
  category: eventCategory,
212
- label: "db_error"
213
- }, error, context).then(() => null));
214
- }));
215
- return updatedUser;
221
+ params: { user },
222
+ value: import_error.ErrorTypes.DATABASE_ERROR
223
+ }, error, context);
224
+ }
216
225
  };
217
- const confirmCode = async (context, args) => {
218
- const action = "confirmEmail";
226
+ const confirmCode = async (context, { code, type }) => {
219
227
  const { database, session: { userId: sessionId } } = context;
220
- const { code, type } = args;
221
- const userDocId = `users/${sessionId}`;
228
+ const userDocId = (0, import_arangodbUtils.getDocId)("users", { userId: sessionId });
222
229
  const aqlQuery = import_arangojs.aql`LET u = DOCUMENT(${userDocId}) RETURN u`;
223
230
  try {
224
- return database.query(aqlQuery).then((cursor) => cursor.next() || {}).then(({ verifiedEmailCode, verifiedPhoneCode }) => {
231
+ return await database.query(aqlQuery).then((cursor) => cursor.next()).then(({ verifiedEmailCode, verifiedPhoneCode }) => {
225
232
  switch (type) {
226
233
  case "email":
227
234
  return code === verifiedEmailCode;
@@ -230,65 +237,44 @@ const confirmCode = async (context, args) => {
230
237
  default:
231
238
  return false;
232
239
  }
233
- }).catch(
234
- (error) => (0, import_utils2.logError)({
235
- action,
236
- args: { code, type, userId: sessionId },
237
- category: eventCategory,
238
- label: import_utils2.ErrorTypes.DATABASE_ERROR
239
- }, error, context)
240
- );
240
+ });
241
241
  } catch (error) {
242
242
  return false;
243
243
  }
244
244
  };
245
- const deleteUser = (context, args) => {
245
+ const deleteUser = (context, user) => {
246
246
  const action = "deleteUser";
247
- const { database, session: { userId: sessionId, userAccess: sessionAccess } } = context;
248
- const { userId } = args;
249
- const isAdmin = sessionAccess > 2;
250
- if (!isAdmin && sessionId !== userId) {
251
- (0, import_utils2.logException)({
252
- action,
253
- args,
254
- category: eventCategory,
255
- label: "unauthorized",
256
- value: "invalid_session"
257
- }, context);
258
- return null;
259
- }
247
+ const { database } = context;
248
+ const { userId } = (0, import_userAdapter.parseUser)(user);
260
249
  const aqlQuery = import_arangojs.aql`FOR u IN users
261
250
  FILTER u._key == ${userId}
262
251
  LIMIT 1
263
252
  REMOVE u IN users
264
253
  RETURN OLD`;
265
- const stripeClient = new import_stripe.default(import_config.Config.get("stripe.token"), { apiVersion, typescript: true });
266
- return database.query(aqlQuery).then((cursor) => cursor.next()).then((user = {}) => stripeClient.customers.del(user.stripeCustomerId).then(() => stripeClient.accounts.del(user.stripeAccountId)).then(() => user)).catch((error) => {
267
- throw error;
268
- });
254
+ const stripeClient = new import_stripe.default(import_config.Config.get("stripe.token"), { apiVersion: STRIPE_API_VERSION, typescript: true });
255
+ return database.query(aqlQuery).then((cursor) => cursor.next()).then((deletedUser) => stripeClient.customers.del(deletedUser?.stripeCustomerId).then(() => stripeClient.accounts.del(deletedUser?.stripeAccountId)).then(() => deletedUser)).catch((error) => (0, import_analyticsUtils.logError)({
256
+ action,
257
+ category: eventCategory,
258
+ params: { userId },
259
+ value: import_error.ErrorTypes.DATABASE_ERROR
260
+ }, error, context));
269
261
  };
270
- const deactivateUser = (context, userId) => {
262
+ const deactivateUser = (context, user) => {
271
263
  const action = "delete";
272
- const { database, session: { userId: sessionId, userAccess: sessionAccess } } = context;
273
- const isAdmin = sessionAccess > 2;
274
- if (!isAdmin && sessionId !== userId) {
275
- (0, import_utils2.logException)({
276
- action,
277
- category: eventCategory,
278
- label: "unauthorized",
279
- value: "invalid_session"
280
- }, context);
281
- return null;
282
- }
264
+ const { database } = context;
265
+ const { userId } = (0, import_userAdapter.parseUser)(user);
283
266
  const updated = {
284
267
  userAccess: 0
285
268
  };
286
269
  const aqlQuery = import_arangojs.aql`UPDATE ${userId} WITH ${updated} IN users LIMIT 1 RETURN NEW`;
287
- return database.query(aqlQuery).then((cursor) => cursor.next()).catch((error) => {
288
- throw error;
289
- });
270
+ return database.query(aqlQuery).then((cursor) => cursor.next()).catch((error) => (0, import_analyticsUtils.logError)({
271
+ action,
272
+ category: eventCategory,
273
+ params: { userId },
274
+ value: import_error.ErrorTypes.DATABASE_ERROR
275
+ }, error, context));
290
276
  };
291
- const getDisplayName = (user = {}) => {
277
+ const getDisplayName = (user) => {
292
278
  const { first, last, name = "", username = "" } = user;
293
279
  const fullname = [first, last].join(" ").trim();
294
280
  if (name) {
@@ -307,30 +293,28 @@ const getSessionUser = (context) => {
307
293
  const aqlQuery = `LET u = DOCUMENT("users/${sessionId}")
308
294
  ${selectQueries.join("\n")}
309
295
  RETURN MERGE(u, {${selectObjects.join(", ")}})`;
310
- return database.query(aqlQuery).then((cursor) => cursor.next()).then((user = {}) => user).catch((error) => (0, import_utils2.logError)({
296
+ return database.query(aqlQuery).then((cursor) => cursor.next()).catch((error) => (0, import_analyticsUtils.logError)({
311
297
  action,
312
- args: { username, userId: sessionId },
313
298
  category: eventCategory,
314
- label: import_utils2.ErrorTypes.DATABASE_ERROR
299
+ params: { username, userId: sessionId },
300
+ value: import_error.ErrorTypes.DATABASE_ERROR
315
301
  }, error, context));
316
302
  };
317
- const getUser = (context, args) => {
303
+ const getUser = (context, user) => {
318
304
  const action = "getUser";
319
- const { userId } = args;
305
+ const { userId } = (0, import_userAdapter.parseUser)(user);
320
306
  const { database, fields } = context;
321
- const formatUserId = (0, import_utils.parseId)(userId);
322
307
  const { objects: selectObjects, queries: selectQueries } = getUserOptional(fields);
323
- const aqlQuery = `LET u = DOCUMENT("users/${formatUserId}")
308
+ const aqlQuery = `LET u = DOCUMENT("users/${userId}")
324
309
  ${selectQueries.join("\n")}
325
310
  FILTER u.userAccess > 0
326
311
  RETURN MERGE(u, {${selectObjects.join(", ")}})`;
327
- return database.query(aqlQuery).then((cursor) => cursor.next()).then((user = {}) => user).catch((error) => (0, import_utils2.logError)({
312
+ return database.query(aqlQuery).then((cursor) => cursor.next()).then((user2) => user2).catch((error) => (0, import_analyticsUtils.logError)({
328
313
  action,
329
- args,
330
314
  category: eventCategory,
331
- label: import_utils2.ErrorTypes.DATABASE_ERROR
332
- }, error, context).then(() => {
333
- }));
315
+ params: { userId },
316
+ value: import_error.ErrorTypes.DATABASE_ERROR
317
+ }, error, context));
334
318
  };
335
319
  const getUsers = (context, options) => {
336
320
  const action = "getUserList";
@@ -347,11 +331,11 @@ const getUsers = (context, options) => {
347
331
  ${limit.aql}
348
332
  SORT u.username
349
333
  RETURN MERGE(u, {${selectObjects.join(", ")}})`;
350
- return database.query(aqlQuery).then((cursor) => cursor.all()).catch((error) => (0, import_utils2.logError)({
334
+ return database.query(aqlQuery).then((cursor) => cursor.all()).catch((error) => (0, import_analyticsUtils.logError)({
351
335
  action,
352
336
  category: eventCategory,
353
- label: import_utils2.ErrorTypes.DATABASE_ERROR
354
- }, error, context).then(() => []));
337
+ value: import_error.ErrorTypes.DATABASE_ERROR
338
+ }, error, context));
355
339
  };
356
340
  const getUsersByReactions = (context, { reactions = [], username }, options) => {
357
341
  const action = "getUsersByReactions";
@@ -368,20 +352,19 @@ const getUsersByReactions = (context, { reactions = [], username }, options) =>
368
352
  const aqlQuery = `FOR u, r IN OUTBOUND "${formatSessionId}" hasReaction
369
353
  OPTIONS {vertexCollections: "users"}
370
354
  ${selectQueries.join("\n")}
371
- ${filterBy.length ? `FILTER ${filterBy.join(" && ")}` : ""}
355
+ FILTER ${filterBy.join(" && ")}
372
356
  ${limit.aql}
373
357
  RETURN MERGE(u, {${selectObjects.join(", ")}})`;
374
- console.log({ aqlQuery });
375
- return database.query(aqlQuery).then((cursor) => cursor.all()).catch((error) => (0, import_utils2.logError)({
358
+ return database.query(aqlQuery).then((cursor) => cursor.all()).catch((error) => (0, import_analyticsUtils.logError)({
376
359
  action,
377
360
  category: eventCategory,
378
- label: import_utils2.ErrorTypes.DATABASE_ERROR
379
- }, error, context).then(() => []));
361
+ value: import_error.ErrorTypes.DATABASE_ERROR
362
+ }, error, context));
380
363
  };
381
364
  const getUsersByTags = (context, { tags, username }, options) => {
382
365
  const action = "getUsersByTags";
383
366
  const { database, fields, session: { userId: sessionId } } = context;
384
- const formatTags = tags.reduce((list, tagName) => {
367
+ const formatTags = tags?.reduce((list, tagName) => {
385
368
  if (tagName) {
386
369
  list.push((0, import_utils.parseChar)(tagName, 32).toLowerCase());
387
370
  }
@@ -399,15 +382,14 @@ const getUsersByTags = (context, { tags, username }, options) => {
399
382
  FOR u, it IN OUTBOUND t isTagged
400
383
  OPTIONS {bfs: true, uniqueVertices: "global", vertexCollections: "users"}
401
384
  ${selectQueries.join("\n")}
402
- ${filterBy.length ? `FILTER ${filterBy.join(" && ")}` : ""}
385
+ FILTER ${filterBy.join(" && ")}
403
386
  ${limit.aql}
404
387
  RETURN DISTINCT MERGE(u, {${selectObjects.join(", ")}})`;
405
- console.log("getUsersByTags", aqlQuery);
406
- return database.query(aqlQuery).then((cursor) => cursor.all()).catch((error) => (0, import_utils2.logError)({
388
+ return database.query(aqlQuery).then((cursor) => cursor.all()).catch((error) => (0, import_analyticsUtils.logError)({
407
389
  action,
408
390
  category: eventCategory,
409
- label: import_utils2.ErrorTypes.DATABASE_ERROR
410
- }, error, context).then(() => []));
391
+ value: import_error.ErrorTypes.DATABASE_ERROR
392
+ }, error, context));
411
393
  };
412
394
  const getUsersByLatest = (context, { username }, options) => {
413
395
  const action = "getUsersByLatest";
@@ -426,72 +408,74 @@ const getUsersByLatest = (context, { username }, options) => {
426
408
  ${limit.aql}
427
409
  SORT distance ASC, u.added DESC
428
410
  RETURN MERGE(u, {${selectObjects.join(", ")}})`;
429
- return database.query(aqlQuery).then((cursor) => cursor.all()).catch((error) => (0, import_utils2.logError)({
411
+ return database.query(aqlQuery).then((cursor) => cursor.all()).catch((error) => (0, import_analyticsUtils.logError)({
430
412
  action,
431
413
  category: eventCategory,
432
- label: import_utils2.ErrorTypes.DATABASE_ERROR
433
- }, error, context).then(() => []));
414
+ value: import_error.ErrorTypes.DATABASE_ERROR
415
+ }, error, context));
434
416
  };
435
417
  const refreshSession = async (context, { expires, token }) => {
436
- const { error } = (0, import_session.getSession)(token);
437
- if (error) {
438
- return { errors: [error] };
439
- }
440
- const { exp, userId, username, userAccess } = (0, import_session.getSession)(token);
441
- const now = Math.ceil(import_luxon.DateTime.local().toSeconds());
442
- if (exp > now) {
443
- return createToken(userId, username, userAccess, expires);
444
- }
445
- return { errors: ["session_expired"] };
418
+ const { userId, username, userAccess } = (0, import_session.getSession)(token);
419
+ return createToken(userId, username, userAccess, expires);
446
420
  };
447
421
  const signIn = async (context, args) => {
448
422
  const action = "signIn";
449
- const { expires, password, username } = args;
423
+ const { database } = context;
424
+ const { email, expires, password, username } = args;
425
+ const formatEmail = (0, import_utils.parseEmail)(email);
450
426
  const formatUsername = (0, import_utils.parseUsername)(username);
451
427
  const formatPassword = (0, import_utils.parsePassword)(password);
452
428
  const formatExpires = (0, import_utils.parseNum)(expires) || 15;
453
- const { database } = context;
454
- if (!formatUsername || !formatPassword) {
455
- return (0, import_utils2.logException)({
429
+ if (!formatUsername && !formatEmail || !formatPassword) {
430
+ return (0, import_analyticsUtils.logException)({
456
431
  action,
457
- args: { username },
458
432
  category: eventCategory,
459
- value: import_utils2.ErrorTypes.INVALID_ARGUMENTS
433
+ params: { username },
434
+ value: import_error.ErrorTypes.INVALID_ARGUMENTS
460
435
  }, context);
461
436
  }
462
- const checkQuery = import_arangojs.aql`FOR u IN users
463
- FILTER u.username == ${formatUsername}
437
+ const filters = [];
438
+ if (formatEmail) {
439
+ filters.push(`u.email == "${formatEmail}"`);
440
+ } else if (formatUsername) {
441
+ filters.push(`u.username == "${formatUsername}"`);
442
+ }
443
+ const checkQuery = `FOR u IN users
444
+ FILTER ${filters.join(" || ")}
464
445
  LIMIT 1
465
446
  RETURN u`;
466
- const checkUser = await database.query(checkQuery).then((cursor) => cursor.next()).catch(
467
- (error) => (0, import_utils2.logError)({
447
+ let checkUser;
448
+ try {
449
+ checkUser = await database.query(checkQuery).then((cursor) => cursor.next());
450
+ } catch (error) {
451
+ return (0, import_analyticsUtils.logError)({
468
452
  action,
469
- args: { username: formatUsername },
470
453
  category: eventCategory,
471
- label: import_utils2.ErrorTypes.DATABASE_ERROR
472
- }, error, context).then(() => null)
473
- );
454
+ params: { username: formatUsername },
455
+ value: import_error.ErrorTypes.DATABASE_ERROR
456
+ }, error, context);
457
+ }
474
458
  if (!checkUser) {
475
- return (0, import_utils2.logException)({
459
+ return (0, import_analyticsUtils.logException)({
476
460
  action,
477
- args: { username },
478
461
  category: eventCategory,
479
- value: import_utils2.ErrorTypes.INVALID_AUTHENTICATION
462
+ params: { username },
463
+ value: import_error.ErrorTypes.INVALID_AUTHENTICATION
480
464
  }, context);
481
465
  }
482
- const { _key: userId, salt, userAccess } = checkUser;
466
+ const { _key: userId, password: validPassword, salt, userAccess } = checkUser;
483
467
  const authPassword = (0, import_utils.createPassword)(formatPassword, salt);
484
- if (checkUser.password !== authPassword) {
485
- return (0, import_utils2.logException)({
468
+ if (validPassword !== authPassword) {
469
+ return (0, import_analyticsUtils.logException)({
486
470
  action,
487
- args: { username },
488
471
  category: eventCategory,
489
- value: import_utils2.ErrorTypes.INVALID_AUTHENTICATION
472
+ params: { userAccess, userId, username },
473
+ value: import_error.ErrorTypes.INVALID_AUTHENTICATION
490
474
  }, context);
491
475
  }
492
476
  return createToken(userId, username, userAccess, formatExpires);
493
477
  };
494
- const signOut = async (context, args) => {
478
+ const signOut = async (context) => {
495
479
  const action = "signOut";
496
480
  const { database, session: { userId: sessionId, username } } = context;
497
481
  const userDocId = `users/${sessionId}`;
@@ -504,16 +488,14 @@ const signOut = async (context, args) => {
504
488
  LIMIT 1
505
489
  RETURN NEW`;
506
490
  try {
507
- await database.query(sessionQuery).then((cursor) => cursor.next()).catch(
508
- (error) => (0, import_utils2.logError)({
509
- action,
510
- args: { username, userId: sessionId },
511
- category: eventCategory,
512
- label: import_utils2.ErrorTypes.DATABASE_ERROR
513
- }, error, context)
514
- );
491
+ await database.query(sessionQuery).then((cursor) => cursor.next());
515
492
  } catch (error) {
516
- return false;
493
+ await (0, import_analyticsUtils.logError)({
494
+ action,
495
+ category: eventCategory,
496
+ params: { username, userId: sessionId },
497
+ value: import_error.ErrorTypes.DATABASE_ERROR
498
+ }, error, context);
517
499
  }
518
500
  return true;
519
501
  };
@@ -526,13 +508,24 @@ const getActiveUserCount = (context) => {
526
508
  RETURN u
527
509
  )
528
510
  RETURN LENGTH(docs)`;
529
- return database.query(countQuery).then((cursor) => cursor.next()).catch(
530
- (error) => (0, import_utils2.logError)({
531
- action,
532
- category: eventCategory,
533
- label: import_utils2.ErrorTypes.DATABASE_ERROR
534
- }, error, context).then(() => 0)
535
- );
511
+ return database.query(countQuery).then((cursor) => cursor.next()).catch((error) => (0, import_analyticsUtils.logError)({
512
+ action,
513
+ category: eventCategory,
514
+ value: import_error.ErrorTypes.DATABASE_ERROR
515
+ }, error, context));
516
+ };
517
+ const getUserByToken = (context, token) => {
518
+ const action = "getUserByToken";
519
+ const { database } = context;
520
+ const { userId } = (0, import_session.getSession)(token);
521
+ const userDocId = (0, import_arangodbUtils.getDocId)("users", { userId });
522
+ const aqlQuery = import_arangojs.aql`LET u = DOCUMENT("${userDocId}") RETURN u`;
523
+ return database.query(aqlQuery).then((cursor) => cursor.next()).catch((error) => (0, import_analyticsUtils.logError)({
524
+ action,
525
+ category: eventCategory,
526
+ params: { userId },
527
+ value: import_error.ErrorTypes.DATABASE_ERROR
528
+ }, error, context));
536
529
  };
537
530
  // Annotate the CommonJS export names for ESM import in node:
538
531
  0 && (module.exports = {
@@ -546,6 +539,7 @@ const getActiveUserCount = (context) => {
546
539
  getDisplayName,
547
540
  getSessionUser,
548
541
  getUser,
542
+ getUserByToken,
549
543
  getUserOptional,
550
544
  getUsers,
551
545
  getUsersByLatest,
@@ -557,4 +551,4 @@ const getActiveUserCount = (context) => {
557
551
  signOut,
558
552
  updateUser
559
553
  });
560
- //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL2FjdGlvbnMvdXNlcnMudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8qKlxuICogQ29weXJpZ2h0IChjKSAyMDE5LVByZXNlbnQsIE5pdHJvZ2VuIExhYnMsIEluYy5cbiAqIENvcHlyaWdodHMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLiBTZWUgdGhlIGFjY29tcGFueWluZyBMSUNFTlNFIGZpbGUgZm9yIHRlcm1zLlxuICovXG5pbXBvcnQge1xuICBjcmVhdGVIYXNoLFxuICBjcmVhdGVQYXNzd29yZCxcbiAgcGFyc2VDaGFyLFxuICBwYXJzZUVtYWlsLFxuICBwYXJzZUlkLFxuICBwYXJzZU51bSxcbiAgcGFyc2VQYXNzd29yZCxcbiAgcGFyc2VQaG9uZSxcbiAgcGFyc2VVc2VybmFtZVxufSBmcm9tICdAbmxhYnMvdXRpbHMnO1xuaW1wb3J0IHthcWx9IGZyb20gJ2FyYW5nb2pzJztcbmltcG9ydCB7QXFsUXVlcnl9IGZyb20gJ2FyYW5nb2pzL2FxbCc7XG5pbXBvcnQge0VkZ2VDb2xsZWN0aW9ufSBmcm9tICdhcmFuZ29qcy9jb2xsZWN0aW9uJztcbmltcG9ydCB7QXJyYXlDdXJzb3J9IGZyb20gJ2FyYW5nb2pzL2N1cnNvcic7XG5pbXBvcnQge0RhdGVUaW1lfSBmcm9tICdsdXhvbic7XG5pbXBvcnQgU3RyaXBlIGZyb20gJ3N0cmlwZSc7XG5cbmltcG9ydCB7Q29uZmlnfSBmcm9tICcuLi9jb25maWcnO1xuaW1wb3J0IHtBcGlDb250ZXh0fSBmcm9tICcuLi90eXBlcy9hdXRoJztcbmltcG9ydCB7VXNlcn0gZnJvbSAnLi4vdHlwZXMvdXNlcnMnO1xuaW1wb3J0IHtFcnJvclR5cGVzLCBnZXRMaW1pdCwgbG9nRXJyb3IsIGxvZ0V4Y2VwdGlvbiwgc2VsZWN0UmVhY3Rpb25Db3VudEJ5VHlwZX0gZnJvbSAnLi4vdXRpbHMnO1xuaW1wb3J0IHtnZXRTZXNzaW9uLCBTZXNzaW9uRXJyb3IsIFNlc3Npb25Ub2tlbiwgc2V0U2Vzc2lvbn0gZnJvbSAnLi4vdXRpbHMvc2Vzc2lvbic7XG5cbmNvbnN0IGV2ZW50Q2F0ZWdvcnk6IHN0cmluZyA9ICd1c2Vycyc7XG5jb25zdCBhcGlWZXJzaW9uOiBhbnkgPSAnMjAyMC0wMy0wMic7XG5cbmV4cG9ydCBpbnRlcmZhY2UgVXNlck9wdGlvbnMge1xuICByZWFkb25seSBmcm9tPzogbnVtYmVyO1xuICByZWFkb25seSB0bz86IG51bWJlcjtcbiAgcmVhZG9ubHkgdXNlcm5hbWU/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBlbnVtIFVzZXJBY2Nlc3Mge1xuICBERUFDVElWQVRFRCA9IDAsXG4gIEFDVElWRSA9IDEsXG4gIFBSRU1JVU0gPSAyLFxuICBDT05URU5UX0FETUlOID0gMyxcbiAgQURNSU4gPSA0XG59XG5cbmV4cG9ydCBjb25zdCBjcmVhdGVUb2tlbiA9IChcbiAgdXNlcklkOiBzdHJpbmcsXG4gIHVzZXJuYW1lOiBzdHJpbmcsXG4gIHVzZXJBY2Nlc3M6IG51bWJlcixcbiAgZXhwaXJlczogbnVtYmVyID0gMTVcbik6IFNlc3Npb25Ub2tlbiA9PiB7XG4gIGNvbnN0IG5vdzogRGF0ZVRpbWUgPSBEYXRlVGltZS5sb2NhbCgpO1xuICBjb25zdCBzZXNzaW9uRXhwaXJlczogRGF0ZVRpbWUgPSBub3cucGx1cyh7bWludXRlczogZXhwaXJlc30pO1xuICBjb25zdCBpYXQ6IG51bWJlciA9IE1hdGguZmxvb3Iobm93LnRvU2Vjb25kcygpKTtcbiAgY29uc3QgZXhwOiBudW1iZXIgPSBNYXRoLmZsb29yKHNlc3Npb25FeHBpcmVzLnRvU2Vjb25kcygpKTtcblxuICBjb25zdCB0b2tlbiA9IHNldFNlc3Npb24oe1xuICAgIGV4cCxcbiAgICBpYXQsXG4gICAgdXNlcm5hbWUsXG4gICAgdXNlckFjY2VzcyxcbiAgICB1c2VySWRcbiAgfSk7XG5cbiAgcmV0dXJuIHtcbiAgICBleHBpcmVzOiBzZXNzaW9uRXhwaXJlcy50b01pbGxpcygpLFxuICAgIGlzc3VlZDogbm93LnRvTWlsbGlzKCksXG4gICAgdG9rZW5cbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBnZXRVc2VyT3B0aW9uYWwgPSAoZmllbGRzOiBzdHJpbmdbXSA9IFtdKSA9PlxuICBmaWVsZHMucmVkdWNlKChzZWxlY3RzOiBhbnksIGZpZWxkOiBzdHJpbmcpID0+IHtcbiAgICBpZihmaWVsZC5pbmNsdWRlcygnQ291bnQnKSkge1xuICAgICAgcmV0dXJuIHNlbGVjdFJlYWN0aW9uQ291bnRCeVR5cGUoJ3VzZXJzJywgJ3UnLCBmaWVsZCwgc2VsZWN0cyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHNlbGVjdHM7XG4gIH0sIHtvYmplY3RzOiBbXSwgcXVlcmllczogW119KTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlVXNlck9wdGlvbnMgPSAob3B0aW9uczogVXNlck9wdGlvbnMgPSB7fSkgPT4ge1xuICBjb25zdCB7XG4gICAgZnJvbSA9IDAsXG4gICAgdG8gPSAzMFxuICB9ID0gb3B0aW9ucztcblxuICByZXR1cm4ge1xuICAgIC4uLm9wdGlvbnMsXG4gICAgbGltaXQ6IGdldExpbWl0KGZyb20sIHRvKVxuICB9O1xufTtcblxuZXhwb3J0IGNvbnN0IGFkZFVzZXIgPSBhc3luYyAoY29udGV4dDogQXBpQ29udGV4dCwgYXJnczogYW55KTogUHJvbWlzZTxVc2VyPiA9PiB7XG4gIGNvbnN0IGFjdGlvbjogc3RyaW5nID0gJ2FkZFVzZXInO1xuICBjb25zdCB7ZGF0YWJhc2V9ID0gY29udGV4dDtcbiAgY29uc3Qge3VzZXJ9ID0gYXJncztcbiAgY29uc3Qge2VtYWlsLCBwYXNzd29yZCwgcGhvbmUsIHVzZXJuYW1lfSA9IHVzZXI7XG4gIGNvbnN0IHNhbHQ6IHN0cmluZyA9IGNyZWF0ZUhhc2goYCR7dXNlcm5hbWV9JHtwYXNzd29yZH1gLCBudWxsKTtcbiAgY29uc3QgZW5jcnlwdGVkUGFzc3dvcmQgPSBjcmVhdGVQYXNzd29yZChwYXNzd29yZCwgc2FsdCk7XG4gIGNvbnN0IGZvcm1hdFVzZXJuYW1lOiBzdHJpbmcgPSBwYXJzZVVzZXJuYW1lKHVzZXJuYW1lKTtcbiAgY29uc3QgZm9ybWF0RW1haWw6IHN0cmluZyA9IHBhcnNlRW1haWwoZW1haWwpO1xuICBjb25zdCBmb3JtYXRQaG9uZTogc3RyaW5nID0gcGFyc2VQaG9uZShwaG9uZSk7XG5cbiAgaWYoIWZvcm1hdFVzZXJuYW1lIHx8ICFwYXNzd29yZCB8fCAoIWZvcm1hdFBob25lICYmICFmb3JtYXRFbWFpbCkpIHtcbiAgICByZXR1cm4gbG9nRXhjZXB0aW9uKHtcbiAgICAgIGFjdGlvbixcbiAgICAgIGFyZ3M6IHt1c2VybmFtZX0sXG4gICAgICBjYXRlZ29yeTogZXZlbnRDYXRlZ29yeSxcbiAgICAgIHZhbHVlOiBFcnJvclR5cGVzLklOVkFMSURfQVJHVU1FTlRTXG4gICAgfSwgY29udGV4dCk7XG4gIH1cblxuICBjb25zdCBmaWx0ZXJzOiBzdHJpbmdbXSA9IFtgdS51c2VybmFtZSA9PSBcIiR7Zm9ybWF0VXNlcm5hbWV9XCJgXTtcblxuICBpZihmb3JtYXRFbWFpbCkge1xuICAgIGZpbHRlcnMucHVzaChgdS5lbWFpbCA9PSBcIiR7Zm9ybWF0RW1haWx9XCJgKTtcbiAgfVxuXG4gIGlmKGZvcm1hdFBob25lKSB7XG4gICAgZmlsdGVycy5wdXNoKGB1LnBob25lID09ICR7Zm9ybWF0UGhvbmV9YCk7XG4gIH1cblxuICBjb25zdCBjaGVja1F1ZXJ5OiBzdHJpbmcgPSBgRk9SIHUgSU4gdXNlcnNcbiAgICBGSUxURVIgJHtmaWx0ZXJzLmpvaW4oJyB8fCAnKX1cbiAgICBSRVRVUk4gdWA7XG4gIGNvbnN0IGV4aXN0aW5nVXNlcnMgPSBhd2FpdCBkYXRhYmFzZS5xdWVyeShjaGVja1F1ZXJ5KVxuICAgIC50aGVuKChjdXJzb3I6IEFycmF5Q3Vyc29yKSA9PiBjdXJzb3IuYWxsKCkpXG4gICAgLmNhdGNoKChlcnJvcikgPT4gbG9nRXJyb3Ioe1xuICAgICAgYWN0aW9uLFxuICAgICAgYXJnczoge3VzZXJuYW1lfSxcbiAgICAgIGNhdGVnb3J5OiBldmVudENhdGVnb3J5LFxuICAgICAgbGFiZWw6IEVycm9yVHlwZXMuREFUQUJBU0VfRVJST1JcbiAgICB9LCBlcnJvciwgY29udGV4dClcbiAgICAgIC50aGVuKCgpID0+IG51bGwpXG4gICAgKTtcblxuICBpZihleGlzdGluZ1VzZXJzLmxlbmd0aCkge1xuICAgIHJldHVybiBsb2dFeGNlcHRpb24oe1xuICAgICAgYWN0aW9uLFxuICAgICAgYXJnczoge3VzZXJuYW1lfSxcbiAgICAgIGNhdGVnb3J5OiBldmVudENhdGVnb3J5LFxuICAgICAgdmFsdWU6IEVycm9yVHlwZXMuRVhJU1RJTkdfVVNFUk5BTUVcbiAgICB9LCBjb250ZXh0KTtcbiAgfVxuXG4gIGNvbnN0IHZlcmlmaWVkRW1haWxDb2RlOiBudW1iZXIgPSBNYXRoLmZsb29yKDEwMDAwMCArIChNYXRoLnJhbmRvbSgpICogOTAwMDAwKSk7XG4gIGNvbnN0IHZlcmlmaWVkUGhvbmVDb2RlOiBudW1iZXIgPSBNYXRoLmZsb29yKDEwMDAwMCArIChNYXRoLnJhbmRvbSgpICogOTAwMDAwKSk7XG5cbiAgLy8gQWRkIG5ldyB1c2VyIHByb3BlcnRpZXNcbiAgY29uc3QgaW5zZXJ0OiBVc2VyID0ge1xuICAgIF9rZXk6IGNyZWF0ZUhhc2godXNlcm5hbWUsIG51bGwpLFxuICAgIGFkZGVkOiBEYXRlLm5vdygpLFxuICAgIGVtYWlsOiBmb3JtYXRFbWFpbCxcbiAgICBtb2RpZmllZDogRGF0ZS5ub3coKSxcbiAgICBwYXNzd29yZDogZW5jcnlwdGVkUGFzc3dvcmQsXG4gICAgcGhvbmU6IGZvcm1hdFBob25lLFxuICAgIHNhbHQsXG4gICAgdXNlcm5hbWU6IGZvcm1hdFVzZXJuYW1lLFxuICAgIHVzZXJBY2Nlc3M6IDEsXG4gICAgdmVyaWZpZWRFbWFpbDogZmFsc2UsXG4gICAgdmVyaWZpZWRFbWFpbENvZGUsXG4gICAgdmVyaWZpZWRQaG9uZTogZmFsc2UsXG4gICAgdmVyaWZpZWRQaG9uZUNvZGVcbiAgfTtcblxuICAvLyBBZGQgbmV3IHVzZXIgaW4gQXJhbmdvREJcbiAgY29uc3QgaW5zZXJ0UXVlcnk6IEFxbFF1ZXJ5ID0gYXFsYElOU0VSVCAke2luc2VydH0gSU4gdXNlcnMgUkVUVVJOIE5FV2A7XG4gIHJldHVybiBhd2FpdCBkYXRhYmFzZS5xdWVyeShpbnNlcnRRdWVyeSlcbiAgICAudGhlbigoY3Vyc29yOiBBcnJheUN1cnNvcikgPT4gY3Vyc29yLm5leHQoKSB8fCB7fSlcbiAgICAuY2F0Y2goKGVycm9yKSA9PiBsb2dFcnJvcih7XG4gICAgICBhY3Rpb24sXG4gICAgICBhcmdzOiB7dXNlcm5hbWV9LFxuICAgICAgY2F0ZWdvcnk6IGV2ZW50Q2F0ZWdvcnksXG4gICAgICBsYWJlbDogRXJyb3JUeXBlcy5EQVRBQkFTRV9FUlJPUlxuICAgIH0sIGVycm9yLCBjb250ZXh0KVxuICAgICAgLnRoZW4oKCkgPT4gbnVsbClcbiAgICApO1xufTtcblxuZXhwb3J0IGNvbnN0IHVwZGF0ZVVzZXIgPSBhc3luYyAoY29udGV4dDogQXBpQ29udGV4dCwgdXNlcjogVXNlcik6IFByb21pc2U8YW55PiA9PiB7XG4gIGNvbnN0IGFjdGlvbjogc3RyaW5nID0gJ3VwZGF0ZVVzZXInO1xuICBjb25zdCB7ZGF0YWJhc2V9ID0gY29udGV4dDtcbiAgY29uc3Qge19rZXksIF9pZCwgaWQsIHRhZ3MgPSBbXSwgdXNlcklkLCAuLi51cGRhdGVkfSA9IHVzZXI7XG4gIGxldCB1c2VyRG9jSWQ6IHN0cmluZztcblxuICBpZihfaWQgfHwgaWQpIHtcbiAgICB1c2VyRG9jSWQgPSBfaWQgfHwgaWQ7XG4gIH0gZWxzZSBpZihfa2V5IHx8IHVzZXJJZCkge1xuICAgIHVzZXJEb2NJZCA9IGB1c2Vycy8ke19rZXkgfHwgdXNlcklkfWA7XG4gIH1cblxuICBjb25zdCB1c2VyUXVlcnk6IEFxbFF1ZXJ5ID0gYXFsYExFVCB1ID0gRE9DVU1FTlQoJHt1c2VyRG9jSWR9KVxuICAgIFVQREFURSB1IFdJVEggJHt1cGRhdGVkfSBJTiB1c2Vyc1xuICAgIFJFVFVSTiBORVdgO1xuXG4gIGNvbnN0IHVwZGF0ZWRVc2VyID0gYXdhaXQgZGF0YWJhc2UucXVlcnkodXNlclF1ZXJ5KVxuICAgIC50aGVuKChjdXJzb3IpID0+IGN1cnNvci5uZXh0KCkpXG4gICAgLmNhdGNoKChlcnJvcjogRXJyb3IpID0+IHtcbiAgICAgIGNvbnNvbGUubG9nKGVycm9yKTtcbiAgICAgIHRocm93IGVycm9yO1xuICAgIH0pO1xuXG4gIGNvbnN0IHRhZ0NvbGxlY3Rpb246IEVkZ2VDb2xsZWN0aW9uID0gZGF0YWJhc2UuY29sbGVjdGlvbignaXNUYWdnZWQnKTtcbiAgYXdhaXQgUHJvbWlzZS5hbGwodGFncy5tYXAoKHtpZDogdGFnRG9jSWQsIG5hbWV9KSA9PiB7XG4gICAgY29uc3QgZWRnZSA9IHtcbiAgICAgIF9mcm9tOiB0YWdEb2NJZCxcbiAgICAgIF9rZXk6IGNyZWF0ZUhhc2goYGlzVGFnZ2VkLSR7dGFnRG9jSWR9LSR7dXNlckRvY0lkfWApLFxuICAgICAgX3RvOiB1c2VyRG9jSWQsXG4gICAgICBhZGRlZDogRGF0ZS5ub3coKSxcbiAgICAgIG5hbWVcbiAgICB9O1xuICAgIGNvbnN0IHRhZ1F1ZXJ5OiBBcWxRdWVyeSA9IGFxbGBGT1IgaXQgSU4gaXNUYWdnZWRcbiAgICAgIEZJTFRFUiBpdC5fZnJvbSA9PSAke3RhZ0RvY0lkfSAmJiBpdC5fdG8gPT0gJHt1c2VyRG9jSWR9ICYmIGl0Lm5hbWUgPT0gJHtuYW1lfVxuICAgICAgTElNSVQgMVxuICAgICAgUkVUVVJOIGl0YDtcblxuICAgIHJldHVybiBkYXRhYmFzZS5xdWVyeSh0YWdRdWVyeSlcbiAgICAgIC50aGVuKChjdXJzb3I6IEFycmF5Q3Vyc29yKSA9PiBjdXJzb3IubmV4dCgpKVxuICAgICAgLnRoZW4oKHRhZ0VkZ2UpID0+IHtcbiAgICAgICAgaWYoISF0YWdFZGdlKSB7XG4gICAgICAgICAgcmV0dXJuIHRhZ0VkZ2U7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGFnQ29sbGVjdGlvbi5zYXZlKGVkZ2UsIHtyZXR1cm5OZXc6IHRydWV9KS50aGVuKCgpID0+IGVkZ2UpO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaCgoZXJyb3I6IEVycm9yKSA9PiBsb2dFcnJvcih7XG4gICAgICAgIGFjdGlvbixcbiAgICAgICAgY2F0ZWdvcnk6IGV2ZW50Q2F0ZWdvcnksXG4gICAgICAgIGxhYmVsOiAnZGJfZXJyb3InXG4gICAgICB9LCBlcnJvciwgY29udGV4dCkudGhlbigoKSA9PiBudWxsKSk7XG4gIH0pKTtcblxuICByZXR1cm4gdXBkYXRlZFVzZXI7XG59O1xuXG5leHBvcnQgY29uc3QgY29uZmlybUNvZGUgPSBhc3luYyAoY29udGV4dDogQXBpQ29udGV4dCwgYXJncyk6IFByb21pc2U8Ym9vbGVhbj4gPT4ge1xuICBjb25zdCBhY3Rpb246IHN0cmluZyA9ICdjb25maXJtRW1haWwnO1xuICBjb25zdCB7ZGF0YWJhc2UsIHNlc3Npb246IHt1c2VySWQ6IHNlc3Npb25JZH19ID0gY29udGV4dDtcbiAgY29uc3Qge2NvZGUsIHR5cGV9ID0gYXJncztcbiAgY29uc3QgdXNlckRvY0lkOiBzdHJpbmcgPSBgdXNlcnMvJHtzZXNzaW9uSWR9YDtcblxuICBjb25zdCBhcWxRdWVyeTogQXFsUXVlcnkgPSBhcWxgTEVUIHUgPSBET0NVTUVOVCgke3VzZXJEb2NJZH0pIFJFVFVSTiB1YDtcblxuICB0cnkge1xuICAgIHJldHVybiBkYXRhYmFzZS5xdWVyeShhcWxRdWVyeSlcbiAgICAgIC50aGVuKChjdXJzb3IpID0+IGN1cnNvci5uZXh0KCkgfHwge30pXG4gICAgICAudGhlbigoe3ZlcmlmaWVkRW1haWxDb2RlLCB2ZXJpZmllZFBob25lQ29kZX06IFVzZXIpID0+IHtcbiAgICAgICAgc3dpdGNoKHR5cGUpIHtcbiAgICAgICAgICBjYXNlICdlbWFpbCc6XG4gICAgICAgICAgICByZXR1cm4gY29kZSA9PT0gdmVyaWZpZWRFbWFpbENvZGU7XG4gICAgICAgICAgY2FzZSAncGhvbmUnOlxuICAgICAgICAgICAgcmV0dXJuIGNvZGUgPT09IHZlcmlmaWVkUGhvbmVDb2RlO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgICAuY2F0Y2goKGVycm9yKSA9PiBsb2dFcnJvcih7XG4gICAgICAgIGFjdGlvbixcbiAgICAgICAgYXJnczoge2NvZGUsIHR5cGUsIHVzZXJJZDogc2Vzc2lvbklkfSxcbiAgICAgICAgY2F0ZWdvcnk6IGV2ZW50Q2F0ZWdvcnksXG4gICAgICAgIGxhYmVsOiBFcnJvclR5cGVzLkRBVEFCQVNFX0VSUk9SXG4gICAgICB9LCBlcnJvciwgY29udGV4dClcbiAgICAgICk7XG4gIH0gY2F0Y2goZXJyb3IpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBkZWxldGVVc2VyID0gKGNvbnRleHQ6IEFwaUNvbnRleHQsIGFyZ3M6IGFueSk6IFByb21pc2U8YW55PiA9PiB7XG4gIGNvbnN0IGFjdGlvbjogc3RyaW5nID0gJ2RlbGV0ZVVzZXInO1xuICBjb25zdCB7ZGF0YWJhc2UsIHNlc3Npb246IHt1c2VySWQ6IHNlc3Npb25JZCwgdXNlckFjY2Vzczogc2Vzc2lvbkFjY2Vzc319ID0gY29udGV4dDtcbiAgY29uc3Qge3VzZXJJZH0gPSBhcmdzO1xuICBjb25zdCBpc0FkbWluOiBib29sZWFuID0gc2Vzc2lvbkFjY2VzcyA+IDI7XG5cbiAgaWYoIWlzQWRtaW4gJiYgKHNlc3Npb25JZCAhPT0gdXNlcklkKSkge1xuICAgIGxvZ0V4Y2VwdGlvbih7XG4gICAgICBhY3Rpb24sXG4gICAgICBhcmdzLFxuICAgICAgY2F0ZWdvcnk6IGV2ZW50Q2F0ZWdvcnksXG4gICAgICBsYWJlbDogJ3VuYXV0aG9yaXplZCcsXG4gICAgICB2YWx1ZTogJ2ludmFsaWRfc2Vzc2lvbidcbiAgICB9LCBjb250ZXh0KTtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGNvbnN0IGFxbFF1ZXJ5OiBBcWxRdWVyeSA9IGFxbGBGT1IgdSBJTiB1c2Vyc1xuICAgIEZJTFRFUiB1Ll9rZXkgPT0gJHt1c2VySWR9XG4gICAgTElNSVQgMVxuICAgIFJFTU9WRSB1IElOIHVzZXJzXG4gICAgUkVUVVJOIE9MRGA7XG5cbiAgLy8gU3RyaXBlXG4gIGNvbnN0IHN0cmlwZUNsaWVudCA9IG5ldyBTdHJpcGUoQ29uZmlnLmdldCgnc3RyaXBlLnRva2VuJyksIHthcGlWZXJzaW9uLCB0eXBlc2NyaXB0OiB0cnVlfSk7XG5cbiAgcmV0dXJuIGRhdGFiYXNlLnF1ZXJ5KGFxbFF1ZXJ5KVxuICAgIC50aGVuKChjdXJzb3I6IEFycmF5Q3Vyc29yKSA9PiBjdXJzb3IubmV4dCgpKVxuICAgIC50aGVuKCh1c2VyOiBVc2VyID0ge30pID0+IHN0cmlwZUNsaWVudC5jdXN0b21lcnMuZGVsKHVzZXIuc3RyaXBlQ3VzdG9tZXJJZClcbiAgICAgIC50aGVuKCgpID0+IHN0cmlwZUNsaWVudC5hY2NvdW50cy5kZWwodXNlci5zdHJpcGVBY2NvdW50SWQpKVxuICAgICAgLnRoZW4oKCkgPT4gdXNlcikpXG4gICAgLmNhdGNoKChlcnJvcjogRXJyb3IpID0+IHtcbiAgICAgIHRocm93IGVycm9yO1xuICAgIH0pO1xufTtcblxuZXhwb3J0IGNvbnN0IGRlYWN0aXZhdGVVc2VyID0gKGNvbnRleHQ6IEFwaUNvbnRleHQsIHVzZXJJZDogc3RyaW5nKTogUHJvbWlzZTxVc2VyPiA9PiB7XG4gIGNvbnN0IGFjdGlvbjogc3RyaW5nID0gJ2RlbGV0ZSc7XG4gIGNvbnN0IHtkYXRhYmFzZSwgc2Vzc2lvbjoge3VzZXJJZDogc2Vzc2lvbklkLCB1c2VyQWNjZXNzOiBzZXNzaW9uQWNjZXNzfX0gPSBjb250ZXh0O1xuICBjb25zdCBpc0FkbWluOiBib29sZWFuID0gc2Vzc2lvbkFjY2VzcyA+IDI7XG5cbiAgaWYoIWlzQWRtaW4gJiYgKHNlc3Npb25JZCAhPT0gdXNlcklkKSkge1xuICAgIGxvZ0V4Y2VwdGlvbih7XG4gICAgICBhY3Rpb24sXG4gICAgICBjYXRlZ29yeTogZXZlbnRDYXRlZ29yeSxcbiAgICAgIGxhYmVsOiAndW5hdXRob3JpemVkJyxcbiAgICAgIHZhbHVlOiAnaW52YWxpZF9zZXNzaW9uJ1xuICAgIH0sIGNvbnRleHQpO1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgY29uc3QgdXBkYXRlZDogVXNlciA9IHtcbiAgICB1c2VyQWNjZXNzOiAwXG4gIH07XG4gIGNvbnN0IGFxbFF1ZXJ5OiBBcWxRdWVyeSA9IGFxbGBVUERBVEUgJHt1c2VySWR9IFdJVEggJHt1cGRhdGVkfSBJTiB1c2VycyBMSU1JVCAxIFJFVFVSTiBORVdgO1xuXG4gIHJldHVybiBkYXRhYmFzZS5xdWVyeShhcWxRdWVyeSlcbiAgICAudGhlbigoY3Vyc29yOiBBcnJheUN1cnNvcikgPT4gY3Vyc29yLm5leHQoKSlcbiAgICAuY2F0Y2goKGVycm9yOiBFcnJvcikgPT4ge1xuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfSk7XG59O1xuXG5leHBvcnQgY29uc3QgZ2V0RGlzcGxheU5hbWUgPSAodXNlcjogVXNlciA9IHt9KTogc3RyaW5nID0+IHtcbiAgY29uc3Qge2ZpcnN0LCBsYXN0LCBuYW1lID0gJycsIHVzZXJuYW1lID0gJyd9ID0gdXNlcjtcbiAgY29uc3QgZnVsbG5hbWU6IHN0cmluZyA9IChbZmlyc3QsIGxhc3RdKS5qb2luKCcgJykudHJpbSgpO1xuXG4gIGlmKG5hbWUpIHtcbiAgICByZXR1cm4gbmFtZTtcbiAgfSBlbHNlIGlmKGZ1bGxuYW1lICE9PSAnJykge1xuICAgIHJldHVybiBmdWxsbmFtZTtcbiAgfSBlbHNlIGlmKHVzZXJuYW1lKSB7XG4gICAgcmV0dXJuIHVzZXJuYW1lO1xuICB9XG5cbiAgcmV0dXJuICdVbmtub3duJztcbn07XG5cbmV4cG9ydCBjb25zdCBnZXRTZXNzaW9uVXNlciA9IChjb250ZXh0OiBBcGlDb250ZXh0KTogUHJvbWlzZTxVc2VyPiA9PiB7XG4gIGNvbnN0IGFjdGlvbjogc3RyaW5nID0gJ2dldFNlc3Npb25Vc2VyJztcbiAgY29uc3Qge2RhdGFiYXNlLCBmaWVsZHMsIHNlc3Npb246IHt1c2VySWQ6IHNlc3Npb25JZCwgdXNlcm5hbWV9fSA9IGNvbnRleHQ7XG4gIGNvbnN0IHtvYmplY3RzOiBzZWxlY3RPYmplY3RzLCBxdWVyaWVzOiBzZWxlY3RRdWVyaWVzfSA9IGdldFVzZXJPcHRpb25hbChmaWVsZHMpO1xuXG4gIGNvbnN0IGFxbFF1ZXJ5OiBzdHJpbmcgPSBgTEVUIHUgPSBET0NVTUVOVChcInVzZXJzLyR7c2Vzc2lvbklkfVwiKVxuICAke3NlbGVjdFF1ZXJpZXMuam9pbignXFxuJyl9XG4gIFJFVFVSTiBNRVJHRSh1LCB7JHtzZWxlY3RPYmplY3RzLmpvaW4oJywgJyl9fSlgO1xuXG4gIHJldHVybiBkYXRhYmFzZS5xdWVyeShhcWxRdWVyeSlcbiAgICAudGhlbigoY3Vyc29yOiBBcnJheUN1cnNvcikgPT4gY3Vyc29yLm5leHQoKSlcbiAgICAudGhlbigodXNlciA9IHt9KSA9PiB1c2VyKVxuICAgIC5jYXRjaCgoZXJyb3I6IEVycm9yKSA9PiBsb2dFcnJvcih7XG4gICAgICBhY3Rpb24sXG4gICAgICBhcmdzOiB7dXNlcm5hbWUsIHVzZXJJZDogc2Vzc2lvbklkfSxcbiAgICAgIGNhdGVnb3J5OiBldmVudENhdGVnb3J5LFxuICAgICAgbGFiZWw6IEVycm9yVHlwZXMuREFUQUJBU0VfRVJST1JcbiAgICB9LCBlcnJvciwgY29udGV4dCkpO1xufTtcblxuZXhwb3J0IGNvbnN0IGdldFVzZXIgPSAoY29udGV4dDogQXBpQ29udGV4dCwgYXJnczogYW55KTogUHJvbWlzZTxVc2VyPiA9PiB7XG4gIGNvbnN0IGFjdGlvbjogc3RyaW5nID0gJ2dldFVzZXInO1xuICBjb25zdCB7dXNlcklkfSA9IGFyZ3M7XG4gIGNvbnN0IHtkYXRhYmFzZSwgZmllbGRzfSA9IGNvbnRleHQ7XG4gIGNvbnN0IGZvcm1hdFVzZXJJZDogc3RyaW5nID0gcGFyc2VJZCh1c2VySWQpO1xuICBjb25zdCB7b2JqZWN0czogc2VsZWN0T2JqZWN0cywgcXVlcmllczogc2VsZWN0UXVlcmllc30gPSBnZXRVc2VyT3B0aW9uYWwoZmllbGRzKTtcblxuICAvLyBHZXQgZGF0YSBmcm9tIGRhdGFiYXNlXG4gIGNvbnN0IGFxbFF1ZXJ5OiBzdHJpbmcgPSBgTEVUIHUgPSBET0NVTUVOVChcInVzZXJzLyR7Zm9ybWF0VXNlcklkfVwiKVxuICAgICR7c2VsZWN0UXVlcmllcy5qb2luKCdcXG4nKX1cbiAgICBGSUxURVIgdS51c2VyQWNjZXNzID4gMFxuICAgIFJFVFVSTiBNRVJHRSh1LCB7JHtzZWxlY3RPYmplY3RzLmpvaW4oJywgJyl9fSlgO1xuXG4gIHJldHVybiBkYXRhYmFzZS5xdWVyeShhcWxRdWVyeSlcbiAgICAudGhlbigoY3Vyc29yOiBBcnJheUN1cnNvcikgPT4gY3Vyc29yLm5leHQoKSlcbiAgICAudGhlbigodXNlciA9IHt9KSA9PiB1c2VyKVxuICAgIC5jYXRjaCgoZXJyb3I6IEVycm9yKSA9PiBsb2dFcnJvcih7XG4gICAgICBhY3Rpb24sXG4gICAgICBhcmdzLFxuICAgICAgY2F0ZWdvcnk6IGV2ZW50Q2F0ZWdvcnksXG4gICAgICBsYWJlbDogRXJyb3JUeXBlcy5EQVRBQkFTRV9FUlJPUlxuICAgIH0sIGVycm9yLCBjb250ZXh0KVxuICAgICAgLnRoZW4oKCkgPT4geyB9KSk7XG59O1xuXG5leHBvcnQgY29uc3QgZ2V0VXNlcnMgPSAoY29udGV4dDogQXBpQ29udGV4dCwgb3B0aW9ucz86IFVzZXJPcHRpb25zKTogUHJvbWlzZTxVc2VyW10+ID0+IHtcbiAgY29uc3QgYWN0aW9uOiBzdHJpbmcgPSAnZ2V0VXNlckxpc3QnO1xuICBjb25zdCB7ZGF0YWJhc2UsIGZpZWxkc30gPSBjb250ZXh0O1xuICBjb25zdCB7bGltaXQsIHVzZXJuYW1lfSA9IHBhcnNlVXNlck9wdGlvbnMob3B0aW9ucyk7XG4gIGNvbnN0IHtvYmplY3RzOiBzZWxlY3RPYmplY3RzLCBxdWVyaWVzOiBzZWxlY3RRdWVyaWVzfSA9IGdldFVzZXJPcHRpb25hbChmaWVsZHMpO1xuICBjb25zdCBmaWx0ZXJCeTogc3RyaW5nW10gPSBbJ3UudXNlckFjY2VzcyA+IDAnXTtcblxuICBpZih1c2VybmFtZSkge1xuICAgIGZpbHRlckJ5LnB1c2goYENPTlRBSU5TKHUudXNlcm5hbWUsIFwiJHtwYXJzZVVzZXJuYW1lKHVzZXJuYW1lKX1cIilgKTtcbiAgfVxuXG4gIC8vIEdldCBkYXRhIGZyb20gZGF0YWJhc2VcbiAgY29uc3QgYXFsUXVlcnk6IHN0cmluZyA9IGBGT1IgdSBJTiB1c2Vyc1xuICAgIEZJTFRFUiAke2ZpbHRlckJ5LmpvaW4oJyAmJiAnKX1cbiAgICAke3NlbGVjdFF1ZXJpZXMuam9pbignXFxuJyl9XG4gICAgJHtsaW1pdC5hcWx9XG4gICAgU09SVCB1LnVzZXJuYW1lXG4gICAgUkVUVVJOIE1FUkdFKHUsIHske3NlbGVjdE9iamVjdHMuam9pbignLCAnKX19KWA7XG5cbiAgcmV0dXJuIGRhdGFiYXNlLnF1ZXJ5KGFxbFF1ZXJ5KVxuICAgIC50aGVuKChjdXJzb3I6IEFycmF5Q3Vyc29yKSA9PiBjdXJzb3IuYWxsKCkpXG4gICAgLmNhdGNoKChlcnJvcjogRXJyb3IpID0+IGxvZ0Vycm9yKHtcbiAgICAgIGFjdGlvbixcbiAgICAgIGNhdGVnb3J5OiBldmVudENhdGVnb3J5LFxuICAgICAgbGFiZWw6IEVycm9yVHlwZXMuREFUQUJBU0VfRVJST1JcbiAgICB9LCBlcnJvciwgY29udGV4dCkudGhlbigoKSA9PiBbXSkpO1xufTtcblxuZXhwb3J0IGNvbnN0IGdldFVzZXJzQnlSZWFjdGlvbnMgPSAoXG4gIGNvbnRleHQ6IEFwaUNvbnRleHQsXG4gIHtyZWFjdGlvbnMgPSBbXSwgdXNlcm5hbWV9OiBhbnksXG4gIG9wdGlvbnM/OiBVc2VyT3B0aW9uc1xuKTogUHJvbWlzZTxVc2VyW10+ID0+IHtcbiAgY29uc3QgYWN0aW9uOiBzdHJpbmcgPSAnZ2V0VXNlcnNCeVJlYWN0aW9ucyc7XG4gIGNvbnN0IHtkYXRhYmFzZSwgZmllbGRzLCBzZXNzaW9uOiB7dXNlcklkOiBzZXNzaW9uSWR9fSA9IGNvbnRleHQ7XG4gIGNvbnN0IGZvcm1hdFJlYWN0aW9uczogc3RyaW5nW10gPSAgcmVhY3Rpb25zLm1hcCgocmVhY3Rpb25OYW1lOiBzdHJpbmcpID0+IHBhcnNlQ2hhcihyZWFjdGlvbk5hbWUsIDMyKS50b0xvd2VyQ2FzZSgpKTtcbiAgY29uc3Qge2xpbWl0fSA9IHBhcnNlVXNlck9wdGlvbnMob3B0aW9ucyk7XG4gIGNvbnN0IHtvYmplY3RzOiBzZWxlY3RPYmplY3RzLCBxdWVyaWVzOiBzZWxlY3RRdWVyaWVzfSA9IGdldFVzZXJPcHRpb25hbChmaWVsZHMpO1xuXG4gIGNvbnN0IGZvcm1hdFNlc3Npb25JZDogc3RyaW5nID0gYHVzZXJzLyR7c2Vzc2lvbklkfWA7XG4gIGNvbnN0IGZvcm1hdFVzZXJuYW1lOiBzdHJpbmcgPSBwYXJzZVVzZXJuYW1lKHVzZXJuYW1lKTtcbiAgY29uc3QgZmlsdGVyQnk6IHN0cmluZ1tdID0gW2BQT1NJVElPTigke0pTT04uc3RyaW5naWZ5KGZvcm1hdFJlYWN0aW9ucyl9LCBMT1dFUihyLm5hbWUpKWBdO1xuXG4gIGlmKHVzZXJuYW1lKSB7XG4gICAgZmlsdGVyQnkucHVzaChgQ09OVEFJTlModS51c2VybmFtZSwgXCIke2Zvcm1hdFVzZXJuYW1lfVwiKWApO1xuICB9XG5cbiAgLy8gR2V0IGRhdGEgZnJvbSBkYXRhYmFzZVxuICBjb25zdCBhcWxRdWVyeTogc3RyaW5nID0gYEZPUiB1LCByIElOIE9VVEJPVU5EIFwiJHtmb3JtYXRTZXNzaW9uSWR9XCIgaGFzUmVhY3Rpb25cbiAgICBPUFRJT05TIHt2ZXJ0ZXhDb2xsZWN0aW9uczogXCJ1c2Vyc1wifVxuICAgICR7c2VsZWN0UXVlcmllcy5qb2luKCdcXG4nKX1cbiAgICAke2ZpbHRlckJ5Lmxlbmd0aCA/IGBGSUxURVIgJHtmaWx0ZXJCeS5qb2luKCcgJiYgJyl9YCA6ICcnfVxuICAgICR7bGltaXQuYXFsfVxuICAgIFJFVFVSTiBNRVJHRSh1LCB7JHtzZWxlY3RPYmplY3RzLmpvaW4oJywgJyl9fSlgO1xuXG4gIGNvbnNvbGUubG9nKHthcWxRdWVyeX0pO1xuICByZXR1cm4gZGF0YWJhc2UucXVlcnkoYXFsUXVlcnkpXG4gICAgLnRoZW4oKGN1cnNvcjogQXJyYXlDdXJzb3IpID0+IGN1cnNvci5hbGwoKSlcbiAgICAuY2F0Y2goKGVycm9yOiBFcnJvcikgPT4gbG9nRXJyb3Ioe1xuICAgICAgYWN0aW9uLFxuICAgICAgY2F0ZWdvcnk6IGV2ZW50Q2F0ZWdvcnksXG4gICAgICBsYWJlbDogRXJyb3JUeXBlcy5EQVRBQkFTRV9FUlJPUlxuICAgIH0sIGVycm9yLCBjb250ZXh0KS50aGVuKCgpID0+IFtdKSk7XG59O1xuXG5leHBvcnQgY29uc3QgZ2V0VXNlcnNCeVRhZ3MgPSAoXG4gIGNvbnRleHQ6IEFwaUNvbnRleHQsXG4gIHt0YWdzLCB1c2VybmFtZX06IGFueSxcbiAgb3B0aW9ucz86IFVzZXJPcHRpb25zXG4pOiBQcm9taXNlPFVzZXJbXT4gPT4ge1xuICBjb25zdCBhY3Rpb246IHN0cmluZyA9ICdnZXRVc2Vyc0J5VGFncyc7XG4gIGNvbnN0IHtkYXRhYmFzZSwgZmllbGRzLCBzZXNzaW9uOiB7dXNlcklkOiBzZXNzaW9uSWR9fSA9IGNvbnRleHQ7XG4gIGNvbnN0IGZvcm1hdFRhZ3M6IHN0cmluZ1tdID0gIHRhZ3MucmVkdWNlKChsaXN0OiBzdHJpbmdbXSwgdGFnTmFtZTogc3RyaW5nKSA9PiB7XG4gICAgaWYodGFnTmFtZSkge1xuICAgICAgbGlzdC5wdXNoKHBhcnNlQ2hhcih0YWdOYW1lLCAzMikudG9Mb3dlckNhc2UoKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGxpc3Q7XG4gIH0sIFtdKTtcbiAgY29uc3Qge2xpbWl0fSA9IHBhcnNlVXNlck9wdGlvbnMob3B0aW9ucyk7XG4gIGNvbnN0IHtvYmplY3RzOiBzZWxlY3RPYmplY3RzLCBxdWVyaWVzOiBzZWxlY3RRdWVyaWVzfSA9IGdldFVzZXJPcHRpb25hbChmaWVsZHMpO1xuXG4gIGNvbnN0IGZvcm1hdFVzZXJuYW1lOiBzdHJpbmcgPSBwYXJzZVVzZXJuYW1lKHVzZXJuYW1lKTtcbiAgY29uc3QgZmlsdGVyQnk6IHN0cmluZ1tdID0gW2B1Ll9rZXkgIT0gXCIke3Nlc3Npb25JZH1cImBdO1xuXG4gIGlmKHVzZXJuYW1lKSB7XG4gICAgZmlsdGVyQnkucHVzaChgQ09OVEFJTlModS51c2VybmFtZSwgXCIke2Zvcm1hdFVzZXJuYW1lfVwiKWApO1xuICB9XG5cbiAgLy8gR2V0IGRhdGEgZnJvbSBkYXRhYmFzZVxuICBjb25zdCBhcWxRdWVyeTogc3RyaW5nID0gYEZPUiB0IElOIHRhZ3NcbiAgICBGSUxURVIgUE9TSVRJT04oJHtKU09OLnN0cmluZ2lmeShmb3JtYXRUYWdzKX0sIExPV0VSKHQubmFtZSkpXG4gICAgRk9SIHUsIGl0IElOIE9VVEJPVU5EIHQgaXNUYWdnZWRcbiAgICBPUFRJT05TIHtiZnM6IHRydWUsIHVuaXF1ZVZlcnRpY2VzOiBcImdsb2JhbFwiLCB2ZXJ0ZXhDb2xsZWN0aW9uczogXCJ1c2Vyc1wifVxuICAgICR7c2VsZWN0UXVlcmllcy5qb2luKCdcXG4nKX1cbiAgICAke2ZpbHRlckJ5Lmxlbmd0aCA/IGBGSUxURVIgJHtmaWx0ZXJCeS5qb2luKCcgJiYgJyl9YCA6ICcnfVxuICAgICR7bGltaXQuYXFsfVxuICAgIFJFVFVSTiBESVNUSU5DVCBNRVJHRSh1LCB7JHtzZWxlY3RPYmplY3RzLmpvaW4oJywgJyl9fSlgO1xuXG4gIGNvbnNvbGUubG9nKCdnZXRVc2Vyc0J5VGFncycsIGFxbFF1ZXJ5KTtcbiAgcmV0dXJuIGRhdGFiYXNlLnF1ZXJ5KGFxbFF1ZXJ5KVxuICAgIC50aGVuKChjdXJzb3I6IEFycmF5Q3Vyc29yKSA9PiBjdXJzb3IuYWxsKCkpXG4gICAgLmNhdGNoKChlcnJvcjogRXJyb3IpID0+IGxvZ0Vycm9yKHtcbiAgICAgIGFjdGlvbixcbiAgICAgIGNhdGVnb3J5OiBldmVudENhdGVnb3J5LFxuICAgICAgbGFiZWw6IEVycm9yVHlwZXMuREFUQUJBU0VfRVJST1JcbiAgICB9LCBlcnJvciwgY29udGV4dCkudGhlbigoKSA9PiBbXSkpO1xufTtcblxuZXhwb3J0IGNvbnN0IGdldFVzZXJzQnlMYXRlc3QgPSAoY29udGV4dDogQXBpQ29udGV4dCwge3VzZXJuYW1lfSwgb3B0aW9ucz86IFVzZXJPcHRpb25zKTogUHJvbWlzZTxVc2VyW10+ID0+IHtcbiAgY29uc3QgYWN0aW9uOiBzdHJpbmcgPSAnZ2V0VXNlcnNCeUxhdGVzdCc7XG4gIGNvbnN0IHtkYXRhYmFzZSwgZmllbGRzLCBzZXNzaW9uOiB7dXNlcklkfX0gPSBjb250ZXh0O1xuICBjb25zdCB7bGltaXR9ID0gcGFyc2VVc2VyT3B0aW9ucyhvcHRpb25zKTtcbiAgY29uc3QgZmlsdGVyID0gWyd1Ll9pZCAhPSBzZXNzaW9uLl9pZCddO1xuICBjb25zdCB7b2JqZWN0czogc2VsZWN0T2JqZWN0cywgcXVlcmllczogc2VsZWN0UXVlcmllc30gPSBnZXRVc2VyT3B0aW9uYWwoZmllbGRzKTtcblxuICBpZih1c2VybmFtZSkge1xuICAgIGZpbHRlci5wdXNoKGBDT05UQUlOUyh1LnVzZXJuYW1lLCBcIiR7cGFyc2VVc2VybmFtZSh1c2VybmFtZSl9XCIpYCk7XG4gIH1cblxuICAvLyBHZXQgZGF0YSBmcm9tIGRhdGFiYXNlXG4gIGNvbnN0IGFxbFF1ZXJ5OiBzdHJpbmcgPSBgRk9SIHUgSU4gdXNlcnNcbiAgICBMRVQgc2Vzc2lvbiA9IERPQ1VNRU5UKFwidXNlcnMvJHt1c2VySWR9XCIpXG4gICAgRklMVEVSICR7ZmlsdGVyLmpvaW4oJyAmJiAnKX1cbiAgICAke3NlbGVjdFF1ZXJpZXMuam9pbignXFxuJyl9XG4gICAgTEVUIGRpc3RhbmNlID0gRElTVEFOQ0UodS5sYXRpdHVkZSB8fCAwLCB1LmxvbmdpdHVkZSB8fCAwLCBzZXNzaW9uLmxhdGl0dWRlIHx8IDAsIHNlc3Npb24ubG9uZ2l0dWRlIHx8IDApXG4gICAgJHtsaW1pdC5hcWx9XG4gICAgU09SVCBkaXN0YW5jZSBBU0MsIHUuYWRkZWQgREVTQ1xuICAgIFJFVFVSTiBNRVJHRSh1LCB7JHtzZWxlY3RPYmplY3RzLmpvaW4oJywgJyl9fSlgO1xuXG4gIHJldHVybiBkYXRhYmFzZS5xdWVyeShhcWxRdWVyeSlcbiAgICAudGhlbigoY3Vyc29yOiBBcnJheUN1cnNvcikgPT4gY3Vyc29yLmFsbCgpKVxuICAgIC5jYXRjaCgoZXJyb3I6IEVycm9yKSA9PiBsb2dFcnJvcih7XG4gICAgICBhY3Rpb24sXG4gICAgICBjYXRlZ29yeTogZXZlbnRDYXRlZ29yeSxcbiAgICAgIGxhYmVsOiBFcnJvclR5cGVzLkRBVEFCQVNFX0VSUk9SXG4gICAgfSwgZXJyb3IsIGNvbnRleHQpLnRoZW4oKCkgPT4gW10pKTtcbn07XG5cbmV4cG9ydCBjb25zdCByZWZyZXNoU2Vzc2lvbiA9IGFzeW5jIChjb250ZXh0OiBBcGlDb250ZXh0LCB7ZXhwaXJlcywgdG9rZW59KTogUHJvbWlzZTxTZXNzaW9uVG9rZW4gfCBTZXNzaW9uRXJyb3I+ID0+IHtcbiAgY29uc3Qge2Vycm9yfSA9IGdldFNlc3Npb24odG9rZW4pO1xuXG4gIGlmKGVycm9yKSB7XG4gICAgcmV0dXJuIHtlcnJvcnM6IFtlcnJvcl19O1xuICB9XG5cbiAgY29uc3Qge2V4cCwgdXNlcklkLCB1c2VybmFtZSwgdXNlckFjY2Vzc30gPSBnZXRTZXNzaW9uKHRva2VuKTtcbiAgY29uc3Qgbm93OiBudW1iZXIgPSBNYXRoLmNlaWwoRGF0ZVRpbWUubG9jYWwoKS50b1NlY29uZHMoKSk7XG5cbiAgaWYoZXhwID4gbm93KSB7XG4gICAgcmV0dXJuIGNyZWF0ZVRva2VuKHVzZXJJZCwgdXNlcm5hbWUsIHVzZXJBY2Nlc3MsIGV4cGlyZXMpO1xuICB9XG5cbiAgcmV0dXJuIHtlcnJvcnM6IFsnc2Vzc2lvbl9leHBpcmVkJ119O1xufTtcblxuZXhwb3J0IGNvbnN0IHNpZ25JbiA9IGFzeW5jIChjb250ZXh0OiBBcGlDb250ZXh0LCBhcmdzKTogUHJvbWlzZTxTZXNzaW9uVG9rZW4+ID0+IHtcbiAgY29uc3QgYWN0aW9uOiBzdHJpbmcgPSAnc2lnbkluJztcbiAgY29uc3Qge2V4cGlyZXMsIHBhc3N3b3JkLCB1c2VybmFtZX0gPSBhcmdzO1xuICBjb25zdCBmb3JtYXRVc2VybmFtZTogc3RyaW5nID0gcGFyc2VVc2VybmFtZSh1c2VybmFtZSk7XG4gIGNvbnN0IGZvcm1hdFBhc3N3b3JkOiBzdHJpbmcgPSBwYXJzZVBhc3N3b3JkKHBhc3N3b3JkKTtcbiAgY29uc3QgZm9ybWF0RXhwaXJlczogbnVtYmVyID0gcGFyc2VOdW0oZXhwaXJlcykgfHwgMTU7XG4gIGNvbnN0IHtkYXRhYmFzZX0gPSBjb250ZXh0O1xuXG4gIGlmKCFmb3JtYXRVc2VybmFtZSB8fCAhZm9ybWF0UGFzc3dvcmQpIHtcbiAgICByZXR1cm4gbG9nRXhjZXB0aW9uKHtcbiAgICAgIGFjdGlvbixcbiAgICAgIGFyZ3M6IHt1c2VybmFtZX0sXG4gICAgICBjYXRlZ29yeTogZXZlbnRDYXRlZ29yeSxcbiAgICAgIHZhbHVlOiBFcnJvclR5cGVzLklOVkFMSURfQVJHVU1FTlRTXG4gICAgfSwgY29udGV4dCk7XG4gIH1cblxuICBjb25zdCBjaGVja1F1ZXJ5OiBBcWxRdWVyeSA9IGFxbGBGT1IgdSBJTiB1c2Vyc1xuICAgIEZJTFRFUiB1LnVzZXJuYW1lID09ICR7Zm9ybWF0VXNlcm5hbWV9XG4gICAgTElNSVQgMVxuICAgIFJFVFVSTiB1YDtcbiAgY29uc3QgY2hlY2tVc2VyOiBVc2VyID0gYXdhaXQgZGF0YWJhc2UucXVlcnkoY2hlY2tRdWVyeSlcbiAgICAudGhlbigoY3Vyc29yKSA9PiBjdXJzb3IubmV4dCgpKVxuICAgIC5jYXRjaCgoZXJyb3IpID0+IGxvZ0Vycm9yKHtcbiAgICAgIGFjdGlvbixcbiAgICAgIGFyZ3M6IHt1c2VybmFtZTogZm9ybWF0VXNlcm5hbWV9LFxuICAgICAgY2F0ZWdvcnk6IGV2ZW50Q2F0ZWdvcnksXG4gICAgICBsYWJlbDogRXJyb3JUeXBlcy5EQVRBQkFTRV9FUlJPUlxuICAgIH0sIGVycm9yLCBjb250ZXh0KVxuICAgICAgLnRoZW4oKCkgPT4gbnVsbClcbiAgICApO1xuXG4gIGlmKCFjaGVja1VzZXIpIHtcbiAgICByZXR1cm4gbG9nRXhjZXB0aW9uKHtcbiAgICAgIGFjdGlvbixcbiAgICAgIGFyZ3M6IHt1c2VybmFtZX0sXG4gICAgICBjYXRlZ29yeTogZXZlbnRDYXRlZ29yeSxcbiAgICAgIHZhbHVlOiBFcnJvclR5cGVzLklOVkFMSURfQVVUSEVOVElDQVRJT05cbiAgICB9LCBjb250ZXh0KTtcbiAgfVxuXG4gIGNvbnN0IHtfa2V5OiB1c2VySWQsIHNhbHQsIHVzZXJBY2Nlc3N9ID0gY2hlY2tVc2VyO1xuICBjb25zdCBhdXRoUGFzc3dvcmQ6IHN0cmluZyA9IGNyZWF0ZVBhc3N3b3JkKGZvcm1hdFBhc3N3b3JkLCBzYWx0KTtcblxuICBpZihjaGVja1VzZXIucGFzc3dvcmQgIT09IGF1dGhQYXNzd29yZCkge1xuICAgIHJldHVybiBsb2dFeGNlcHRpb24oe1xuICAgICAgYWN0aW9uLFxuICAgICAgYXJnczoge3VzZXJuYW1lfSxcbiAgICAgIGNhdGVnb3J5OiBldmVudENhdGVnb3J5LFxuICAgICAgdmFsdWU6IEVycm9yVHlwZXMuSU5WQUxJRF9BVVRIRU5USUNBVElPTlxuICAgIH0sIGNvbnRleHQpO1xuICB9XG5cbiAgcmV0dXJuIGNyZWF0ZVRva2VuKHVzZXJJZCwgdXNlcm5hbWUsIHVzZXJBY2Nlc3MsIGZvcm1hdEV4cGlyZXMpO1xufTtcblxuZXhwb3J0IGNvbnN0IHNpZ25PdXQgPSBhc3luYyAoY29udGV4dDogQXBpQ29udGV4dCwgYXJncyk6IFByb21pc2U8Ym9vbGVhbj4gPT4ge1xuICBjb25zdCBhY3Rpb246IHN0cmluZyA9ICdzaWduT3V0JztcbiAgY29uc3Qge2RhdGFiYXNlLCBzZXNzaW9uOiB7dXNlcklkOiBzZXNzaW9uSWQsIHVzZXJuYW1lfX0gPSBjb250ZXh0O1xuICBjb25zdCB1c2VyRG9jSWQ6IHN0cmluZyA9IGB1c2Vycy8ke3Nlc3Npb25JZH1gO1xuXG4gIGNvbnN0IHVwZGF0ZSA9IHtcbiAgICBsYXN0T25saW5lOiBEYXRlLm5vdygpLFxuICAgIHNlc3Npb25JZDogbnVsbFxuICB9O1xuICBjb25zdCBzZXNzaW9uUXVlcnk6IEFxbFF1ZXJ5ID0gYXFsYExFVCB1ID0gRE9DVU1FTlQoJHt1c2VyRG9jSWR9KVxuICAgIFVQREFURSB1IFdJVEggJHt1cGRhdGV9IElOIHVzZXJzXG4gICAgTElNSVQgMVxuICAgIFJFVFVSTiBORVdgO1xuXG4gIHRyeSB7XG4gICAgYXdhaXQgZGF0YWJhc2UucXVlcnkoc2Vzc2lvblF1ZXJ5KVxuICAgICAgLnRoZW4oKGN1cnNvcikgPT4gY3Vyc29yLm5leHQoKSlcbiAgICAgIC5jYXRjaCgoZXJyb3IpID0+IGxvZ0Vycm9yKHtcbiAgICAgICAgYWN0aW9uLFxuICAgICAgICBhcmdzOiB7dXNlcm5hbWUsIHVzZXJJZDogc2Vzc2lvbklkfSxcbiAgICAgICAgY2F0ZWdvcnk6IGV2ZW50Q2F0ZWdvcnksXG4gICAgICAgIGxhYmVsOiBFcnJvclR5cGVzLkRBVEFCQVNFX0VSUk9SXG4gICAgICB9LCBlcnJvciwgY29udGV4dClcbiAgICAgICk7XG4gIH0gY2F0Y2goZXJyb3IpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn07XG5cbmV4cG9ydCBjb25zdCBnZXRBY3RpdmVVc2VyQ291bnQgPSAoY29udGV4dDogQXBpQ29udGV4dCkgPT4ge1xuICBjb25zdCBhY3Rpb246IHN0cmluZyA9ICdnZXRBY3RpdmVVc2VyQ291bnQnO1xuICBjb25zdCB7ZGF0YWJhc2V9ID0gY29udGV4dDtcbiAgY29uc3QgY291bnRRdWVyeTogQXFsUXVlcnkgPSBhcWxgTEVUIGRvY3MgPSAoXG4gICAgRk9SIHUgSU4gdXNlcnNcbiAgICBGSUxURVIgdS5hY3RpdmUgPT0gdHJ1ZVxuICAgIFJFVFVSTiB1XG4gIClcbiAgUkVUVVJOIExFTkdUSChkb2NzKWA7XG5cbiAgcmV0dXJuIGRhdGFiYXNlLnF1ZXJ5KGNvdW50UXVlcnkpXG4gICAgLnRoZW4oKGN1cnNvcikgPT4gY3Vyc29yLm5leHQoKSlcbiAgICAuY2F0Y2goKGVycm9yKSA9PiBsb2dFcnJvcih7XG4gICAgICBhY3Rpb24sXG4gICAgICBjYXRlZ29yeTogZXZlbnRDYXRlZ29yeSxcbiAgICAgIGxhYmVsOiBFcnJvclR5cGVzLkRBVEFCQVNFX0VSUk9SXG4gICAgfSwgZXJyb3IsIGNvbnRleHQpXG4gICAgICAudGhlbigoKSA9PiAwKVxuICAgICk7XG59O1xuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBSUEsbUJBVU87QUFDUCxzQkFBa0I7QUFJbEIsbUJBQXVCO0FBQ3ZCLG9CQUFtQjtBQUVuQixvQkFBcUI7QUFHckIsSUFBQUEsZ0JBQXNGO0FBQ3RGLHFCQUFpRTtBQUVqRSxNQUFNLGdCQUF3QjtBQUM5QixNQUFNLGFBQWtCO0FBUWpCLElBQUssYUFBTCxrQkFBS0MsZ0JBQUw7QUFDTCxFQUFBQSx3QkFBQSxpQkFBYyxLQUFkO0FBQ0EsRUFBQUEsd0JBQUEsWUFBUyxLQUFUO0FBQ0EsRUFBQUEsd0JBQUEsYUFBVSxLQUFWO0FBQ0EsRUFBQUEsd0JBQUEsbUJBQWdCLEtBQWhCO0FBQ0EsRUFBQUEsd0JBQUEsV0FBUSxLQUFSO0FBTFUsU0FBQUE7QUFBQSxHQUFBO0FBUUwsTUFBTSxjQUFjLENBQ3pCLFFBQ0EsVUFDQSxZQUNBLFVBQWtCLE9BQ0Q7QUFDakIsUUFBTSxNQUFnQixzQkFBUyxNQUFNO0FBQ3JDLFFBQU0saUJBQTJCLElBQUksS0FBSyxFQUFDLFNBQVMsUUFBTyxDQUFDO0FBQzVELFFBQU0sTUFBYyxLQUFLLE1BQU0sSUFBSSxVQUFVLENBQUM7QUFDOUMsUUFBTSxNQUFjLEtBQUssTUFBTSxlQUFlLFVBQVUsQ0FBQztBQUV6RCxRQUFNLFlBQVEsMkJBQVc7QUFB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
554
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL2FjdGlvbnMvdXNlcnMudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8qKlxuICogQ29weXJpZ2h0IChjKSAyMDE5LVByZXNlbnQsIE5pdHJvZ2VuIExhYnMsIEluYy5cbiAqIENvcHlyaWdodHMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLiBTZWUgdGhlIGFjY29tcGFueWluZyBMSUNFTlNFIGZpbGUgZm9yIHRlcm1zLlxuICovXG5pbXBvcnQge1xuICBjcmVhdGVIYXNoLFxuICBjcmVhdGVQYXNzd29yZCxcbiAgcGFyc2VDaGFyLFxuICBwYXJzZUVtYWlsLFxuICBwYXJzZUlkLFxuICBwYXJzZU51bSxcbiAgcGFyc2VQYXNzd29yZCxcbiAgcGFyc2VQaG9uZSxcbiAgcGFyc2VVc2VybmFtZVxufSBmcm9tICdAbmxhYnMvdXRpbHMnO1xuaW1wb3J0IHthcWx9IGZyb20gJ2FyYW5nb2pzJztcbmltcG9ydCB7QXFsUXVlcnl9IGZyb20gJ2FyYW5nb2pzL2FxbCc7XG5pbXBvcnQge0VkZ2VDb2xsZWN0aW9ufSBmcm9tICdhcmFuZ29qcy9jb2xsZWN0aW9uJztcbmltcG9ydCB7QXJyYXlDdXJzb3J9IGZyb20gJ2FyYW5nb2pzL2N1cnNvcic7XG5pbXBvcnQge0RhdGVUaW1lfSBmcm9tICdsdXhvbic7XG5pbXBvcnQgU3RyaXBlIGZyb20gJ3N0cmlwZSc7XG5cbmltcG9ydCB7Q29uZmlnfSBmcm9tICcuLi9jb25maWcnO1xuaW1wb3J0IHR5cGUge0FwaUNvbnRleHR9IGZyb20gJy4uL3R5cGVzL2F1dGgnO1xuaW1wb3J0IHR5cGUge1VzZXJUeXBlfSBmcm9tICcuLi90eXBlcy91c2Vycyc7XG5pbXBvcnQge2xvZ0Vycm9yLCBsb2dFeGNlcHRpb259IGZyb20gJy4uL3V0aWxzL2FuYWx5dGljc1V0aWxzJztcbmltcG9ydCB7Z2V0RG9jSWQsIGdldExpbWl0LCBzZWxlY3RSZWFjdGlvbkNvdW50QnlUeXBlfSBmcm9tICcuLi91dGlscy9hcmFuZ29kYlV0aWxzJztcbmltcG9ydCB7Z2V0U2Vzc2lvbiwgaXNBZG1pblVzZXIsIFNlc3Npb25Ub2tlbiwgc2V0U2Vzc2lvbn0gZnJvbSAnLi4vdXRpbHMvc2Vzc2lvbic7XG5pbXBvcnQge0Vycm9yVHlwZXMsIFNlc3Npb25FcnJvcn0gZnJvbSAnLi4vdHlwZXMvZXJyb3InO1xuaW1wb3J0IHtwYXJzZVVzZXJ9IGZyb20gJy4uL2FkYXB0ZXJzL3VzZXJBZGFwdGVyJztcblxuY29uc3QgZXZlbnRDYXRlZ29yeTogc3RyaW5nID0gJ3VzZXJzJztcbmNvbnN0IFNUUklQRV9BUElfVkVSU0lPTjogYW55ID0gJzIwMjAtMDMtMDInO1xuXG5leHBvcnQgaW50ZXJmYWNlIFVzZXJPcHRpb25zIHtcbiAgcmVhZG9ubHkgZnJvbT86IG51bWJlcjtcbiAgcmVhZG9ubHkgdG8/OiBudW1iZXI7XG4gIHJlYWRvbmx5IHVzZXJuYW1lPzogc3RyaW5nO1xufVxuXG5leHBvcnQgZW51bSBVc2VyQWNjZXNzIHtcbiAgREVBQ1RJVkFURUQgPSAwLFxuICBBQ1RJVkUgPSAxLFxuICBQUkVNSVVNID0gMixcbiAgQ09OVEVOVF9BRE1JTiA9IDMsXG4gIEFETUlOID0gNFxufVxuXG5leHBvcnQgY29uc3QgY3JlYXRlVG9rZW4gPSAoXG4gIHVzZXJJZDogc3RyaW5nLFxuICB1c2VybmFtZTogc3RyaW5nLFxuICB1c2VyQWNjZXNzOiBudW1iZXIsXG4gIGV4cGlyZXNJbk1pbnV0ZXM6IG51bWJlciA9IDE1XG4pOiBTZXNzaW9uVG9rZW4gPT4ge1xuICBjb25zdCBub3c6IERhdGVUaW1lID0gRGF0ZVRpbWUubG9jYWwoKTtcbiAgY29uc3Qgc2Vzc2lvbkV4cGlyZXM6IERhdGVUaW1lID0gbm93LnBsdXMoe21pbnV0ZXM6IGV4cGlyZXNJbk1pbnV0ZXN9KTtcbiAgY29uc3QgaWF0OiBudW1iZXIgPSBNYXRoLmZsb29yKG5vdy50b1NlY29uZHMoKSk7XG4gIGNvbnN0IGV4cDogbnVtYmVyID0gTWF0aC5mbG9vcihzZXNzaW9uRXhwaXJlcy50b1NlY29uZHMoKSk7XG4gIGNvbnN0IHRva2VuID0gc2V0U2Vzc2lvbih7XG4gICAgZXhwLFxuICAgIGlhdCxcbiAgICB1c2VybmFtZSxcbiAgICB1c2VyQWNjZXNzLFxuICAgIHVzZXJJZFxuICB9KTtcblxuICByZXR1cm4ge1xuICAgIGV4cGlyZXM6IHNlc3Npb25FeHBpcmVzLnRvTWlsbGlzKCksXG4gICAgaXNzdWVkOiBub3cudG9NaWxsaXMoKSxcbiAgICB0b2tlblxuICB9O1xufTtcblxuZXhwb3J0IGNvbnN0IGdldFVzZXJPcHRpb25hbCA9IChmaWVsZHM6IHN0cmluZ1tdID0gW10pID0+XG4gIGZpZWxkcy5yZWR1Y2UoKHNlbGVjdHM6IGFueSwgZmllbGQ6IHN0cmluZykgPT4ge1xuICAgIGlmKGZpZWxkLmluY2x1ZGVzKCdDb3VudCcpKSB7XG4gICAgICByZXR1cm4gc2VsZWN0UmVhY3Rpb25Db3VudEJ5VHlwZSgndXNlcnMnLCAndScsIGZpZWxkLCBzZWxlY3RzKTtcbiAgICB9XG5cbiAgICByZXR1cm4gc2VsZWN0cztcbiAgfSwge29iamVjdHM6IFtdLCBxdWVyaWVzOiBbXX0pO1xuXG5leHBvcnQgY29uc3QgcGFyc2VVc2VyT3B0aW9ucyA9IChvcHRpb25zOiBVc2VyT3B0aW9ucyA9IHt9KSA9PiB7XG4gIGNvbnN0IHtcbiAgICBmcm9tID0gMCxcbiAgICB0byA9IDMwXG4gIH0gPSBvcHRpb25zO1xuICBjb25zdCBsaW1pdCA9IGdldExpbWl0KGZyb20sIHRvKTtcblxuICByZXR1cm4ge1xuICAgIC4uLm9wdGlvbnMsXG4gICAgbGltaXRcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBhZGRVc2VyID0gYXN5bmMgKGNvbnRleHQ6IEFwaUNvbnRleHQsIHVzZXI6IFVzZXJUeXBlKTogUHJvbWlzZTxVc2VyVHlwZT4gPT4ge1xuICBjb25zdCBhY3Rpb24gPSAnYWRkVXNlcic7XG4gIGNvbnN0IHtkYXRhYmFzZX0gPSBjb250ZXh0O1xuICBjb25zdCB7ZW1haWwsIHBhc3N3b3JkLCBwaG9uZSwgdXNlcm5hbWV9ID0gcGFyc2VVc2VyKHVzZXIpO1xuICBjb25zdCBzYWx0OiBzdHJpbmcgPSBjcmVhdGVIYXNoKGAke3VzZXJuYW1lfSR7cGFzc3dvcmR9YCwgbnVsbCk7XG4gIGNvbnN0IGVuY3J5cHRlZFBhc3N3b3JkID0gY3JlYXRlUGFzc3dvcmQocGFzc3dvcmQsIHNhbHQpO1xuICBjb25zdCBmb3JtYXRVc2VybmFtZTogc3RyaW5nID0gcGFyc2VVc2VybmFtZSh1c2VybmFtZSk7XG4gIGNvbnN0IGZvcm1hdEVtYWlsOiBzdHJpbmcgPSBwYXJzZUVtYWlsKGVtYWlsKTtcbiAgY29uc3QgZm9ybWF0UGhvbmU6IHN0cmluZyA9IHBhcnNlUGhvbmUocGhvbmUpO1xuXG4gIGlmKCFmb3JtYXRVc2VybmFtZSB8fCAhcGFzc3dvcmQgfHwgKCFmb3JtYXRQaG9uZSAmJiAhZm9ybWF0RW1haWwpKSB7XG4gICAgcmV0dXJuIGxvZ0V4Y2VwdGlvbih7XG4gICAgICBhY3Rpb24sXG4gICAgICBjYXRlZ29yeTogZXZlbnRDYXRlZ29yeSxcbiAgICAgIHBhcmFtczoge3VzZXJuYW1lfSxcbiAgICAgIHZhbHVlOiBFcnJvclR5cGVzLklOVkFMSURfQVJHVU1FTlRTXG4gICAgfSwgY29udGV4dCk7XG4gIH1cblxuICBjb25zdCBmaWx0ZXJzOiBzdHJpbmdbXSA9IFtgdS51c2VybmFtZSA9PSBcIiR7Zm9ybWF0VXNlcm5hbWV9XCJgXTtcblxuICBpZihmb3JtYXRFbWFpbCkge1xuICAgIGZpbHRlcnMucHVzaChgdS5lbWFpbCA9PSBcIiR7Zm9ybWF0RW1haWx9XCJgKTtcbiAgfVxuXG4gIGlmKGZvcm1hdFBob25lKSB7XG4gICAgZmlsdGVycy5wdXNoKGB1LnBob25lID09ICR7Zm9ybWF0UGhvbmV9YCk7XG4gIH1cblxuICBjb25zdCBjaGVja1F1ZXJ5OiBzdHJpbmcgPSBgRk9SIHUgSU4gdXNlcnNcbiAgICBGSUxURVIgJHtmaWx0ZXJzLmpvaW4oJyB8fCAnKX1cbiAgICBMSU1JVCAxXG4gICAgUkVUVVJOIHVgO1xuXG4gIHRyeSB7XG4gICAgY29uc3QgZXhpc3RpbmdVc2VycyA9IGF3YWl0IGRhdGFiYXNlLnF1ZXJ5KGNoZWNrUXVlcnkpLnRoZW4oKGN1cnNvcjogQXJyYXlDdXJzb3IpID0+IGN1cnNvci5hbGwoKSk7XG5cbiAgICBpZihleGlzdGluZ1VzZXJzLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGxvZ0V4Y2VwdGlvbih7XG4gICAgICAgIGFjdGlvbixcbiAgICAgICAgY2F0ZWdvcnk6IGV2ZW50Q2F0ZWdvcnksXG4gICAgICAgIHBhcmFtczoge3VzZXJuYW1lfSxcbiAgICAgICAgdmFsdWU6IEVycm9yVHlwZXMuRVhJU1RJTkdfSVRFTVxuICAgICAgfSwgY29udGV4dCk7XG4gICAgfVxuICB9IGNhdGNoKGVycm9yKSB7XG4gICAgcmV0dXJuIGxvZ0Vycm9yKHtcbiAgICAgIGFjdGlvbixcbiAgICAgIGNhdGVnb3J5OiBldmVudENhdGVnb3J5LFxuICAgICAgcGFyYW1zOiB7dXNlcm5hbWV9LFxuICAgICAgdmFsdWU6IEVycm9yVHlwZXMuREFUQUJBU0VfRVJST1JcbiAgICB9LCBlcnJvciwgY29udGV4dCk7XG4gIH1cblxuICBjb25zdCB2ZXJpZmllZEVtYWlsQ29kZTogbnVtYmVyID0gTWF0aC5mbG9vcigxMDAwMDAgKyAoTWF0aC5yYW5kb20oKSAqIDkwMDAwMCkpO1xuICBjb25zdCB2ZXJpZmllZFBob25lQ29kZTogbnVtYmVyID0gTWF0aC5mbG9vcigxMDAwMDAgKyAoTWF0aC5yYW5kb20oKSAqIDkwMDAwMCkpO1xuXG4gIGNvbnN0IGluc2VydDogVXNlclR5cGUgPSB7XG4gICAgX2tleTogY3JlYXRlSGFzaCh1c2VybmFtZSwgbnVsbCksXG4gICAgYWRkZWQ6IERhdGUubm93KCksXG4gICAgZW1haWw6IGZvcm1hdEVtYWlsLFxuICAgIG1vZGlmaWVkOiBEYXRlLm5vdygpLFxuICAgIHBhc3N3b3JkOiBlbmNyeXB0ZWRQYXNzd29yZCxcbiAgICBwaG9uZTogZm9ybWF0UGhvbmUsXG4gICAgc2FsdCxcbiAgICB1c2VybmFtZTogZm9ybWF0VXNlcm5hbWUsXG4gICAgdXNlckFjY2VzczogMSxcbiAgICB2ZXJpZmllZEVtYWlsOiBmYWxzZSxcbiAgICB2ZXJpZmllZEVtYWlsQ29kZSxcbiAgICB2ZXJpZmllZFBob25lOiBmYWxzZSxcbiAgICB2ZXJpZmllZFBob25lQ29kZVxuICB9O1xuXG4gIGNvbnN0IGluc2VydFF1ZXJ5OiBBcWxRdWVyeSA9IGFxbGBJTlNFUlQgJHtpbnNlcnR9IElOIHVzZXJzIFJFVFVSTiBORVdgO1xuXG4gIHJldHVybiBhd2FpdCBkYXRhYmFzZS5xdWVyeShpbnNlcnRRdWVyeSlcbiAgICAudGhlbigoY3Vyc29yOiBBcnJheUN1cnNvcikgPT4gY3Vyc29yLm5leHQoKSlcbiAgICAuY2F0Y2goKGVycm9yKSA9PiBsb2dFcnJvcih7XG4gICAgICBhY3Rpb24sXG4gICAgICBjYXRlZ29yeTogZXZlbnRDYXRlZ29yeSxcbiAgICAgIHBhcmFtczoge3VzZXJuYW1lfSxcbiAgICAgIHZhbHVlOiBFcnJvclR5cGVzLkRBVEFCQVNFX0VSUk9SXG4gICAgfSwgZXJyb3IsIGNvbnRleHQpKTtcbn07XG5cbmV4cG9ydCBjb25zdCB1cGRhdGVVc2VyID0gYXN5bmMgKGNvbnRleHQ6IEFwaUNvbnRleHQsIHVzZXI6IFVzZXJUeXBlKTogUHJvbWlzZTxVc2VyVHlwZT4gPT4ge1xuICBjb25zdCBhY3Rpb24gPSAndXBkYXRlVXNlcic7XG4gIGNvbnN0IHtkYXRhYmFzZSwgc2Vzc2lvbn0gPSBjb250ZXh0O1xuICBjb25zdCB7X2tleSwgX2lkLCBpZCwgdGFncyA9IFtdLCB1c2VySWQsIC4uLnVwZGF0ZWR9ID0gcGFyc2VVc2VyKHVzZXIpO1xuXG4gIGlmKCFpc0FkbWluVXNlcihzZXNzaW9uKSAmJiAoc2Vzc2lvbj8udXNlcklkICE9PSB1c2VySWQpKSB7XG4gICAgcmV0dXJuIGxvZ0V4Y2VwdGlvbih7XG4gICAgICBhY3Rpb24sXG4gICAgICBjYXRlZ29yeTogZXZlbnRDYXRlZ29yeSxcbiAgICAgIHBhcmFtczoge3Nlc3Npb259LFxuICAgICAgdmFsdWU6IEVycm9yVHlwZXMuSU5WQUxJRF9TRVNTSU9OXG4gICAgfSwgY29udGV4dCk7XG4gIH1cblxuICBjb25zdCB1c2VyUXVlcnk6IEFxbFF1ZXJ5ID0gYXFsYExFVCB1ID0gRE9DVU1FTlQoJHtpZH0pXG4gICAgVVBEQVRFIHUgV0lUSCAke3VwZGF0ZWR9IElOIHVzZXJzXG4gICAgUkVUVVJOIE5FV2A7XG5cbiAgdHJ5IHtcbiAgICBjb25zdCB1cGRhdGVkVXNlciA9IGF3YWl0IGRhdGFiYXNlLnF1ZXJ5KHVzZXJRdWVyeSkudGhlbigoY3Vyc29yKSA9PiBjdXJzb3IubmV4dCgpKTtcbiAgICBjb25zdCB0YWdDb2xsZWN0aW9uOiBFZGdlQ29sbGVjdGlvbiA9IGRhdGFiYXNlLmNvbGxlY3Rpb24oJ2lzVGFnZ2VkJyk7XG5cbiAgICBhd2FpdCBQcm9taXNlLmFsbCh0YWdzLm1hcCgoe2lkOiB0YWdEb2NJZCwgbmFtZX0pID0+IHtcbiAgICAgIGNvbnN0IHRhZ1F1ZXJ5OiBBcWxRdWVyeSA9IGFxbGBGT1IgaXQgSU4gaXNUYWdnZWRcbiAgICAgICAgRklMVEVSIGl0Ll9mcm9tID09ICR7dGFnRG9jSWR9ICYmIGl0Ll90byA9PSAke2lkfSAmJiBpdC5uYW1lID09ICR7bmFtZX1cbiAgICAgICAgTElNSVQgMVxuICAgICAgICBSRVRVUk4gaXRgO1xuXG4gICAgICByZXR1cm4gZGF0YWJhc2UucXVlcnkodGFnUXVlcnkpXG4gICAgICAgIC50aGVuKChjdXJzb3I6IEFycmF5Q3Vyc29yKSA9PiBjdXJzb3IubmV4dCgpKVxuICAgICAgICAudGhlbigodGFnRWRnZSkgPT4ge1xuICAgICAgICAgIGlmKCEhdGFnRWRnZSkge1xuICAgICAgICAgICAgcmV0dXJuIHRhZ0VkZ2U7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgZWRnZSA9IHtcbiAgICAgICAgICAgIF9mcm9tOiB0YWdEb2NJZCxcbiAgICAgICAgICAgIF9rZXk6IGNyZWF0ZUhhc2goYGlzVGFnZ2VkLSR7dGFnRG9jSWR9LSR7aWR9YCksXG4gICAgICAgICAgICBfdG86IGlkLFxuICAgICAgICAgICAgYWRkZWQ6IERhdGUubm93KCksXG4gICAgICAgICAgICBuYW1lXG4gICAgICAgICAgfTtcblxuICAgICAgICAgIHJldHVybiB0YWdDb2xsZWN0aW9uLnNhdmUoZWRnZSwge3JldHVybk5ldzogdHJ1ZX0pLnRoZW4oKCkgPT4gZWRnZSk7XG4gICAgICAgIH0pO1xuICAgIH0pKTtcblxuICAgIHJldHVybiB1cGRhdGVkVXNlcjtcbiAgfSBjYXRjaChlcnJvcikge1xuICAgIHJldHVybiBsb2dFcnJvcih7XG4gICAgICBhY3Rpb24sXG4gICAgICBjYXRlZ29yeTogZXZlbnRDYXRlZ29yeSxcbiAgICAgIHBhcmFtczoge3VzZXJ9LFxuICAgICAgdmFsdWU6IEVycm9yVHlwZXMuREFUQUJBU0VfRVJST1JcbiAgICB9LCBlcnJvciwgY29udGV4dCk7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBjb25maXJtQ29kZSA9IGFzeW5jIChjb250ZXh0OiBBcGlDb250ZXh0LCB7Y29kZSwgdHlwZX0pOiBQcm9taXNlPGJvb2xlYW4+ID0+IHtcbiAgY29uc3Qge2RhdGFiYXNlLCBzZXNzaW9uOiB7dXNlcklkOiBzZXNzaW9uSWR9fSA9IGNvbnRleHQ7XG4gIGNvbnN0IHVzZXJEb2NJZCA9IGdldERvY0lkKCd1c2VycycsIHt1c2VySWQ6IHNlc3Npb25JZH0pO1xuICBjb25zdCBhcWxRdWVyeTogQXFsUXVlcnkgPSBhcWxgTEVUIHUgPSBET0NVTUVOVCgke3VzZXJEb2NJZH0pIFJFVFVSTiB1YDtcblxuICB0cnkge1xuICAgIHJldHVybiBhd2FpdCBkYXRhYmFzZS5xdWVyeShhcWxRdWVyeSlcbiAgICAgIC50aGVuKChjdXJzb3IpID0+IGN1cnNvci5uZXh0KCkpXG4gICAgICAudGhlbigoe3ZlcmlmaWVkRW1haWxDb2RlLCB2ZXJpZmllZFBob25lQ29kZX06IFVzZXJUeXBlKSA9PiB7XG4gICAgICAgIHN3aXRjaCh0eXBlKSB7XG4gICAgICAgICAgY2FzZSAnZW1haWwnOlxuICAgICAgICAgICAgcmV0dXJuIGNvZGUgPT09IHZlcmlmaWVkRW1haWxDb2RlO1xuICAgICAgICAgIGNhc2UgJ3Bob25lJzpcbiAgICAgICAgICAgIHJldHVybiBjb2RlID09PSB2ZXJpZmllZFBob25lQ29kZTtcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgfSBjYXRjaChlcnJvcikge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IGRlbGV0ZVVzZXIgPSAoY29udGV4dDogQXBpQ29udGV4dCwgdXNlcjogVXNlclR5cGUpOiBQcm9taXNlPGFueT4gPT4ge1xuICBjb25zdCBhY3Rpb24gPSAnZGVsZXRlVXNlcic7XG4gIGNvbnN0IHtkYXRhYmFzZX0gPSBjb250ZXh0O1xuICBjb25zdCB7dXNlcklkfSA9IHBhcnNlVXNlcih1c2VyKTtcblxuICBjb25zdCBhcWxRdWVyeTogQXFsUXVlcnkgPSBhcWxgRk9SIHUgSU4gdXNlcnNcbiAgICBGSUxURVIgdS5fa2V5ID09ICR7dXNlcklkfVxuICAgIExJTUlUIDFcbiAgICBSRU1PVkUgdSBJTiB1c2Vyc1xuICAgIFJFVFVSTiBPTERgO1xuXG4gIGNvbnN0IHN0cmlwZUNsaWVudCA9IG5ldyBTdHJpcGUoQ29uZmlnLmdldCgnc3RyaXBlLnRva2VuJyksIHthcGlWZXJzaW9uOiBTVFJJUEVfQVBJX1ZFUlNJT04sIHR5cGVzY3JpcHQ6IHRydWV9KTtcblxuICByZXR1cm4gZGF0YWJhc2UucXVlcnkoYXFsUXVlcnkpXG4gICAgLnRoZW4oKGN1cnNvcjogQXJyYXlDdXJzb3IpID0+IGN1cnNvci5uZXh0KCkpXG4gICAgLnRoZW4oKGRlbGV0ZWRVc2VyKSA9PiBzdHJpcGVDbGllbnQuY3VzdG9tZXJzLmRlbChkZWxldGVkVXNlcj8uc3RyaXBlQ3VzdG9tZXJJZClcbiAgICAgIC50aGVuKCgpID0+IHN0cmlwZUNsaWVudC5hY2NvdW50cy5kZWwoZGVsZXRlZFVzZXI/LnN0cmlwZUFjY291bnRJZCkpXG4gICAgICAudGhlbigoKSA9PiBkZWxldGVkVXNlcikpXG4gICAgLmNhdGNoKChlcnJvcjogRXJyb3IpID0+IGxvZ0Vycm9yKHtcbiAgICAgIGFjdGlvbixcbiAgICAgIGNhdGVnb3J5OiBldmVudENhdGVnb3J5LFxuICAgICAgcGFyYW1zOiB7dXNlcklkfSxcbiAgICAgIHZhbHVlOiBFcnJvclR5cGVzLkRBVEFCQVNFX0VSUk9SXG4gICAgfSwgZXJyb3IsY29udGV4dCkpO1xufTtcblxuZXhwb3J0IGNvbnN0IGRlYWN0aXZhdGVVc2VyID0gKGNvbnRleHQ6IEFwaUNvbnRleHQsIHVzZXI6IFVzZXJUeXBlKTogUHJvbWlzZTxVc2VyVHlwZT4gPT4ge1xuICBjb25zdCBhY3Rpb24gPSAnZGVsZXRlJztcbiAgY29uc3Qge2RhdGFiYXNlfSA9IGNvbnRleHQ7XG4gIGNvbnN0IHt1c2VySWR9ID0gcGFyc2VVc2VyKHVzZXIpO1xuICBjb25zdCB1cGRhdGVkOiBVc2VyVHlwZSA9IHtcbiAgICB1c2VyQWNjZXNzOiAwXG4gIH07XG4gIGNvbnN0IGFxbFF1ZXJ5OiBBcWxRdWVyeSA9IGFxbGBVUERBVEUgJHt1c2VySWR9IFdJVEggJHt1cGRhdGVkfSBJTiB1c2VycyBMSU1JVCAxIFJFVFVSTiBORVdgO1xuXG4gIHJldHVybiBkYXRhYmFzZS5xdWVyeShhcWxRdWVyeSlcbiAgICAudGhlbigoY3Vyc29yOiBBcnJheUN1cnNvcikgPT4gY3Vyc29yLm5leHQoKSlcbiAgICAuY2F0Y2goKGVycm9yOiBFcnJvcikgPT4gbG9nRXJyb3Ioe1xuICAgICAgYWN0aW9uLFxuICAgICAgY2F0ZWdvcnk6IGV2ZW50Q2F0ZWdvcnksXG4gICAgICBwYXJhbXM6IHt1c2VySWR9LFxuICAgICAgdmFsdWU6IEVycm9yVHlwZXMuREFUQUJBU0VfRVJST1JcbiAgICB9LCBlcnJvcixjb250ZXh0KSk7XG59O1xuXG5leHBvcnQgY29uc3QgZ2V0RGlzcGxheU5hbWUgPSAodXNlcjogVXNlclR5cGUpOiBzdHJpbmcgPT4ge1xuICBjb25zdCB7Zmlyc3QsIGxhc3QsIG5hbWUgPSAnJywgdXNlcm5hbWUgPSAnJ30gPSB1c2VyO1xuICBjb25zdCBmdWxsbmFtZSA9IChbZmlyc3QsIGxhc3RdKS5qb2luKCcgJykudHJpbSgpO1xuXG4gIGlmKG5hbWUpIHtcbiAgICByZXR1cm4gbmFtZTtcbiAgfSBlbHNlIGlmKGZ1bGxuYW1lICE9PSAnJykge1xuICAgIHJldHVybiBmdWxsbmFtZTtcbiAgfSBlbHNlIGlmKHVzZXJuYW1lKSB7XG4gICAgcmV0dXJuIHVzZXJuYW1lO1xuICB9XG5cbiAgcmV0dXJuICdVbmtub3duJztcbn07XG5cbmV4cG9ydCBjb25zdCBnZXRTZXNzaW9uVXNlciA9IChjb250ZXh0OiBBcGlDb250ZXh0KTogUHJvbWlzZTxVc2VyVHlwZT4gPT4ge1xuICBjb25zdCBhY3Rpb24gPSAnZ2V0U2Vzc2lvblVzZXInO1xuICBjb25zdCB7ZGF0YWJhc2UsIGZpZWxkcywgc2Vzc2lvbjoge3VzZXJJZDogc2Vzc2lvbklkLCB1c2VybmFtZX19ID0gY29udGV4dDtcbiAgY29uc3Qge29iamVjdHM6IHNlbGVjdE9iamVjdHMsIHF1ZXJpZXM6IHNlbGVjdFF1ZXJpZXN9ID0gZ2V0VXNlck9wdGlvbmFsKGZpZWxkcyk7XG5cbiAgY29uc3QgYXFsUXVlcnk6IHN0cmluZyA9IGBMRVQgdSA9IERPQ1VNRU5UKFwidXNlcnMvJHtzZXNzaW9uSWR9XCIpXG4gICR7c2VsZWN0UXVlcmllcy5qb2luKCdcXG4nKX1cbiAgUkVUVVJOIE1FUkdFKHUsIHske3NlbGVjdE9iamVjdHMuam9pbignLCAnKX19KWA7XG5cbiAgcmV0dXJuIGRhdGFiYXNlLnF1ZXJ5KGFxbFF1ZXJ5KVxuICAgIC50aGVuKChjdXJzb3I6IEFycmF5Q3Vyc29yKSA9PiBjdXJzb3IubmV4dCgpKVxuICAgIC5jYXRjaCgoZXJyb3I6IEVycm9yKSA9PiBsb2dFcnJvcih7XG4gICAgICBhY3Rpb24sXG4gICAgICBjYXRlZ29yeTogZXZlbnRDYXRlZ29yeSxcbiAgICAgIHBhcmFtczoge3VzZXJuYW1lLCB1c2VySWQ6IHNlc3Npb25JZH0sXG4gICAgICB2YWx1ZTogRXJyb3JUeXBlcy5EQVRBQkFTRV9FUlJPUlxuICAgIH0sIGVycm9yLCBjb250ZXh0KSk7XG59O1xuXG5leHBvcnQgY29uc3QgZ2V0VXNlciA9IChjb250ZXh0OiBBcGlDb250ZXh0LCB1c2VyOiBVc2VyVHlwZSk6IFByb21pc2U8VXNlclR5cGU+ID0+IHtcbiAgY29uc3QgYWN0aW9uID0gJ2dldFVzZXInO1xuICBjb25zdCB7dXNlcklkfSA9IHBhcnNlVXNlcih1c2VyKTtcbiAgY29uc3Qge2RhdGFiYXNlLCBmaWVsZHN9ID0gY29udGV4dDtcbiAgY29uc3Qge29iamVjdHM6IHNlbGVjdE9iamVjdHMsIHF1ZXJpZXM6IHNlbGVjdFF1ZXJpZXN9ID0gZ2V0VXNlck9wdGlvbmFsKGZpZWxkcyk7XG5cbiAgY29uc3QgYXFsUXVlcnk6IHN0cmluZyA9IGBMRVQgdSA9IERPQ1VNRU5UKFwidXNlcnMvJHt1c2VySWR9XCIpXG4gICAgJHtzZWxlY3RRdWVyaWVzLmpvaW4oJ1xcbicpfVxuICAgIEZJTFRFUiB1LnVzZXJBY2Nlc3MgPiAwXG4gICAgUkVUVVJOIE1FUkdFKHUsIHske3NlbGVjdE9iamVjdHMuam9pbignLCAnKX19KWA7XG5cbiAgcmV0dXJuIGRhdGFiYXNlLnF1ZXJ5KGFxbFF1ZXJ5KVxuICAgIC50aGVuKChjdXJzb3I6IEFycmF5Q3Vyc29yKSA9PiBjdXJzb3IubmV4dCgpKVxuICAgIC50aGVuKCh1c2VyKSA9PiB1c2VyKVxuICAgIC5jYXRjaCgoZXJyb3I6IEVycm9yKSA9PiBsb2dFcnJvcih7XG4gICAgICBhY3Rpb24sXG4gICAgICBjYXRlZ29yeTogZXZlbnRDYXRlZ29yeSxcbiAgICAgIHBhcmFtczoge3VzZXJJZH0sXG4gICAgICB2YWx1ZTogRXJyb3JUeXBlcy5EQVRBQkFTRV9FUlJPUlxuICAgIH0sIGVycm9yLCBjb250ZXh0KSk7XG59O1xuXG5leHBvcnQgY29uc3QgZ2V0VXNlcnMgPSAoY29udGV4dDogQXBpQ29udGV4dCwgb3B0aW9ucz86IFVzZXJPcHRpb25zKTogUHJvbWlzZTxVc2VyVHlwZVtdPiA9PiB7XG4gIGNvbnN0IGFjdGlvbiA9ICdnZXRVc2VyTGlzdCc7XG4gIGNvbnN0IHtkYXRhYmFzZSwgZmllbGRzfSA9IGNvbnRleHQ7XG4gIGNvbnN0IHtsaW1pdCwgdXNlcm5hbWV9ID0gcGFyc2VVc2VyT3B0aW9ucyhvcHRpb25zKTtcbiAgY29uc3Qge29iamVjdHM6IHNlbGVjdE9iamVjdHMsIHF1ZXJpZXM6IHNlbGVjdFF1ZXJpZXN9ID0gZ2V0VXNlck9wdGlvbmFsKGZpZWxkcyk7XG4gIGNvbnN0IGZpbHRlckJ5OiBzdHJpbmdbXSA9IFsndS51c2VyQWNjZXNzID4gMCddO1xuXG4gIGlmKHVzZXJuYW1lKSB7XG4gICAgZmlsdGVyQnkucHVzaChgQ09OVEFJTlModS51c2VybmFtZSwgXCIke3BhcnNlVXNlcm5hbWUodXNlcm5hbWUpfVwiKWApO1xuICB9XG5cbiAgY29uc3QgYXFsUXVlcnk6IHN0cmluZyA9IGBGT1IgdSBJTiB1c2Vyc1xuICAgIEZJTFRFUiAke2ZpbHRlckJ5LmpvaW4oJyAmJiAnKX1cbiAgICAke3NlbGVjdFF1ZXJpZXMuam9pbignXFxuJyl9XG4gICAgJHtsaW1pdC5hcWx9XG4gICAgU09SVCB1LnVzZXJuYW1lXG4gICAgUkVUVVJOIE1FUkdFKHUsIHske3NlbGVjdE9iamVjdHMuam9pbignLCAnKX19KWA7XG5cbiAgcmV0dXJuIGRhdGFiYXNlLnF1ZXJ5KGFxbFF1ZXJ5KVxuICAgIC50aGVuKChjdXJzb3I6IEFycmF5Q3Vyc29yKSA9PiBjdXJzb3IuYWxsKCkpXG4gICAgLmNhdGNoKChlcnJvcjogRXJyb3IpID0+IGxvZ0Vycm9yKHtcbiAgICAgIGFjdGlvbixcbiAgICAgIGNhdGVnb3J5OiBldmVudENhdGVnb3J5LFxuICAgICAgdmFsdWU6IEVycm9yVHlwZXMuREFUQUJBU0VfRVJST1JcbiAgICB9LCBlcnJvciwgY29udGV4dCkpO1xufTtcblxuZXhwb3J0IGNvbnN0IGdldFVzZXJzQnlSZWFjdGlvbnMgPSAoXG4gIGNvbnRleHQ6IEFwaUNvbnRleHQsXG4gIHtyZWFjdGlvbnMgPSBbXSwgdXNlcm5hbWV9OiBhbnksXG4gIG9wdGlvbnM/OiBVc2VyT3B0aW9uc1xuKTogUHJvbWlzZTxVc2VyVHlwZVtdPiA9PiB7XG4gIGNvbnN0IGFjdGlvbiA9ICdnZXRVc2Vyc0J5UmVhY3Rpb25zJztcbiAgY29uc3Qge2RhdGFiYXNlLCBmaWVsZHMsIHNlc3Npb246IHt1c2VySWQ6IHNlc3Npb25JZH19ID0gY29udGV4dDtcbiAgY29uc3QgZm9ybWF0UmVhY3Rpb25zOiBzdHJpbmdbXSA9ICByZWFjdGlvbnMubWFwKChyZWFjdGlvbk5hbWU6IHN0cmluZykgPT4gcGFyc2VDaGFyKHJlYWN0aW9uTmFtZSwgMzIpLnRvTG93ZXJDYXNlKCkpO1xuICBjb25zdCB7bGltaXR9ID0gcGFyc2VVc2VyT3B0aW9ucyhvcHRpb25zKTtcbiAgY29uc3Qge29iamVjdHM6IHNlbGVjdE9iamVjdHMsIHF1ZXJpZXM6IHNlbGVjdFF1ZXJpZXN9ID0gZ2V0VXNlck9wdGlvbmFsKGZpZWxkcyk7XG4gIGNvbnN0IGZvcm1hdFNlc3Npb25JZDogc3RyaW5nID0gYHVzZXJzLyR7c2Vzc2lvbklkfWA7XG4gIGNvbnN0IGZvcm1hdFVzZXJuYW1lOiBzdHJpbmcgPSBwYXJzZVVzZXJuYW1lKHVzZXJuYW1lKTtcbiAgY29uc3QgZmlsdGVyQnk6IHN0cmluZ1tdID0gW2BQT1NJVElPTigke0pTT04uc3RyaW5naWZ5KGZvcm1hdFJlYWN0aW9ucyl9LCBMT1dFUihyLm5hbWUpKWBdO1xuXG4gIGlmKHVzZXJuYW1lKSB7XG4gICAgZmlsdGVyQnkucHVzaChgQ09OVEFJTlModS51c2VybmFtZSwgXCIke2Zvcm1hdFVzZXJuYW1lfVwiKWApO1xuICB9XG5cbiAgY29uc3QgYXFsUXVlcnk6IHN0cmluZyA9IGBGT1IgdSwgciBJTiBPVVRCT1VORCBcIiR7Zm9ybWF0U2Vzc2lvbklkfVwiIGhhc1JlYWN0aW9uXG4gICAgT1BUSU9OUyB7dmVydGV4Q29sbGVjdGlvbnM6IFwidXNlcnNcIn1cbiAgICAke3NlbGVjdFF1ZXJpZXMuam9pbignXFxuJyl9XG4gICAgRklMVEVSICR7ZmlsdGVyQnkuam9pbignICYmICcpfVxuICAgICR7bGltaXQuYXFsfVxuICAgIFJFVFVSTiBNRVJHRSh1LCB7JHtzZWxlY3RPYmplY3RzLmpvaW4oJywgJyl9fSlgO1xuXG4gIHJldHVybiBkYXRhYmFzZS5xdWVyeShhcWxRdWVyeSlcbiAgICAudGhlbigoY3Vyc29yOiBBcnJheUN1cnNvcikgPT4gY3Vyc29yLmFsbCgpKVxuICAgIC5jYXRjaCgoZXJyb3I6IEVycm9yKSA9PiBsb2dFcnJvcih7XG4gICAgICBhY3Rpb24sXG4gICAgICBjYXRlZ29yeTogZXZlbnRDYXRlZ29yeSxcbiAgICAgIHZhbHVlOiBFcnJvclR5cGVzLkRBVEFCQVNFX0VSUk9SXG4gICAgfSwgZXJyb3IsIGNvbnRleHQpKTtcbn07XG5cbmV4cG9ydCBjb25zdCBnZXRVc2Vyc0J5VGFncyA9IChcbiAgY29udGV4dDogQXBpQ29udGV4dCxcbiAge3RhZ3MsIHVzZXJuYW1lfTogYW55LFxuICBvcHRpb25zPzogVXNlck9wdGlvbnNcbik6IFByb21pc2U8VXNlclR5cGVbXT4gPT4ge1xuICBjb25zdCBhY3Rpb24gPSAnZ2V0VXNlcnNCeVRhZ3MnO1xuICBjb25zdCB7ZGF0YWJhc2UsIGZpZWxkcywgc2Vzc2lvbjoge3VzZXJJZDogc2Vzc2lvbklkfX0gPSBjb250ZXh0O1xuICBjb25zdCBmb3JtYXRUYWdzOiBzdHJpbmdbXSA9ICB0YWdzPy5yZWR1Y2UoKGxpc3Q6IHN0cmluZ1tdLCB0YWdOYW1lOiBzdHJpbmcpID0+IHtcbiAgICBpZih0YWdOYW1lKSB7XG4gICAgICBsaXN0LnB1c2gocGFyc2VDaGFyKHRhZ05hbWUsIDMyKS50b0xvd2VyQ2FzZSgpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbGlzdDtcbiAgfSwgW10pO1xuICBjb25zdCB7bGltaXR9ID0gcGFyc2VVc2VyT3B0aW9ucyhvcHRpb25zKTtcbiAgY29uc3Qge29iamVjdHM6IHNlbGVjdE9iamVjdHMsIHF1ZXJpZXM6IHNlbGVjdFF1ZXJpZXN9ID0gZ2V0VXNlck9wdGlvbmFsKGZpZWxkcyk7XG4gIGNvbnN0IGZvcm1hdFVzZXJuYW1lOiBzdHJpbmcgPSBwYXJzZVVzZXJuYW1lKHVzZXJuYW1lKTtcbiAgY29uc3QgZmlsdGVyQnk6IHN0cmluZ1tdID0gW2B1Ll9rZXkgIT0gXCIke3Nlc3Npb25JZH1cImBdO1xuXG4gIGlmKHVzZXJuYW1lKSB7XG4gICAgZmlsdGVyQnkucHVzaChgQ09OVEFJTlModS51c2VybmFtZSwgXCIke2Zvcm1hdFVzZXJuYW1lfVwiKWApO1xuICB9XG5cbiAgY29uc3QgYXFsUXVlcnk6IHN0cmluZyA9IGBGT1IgdCBJTiB0YWdzXG4gICAgRklMVEVSIFBPU0lUSU9OKCR7SlNPTi5zdHJpbmdpZnkoZm9ybWF0VGFncyl9LCBMT1dFUih0Lm5hbWUpKVxuICAgIEZPUiB1LCBpdCBJTiBPVVRCT1VORCB0IGlzVGFnZ2VkXG4gICAgT1BUSU9OUyB7YmZzOiB0cnVlLCB1bmlxdWVWZXJ0aWNlczogXCJnbG9iYWxcIiwgdmVydGV4Q29sbGVjdGlvbnM6IFwidXNlcnNcIn1cbiAgICAke3NlbGVjdFF1ZXJpZXMuam9pbignXFxuJyl9XG4gICAgRklMVEVSICR7ZmlsdGVyQnkuam9pbignICYmICcpfVxuICAgICR7bGltaXQuYXFsfVxuICAgIFJFVFVSTiBESVNUSU5DVCBNRVJHRSh1LCB7JHtzZWxlY3RPYmplY3RzLmpvaW4oJywgJyl9fSlgO1xuXG4gIHJldHVybiBkYXRhYmFzZS5xdWVyeShhcWxRdWVyeSlcbiAgICAudGhlbigoY3Vyc29yOiBBcnJheUN1cnNvcikgPT4gY3Vyc29yLmFsbCgpKVxuICAgIC5jYXRjaCgoZXJyb3I6IEVycm9yKSA9PiBsb2dFcnJvcih7XG4gICAgICBhY3Rpb24sXG4gICAgICBjYXRlZ29yeTogZXZlbnRDYXRlZ29yeSxcbiAgICAgIHZhbHVlOiBFcnJvclR5cGVzLkRBVEFCQVNFX0VSUk9SXG4gICAgfSwgZXJyb3IsIGNvbnRleHQpKTtcbn07XG5cbmV4cG9ydCBjb25zdCBnZXRVc2Vyc0J5TGF0ZXN0ID0gKGNvbnRleHQ6IEFwaUNvbnRleHQsIHt1c2VybmFtZX06IGFueSwgb3B0aW9ucz86IFVzZXJPcHRpb25zKTogUHJvbWlzZTxVc2VyVHlwZVtdPiA9PiB7XG4gIGNvbnN0IGFjdGlvbiA9ICdnZXRVc2Vyc0J5TGF0ZXN0JztcbiAgY29uc3Qge2RhdGFiYXNlLCBmaWVsZHMsIHNlc3Npb246IHt1c2VySWR9fSA9IGNvbnRleHQ7XG4gIGNvbnN0IHtsaW1pdH0gPSBwYXJzZVVzZXJPcHRpb25zKG9wdGlvbnMpO1xuICBjb25zdCBmaWx0ZXIgPSBbJ3UuX2lkICE9IHNlc3Npb24uX2lkJ107XG4gIGNvbnN0IHtvYmplY3RzOiBzZWxlY3RPYmplY3RzLCBxdWVyaWVzOiBzZWxlY3RRdWVyaWVzfSA9IGdldFVzZXJPcHRpb25hbChmaWVsZHMpO1xuXG4gIGlmKHVzZXJuYW1lKSB7XG4gICAgZmlsdGVyLnB1c2goYENPTlRBSU5TKHUudXNlcm5hbWUsIFwiJHtwYXJzZVVzZXJuYW1lKHVzZXJuYW1lKX1cIilgKTtcbiAgfVxuXG4gIC8vIEdldCBkYXRhIGZyb20gZGF0YWJhc2VcbiAgY29uc3QgYXFsUXVlcnk6IHN0cmluZyA9IGBGT1IgdSBJTiB1c2Vyc1xuICAgIExFVCBzZXNzaW9uID0gRE9DVU1FTlQoXCJ1c2Vycy8ke3VzZXJJZH1cIilcbiAgICBGSUxURVIgJHtmaWx0ZXIuam9pbignICYmICcpfVxuICAgICR7c2VsZWN0UXVlcmllcy5qb2luKCdcXG4nKX1cbiAgICBMRVQgZGlzdGFuY2UgPSBESVNUQU5DRSh1LmxhdGl0dWRlIHx8IDAsIHUubG9uZ2l0dWRlIHx8IDAsIHNlc3Npb24ubGF0aXR1ZGUgfHwgMCwgc2Vzc2lvbi5sb25naXR1ZGUgfHwgMClcbiAgICAke2xpbWl0LmFxbH1cbiAgICBTT1JUIGRpc3RhbmNlIEFTQywgdS5hZGRlZCBERVNDXG4gICAgUkVUVVJOIE1FUkdFKHUsIHske3NlbGVjdE9iamVjdHMuam9pbignLCAnKX19KWA7XG5cbiAgcmV0dXJuIGRhdGFiYXNlLnF1ZXJ5KGFxbFF1ZXJ5KVxuICAgIC50aGVuKChjdXJzb3I6IEFycmF5Q3Vyc29yKSA9PiBjdXJzb3IuYWxsKCkpXG4gICAgLmNhdGNoKChlcnJvcjogRXJyb3IpID0+IGxvZ0Vycm9yKHtcbiAgICAgIGFjdGlvbixcbiAgICAgIGNhdGVnb3J5OiBldmVudENhdGVnb3J5LFxuICAgICAgdmFsdWU6IEVycm9yVHlwZXMuREFUQUJBU0VfRVJST1JcbiAgICB9LCBlcnJvciwgY29udGV4dCkpO1xufTtcblxuZXhwb3J0IGNvbnN0IHJlZnJlc2hTZXNzaW9uID0gYXN5bmMgKGNvbnRleHQ6IEFwaUNvbnRleHQsIHtleHBpcmVzLCB0b2tlbn0pOiBQcm9taXNlPFNlc3Npb25Ub2tlbiB8IFNlc3Npb25FcnJvcj4gPT4ge1xuICBjb25zdCB7dXNlcklkLCB1c2VybmFtZSwgdXNlckFjY2Vzc30gPSBnZXRTZXNzaW9uKHRva2VuKTtcblxuICByZXR1cm4gY3JlYXRlVG9rZW4odXNlcklkLCB1c2VybmFtZSwgdXNlckFjY2VzcywgZXhwaXJlcyk7XG59O1xuXG5leHBvcnQgY29uc3Qgc2lnbkluID0gYXN5bmMgKGNvbnRleHQ6IEFwaUNvbnRleHQsIGFyZ3MpOiBQcm9taXNlPFNlc3Npb25Ub2tlbj4gPT4ge1xuICBjb25zdCBhY3Rpb24gPSAnc2lnbkluJztcbiAgY29uc3Qge2RhdGFiYXNlfSA9IGNvbnRleHQ7XG4gIGNvbnN0IHtlbWFpbCwgZXhwaXJlcywgcGFzc3dvcmQsIHVzZXJuYW1lfSA9IGFyZ3M7XG4gIGNvbnN0IGZvcm1hdEVtYWlsOiBzdHJpbmcgPSBwYXJzZUVtYWlsKGVtYWlsKTtcbiAgY29uc3QgZm9ybWF0VXNlcm5hbWU6IHN0cmluZyA9IHBhcnNlVXNlcm5hbWUodXNlcm5hbWUpO1xuICBjb25zdCBmb3JtYXRQYXNzd29yZDogc3RyaW5nID0gcGFyc2VQYXNzd29yZChwYXNzd29yZCk7XG4gIGNvbnN0IGZvcm1hdEV4cGlyZXM6IG51bWJlciA9IHBhcnNlTnVtKGV4cGlyZXMpIHx8IDE1O1xuXG4gIGlmKCghZm9ybWF0VXNlcm5hbWUgJiYgIWZvcm1hdEVtYWlsKSB8fCAhZm9ybWF0UGFzc3dvcmQpIHtcbiAgICByZXR1cm4gbG9nRXhjZXB0aW9uKHtcbiAgICAgIGFjdGlvbixcbiAgICAgIGNhdGVnb3J5OiBldmVudENhdGVnb3J5LFxuICAgICAgcGFyYW1zOiB7dXNlcm5hbWV9LFxuICAgICAgdmFsdWU6IEVycm9yVHlwZXMuSU5WQUxJRF9BUkdVTUVOVFNcbiAgICB9LCBjb250ZXh0KTtcbiAgfVxuXG4gIGNvbnN0IGZpbHRlcnM6IHN0cmluZ1tdID0gW107XG5cbiAgaWYoZm9ybWF0RW1haWwpIHtcbiAgICBmaWx0ZXJzLnB1c2goYHUuZW1haWwgPT0gXCIke2Zvcm1hdEVtYWlsfVwiYCk7XG4gIH0gZWxzZSBpZihmb3JtYXRVc2VybmFtZSkge1xuICAgIGZpbHRlcnMucHVzaChgdS51c2VybmFtZSA9PSBcIiR7Zm9ybWF0VXNlcm5hbWV9XCJgKTtcbiAgfVxuXG4gIGNvbnN0IGNoZWNrUXVlcnk6IHN0cmluZyA9IGBGT1IgdSBJTiB1c2Vyc1xuICAgIEZJTFRFUiAke2ZpbHRlcnMuam9pbignIHx8ICcpfVxuICAgIExJTUlUIDFcbiAgICBSRVRVUk4gdWA7XG5cbiAgbGV0IGNoZWNrVXNlcjogVXNlclR5cGU7XG5cbiAgdHJ5IHtcbiAgICBjaGVja1VzZXIgPSBhd2FpdCBkYXRhYmFzZS5xdWVyeShjaGVja1F1ZXJ5KS50aGVuKChjdXJzb3IpID0+IGN1cnNvci5uZXh0KCkpO1xuICB9IGNhdGNoKGVycm9yKSB7XG4gICAgcmV0dXJuIGxvZ0Vycm9yKHtcbiAgICAgIGFjdGlvbixcbiAgICAgIGNhdGVnb3J5OiBldmVudENhdGVnb3J5LFxuICAgICAgcGFyYW1zOiB7dXNlcm5hbWU6IGZvcm1hdFVzZXJuYW1lfSxcbiAgICAgIHZhbHVlOiBFcnJvclR5cGVzLkRBVEFCQVNFX0VSUk9SXG4gICAgfSwgZXJyb3IsIGNvbnRleHQpO1xuICB9XG5cbiAgaWYoIWNoZWNrVXNlcikge1xuICAgIHJldHVybiBsb2dFeGNlcHRpb24oe1xuICAgICAgYWN0aW9uLFxuICAgICAgY2F0ZWdvcnk6IGV2ZW50Q2F0ZWdvcnksXG4gICAgICBwYXJhbXM6IHt1c2VybmFtZX0sXG4gICAgICB2YWx1ZTogRXJyb3JUeXBlcy5JTlZBTElEX0FVVEhFTlRJQ0FUSU9OXG4gICAgfSwgY29udGV4dCk7XG4gIH1cblxuICBjb25zdCB7X2tleTogdXNlcklkLCBwYXNzd29yZDogdmFsaWRQYXNzd29yZCwgc2FsdCwgdXNlckFjY2Vzc30gPSBjaGVja1VzZXI7XG4gIGNvbnN0IGF1dGhQYXNzd29yZDogc3RyaW5nID0gY3JlYXRlUGFzc3dvcmQoZm9ybWF0UGFzc3dvcmQsIHNhbHQpO1xuXG4gIGlmKHZhbGlkUGFzc3dvcmQgIT09IGF1dGhQYXNzd29yZCkge1xuICAgIHJldHVybiBsb2dFeGNlcHRpb24oe1xuICAgICAgYWN0aW9uLFxuICAgICAgY2F0ZWdvcnk6IGV2ZW50Q2F0ZWdvcnksXG4gICAgICBwYXJhbXM6IHt1c2VyQWNjZXNzLCB1c2VySWQsIHVzZXJuYW1lfSxcbiAgICAgIHZhbHVlOiBFcnJvclR5cGVzLklOVkFMSURfQVVUSEVOVElDQVRJT05cbiAgICB9LCBjb250ZXh0KTtcbiAgfVxuXG4gIHJldHVybiBjcmVhdGVUb2tlbih1c2VySWQsIHVzZXJuYW1lLCB1c2VyQWNjZXNzLCBmb3JtYXRFeHBpcmVzKTtcbn07XG5cbmV4cG9ydCBjb25zdCBzaWduT3V0ID0gYXN5bmMgKGNvbnRleHQ6IEFwaUNvbnRleHQpOiBQcm9taXNlPGJvb2xlYW4+ID0+IHtcbiAgY29uc3QgYWN0aW9uID0gJ3NpZ25PdXQnO1xuICBjb25zdCB7ZGF0YWJhc2UsIHNlc3Npb246IHt1c2VySWQ6IHNlc3Npb25JZCwgdXNlcm5hbWV9fSA9IGNvbnRleHQ7XG4gIGNvbnN0IHVzZXJEb2NJZDogc3RyaW5nID0gYHVzZXJzLyR7c2Vzc2lvbklkfWA7XG5cbiAgY29uc3QgdXBkYXRlID0ge1xuICAgIGxhc3RPbmxpbmU6IERhdGUubm93KCksXG4gICAgc2Vzc2lvbklkOiBudWxsXG4gIH07XG4gIGNvbnN0IHNlc3Npb25RdWVyeTogQXFsUXVlcnkgPSBhcWxgTEVUIHUgPSBET0NVTUVOVCgke3VzZXJEb2NJZH0pXG4gICAgVVBEQVRFIHUgV0lUSCAke3VwZGF0ZX0gSU4gdXNlcnNcbiAgICBMSU1JVCAxXG4gICAgUkVUVVJOIE5FV2A7XG5cbiAgdHJ5IHtcbiAgICBhd2FpdCBkYXRhYmFzZS5xdWVyeShzZXNzaW9uUXVlcnkpLnRoZW4oKGN1cnNvcikgPT4gY3Vyc29yLm5leHQoKSk7XG4gIH0gY2F0Y2goZXJyb3IpIHtcbiAgICBhd2FpdCBsb2dFcnJvcih7XG4gICAgICBhY3Rpb24sXG4gICAgICBjYXRlZ29yeTogZXZlbnRDYXRlZ29yeSxcbiAgICAgIHBhcmFtczoge3VzZXJuYW1lLCB1c2VySWQ6IHNlc3Npb25JZH0sXG4gICAgICB2YWx1ZTogRXJyb3JUeXBlcy5EQVRBQkFTRV9FUlJPUlxuICAgIH0sIGVycm9yLCBjb250ZXh0KTtcbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufTtcblxuZXhwb3J0IGNvbnN0IGdldEFjdGl2ZVVzZXJDb3VudCA9IChjb250ZXh0OiBBcGlDb250ZXh0KSA9PiB7XG4gIGNvbnN0IGFjdGlvbiA9ICdnZXRBY3RpdmVVc2VyQ291bnQnO1xuICBjb25zdCB7ZGF0YWJhc2V9ID0gY29udGV4dDtcbiAgY29uc3QgY291bnRRdWVyeTogQXFsUXVlcnkgPSBhcWxgTEVUIGRvY3MgPSAoXG4gICAgRk9SIHUgSU4gdXNlcnNcbiAgICBGSUxURVIgdS5hY3RpdmUgPT0gdHJ1ZVxuICAgIFJFVFVSTiB1XG4gIClcbiAgUkVUVVJOIExFTkdUSChkb2NzKWA7XG5cbiAgcmV0dXJuIGRhdGFiYXNlLnF1ZXJ5KGNvdW50UXVlcnkpXG4gICAgLnRoZW4oKGN1cnNvcikgPT4gY3Vyc29yLm5leHQoKSlcbiAgICAuY2F0Y2goKGVycm9yKSA9PiBsb2dFcnJvcih7XG4gICAgICBhY3Rpb24sXG4gICAgICBjYXRlZ29yeTogZXZlbnRDYXRlZ29yeSxcbiAgICAgIHZhbHVlOiBFcnJvclR5cGVzLkRBVEFCQVNFX0VSUk9SXG4gICAgfSwgZXJyb3IsIGNvbnRleHQpKTtcbn07XG5cbmV4cG9ydCBjb25zdCBnZXRVc2VyQnlUb2tlbiA9IChjb250ZXh0OiBBcGlDb250ZXh0LCB0b2tlbjogc3RyaW5nKTogUHJvbWlzZTxVc2VyVHlwZT4gPT4ge1xuICBjb25zdCBhY3Rpb24gPSAnZ2V0VXNlckJ5VG9rZW4nO1xuICBjb25zdCB7ZGF0YWJhc2V9ID0gY29udGV4dDtcbiAgY29uc3Qge3VzZXJJZH0gPSBnZXRTZXNzaW9uKHRva2VuKTtcbiAgY29uc3QgdXNlckRvY0lkID0gZ2V0RG9jSWQoJ3VzZXJzJywge3VzZXJJZH0pO1xuICBjb25zdCBhcWxRdWVyeTogQXFsUXVlcnkgPSBhcWxgTEVUIHUgPSBET0NVTUVOVChcIiR7dXNlckRvY0lkfVwiKSBSRVRVUk4gdWA7XG5cbiAgcmV0dXJuIGRhdGFiYXNlLnF1ZXJ5KGFxbFF1ZXJ5KVxuICAgIC50aGVuKChjdXJzb3I6IEFycmF5Q3Vyc29yKSA9PiBjdXJzb3IubmV4dCgpKVxuICAgIC5jYXRjaCgoZXJyb3I6IEVycm9yKSA9PiBsb2dFcnJvcih7XG4gICAgICBhY3Rpb24sXG4gICAgICBjYXRlZ29yeTogZXZlbnRDYXRlZ29yeSxcbiAgICAgIHBhcmFtczoge3VzZXJJZH0sXG4gICAgICB2YWx1ZTogRXJyb3JUeXBlcy5EQVRBQkFTRV9FUlJPUlxuICAgIH0sIGVycm9yLCBjb250ZXh0KSk7XG59O1xuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFBQTtB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QUFBQSxJQUNwQixHQUFHLE9BQU87QUFBQSxFQUNaO0FBRUEsU0FBTyxZQUFZLFFBQVEsVUFBVSxZQUFZLGFBQWE7QUFDaEU7QUFFTyxNQUFNLFVBQVUsT0FBTyxZQUEwQztBQUN0RSxRQUFNLFNBQVM7QUFDZixRQUFNLEVBQUMsVUFBVSxTQUFTLEVBQUMsUUFBUSxXQUFXLFNBQVEsRUFBQyxJQUFJO0FBQzNELFFBQU0sWUFBb0IsU0FBUyxTQUFTO0FBRTVDLFFBQU0sU0FBUztBQUFBLElBQ2IsWUFBWSxLQUFLLElBQUk7QUFBQSxJQUNyQixXQUFXO0FBQUEsRUFDYjtBQUNBLFFBQU0sZUFBeUIsdUNBQXVCLFNBQVM7QUFBQSxvQkFDN0MsTUFBTTtBQUFBO0FBQUE7QUFJeEIsTUFBSTtBQUNGLFVBQU0sU0FBUyxNQUFNLFlBQVksRUFBRSxLQUFLLENBQUMsV0FBVyxPQUFPLEtBQUssQ0FBQztBQUFBLEVBQ25FLFNBQVEsT0FBTztBQUNiLGNBQU0sZ0NBQVM7QUFBQSxNQUNiO0FBQUEsTUFDQSxVQUFVO0FBQUEsTUFDVixRQUFRLEVBQUMsVUFBVSxRQUFRLFVBQVM7QUFBQSxNQUNwQyxPQUFPLHdCQUFXO0FBQUEsSUFDcEIsR0FBRyxPQUFPLE9BQU87QUFBQSxFQUNuQjtBQUVBLFNBQU87QUFDVDtBQUVPLE1BQU0scUJBQXFCLENBQUMsWUFBd0I7QUFDekQsUUFBTSxTQUFTO0FBQ2YsUUFBTSxFQUFDLFNBQVEsSUFBSTtBQUNuQixRQUFNLGFBQXVCO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQU83QixTQUFPLFNBQVMsTUFBTSxVQUFVLEVBQzdCLEtBQUssQ0FBQyxXQUFXLE9BQU8sS0FBSyxDQUFDLEVBQzlCLE1BQU0sQ0FBQyxjQUFVLGdDQUFTO0FBQUEsSUFDekI7QUFBQSxJQUNBLFVBQVU7QUFBQSxJQUNWLE9BQU8sd0JBQVc7QUFBQSxFQUNwQixHQUFHLE9BQU8sT0FBTyxDQUFDO0FBQ3RCO0FBRU8sTUFBTSxpQkFBaUIsQ0FBQyxTQUFxQixVQUFxQztBQUN2RixRQUFNLFNBQVM7QUFDZixRQUFNLEVBQUMsU0FBUSxJQUFJO0FBQ25CLFFBQU0sRUFBQyxPQUFNLFFBQUksMkJBQVcsS0FBSztBQUNqQyxRQUFNLGdCQUFZLCtCQUFTLFNBQVMsRUFBQyxPQUFNLENBQUM7QUFDNUMsUUFBTSxXQUFxQix3Q0FBd0IsU0FBUztBQUU1RCxTQUFPLFNBQVMsTUFBTSxRQUFRLEVBQzNCLEtBQUssQ0FBQyxXQUF3QixPQUFPLEtBQUssQ0FBQyxFQUMzQyxNQUFNLENBQUMsY0FBaUIsZ0NBQVM7QUFBQSxJQUNoQztBQUFBLElBQ0EsVUFBVTtBQUFBLElBQ1YsUUFBUSxFQUFDLE9BQU07QUFBQSxJQUNmLE9BQU8sd0JBQVc7QUFBQSxFQUNwQixHQUFHLE9BQU8sT0FBTyxDQUFDO0FBQ3RCOyIsCiAgIm5hbWVzIjogWyJVc2VyQWNjZXNzIiwgIlN0cmlwZSIsICJ1c2VyIl0KfQo=