@beiguancyc/parse-server 9.9.0-ruixiang.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (251) hide show
  1. package/LICENSE +176 -0
  2. package/NOTICE +10 -0
  3. package/README.md +1311 -0
  4. package/bin/parse-live-query-server +3 -0
  5. package/bin/parse-server +3 -0
  6. package/lib/AccountLockout.js +149 -0
  7. package/lib/Adapters/AdapterLoader.js +60 -0
  8. package/lib/Adapters/Analytics/AnalyticsAdapter.js +32 -0
  9. package/lib/Adapters/Auth/AuthAdapter.js +132 -0
  10. package/lib/Adapters/Auth/BaseCodeAuthAdapter.js +119 -0
  11. package/lib/Adapters/Auth/OAuth1Client.js +204 -0
  12. package/lib/Adapters/Auth/apple.js +125 -0
  13. package/lib/Adapters/Auth/facebook.js +187 -0
  14. package/lib/Adapters/Auth/gcenter.js +217 -0
  15. package/lib/Adapters/Auth/github.js +125 -0
  16. package/lib/Adapters/Auth/google.js +122 -0
  17. package/lib/Adapters/Auth/gpgames.js +125 -0
  18. package/lib/Adapters/Auth/httpsRequest.js +41 -0
  19. package/lib/Adapters/Auth/index.js +248 -0
  20. package/lib/Adapters/Auth/instagram.js +118 -0
  21. package/lib/Adapters/Auth/janraincapture.js +85 -0
  22. package/lib/Adapters/Auth/janrainengage.js +57 -0
  23. package/lib/Adapters/Auth/keycloak.js +168 -0
  24. package/lib/Adapters/Auth/ldap.js +193 -0
  25. package/lib/Adapters/Auth/line.js +125 -0
  26. package/lib/Adapters/Auth/linkedin.js +117 -0
  27. package/lib/Adapters/Auth/meetup.js +44 -0
  28. package/lib/Adapters/Auth/mfa.js +334 -0
  29. package/lib/Adapters/Auth/microsoft.js +111 -0
  30. package/lib/Adapters/Auth/oauth2.js +115 -0
  31. package/lib/Adapters/Auth/phantauth.js +53 -0
  32. package/lib/Adapters/Auth/qq.js +113 -0
  33. package/lib/Adapters/Auth/spotify.js +115 -0
  34. package/lib/Adapters/Auth/twitter.js +197 -0
  35. package/lib/Adapters/Auth/utils.js +28 -0
  36. package/lib/Adapters/Auth/vkontakte.js +55 -0
  37. package/lib/Adapters/Auth/wechat.js +110 -0
  38. package/lib/Adapters/Auth/weibo.js +141 -0
  39. package/lib/Adapters/Cache/CacheAdapter.js +40 -0
  40. package/lib/Adapters/Cache/InMemoryCache.js +61 -0
  41. package/lib/Adapters/Cache/InMemoryCacheAdapter.js +34 -0
  42. package/lib/Adapters/Cache/LRUCache.js +35 -0
  43. package/lib/Adapters/Cache/NullCacheAdapter.js +26 -0
  44. package/lib/Adapters/Cache/RedisCacheAdapter.js +109 -0
  45. package/lib/Adapters/Cache/SchemaCache.js +25 -0
  46. package/lib/Adapters/Email/MailAdapter.js +32 -0
  47. package/lib/Adapters/Files/FilesAdapter.js +129 -0
  48. package/lib/Adapters/Files/GridFSBucketAdapter.js +280 -0
  49. package/lib/Adapters/Files/GridStoreAdapter.js +5 -0
  50. package/lib/Adapters/Logger/LoggerAdapter.js +27 -0
  51. package/lib/Adapters/Logger/WinstonLogger.js +107 -0
  52. package/lib/Adapters/Logger/WinstonLoggerAdapter.js +63 -0
  53. package/lib/Adapters/MessageQueue/EventEmitterMQ.js +55 -0
  54. package/lib/Adapters/PubSub/EventEmitterPubSub.js +53 -0
  55. package/lib/Adapters/PubSub/PubSubAdapter.js +34 -0
  56. package/lib/Adapters/PubSub/RedisPubSub.js +49 -0
  57. package/lib/Adapters/Push/PushAdapter.js +40 -0
  58. package/lib/Adapters/Storage/Mongo/MongoCollection.js +212 -0
  59. package/lib/Adapters/Storage/Mongo/MongoSchemaCollection.js +334 -0
  60. package/lib/Adapters/Storage/Mongo/MongoStorageAdapter.js +1047 -0
  61. package/lib/Adapters/Storage/Mongo/MongoTransform.js +1397 -0
  62. package/lib/Adapters/Storage/Postgres/PostgresClient.js +38 -0
  63. package/lib/Adapters/Storage/Postgres/PostgresConfigParser.js +73 -0
  64. package/lib/Adapters/Storage/Postgres/PostgresStorageAdapter.js +2409 -0
  65. package/lib/Adapters/Storage/Postgres/sql/array/add-unique.sql +11 -0
  66. package/lib/Adapters/Storage/Postgres/sql/array/add.sql +11 -0
  67. package/lib/Adapters/Storage/Postgres/sql/array/contains-all-regex.sql +14 -0
  68. package/lib/Adapters/Storage/Postgres/sql/array/contains-all.sql +14 -0
  69. package/lib/Adapters/Storage/Postgres/sql/array/contains.sql +11 -0
  70. package/lib/Adapters/Storage/Postgres/sql/array/remove.sql +11 -0
  71. package/lib/Adapters/Storage/Postgres/sql/index.js +32 -0
  72. package/lib/Adapters/Storage/Postgres/sql/misc/json-object-set-keys.sql +19 -0
  73. package/lib/Adapters/Storage/StorageAdapter.js +2 -0
  74. package/lib/Adapters/WebSocketServer/WSAdapter.js +35 -0
  75. package/lib/Adapters/WebSocketServer/WSSAdapter.js +66 -0
  76. package/lib/Auth.js +687 -0
  77. package/lib/AuthDataLock.js +53 -0
  78. package/lib/ClientSDK.js +39 -0
  79. package/lib/Config.js +879 -0
  80. package/lib/Controllers/AdaptableController.js +72 -0
  81. package/lib/Controllers/AnalyticsController.js +43 -0
  82. package/lib/Controllers/CacheController.js +71 -0
  83. package/lib/Controllers/DatabaseController.js +1685 -0
  84. package/lib/Controllers/FilesController.js +122 -0
  85. package/lib/Controllers/HooksController.js +254 -0
  86. package/lib/Controllers/LiveQueryController.js +72 -0
  87. package/lib/Controllers/LoggerController.js +222 -0
  88. package/lib/Controllers/ParseGraphQLController.js +294 -0
  89. package/lib/Controllers/PushController.js +224 -0
  90. package/lib/Controllers/SchemaController.js +1563 -0
  91. package/lib/Controllers/UserController.js +364 -0
  92. package/lib/Controllers/index.js +251 -0
  93. package/lib/Controllers/types.js +2 -0
  94. package/lib/Deprecator/Deprecations.js +100 -0
  95. package/lib/Deprecator/Deprecator.js +140 -0
  96. package/lib/Error.js +50 -0
  97. package/lib/FileUrlValidator.js +69 -0
  98. package/lib/GraphQL/ParseGraphQLSchema.js +375 -0
  99. package/lib/GraphQL/ParseGraphQLServer.js +241 -0
  100. package/lib/GraphQL/helpers/objectsMutations.js +30 -0
  101. package/lib/GraphQL/helpers/objectsQueries.js +246 -0
  102. package/lib/GraphQL/helpers/queryComplexity.js +138 -0
  103. package/lib/GraphQL/loaders/configMutations.js +87 -0
  104. package/lib/GraphQL/loaders/configQueries.js +79 -0
  105. package/lib/GraphQL/loaders/defaultGraphQLMutations.js +21 -0
  106. package/lib/GraphQL/loaders/defaultGraphQLQueries.js +23 -0
  107. package/lib/GraphQL/loaders/defaultGraphQLTypes.js +1099 -0
  108. package/lib/GraphQL/loaders/defaultRelaySchema.js +53 -0
  109. package/lib/GraphQL/loaders/filesMutations.js +107 -0
  110. package/lib/GraphQL/loaders/functionsMutations.js +77 -0
  111. package/lib/GraphQL/loaders/parseClassMutations.js +267 -0
  112. package/lib/GraphQL/loaders/parseClassQueries.js +126 -0
  113. package/lib/GraphQL/loaders/parseClassTypes.js +493 -0
  114. package/lib/GraphQL/loaders/schemaDirectives.js +62 -0
  115. package/lib/GraphQL/loaders/schemaMutations.js +161 -0
  116. package/lib/GraphQL/loaders/schemaQueries.js +80 -0
  117. package/lib/GraphQL/loaders/schemaTypes.js +341 -0
  118. package/lib/GraphQL/loaders/usersMutations.js +433 -0
  119. package/lib/GraphQL/loaders/usersQueries.js +90 -0
  120. package/lib/GraphQL/parseGraphQLUtils.js +71 -0
  121. package/lib/GraphQL/transformers/className.js +14 -0
  122. package/lib/GraphQL/transformers/constraintType.js +53 -0
  123. package/lib/GraphQL/transformers/inputType.js +51 -0
  124. package/lib/GraphQL/transformers/mutation.js +280 -0
  125. package/lib/GraphQL/transformers/outputType.js +51 -0
  126. package/lib/GraphQL/transformers/query.js +237 -0
  127. package/lib/GraphQL/transformers/schemaFields.js +99 -0
  128. package/lib/InstallationDedup.js +178 -0
  129. package/lib/KeyPromiseQueue.js +48 -0
  130. package/lib/LiveQuery/Client.js +90 -0
  131. package/lib/LiveQuery/Id.js +20 -0
  132. package/lib/LiveQuery/ParseCloudCodePublisher.js +54 -0
  133. package/lib/LiveQuery/ParseLiveQueryServer.js +1071 -0
  134. package/lib/LiveQuery/ParsePubSub.js +37 -0
  135. package/lib/LiveQuery/ParseWebSocketServer.js +66 -0
  136. package/lib/LiveQuery/QueryTools.js +443 -0
  137. package/lib/LiveQuery/RequestSchema.js +161 -0
  138. package/lib/LiveQuery/SessionTokenCache.js +51 -0
  139. package/lib/LiveQuery/Subscription.js +47 -0
  140. package/lib/LiveQuery/equalObjects.js +50 -0
  141. package/lib/Options/Definitions.js +1599 -0
  142. package/lib/Options/docs.js +389 -0
  143. package/lib/Options/index.js +12 -0
  144. package/lib/Options/parsers.js +89 -0
  145. package/lib/Page.js +44 -0
  146. package/lib/ParseMessageQueue.js +24 -0
  147. package/lib/ParseServer.js +632 -0
  148. package/lib/ParseServerRESTController.js +173 -0
  149. package/lib/PromiseRouter.js +208 -0
  150. package/lib/Push/PushQueue.js +67 -0
  151. package/lib/Push/PushWorker.js +101 -0
  152. package/lib/Push/utils.js +129 -0
  153. package/lib/RestQuery.js +1208 -0
  154. package/lib/RestWrite.js +1671 -0
  155. package/lib/Routers/AggregateRouter.js +150 -0
  156. package/lib/Routers/AnalyticsRouter.js +26 -0
  157. package/lib/Routers/AudiencesRouter.js +54 -0
  158. package/lib/Routers/ClassesRouter.js +191 -0
  159. package/lib/Routers/CloudCodeRouter.js +87 -0
  160. package/lib/Routers/FeaturesRouter.js +72 -0
  161. package/lib/Routers/FilesRouter.js +772 -0
  162. package/lib/Routers/FunctionsRouter.js +341 -0
  163. package/lib/Routers/GlobalConfigRouter.js +123 -0
  164. package/lib/Routers/GraphQLRouter.js +41 -0
  165. package/lib/Routers/HooksRouter.js +121 -0
  166. package/lib/Routers/IAPValidationRouter.js +113 -0
  167. package/lib/Routers/InstallationsRouter.js +46 -0
  168. package/lib/Routers/LogsRouter.js +57 -0
  169. package/lib/Routers/PagesRouter.js +676 -0
  170. package/lib/Routers/PurgeRouter.js +45 -0
  171. package/lib/Routers/PushRouter.js +75 -0
  172. package/lib/Routers/RolesRouter.js +33 -0
  173. package/lib/Routers/SchemasRouter.js +118 -0
  174. package/lib/Routers/SecurityRouter.js +34 -0
  175. package/lib/Routers/SessionsRouter.js +126 -0
  176. package/lib/Routers/UsersRouter.js +733 -0
  177. package/lib/SchemaMigrations/DefinedSchemas.js +379 -0
  178. package/lib/SchemaMigrations/Migrations.js +30 -0
  179. package/lib/Security/Check.js +109 -0
  180. package/lib/Security/CheckGroup.js +44 -0
  181. package/lib/Security/CheckGroups/CheckGroupDatabase.js +44 -0
  182. package/lib/Security/CheckGroups/CheckGroupServerConfig.js +160 -0
  183. package/lib/Security/CheckGroups/CheckGroups.js +21 -0
  184. package/lib/Security/CheckRunner.js +213 -0
  185. package/lib/SharedRest.js +34 -0
  186. package/lib/StatusHandler.js +329 -0
  187. package/lib/TestUtils.js +87 -0
  188. package/lib/Utils.js +577 -0
  189. package/lib/batch.js +185 -0
  190. package/lib/cache.js +12 -0
  191. package/lib/cli/definitions/parse-live-query-server.js +9 -0
  192. package/lib/cli/definitions/parse-server.js +9 -0
  193. package/lib/cli/parse-live-query-server.js +14 -0
  194. package/lib/cli/parse-server.js +101 -0
  195. package/lib/cli/utils/commander.js +132 -0
  196. package/lib/cli/utils/runner.js +53 -0
  197. package/lib/cloud-code/Parse.Cloud.js +797 -0
  198. package/lib/cloud-code/Parse.Server.js +21 -0
  199. package/lib/cryptoUtils.js +54 -0
  200. package/lib/defaults.js +58 -0
  201. package/lib/deprecated.js +12 -0
  202. package/lib/index.js +89 -0
  203. package/lib/logger.js +40 -0
  204. package/lib/middlewares.js +810 -0
  205. package/lib/password.js +40 -0
  206. package/lib/request.js +175 -0
  207. package/lib/requiredParameter.js +11 -0
  208. package/lib/rest.js +264 -0
  209. package/lib/triggers.js +949 -0
  210. package/lib/vendor/README.md +8 -0
  211. package/lib/vendor/mongodbUrl.js +1012 -0
  212. package/package.json +172 -0
  213. package/postinstall.js +38 -0
  214. package/public/custom_json.html +17 -0
  215. package/public/custom_json.json +23 -0
  216. package/public/custom_page.html +15 -0
  217. package/public/de/email_verification_link_expired.html +24 -0
  218. package/public/de/email_verification_link_invalid.html +21 -0
  219. package/public/de/email_verification_send_fail.html +21 -0
  220. package/public/de/email_verification_send_success.html +19 -0
  221. package/public/de/email_verification_success.html +18 -0
  222. package/public/de/password_reset.html +65 -0
  223. package/public/de/password_reset_link_invalid.html +19 -0
  224. package/public/de/password_reset_success.html +18 -0
  225. package/public/de-AT/email_verification_link_expired.html +24 -0
  226. package/public/de-AT/email_verification_link_invalid.html +21 -0
  227. package/public/de-AT/email_verification_send_fail.html +21 -0
  228. package/public/de-AT/email_verification_send_success.html +19 -0
  229. package/public/de-AT/email_verification_success.html +18 -0
  230. package/public/de-AT/password_reset.html +65 -0
  231. package/public/de-AT/password_reset_link_invalid.html +19 -0
  232. package/public/de-AT/password_reset_success.html +18 -0
  233. package/public/email_verification_link_expired.html +24 -0
  234. package/public/email_verification_link_invalid.html +21 -0
  235. package/public/email_verification_send_fail.html +21 -0
  236. package/public/email_verification_send_success.html +19 -0
  237. package/public/email_verification_success.html +18 -0
  238. package/public/password_reset.html +65 -0
  239. package/public/password_reset_link_invalid.html +19 -0
  240. package/public/password_reset_success.html +18 -0
  241. package/types/@types/@parse/fs-files-adapter/index.d.ts +5 -0
  242. package/types/@types/deepcopy/index.d.ts +5 -0
  243. package/types/LiveQuery/ParseLiveQueryServer.d.ts +40 -0
  244. package/types/Options/index.d.ts +320 -0
  245. package/types/ParseServer.d.ts +65 -0
  246. package/types/eslint.config.mjs +30 -0
  247. package/types/index.d.ts +21 -0
  248. package/types/logger.d.ts +2 -0
  249. package/types/tests.ts +44 -0
  250. package/types/tsconfig.json +24 -0
  251. package/views/choose_password +215 -0
@@ -0,0 +1,2409 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = exports.PostgresStorageAdapter = void 0;
7
+ var _PostgresClient = require("./PostgresClient");
8
+ var _node = _interopRequireDefault(require("parse/node"));
9
+ var _lodash = _interopRequireDefault(require("lodash"));
10
+ var _crypto = require("crypto");
11
+ var _sql = _interopRequireDefault(require("./sql"));
12
+ var _StorageAdapter = require("../StorageAdapter");
13
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
14
+ // -disable-next
15
+ // -disable-next
16
+ // -disable-next
17
+ const Utils = require('../../../Utils');
18
+ const PostgresRelationDoesNotExistError = '42P01';
19
+ const PostgresDuplicateRelationError = '42P07';
20
+ const PostgresDuplicateColumnError = '42701';
21
+ const PostgresMissingColumnError = '42703';
22
+ const PostgresUniqueIndexViolationError = '23505';
23
+ const logger = require('../../../logger');
24
+ const debug = function (...args) {
25
+ args = ['PG: ' + arguments[0]].concat(args.slice(1, args.length));
26
+ const log = logger.getLogger();
27
+ log.debug.apply(log, args);
28
+ };
29
+ const parseTypeToPostgresType = type => {
30
+ switch (type.type) {
31
+ case 'String':
32
+ return 'text';
33
+ case 'Date':
34
+ return 'timestamp with time zone';
35
+ case 'Object':
36
+ return 'jsonb';
37
+ case 'File':
38
+ return 'text';
39
+ case 'Boolean':
40
+ return 'boolean';
41
+ case 'Pointer':
42
+ return 'text';
43
+ case 'Number':
44
+ return 'double precision';
45
+ case 'GeoPoint':
46
+ return 'point';
47
+ case 'Bytes':
48
+ return 'jsonb';
49
+ case 'Polygon':
50
+ return 'polygon';
51
+ case 'Array':
52
+ if (type.contents && type.contents.type === 'String') {
53
+ return 'text[]';
54
+ } else {
55
+ return 'jsonb';
56
+ }
57
+ default:
58
+ throw `no type for ${JSON.stringify(type)} yet`;
59
+ }
60
+ };
61
+ const ParseToPosgresComparator = {
62
+ $gt: '>',
63
+ $lt: '<',
64
+ $gte: '>=',
65
+ $lte: '<='
66
+ };
67
+ const mongoAggregateToPostgres = {
68
+ $dayOfMonth: 'DAY',
69
+ $dayOfWeek: 'DOW',
70
+ $dayOfYear: 'DOY',
71
+ $isoDayOfWeek: 'ISODOW',
72
+ $isoWeekYear: 'ISOYEAR',
73
+ $hour: 'HOUR',
74
+ $minute: 'MINUTE',
75
+ $second: 'SECOND',
76
+ $millisecond: 'MILLISECONDS',
77
+ $month: 'MONTH',
78
+ $week: 'WEEK',
79
+ $year: 'YEAR'
80
+ };
81
+ const toPostgresValue = value => {
82
+ if (typeof value === 'object') {
83
+ if (value.__type === 'Date') {
84
+ return value.iso;
85
+ }
86
+ if (value.__type === 'File') {
87
+ return value.name;
88
+ }
89
+ }
90
+ return value;
91
+ };
92
+ const toPostgresValueCastType = value => {
93
+ const postgresValue = toPostgresValue(value);
94
+ let castType;
95
+ switch (typeof postgresValue) {
96
+ case 'number':
97
+ castType = 'double precision';
98
+ break;
99
+ case 'boolean':
100
+ castType = 'boolean';
101
+ break;
102
+ default:
103
+ castType = undefined;
104
+ }
105
+ return castType;
106
+ };
107
+ const transformValue = value => {
108
+ if (typeof value === 'object' && value.__type === 'Pointer') {
109
+ return value.objectId;
110
+ }
111
+ return value;
112
+ };
113
+
114
+ // Duplicate from then mongo adapter...
115
+ const emptyCLPS = Object.freeze({
116
+ find: {},
117
+ get: {},
118
+ count: {},
119
+ create: {},
120
+ update: {},
121
+ delete: {},
122
+ addField: {},
123
+ protectedFields: {}
124
+ });
125
+ const defaultCLPS = Object.freeze({
126
+ ACL: {
127
+ '*': {
128
+ read: true,
129
+ write: true
130
+ }
131
+ },
132
+ find: {
133
+ '*': true
134
+ },
135
+ get: {
136
+ '*': true
137
+ },
138
+ count: {
139
+ '*': true
140
+ },
141
+ create: {
142
+ '*': true
143
+ },
144
+ update: {
145
+ '*': true
146
+ },
147
+ delete: {
148
+ '*': true
149
+ },
150
+ addField: {
151
+ '*': true
152
+ },
153
+ protectedFields: {
154
+ '*': []
155
+ }
156
+ });
157
+ const toParseSchema = schema => {
158
+ if (schema.className === '_User') {
159
+ delete schema.fields._hashed_password;
160
+ }
161
+ if (schema.fields) {
162
+ delete schema.fields._wperm;
163
+ delete schema.fields._rperm;
164
+ }
165
+ let clps = defaultCLPS;
166
+ if (schema.classLevelPermissions) {
167
+ clps = {
168
+ ...emptyCLPS,
169
+ ...schema.classLevelPermissions
170
+ };
171
+ }
172
+ let indexes = {};
173
+ if (schema.indexes) {
174
+ indexes = {
175
+ ...schema.indexes
176
+ };
177
+ }
178
+ return {
179
+ className: schema.className,
180
+ fields: schema.fields,
181
+ classLevelPermissions: clps,
182
+ indexes
183
+ };
184
+ };
185
+ const toPostgresSchema = schema => {
186
+ if (!schema) {
187
+ return schema;
188
+ }
189
+ schema.fields = schema.fields || {};
190
+ schema.fields._wperm = {
191
+ type: 'Array',
192
+ contents: {
193
+ type: 'String'
194
+ }
195
+ };
196
+ schema.fields._rperm = {
197
+ type: 'Array',
198
+ contents: {
199
+ type: 'String'
200
+ }
201
+ };
202
+ if (schema.className === '_User') {
203
+ schema.fields._hashed_password = {
204
+ type: 'String'
205
+ };
206
+ schema.fields._password_history = {
207
+ type: 'Array'
208
+ };
209
+ }
210
+ return schema;
211
+ };
212
+ const isArrayIndex = arrayIndex => Array.from(arrayIndex).every(c => c >= '0' && c <= '9');
213
+ const handleDotFields = object => {
214
+ Object.keys(object).forEach(fieldName => {
215
+ if (fieldName.indexOf('.') > -1) {
216
+ const components = fieldName.split('.');
217
+ const first = components.shift();
218
+ object[first] = object[first] || {};
219
+ let currentObj = object[first];
220
+ let next;
221
+ let value = object[fieldName];
222
+ if (value && value.__op === 'Delete') {
223
+ value = undefined;
224
+ }
225
+ while (next = components.shift()) {
226
+ currentObj[next] = currentObj[next] || {};
227
+ if (components.length === 0) {
228
+ currentObj[next] = value;
229
+ }
230
+ currentObj = currentObj[next];
231
+ }
232
+ delete object[fieldName];
233
+ }
234
+ });
235
+ return object;
236
+ };
237
+ const escapeSqlString = value => value.replace(/'/g, "''");
238
+ const escapeJsonString = value => JSON.stringify(value).slice(1, -1);
239
+ const transformDotFieldToComponents = fieldName => {
240
+ return fieldName.split('.').map((cmpt, index) => {
241
+ if (index === 0) {
242
+ return `"${cmpt.replace(/"/g, '""')}"`;
243
+ }
244
+ if (isArrayIndex(cmpt)) {
245
+ return Number(cmpt);
246
+ } else {
247
+ return `'${escapeSqlString(cmpt)}'`;
248
+ }
249
+ });
250
+ };
251
+ const transformDotField = fieldName => {
252
+ if (fieldName.indexOf('.') === -1) {
253
+ return `"${fieldName.replace(/"/g, '""')}"`;
254
+ }
255
+ const components = transformDotFieldToComponents(fieldName);
256
+ let name = components.slice(0, components.length - 1).join('->');
257
+ name += '->>' + components[components.length - 1];
258
+ return name;
259
+ };
260
+ const validateAggregateFieldName = name => {
261
+ if (typeof name !== 'string' || !name.match(/^[a-zA-Z][a-zA-Z0-9_]*$/)) {
262
+ throw new _node.default.Error(_node.default.Error.INVALID_KEY_NAME, `Invalid field name: ${name}`);
263
+ }
264
+ };
265
+ const transformAggregateField = fieldName => {
266
+ if (typeof fieldName !== 'string') {
267
+ return fieldName;
268
+ }
269
+ if (fieldName === '$_created_at') {
270
+ return 'createdAt';
271
+ }
272
+ if (fieldName === '$_updated_at') {
273
+ return 'updatedAt';
274
+ }
275
+ if (!fieldName.startsWith('$')) {
276
+ throw new _node.default.Error(_node.default.Error.INVALID_KEY_NAME, `Invalid field name: ${fieldName}`);
277
+ }
278
+ const name = fieldName.substring(1);
279
+ validateAggregateFieldName(name);
280
+ return name;
281
+ };
282
+ const validateKeys = object => {
283
+ if (typeof object == 'object') {
284
+ for (const key in object) {
285
+ if (typeof object[key] == 'object') {
286
+ validateKeys(object[key]);
287
+ }
288
+ if (key.includes('$') || key.includes('.')) {
289
+ throw new _node.default.Error(_node.default.Error.INVALID_NESTED_KEY, "Nested keys should not contain the '$' or '.' characters");
290
+ }
291
+ }
292
+ }
293
+ };
294
+
295
+ // Returns the list of join tables on a schema
296
+ const joinTablesForSchema = schema => {
297
+ const list = [];
298
+ if (schema) {
299
+ Object.keys(schema.fields).forEach(field => {
300
+ if (schema.fields[field].type === 'Relation') {
301
+ list.push(`_Join:${field}:${schema.className}`);
302
+ }
303
+ });
304
+ }
305
+ return list;
306
+ };
307
+ const buildWhereClause = ({
308
+ schema,
309
+ query,
310
+ index,
311
+ caseInsensitive
312
+ }) => {
313
+ const patterns = [];
314
+ let values = [];
315
+ const sorts = [];
316
+ schema = toPostgresSchema(schema);
317
+ for (const fieldName in query) {
318
+ const isArrayField = schema.fields && schema.fields[fieldName] && schema.fields[fieldName].type === 'Array';
319
+ const initialPatternsLength = patterns.length;
320
+ const fieldValue = query[fieldName];
321
+
322
+ // nothing in the schema, it's gonna blow up
323
+ if (!schema.fields[fieldName]) {
324
+ // as it won't exist
325
+ if (fieldValue && fieldValue.$exists === false) {
326
+ continue;
327
+ }
328
+ }
329
+ const authDataMatch = fieldName.match(/^_auth_data_([a-zA-Z0-9_]+)$/);
330
+ if (authDataMatch) {
331
+ // TODO: Handle querying by _auth_data_provider, authData is stored in authData field
332
+ continue;
333
+ } else if (caseInsensitive && (fieldName === 'username' || fieldName === 'email')) {
334
+ patterns.push(`LOWER($${index}:name) = LOWER($${index + 1})`);
335
+ values.push(fieldName, fieldValue);
336
+ index += 2;
337
+ } else if (fieldName.indexOf('.') >= 0) {
338
+ let name = transformDotField(fieldName);
339
+ if (fieldValue === null) {
340
+ patterns.push(`$${index}:raw IS NULL`);
341
+ values.push(name);
342
+ index += 1;
343
+ continue;
344
+ } else {
345
+ if (fieldValue.$in) {
346
+ name = transformDotFieldToComponents(fieldName).join('->');
347
+ patterns.push(`($${index}:raw)::jsonb @> $${index + 1}::jsonb`);
348
+ values.push(name, JSON.stringify(fieldValue.$in));
349
+ index += 2;
350
+ } else if (fieldValue.$regex) {
351
+ // Handle later
352
+ } else if (typeof fieldValue !== 'object') {
353
+ patterns.push(`$${index}:raw = $${index + 1}::text`);
354
+ values.push(name, fieldValue);
355
+ index += 2;
356
+ } else if (typeof fieldValue === 'object' && !Object.keys(fieldValue).some(key => key.startsWith('$'))) {
357
+ name = transformDotFieldToComponents(fieldName).join('->');
358
+ patterns.push(`($${index}:raw)::jsonb = $${index + 1}::jsonb`);
359
+ values.push(name, JSON.stringify(fieldValue));
360
+ index += 2;
361
+ }
362
+ }
363
+ } else if (fieldValue === null || fieldValue === undefined) {
364
+ patterns.push(`$${index}:name IS NULL`);
365
+ values.push(fieldName);
366
+ index += 1;
367
+ continue;
368
+ } else if (typeof fieldValue === 'string') {
369
+ patterns.push(`$${index}:name = $${index + 1}`);
370
+ values.push(fieldName, fieldValue);
371
+ index += 2;
372
+ } else if (typeof fieldValue === 'boolean') {
373
+ patterns.push(`$${index}:name = $${index + 1}`);
374
+ // Can't cast boolean to double precision
375
+ if (schema.fields[fieldName] && schema.fields[fieldName].type === 'Number') {
376
+ // Should always return zero results
377
+ const MAX_INT_PLUS_ONE = 9223372036854775808;
378
+ values.push(fieldName, MAX_INT_PLUS_ONE);
379
+ } else {
380
+ values.push(fieldName, fieldValue);
381
+ }
382
+ index += 2;
383
+ } else if (typeof fieldValue === 'number') {
384
+ patterns.push(`$${index}:name = $${index + 1}`);
385
+ values.push(fieldName, fieldValue);
386
+ index += 2;
387
+ } else if (['$or', '$nor', '$and'].includes(fieldName)) {
388
+ const clauses = [];
389
+ const clauseValues = [];
390
+ fieldValue.forEach(subQuery => {
391
+ const clause = buildWhereClause({
392
+ schema,
393
+ query: subQuery,
394
+ index,
395
+ caseInsensitive
396
+ });
397
+ if (clause.pattern.length > 0) {
398
+ clauses.push(clause.pattern);
399
+ clauseValues.push(...clause.values);
400
+ index += clause.values.length;
401
+ }
402
+ });
403
+ const orOrAnd = fieldName === '$and' ? ' AND ' : ' OR ';
404
+ const not = fieldName === '$nor' ? ' NOT ' : '';
405
+ patterns.push(`${not}(${clauses.join(orOrAnd)})`);
406
+ values.push(...clauseValues);
407
+ }
408
+ if (fieldValue.$ne !== undefined) {
409
+ if (isArrayField) {
410
+ fieldValue.$ne = JSON.stringify([fieldValue.$ne]);
411
+ patterns.push(`NOT array_contains($${index}:name, $${index + 1})`);
412
+ } else {
413
+ if (fieldValue.$ne === null) {
414
+ patterns.push(`$${index}:name IS NOT NULL`);
415
+ values.push(fieldName);
416
+ index += 1;
417
+ continue;
418
+ } else {
419
+ // if not null, we need to manually exclude null
420
+ if (fieldValue.$ne.__type === 'GeoPoint') {
421
+ patterns.push(`($${index}:name <> POINT($${index + 1}, $${index + 2}) OR $${index}:name IS NULL)`);
422
+ } else {
423
+ if (fieldName.indexOf('.') >= 0) {
424
+ const castType = toPostgresValueCastType(fieldValue.$ne);
425
+ const constraintFieldName = castType ? `CAST ((${transformDotField(fieldName)}) AS ${castType})` : transformDotField(fieldName);
426
+ patterns.push(`(${constraintFieldName} <> $${index + 1} OR ${constraintFieldName} IS NULL)`);
427
+ } else if (typeof fieldValue.$ne === 'object' && fieldValue.$ne.$relativeTime) {
428
+ throw new _node.default.Error(_node.default.Error.INVALID_JSON, '$relativeTime can only be used with the $lt, $lte, $gt, and $gte operators');
429
+ } else {
430
+ patterns.push(`($${index}:name <> $${index + 1} OR $${index}:name IS NULL)`);
431
+ }
432
+ }
433
+ }
434
+ }
435
+ if (fieldValue.$ne.__type === 'GeoPoint') {
436
+ const point = fieldValue.$ne;
437
+ values.push(fieldName, point.longitude, point.latitude);
438
+ index += 3;
439
+ } else {
440
+ // TODO: support arrays
441
+ values.push(fieldName, fieldValue.$ne);
442
+ index += 2;
443
+ }
444
+ }
445
+ if (fieldValue.$eq !== undefined) {
446
+ if (fieldValue.$eq === null) {
447
+ patterns.push(`$${index}:name IS NULL`);
448
+ values.push(fieldName);
449
+ index += 1;
450
+ } else {
451
+ if (fieldName.indexOf('.') >= 0) {
452
+ const castType = toPostgresValueCastType(fieldValue.$eq);
453
+ const constraintFieldName = castType ? `CAST ((${transformDotField(fieldName)}) AS ${castType})` : transformDotField(fieldName);
454
+ values.push(fieldValue.$eq);
455
+ patterns.push(`${constraintFieldName} = $${index++}`);
456
+ } else if (typeof fieldValue.$eq === 'object' && fieldValue.$eq.$relativeTime) {
457
+ throw new _node.default.Error(_node.default.Error.INVALID_JSON, '$relativeTime can only be used with the $lt, $lte, $gt, and $gte operators');
458
+ } else {
459
+ values.push(fieldName, fieldValue.$eq);
460
+ patterns.push(`$${index}:name = $${index + 1}`);
461
+ index += 2;
462
+ }
463
+ }
464
+ }
465
+ const isInOrNin = Array.isArray(fieldValue.$in) || Array.isArray(fieldValue.$nin);
466
+ if (Array.isArray(fieldValue.$in) && isArrayField && schema.fields[fieldName].contents && schema.fields[fieldName].contents.type === 'String') {
467
+ const inPatterns = [];
468
+ let allowNull = false;
469
+ values.push(fieldName);
470
+ fieldValue.$in.forEach((listElem, listIndex) => {
471
+ if (listElem === null) {
472
+ allowNull = true;
473
+ } else {
474
+ values.push(listElem);
475
+ inPatterns.push(`$${index + 1 + listIndex - (allowNull ? 1 : 0)}`);
476
+ }
477
+ });
478
+ if (allowNull) {
479
+ patterns.push(`($${index}:name IS NULL OR $${index}:name && ARRAY[${inPatterns.join()}])`);
480
+ } else {
481
+ patterns.push(`$${index}:name && ARRAY[${inPatterns.join()}]`);
482
+ }
483
+ index = index + 1 + inPatterns.length;
484
+ } else if (isInOrNin) {
485
+ var createConstraint = (baseArray, notIn) => {
486
+ const not = notIn ? ' NOT ' : '';
487
+ if (baseArray.length > 0) {
488
+ if (isArrayField) {
489
+ patterns.push(`${not} array_contains($${index}:name, $${index + 1})`);
490
+ values.push(fieldName, JSON.stringify(baseArray));
491
+ index += 2;
492
+ } else {
493
+ // Handle Nested Dot Notation Above
494
+ if (fieldName.indexOf('.') >= 0) {
495
+ return;
496
+ }
497
+ const fieldType = schema.fields[fieldName]?.type;
498
+ if (fieldType === 'String') {
499
+ const operatorName = notIn ? '$nin' : '$in';
500
+ for (const elem of baseArray) {
501
+ if (elem != null && typeof elem !== 'string') {
502
+ throw new _node.default.Error(_node.default.Error.INVALID_QUERY, `${operatorName} element type mismatch: expected string for field "${fieldName}"`);
503
+ }
504
+ }
505
+ }
506
+ const inPatterns = [];
507
+ values.push(fieldName);
508
+ baseArray.forEach((listElem, listIndex) => {
509
+ if (listElem != null) {
510
+ values.push(listElem);
511
+ inPatterns.push(`$${index + 1 + listIndex}`);
512
+ }
513
+ });
514
+ patterns.push(`$${index}:name ${not} IN (${inPatterns.join()})`);
515
+ index = index + 1 + inPatterns.length;
516
+ }
517
+ } else if (!notIn) {
518
+ values.push(fieldName);
519
+ patterns.push(`$${index}:name IS NULL`);
520
+ index = index + 1;
521
+ } else {
522
+ // Handle empty array
523
+ if (notIn) {
524
+ patterns.push('1 = 1'); // Return all values
525
+ } else {
526
+ patterns.push('1 = 2'); // Return no values
527
+ }
528
+ }
529
+ };
530
+ if (fieldValue.$in) {
531
+ createConstraint(_lodash.default.flatMap(fieldValue.$in, elt => elt), false);
532
+ }
533
+ if (fieldValue.$nin) {
534
+ createConstraint(_lodash.default.flatMap(fieldValue.$nin, elt => elt), true);
535
+ }
536
+ } else if (typeof fieldValue.$in !== 'undefined') {
537
+ throw new _node.default.Error(_node.default.Error.INVALID_JSON, 'bad $in value');
538
+ } else if (typeof fieldValue.$nin !== 'undefined') {
539
+ throw new _node.default.Error(_node.default.Error.INVALID_JSON, 'bad $nin value');
540
+ }
541
+ if (Array.isArray(fieldValue.$all) && isArrayField) {
542
+ if (isAnyValueRegexStartsWith(fieldValue.$all)) {
543
+ if (!isAllValuesRegexOrNone(fieldValue.$all)) {
544
+ throw new _node.default.Error(_node.default.Error.INVALID_JSON, 'All $all values must be of regex type or none: ' + fieldValue.$all);
545
+ }
546
+ for (let i = 0; i < fieldValue.$all.length; i += 1) {
547
+ const value = processRegexPattern(fieldValue.$all[i].$regex);
548
+ fieldValue.$all[i] = value.substring(1) + '%';
549
+ }
550
+ patterns.push(`array_contains_all_regex($${index}:name, $${index + 1}::jsonb)`);
551
+ } else {
552
+ patterns.push(`array_contains_all($${index}:name, $${index + 1}::jsonb)`);
553
+ }
554
+ values.push(fieldName, JSON.stringify(fieldValue.$all));
555
+ index += 2;
556
+ } else if (Array.isArray(fieldValue.$all)) {
557
+ if (fieldValue.$all.length === 1) {
558
+ patterns.push(`$${index}:name = $${index + 1}`);
559
+ values.push(fieldName, fieldValue.$all[0].objectId);
560
+ index += 2;
561
+ }
562
+ }
563
+ if (typeof fieldValue.$exists !== 'undefined') {
564
+ if (typeof fieldValue.$exists === 'object' && fieldValue.$exists.$relativeTime) {
565
+ throw new _node.default.Error(_node.default.Error.INVALID_JSON, '$relativeTime can only be used with the $lt, $lte, $gt, and $gte operators');
566
+ } else if (fieldValue.$exists) {
567
+ patterns.push(`$${index}:name IS NOT NULL`);
568
+ } else {
569
+ patterns.push(`$${index}:name IS NULL`);
570
+ }
571
+ values.push(fieldName);
572
+ index += 1;
573
+ }
574
+ if (fieldValue.$containedBy) {
575
+ const arr = fieldValue.$containedBy;
576
+ if (!Array.isArray(arr)) {
577
+ throw new _node.default.Error(_node.default.Error.INVALID_JSON, `bad $containedBy: should be an array`);
578
+ }
579
+ patterns.push(`$${index}:name <@ $${index + 1}::jsonb`);
580
+ values.push(fieldName, JSON.stringify(arr));
581
+ index += 2;
582
+ }
583
+ if (fieldValue.$text) {
584
+ const search = fieldValue.$text.$search;
585
+ let language = 'english';
586
+ if (typeof search !== 'object') {
587
+ throw new _node.default.Error(_node.default.Error.INVALID_JSON, `bad $text: $search, should be object`);
588
+ }
589
+ if (!search.$term || typeof search.$term !== 'string') {
590
+ throw new _node.default.Error(_node.default.Error.INVALID_JSON, `bad $text: $term, should be string`);
591
+ }
592
+ if (search.$language && typeof search.$language !== 'string') {
593
+ throw new _node.default.Error(_node.default.Error.INVALID_JSON, `bad $text: $language, should be string`);
594
+ } else if (search.$language) {
595
+ language = search.$language;
596
+ }
597
+ if (search.$caseSensitive && typeof search.$caseSensitive !== 'boolean') {
598
+ throw new _node.default.Error(_node.default.Error.INVALID_JSON, `bad $text: $caseSensitive, should be boolean`);
599
+ } else if (search.$caseSensitive) {
600
+ throw new _node.default.Error(_node.default.Error.INVALID_JSON, `bad $text: $caseSensitive not supported, please use $regex or create a separate lower case column.`);
601
+ }
602
+ if (search.$diacriticSensitive && typeof search.$diacriticSensitive !== 'boolean') {
603
+ throw new _node.default.Error(_node.default.Error.INVALID_JSON, `bad $text: $diacriticSensitive, should be boolean`);
604
+ } else if (search.$diacriticSensitive === false) {
605
+ throw new _node.default.Error(_node.default.Error.INVALID_JSON, `bad $text: $diacriticSensitive - false not supported, install Postgres Unaccent Extension`);
606
+ }
607
+ patterns.push(`to_tsvector($${index}, $${index + 1}:name) @@ to_tsquery($${index + 2}, $${index + 3})`);
608
+ values.push(language, fieldName, language, search.$term);
609
+ index += 4;
610
+ }
611
+ if (fieldValue.$nearSphere) {
612
+ const point = fieldValue.$nearSphere;
613
+ const distance = fieldValue.$maxDistance;
614
+ const distanceInKM = distance * 6371 * 1000;
615
+ patterns.push(`ST_DistanceSphere($${index}:name::geometry, POINT($${index + 1}, $${index + 2})::geometry) <= $${index + 3}`);
616
+ sorts.push(`ST_DistanceSphere($${index}:name::geometry, POINT($${index + 1}, $${index + 2})::geometry) ASC`);
617
+ values.push(fieldName, point.longitude, point.latitude, distanceInKM);
618
+ index += 4;
619
+ }
620
+ if (fieldValue.$within && fieldValue.$within.$box) {
621
+ const box = fieldValue.$within.$box;
622
+ const left = box[0].longitude;
623
+ const bottom = box[0].latitude;
624
+ const right = box[1].longitude;
625
+ const top = box[1].latitude;
626
+ patterns.push(`$${index}:name::point <@ $${index + 1}::box`);
627
+ values.push(fieldName, `((${left}, ${bottom}), (${right}, ${top}))`);
628
+ index += 2;
629
+ }
630
+ if (fieldValue.$geoWithin && fieldValue.$geoWithin.$centerSphere) {
631
+ const centerSphere = fieldValue.$geoWithin.$centerSphere;
632
+ if (!Array.isArray(centerSphere) || centerSphere.length < 2) {
633
+ throw new _node.default.Error(_node.default.Error.INVALID_JSON, 'bad $geoWithin value; $centerSphere should be an array of Parse.GeoPoint and distance');
634
+ }
635
+ // Get point, convert to geo point if necessary and validate
636
+ let point = centerSphere[0];
637
+ if (Array.isArray(point) && point.length === 2) {
638
+ point = new _node.default.GeoPoint(point[1], point[0]);
639
+ } else if (!GeoPointCoder.isValidJSON(point)) {
640
+ throw new _node.default.Error(_node.default.Error.INVALID_JSON, 'bad $geoWithin value; $centerSphere geo point invalid');
641
+ }
642
+ _node.default.GeoPoint._validate(point.latitude, point.longitude);
643
+ // Get distance and validate
644
+ const distance = centerSphere[1];
645
+ if (isNaN(distance) || distance < 0) {
646
+ throw new _node.default.Error(_node.default.Error.INVALID_JSON, 'bad $geoWithin value; $centerSphere distance invalid');
647
+ }
648
+ const distanceInKM = distance * 6371 * 1000;
649
+ patterns.push(`ST_DistanceSphere($${index}:name::geometry, POINT($${index + 1}, $${index + 2})::geometry) <= $${index + 3}`);
650
+ values.push(fieldName, point.longitude, point.latitude, distanceInKM);
651
+ index += 4;
652
+ }
653
+ if (fieldValue.$geoWithin && fieldValue.$geoWithin.$polygon) {
654
+ const polygon = fieldValue.$geoWithin.$polygon;
655
+ let points;
656
+ if (typeof polygon === 'object' && polygon.__type === 'Polygon') {
657
+ if (!polygon.coordinates || polygon.coordinates.length < 3) {
658
+ throw new _node.default.Error(_node.default.Error.INVALID_JSON, 'bad $geoWithin value; Polygon.coordinates should contain at least 3 lon/lat pairs');
659
+ }
660
+ points = polygon.coordinates;
661
+ } else if (Array.isArray(polygon)) {
662
+ if (polygon.length < 3) {
663
+ throw new _node.default.Error(_node.default.Error.INVALID_JSON, 'bad $geoWithin value; $polygon should contain at least 3 GeoPoints');
664
+ }
665
+ points = polygon;
666
+ } else {
667
+ throw new _node.default.Error(_node.default.Error.INVALID_JSON, "bad $geoWithin value; $polygon should be Polygon object or Array of Parse.GeoPoint's");
668
+ }
669
+ points = points.map(point => {
670
+ if (Array.isArray(point) && point.length === 2) {
671
+ _node.default.GeoPoint._validate(point[1], point[0]);
672
+ return `(${point[0]}, ${point[1]})`;
673
+ }
674
+ if (typeof point !== 'object' || point.__type !== 'GeoPoint') {
675
+ throw new _node.default.Error(_node.default.Error.INVALID_JSON, 'bad $geoWithin value');
676
+ } else {
677
+ _node.default.GeoPoint._validate(point.latitude, point.longitude);
678
+ }
679
+ return `(${point.longitude}, ${point.latitude})`;
680
+ }).join(', ');
681
+ patterns.push(`$${index}:name::point <@ $${index + 1}::polygon`);
682
+ values.push(fieldName, `(${points})`);
683
+ index += 2;
684
+ }
685
+ if (fieldValue.$geoIntersects && fieldValue.$geoIntersects.$point) {
686
+ const point = fieldValue.$geoIntersects.$point;
687
+ if (typeof point !== 'object' || point.__type !== 'GeoPoint') {
688
+ throw new _node.default.Error(_node.default.Error.INVALID_JSON, 'bad $geoIntersect value; $point should be GeoPoint');
689
+ } else {
690
+ _node.default.GeoPoint._validate(point.latitude, point.longitude);
691
+ }
692
+ patterns.push(`$${index}:name::polygon @> $${index + 1}::point`);
693
+ values.push(fieldName, `(${point.longitude}, ${point.latitude})`);
694
+ index += 2;
695
+ }
696
+ if (fieldValue.$regex) {
697
+ let regex = fieldValue.$regex;
698
+ let operator = '~';
699
+ const opts = fieldValue.$options;
700
+ if (opts) {
701
+ if (opts.indexOf('i') >= 0) {
702
+ operator = '~*';
703
+ }
704
+ if (opts.indexOf('x') >= 0) {
705
+ regex = removeWhiteSpace(regex);
706
+ }
707
+ }
708
+ regex = processRegexPattern(regex);
709
+ if (fieldName.indexOf('.') >= 0) {
710
+ const name = transformDotField(fieldName);
711
+ patterns.push(`$${index}:raw ${operator} '$${index + 1}:raw'`);
712
+ values.push(name, regex);
713
+ } else {
714
+ patterns.push(`$${index}:name ${operator} '$${index + 1}:raw'`);
715
+ values.push(fieldName, regex);
716
+ }
717
+ index += 2;
718
+ }
719
+ if (fieldValue.__type === 'Pointer') {
720
+ if (isArrayField) {
721
+ patterns.push(`array_contains($${index}:name, $${index + 1})`);
722
+ values.push(fieldName, JSON.stringify([fieldValue]));
723
+ index += 2;
724
+ } else {
725
+ patterns.push(`$${index}:name = $${index + 1}`);
726
+ values.push(fieldName, fieldValue.objectId);
727
+ index += 2;
728
+ }
729
+ }
730
+ if (fieldValue.__type === 'Date') {
731
+ patterns.push(`$${index}:name = $${index + 1}`);
732
+ values.push(fieldName, fieldValue.iso);
733
+ index += 2;
734
+ }
735
+ if (fieldValue.__type === 'GeoPoint') {
736
+ patterns.push(`$${index}:name ~= POINT($${index + 1}, $${index + 2})`);
737
+ values.push(fieldName, fieldValue.longitude, fieldValue.latitude);
738
+ index += 3;
739
+ }
740
+ if (fieldValue.__type === 'Polygon') {
741
+ const value = convertPolygonToSQL(fieldValue.coordinates);
742
+ patterns.push(`$${index}:name ~= $${index + 1}::polygon`);
743
+ values.push(fieldName, value);
744
+ index += 2;
745
+ }
746
+ Object.keys(ParseToPosgresComparator).forEach(cmp => {
747
+ if (fieldValue[cmp] || fieldValue[cmp] === 0) {
748
+ const pgComparator = ParseToPosgresComparator[cmp];
749
+ let constraintFieldName;
750
+ let postgresValue = toPostgresValue(fieldValue[cmp]);
751
+ if (fieldName.indexOf('.') >= 0) {
752
+ const castType = toPostgresValueCastType(fieldValue[cmp]);
753
+ constraintFieldName = castType ? `CAST ((${transformDotField(fieldName)}) AS ${castType})` : transformDotField(fieldName);
754
+ } else {
755
+ if (typeof postgresValue === 'object' && postgresValue.$relativeTime) {
756
+ if (schema.fields[fieldName].type !== 'Date') {
757
+ throw new _node.default.Error(_node.default.Error.INVALID_JSON, '$relativeTime can only be used with Date field');
758
+ }
759
+ const parserResult = Utils.relativeTimeToDate(postgresValue.$relativeTime);
760
+ if (parserResult.status === 'success') {
761
+ postgresValue = toPostgresValue(parserResult.result);
762
+ } else {
763
+ // eslint-disable-next-line no-console
764
+ console.error('Error while parsing relative date', parserResult);
765
+ throw new _node.default.Error(_node.default.Error.INVALID_JSON, `bad $relativeTime (${postgresValue.$relativeTime}) value. ${parserResult.info}`);
766
+ }
767
+ }
768
+ constraintFieldName = `$${index++}:name`;
769
+ values.push(fieldName);
770
+ }
771
+ values.push(postgresValue);
772
+ patterns.push(`${constraintFieldName} ${pgComparator} $${index++}`);
773
+ }
774
+ });
775
+ if (initialPatternsLength === patterns.length) {
776
+ throw new _node.default.Error(_node.default.Error.OPERATION_FORBIDDEN, `Postgres doesn't support this query type yet ${JSON.stringify(fieldValue)}`);
777
+ }
778
+ }
779
+ values = values.map(transformValue);
780
+ return {
781
+ pattern: patterns.join(' AND '),
782
+ values,
783
+ sorts
784
+ };
785
+ };
786
+ class PostgresStorageAdapter {
787
+ // Private
788
+
789
+ constructor({
790
+ uri,
791
+ collectionPrefix = '',
792
+ databaseOptions = {}
793
+ }) {
794
+ const options = {
795
+ ...databaseOptions
796
+ };
797
+ this._collectionPrefix = collectionPrefix;
798
+ this.enableSchemaHooks = !!databaseOptions.enableSchemaHooks;
799
+ this.disableIndexFieldValidation = !!databaseOptions.disableIndexFieldValidation;
800
+ this.schemaCacheTtl = databaseOptions.schemaCacheTtl;
801
+ for (const key of ['enableSchemaHooks', 'schemaCacheTtl', 'disableIndexFieldValidation']) {
802
+ delete options[key];
803
+ }
804
+ const {
805
+ client,
806
+ pgp
807
+ } = (0, _PostgresClient.createClient)(uri, options);
808
+ this._client = client;
809
+ this._onchange = () => {};
810
+ this._pgp = pgp;
811
+ this._uuid = (0, _crypto.randomUUID)();
812
+ this.canSortOnJoinTables = false;
813
+ }
814
+ watch(callback) {
815
+ this._onchange = callback;
816
+ }
817
+
818
+ //Note that analyze=true will run the query, executing INSERTS, DELETES, etc.
819
+ createExplainableQuery(query, analyze = false) {
820
+ if (analyze) {
821
+ return 'EXPLAIN (ANALYZE, FORMAT JSON) ' + query;
822
+ } else {
823
+ return 'EXPLAIN (FORMAT JSON) ' + query;
824
+ }
825
+ }
826
+ handleShutdown() {
827
+ if (this._stream) {
828
+ this._stream.done();
829
+ delete this._stream;
830
+ }
831
+ if (!this._client) {
832
+ return;
833
+ }
834
+ this._client.$pool.end();
835
+ }
836
+ async _listenToSchema() {
837
+ if (!this._stream && this.enableSchemaHooks) {
838
+ this._stream = await this._client.connect({
839
+ direct: true
840
+ });
841
+ this._stream.client.on('notification', data => {
842
+ const payload = JSON.parse(data.payload);
843
+ if (payload.senderId !== this._uuid) {
844
+ this._onchange();
845
+ }
846
+ });
847
+ await this._stream.none('LISTEN $1~', 'schema.change');
848
+ }
849
+ }
850
+ _notifySchemaChange() {
851
+ if (this._stream) {
852
+ this._stream.none('NOTIFY $1~, $2', ['schema.change', {
853
+ senderId: this._uuid
854
+ }]).catch(error => {
855
+ // eslint-disable-next-line no-console
856
+ console.log('Failed to Notify:', error); // unlikely to ever happen
857
+ });
858
+ }
859
+ }
860
+ async _ensureSchemaCollectionExists(conn) {
861
+ conn = conn || this._client;
862
+ await conn.none('CREATE TABLE IF NOT EXISTS "_SCHEMA" ( "className" varChar(120), "schema" jsonb, "isParseClass" bool, PRIMARY KEY ("className") )').catch(error => {
863
+ throw error;
864
+ });
865
+ }
866
+ async classExists(name) {
867
+ return this._client.one('SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = $1)', [name], a => a.exists);
868
+ }
869
+ async setClassLevelPermissions(className, CLPs) {
870
+ await this._client.task('set-class-level-permissions', async t => {
871
+ const values = [className, 'schema', 'classLevelPermissions', JSON.stringify(CLPs)];
872
+ await t.none(`UPDATE "_SCHEMA" SET $2:name = json_object_set_key($2:name, $3::text, $4::jsonb) WHERE "className" = $1`, values);
873
+ });
874
+ this._notifySchemaChange();
875
+ }
876
+ async setIndexesWithSchemaFormat(className, submittedIndexes, existingIndexes = {}, fields, conn) {
877
+ conn = conn || this._client;
878
+ const self = this;
879
+ if (submittedIndexes === undefined) {
880
+ return Promise.resolve();
881
+ }
882
+ if (Object.keys(existingIndexes).length === 0) {
883
+ existingIndexes = {
884
+ _id_: {
885
+ _id: 1
886
+ }
887
+ };
888
+ }
889
+ const deletedIndexes = [];
890
+ const insertedIndexes = [];
891
+ Object.keys(submittedIndexes).forEach(name => {
892
+ const field = submittedIndexes[name];
893
+ if (existingIndexes[name] && field.__op !== 'Delete') {
894
+ throw new _node.default.Error(_node.default.Error.INVALID_QUERY, `Index ${name} exists, cannot update.`);
895
+ }
896
+ if (!existingIndexes[name] && field.__op === 'Delete') {
897
+ throw new _node.default.Error(_node.default.Error.INVALID_QUERY, `Index ${name} does not exist, cannot delete.`);
898
+ }
899
+ if (field.__op === 'Delete') {
900
+ deletedIndexes.push(name);
901
+ delete existingIndexes[name];
902
+ } else {
903
+ Object.keys(field).forEach(key => {
904
+ if (!this.disableIndexFieldValidation && !Object.prototype.hasOwnProperty.call(fields, key)) {
905
+ throw new _node.default.Error(_node.default.Error.INVALID_QUERY, `Field ${key} does not exist, cannot add index.`);
906
+ }
907
+ });
908
+ existingIndexes[name] = field;
909
+ insertedIndexes.push({
910
+ key: field,
911
+ name
912
+ });
913
+ }
914
+ });
915
+ await conn.tx('set-indexes-with-schema-format', async t => {
916
+ try {
917
+ if (insertedIndexes.length > 0) {
918
+ await self.createIndexes(className, insertedIndexes, t);
919
+ }
920
+ } catch (e) {
921
+ // pg-promise use Batch error see https://github.com/vitaly-t/spex/blob/e572030f261be1a8e9341fc6f637e36ad07f5231/src/errors/batch.js#L59
922
+ const columnDoesNotExistError = e.getErrors && e.getErrors()[0] && e.getErrors()[0].code === '42703';
923
+ // Specific case when the column does not exist
924
+ if (columnDoesNotExistError) {
925
+ // If the disableIndexFieldValidation is true, we should ignore the error
926
+ if (!this.disableIndexFieldValidation) {
927
+ throw e;
928
+ }
929
+ } else {
930
+ throw e;
931
+ }
932
+ }
933
+ if (deletedIndexes.length > 0) {
934
+ await self.dropIndexes(className, deletedIndexes, t);
935
+ }
936
+ await t.none('UPDATE "_SCHEMA" SET $2:name = json_object_set_key($2:name, $3::text, $4::jsonb) WHERE "className" = $1', [className, 'schema', 'indexes', JSON.stringify(existingIndexes)]);
937
+ });
938
+ this._notifySchemaChange();
939
+ }
940
+ async createClass(className, schema, conn) {
941
+ conn = conn || this._client;
942
+ const parseSchema = await conn.tx('create-class', async t => {
943
+ await this.createTable(className, schema, t);
944
+ await t.none('INSERT INTO "_SCHEMA" ("className", "schema", "isParseClass") VALUES ($<className>, $<schema>, true)', {
945
+ className,
946
+ schema
947
+ });
948
+ await this.setIndexesWithSchemaFormat(className, schema.indexes, {}, schema.fields, t);
949
+ return toParseSchema(schema);
950
+ }).catch(err => {
951
+ if (err.code === PostgresUniqueIndexViolationError && err.detail.includes(className)) {
952
+ throw new _node.default.Error(_node.default.Error.DUPLICATE_VALUE, `Class ${className} already exists.`);
953
+ }
954
+ throw err;
955
+ });
956
+ this._notifySchemaChange();
957
+ return parseSchema;
958
+ }
959
+
960
+ // Just create a table, do not insert in schema
961
+ async createTable(className, schema, conn) {
962
+ conn = conn || this._client;
963
+ debug('createTable');
964
+ const valuesArray = [];
965
+ const patternsArray = [];
966
+ const fields = Object.assign({}, schema.fields);
967
+ if (className === '_User') {
968
+ fields._email_verify_token_expires_at = {
969
+ type: 'Date'
970
+ };
971
+ fields._email_verify_token = {
972
+ type: 'String'
973
+ };
974
+ fields._account_lockout_expires_at = {
975
+ type: 'Date'
976
+ };
977
+ fields._failed_login_count = {
978
+ type: 'Number'
979
+ };
980
+ fields._perishable_token = {
981
+ type: 'String'
982
+ };
983
+ fields._perishable_token_expires_at = {
984
+ type: 'Date'
985
+ };
986
+ fields._password_changed_at = {
987
+ type: 'Date'
988
+ };
989
+ fields._password_history = {
990
+ type: 'Array'
991
+ };
992
+ }
993
+ let index = 2;
994
+ const relations = [];
995
+ Object.keys(fields).forEach(fieldName => {
996
+ const parseType = fields[fieldName];
997
+ // Skip when it's a relation
998
+ // We'll create the tables later
999
+ if (parseType.type === 'Relation') {
1000
+ relations.push(fieldName);
1001
+ return;
1002
+ }
1003
+ if (['_rperm', '_wperm'].indexOf(fieldName) >= 0) {
1004
+ parseType.contents = {
1005
+ type: 'String'
1006
+ };
1007
+ }
1008
+ valuesArray.push(fieldName);
1009
+ valuesArray.push(parseTypeToPostgresType(parseType));
1010
+ patternsArray.push(`$${index}:name $${index + 1}:raw`);
1011
+ if (fieldName === 'objectId') {
1012
+ patternsArray.push(`PRIMARY KEY ($${index}:name)`);
1013
+ }
1014
+ index = index + 2;
1015
+ });
1016
+ const qs = `CREATE TABLE IF NOT EXISTS $1:name (${patternsArray.join()})`;
1017
+ const values = [className, ...valuesArray];
1018
+ return conn.task('create-table', async t => {
1019
+ try {
1020
+ await t.none(qs, values);
1021
+ } catch (error) {
1022
+ if (error.code !== PostgresDuplicateRelationError) {
1023
+ throw error;
1024
+ }
1025
+ // ELSE: Table already exists, must have been created by a different request. Ignore the error.
1026
+ }
1027
+ await t.tx('create-table-tx', tx => {
1028
+ return tx.batch(relations.map(fieldName => {
1029
+ return tx.none('CREATE TABLE IF NOT EXISTS $<joinTable:name> ("relatedId" varChar(120), "owningId" varChar(120), PRIMARY KEY("relatedId", "owningId") )', {
1030
+ joinTable: `_Join:${fieldName}:${className}`
1031
+ });
1032
+ }));
1033
+ });
1034
+ });
1035
+ }
1036
+ async schemaUpgrade(className, schema, conn) {
1037
+ debug('schemaUpgrade');
1038
+ conn = conn || this._client;
1039
+ const self = this;
1040
+ await conn.task('schema-upgrade', async t => {
1041
+ const columns = await t.map('SELECT column_name FROM information_schema.columns WHERE table_name = $<className>', {
1042
+ className
1043
+ }, a => a.column_name);
1044
+ const newColumns = Object.keys(schema.fields).filter(item => columns.indexOf(item) === -1).map(fieldName => self.addFieldIfNotExists(className, fieldName, schema.fields[fieldName]));
1045
+ await t.batch(newColumns);
1046
+ });
1047
+ }
1048
+ async addFieldIfNotExists(className, fieldName, type) {
1049
+ // TODO: Must be revised for invalid logic...
1050
+ debug('addFieldIfNotExists');
1051
+ const self = this;
1052
+ await this._client.tx('add-field-if-not-exists', async t => {
1053
+ if (type.type !== 'Relation') {
1054
+ try {
1055
+ await t.none('ALTER TABLE $<className:name> ADD COLUMN IF NOT EXISTS $<fieldName:name> $<postgresType:raw>', {
1056
+ className,
1057
+ fieldName,
1058
+ postgresType: parseTypeToPostgresType(type)
1059
+ });
1060
+ } catch (error) {
1061
+ if (error.code === PostgresRelationDoesNotExistError) {
1062
+ return self.createClass(className, {
1063
+ fields: {
1064
+ [fieldName]: type
1065
+ }
1066
+ }, t);
1067
+ }
1068
+ if (error.code !== PostgresDuplicateColumnError) {
1069
+ throw error;
1070
+ }
1071
+ // Column already exists, created by other request. Carry on to see if it's the right type.
1072
+ }
1073
+ } else {
1074
+ await t.none('CREATE TABLE IF NOT EXISTS $<joinTable:name> ("relatedId" varChar(120), "owningId" varChar(120), PRIMARY KEY("relatedId", "owningId") )', {
1075
+ joinTable: `_Join:${fieldName}:${className}`
1076
+ });
1077
+ }
1078
+ const result = await t.any('SELECT "schema" FROM "_SCHEMA" WHERE "className" = $<className> and ("schema"::json->\'fields\'->$<fieldName>) is not null', {
1079
+ className,
1080
+ fieldName
1081
+ });
1082
+ if (result[0]) {
1083
+ throw 'Attempted to add a field that already exists';
1084
+ } else {
1085
+ const path = `{fields,${fieldName}}`;
1086
+ await t.none('UPDATE "_SCHEMA" SET "schema"=jsonb_set("schema", $<path>, $<type>) WHERE "className"=$<className>', {
1087
+ path,
1088
+ type,
1089
+ className
1090
+ });
1091
+ }
1092
+ });
1093
+ this._notifySchemaChange();
1094
+ }
1095
+ async updateFieldOptions(className, fieldName, type) {
1096
+ await this._client.tx('update-schema-field-options', async t => {
1097
+ const path = `{fields,${fieldName}}`;
1098
+ await t.none('UPDATE "_SCHEMA" SET "schema"=jsonb_set("schema", $<path>, $<type>) WHERE "className"=$<className>', {
1099
+ path,
1100
+ type,
1101
+ className
1102
+ });
1103
+ });
1104
+ }
1105
+
1106
+ // Drops a collection. Resolves with true if it was a Parse Schema (eg. _User, Custom, etc.)
1107
+ // and resolves with false if it wasn't (eg. a join table). Rejects if deletion was impossible.
1108
+ async deleteClass(className) {
1109
+ const operations = [{
1110
+ query: `DROP TABLE IF EXISTS $1:name`,
1111
+ values: [className]
1112
+ }, {
1113
+ query: `DELETE FROM "_SCHEMA" WHERE "className" = $1`,
1114
+ values: [className]
1115
+ }];
1116
+ const response = await this._client.tx(t => t.none(this._pgp.helpers.concat(operations))).then(() => className.indexOf('_Join:') != 0); // resolves with false when _Join table
1117
+
1118
+ this._notifySchemaChange();
1119
+ return response;
1120
+ }
1121
+
1122
+ // Delete all data known to this adapter. Used for testing.
1123
+ async deleteAllClasses() {
1124
+ const now = new Date().getTime();
1125
+ const helpers = this._pgp.helpers;
1126
+ debug('deleteAllClasses');
1127
+ if (this._client?.$pool.ended) {
1128
+ return;
1129
+ }
1130
+ await this._client.task('delete-all-classes', async t => {
1131
+ try {
1132
+ const results = await t.any('SELECT * FROM "_SCHEMA"');
1133
+ const joins = results.reduce((list, schema) => {
1134
+ return list.concat(joinTablesForSchema(schema.schema));
1135
+ }, []);
1136
+ const classes = ['_SCHEMA', '_PushStatus', '_JobStatus', '_JobSchedule', '_Hooks', '_GlobalConfig', '_GraphQLConfig', '_Audience', '_Idempotency', ...results.map(result => result.className), ...joins];
1137
+ const queries = classes.map(className => ({
1138
+ query: 'DROP TABLE IF EXISTS $<className:name>',
1139
+ values: {
1140
+ className
1141
+ }
1142
+ }));
1143
+ await t.tx(tx => tx.none(helpers.concat(queries)));
1144
+ } catch (error) {
1145
+ if (error.code !== PostgresRelationDoesNotExistError) {
1146
+ throw error;
1147
+ }
1148
+ // No _SCHEMA collection. Don't delete anything.
1149
+ }
1150
+ }).then(() => {
1151
+ debug(`deleteAllClasses done in ${new Date().getTime() - now}`);
1152
+ });
1153
+ }
1154
+
1155
+ // Remove the column and all the data. For Relations, the _Join collection is handled
1156
+ // specially, this function does not delete _Join columns. It should, however, indicate
1157
+ // that the relation fields does not exist anymore. In mongo, this means removing it from
1158
+ // the _SCHEMA collection. There should be no actual data in the collection under the same name
1159
+ // as the relation column, so it's fine to attempt to delete it. If the fields listed to be
1160
+ // deleted do not exist, this function should return successfully anyways. Checking for
1161
+ // attempts to delete non-existent fields is the responsibility of Parse Server.
1162
+
1163
+ // This function is not obligated to delete fields atomically. It is given the field
1164
+ // names in a list so that databases that are capable of deleting fields atomically
1165
+ // may do so.
1166
+
1167
+ // Returns a Promise.
1168
+ async deleteFields(className, schema, fieldNames) {
1169
+ debug('deleteFields');
1170
+ fieldNames = fieldNames.reduce((list, fieldName) => {
1171
+ const field = schema.fields[fieldName];
1172
+ if (field.type !== 'Relation') {
1173
+ list.push(fieldName);
1174
+ }
1175
+ delete schema.fields[fieldName];
1176
+ return list;
1177
+ }, []);
1178
+ const values = [className, ...fieldNames];
1179
+ const columns = fieldNames.map((name, idx) => {
1180
+ return `$${idx + 2}:name`;
1181
+ }).join(', DROP COLUMN');
1182
+ await this._client.tx('delete-fields', async t => {
1183
+ await t.none('UPDATE "_SCHEMA" SET "schema" = $<schema> WHERE "className" = $<className>', {
1184
+ schema,
1185
+ className
1186
+ });
1187
+ if (values.length > 1) {
1188
+ await t.none(`ALTER TABLE $1:name DROP COLUMN IF EXISTS ${columns}`, values);
1189
+ }
1190
+ });
1191
+ this._notifySchemaChange();
1192
+ }
1193
+
1194
+ // Return a promise for all schemas known to this adapter, in Parse format. In case the
1195
+ // schemas cannot be retrieved, returns a promise that rejects. Requirements for the
1196
+ // rejection reason are TBD.
1197
+ async getAllClasses() {
1198
+ return this._client.task('get-all-classes', async t => {
1199
+ return await t.map('SELECT * FROM "_SCHEMA"', null, row => toParseSchema({
1200
+ className: row.className,
1201
+ ...row.schema
1202
+ }));
1203
+ });
1204
+ }
1205
+
1206
+ // Return a promise for the schema with the given name, in Parse format. If
1207
+ // this adapter doesn't know about the schema, return a promise that rejects with
1208
+ // undefined as the reason.
1209
+ async getClass(className) {
1210
+ debug('getClass');
1211
+ return this._client.any('SELECT * FROM "_SCHEMA" WHERE "className" = $<className>', {
1212
+ className
1213
+ }).then(result => {
1214
+ if (result.length !== 1) {
1215
+ throw undefined;
1216
+ }
1217
+ return result[0].schema;
1218
+ }).then(toParseSchema);
1219
+ }
1220
+
1221
+ // TODO: remove the mongo format dependency in the return value
1222
+ async createObject(className, schema, object, transactionalSession) {
1223
+ debug('createObject');
1224
+ let columnsArray = [];
1225
+ const valuesArray = [];
1226
+ schema = toPostgresSchema(schema);
1227
+ const geoPoints = {};
1228
+ object = handleDotFields(object);
1229
+ validateKeys(object);
1230
+ Object.keys(object).forEach(fieldName => {
1231
+ if (object[fieldName] === null) {
1232
+ return;
1233
+ }
1234
+ var authDataMatch = fieldName.match(/^_auth_data_([a-zA-Z0-9_]+)$/);
1235
+ const authDataAlreadyExists = !!object.authData;
1236
+ if (authDataMatch) {
1237
+ var provider = authDataMatch[1];
1238
+ object['authData'] = object['authData'] || {};
1239
+ object['authData'][provider] = object[fieldName];
1240
+ delete object[fieldName];
1241
+ fieldName = 'authData';
1242
+ // Avoid adding authData multiple times to the query
1243
+ if (authDataAlreadyExists) {
1244
+ return;
1245
+ }
1246
+ }
1247
+ columnsArray.push(fieldName);
1248
+ if (!schema.fields[fieldName] && className === '_User') {
1249
+ if (fieldName === '_email_verify_token' || fieldName === '_failed_login_count' || fieldName === '_perishable_token' || fieldName === '_password_history') {
1250
+ valuesArray.push(object[fieldName]);
1251
+ }
1252
+ if (fieldName === '_email_verify_token_expires_at') {
1253
+ if (object[fieldName]) {
1254
+ valuesArray.push(object[fieldName].iso);
1255
+ } else {
1256
+ valuesArray.push(null);
1257
+ }
1258
+ }
1259
+ if (fieldName === '_account_lockout_expires_at' || fieldName === '_perishable_token_expires_at' || fieldName === '_password_changed_at') {
1260
+ if (object[fieldName]) {
1261
+ valuesArray.push(object[fieldName].iso);
1262
+ } else {
1263
+ valuesArray.push(null);
1264
+ }
1265
+ }
1266
+ return;
1267
+ }
1268
+ switch (schema.fields[fieldName].type) {
1269
+ case 'Date':
1270
+ if (object[fieldName]) {
1271
+ valuesArray.push(object[fieldName].iso);
1272
+ } else {
1273
+ valuesArray.push(null);
1274
+ }
1275
+ break;
1276
+ case 'Pointer':
1277
+ valuesArray.push(object[fieldName].objectId);
1278
+ break;
1279
+ case 'Array':
1280
+ if (['_rperm', '_wperm'].indexOf(fieldName) >= 0) {
1281
+ valuesArray.push(object[fieldName]);
1282
+ } else {
1283
+ valuesArray.push(JSON.stringify(object[fieldName]));
1284
+ }
1285
+ break;
1286
+ case 'Object':
1287
+ case 'Bytes':
1288
+ case 'String':
1289
+ case 'Number':
1290
+ case 'Boolean':
1291
+ valuesArray.push(object[fieldName]);
1292
+ break;
1293
+ case 'File':
1294
+ valuesArray.push(object[fieldName].name);
1295
+ break;
1296
+ case 'Polygon':
1297
+ {
1298
+ const value = convertPolygonToSQL(object[fieldName].coordinates);
1299
+ valuesArray.push(value);
1300
+ break;
1301
+ }
1302
+ case 'GeoPoint':
1303
+ // pop the point and process later
1304
+ geoPoints[fieldName] = object[fieldName];
1305
+ columnsArray.pop();
1306
+ break;
1307
+ default:
1308
+ throw `Type ${schema.fields[fieldName].type} not supported yet`;
1309
+ }
1310
+ });
1311
+ columnsArray = columnsArray.concat(Object.keys(geoPoints));
1312
+ const initialValues = valuesArray.map((val, index) => {
1313
+ let termination = '';
1314
+ const fieldName = columnsArray[index];
1315
+ if (['_rperm', '_wperm'].indexOf(fieldName) >= 0) {
1316
+ termination = '::text[]';
1317
+ } else if (schema.fields[fieldName] && schema.fields[fieldName].type === 'Array') {
1318
+ termination = '::jsonb';
1319
+ }
1320
+ return `$${index + 2 + columnsArray.length}${termination}`;
1321
+ });
1322
+ const geoPointsInjects = Object.keys(geoPoints).map(key => {
1323
+ const value = geoPoints[key];
1324
+ valuesArray.push(value.longitude, value.latitude);
1325
+ const l = valuesArray.length + columnsArray.length;
1326
+ return `POINT($${l}, $${l + 1})`;
1327
+ });
1328
+ const columnsPattern = columnsArray.map((col, index) => `$${index + 2}:name`).join();
1329
+ const valuesPattern = initialValues.concat(geoPointsInjects).join();
1330
+ const qs = `INSERT INTO $1:name (${columnsPattern}) VALUES (${valuesPattern})`;
1331
+ const values = [className, ...columnsArray, ...valuesArray];
1332
+ const promise = (transactionalSession ? transactionalSession.t : this._client).none(qs, values).then(() => ({
1333
+ ops: [object]
1334
+ })).catch(error => {
1335
+ if (error.code === PostgresUniqueIndexViolationError) {
1336
+ const err = new _node.default.Error(_node.default.Error.DUPLICATE_VALUE, 'A duplicate value for a field with unique values was provided');
1337
+ err.underlyingError = error;
1338
+ if (error.constraint) {
1339
+ // Check for authData unique index violations first
1340
+ const authDataMatch = error.constraint.match(/_User_unique_authData_([a-zA-Z0-9_]+)_id/);
1341
+ if (authDataMatch) {
1342
+ err.userInfo = {
1343
+ duplicated_field: `_auth_data_${authDataMatch[1]}`
1344
+ };
1345
+ } else {
1346
+ const matches = error.constraint.match(/unique_([a-zA-Z]+)/);
1347
+ if (matches && Array.isArray(matches)) {
1348
+ err.userInfo = {
1349
+ duplicated_field: matches[1]
1350
+ };
1351
+ }
1352
+ }
1353
+ }
1354
+ error = err;
1355
+ }
1356
+ throw error;
1357
+ });
1358
+ if (transactionalSession) {
1359
+ transactionalSession.batch.push(promise);
1360
+ }
1361
+ return promise;
1362
+ }
1363
+
1364
+ // Remove all objects that match the given Parse Query.
1365
+ // If no objects match, reject with OBJECT_NOT_FOUND. If objects are found and deleted, resolve with undefined.
1366
+ // If there is some other error, reject with INTERNAL_SERVER_ERROR.
1367
+ async deleteObjectsByQuery(className, schema, query, transactionalSession) {
1368
+ debug('deleteObjectsByQuery');
1369
+ const values = [className];
1370
+ const index = 2;
1371
+ const where = buildWhereClause({
1372
+ schema,
1373
+ index,
1374
+ query,
1375
+ caseInsensitive: false
1376
+ });
1377
+ values.push(...where.values);
1378
+ if (Object.keys(query).length === 0) {
1379
+ where.pattern = 'TRUE';
1380
+ }
1381
+ const qs = `WITH deleted AS (DELETE FROM $1:name WHERE ${where.pattern} RETURNING *) SELECT count(*) FROM deleted`;
1382
+ const promise = (transactionalSession ? transactionalSession.t : this._client).one(qs, values, a => +a.count).then(count => {
1383
+ if (count === 0) {
1384
+ throw new _node.default.Error(_node.default.Error.OBJECT_NOT_FOUND, 'Object not found.');
1385
+ } else {
1386
+ return count;
1387
+ }
1388
+ }).catch(error => {
1389
+ if (error.code !== PostgresRelationDoesNotExistError) {
1390
+ throw error;
1391
+ }
1392
+ // ELSE: Don't delete anything if doesn't exist
1393
+ });
1394
+ if (transactionalSession) {
1395
+ transactionalSession.batch.push(promise);
1396
+ }
1397
+ return promise;
1398
+ }
1399
+ // Return value not currently well specified.
1400
+ async findOneAndUpdate(className, schema, query, update, transactionalSession) {
1401
+ debug('findOneAndUpdate');
1402
+ return this.updateObjectsByQuery(className, schema, query, update, transactionalSession).then(val => val[0]);
1403
+ }
1404
+
1405
+ // Apply the update to all objects that match the given Parse Query.
1406
+ async updateObjectsByQuery(className, schema, query, update, transactionalSession) {
1407
+ debug('updateObjectsByQuery');
1408
+ const updatePatterns = [];
1409
+ const values = [className];
1410
+ let index = 2;
1411
+ schema = toPostgresSchema(schema);
1412
+ const originalUpdate = {
1413
+ ...update
1414
+ };
1415
+
1416
+ // Set flag for dot notation fields
1417
+ const dotNotationOptions = {};
1418
+ Object.keys(update).forEach(fieldName => {
1419
+ if (fieldName.indexOf('.') > -1) {
1420
+ const components = fieldName.split('.');
1421
+ const first = components.shift();
1422
+ dotNotationOptions[first] = true;
1423
+ } else {
1424
+ dotNotationOptions[fieldName] = false;
1425
+ }
1426
+ });
1427
+ update = handleDotFields(update);
1428
+ // Resolve authData first,
1429
+ // So we don't end up with multiple key updates
1430
+ for (const fieldName in update) {
1431
+ const authDataMatch = fieldName.match(/^_auth_data_([a-zA-Z0-9_]+)$/);
1432
+ if (authDataMatch) {
1433
+ var provider = authDataMatch[1];
1434
+ const value = update[fieldName];
1435
+ delete update[fieldName];
1436
+ update['authData'] = update['authData'] || {};
1437
+ update['authData'][provider] = value;
1438
+ }
1439
+ }
1440
+ for (const fieldName in update) {
1441
+ const fieldValue = update[fieldName];
1442
+ // Drop any undefined values.
1443
+ if (typeof fieldValue === 'undefined') {
1444
+ delete update[fieldName];
1445
+ } else if (fieldValue === null) {
1446
+ updatePatterns.push(`$${index}:name = NULL`);
1447
+ values.push(fieldName);
1448
+ index += 1;
1449
+ } else if (fieldName == 'authData') {
1450
+ // This recursively sets the json_object
1451
+ // Only 1 level deep
1452
+ const generate = (jsonb, key, value) => {
1453
+ return `json_object_set_key(COALESCE(${jsonb}, '{}'::jsonb), ${key}, ${value})::jsonb`;
1454
+ };
1455
+ const generateRemove = (jsonb, key) => {
1456
+ return `(COALESCE(${jsonb}, '{}'::jsonb) - ${key})`;
1457
+ };
1458
+ const lastKey = `$${index}:name`;
1459
+ const fieldNameIndex = index;
1460
+ index += 1;
1461
+ values.push(fieldName);
1462
+ const update = Object.keys(fieldValue).reduce((lastKey, key) => {
1463
+ let value = fieldValue[key];
1464
+ if (value && value.__op === 'Delete') {
1465
+ value = null;
1466
+ }
1467
+ if (value === null) {
1468
+ const str = generateRemove(lastKey, `$${index}::text`);
1469
+ values.push(key);
1470
+ index += 1;
1471
+ return str;
1472
+ }
1473
+ const str = generate(lastKey, `$${index}::text`, `$${index + 1}::jsonb`);
1474
+ index += 2;
1475
+ if (value) {
1476
+ value = JSON.stringify(value);
1477
+ }
1478
+ values.push(key, value);
1479
+ return str;
1480
+ }, lastKey);
1481
+ updatePatterns.push(`$${fieldNameIndex}:name = ${update}`);
1482
+ } else if (fieldValue.__op === 'Increment') {
1483
+ updatePatterns.push(`$${index}:name = COALESCE($${index}:name, 0) + $${index + 1}`);
1484
+ values.push(fieldName, fieldValue.amount);
1485
+ index += 2;
1486
+ } else if (fieldValue.__op === 'Add') {
1487
+ updatePatterns.push(`$${index}:name = array_add(COALESCE($${index}:name, '[]'::jsonb), $${index + 1}::jsonb)`);
1488
+ values.push(fieldName, JSON.stringify(fieldValue.objects));
1489
+ index += 2;
1490
+ } else if (fieldValue.__op === 'Delete') {
1491
+ updatePatterns.push(`$${index}:name = $${index + 1}`);
1492
+ values.push(fieldName, null);
1493
+ index += 2;
1494
+ } else if (fieldValue.__op === 'Remove') {
1495
+ updatePatterns.push(`$${index}:name = array_remove(COALESCE($${index}:name, '[]'::jsonb), $${index + 1}::jsonb)`);
1496
+ values.push(fieldName, JSON.stringify(fieldValue.objects));
1497
+ index += 2;
1498
+ } else if (fieldValue.__op === 'AddUnique') {
1499
+ updatePatterns.push(`$${index}:name = array_add_unique(COALESCE($${index}:name, '[]'::jsonb), $${index + 1}::jsonb)`);
1500
+ values.push(fieldName, JSON.stringify(fieldValue.objects));
1501
+ index += 2;
1502
+ } else if (fieldName === 'updatedAt') {
1503
+ //TODO: stop special casing this. It should check for __type === 'Date' and use .iso
1504
+ updatePatterns.push(`$${index}:name = $${index + 1}`);
1505
+ values.push(fieldName, fieldValue);
1506
+ index += 2;
1507
+ } else if (typeof fieldValue === 'string') {
1508
+ updatePatterns.push(`$${index}:name = $${index + 1}`);
1509
+ values.push(fieldName, fieldValue);
1510
+ index += 2;
1511
+ } else if (typeof fieldValue === 'boolean') {
1512
+ updatePatterns.push(`$${index}:name = $${index + 1}`);
1513
+ values.push(fieldName, fieldValue);
1514
+ index += 2;
1515
+ } else if (fieldValue.__type === 'Pointer') {
1516
+ updatePatterns.push(`$${index}:name = $${index + 1}`);
1517
+ values.push(fieldName, fieldValue.objectId);
1518
+ index += 2;
1519
+ } else if (fieldValue.__type === 'Date') {
1520
+ updatePatterns.push(`$${index}:name = $${index + 1}`);
1521
+ values.push(fieldName, toPostgresValue(fieldValue));
1522
+ index += 2;
1523
+ } else if (Utils.isDate(fieldValue)) {
1524
+ updatePatterns.push(`$${index}:name = $${index + 1}`);
1525
+ values.push(fieldName, fieldValue);
1526
+ index += 2;
1527
+ } else if (fieldValue.__type === 'File') {
1528
+ updatePatterns.push(`$${index}:name = $${index + 1}`);
1529
+ values.push(fieldName, toPostgresValue(fieldValue));
1530
+ index += 2;
1531
+ } else if (fieldValue.__type === 'GeoPoint') {
1532
+ updatePatterns.push(`$${index}:name = POINT($${index + 1}, $${index + 2})`);
1533
+ values.push(fieldName, fieldValue.longitude, fieldValue.latitude);
1534
+ index += 3;
1535
+ } else if (fieldValue.__type === 'Polygon') {
1536
+ const value = convertPolygonToSQL(fieldValue.coordinates);
1537
+ updatePatterns.push(`$${index}:name = $${index + 1}::polygon`);
1538
+ values.push(fieldName, value);
1539
+ index += 2;
1540
+ } else if (fieldValue.__type === 'Relation') {
1541
+ // noop
1542
+ } else if (typeof fieldValue === 'number') {
1543
+ updatePatterns.push(`$${index}:name = $${index + 1}`);
1544
+ values.push(fieldName, fieldValue);
1545
+ index += 2;
1546
+ } else if (typeof fieldValue === 'object' && schema.fields[fieldName] && schema.fields[fieldName].type === 'Object') {
1547
+ // Gather keys to increment
1548
+ const keysToIncrement = Object.keys(originalUpdate).filter(k => {
1549
+ // choose top level fields that have a delete operation set
1550
+ // Note that Object.keys is iterating over the **original** update object
1551
+ // and that some of the keys of the original update could be null or undefined:
1552
+ // (See the above check `if (fieldValue === null || typeof fieldValue == "undefined")`)
1553
+ const value = originalUpdate[k];
1554
+ return value && value.__op === 'Increment' && k.split('.').length === 2 && k.split('.')[0] === fieldName;
1555
+ }).map(k => k.split('.')[1]);
1556
+ let incrementPatterns = '';
1557
+ const incrementValues = [];
1558
+ if (keysToIncrement.length > 0) {
1559
+ incrementPatterns = ' || ' + keysToIncrement.map(c => {
1560
+ const amount = fieldValue[c].amount;
1561
+ if (typeof amount !== 'number') {
1562
+ throw new _node.default.Error(_node.default.Error.INVALID_JSON, 'incrementing must provide a number');
1563
+ }
1564
+ incrementValues.push(amount);
1565
+ const amountIndex = index + incrementValues.length;
1566
+ const jsonSafeName = escapeSqlString(escapeJsonString(c));
1567
+ const sqlSafeName = escapeSqlString(c);
1568
+ return `CONCAT('{"${jsonSafeName}":', COALESCE($${index}:name->>'${sqlSafeName}','0')::int + $${amountIndex}, '}')::jsonb`;
1569
+ }).join(' || ');
1570
+ // Strip the keys
1571
+ keysToIncrement.forEach(key => {
1572
+ delete fieldValue[key];
1573
+ });
1574
+ }
1575
+ const keysToDelete = Object.keys(originalUpdate).filter(k => {
1576
+ // choose top level fields that have a delete operation set.
1577
+ const value = originalUpdate[k];
1578
+ return value && value.__op === 'Delete' && k.split('.').length === 2 && k.split('.')[0] === fieldName;
1579
+ }).map(k => k.split('.')[1]);
1580
+ const deletePatterns = keysToDelete.reduce((p, c, i) => {
1581
+ return p + ` - '$${index + 1 + incrementValues.length + i}:value'`;
1582
+ }, '');
1583
+ // Override Object
1584
+ let updateObject = "'{}'::jsonb";
1585
+ if (dotNotationOptions[fieldName]) {
1586
+ // Merge Object
1587
+ updateObject = `COALESCE($${index}:name, '{}'::jsonb)`;
1588
+ }
1589
+ updatePatterns.push(`$${index}:name = (${updateObject} ${deletePatterns} ${incrementPatterns} || $${index + 1 + incrementValues.length + keysToDelete.length}::jsonb )`);
1590
+ values.push(fieldName, ...incrementValues, ...keysToDelete, JSON.stringify(fieldValue));
1591
+ index += 2 + incrementValues.length + keysToDelete.length;
1592
+ } else if (Array.isArray(fieldValue) && schema.fields[fieldName] && schema.fields[fieldName].type === 'Array') {
1593
+ const expectedType = parseTypeToPostgresType(schema.fields[fieldName]);
1594
+ if (expectedType === 'text[]') {
1595
+ updatePatterns.push(`$${index}:name = $${index + 1}::text[]`);
1596
+ values.push(fieldName, fieldValue);
1597
+ index += 2;
1598
+ } else {
1599
+ updatePatterns.push(`$${index}:name = $${index + 1}::jsonb`);
1600
+ values.push(fieldName, JSON.stringify(fieldValue));
1601
+ index += 2;
1602
+ }
1603
+ } else {
1604
+ debug('Not supported update', {
1605
+ fieldName,
1606
+ fieldValue
1607
+ });
1608
+ return Promise.reject(new _node.default.Error(_node.default.Error.OPERATION_FORBIDDEN, `Postgres doesn't support update ${JSON.stringify(fieldValue)} yet`));
1609
+ }
1610
+ }
1611
+ const where = buildWhereClause({
1612
+ schema,
1613
+ index,
1614
+ query,
1615
+ caseInsensitive: false
1616
+ });
1617
+ values.push(...where.values);
1618
+ const whereClause = where.pattern.length > 0 ? `WHERE ${where.pattern}` : '';
1619
+ const qs = `UPDATE $1:name SET ${updatePatterns.join()} ${whereClause} RETURNING *`;
1620
+ const promise = (transactionalSession ? transactionalSession.t : this._client).any(qs, values).catch(error => {
1621
+ if (error.code === PostgresUniqueIndexViolationError) {
1622
+ const err = new _node.default.Error(_node.default.Error.DUPLICATE_VALUE, 'A duplicate value for a field with unique values was provided');
1623
+ err.underlyingError = error;
1624
+ if (error.constraint) {
1625
+ const authDataMatch = error.constraint.match(/_User_unique_authData_([a-zA-Z0-9_]+)_id/);
1626
+ if (authDataMatch) {
1627
+ err.userInfo = {
1628
+ duplicated_field: `_auth_data_${authDataMatch[1]}`
1629
+ };
1630
+ } else {
1631
+ const matches = error.constraint.match(/unique_([a-zA-Z]+)/);
1632
+ if (matches && Array.isArray(matches)) {
1633
+ err.userInfo = {
1634
+ duplicated_field: matches[1]
1635
+ };
1636
+ }
1637
+ }
1638
+ }
1639
+ throw err;
1640
+ }
1641
+ throw error;
1642
+ });
1643
+ if (transactionalSession) {
1644
+ transactionalSession.batch.push(promise);
1645
+ }
1646
+ return promise;
1647
+ }
1648
+
1649
+ // Hopefully, we can get rid of this. It's only used for config and hooks.
1650
+ upsertOneObject(className, schema, query, update, transactionalSession) {
1651
+ debug('upsertOneObject');
1652
+ const createValue = Object.assign({}, query, update);
1653
+ return this.createObject(className, schema, createValue, transactionalSession).catch(error => {
1654
+ // ignore duplicate value errors as it's upsert
1655
+ if (error.code !== _node.default.Error.DUPLICATE_VALUE) {
1656
+ throw error;
1657
+ }
1658
+ return this.findOneAndUpdate(className, schema, query, update, transactionalSession);
1659
+ });
1660
+ }
1661
+ find(className, schema, query, {
1662
+ skip,
1663
+ limit,
1664
+ sort,
1665
+ keys,
1666
+ caseInsensitive,
1667
+ explain
1668
+ }) {
1669
+ debug('find');
1670
+ const hasLimit = limit !== undefined;
1671
+ const hasSkip = skip !== undefined;
1672
+ let values = [className];
1673
+ const where = buildWhereClause({
1674
+ schema,
1675
+ query,
1676
+ index: 2,
1677
+ caseInsensitive
1678
+ });
1679
+ values.push(...where.values);
1680
+ const wherePattern = where.pattern.length > 0 ? `WHERE ${where.pattern}` : '';
1681
+ const limitPattern = hasLimit ? `LIMIT $${values.length + 1}` : '';
1682
+ if (hasLimit) {
1683
+ values.push(limit);
1684
+ }
1685
+ const skipPattern = hasSkip ? `OFFSET $${values.length + 1}` : '';
1686
+ if (hasSkip) {
1687
+ values.push(skip);
1688
+ }
1689
+ let sortPattern = '';
1690
+ if (sort) {
1691
+ const sortCopy = sort;
1692
+ const sorting = Object.keys(sort).map(key => {
1693
+ const transformKey = transformDotFieldToComponents(key).join('->');
1694
+ // Using $idx pattern gives: non-integer constant in ORDER BY
1695
+ if (sortCopy[key] === 1) {
1696
+ return `${transformKey} ASC`;
1697
+ }
1698
+ return `${transformKey} DESC`;
1699
+ }).join();
1700
+ sortPattern = sort !== undefined && Object.keys(sort).length > 0 ? `ORDER BY ${sorting}` : '';
1701
+ }
1702
+ if (where.sorts && Object.keys(where.sorts).length > 0) {
1703
+ sortPattern = `ORDER BY ${where.sorts.join()}`;
1704
+ }
1705
+ let columns = '*';
1706
+ if (keys) {
1707
+ // Exclude empty keys
1708
+ // Replace ACL by it's keys
1709
+ keys = keys.reduce((memo, key) => {
1710
+ if (key === 'ACL') {
1711
+ memo.push('_rperm');
1712
+ memo.push('_wperm');
1713
+ } else if (key.length > 0 && (
1714
+ // Remove selected field not referenced in the schema
1715
+ // Relation is not a column in postgres
1716
+ // $score is a Parse special field and is also not a column
1717
+ schema.fields[key] && schema.fields[key].type !== 'Relation' || key === '$score')) {
1718
+ memo.push(key);
1719
+ }
1720
+ return memo;
1721
+ }, []);
1722
+ columns = keys.map((key, index) => {
1723
+ if (key === '$score') {
1724
+ return `ts_rank_cd(to_tsvector($${2}, $${3}:name), to_tsquery($${4}, $${5}), 32) as score`;
1725
+ }
1726
+ return `$${index + values.length + 1}:name`;
1727
+ }).join();
1728
+ values = values.concat(keys);
1729
+ }
1730
+ const originalQuery = `SELECT ${columns} FROM $1:name ${wherePattern} ${sortPattern} ${limitPattern} ${skipPattern}`;
1731
+ const qs = explain ? this.createExplainableQuery(originalQuery) : originalQuery;
1732
+ return this._client.any(qs, values).catch(error => {
1733
+ if (error.code !== PostgresRelationDoesNotExistError && error.code !== PostgresMissingColumnError) {
1734
+ throw error;
1735
+ }
1736
+ return [];
1737
+ }).then(results => {
1738
+ if (explain) {
1739
+ return results;
1740
+ }
1741
+ return results.map(object => this.postgresObjectToParseObject(className, object, schema));
1742
+ });
1743
+ }
1744
+
1745
+ // Converts from a postgres-format object to a REST-format object.
1746
+ // Does not strip out anything based on a lack of authentication.
1747
+ postgresObjectToParseObject(className, object, schema) {
1748
+ Object.keys(schema.fields).forEach(fieldName => {
1749
+ if (schema.fields[fieldName].type === 'Pointer' && object[fieldName]) {
1750
+ object[fieldName] = {
1751
+ objectId: object[fieldName],
1752
+ __type: 'Pointer',
1753
+ className: schema.fields[fieldName].targetClass
1754
+ };
1755
+ }
1756
+ if (schema.fields[fieldName].type === 'Relation') {
1757
+ object[fieldName] = {
1758
+ __type: 'Relation',
1759
+ className: schema.fields[fieldName].targetClass
1760
+ };
1761
+ }
1762
+ if (object[fieldName] && schema.fields[fieldName].type === 'GeoPoint') {
1763
+ object[fieldName] = {
1764
+ __type: 'GeoPoint',
1765
+ latitude: object[fieldName].y,
1766
+ longitude: object[fieldName].x
1767
+ };
1768
+ }
1769
+ if (object[fieldName] && schema.fields[fieldName].type === 'Polygon') {
1770
+ let coords = new String(object[fieldName]);
1771
+ coords = coords.substring(2, coords.length - 2).split('),(');
1772
+ const updatedCoords = coords.map(point => {
1773
+ return [parseFloat(point.split(',')[1]), parseFloat(point.split(',')[0])];
1774
+ });
1775
+ object[fieldName] = {
1776
+ __type: 'Polygon',
1777
+ coordinates: updatedCoords
1778
+ };
1779
+ }
1780
+ if (object[fieldName] && schema.fields[fieldName].type === 'File') {
1781
+ object[fieldName] = {
1782
+ __type: 'File',
1783
+ name: object[fieldName]
1784
+ };
1785
+ }
1786
+ });
1787
+ //TODO: remove this reliance on the mongo format. DB adapter shouldn't know there is a difference between created at and any other date field.
1788
+ if (object.createdAt) {
1789
+ object.createdAt = object.createdAt.toISOString();
1790
+ }
1791
+ if (object.updatedAt) {
1792
+ object.updatedAt = object.updatedAt.toISOString();
1793
+ }
1794
+ if (object.expiresAt) {
1795
+ object.expiresAt = {
1796
+ __type: 'Date',
1797
+ iso: object.expiresAt.toISOString()
1798
+ };
1799
+ }
1800
+ if (object._email_verify_token_expires_at) {
1801
+ object._email_verify_token_expires_at = {
1802
+ __type: 'Date',
1803
+ iso: object._email_verify_token_expires_at.toISOString()
1804
+ };
1805
+ }
1806
+ if (object._account_lockout_expires_at) {
1807
+ object._account_lockout_expires_at = {
1808
+ __type: 'Date',
1809
+ iso: object._account_lockout_expires_at.toISOString()
1810
+ };
1811
+ }
1812
+ if (object._perishable_token_expires_at) {
1813
+ object._perishable_token_expires_at = {
1814
+ __type: 'Date',
1815
+ iso: object._perishable_token_expires_at.toISOString()
1816
+ };
1817
+ }
1818
+ if (object._password_changed_at) {
1819
+ object._password_changed_at = {
1820
+ __type: 'Date',
1821
+ iso: object._password_changed_at.toISOString()
1822
+ };
1823
+ }
1824
+ for (const fieldName in object) {
1825
+ if (object[fieldName] === null) {
1826
+ delete object[fieldName];
1827
+ }
1828
+ if (Utils.isDate(object[fieldName])) {
1829
+ object[fieldName] = {
1830
+ __type: 'Date',
1831
+ iso: object[fieldName].toISOString()
1832
+ };
1833
+ }
1834
+ }
1835
+ return object;
1836
+ }
1837
+
1838
+ // Create a unique index. Unique indexes on nullable fields are not allowed. Since we don't
1839
+ // currently know which fields are nullable and which aren't, we ignore that criteria.
1840
+ // As such, we shouldn't expose this function to users of parse until we have an out-of-band
1841
+ // Way of determining if a field is nullable. Undefined doesn't count against uniqueness,
1842
+ // which is why we use sparse indexes.
1843
+ async ensureUniqueness(className, schema, fieldNames) {
1844
+ const constraintName = `${className}_unique_${fieldNames.sort().join('_')}`;
1845
+ const constraintPatterns = fieldNames.map((fieldName, index) => `$${index + 3}:name`);
1846
+ const qs = `CREATE UNIQUE INDEX IF NOT EXISTS $2:name ON $1:name(${constraintPatterns.join()})`;
1847
+ return this._client.none(qs, [className, constraintName, ...fieldNames]).catch(error => {
1848
+ if (error.code === PostgresDuplicateRelationError && error.message.includes(constraintName)) {
1849
+ // Index already exists. Ignore error.
1850
+ } else if (error.code === PostgresUniqueIndexViolationError && error.message.includes(constraintName)) {
1851
+ // Cast the error into the proper parse error
1852
+ throw new _node.default.Error(_node.default.Error.DUPLICATE_VALUE, 'A duplicate value for a field with unique values was provided');
1853
+ } else {
1854
+ throw error;
1855
+ }
1856
+ });
1857
+ }
1858
+
1859
+ // Creates a unique index on authData-><provider>->>'id' to prevent
1860
+ // race conditions during concurrent signups with the same authData.
1861
+ async ensureAuthDataUniqueness(provider) {
1862
+ const indexName = `_User_unique_authData_${provider}_id`;
1863
+ const qs = `CREATE UNIQUE INDEX IF NOT EXISTS $1:name ON "_User" (("authData"->$2::text->>'id')) WHERE "authData"->$2::text->>'id' IS NOT NULL`;
1864
+ await this._client.none(qs, [indexName, provider]).catch(error => {
1865
+ if (error.code === PostgresDuplicateRelationError && error.message.includes(indexName)) {
1866
+ // Index already exists. Ignore error.
1867
+ } else if (error.code === PostgresUniqueIndexViolationError && error.message.includes(indexName)) {
1868
+ throw new _node.default.Error(_node.default.Error.DUPLICATE_VALUE, 'Tried to ensure field uniqueness for a class that already has duplicates.');
1869
+ } else {
1870
+ throw error;
1871
+ }
1872
+ });
1873
+ }
1874
+
1875
+ // Executes a count.
1876
+ async count(className, schema, query, readPreference, estimate = true) {
1877
+ debug('count');
1878
+ const values = [className];
1879
+ const where = buildWhereClause({
1880
+ schema,
1881
+ query,
1882
+ index: 2,
1883
+ caseInsensitive: false
1884
+ });
1885
+ values.push(...where.values);
1886
+ const wherePattern = where.pattern.length > 0 ? `WHERE ${where.pattern}` : '';
1887
+ let qs = '';
1888
+ if (where.pattern.length > 0 || !estimate) {
1889
+ qs = `SELECT count(*) FROM $1:name ${wherePattern}`;
1890
+ } else {
1891
+ qs = 'SELECT reltuples AS approximate_row_count FROM pg_class WHERE relname = $1';
1892
+ }
1893
+ return this._client.one(qs, values, a => {
1894
+ if (a.approximate_row_count == null || a.approximate_row_count == -1) {
1895
+ return !isNaN(+a.count) ? +a.count : 0;
1896
+ } else {
1897
+ return +a.approximate_row_count;
1898
+ }
1899
+ }).catch(error => {
1900
+ if (error.code !== PostgresRelationDoesNotExistError && error.code !== PostgresMissingColumnError) {
1901
+ throw error;
1902
+ }
1903
+ return 0;
1904
+ });
1905
+ }
1906
+ async distinct(className, schema, query, fieldName) {
1907
+ debug('distinct');
1908
+ const fieldSegments = fieldName.split('.');
1909
+ for (const segment of fieldSegments) {
1910
+ if (!segment.match(/^[a-zA-Z][a-zA-Z0-9_]*$/)) {
1911
+ throw new _node.default.Error(_node.default.Error.INVALID_KEY_NAME, `Invalid field name: ${fieldName}`);
1912
+ }
1913
+ }
1914
+ let field = fieldName;
1915
+ let column = fieldName;
1916
+ const isNested = fieldName.indexOf('.') >= 0;
1917
+ if (isNested) {
1918
+ field = transformDotFieldToComponents(fieldName).join('->');
1919
+ column = fieldSegments[0];
1920
+ }
1921
+ const isArrayField = schema.fields && schema.fields[fieldName] && schema.fields[fieldName].type === 'Array';
1922
+ const isPointerField = schema.fields && schema.fields[fieldName] && schema.fields[fieldName].type === 'Pointer';
1923
+ const values = [field, column, className];
1924
+ const where = buildWhereClause({
1925
+ schema,
1926
+ query,
1927
+ index: 4,
1928
+ caseInsensitive: false
1929
+ });
1930
+ values.push(...where.values);
1931
+ const wherePattern = where.pattern.length > 0 ? `WHERE ${where.pattern}` : '';
1932
+ const transformer = isArrayField ? 'jsonb_array_elements' : 'ON';
1933
+ let qs = `SELECT DISTINCT ${transformer}($1:name) $2:name FROM $3:name ${wherePattern}`;
1934
+ if (isNested) {
1935
+ qs = `SELECT DISTINCT ${transformer}($1:raw) $2:raw FROM $3:name ${wherePattern}`;
1936
+ }
1937
+ return this._client.any(qs, values).catch(error => {
1938
+ if (error.code === PostgresMissingColumnError) {
1939
+ return [];
1940
+ }
1941
+ throw error;
1942
+ }).then(results => {
1943
+ if (!isNested) {
1944
+ results = results.filter(object => object[field] !== null);
1945
+ return results.map(object => {
1946
+ if (!isPointerField) {
1947
+ return object[field];
1948
+ }
1949
+ return {
1950
+ __type: 'Pointer',
1951
+ className: schema.fields[fieldName].targetClass,
1952
+ objectId: object[field]
1953
+ };
1954
+ });
1955
+ }
1956
+ const child = fieldName.split('.')[1];
1957
+ return results.map(object => object[column][child]);
1958
+ }).then(results => results.map(object => this.postgresObjectToParseObject(className, object, schema)));
1959
+ }
1960
+ async aggregate(className, schema, pipeline, readPreference, hint, explain) {
1961
+ debug('aggregate');
1962
+ const values = [className];
1963
+ let index = 2;
1964
+ let columns = [];
1965
+ let countField = null;
1966
+ let groupValues = null;
1967
+ let wherePattern = '';
1968
+ let limitPattern = '';
1969
+ let skipPattern = '';
1970
+ let sortPattern = '';
1971
+ let groupPattern = '';
1972
+ for (let i = 0; i < pipeline.length; i += 1) {
1973
+ const stage = pipeline[i];
1974
+ if (stage.$group) {
1975
+ for (const field in stage.$group) {
1976
+ const value = stage.$group[field];
1977
+ if (value === null || value === undefined) {
1978
+ continue;
1979
+ }
1980
+ if (field === '_id' && typeof value === 'string' && value !== '') {
1981
+ columns.push(`$${index}:name AS "objectId"`);
1982
+ groupPattern = `GROUP BY $${index}:name`;
1983
+ values.push(transformAggregateField(value));
1984
+ index += 1;
1985
+ continue;
1986
+ }
1987
+ if (field === '_id' && typeof value === 'object' && Object.keys(value).length !== 0) {
1988
+ groupValues = value;
1989
+ const groupByFields = [];
1990
+ for (const alias in value) {
1991
+ if (typeof value[alias] === 'string' && value[alias]) {
1992
+ const source = transformAggregateField(value[alias]);
1993
+ if (!groupByFields.includes(`"${source}"`)) {
1994
+ groupByFields.push(`"${source}"`);
1995
+ }
1996
+ values.push(source, alias);
1997
+ columns.push(`$${index}:name AS $${index + 1}:name`);
1998
+ index += 2;
1999
+ } else {
2000
+ const operation = Object.keys(value[alias])[0];
2001
+ const source = transformAggregateField(value[alias][operation]);
2002
+ if (mongoAggregateToPostgres[operation]) {
2003
+ if (!groupByFields.includes(`"${source}"`)) {
2004
+ groupByFields.push(`"${source}"`);
2005
+ }
2006
+ columns.push(`EXTRACT(${mongoAggregateToPostgres[operation]} FROM $${index}:name AT TIME ZONE 'UTC')::integer AS $${index + 1}:name`);
2007
+ values.push(source, alias);
2008
+ index += 2;
2009
+ }
2010
+ }
2011
+ }
2012
+ groupPattern = `GROUP BY $${index}:raw`;
2013
+ values.push(groupByFields.join());
2014
+ index += 1;
2015
+ continue;
2016
+ }
2017
+ if (typeof value === 'object') {
2018
+ if (value.$sum) {
2019
+ if (typeof value.$sum === 'string') {
2020
+ columns.push(`SUM($${index}:name) AS $${index + 1}:name`);
2021
+ values.push(transformAggregateField(value.$sum), field);
2022
+ index += 2;
2023
+ } else {
2024
+ countField = field;
2025
+ columns.push(`COUNT(*) AS $${index}:name`);
2026
+ values.push(field);
2027
+ index += 1;
2028
+ }
2029
+ }
2030
+ if (value.$max) {
2031
+ columns.push(`MAX($${index}:name) AS $${index + 1}:name`);
2032
+ values.push(transformAggregateField(value.$max), field);
2033
+ index += 2;
2034
+ }
2035
+ if (value.$min) {
2036
+ columns.push(`MIN($${index}:name) AS $${index + 1}:name`);
2037
+ values.push(transformAggregateField(value.$min), field);
2038
+ index += 2;
2039
+ }
2040
+ if (value.$avg) {
2041
+ columns.push(`AVG($${index}:name) AS $${index + 1}:name`);
2042
+ values.push(transformAggregateField(value.$avg), field);
2043
+ index += 2;
2044
+ }
2045
+ }
2046
+ }
2047
+ } else {
2048
+ columns.push('*');
2049
+ }
2050
+ if (stage.$project) {
2051
+ if (columns.includes('*')) {
2052
+ columns = [];
2053
+ }
2054
+ for (const field in stage.$project) {
2055
+ const value = stage.$project[field];
2056
+ if (value === 1 || value === true) {
2057
+ columns.push(`$${index}:name`);
2058
+ values.push(field);
2059
+ index += 1;
2060
+ }
2061
+ }
2062
+ }
2063
+ if (stage.$match) {
2064
+ const patterns = [];
2065
+ const orOrAnd = Object.prototype.hasOwnProperty.call(stage.$match, '$or') ? ' OR ' : ' AND ';
2066
+ if (stage.$match.$or) {
2067
+ const collapse = {};
2068
+ stage.$match.$or.forEach(element => {
2069
+ for (const key in element) {
2070
+ collapse[key] = element[key];
2071
+ }
2072
+ });
2073
+ stage.$match = collapse;
2074
+ }
2075
+ for (let field in stage.$match) {
2076
+ const value = stage.$match[field];
2077
+ if (field === '_id') {
2078
+ field = 'objectId';
2079
+ }
2080
+ const matchPatterns = [];
2081
+ Object.keys(ParseToPosgresComparator).forEach(cmp => {
2082
+ if (value[cmp]) {
2083
+ const pgComparator = ParseToPosgresComparator[cmp];
2084
+ matchPatterns.push(`$${index}:name ${pgComparator} $${index + 1}`);
2085
+ values.push(field, toPostgresValue(value[cmp]));
2086
+ index += 2;
2087
+ }
2088
+ });
2089
+ if (matchPatterns.length > 0) {
2090
+ patterns.push(`(${matchPatterns.join(' AND ')})`);
2091
+ }
2092
+ if (schema.fields[field] && schema.fields[field].type && matchPatterns.length === 0) {
2093
+ patterns.push(`$${index}:name = $${index + 1}`);
2094
+ values.push(field, value);
2095
+ index += 2;
2096
+ }
2097
+ }
2098
+ wherePattern = patterns.length > 0 ? `WHERE ${patterns.join(` ${orOrAnd} `)}` : '';
2099
+ }
2100
+ if (stage.$limit) {
2101
+ limitPattern = `LIMIT $${index}`;
2102
+ values.push(stage.$limit);
2103
+ index += 1;
2104
+ }
2105
+ if (stage.$skip) {
2106
+ skipPattern = `OFFSET $${index}`;
2107
+ values.push(stage.$skip);
2108
+ index += 1;
2109
+ }
2110
+ if (stage.$sort) {
2111
+ const sort = stage.$sort;
2112
+ const keys = Object.keys(sort);
2113
+ const sorting = keys.map(key => {
2114
+ const transformer = sort[key] === 1 ? 'ASC' : 'DESC';
2115
+ const order = `$${index}:name ${transformer}`;
2116
+ index += 1;
2117
+ return order;
2118
+ }).join();
2119
+ values.push(...keys);
2120
+ sortPattern = sort !== undefined && sorting.length > 0 ? `ORDER BY ${sorting}` : '';
2121
+ }
2122
+ }
2123
+ if (groupPattern) {
2124
+ columns.forEach((e, i, a) => {
2125
+ if (e && e.trim() === '*') {
2126
+ a[i] = '';
2127
+ }
2128
+ });
2129
+ }
2130
+ const originalQuery = `SELECT ${columns.filter(Boolean).join()} FROM $1:name ${wherePattern} ${skipPattern} ${groupPattern} ${sortPattern} ${limitPattern}`;
2131
+ const qs = explain ? this.createExplainableQuery(originalQuery) : originalQuery;
2132
+ return this._client.any(qs, values).then(a => {
2133
+ if (explain) {
2134
+ return a;
2135
+ }
2136
+ const results = a.map(object => this.postgresObjectToParseObject(className, object, schema));
2137
+ results.forEach(result => {
2138
+ if (!Object.prototype.hasOwnProperty.call(result, 'objectId')) {
2139
+ result.objectId = null;
2140
+ }
2141
+ if (groupValues) {
2142
+ result.objectId = {};
2143
+ for (const key in groupValues) {
2144
+ result.objectId[key] = result[key];
2145
+ delete result[key];
2146
+ }
2147
+ }
2148
+ if (countField) {
2149
+ result[countField] = parseInt(result[countField], 10);
2150
+ }
2151
+ });
2152
+ return results;
2153
+ });
2154
+ }
2155
+ async performInitialization({
2156
+ VolatileClassesSchemas
2157
+ }) {
2158
+ // TODO: This method needs to be rewritten to make proper use of connections (@vitaly-t)
2159
+ debug('performInitialization');
2160
+ await this._ensureSchemaCollectionExists();
2161
+ const promises = VolatileClassesSchemas.map(schema => {
2162
+ return this.createTable(schema.className, schema).catch(err => {
2163
+ if (err.code === PostgresDuplicateRelationError || err.code === _node.default.Error.INVALID_CLASS_NAME) {
2164
+ return Promise.resolve();
2165
+ }
2166
+ throw err;
2167
+ }).then(() => this.schemaUpgrade(schema.className, schema));
2168
+ });
2169
+ promises.push(this._listenToSchema());
2170
+ return Promise.all(promises).then(() => {
2171
+ return this._client.tx('perform-initialization', async t => {
2172
+ await t.none(_sql.default.misc.jsonObjectSetKeys);
2173
+ await t.none(_sql.default.array.add);
2174
+ await t.none(_sql.default.array.addUnique);
2175
+ await t.none(_sql.default.array.remove);
2176
+ await t.none(_sql.default.array.containsAll);
2177
+ await t.none(_sql.default.array.containsAllRegex);
2178
+ await t.none(_sql.default.array.contains);
2179
+ return t.ctx;
2180
+ });
2181
+ }).then(ctx => {
2182
+ debug(`initializationDone in ${ctx.duration}`);
2183
+ }).catch(error => {
2184
+ // eslint-disable-next-line no-console
2185
+ console.error(error);
2186
+ });
2187
+ }
2188
+ async createIndexes(className, indexes, conn) {
2189
+ return (conn || this._client).tx(t => t.batch(indexes.map(i => {
2190
+ return t.none('CREATE INDEX IF NOT EXISTS $1:name ON $2:name ($3:name)', [i.name, className, i.key]);
2191
+ })));
2192
+ }
2193
+ async createIndexesIfNeeded(className, fieldName, type, conn) {
2194
+ await (conn || this._client).none('CREATE INDEX IF NOT EXISTS $1:name ON $2:name ($3:name)', [fieldName, className, type]);
2195
+ }
2196
+ async dropIndexes(className, indexes, conn) {
2197
+ const queries = indexes.map(i => ({
2198
+ query: 'DROP INDEX $1:name',
2199
+ values: i
2200
+ }));
2201
+ await (conn || this._client).tx(t => t.none(this._pgp.helpers.concat(queries)));
2202
+ }
2203
+ async getIndexes(className) {
2204
+ const qs = 'SELECT * FROM pg_indexes WHERE tablename = ${className}';
2205
+ return this._client.any(qs, {
2206
+ className
2207
+ });
2208
+ }
2209
+ async updateSchemaWithIndexes() {
2210
+ return Promise.resolve();
2211
+ }
2212
+
2213
+ // Used for testing purposes
2214
+ async updateEstimatedCount(className) {
2215
+ return this._client.none('ANALYZE $1:name', [className]);
2216
+ }
2217
+ async createTransactionalSession() {
2218
+ return new Promise(resolve => {
2219
+ const transactionalSession = {};
2220
+ transactionalSession.result = this._client.tx(t => {
2221
+ transactionalSession.t = t;
2222
+ transactionalSession.promise = new Promise(resolve => {
2223
+ transactionalSession.resolve = resolve;
2224
+ });
2225
+ transactionalSession.batch = [];
2226
+ resolve(transactionalSession);
2227
+ return transactionalSession.promise;
2228
+ });
2229
+ });
2230
+ }
2231
+ commitTransactionalSession(transactionalSession) {
2232
+ transactionalSession.resolve(transactionalSession.t.batch(transactionalSession.batch));
2233
+ return transactionalSession.result;
2234
+ }
2235
+ abortTransactionalSession(transactionalSession) {
2236
+ const result = transactionalSession.result.catch();
2237
+ transactionalSession.batch.push(Promise.reject());
2238
+ transactionalSession.resolve(transactionalSession.t.batch(transactionalSession.batch));
2239
+ return result;
2240
+ }
2241
+ async ensureIndex(className, schema, fieldNames, indexName, caseInsensitive = false, options = {}) {
2242
+ const conn = options.conn !== undefined ? options.conn : this._client;
2243
+ const defaultIndexName = `parse_default_${fieldNames.sort().join('_')}`;
2244
+ const indexNameOptions = indexName != null ? {
2245
+ name: indexName
2246
+ } : {
2247
+ name: defaultIndexName
2248
+ };
2249
+ const constraintPatterns = caseInsensitive ? fieldNames.map((fieldName, index) => `lower($${index + 3}:name) varchar_pattern_ops`) : fieldNames.map((fieldName, index) => `$${index + 3}:name`);
2250
+ const qs = `CREATE INDEX IF NOT EXISTS $1:name ON $2:name (${constraintPatterns.join()})`;
2251
+ const setIdempotencyFunction = options.setIdempotencyFunction !== undefined ? options.setIdempotencyFunction : false;
2252
+ if (setIdempotencyFunction) {
2253
+ await this.ensureIdempotencyFunctionExists(options);
2254
+ }
2255
+ await conn.none(qs, [indexNameOptions.name, className, ...fieldNames]).catch(error => {
2256
+ if (error.code === PostgresDuplicateRelationError && error.message.includes(indexNameOptions.name)) {
2257
+ // Index already exists. Ignore error.
2258
+ } else if (error.code === PostgresUniqueIndexViolationError && error.message.includes(indexNameOptions.name)) {
2259
+ // Cast the error into the proper parse error
2260
+ throw new _node.default.Error(_node.default.Error.DUPLICATE_VALUE, 'A duplicate value for a field with unique values was provided');
2261
+ } else {
2262
+ throw error;
2263
+ }
2264
+ });
2265
+ }
2266
+ async deleteIdempotencyFunction(options = {}) {
2267
+ const conn = options.conn !== undefined ? options.conn : this._client;
2268
+ const qs = 'DROP FUNCTION IF EXISTS idempotency_delete_expired_records()';
2269
+ return conn.none(qs).catch(error => {
2270
+ throw error;
2271
+ });
2272
+ }
2273
+ async ensureIdempotencyFunctionExists(options = {}) {
2274
+ const conn = options.conn !== undefined ? options.conn : this._client;
2275
+ const ttlOptions = options.ttl !== undefined ? `${options.ttl} seconds` : '60 seconds';
2276
+ const qs = 'CREATE OR REPLACE FUNCTION idempotency_delete_expired_records() RETURNS void LANGUAGE plpgsql AS $$ BEGIN DELETE FROM "_Idempotency" WHERE expire < NOW() - INTERVAL $1; END; $$;';
2277
+ return conn.none(qs, [ttlOptions]).catch(error => {
2278
+ throw error;
2279
+ });
2280
+ }
2281
+ }
2282
+ exports.PostgresStorageAdapter = PostgresStorageAdapter;
2283
+ function convertPolygonToSQL(polygon) {
2284
+ if (polygon.length < 3) {
2285
+ throw new _node.default.Error(_node.default.Error.INVALID_JSON, `Polygon must have at least 3 values`);
2286
+ }
2287
+ if (polygon[0][0] !== polygon[polygon.length - 1][0] || polygon[0][1] !== polygon[polygon.length - 1][1]) {
2288
+ polygon.push(polygon[0]);
2289
+ }
2290
+ const unique = polygon.filter((item, index, ar) => {
2291
+ let foundIndex = -1;
2292
+ for (let i = 0; i < ar.length; i += 1) {
2293
+ const pt = ar[i];
2294
+ if (pt[0] === item[0] && pt[1] === item[1]) {
2295
+ foundIndex = i;
2296
+ break;
2297
+ }
2298
+ }
2299
+ return foundIndex === index;
2300
+ });
2301
+ if (unique.length < 3) {
2302
+ throw new _node.default.Error(_node.default.Error.INTERNAL_SERVER_ERROR, 'GeoJSON: Loop must have at least 3 different vertices');
2303
+ }
2304
+ const points = polygon.map(point => {
2305
+ _node.default.GeoPoint._validate(parseFloat(point[1]), parseFloat(point[0]));
2306
+ return `(${point[1]}, ${point[0]})`;
2307
+ }).join(', ');
2308
+ return `(${points})`;
2309
+ }
2310
+ function removeWhiteSpace(regex) {
2311
+ if (!regex.endsWith('\n')) {
2312
+ regex += '\n';
2313
+ }
2314
+
2315
+ // remove non escaped comments
2316
+ return regex.replace(/([^\\])#.*\n/gim, '$1')
2317
+ // remove lines starting with a comment
2318
+ .replace(/^#.*\n/gim, '')
2319
+ // remove non escaped whitespace
2320
+ .replace(/([^\\])\s+/gim, '$1')
2321
+ // remove whitespace at the beginning of a line
2322
+ .replace(/^\s+/, '').trim();
2323
+ }
2324
+ function processRegexPattern(s) {
2325
+ if (s && s.startsWith('^')) {
2326
+ // regex for startsWith
2327
+ return '^' + literalizeRegexPart(s.slice(1));
2328
+ } else if (s && s.endsWith('$')) {
2329
+ // regex for endsWith
2330
+ return literalizeRegexPart(s.slice(0, s.length - 1)) + '$';
2331
+ }
2332
+
2333
+ // regex for contains
2334
+ return literalizeRegexPart(s);
2335
+ }
2336
+ function isStartsWithRegex(value) {
2337
+ if (!value || typeof value !== 'string' || !value.startsWith('^')) {
2338
+ return false;
2339
+ }
2340
+ const matches = value.match(/\^\\Q.*\\E/);
2341
+ return !!matches;
2342
+ }
2343
+ function isAllValuesRegexOrNone(values) {
2344
+ if (!values || !Array.isArray(values) || values.length === 0) {
2345
+ return true;
2346
+ }
2347
+ const firstValuesIsRegex = isStartsWithRegex(values[0].$regex);
2348
+ if (values.length === 1) {
2349
+ return firstValuesIsRegex;
2350
+ }
2351
+ for (let i = 1, length = values.length; i < length; ++i) {
2352
+ if (firstValuesIsRegex !== isStartsWithRegex(values[i].$regex)) {
2353
+ return false;
2354
+ }
2355
+ }
2356
+ return true;
2357
+ }
2358
+ function isAnyValueRegexStartsWith(values) {
2359
+ return values.some(function (value) {
2360
+ return isStartsWithRegex(value.$regex);
2361
+ });
2362
+ }
2363
+ function createLiteralRegex(remaining) {
2364
+ return remaining.split('').map(c => {
2365
+ const regex = RegExp('[0-9 ]|\\p{L}', 'u'); // Support all Unicode letter chars
2366
+ if (c.match(regex) !== null) {
2367
+ // Don't escape alphanumeric characters
2368
+ return c;
2369
+ }
2370
+ // Escape everything else (single quotes with single quotes, everything else with a backslash)
2371
+ return c === `'` ? `''` : `\\${c}`;
2372
+ }).join('');
2373
+ }
2374
+ function literalizeRegexPart(s) {
2375
+ const matcher1 = /\\Q((?!\\E).*)\\E$/;
2376
+ const result1 = s.match(matcher1);
2377
+ if (result1 && result1.length > 1 && result1.index > -1) {
2378
+ // Process Regex that has a beginning and an end specified for the literal text
2379
+ const prefix = s.substring(0, result1.index);
2380
+ const remaining = result1[1];
2381
+ return literalizeRegexPart(prefix) + createLiteralRegex(remaining);
2382
+ }
2383
+
2384
+ // Process Regex that has a beginning specified for the literal text
2385
+ const matcher2 = /\\Q((?!\\E).*)$/;
2386
+ const result2 = s.match(matcher2);
2387
+ if (result2 && result2.length > 1 && result2.index > -1) {
2388
+ const prefix = s.substring(0, result2.index);
2389
+ const remaining = result2[1];
2390
+ return literalizeRegexPart(prefix) + createLiteralRegex(remaining);
2391
+ }
2392
+
2393
+ // Remove problematic chars from remaining text
2394
+ return s
2395
+ // Remove all instances of \Q and \E
2396
+ .replace(/([^\\])(\\E)/, '$1').replace(/([^\\])(\\Q)/, '$1').replace(/^\\E/, '').replace(/^\\Q/, '')
2397
+ // Ensure even number of single quote sequences by adding an extra single quote if needed;
2398
+ // this ensures that every single quote is escaped
2399
+ .replace(/'+/g, match => {
2400
+ return match.length % 2 === 0 ? match : match + "'";
2401
+ });
2402
+ }
2403
+ var GeoPointCoder = {
2404
+ isValidJSON(value) {
2405
+ return typeof value === 'object' && value !== null && value.__type === 'GeoPoint';
2406
+ }
2407
+ };
2408
+ var _default = exports.default = PostgresStorageAdapter;
2409
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfUG9zdGdyZXNDbGllbnQiLCJyZXF1aXJlIiwiX25vZGUiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwiX2xvZGFzaCIsIl9jcnlwdG8iLCJfc3FsIiwiX1N0b3JhZ2VBZGFwdGVyIiwiZSIsIl9fZXNNb2R1bGUiLCJkZWZhdWx0IiwiVXRpbHMiLCJQb3N0Z3Jlc1JlbGF0aW9uRG9lc05vdEV4aXN0RXJyb3IiLCJQb3N0Z3Jlc0R1cGxpY2F0ZVJlbGF0aW9uRXJyb3IiLCJQb3N0Z3Jlc0R1cGxpY2F0ZUNvbHVtbkVycm9yIiwiUG9zdGdyZXNNaXNzaW5nQ29sdW1uRXJyb3IiLCJQb3N0Z3Jlc1VuaXF1ZUluZGV4VmlvbGF0aW9uRXJyb3IiLCJsb2dnZXIiLCJkZWJ1ZyIsImFyZ3MiLCJhcmd1bWVudHMiLCJjb25jYXQiLCJzbGljZSIsImxlbmd0aCIsImxvZyIsImdldExvZ2dlciIsImFwcGx5IiwicGFyc2VUeXBlVG9Qb3N0Z3Jlc1R5cGUiLCJ0eXBlIiwiY29udGVudHMiLCJKU09OIiwic3RyaW5naWZ5IiwiUGFyc2VUb1Bvc2dyZXNDb21wYXJhdG9yIiwiJGd0IiwiJGx0IiwiJGd0ZSIsIiRsdGUiLCJtb25nb0FnZ3JlZ2F0ZVRvUG9zdGdyZXMiLCIkZGF5T2ZNb250aCIsIiRkYXlPZldlZWsiLCIkZGF5T2ZZZWFyIiwiJGlzb0RheU9mV2VlayIsIiRpc29XZWVrWWVhciIsIiRob3VyIiwiJG1pbnV0ZSIsIiRzZWNvbmQiLCIkbWlsbGlzZWNvbmQiLCIkbW9udGgiLCIkd2VlayIsIiR5ZWFyIiwidG9Qb3N0Z3Jlc1ZhbHVlIiwidmFsdWUiLCJfX3R5cGUiLCJpc28iLCJuYW1lIiwidG9Qb3N0Z3Jlc1ZhbHVlQ2FzdFR5cGUiLCJwb3N0Z3Jlc1ZhbHVlIiwiY2FzdFR5cGUiLCJ1bmRlZmluZWQiLCJ0cmFuc2Zvcm1WYWx1ZSIsIm9iamVjdElkIiwiZW1wdHlDTFBTIiwiT2JqZWN0IiwiZnJlZXplIiwiZmluZCIsImdldCIsImNvdW50IiwiY3JlYXRlIiwidXBkYXRlIiwiZGVsZXRlIiwiYWRkRmllbGQiLCJwcm90ZWN0ZWRGaWVsZHMiLCJkZWZhdWx0Q0xQUyIsIkFDTCIsInJlYWQiLCJ3cml0ZSIsInRvUGFyc2VTY2hlbWEiLCJzY2hlbWEiLCJjbGFzc05hbWUiLCJmaWVsZHMiLCJfaGFzaGVkX3Bhc3N3b3JkIiwiX3dwZXJtIiwiX3JwZXJtIiwiY2xwcyIsImNsYXNzTGV2ZWxQZXJtaXNzaW9ucyIsImluZGV4ZXMiLCJ0b1Bvc3RncmVzU2NoZW1hIiwiX3Bhc3N3b3JkX2hpc3RvcnkiLCJpc0FycmF5SW5kZXgiLCJhcnJheUluZGV4IiwiQXJyYXkiLCJmcm9tIiwiZXZlcnkiLCJjIiwiaGFuZGxlRG90RmllbGRzIiwib2JqZWN0Iiwia2V5cyIsImZvckVhY2giLCJmaWVsZE5hbWUiLCJpbmRleE9mIiwiY29tcG9uZW50cyIsInNwbGl0IiwiZmlyc3QiLCJzaGlmdCIsImN1cnJlbnRPYmoiLCJuZXh0IiwiX19vcCIsImVzY2FwZVNxbFN0cmluZyIsInJlcGxhY2UiLCJlc2NhcGVKc29uU3RyaW5nIiwidHJhbnNmb3JtRG90RmllbGRUb0NvbXBvbmVudHMiLCJtYXAiLCJjbXB0IiwiaW5kZXgiLCJOdW1iZXIiLCJ0cmFuc2Zvcm1Eb3RGaWVsZCIsImpvaW4iLCJ2YWxpZGF0ZUFnZ3JlZ2F0ZUZpZWxkTmFtZSIsIm1hdGNoIiwiUGFyc2UiLCJFcnJvciIsIklOVkFMSURfS0VZX05BTUUiLCJ0cmFuc2Zvcm1BZ2dyZWdhdGVGaWVsZCIsInN0YXJ0c1dpdGgiLCJzdWJzdHJpbmciLCJ2YWxpZGF0ZUtleXMiLCJrZXkiLCJpbmNsdWRlcyIsIklOVkFMSURfTkVTVEVEX0tFWSIsImpvaW5UYWJsZXNGb3JTY2hlbWEiLCJsaXN0IiwiZmllbGQiLCJwdXNoIiwiYnVpbGRXaGVyZUNsYXVzZSIsInF1ZXJ5IiwiY2FzZUluc2Vuc2l0aXZlIiwicGF0dGVybnMiLCJ2YWx1ZXMiLCJzb3J0cyIsImlzQXJyYXlGaWVsZCIsImluaXRpYWxQYXR0ZXJuc0xlbmd0aCIsImZpZWxkVmFsdWUiLCIkZXhpc3RzIiwiYXV0aERhdGFNYXRjaCIsIiRpbiIsIiRyZWdleCIsInNvbWUiLCJNQVhfSU5UX1BMVVNfT05FIiwiY2xhdXNlcyIsImNsYXVzZVZhbHVlcyIsInN1YlF1ZXJ5IiwiY2xhdXNlIiwicGF0dGVybiIsIm9yT3JBbmQiLCJub3QiLCIkbmUiLCJjb25zdHJhaW50RmllbGROYW1lIiwiJHJlbGF0aXZlVGltZSIsIklOVkFMSURfSlNPTiIsInBvaW50IiwibG9uZ2l0dWRlIiwibGF0aXR1ZGUiLCIkZXEiLCJpc0luT3JOaW4iLCJpc0FycmF5IiwiJG5pbiIsImluUGF0dGVybnMiLCJhbGxvd051bGwiLCJsaXN0RWxlbSIsImxpc3RJbmRleCIsImNyZWF0ZUNvbnN0cmFpbnQiLCJiYXNlQXJyYXkiLCJub3RJbiIsImZpZWxkVHlwZSIsIm9wZXJhdG9yTmFtZSIsImVsZW0iLCJJTlZBTElEX1FVRVJZIiwiXyIsImZsYXRNYXAiLCJlbHQiLCIkYWxsIiwiaXNBbnlWYWx1ZVJlZ2V4U3RhcnRzV2l0aCIsImlzQWxsVmFsdWVzUmVnZXhPck5vbmUiLCJpIiwicHJvY2Vzc1JlZ2V4UGF0dGVybiIsIiRjb250YWluZWRCeSIsImFyciIsIiR0ZXh0Iiwic2VhcmNoIiwiJHNlYXJjaCIsImxhbmd1YWdlIiwiJHRlcm0iLCIkbGFuZ3VhZ2UiLCIkY2FzZVNlbnNpdGl2ZSIsIiRkaWFjcml0aWNTZW5zaXRpdmUiLCIkbmVhclNwaGVyZSIsImRpc3RhbmNlIiwiJG1heERpc3RhbmNlIiwiZGlzdGFuY2VJbktNIiwiJHdpdGhpbiIsIiRib3giLCJib3giLCJsZWZ0IiwiYm90dG9tIiwicmlnaHQiLCJ0b3AiLCIkZ2VvV2l0aGluIiwiJGNlbnRlclNwaGVyZSIsImNlbnRlclNwaGVyZSIsIkdlb1BvaW50IiwiR2VvUG9pbnRDb2RlciIsImlzVmFsaWRKU09OIiwiX3ZhbGlkYXRlIiwiaXNOYU4iLCIkcG9seWdvbiIsInBvbHlnb24iLCJwb2ludHMiLCJjb29yZGluYXRlcyIsIiRnZW9JbnRlcnNlY3RzIiwiJHBvaW50IiwicmVnZXgiLCJvcGVyYXRvciIsIm9wdHMiLCIkb3B0aW9ucyIsInJlbW92ZVdoaXRlU3BhY2UiLCJjb252ZXJ0UG9seWdvblRvU1FMIiwiY21wIiwicGdDb21wYXJhdG9yIiwicGFyc2VyUmVzdWx0IiwicmVsYXRpdmVUaW1lVG9EYXRlIiwic3RhdHVzIiwicmVzdWx0IiwiY29uc29sZSIsImVycm9yIiwiaW5mbyIsIk9QRVJBVElPTl9GT1JCSURERU4iLCJQb3N0Z3Jlc1N0b3JhZ2VBZGFwdGVyIiwiY29uc3RydWN0b3IiLCJ1cmkiLCJjb2xsZWN0aW9uUHJlZml4IiwiZGF0YWJhc2VPcHRpb25zIiwib3B0aW9ucyIsIl9jb2xsZWN0aW9uUHJlZml4IiwiZW5hYmxlU2NoZW1hSG9va3MiLCJkaXNhYmxlSW5kZXhGaWVsZFZhbGlkYXRpb24iLCJzY2hlbWFDYWNoZVR0bCIsImNsaWVudCIsInBncCIsImNyZWF0ZUNsaWVudCIsIl9jbGllbnQiLCJfb25jaGFuZ2UiLCJfcGdwIiwiX3V1aWQiLCJyYW5kb21VVUlEIiwiY2FuU29ydE9uSm9pblRhYmxlcyIsIndhdGNoIiwiY2FsbGJhY2siLCJjcmVhdGVFeHBsYWluYWJsZVF1ZXJ5IiwiYW5hbHl6ZSIsImhhbmRsZVNodXRkb3duIiwiX3N0cmVhbSIsImRvbmUiLCIkcG9vbCIsImVuZCIsIl9saXN0ZW5Ub1NjaGVtYSIsImNvbm5lY3QiLCJkaXJlY3QiLCJvbiIsImRhdGEiLCJwYXlsb2FkIiwicGFyc2UiLCJzZW5kZXJJZCIsIm5vbmUiLCJfbm90aWZ5U2NoZW1hQ2hhbmdlIiwiY2F0Y2giLCJfZW5zdXJlU2NoZW1hQ29sbGVjdGlvbkV4aXN0cyIsImNvbm4iLCJjbGFzc0V4aXN0cyIsIm9uZSIsImEiLCJleGlzdHMiLCJzZXRDbGFzc0xldmVsUGVybWlzc2lvbnMiLCJDTFBzIiwidGFzayIsInQiLCJzZXRJbmRleGVzV2l0aFNjaGVtYUZvcm1hdCIsInN1Ym1pdHRlZEluZGV4ZXMiLCJleGlzdGluZ0luZGV4ZXMiLCJzZWxmIiwiUHJvbWlzZSIsInJlc29sdmUiLCJfaWRfIiwiX2lkIiwiZGVsZXRlZEluZGV4ZXMiLCJpbnNlcnRlZEluZGV4ZXMiLCJwcm90b3R5cGUiLCJoYXNPd25Qcm9wZXJ0eSIsImNhbGwiLCJ0eCIsImNyZWF0ZUluZGV4ZXMiLCJjb2x1bW5Eb2VzTm90RXhpc3RFcnJvciIsImdldEVycm9ycyIsImNvZGUiLCJkcm9wSW5kZXhlcyIsImNyZWF0ZUNsYXNzIiwicGFyc2VTY2hlbWEiLCJjcmVhdGVUYWJsZSIsImVyciIsImRldGFpbCIsIkRVUExJQ0FURV9WQUxVRSIsInZhbHVlc0FycmF5IiwicGF0dGVybnNBcnJheSIsImFzc2lnbiIsIl9lbWFpbF92ZXJpZnlfdG9rZW5fZXhwaXJlc19hdCIsIl9lbWFpbF92ZXJpZnlfdG9rZW4iLCJfYWNjb3VudF9sb2Nrb3V0X2V4cGlyZXNfYXQiLCJfZmFpbGVkX2xvZ2luX2NvdW50IiwiX3BlcmlzaGFibGVfdG9rZW4iLCJfcGVyaXNoYWJsZV90b2tlbl9leHBpcmVzX2F0IiwiX3Bhc3N3b3JkX2NoYW5nZWRfYXQiLCJyZWxhdGlvbnMiLCJwYXJzZVR5cGUiLCJxcyIsImJhdGNoIiwiam9pblRhYmxlIiwic2NoZW1hVXBncmFkZSIsImNvbHVtbnMiLCJjb2x1bW5fbmFtZSIsIm5ld0NvbHVtbnMiLCJmaWx0ZXIiLCJpdGVtIiwiYWRkRmllbGRJZk5vdEV4aXN0cyIsInBvc3RncmVzVHlwZSIsImFueSIsInBhdGgiLCJ1cGRhdGVGaWVsZE9wdGlvbnMiLCJkZWxldGVDbGFzcyIsIm9wZXJhdGlvbnMiLCJyZXNwb25zZSIsImhlbHBlcnMiLCJ0aGVuIiwiZGVsZXRlQWxsQ2xhc3NlcyIsIm5vdyIsIkRhdGUiLCJnZXRUaW1lIiwiZW5kZWQiLCJyZXN1bHRzIiwiam9pbnMiLCJyZWR1Y2UiLCJjbGFzc2VzIiwicXVlcmllcyIsImRlbGV0ZUZpZWxkcyIsImZpZWxkTmFtZXMiLCJpZHgiLCJnZXRBbGxDbGFzc2VzIiwicm93IiwiZ2V0Q2xhc3MiLCJjcmVhdGVPYmplY3QiLCJ0cmFuc2FjdGlvbmFsU2Vzc2lvbiIsImNvbHVtbnNBcnJheSIsImdlb1BvaW50cyIsImF1dGhEYXRhQWxyZWFkeUV4aXN0cyIsImF1dGhEYXRhIiwicHJvdmlkZXIiLCJwb3AiLCJpbml0aWFsVmFsdWVzIiwidmFsIiwidGVybWluYXRpb24iLCJnZW9Qb2ludHNJbmplY3RzIiwibCIsImNvbHVtbnNQYXR0ZXJuIiwiY29sIiwidmFsdWVzUGF0dGVybiIsInByb21pc2UiLCJvcHMiLCJ1bmRlcmx5aW5nRXJyb3IiLCJjb25zdHJhaW50IiwidXNlckluZm8iLCJkdXBsaWNhdGVkX2ZpZWxkIiwibWF0Y2hlcyIsImRlbGV0ZU9iamVjdHNCeVF1ZXJ5Iiwid2hlcmUiLCJPQkpFQ1RfTk9UX0ZPVU5EIiwiZmluZE9uZUFuZFVwZGF0ZSIsInVwZGF0ZU9iamVjdHNCeVF1ZXJ5IiwidXBkYXRlUGF0dGVybnMiLCJvcmlnaW5hbFVwZGF0ZSIsImRvdE5vdGF0aW9uT3B0aW9ucyIsImdlbmVyYXRlIiwianNvbmIiLCJnZW5lcmF0ZVJlbW92ZSIsImxhc3RLZXkiLCJmaWVsZE5hbWVJbmRleCIsInN0ciIsImFtb3VudCIsIm9iamVjdHMiLCJpc0RhdGUiLCJrZXlzVG9JbmNyZW1lbnQiLCJrIiwiaW5jcmVtZW50UGF0dGVybnMiLCJpbmNyZW1lbnRWYWx1ZXMiLCJhbW91bnRJbmRleCIsImpzb25TYWZlTmFtZSIsInNxbFNhZmVOYW1lIiwia2V5c1RvRGVsZXRlIiwiZGVsZXRlUGF0dGVybnMiLCJwIiwidXBkYXRlT2JqZWN0IiwiZXhwZWN0ZWRUeXBlIiwicmVqZWN0Iiwid2hlcmVDbGF1c2UiLCJ1cHNlcnRPbmVPYmplY3QiLCJjcmVhdGVWYWx1ZSIsInNraXAiLCJsaW1pdCIsInNvcnQiLCJleHBsYWluIiwiaGFzTGltaXQiLCJoYXNTa2lwIiwid2hlcmVQYXR0ZXJuIiwibGltaXRQYXR0ZXJuIiwic2tpcFBhdHRlcm4iLCJzb3J0UGF0dGVybiIsInNvcnRDb3B5Iiwic29ydGluZyIsInRyYW5zZm9ybUtleSIsIm1lbW8iLCJvcmlnaW5hbFF1ZXJ5IiwicG9zdGdyZXNPYmplY3RUb1BhcnNlT2JqZWN0IiwidGFyZ2V0Q2xhc3MiLCJ5IiwieCIsImNvb3JkcyIsIlN0cmluZyIsInVwZGF0ZWRDb29yZHMiLCJwYXJzZUZsb2F0IiwiY3JlYXRlZEF0IiwidG9JU09TdHJpbmciLCJ1cGRhdGVkQXQiLCJleHBpcmVzQXQiLCJlbnN1cmVVbmlxdWVuZXNzIiwiY29uc3RyYWludE5hbWUiLCJjb25zdHJhaW50UGF0dGVybnMiLCJtZXNzYWdlIiwiZW5zdXJlQXV0aERhdGFVbmlxdWVuZXNzIiwiaW5kZXhOYW1lIiwicmVhZFByZWZlcmVuY2UiLCJlc3RpbWF0ZSIsImFwcHJveGltYXRlX3Jvd19jb3VudCIsImRpc3RpbmN0IiwiZmllbGRTZWdtZW50cyIsInNlZ21lbnQiLCJjb2x1bW4iLCJpc05lc3RlZCIsImlzUG9pbnRlckZpZWxkIiwidHJhbnNmb3JtZXIiLCJjaGlsZCIsImFnZ3JlZ2F0ZSIsInBpcGVsaW5lIiwiaGludCIsImNvdW50RmllbGQiLCJncm91cFZhbHVlcyIsImdyb3VwUGF0dGVybiIsInN0YWdlIiwiJGdyb3VwIiwiZ3JvdXBCeUZpZWxkcyIsImFsaWFzIiwic291cmNlIiwib3BlcmF0aW9uIiwiJHN1bSIsIiRtYXgiLCIkbWluIiwiJGF2ZyIsIiRwcm9qZWN0IiwiJG1hdGNoIiwiJG9yIiwiY29sbGFwc2UiLCJlbGVtZW50IiwibWF0Y2hQYXR0ZXJucyIsIiRsaW1pdCIsIiRza2lwIiwiJHNvcnQiLCJvcmRlciIsInRyaW0iLCJCb29sZWFuIiwicGFyc2VJbnQiLCJwZXJmb3JtSW5pdGlhbGl6YXRpb24iLCJWb2xhdGlsZUNsYXNzZXNTY2hlbWFzIiwicHJvbWlzZXMiLCJJTlZBTElEX0NMQVNTX05BTUUiLCJhbGwiLCJzcWwiLCJtaXNjIiwianNvbk9iamVjdFNldEtleXMiLCJhcnJheSIsImFkZCIsImFkZFVuaXF1ZSIsInJlbW92ZSIsImNvbnRhaW5zQWxsIiwiY29udGFpbnNBbGxSZWdleCIsImNvbnRhaW5zIiwiY3R4IiwiZHVyYXRpb24iLCJjcmVhdGVJbmRleGVzSWZOZWVkZWQiLCJnZXRJbmRleGVzIiwidXBkYXRlU2NoZW1hV2l0aEluZGV4ZXMiLCJ1cGRhdGVFc3RpbWF0ZWRDb3VudCIsImNyZWF0ZVRyYW5zYWN0aW9uYWxTZXNzaW9uIiwiY29tbWl0VHJhbnNhY3Rpb25hbFNlc3Npb24iLCJhYm9ydFRyYW5zYWN0aW9uYWxTZXNzaW9uIiwiZW5zdXJlSW5kZXgiLCJkZWZhdWx0SW5kZXhOYW1lIiwiaW5kZXhOYW1lT3B0aW9ucyIsInNldElkZW1wb3RlbmN5RnVuY3Rpb24iLCJlbnN1cmVJZGVtcG90ZW5jeUZ1bmN0aW9uRXhpc3RzIiwiZGVsZXRlSWRlbXBvdGVuY3lGdW5jdGlvbiIsInR0bE9wdGlvbnMiLCJ0dGwiLCJleHBvcnRzIiwidW5pcXVlIiwiYXIiLCJmb3VuZEluZGV4IiwicHQiLCJJTlRFUk5BTF9TRVJWRVJfRVJST1IiLCJlbmRzV2l0aCIsInMiLCJsaXRlcmFsaXplUmVnZXhQYXJ0IiwiaXNTdGFydHNXaXRoUmVnZXgiLCJmaXJzdFZhbHVlc0lzUmVnZXgiLCJjcmVhdGVMaXRlcmFsUmVnZXgiLCJyZW1haW5pbmciLCJSZWdFeHAiLCJtYXRjaGVyMSIsInJlc3VsdDEiLCJwcmVmaXgiLCJtYXRjaGVyMiIsInJlc3VsdDIiLCJfZGVmYXVsdCJdLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9BZGFwdGVycy9TdG9yYWdlL1Bvc3RncmVzL1Bvc3RncmVzU3RvcmFnZUFkYXB0ZXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gQGZsb3dcbmltcG9ydCB7IGNyZWF0ZUNsaWVudCB9IGZyb20gJy4vUG9zdGdyZXNDbGllbnQnO1xuLy8gQGZsb3ctZGlzYWJsZS1uZXh0XG5pbXBvcnQgUGFyc2UgZnJvbSAncGFyc2Uvbm9kZSc7XG4vLyBAZmxvdy1kaXNhYmxlLW5leHRcbmltcG9ydCBfIGZyb20gJ2xvZGFzaCc7XG4vLyBAZmxvdy1kaXNhYmxlLW5leHRcbmltcG9ydCB7IHJhbmRvbVVVSUQgfSBmcm9tICdjcnlwdG8nO1xuaW1wb3J0IHNxbCBmcm9tICcuL3NxbCc7XG5pbXBvcnQgeyBTdG9yYWdlQWRhcHRlciB9IGZyb20gJy4uL1N0b3JhZ2VBZGFwdGVyJztcbmltcG9ydCB0eXBlIHsgU2NoZW1hVHlwZSwgUXVlcnlUeXBlLCBRdWVyeU9wdGlvbnMgfSBmcm9tICcuLi9TdG9yYWdlQWRhcHRlcic7XG5jb25zdCBVdGlscyA9IHJlcXVpcmUoJy4uLy4uLy4uL1V0aWxzJyk7XG5cbmNvbnN0IFBvc3RncmVzUmVsYXRpb25Eb2VzTm90RXhpc3RFcnJvciA9ICc0MlAwMSc7XG5jb25zdCBQb3N0Z3Jlc0R1cGxpY2F0ZVJlbGF0aW9uRXJyb3IgPSAnNDJQMDcnO1xuY29uc3QgUG9zdGdyZXNEdXBsaWNhdGVDb2x1bW5FcnJvciA9ICc0MjcwMSc7XG5jb25zdCBQb3N0Z3Jlc01pc3NpbmdDb2x1bW5FcnJvciA9ICc0MjcwMyc7XG5jb25zdCBQb3N0Z3Jlc1VuaXF1ZUluZGV4VmlvbGF0aW9uRXJyb3IgPSAnMjM1MDUnO1xuY29uc3QgbG9nZ2VyID0gcmVxdWlyZSgnLi4vLi4vLi4vbG9nZ2VyJyk7XG5cbmNvbnN0IGRlYnVnID0gZnVuY3Rpb24gKC4uLmFyZ3M6IGFueSkge1xuICBhcmdzID0gWydQRzogJyArIGFyZ3VtZW50c1swXV0uY29uY2F0KGFyZ3Muc2xpY2UoMSwgYXJncy5sZW5ndGgpKTtcbiAgY29uc3QgbG9nID0gbG9nZ2VyLmdldExvZ2dlcigpO1xuICBsb2cuZGVidWcuYXBwbHkobG9nLCBhcmdzKTtcbn07XG5cbmNvbnN0IHBhcnNlVHlwZVRvUG9zdGdyZXNUeXBlID0gdHlwZSA9PiB7XG4gIHN3aXRjaCAodHlwZS50eXBlKSB7XG4gICAgY2FzZSAnU3RyaW5nJzpcbiAgICAgIHJldHVybiAndGV4dCc7XG4gICAgY2FzZSAnRGF0ZSc6XG4gICAgICByZXR1cm4gJ3RpbWVzdGFtcCB3aXRoIHRpbWUgem9uZSc7XG4gICAgY2FzZSAnT2JqZWN0JzpcbiAgICAgIHJldHVybiAnanNvbmInO1xuICAgIGNhc2UgJ0ZpbGUnOlxuICAgICAgcmV0dXJuICd0ZXh0JztcbiAgICBjYXNlICdCb29sZWFuJzpcbiAgICAgIHJldHVybiAnYm9vbGVhbic7XG4gICAgY2FzZSAnUG9pbnRlcic6XG4gICAgICByZXR1cm4gJ3RleHQnO1xuICAgIGNhc2UgJ051bWJlcic6XG4gICAgICByZXR1cm4gJ2RvdWJsZSBwcmVjaXNpb24nO1xuICAgIGNhc2UgJ0dlb1BvaW50JzpcbiAgICAgIHJldHVybiAncG9pbnQnO1xuICAgIGNhc2UgJ0J5dGVzJzpcbiAgICAgIHJldHVybiAnanNvbmInO1xuICAgIGNhc2UgJ1BvbHlnb24nOlxuICAgICAgcmV0dXJuICdwb2x5Z29uJztcbiAgICBjYXNlICdBcnJheSc6XG4gICAgICBpZiAodHlwZS5jb250ZW50cyAmJiB0eXBlLmNvbnRlbnRzLnR5cGUgPT09ICdTdHJpbmcnKSB7XG4gICAgICAgIHJldHVybiAndGV4dFtdJztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiAnanNvbmInO1xuICAgICAgfVxuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBgbm8gdHlwZSBmb3IgJHtKU09OLnN0cmluZ2lmeSh0eXBlKX0geWV0YDtcbiAgfVxufTtcblxuY29uc3QgUGFyc2VUb1Bvc2dyZXNDb21wYXJhdG9yID0ge1xuICAkZ3Q6ICc+JyxcbiAgJGx0OiAnPCcsXG4gICRndGU6ICc+PScsXG4gICRsdGU6ICc8PScsXG59O1xuXG5jb25zdCBtb25nb0FnZ3JlZ2F0ZVRvUG9zdGdyZXMgPSB7XG4gICRkYXlPZk1vbnRoOiAnREFZJyxcbiAgJGRheU9mV2VlazogJ0RPVycsXG4gICRkYXlPZlllYXI6ICdET1knLFxuICAkaXNvRGF5T2ZXZWVrOiAnSVNPRE9XJyxcbiAgJGlzb1dlZWtZZWFyOiAnSVNPWUVBUicsXG4gICRob3VyOiAnSE9VUicsXG4gICRtaW51dGU6ICdNSU5VVEUnLFxuICAkc2Vjb25kOiAnU0VDT05EJyxcbiAgJG1pbGxpc2Vjb25kOiAnTUlMTElTRUNPTkRTJyxcbiAgJG1vbnRoOiAnTU9OVEgnLFxuICAkd2VlazogJ1dFRUsnLFxuICAkeWVhcjogJ1lFQVInLFxufTtcblxuY29uc3QgdG9Qb3N0Z3Jlc1ZhbHVlID0gdmFsdWUgPT4ge1xuICBpZiAodHlwZW9mIHZhbHVlID09PSAnb2JqZWN0Jykge1xuICAgIGlmICh2YWx1ZS5fX3R5cGUgPT09ICdEYXRlJykge1xuICAgICAgcmV0dXJuIHZhbHVlLmlzbztcbiAgICB9XG4gICAgaWYgKHZhbHVlLl9fdHlwZSA9PT0gJ0ZpbGUnKSB7XG4gICAgICByZXR1cm4gdmFsdWUubmFtZTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHZhbHVlO1xufTtcblxuY29uc3QgdG9Qb3N0Z3Jlc1ZhbHVlQ2FzdFR5cGUgPSB2YWx1ZSA9PiB7XG4gIGNvbnN0IHBvc3RncmVzVmFsdWUgPSB0b1Bvc3RncmVzVmFsdWUodmFsdWUpO1xuICBsZXQgY2FzdFR5cGU7XG4gIHN3aXRjaCAodHlwZW9mIHBvc3RncmVzVmFsdWUpIHtcbiAgICBjYXNlICdudW1iZXInOlxuICAgICAgY2FzdFR5cGUgPSAnZG91YmxlIHByZWNpc2lvbic7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdib29sZWFuJzpcbiAgICAgIGNhc3RUeXBlID0gJ2Jvb2xlYW4nO1xuICAgICAgYnJlYWs7XG4gICAgZGVmYXVsdDpcbiAgICAgIGNhc3RUeXBlID0gdW5kZWZpbmVkO1xuICB9XG4gIHJldHVybiBjYXN0VHlwZTtcbn07XG5cbmNvbnN0IHRyYW5zZm9ybVZhbHVlID0gdmFsdWUgPT4ge1xuICBpZiAodHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJiB2YWx1ZS5fX3R5cGUgPT09ICdQb2ludGVyJykge1xuICAgIHJldHVybiB2YWx1ZS5vYmplY3RJZDtcbiAgfVxuICByZXR1cm4gdmFsdWU7XG59O1xuXG4vLyBEdXBsaWNhdGUgZnJvbSB0aGVuIG1vbmdvIGFkYXB0ZXIuLi5cbmNvbnN0IGVtcHR5Q0xQUyA9IE9iamVjdC5mcmVlemUoe1xuICBmaW5kOiB7fSxcbiAgZ2V0OiB7fSxcbiAgY291bnQ6IHt9LFxuICBjcmVhdGU6IHt9LFxuICB1cGRhdGU6IHt9LFxuICBkZWxldGU6IHt9LFxuICBhZGRGaWVsZDoge30sXG4gIHByb3RlY3RlZEZpZWxkczoge30sXG59KTtcblxuY29uc3QgZGVmYXVsdENMUFMgPSBPYmplY3QuZnJlZXplKHtcbiAgQUNMOiB7XG4gICAgJyonOiB7XG4gICAgICByZWFkOiB0cnVlLFxuICAgICAgd3JpdGU6IHRydWUsXG4gICAgfSxcbiAgfSxcbiAgZmluZDogeyAnKic6IHRydWUgfSxcbiAgZ2V0OiB7ICcqJzogdHJ1ZSB9LFxuICBjb3VudDogeyAnKic6IHRydWUgfSxcbiAgY3JlYXRlOiB7ICcqJzogdHJ1ZSB9LFxuICB1cGRhdGU6IHsgJyonOiB0cnVlIH0sXG4gIGRlbGV0ZTogeyAnKic6IHRydWUgfSxcbiAgYWRkRmllbGQ6IHsgJyonOiB0cnVlIH0sXG4gIHByb3RlY3RlZEZpZWxkczogeyAnKic6IFtdIH0sXG59KTtcblxuY29uc3QgdG9QYXJzZVNjaGVtYSA9IHNjaGVtYSA9PiB7XG4gIGlmIChzY2hlbWEuY2xhc3NOYW1lID09PSAnX1VzZXInKSB7XG4gICAgZGVsZXRlIHNjaGVtYS5maWVsZHMuX2hhc2hlZF9wYXNzd29yZDtcbiAgfVxuICBpZiAoc2NoZW1hLmZpZWxkcykge1xuICAgIGRlbGV0ZSBzY2hlbWEuZmllbGRzLl93cGVybTtcbiAgICBkZWxldGUgc2NoZW1hLmZpZWxkcy5fcnBlcm07XG4gIH1cbiAgbGV0IGNscHMgPSBkZWZhdWx0Q0xQUztcbiAgaWYgKHNjaGVtYS5jbGFzc0xldmVsUGVybWlzc2lvbnMpIHtcbiAgICBjbHBzID0geyAuLi5lbXB0eUNMUFMsIC4uLnNjaGVtYS5jbGFzc0xldmVsUGVybWlzc2lvbnMgfTtcbiAgfVxuICBsZXQgaW5kZXhlcyA9IHt9O1xuICBpZiAoc2NoZW1hLmluZGV4ZXMpIHtcbiAgICBpbmRleGVzID0geyAuLi5zY2hlbWEuaW5kZXhlcyB9O1xuICB9XG4gIHJldHVybiB7XG4gICAgY2xhc3NOYW1lOiBzY2hlbWEuY2xhc3NOYW1lLFxuICAgIGZpZWxkczogc2NoZW1hLmZpZWxkcyxcbiAgICBjbGFzc0xldmVsUGVybWlzc2lvbnM6IGNscHMsXG4gICAgaW5kZXhlcyxcbiAgfTtcbn07XG5cbmNvbnN0IHRvUG9zdGdyZXNTY2hlbWEgPSBzY2hlbWEgPT4ge1xuICBpZiAoIXNjaGVtYSkge1xuICAgIHJldHVybiBzY2hlbWE7XG4gIH1cbiAgc2NoZW1hLmZpZWxkcyA9IHNjaGVtYS5maWVsZHMgfHwge307XG4gIHNjaGVtYS5maWVsZHMuX3dwZXJtID0geyB0eXBlOiAnQXJyYXknLCBjb250ZW50czogeyB0eXBlOiAnU3RyaW5nJyB9IH07XG4gIHNjaGVtYS5maWVsZHMuX3JwZXJtID0geyB0eXBlOiAnQXJyYXknLCBjb250ZW50czogeyB0eXBlOiAnU3RyaW5nJyB9IH07XG4gIGlmIChzY2hlbWEuY2xhc3NOYW1lID09PSAnX1VzZXInKSB7XG4gICAgc2NoZW1hLmZpZWxkcy5faGFzaGVkX3Bhc3N3b3JkID0geyB0eXBlOiAnU3RyaW5nJyB9O1xuICAgIHNjaGVtYS5maWVsZHMuX3Bhc3N3b3JkX2hpc3RvcnkgPSB7IHR5cGU6ICdBcnJheScgfTtcbiAgfVxuICByZXR1cm4gc2NoZW1hO1xufTtcblxuY29uc3QgaXNBcnJheUluZGV4ID0gKGFycmF5SW5kZXgpID0+IEFycmF5LmZyb20oYXJyYXlJbmRleCkuZXZlcnkoYyA9PiBjID49ICcwJyAmJiBjIDw9ICc5Jyk7XG5cbmNvbnN0IGhhbmRsZURvdEZpZWxkcyA9IG9iamVjdCA9PiB7XG4gIE9iamVjdC5rZXlzKG9iamVjdCkuZm9yRWFjaChmaWVsZE5hbWUgPT4ge1xuICAgIGlmIChmaWVsZE5hbWUuaW5kZXhPZignLicpID4gLTEpIHtcbiAgICAgIGNvbnN0IGNvbXBvbmVudHMgPSBmaWVsZE5hbWUuc3BsaXQoJy4nKTtcbiAgICAgIGNvbnN0IGZpcnN0ID0gY29tcG9uZW50cy5zaGlmdCgpO1xuICAgICAgb2JqZWN0W2ZpcnN0XSA9IG9iamVjdFtmaXJzdF0gfHwge307XG4gICAgICBsZXQgY3VycmVudE9iaiA9IG9iamVjdFtmaXJzdF07XG4gICAgICBsZXQgbmV4dDtcbiAgICAgIGxldCB2YWx1ZSA9IG9iamVjdFtmaWVsZE5hbWVdO1xuICAgICAgaWYgKHZhbHVlICYmIHZhbHVlLl9fb3AgPT09ICdEZWxldGUnKSB7XG4gICAgICAgIHZhbHVlID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgd2hpbGUgKChuZXh0ID0gY29tcG9uZW50cy5zaGlmdCgpKSkge1xuICAgICAgICBjdXJyZW50T2JqW25leHRdID0gY3VycmVudE9ialtuZXh0XSB8fCB7fTtcbiAgICAgICAgaWYgKGNvbXBvbmVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgY3VycmVudE9ialtuZXh0XSA9IHZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGN1cnJlbnRPYmogPSBjdXJyZW50T2JqW25leHRdO1xuICAgICAgfVxuICAgICAgZGVsZXRlIG9iamVjdFtmaWVsZE5hbWVdO1xuICAgIH1cbiAgfSk7XG4gIHJldHVybiBvYmplY3Q7XG59O1xuXG5jb25zdCBlc2NhcGVTcWxTdHJpbmcgPSB2YWx1ZSA9PiB2YWx1ZS5yZXBsYWNlKC8nL2csIFwiJydcIik7XG5jb25zdCBlc2NhcGVKc29uU3RyaW5nID0gdmFsdWUgPT4gSlNPTi5zdHJpbmdpZnkodmFsdWUpLnNsaWNlKDEsIC0xKTtcblxuY29uc3QgdHJhbnNmb3JtRG90RmllbGRUb0NvbXBvbmVudHMgPSBmaWVsZE5hbWUgPT4ge1xuICByZXR1cm4gZmllbGROYW1lLnNwbGl0KCcuJykubWFwKChjbXB0LCBpbmRleCkgPT4ge1xuICAgIGlmIChpbmRleCA9PT0gMCkge1xuICAgICAgcmV0dXJuIGBcIiR7Y21wdC5yZXBsYWNlKC9cIi9nLCAnXCJcIicpfVwiYDtcbiAgICB9XG4gICAgaWYgKGlzQXJyYXlJbmRleChjbXB0KSkge1xuICAgICAgcmV0dXJuIE51bWJlcihjbXB0KTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGAnJHtlc2NhcGVTcWxTdHJpbmcoY21wdCl9J2A7XG4gICAgfVxuICB9KTtcbn07XG5cbmNvbnN0IHRyYW5zZm9ybURvdEZpZWxkID0gZmllbGROYW1lID0+IHtcbiAgaWYgKGZpZWxkTmFtZS5pbmRleE9mKCcuJykgPT09IC0xKSB7XG4gICAgcmV0dXJuIGBcIiR7ZmllbGROYW1lLnJlcGxhY2UoL1wiL2csICdcIlwiJyl9XCJgO1xuICB9XG4gIGNvbnN0IGNvbXBvbmVudHMgPSB0cmFuc2Zvcm1Eb3RGaWVsZFRvQ29tcG9uZW50cyhmaWVsZE5hbWUpO1xuICBsZXQgbmFtZSA9IGNvbXBvbmVudHMuc2xpY2UoMCwgY29tcG9uZW50cy5sZW5ndGggLSAxKS5qb2luKCctPicpO1xuICBuYW1lICs9ICctPj4nICsgY29tcG9uZW50c1tjb21wb25lbnRzLmxlbmd0aCAtIDFdO1xuICByZXR1cm4gbmFtZTtcbn07XG5cbmNvbnN0IHZhbGlkYXRlQWdncmVnYXRlRmllbGROYW1lID0gbmFtZSA9PiB7XG4gIGlmICh0eXBlb2YgbmFtZSAhPT0gJ3N0cmluZycgfHwgIW5hbWUubWF0Y2goL15bYS16QS1aXVthLXpBLVowLTlfXSokLykpIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9LRVlfTkFNRSwgYEludmFsaWQgZmllbGQgbmFtZTogJHtuYW1lfWApO1xuICB9XG59O1xuXG5jb25zdCB0cmFuc2Zvcm1BZ2dyZWdhdGVGaWVsZCA9IGZpZWxkTmFtZSA9PiB7XG4gIGlmICh0eXBlb2YgZmllbGROYW1lICE9PSAnc3RyaW5nJykge1xuICAgIHJldHVybiBmaWVsZE5hbWU7XG4gIH1cbiAgaWYgKGZpZWxkTmFtZSA9PT0gJyRfY3JlYXRlZF9hdCcpIHtcbiAgICByZXR1cm4gJ2NyZWF0ZWRBdCc7XG4gIH1cbiAgaWYgKGZpZWxkTmFtZSA9PT0gJyRfdXBkYXRlZF9hdCcpIHtcbiAgICByZXR1cm4gJ3VwZGF0ZWRBdCc7XG4gIH1cbiAgaWYgKCFmaWVsZE5hbWUuc3RhcnRzV2l0aCgnJCcpKSB7XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfS0VZX05BTUUsIGBJbnZhbGlkIGZpZWxkIG5hbWU6ICR7ZmllbGROYW1lfWApO1xuICB9XG4gIGNvbnN0IG5hbWUgPSBmaWVsZE5hbWUuc3Vic3RyaW5nKDEpO1xuICB2YWxpZGF0ZUFnZ3JlZ2F0ZUZpZWxkTmFtZShuYW1lKTtcbiAgcmV0dXJuIG5hbWU7XG59O1xuXG5jb25zdCB2YWxpZGF0ZUtleXMgPSBvYmplY3QgPT4ge1xuICBpZiAodHlwZW9mIG9iamVjdCA9PSAnb2JqZWN0Jykge1xuICAgIGZvciAoY29uc3Qga2V5IGluIG9iamVjdCkge1xuICAgICAgaWYgKHR5cGVvZiBvYmplY3Rba2V5XSA9PSAnb2JqZWN0Jykge1xuICAgICAgICB2YWxpZGF0ZUtleXMob2JqZWN0W2tleV0pO1xuICAgICAgfVxuXG4gICAgICBpZiAoa2V5LmluY2x1ZGVzKCckJykgfHwga2V5LmluY2x1ZGVzKCcuJykpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfTkVTVEVEX0tFWSxcbiAgICAgICAgICBcIk5lc3RlZCBrZXlzIHNob3VsZCBub3QgY29udGFpbiB0aGUgJyQnIG9yICcuJyBjaGFyYWN0ZXJzXCJcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn07XG5cbi8vIFJldHVybnMgdGhlIGxpc3Qgb2Ygam9pbiB0YWJsZXMgb24gYSBzY2hlbWFcbmNvbnN0IGpvaW5UYWJsZXNGb3JTY2hlbWEgPSBzY2hlbWEgPT4ge1xuICBjb25zdCBsaXN0ID0gW107XG4gIGlmIChzY2hlbWEpIHtcbiAgICBPYmplY3Qua2V5cyhzY2hlbWEuZmllbGRzKS5mb3JFYWNoKGZpZWxkID0+IHtcbiAgICAgIGlmIChzY2hlbWEuZmllbGRzW2ZpZWxkXS50eXBlID09PSAnUmVsYXRpb24nKSB7XG4gICAgICAgIGxpc3QucHVzaChgX0pvaW46JHtmaWVsZH06JHtzY2hlbWEuY2xhc3NOYW1lfWApO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG4gIHJldHVybiBsaXN0O1xufTtcblxuaW50ZXJmYWNlIFdoZXJlQ2xhdXNlIHtcbiAgcGF0dGVybjogc3RyaW5nO1xuICB2YWx1ZXM6IEFycmF5PGFueT47XG4gIHNvcnRzOiBBcnJheTxhbnk+O1xufVxuXG5jb25zdCBidWlsZFdoZXJlQ2xhdXNlID0gKHsgc2NoZW1hLCBxdWVyeSwgaW5kZXgsIGNhc2VJbnNlbnNpdGl2ZSB9KTogV2hlcmVDbGF1c2UgPT4ge1xuICBjb25zdCBwYXR0ZXJucyA9IFtdO1xuICBsZXQgdmFsdWVzID0gW107XG4gIGNvbnN0IHNvcnRzID0gW107XG5cbiAgc2NoZW1hID0gdG9Qb3N0Z3Jlc1NjaGVtYShzY2hlbWEpO1xuICBmb3IgKGNvbnN0IGZpZWxkTmFtZSBpbiBxdWVyeSkge1xuICAgIGNvbnN0IGlzQXJyYXlGaWVsZCA9XG4gICAgICBzY2hlbWEuZmllbGRzICYmIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXSAmJiBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0udHlwZSA9PT0gJ0FycmF5JztcbiAgICBjb25zdCBpbml0aWFsUGF0dGVybnNMZW5ndGggPSBwYXR0ZXJucy5sZW5ndGg7XG4gICAgY29uc3QgZmllbGRWYWx1ZSA9IHF1ZXJ5W2ZpZWxkTmFtZV07XG5cbiAgICAvLyBub3RoaW5nIGluIHRoZSBzY2hlbWEsIGl0J3MgZ29ubmEgYmxvdyB1cFxuICAgIGlmICghc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdKSB7XG4gICAgICAvLyBhcyBpdCB3b24ndCBleGlzdFxuICAgICAgaWYgKGZpZWxkVmFsdWUgJiYgZmllbGRWYWx1ZS4kZXhpc3RzID09PSBmYWxzZSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgY29uc3QgYXV0aERhdGFNYXRjaCA9IGZpZWxkTmFtZS5tYXRjaCgvXl9hdXRoX2RhdGFfKFthLXpBLVowLTlfXSspJC8pO1xuICAgIGlmIChhdXRoRGF0YU1hdGNoKSB7XG4gICAgICAvLyBUT0RPOiBIYW5kbGUgcXVlcnlpbmcgYnkgX2F1dGhfZGF0YV9wcm92aWRlciwgYXV0aERhdGEgaXMgc3RvcmVkIGluIGF1dGhEYXRhIGZpZWxkXG4gICAgICBjb250aW51ZTtcbiAgICB9IGVsc2UgaWYgKGNhc2VJbnNlbnNpdGl2ZSAmJiAoZmllbGROYW1lID09PSAndXNlcm5hbWUnIHx8IGZpZWxkTmFtZSA9PT0gJ2VtYWlsJykpIHtcbiAgICAgIHBhdHRlcm5zLnB1c2goYExPV0VSKCQke2luZGV4fTpuYW1lKSA9IExPV0VSKCQke2luZGV4ICsgMX0pYCk7XG4gICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIGZpZWxkVmFsdWUpO1xuICAgICAgaW5kZXggKz0gMjtcbiAgICB9IGVsc2UgaWYgKGZpZWxkTmFtZS5pbmRleE9mKCcuJykgPj0gMCkge1xuICAgICAgbGV0IG5hbWUgPSB0cmFuc2Zvcm1Eb3RGaWVsZChmaWVsZE5hbWUpO1xuICAgICAgaWYgKGZpZWxkVmFsdWUgPT09IG51bGwpIHtcbiAgICAgICAgcGF0dGVybnMucHVzaChgJCR7aW5kZXh9OnJhdyBJUyBOVUxMYCk7XG4gICAgICAgIHZhbHVlcy5wdXNoKG5hbWUpO1xuICAgICAgICBpbmRleCArPSAxO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChmaWVsZFZhbHVlLiRpbikge1xuICAgICAgICAgIG5hbWUgPSB0cmFuc2Zvcm1Eb3RGaWVsZFRvQ29tcG9uZW50cyhmaWVsZE5hbWUpLmpvaW4oJy0+Jyk7XG4gICAgICAgICAgcGF0dGVybnMucHVzaChgKCQke2luZGV4fTpyYXcpOjpqc29uYiBAPiAkJHtpbmRleCArIDF9Ojpqc29uYmApO1xuICAgICAgICAgIHZhbHVlcy5wdXNoKG5hbWUsIEpTT04uc3RyaW5naWZ5KGZpZWxkVmFsdWUuJGluKSk7XG4gICAgICAgICAgaW5kZXggKz0gMjtcbiAgICAgICAgfSBlbHNlIGlmIChmaWVsZFZhbHVlLiRyZWdleCkge1xuICAgICAgICAgIC8vIEhhbmRsZSBsYXRlclxuICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBmaWVsZFZhbHVlICE9PSAnb2JqZWN0Jykge1xuICAgICAgICAgIHBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpyYXcgPSAkJHtpbmRleCArIDF9Ojp0ZXh0YCk7XG4gICAgICAgICAgdmFsdWVzLnB1c2gobmFtZSwgZmllbGRWYWx1ZSk7XG4gICAgICAgICAgaW5kZXggKz0gMjtcbiAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICB0eXBlb2YgZmllbGRWYWx1ZSA9PT0gJ29iamVjdCcgJiZcbiAgICAgICAgICAhT2JqZWN0LmtleXMoZmllbGRWYWx1ZSkuc29tZShrZXkgPT4ga2V5LnN0YXJ0c1dpdGgoJyQnKSlcbiAgICAgICAgKSB7XG4gICAgICAgICAgbmFtZSA9IHRyYW5zZm9ybURvdEZpZWxkVG9Db21wb25lbnRzKGZpZWxkTmFtZSkuam9pbignLT4nKTtcbiAgICAgICAgICBwYXR0ZXJucy5wdXNoKGAoJCR7aW5kZXh9OnJhdyk6Ompzb25iID0gJCR7aW5kZXggKyAxfTo6anNvbmJgKTtcbiAgICAgICAgICB2YWx1ZXMucHVzaChuYW1lLCBKU09OLnN0cmluZ2lmeShmaWVsZFZhbHVlKSk7XG4gICAgICAgICAgaW5kZXggKz0gMjtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoZmllbGRWYWx1ZSA9PT0gbnVsbCB8fCBmaWVsZFZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lIElTIE5VTExgKTtcbiAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSk7XG4gICAgICBpbmRleCArPSAxO1xuICAgICAgY29udGludWU7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgZmllbGRWYWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lID0gJCR7aW5kZXggKyAxfWApO1xuICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCBmaWVsZFZhbHVlKTtcbiAgICAgIGluZGV4ICs9IDI7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgZmllbGRWYWx1ZSA9PT0gJ2Jvb2xlYW4nKSB7XG4gICAgICBwYXR0ZXJucy5wdXNoKGAkJHtpbmRleH06bmFtZSA9ICQke2luZGV4ICsgMX1gKTtcbiAgICAgIC8vIENhbid0IGNhc3QgYm9vbGVhbiB0byBkb3VibGUgcHJlY2lzaW9uXG4gICAgICBpZiAoc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdICYmIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS50eXBlID09PSAnTnVtYmVyJykge1xuICAgICAgICAvLyBTaG91bGQgYWx3YXlzIHJldHVybiB6ZXJvIHJlc3VsdHNcbiAgICAgICAgY29uc3QgTUFYX0lOVF9QTFVTX09ORSA9IDkyMjMzNzIwMzY4NTQ3NzU4MDg7XG4gICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgTUFYX0lOVF9QTFVTX09ORSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIGZpZWxkVmFsdWUpO1xuICAgICAgfVxuICAgICAgaW5kZXggKz0gMjtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBmaWVsZFZhbHVlID09PSAnbnVtYmVyJykge1xuICAgICAgcGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgPSAkJHtpbmRleCArIDF9YCk7XG4gICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIGZpZWxkVmFsdWUpO1xuICAgICAgaW5kZXggKz0gMjtcbiAgICB9IGVsc2UgaWYgKFsnJG9yJywgJyRub3InLCAnJGFuZCddLmluY2x1ZGVzKGZpZWxkTmFtZSkpIHtcbiAgICAgIGNvbnN0IGNsYXVzZXMgPSBbXTtcbiAgICAgIGNvbnN0IGNsYXVzZVZhbHVlcyA9IFtdO1xuICAgICAgZmllbGRWYWx1ZS5mb3JFYWNoKHN1YlF1ZXJ5ID0+IHtcbiAgICAgICAgY29uc3QgY2xhdXNlID0gYnVpbGRXaGVyZUNsYXVzZSh7XG4gICAgICAgICAgc2NoZW1hLFxuICAgICAgICAgIHF1ZXJ5OiBzdWJRdWVyeSxcbiAgICAgICAgICBpbmRleCxcbiAgICAgICAgICBjYXNlSW5zZW5zaXRpdmUsXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoY2xhdXNlLnBhdHRlcm4ubGVuZ3RoID4gMCkge1xuICAgICAgICAgIGNsYXVzZXMucHVzaChjbGF1c2UucGF0dGVybik7XG4gICAgICAgICAgY2xhdXNlVmFsdWVzLnB1c2goLi4uY2xhdXNlLnZhbHVlcyk7XG4gICAgICAgICAgaW5kZXggKz0gY2xhdXNlLnZhbHVlcy5sZW5ndGg7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBvck9yQW5kID0gZmllbGROYW1lID09PSAnJGFuZCcgPyAnIEFORCAnIDogJyBPUiAnO1xuICAgICAgY29uc3Qgbm90ID0gZmllbGROYW1lID09PSAnJG5vcicgPyAnIE5PVCAnIDogJyc7XG5cbiAgICAgIHBhdHRlcm5zLnB1c2goYCR7bm90fSgke2NsYXVzZXMuam9pbihvck9yQW5kKX0pYCk7XG4gICAgICB2YWx1ZXMucHVzaCguLi5jbGF1c2VWYWx1ZXMpO1xuICAgIH1cblxuICAgIGlmIChmaWVsZFZhbHVlLiRuZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBpZiAoaXNBcnJheUZpZWxkKSB7XG4gICAgICAgIGZpZWxkVmFsdWUuJG5lID0gSlNPTi5zdHJpbmdpZnkoW2ZpZWxkVmFsdWUuJG5lXSk7XG4gICAgICAgIHBhdHRlcm5zLnB1c2goYE5PVCBhcnJheV9jb250YWlucygkJHtpbmRleH06bmFtZSwgJCR7aW5kZXggKyAxfSlgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChmaWVsZFZhbHVlLiRuZSA9PT0gbnVsbCkge1xuICAgICAgICAgIHBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lIElTIE5PVCBOVUxMYCk7XG4gICAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lKTtcbiAgICAgICAgICBpbmRleCArPSAxO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIGlmIG5vdCBudWxsLCB3ZSBuZWVkIHRvIG1hbnVhbGx5IGV4Y2x1ZGUgbnVsbFxuICAgICAgICAgIGlmIChmaWVsZFZhbHVlLiRuZS5fX3R5cGUgPT09ICdHZW9Qb2ludCcpIHtcbiAgICAgICAgICAgIHBhdHRlcm5zLnB1c2goXG4gICAgICAgICAgICAgIGAoJCR7aW5kZXh9Om5hbWUgPD4gUE9JTlQoJCR7aW5kZXggKyAxfSwgJCR7aW5kZXggKyAyfSkgT1IgJCR7aW5kZXh9Om5hbWUgSVMgTlVMTClgXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoZmllbGROYW1lLmluZGV4T2YoJy4nKSA+PSAwKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGNhc3RUeXBlID0gdG9Qb3N0Z3Jlc1ZhbHVlQ2FzdFR5cGUoZmllbGRWYWx1ZS4kbmUpO1xuICAgICAgICAgICAgICBjb25zdCBjb25zdHJhaW50RmllbGROYW1lID0gY2FzdFR5cGVcbiAgICAgICAgICAgICAgICA/IGBDQVNUICgoJHt0cmFuc2Zvcm1Eb3RGaWVsZChmaWVsZE5hbWUpfSkgQVMgJHtjYXN0VHlwZX0pYFxuICAgICAgICAgICAgICAgIDogdHJhbnNmb3JtRG90RmllbGQoZmllbGROYW1lKTtcbiAgICAgICAgICAgICAgcGF0dGVybnMucHVzaChcbiAgICAgICAgICAgICAgICBgKCR7Y29uc3RyYWludEZpZWxkTmFtZX0gPD4gJCR7aW5kZXggKyAxfSBPUiAke2NvbnN0cmFpbnRGaWVsZE5hbWV9IElTIE5VTEwpYFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgZmllbGRWYWx1ZS4kbmUgPT09ICdvYmplY3QnICYmIGZpZWxkVmFsdWUuJG5lLiRyZWxhdGl2ZVRpbWUpIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICAgICAgICAnJHJlbGF0aXZlVGltZSBjYW4gb25seSBiZSB1c2VkIHdpdGggdGhlICRsdCwgJGx0ZSwgJGd0LCBhbmQgJGd0ZSBvcGVyYXRvcnMnXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBwYXR0ZXJucy5wdXNoKGAoJCR7aW5kZXh9Om5hbWUgPD4gJCR7aW5kZXggKyAxfSBPUiAkJHtpbmRleH06bmFtZSBJUyBOVUxMKWApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKGZpZWxkVmFsdWUuJG5lLl9fdHlwZSA9PT0gJ0dlb1BvaW50Jykge1xuICAgICAgICBjb25zdCBwb2ludCA9IGZpZWxkVmFsdWUuJG5lO1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIHBvaW50LmxvbmdpdHVkZSwgcG9pbnQubGF0aXR1ZGUpO1xuICAgICAgICBpbmRleCArPSAzO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gVE9ETzogc3VwcG9ydCBhcnJheXNcbiAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCBmaWVsZFZhbHVlLiRuZSk7XG4gICAgICAgIGluZGV4ICs9IDI7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChmaWVsZFZhbHVlLiRlcSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBpZiAoZmllbGRWYWx1ZS4kZXEgPT09IG51bGwpIHtcbiAgICAgICAgcGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgSVMgTlVMTGApO1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUpO1xuICAgICAgICBpbmRleCArPSAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKGZpZWxkTmFtZS5pbmRleE9mKCcuJykgPj0gMCkge1xuICAgICAgICAgIGNvbnN0IGNhc3RUeXBlID0gdG9Qb3N0Z3Jlc1ZhbHVlQ2FzdFR5cGUoZmllbGRWYWx1ZS4kZXEpO1xuICAgICAgICAgIGNvbnN0IGNvbnN0cmFpbnRGaWVsZE5hbWUgPSBjYXN0VHlwZVxuICAgICAgICAgICAgPyBgQ0FTVCAoKCR7dHJhbnNmb3JtRG90RmllbGQoZmllbGROYW1lKX0pIEFTICR7Y2FzdFR5cGV9KWBcbiAgICAgICAgICAgIDogdHJhbnNmb3JtRG90RmllbGQoZmllbGROYW1lKTtcbiAgICAgICAgICB2YWx1ZXMucHVzaChmaWVsZFZhbHVlLiRlcSk7XG4gICAgICAgICAgcGF0dGVybnMucHVzaChgJHtjb25zdHJhaW50RmllbGROYW1lfSA9ICQke2luZGV4Kyt9YCk7XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGZpZWxkVmFsdWUuJGVxID09PSAnb2JqZWN0JyAmJiBmaWVsZFZhbHVlLiRlcS4kcmVsYXRpdmVUaW1lKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgICAgJyRyZWxhdGl2ZVRpbWUgY2FuIG9ubHkgYmUgdXNlZCB3aXRoIHRoZSAkbHQsICRsdGUsICRndCwgYW5kICRndGUgb3BlcmF0b3JzJ1xuICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCBmaWVsZFZhbHVlLiRlcSk7XG4gICAgICAgICAgcGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgPSAkJHtpbmRleCArIDF9YCk7XG4gICAgICAgICAgaW5kZXggKz0gMjtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICBjb25zdCBpc0luT3JOaW4gPSBBcnJheS5pc0FycmF5KGZpZWxkVmFsdWUuJGluKSB8fCBBcnJheS5pc0FycmF5KGZpZWxkVmFsdWUuJG5pbik7XG4gICAgaWYgKFxuICAgICAgQXJyYXkuaXNBcnJheShmaWVsZFZhbHVlLiRpbikgJiZcbiAgICAgIGlzQXJyYXlGaWVsZCAmJlxuICAgICAgc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdLmNvbnRlbnRzICYmXG4gICAgICBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0uY29udGVudHMudHlwZSA9PT0gJ1N0cmluZydcbiAgICApIHtcbiAgICAgIGNvbnN0IGluUGF0dGVybnMgPSBbXTtcbiAgICAgIGxldCBhbGxvd051bGwgPSBmYWxzZTtcbiAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSk7XG4gICAgICBmaWVsZFZhbHVlLiRpbi5mb3JFYWNoKChsaXN0RWxlbSwgbGlzdEluZGV4KSA9PiB7XG4gICAgICAgIGlmIChsaXN0RWxlbSA9PT0gbnVsbCkge1xuICAgICAgICAgIGFsbG93TnVsbCA9IHRydWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdmFsdWVzLnB1c2gobGlzdEVsZW0pO1xuICAgICAgICAgIGluUGF0dGVybnMucHVzaChgJCR7aW5kZXggKyAxICsgbGlzdEluZGV4IC0gKGFsbG93TnVsbCA/IDEgOiAwKX1gKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBpZiAoYWxsb3dOdWxsKSB7XG4gICAgICAgIHBhdHRlcm5zLnB1c2goYCgkJHtpbmRleH06bmFtZSBJUyBOVUxMIE9SICQke2luZGV4fTpuYW1lICYmIEFSUkFZWyR7aW5QYXR0ZXJucy5qb2luKCl9XSlgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lICYmIEFSUkFZWyR7aW5QYXR0ZXJucy5qb2luKCl9XWApO1xuICAgICAgfVxuICAgICAgaW5kZXggPSBpbmRleCArIDEgKyBpblBhdHRlcm5zLmxlbmd0aDtcbiAgICB9IGVsc2UgaWYgKGlzSW5Pck5pbikge1xuICAgICAgdmFyIGNyZWF0ZUNvbnN0cmFpbnQgPSAoYmFzZUFycmF5LCBub3RJbikgPT4ge1xuICAgICAgICBjb25zdCBub3QgPSBub3RJbiA/ICcgTk9UICcgOiAnJztcbiAgICAgICAgaWYgKGJhc2VBcnJheS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgaWYgKGlzQXJyYXlGaWVsZCkge1xuICAgICAgICAgICAgcGF0dGVybnMucHVzaChgJHtub3R9IGFycmF5X2NvbnRhaW5zKCQke2luZGV4fTpuYW1lLCAkJHtpbmRleCArIDF9KWApO1xuICAgICAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCBKU09OLnN0cmluZ2lmeShiYXNlQXJyYXkpKTtcbiAgICAgICAgICAgIGluZGV4ICs9IDI7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIEhhbmRsZSBOZXN0ZWQgRG90IE5vdGF0aW9uIEFib3ZlXG4gICAgICAgICAgICBpZiAoZmllbGROYW1lLmluZGV4T2YoJy4nKSA+PSAwKSB7XG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGZpZWxkVHlwZSA9IHNjaGVtYS5maWVsZHNbZmllbGROYW1lXT8udHlwZTtcbiAgICAgICAgICAgIGlmIChmaWVsZFR5cGUgPT09ICdTdHJpbmcnKSB7XG4gICAgICAgICAgICAgIGNvbnN0IG9wZXJhdG9yTmFtZSA9IG5vdEluID8gJyRuaW4nIDogJyRpbic7XG4gICAgICAgICAgICAgIGZvciAoY29uc3QgZWxlbSBvZiBiYXNlQXJyYXkpIHtcbiAgICAgICAgICAgICAgICBpZiAoZWxlbSAhPSBudWxsICYmIHR5cGVvZiBlbGVtICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX1FVRVJZLFxuICAgICAgICAgICAgICAgICAgICBgJHtvcGVyYXRvck5hbWV9IGVsZW1lbnQgdHlwZSBtaXNtYXRjaDogZXhwZWN0ZWQgc3RyaW5nIGZvciBmaWVsZCBcIiR7ZmllbGROYW1lfVwiYFxuICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGluUGF0dGVybnMgPSBbXTtcbiAgICAgICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSk7XG4gICAgICAgICAgICBiYXNlQXJyYXkuZm9yRWFjaCgobGlzdEVsZW0sIGxpc3RJbmRleCkgPT4ge1xuICAgICAgICAgICAgICBpZiAobGlzdEVsZW0gIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHZhbHVlcy5wdXNoKGxpc3RFbGVtKTtcbiAgICAgICAgICAgICAgICBpblBhdHRlcm5zLnB1c2goYCQke2luZGV4ICsgMSArIGxpc3RJbmRleH1gKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBwYXR0ZXJucy5wdXNoKGAkJHtpbmRleH06bmFtZSAke25vdH0gSU4gKCR7aW5QYXR0ZXJucy5qb2luKCl9KWApO1xuICAgICAgICAgICAgaW5kZXggPSBpbmRleCArIDEgKyBpblBhdHRlcm5zLmxlbmd0aDtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoIW5vdEluKSB7XG4gICAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lKTtcbiAgICAgICAgICBwYXR0ZXJucy5wdXNoKGAkJHtpbmRleH06bmFtZSBJUyBOVUxMYCk7XG4gICAgICAgICAgaW5kZXggPSBpbmRleCArIDE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gSGFuZGxlIGVtcHR5IGFycmF5XG4gICAgICAgICAgaWYgKG5vdEluKSB7XG4gICAgICAgICAgICBwYXR0ZXJucy5wdXNoKCcxID0gMScpOyAvLyBSZXR1cm4gYWxsIHZhbHVlc1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwYXR0ZXJucy5wdXNoKCcxID0gMicpOyAvLyBSZXR1cm4gbm8gdmFsdWVzXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgaWYgKGZpZWxkVmFsdWUuJGluKSB7XG4gICAgICAgIGNyZWF0ZUNvbnN0cmFpbnQoXG4gICAgICAgICAgXy5mbGF0TWFwKGZpZWxkVmFsdWUuJGluLCBlbHQgPT4gZWx0KSxcbiAgICAgICAgICBmYWxzZVxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgaWYgKGZpZWxkVmFsdWUuJG5pbikge1xuICAgICAgICBjcmVhdGVDb25zdHJhaW50KFxuICAgICAgICAgIF8uZmxhdE1hcChmaWVsZFZhbHVlLiRuaW4sIGVsdCA9PiBlbHQpLFxuICAgICAgICAgIHRydWVcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBmaWVsZFZhbHVlLiRpbiAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sICdiYWQgJGluIHZhbHVlJyk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgZmllbGRWYWx1ZS4kbmluICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfSlNPTiwgJ2JhZCAkbmluIHZhbHVlJyk7XG4gICAgfVxuXG4gICAgaWYgKEFycmF5LmlzQXJyYXkoZmllbGRWYWx1ZS4kYWxsKSAmJiBpc0FycmF5RmllbGQpIHtcbiAgICAgIGlmIChpc0FueVZhbHVlUmVnZXhTdGFydHNXaXRoKGZpZWxkVmFsdWUuJGFsbCkpIHtcbiAgICAgICAgaWYgKCFpc0FsbFZhbHVlc1JlZ2V4T3JOb25lKGZpZWxkVmFsdWUuJGFsbCkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgICAnQWxsICRhbGwgdmFsdWVzIG11c3QgYmUgb2YgcmVnZXggdHlwZSBvciBub25lOiAnICsgZmllbGRWYWx1ZS4kYWxsXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZmllbGRWYWx1ZS4kYWxsLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgY29uc3QgdmFsdWUgPSBwcm9jZXNzUmVnZXhQYXR0ZXJuKGZpZWxkVmFsdWUuJGFsbFtpXS4kcmVnZXgpO1xuICAgICAgICAgIGZpZWxkVmFsdWUuJGFsbFtpXSA9IHZhbHVlLnN1YnN0cmluZygxKSArICclJztcbiAgICAgICAgfVxuICAgICAgICBwYXR0ZXJucy5wdXNoKGBhcnJheV9jb250YWluc19hbGxfcmVnZXgoJCR7aW5kZXh9Om5hbWUsICQke2luZGV4ICsgMX06Ompzb25iKWApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGF0dGVybnMucHVzaChgYXJyYXlfY29udGFpbnNfYWxsKCQke2luZGV4fTpuYW1lLCAkJHtpbmRleCArIDF9Ojpqc29uYilgKTtcbiAgICAgIH1cbiAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgSlNPTi5zdHJpbmdpZnkoZmllbGRWYWx1ZS4kYWxsKSk7XG4gICAgICBpbmRleCArPSAyO1xuICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShmaWVsZFZhbHVlLiRhbGwpKSB7XG4gICAgICBpZiAoZmllbGRWYWx1ZS4kYWxsLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICBwYXR0ZXJucy5wdXNoKGAkJHtpbmRleH06bmFtZSA9ICQke2luZGV4ICsgMX1gKTtcbiAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCBmaWVsZFZhbHVlLiRhbGxbMF0ub2JqZWN0SWQpO1xuICAgICAgICBpbmRleCArPSAyO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICh0eXBlb2YgZmllbGRWYWx1ZS4kZXhpc3RzICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgaWYgKHR5cGVvZiBmaWVsZFZhbHVlLiRleGlzdHMgPT09ICdvYmplY3QnICYmIGZpZWxkVmFsdWUuJGV4aXN0cy4kcmVsYXRpdmVUaW1lKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgJyRyZWxhdGl2ZVRpbWUgY2FuIG9ubHkgYmUgdXNlZCB3aXRoIHRoZSAkbHQsICRsdGUsICRndCwgYW5kICRndGUgb3BlcmF0b3JzJ1xuICAgICAgICApO1xuICAgICAgfSBlbHNlIGlmIChmaWVsZFZhbHVlLiRleGlzdHMpIHtcbiAgICAgICAgcGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgSVMgTk9UIE5VTExgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lIElTIE5VTExgKTtcbiAgICAgIH1cbiAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSk7XG4gICAgICBpbmRleCArPSAxO1xuICAgIH1cblxuICAgIGlmIChmaWVsZFZhbHVlLiRjb250YWluZWRCeSkge1xuICAgICAgY29uc3QgYXJyID0gZmllbGRWYWx1ZS4kY29udGFpbmVkQnk7XG4gICAgICBpZiAoIUFycmF5LmlzQXJyYXkoYXJyKSkge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLCBgYmFkICRjb250YWluZWRCeTogc2hvdWxkIGJlIGFuIGFycmF5YCk7XG4gICAgICB9XG5cbiAgICAgIHBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lIDxAICQke2luZGV4ICsgMX06Ompzb25iYCk7XG4gICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIEpTT04uc3RyaW5naWZ5KGFycikpO1xuICAgICAgaW5kZXggKz0gMjtcbiAgICB9XG5cbiAgICBpZiAoZmllbGRWYWx1ZS4kdGV4dCkge1xuICAgICAgY29uc3Qgc2VhcmNoID0gZmllbGRWYWx1ZS4kdGV4dC4kc2VhcmNoO1xuICAgICAgbGV0IGxhbmd1YWdlID0gJ2VuZ2xpc2gnO1xuICAgICAgaWYgKHR5cGVvZiBzZWFyY2ggIT09ICdvYmplY3QnKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sIGBiYWQgJHRleHQ6ICRzZWFyY2gsIHNob3VsZCBiZSBvYmplY3RgKTtcbiAgICAgIH1cbiAgICAgIGlmICghc2VhcmNoLiR0ZXJtIHx8IHR5cGVvZiBzZWFyY2guJHRlcm0gIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sIGBiYWQgJHRleHQ6ICR0ZXJtLCBzaG91bGQgYmUgc3RyaW5nYCk7XG4gICAgICB9XG4gICAgICBpZiAoc2VhcmNoLiRsYW5ndWFnZSAmJiB0eXBlb2Ygc2VhcmNoLiRsYW5ndWFnZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfSlNPTiwgYGJhZCAkdGV4dDogJGxhbmd1YWdlLCBzaG91bGQgYmUgc3RyaW5nYCk7XG4gICAgICB9IGVsc2UgaWYgKHNlYXJjaC4kbGFuZ3VhZ2UpIHtcbiAgICAgICAgbGFuZ3VhZ2UgPSBzZWFyY2guJGxhbmd1YWdlO1xuICAgICAgfVxuICAgICAgaWYgKHNlYXJjaC4kY2FzZVNlbnNpdGl2ZSAmJiB0eXBlb2Ygc2VhcmNoLiRjYXNlU2Vuc2l0aXZlICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICBgYmFkICR0ZXh0OiAkY2FzZVNlbnNpdGl2ZSwgc2hvdWxkIGJlIGJvb2xlYW5gXG4gICAgICAgICk7XG4gICAgICB9IGVsc2UgaWYgKHNlYXJjaC4kY2FzZVNlbnNpdGl2ZSkge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgIGBiYWQgJHRleHQ6ICRjYXNlU2Vuc2l0aXZlIG5vdCBzdXBwb3J0ZWQsIHBsZWFzZSB1c2UgJHJlZ2V4IG9yIGNyZWF0ZSBhIHNlcGFyYXRlIGxvd2VyIGNhc2UgY29sdW1uLmBcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIGlmIChzZWFyY2guJGRpYWNyaXRpY1NlbnNpdGl2ZSAmJiB0eXBlb2Ygc2VhcmNoLiRkaWFjcml0aWNTZW5zaXRpdmUgIT09ICdib29sZWFuJykge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgIGBiYWQgJHRleHQ6ICRkaWFjcml0aWNTZW5zaXRpdmUsIHNob3VsZCBiZSBib29sZWFuYFxuICAgICAgICApO1xuICAgICAgfSBlbHNlIGlmIChzZWFyY2guJGRpYWNyaXRpY1NlbnNpdGl2ZSA9PT0gZmFsc2UpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICBgYmFkICR0ZXh0OiAkZGlhY3JpdGljU2Vuc2l0aXZlIC0gZmFsc2Ugbm90IHN1cHBvcnRlZCwgaW5zdGFsbCBQb3N0Z3JlcyBVbmFjY2VudCBFeHRlbnNpb25gXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBwYXR0ZXJucy5wdXNoKFxuICAgICAgICBgdG9fdHN2ZWN0b3IoJCR7aW5kZXh9LCAkJHtpbmRleCArIDF9Om5hbWUpIEBAIHRvX3RzcXVlcnkoJCR7aW5kZXggKyAyfSwgJCR7aW5kZXggKyAzfSlgXG4gICAgICApO1xuICAgICAgdmFsdWVzLnB1c2gobGFuZ3VhZ2UsIGZpZWxkTmFtZSwgbGFuZ3VhZ2UsIHNlYXJjaC4kdGVybSk7XG4gICAgICBpbmRleCArPSA0O1xuICAgIH1cblxuICAgIGlmIChmaWVsZFZhbHVlLiRuZWFyU3BoZXJlKSB7XG4gICAgICBjb25zdCBwb2ludCA9IGZpZWxkVmFsdWUuJG5lYXJTcGhlcmU7XG4gICAgICBjb25zdCBkaXN0YW5jZSA9IGZpZWxkVmFsdWUuJG1heERpc3RhbmNlO1xuICAgICAgY29uc3QgZGlzdGFuY2VJbktNID0gZGlzdGFuY2UgKiA2MzcxICogMTAwMDtcbiAgICAgIHBhdHRlcm5zLnB1c2goXG4gICAgICAgIGBTVF9EaXN0YW5jZVNwaGVyZSgkJHtpbmRleH06bmFtZTo6Z2VvbWV0cnksIFBPSU5UKCQke2luZGV4ICsgMX0sICQke2luZGV4ICsgMlxuICAgICAgICB9KTo6Z2VvbWV0cnkpIDw9ICQke2luZGV4ICsgM31gXG4gICAgICApO1xuICAgICAgc29ydHMucHVzaChcbiAgICAgICAgYFNUX0Rpc3RhbmNlU3BoZXJlKCQke2luZGV4fTpuYW1lOjpnZW9tZXRyeSwgUE9JTlQoJCR7aW5kZXggKyAxfSwgJCR7aW5kZXggKyAyXG4gICAgICAgIH0pOjpnZW9tZXRyeSkgQVNDYFxuICAgICAgKTtcbiAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgcG9pbnQubG9uZ2l0dWRlLCBwb2ludC5sYXRpdHVkZSwgZGlzdGFuY2VJbktNKTtcbiAgICAgIGluZGV4ICs9IDQ7XG4gICAgfVxuXG4gICAgaWYgKGZpZWxkVmFsdWUuJHdpdGhpbiAmJiBmaWVsZFZhbHVlLiR3aXRoaW4uJGJveCkge1xuICAgICAgY29uc3QgYm94ID0gZmllbGRWYWx1ZS4kd2l0aGluLiRib3g7XG4gICAgICBjb25zdCBsZWZ0ID0gYm94WzBdLmxvbmdpdHVkZTtcbiAgICAgIGNvbnN0IGJvdHRvbSA9IGJveFswXS5sYXRpdHVkZTtcbiAgICAgIGNvbnN0IHJpZ2h0ID0gYm94WzFdLmxvbmdpdHVkZTtcbiAgICAgIGNvbnN0IHRvcCA9IGJveFsxXS5sYXRpdHVkZTtcblxuICAgICAgcGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWU6OnBvaW50IDxAICQke2luZGV4ICsgMX06OmJveGApO1xuICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCBgKCgke2xlZnR9LCAke2JvdHRvbX0pLCAoJHtyaWdodH0sICR7dG9wfSkpYCk7XG4gICAgICBpbmRleCArPSAyO1xuICAgIH1cblxuICAgIGlmIChmaWVsZFZhbHVlLiRnZW9XaXRoaW4gJiYgZmllbGRWYWx1ZS4kZ2VvV2l0aGluLiRjZW50ZXJTcGhlcmUpIHtcbiAgICAgIGNvbnN0IGNlbnRlclNwaGVyZSA9IGZpZWxkVmFsdWUuJGdlb1dpdGhpbi4kY2VudGVyU3BoZXJlO1xuICAgICAgaWYgKCFBcnJheS5pc0FycmF5KGNlbnRlclNwaGVyZSkgfHwgY2VudGVyU3BoZXJlLmxlbmd0aCA8IDIpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICAnYmFkICRnZW9XaXRoaW4gdmFsdWU7ICRjZW50ZXJTcGhlcmUgc2hvdWxkIGJlIGFuIGFycmF5IG9mIFBhcnNlLkdlb1BvaW50IGFuZCBkaXN0YW5jZSdcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIC8vIEdldCBwb2ludCwgY29udmVydCB0byBnZW8gcG9pbnQgaWYgbmVjZXNzYXJ5IGFuZCB2YWxpZGF0ZVxuICAgICAgbGV0IHBvaW50ID0gY2VudGVyU3BoZXJlWzBdO1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkocG9pbnQpICYmIHBvaW50Lmxlbmd0aCA9PT0gMikge1xuICAgICAgICBwb2ludCA9IG5ldyBQYXJzZS5HZW9Qb2ludChwb2ludFsxXSwgcG9pbnRbMF0pO1xuICAgICAgfSBlbHNlIGlmICghR2VvUG9pbnRDb2Rlci5pc1ZhbGlkSlNPTihwb2ludCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICAnYmFkICRnZW9XaXRoaW4gdmFsdWU7ICRjZW50ZXJTcGhlcmUgZ2VvIHBvaW50IGludmFsaWQnXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBQYXJzZS5HZW9Qb2ludC5fdmFsaWRhdGUocG9pbnQubGF0aXR1ZGUsIHBvaW50LmxvbmdpdHVkZSk7XG4gICAgICAvLyBHZXQgZGlzdGFuY2UgYW5kIHZhbGlkYXRlXG4gICAgICBjb25zdCBkaXN0YW5jZSA9IGNlbnRlclNwaGVyZVsxXTtcbiAgICAgIGlmIChpc05hTihkaXN0YW5jZSkgfHwgZGlzdGFuY2UgPCAwKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgJ2JhZCAkZ2VvV2l0aGluIHZhbHVlOyAkY2VudGVyU3BoZXJlIGRpc3RhbmNlIGludmFsaWQnXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBjb25zdCBkaXN0YW5jZUluS00gPSBkaXN0YW5jZSAqIDYzNzEgKiAxMDAwO1xuICAgICAgcGF0dGVybnMucHVzaChcbiAgICAgICAgYFNUX0Rpc3RhbmNlU3BoZXJlKCQke2luZGV4fTpuYW1lOjpnZW9tZXRyeSwgUE9JTlQoJCR7aW5kZXggKyAxfSwgJCR7aW5kZXggKyAyXG4gICAgICAgIH0pOjpnZW9tZXRyeSkgPD0gJCR7aW5kZXggKyAzfWBcbiAgICAgICk7XG4gICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIHBvaW50LmxvbmdpdHVkZSwgcG9pbnQubGF0aXR1ZGUsIGRpc3RhbmNlSW5LTSk7XG4gICAgICBpbmRleCArPSA0O1xuICAgIH1cblxuICAgIGlmIChmaWVsZFZhbHVlLiRnZW9XaXRoaW4gJiYgZmllbGRWYWx1ZS4kZ2VvV2l0aGluLiRwb2x5Z29uKSB7XG4gICAgICBjb25zdCBwb2x5Z29uID0gZmllbGRWYWx1ZS4kZ2VvV2l0aGluLiRwb2x5Z29uO1xuICAgICAgbGV0IHBvaW50cztcbiAgICAgIGlmICh0eXBlb2YgcG9seWdvbiA9PT0gJ29iamVjdCcgJiYgcG9seWdvbi5fX3R5cGUgPT09ICdQb2x5Z29uJykge1xuICAgICAgICBpZiAoIXBvbHlnb24uY29vcmRpbmF0ZXMgfHwgcG9seWdvbi5jb29yZGluYXRlcy5sZW5ndGggPCAzKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgICAgJ2JhZCAkZ2VvV2l0aGluIHZhbHVlOyBQb2x5Z29uLmNvb3JkaW5hdGVzIHNob3VsZCBjb250YWluIGF0IGxlYXN0IDMgbG9uL2xhdCBwYWlycydcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIHBvaW50cyA9IHBvbHlnb24uY29vcmRpbmF0ZXM7XG4gICAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkocG9seWdvbikpIHtcbiAgICAgICAgaWYgKHBvbHlnb24ubGVuZ3RoIDwgMykge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICAgICdiYWQgJGdlb1dpdGhpbiB2YWx1ZTsgJHBvbHlnb24gc2hvdWxkIGNvbnRhaW4gYXQgbGVhc3QgMyBHZW9Qb2ludHMnXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBwb2ludHMgPSBwb2x5Z29uO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICBcImJhZCAkZ2VvV2l0aGluIHZhbHVlOyAkcG9seWdvbiBzaG91bGQgYmUgUG9seWdvbiBvYmplY3Qgb3IgQXJyYXkgb2YgUGFyc2UuR2VvUG9pbnQnc1wiXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBwb2ludHMgPSBwb2ludHNcbiAgICAgICAgLm1hcChwb2ludCA9PiB7XG4gICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkocG9pbnQpICYmIHBvaW50Lmxlbmd0aCA9PT0gMikge1xuICAgICAgICAgICAgUGFyc2UuR2VvUG9pbnQuX3ZhbGlkYXRlKHBvaW50WzFdLCBwb2ludFswXSk7XG4gICAgICAgICAgICByZXR1cm4gYCgke3BvaW50WzBdfSwgJHtwb2ludFsxXX0pYDtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHR5cGVvZiBwb2ludCAhPT0gJ29iamVjdCcgfHwgcG9pbnQuX190eXBlICE9PSAnR2VvUG9pbnQnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLCAnYmFkICRnZW9XaXRoaW4gdmFsdWUnKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgUGFyc2UuR2VvUG9pbnQuX3ZhbGlkYXRlKHBvaW50LmxhdGl0dWRlLCBwb2ludC5sb25naXR1ZGUpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gYCgke3BvaW50LmxvbmdpdHVkZX0sICR7cG9pbnQubGF0aXR1ZGV9KWA7XG4gICAgICAgIH0pXG4gICAgICAgIC5qb2luKCcsICcpO1xuXG4gICAgICBwYXR0ZXJucy5wdXNoKGAkJHtpbmRleH06bmFtZTo6cG9pbnQgPEAgJCR7aW5kZXggKyAxfTo6cG9seWdvbmApO1xuICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCBgKCR7cG9pbnRzfSlgKTtcbiAgICAgIGluZGV4ICs9IDI7XG4gICAgfVxuICAgIGlmIChmaWVsZFZhbHVlLiRnZW9JbnRlcnNlY3RzICYmIGZpZWxkVmFsdWUuJGdlb0ludGVyc2VjdHMuJHBvaW50KSB7XG4gICAgICBjb25zdCBwb2ludCA9IGZpZWxkVmFsdWUuJGdlb0ludGVyc2VjdHMuJHBvaW50O1xuICAgICAgaWYgKHR5cGVvZiBwb2ludCAhPT0gJ29iamVjdCcgfHwgcG9pbnQuX190eXBlICE9PSAnR2VvUG9pbnQnKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgJ2JhZCAkZ2VvSW50ZXJzZWN0IHZhbHVlOyAkcG9pbnQgc2hvdWxkIGJlIEdlb1BvaW50J1xuICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgUGFyc2UuR2VvUG9pbnQuX3ZhbGlkYXRlKHBvaW50LmxhdGl0dWRlLCBwb2ludC5sb25naXR1ZGUpO1xuICAgICAgfVxuICAgICAgcGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWU6OnBvbHlnb24gQD4gJCR7aW5kZXggKyAxfTo6cG9pbnRgKTtcbiAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgYCgke3BvaW50LmxvbmdpdHVkZX0sICR7cG9pbnQubGF0aXR1ZGV9KWApO1xuICAgICAgaW5kZXggKz0gMjtcbiAgICB9XG5cbiAgICBpZiAoZmllbGRWYWx1ZS4kcmVnZXgpIHtcbiAgICAgIGxldCByZWdleCA9IGZpZWxkVmFsdWUuJHJlZ2V4O1xuICAgICAgbGV0IG9wZXJhdG9yID0gJ34nO1xuICAgICAgY29uc3Qgb3B0cyA9IGZpZWxkVmFsdWUuJG9wdGlvbnM7XG4gICAgICBpZiAob3B0cykge1xuICAgICAgICBpZiAob3B0cy5pbmRleE9mKCdpJykgPj0gMCkge1xuICAgICAgICAgIG9wZXJhdG9yID0gJ34qJztcbiAgICAgICAgfVxuICAgICAgICBpZiAob3B0cy5pbmRleE9mKCd4JykgPj0gMCkge1xuICAgICAgICAgIHJlZ2V4ID0gcmVtb3ZlV2hpdGVTcGFjZShyZWdleCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmVnZXggPSBwcm9jZXNzUmVnZXhQYXR0ZXJuKHJlZ2V4KTtcblxuICAgICAgaWYgKGZpZWxkTmFtZS5pbmRleE9mKCcuJykgPj0gMCkge1xuICAgICAgICBjb25zdCBuYW1lID0gdHJhbnNmb3JtRG90RmllbGQoZmllbGROYW1lKTtcbiAgICAgICAgcGF0dGVybnMucHVzaChgJCR7aW5kZXh9OnJhdyAke29wZXJhdG9yfSAnJCR7aW5kZXggKyAxfTpyYXcnYCk7XG4gICAgICAgIHZhbHVlcy5wdXNoKG5hbWUsIHJlZ2V4KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lICR7b3BlcmF0b3J9ICckJHtpbmRleCArIDF9OnJhdydgKTtcbiAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCByZWdleCk7XG4gICAgICB9XG4gICAgICBpbmRleCArPSAyO1xuICAgIH1cblxuICAgIGlmIChmaWVsZFZhbHVlLl9fdHlwZSA9PT0gJ1BvaW50ZXInKSB7XG4gICAgICBpZiAoaXNBcnJheUZpZWxkKSB7XG4gICAgICAgIHBhdHRlcm5zLnB1c2goYGFycmF5X2NvbnRhaW5zKCQke2luZGV4fTpuYW1lLCAkJHtpbmRleCArIDF9KWApO1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIEpTT04uc3RyaW5naWZ5KFtmaWVsZFZhbHVlXSkpO1xuICAgICAgICBpbmRleCArPSAyO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgPSAkJHtpbmRleCArIDF9YCk7XG4gICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgZmllbGRWYWx1ZS5vYmplY3RJZCk7XG4gICAgICAgIGluZGV4ICs9IDI7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGZpZWxkVmFsdWUuX190eXBlID09PSAnRGF0ZScpIHtcbiAgICAgIHBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lID0gJCR7aW5kZXggKyAxfWApO1xuICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCBmaWVsZFZhbHVlLmlzbyk7XG4gICAgICBpbmRleCArPSAyO1xuICAgIH1cblxuICAgIGlmIChmaWVsZFZhbHVlLl9fdHlwZSA9PT0gJ0dlb1BvaW50Jykge1xuICAgICAgcGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgfj0gUE9JTlQoJCR7aW5kZXggKyAxfSwgJCR7aW5kZXggKyAyfSlgKTtcbiAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgZmllbGRWYWx1ZS5sb25naXR1ZGUsIGZpZWxkVmFsdWUubGF0aXR1ZGUpO1xuICAgICAgaW5kZXggKz0gMztcbiAgICB9XG5cbiAgICBpZiAoZmllbGRWYWx1ZS5fX3R5cGUgPT09ICdQb2x5Z29uJykge1xuICAgICAgY29uc3QgdmFsdWUgPSBjb252ZXJ0UG9seWdvblRvU1FMKGZpZWxkVmFsdWUuY29vcmRpbmF0ZXMpO1xuICAgICAgcGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgfj0gJCR7aW5kZXggKyAxfTo6cG9seWdvbmApO1xuICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCB2YWx1ZSk7XG4gICAgICBpbmRleCArPSAyO1xuICAgIH1cblxuICAgIE9iamVjdC5rZXlzKFBhcnNlVG9Qb3NncmVzQ29tcGFyYXRvcikuZm9yRWFjaChjbXAgPT4ge1xuICAgICAgaWYgKGZpZWxkVmFsdWVbY21wXSB8fCBmaWVsZFZhbHVlW2NtcF0gPT09IDApIHtcbiAgICAgICAgY29uc3QgcGdDb21wYXJhdG9yID0gUGFyc2VUb1Bvc2dyZXNDb21wYXJhdG9yW2NtcF07XG4gICAgICAgIGxldCBjb25zdHJhaW50RmllbGROYW1lO1xuICAgICAgICBsZXQgcG9zdGdyZXNWYWx1ZSA9IHRvUG9zdGdyZXNWYWx1ZShmaWVsZFZhbHVlW2NtcF0pO1xuXG4gICAgICAgIGlmIChmaWVsZE5hbWUuaW5kZXhPZignLicpID49IDApIHtcbiAgICAgICAgICBjb25zdCBjYXN0VHlwZSA9IHRvUG9zdGdyZXNWYWx1ZUNhc3RUeXBlKGZpZWxkVmFsdWVbY21wXSk7XG4gICAgICAgICAgY29uc3RyYWludEZpZWxkTmFtZSA9IGNhc3RUeXBlXG4gICAgICAgICAgICA/IGBDQVNUICgoJHt0cmFuc2Zvcm1Eb3RGaWVsZChmaWVsZE5hbWUpfSkgQVMgJHtjYXN0VHlwZX0pYFxuICAgICAgICAgICAgOiB0cmFuc2Zvcm1Eb3RGaWVsZChmaWVsZE5hbWUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmICh0eXBlb2YgcG9zdGdyZXNWYWx1ZSA9PT0gJ29iamVjdCcgJiYgcG9zdGdyZXNWYWx1ZS4kcmVsYXRpdmVUaW1lKSB7XG4gICAgICAgICAgICBpZiAoc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdLnR5cGUgIT09ICdEYXRlJykge1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgICAgICAgICckcmVsYXRpdmVUaW1lIGNhbiBvbmx5IGJlIHVzZWQgd2l0aCBEYXRlIGZpZWxkJ1xuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgcGFyc2VyUmVzdWx0ID0gVXRpbHMucmVsYXRpdmVUaW1lVG9EYXRlKHBvc3RncmVzVmFsdWUuJHJlbGF0aXZlVGltZSk7XG4gICAgICAgICAgICBpZiAocGFyc2VyUmVzdWx0LnN0YXR1cyA9PT0gJ3N1Y2Nlc3MnKSB7XG4gICAgICAgICAgICAgIHBvc3RncmVzVmFsdWUgPSB0b1Bvc3RncmVzVmFsdWUocGFyc2VyUmVzdWx0LnJlc3VsdCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciB3aGlsZSBwYXJzaW5nIHJlbGF0aXZlIGRhdGUnLCBwYXJzZXJSZXN1bHQpO1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgICAgICAgIGBiYWQgJHJlbGF0aXZlVGltZSAoJHtwb3N0Z3Jlc1ZhbHVlLiRyZWxhdGl2ZVRpbWV9KSB2YWx1ZS4gJHtwYXJzZXJSZXN1bHQuaW5mb31gXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnN0cmFpbnRGaWVsZE5hbWUgPSBgJCR7aW5kZXgrK306bmFtZWA7XG4gICAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lKTtcbiAgICAgICAgfVxuICAgICAgICB2YWx1ZXMucHVzaChwb3N0Z3Jlc1ZhbHVlKTtcbiAgICAgICAgcGF0dGVybnMucHVzaChgJHtjb25zdHJhaW50RmllbGROYW1lfSAke3BnQ29tcGFyYXRvcn0gJCR7aW5kZXgrK31gKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGlmIChpbml0aWFsUGF0dGVybnNMZW5ndGggPT09IHBhdHRlcm5zLmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5PUEVSQVRJT05fRk9SQklEREVOLFxuICAgICAgICBgUG9zdGdyZXMgZG9lc24ndCBzdXBwb3J0IHRoaXMgcXVlcnkgdHlwZSB5ZXQgJHtKU09OLnN0cmluZ2lmeShmaWVsZFZhbHVlKX1gXG4gICAgICApO1xuICAgIH1cbiAgfVxuICB2YWx1ZXMgPSB2YWx1ZXMubWFwKHRyYW5zZm9ybVZhbHVlKTtcbiAgcmV0dXJuIHsgcGF0dGVybjogcGF0dGVybnMuam9pbignIEFORCAnKSwgdmFsdWVzLCBzb3J0cyB9O1xufTtcblxuZXhwb3J0IGNsYXNzIFBvc3RncmVzU3RvcmFnZUFkYXB0ZXIgaW1wbGVtZW50cyBTdG9yYWdlQWRhcHRlciB7XG4gIGNhblNvcnRPbkpvaW5UYWJsZXM6IGJvb2xlYW47XG4gIGVuYWJsZVNjaGVtYUhvb2tzOiBib29sZWFuO1xuXG4gIC8vIFByaXZhdGVcbiAgX2NvbGxlY3Rpb25QcmVmaXg6IHN0cmluZztcbiAgX2NsaWVudDogYW55O1xuICBfb25jaGFuZ2U6IGFueTtcbiAgX3BncDogYW55O1xuICBfc3RyZWFtOiBhbnk7XG4gIF91dWlkOiBhbnk7XG4gIHNjaGVtYUNhY2hlVHRsOiA/bnVtYmVyO1xuICBkaXNhYmxlSW5kZXhGaWVsZFZhbGlkYXRpb246IGJvb2xlYW47XG5cbiAgY29uc3RydWN0b3IoeyB1cmksIGNvbGxlY3Rpb25QcmVmaXggPSAnJywgZGF0YWJhc2VPcHRpb25zID0ge30gfTogYW55KSB7XG4gICAgY29uc3Qgb3B0aW9ucyA9IHsgLi4uZGF0YWJhc2VPcHRpb25zIH07XG4gICAgdGhpcy5fY29sbGVjdGlvblByZWZpeCA9IGNvbGxlY3Rpb25QcmVmaXg7XG4gICAgdGhpcy5lbmFibGVTY2hlbWFIb29rcyA9ICEhZGF0YWJhc2VPcHRpb25zLmVuYWJsZVNjaGVtYUhvb2tzO1xuICAgIHRoaXMuZGlzYWJsZUluZGV4RmllbGRWYWxpZGF0aW9uID0gISFkYXRhYmFzZU9wdGlvbnMuZGlzYWJsZUluZGV4RmllbGRWYWxpZGF0aW9uO1xuXG4gICAgdGhpcy5zY2hlbWFDYWNoZVR0bCA9IGRhdGFiYXNlT3B0aW9ucy5zY2hlbWFDYWNoZVR0bDtcbiAgICBmb3IgKGNvbnN0IGtleSBvZiBbJ2VuYWJsZVNjaGVtYUhvb2tzJywgJ3NjaGVtYUNhY2hlVHRsJywgJ2Rpc2FibGVJbmRleEZpZWxkVmFsaWRhdGlvbiddKSB7XG4gICAgICBkZWxldGUgb3B0aW9uc1trZXldO1xuICAgIH1cblxuICAgIGNvbnN0IHsgY2xpZW50LCBwZ3AgfSA9IGNyZWF0ZUNsaWVudCh1cmksIG9wdGlvbnMpO1xuICAgIHRoaXMuX2NsaWVudCA9IGNsaWVudDtcbiAgICB0aGlzLl9vbmNoYW5nZSA9ICgpID0+IHsgfTtcbiAgICB0aGlzLl9wZ3AgPSBwZ3A7XG4gICAgdGhpcy5fdXVpZCA9IHJhbmRvbVVVSUQoKTtcbiAgICB0aGlzLmNhblNvcnRPbkpvaW5UYWJsZXMgPSBmYWxzZTtcbiAgfVxuXG4gIHdhdGNoKGNhbGxiYWNrOiAoKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgdGhpcy5fb25jaGFuZ2UgPSBjYWxsYmFjaztcbiAgfVxuXG4gIC8vTm90ZSB0aGF0IGFuYWx5emU9dHJ1ZSB3aWxsIHJ1biB0aGUgcXVlcnksIGV4ZWN1dGluZyBJTlNFUlRTLCBERUxFVEVTLCBldGMuXG4gIGNyZWF0ZUV4cGxhaW5hYmxlUXVlcnkocXVlcnk6IHN0cmluZywgYW5hbHl6ZTogYm9vbGVhbiA9IGZhbHNlKSB7XG4gICAgaWYgKGFuYWx5emUpIHtcbiAgICAgIHJldHVybiAnRVhQTEFJTiAoQU5BTFlaRSwgRk9STUFUIEpTT04pICcgKyBxdWVyeTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuICdFWFBMQUlOIChGT1JNQVQgSlNPTikgJyArIHF1ZXJ5O1xuICAgIH1cbiAgfVxuXG4gIGhhbmRsZVNodXRkb3duKCkge1xuICAgIGlmICh0aGlzLl9zdHJlYW0pIHtcbiAgICAgIHRoaXMuX3N0cmVhbS5kb25lKCk7XG4gICAgICBkZWxldGUgdGhpcy5fc3RyZWFtO1xuICAgIH1cbiAgICBpZiAoIXRoaXMuX2NsaWVudCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLl9jbGllbnQuJHBvb2wuZW5kKCk7XG4gIH1cblxuICBhc3luYyBfbGlzdGVuVG9TY2hlbWEoKSB7XG4gICAgaWYgKCF0aGlzLl9zdHJlYW0gJiYgdGhpcy5lbmFibGVTY2hlbWFIb29rcykge1xuICAgICAgdGhpcy5fc3RyZWFtID0gYXdhaXQgdGhpcy5fY2xpZW50LmNvbm5lY3QoeyBkaXJlY3Q6IHRydWUgfSk7XG4gICAgICB0aGlzLl9zdHJlYW0uY2xpZW50Lm9uKCdub3RpZmljYXRpb24nLCBkYXRhID0+IHtcbiAgICAgICAgY29uc3QgcGF5bG9hZCA9IEpTT04ucGFyc2UoZGF0YS5wYXlsb2FkKTtcbiAgICAgICAgaWYgKHBheWxvYWQuc2VuZGVySWQgIT09IHRoaXMuX3V1aWQpIHtcbiAgICAgICAgICB0aGlzLl9vbmNoYW5nZSgpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIGF3YWl0IHRoaXMuX3N0cmVhbS5ub25lKCdMSVNURU4gJDF+JywgJ3NjaGVtYS5jaGFuZ2UnKTtcbiAgICB9XG4gIH1cblxuICBfbm90aWZ5U2NoZW1hQ2hhbmdlKCkge1xuICAgIGlmICh0aGlzLl9zdHJlYW0pIHtcbiAgICAgIHRoaXMuX3N0cmVhbVxuICAgICAgICAubm9uZSgnTk9USUZZICQxfiwgJDInLCBbJ3NjaGVtYS5jaGFuZ2UnLCB7IHNlbmRlcklkOiB0aGlzLl91dWlkIH1dKVxuICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICAgICAgY29uc29sZS5sb2coJ0ZhaWxlZCB0byBOb3RpZnk6JywgZXJyb3IpOyAvLyB1bmxpa2VseSB0byBldmVyIGhhcHBlblxuICAgICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBfZW5zdXJlU2NoZW1hQ29sbGVjdGlvbkV4aXN0cyhjb25uOiBhbnkpIHtcbiAgICBjb25uID0gY29ubiB8fCB0aGlzLl9jbGllbnQ7XG4gICAgYXdhaXQgY29ublxuICAgICAgLm5vbmUoXG4gICAgICAgICdDUkVBVEUgVEFCTEUgSUYgTk9UIEVYSVNUUyBcIl9TQ0hFTUFcIiAoIFwiY2xhc3NOYW1lXCIgdmFyQ2hhcigxMjApLCBcInNjaGVtYVwiIGpzb25iLCBcImlzUGFyc2VDbGFzc1wiIGJvb2wsIFBSSU1BUlkgS0VZIChcImNsYXNzTmFtZVwiKSApJ1xuICAgICAgKVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9KTtcbiAgfVxuXG4gIGFzeW5jIGNsYXNzRXhpc3RzKG5hbWU6IHN0cmluZykge1xuICAgIHJldHVybiB0aGlzLl9jbGllbnQub25lKFxuICAgICAgJ1NFTEVDVCBFWElTVFMgKFNFTEVDVCAxIEZST00gaW5mb3JtYXRpb25fc2NoZW1hLnRhYmxlcyBXSEVSRSB0YWJsZV9uYW1lID0gJDEpJyxcbiAgICAgIFtuYW1lXSxcbiAgICAgIGEgPT4gYS5leGlzdHNcbiAgICApO1xuICB9XG5cbiAgYXN5bmMgc2V0Q2xhc3NMZXZlbFBlcm1pc3Npb25zKGNsYXNzTmFtZTogc3RyaW5nLCBDTFBzOiBhbnkpIHtcbiAgICBhd2FpdCB0aGlzLl9jbGllbnQudGFzaygnc2V0LWNsYXNzLWxldmVsLXBlcm1pc3Npb25zJywgYXN5bmMgdCA9PiB7XG4gICAgICBjb25zdCB2YWx1ZXMgPSBbY2xhc3NOYW1lLCAnc2NoZW1hJywgJ2NsYXNzTGV2ZWxQZXJtaXNzaW9ucycsIEpTT04uc3RyaW5naWZ5KENMUHMpXTtcbiAgICAgIGF3YWl0IHQubm9uZShcbiAgICAgICAgYFVQREFURSBcIl9TQ0hFTUFcIiBTRVQgJDI6bmFtZSA9IGpzb25fb2JqZWN0X3NldF9rZXkoJDI6bmFtZSwgJDM6OnRleHQsICQ0Ojpqc29uYikgV0hFUkUgXCJjbGFzc05hbWVcIiA9ICQxYCxcbiAgICAgICAgdmFsdWVzXG4gICAgICApO1xuICAgIH0pO1xuICAgIHRoaXMuX25vdGlmeVNjaGVtYUNoYW5nZSgpO1xuICB9XG5cbiAgYXN5bmMgc2V0SW5kZXhlc1dpdGhTY2hlbWFGb3JtYXQoXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgc3VibWl0dGVkSW5kZXhlczogYW55LFxuICAgIGV4aXN0aW5nSW5kZXhlczogYW55ID0ge30sXG4gICAgZmllbGRzOiBhbnksXG4gICAgY29ubjogP2FueVxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25uID0gY29ubiB8fCB0aGlzLl9jbGllbnQ7XG4gICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgaWYgKHN1Ym1pdHRlZEluZGV4ZXMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH1cbiAgICBpZiAoT2JqZWN0LmtleXMoZXhpc3RpbmdJbmRleGVzKS5sZW5ndGggPT09IDApIHtcbiAgICAgIGV4aXN0aW5nSW5kZXhlcyA9IHsgX2lkXzogeyBfaWQ6IDEgfSB9O1xuICAgIH1cbiAgICBjb25zdCBkZWxldGVkSW5kZXhlcyA9IFtdO1xuICAgIGNvbnN0IGluc2VydGVkSW5kZXhlcyA9IFtdO1xuICAgIE9iamVjdC5rZXlzKHN1Ym1pdHRlZEluZGV4ZXMpLmZvckVhY2gobmFtZSA9PiB7XG4gICAgICBjb25zdCBmaWVsZCA9IHN1Ym1pdHRlZEluZGV4ZXNbbmFtZV07XG4gICAgICBpZiAoZXhpc3RpbmdJbmRleGVzW25hbWVdICYmIGZpZWxkLl9fb3AgIT09ICdEZWxldGUnKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX1FVRVJZLCBgSW5kZXggJHtuYW1lfSBleGlzdHMsIGNhbm5vdCB1cGRhdGUuYCk7XG4gICAgICB9XG4gICAgICBpZiAoIWV4aXN0aW5nSW5kZXhlc1tuYW1lXSAmJiBmaWVsZC5fX29wID09PSAnRGVsZXRlJykge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9RVUVSWSxcbiAgICAgICAgICBgSW5kZXggJHtuYW1lfSBkb2VzIG5vdCBleGlzdCwgY2Fubm90IGRlbGV0ZS5gXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBpZiAoZmllbGQuX19vcCA9PT0gJ0RlbGV0ZScpIHtcbiAgICAgICAgZGVsZXRlZEluZGV4ZXMucHVzaChuYW1lKTtcbiAgICAgICAgZGVsZXRlIGV4aXN0aW5nSW5kZXhlc1tuYW1lXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIE9iamVjdC5rZXlzKGZpZWxkKS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgIXRoaXMuZGlzYWJsZUluZGV4RmllbGRWYWxpZGF0aW9uICYmXG4gICAgICAgICAgICAhT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGZpZWxkcywga2V5KVxuICAgICAgICAgICkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX1FVRVJZLFxuICAgICAgICAgICAgICBgRmllbGQgJHtrZXl9IGRvZXMgbm90IGV4aXN0LCBjYW5ub3QgYWRkIGluZGV4LmBcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgZXhpc3RpbmdJbmRleGVzW25hbWVdID0gZmllbGQ7XG4gICAgICAgIGluc2VydGVkSW5kZXhlcy5wdXNoKHtcbiAgICAgICAgICBrZXk6IGZpZWxkLFxuICAgICAgICAgIG5hbWUsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuICAgIGF3YWl0IGNvbm4udHgoJ3NldC1pbmRleGVzLXdpdGgtc2NoZW1hLWZvcm1hdCcsIGFzeW5jIHQgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgaWYgKGluc2VydGVkSW5kZXhlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgYXdhaXQgc2VsZi5jcmVhdGVJbmRleGVzKGNsYXNzTmFtZSwgaW5zZXJ0ZWRJbmRleGVzLCB0KTtcbiAgICAgICAgfVxuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAvLyBwZy1wcm9taXNlIHVzZSBCYXRjaCBlcnJvciBzZWUgaHR0cHM6Ly9naXRodWIuY29tL3ZpdGFseS10L3NwZXgvYmxvYi9lNTcyMDMwZjI2MWJlMWE4ZTkzNDFmYzZmNjM3ZTM2YWQwN2Y1MjMxL3NyYy9lcnJvcnMvYmF0Y2guanMjTDU5XG4gICAgICAgIGNvbnN0IGNvbHVtbkRvZXNOb3RFeGlzdEVycm9yID0gZS5nZXRFcnJvcnMgJiYgZS5nZXRFcnJvcnMoKVswXSAmJiBlLmdldEVycm9ycygpWzBdLmNvZGUgPT09ICc0MjcwMyc7XG4gICAgICAgIC8vIFNwZWNpZmljIGNhc2Ugd2hlbiB0aGUgY29sdW1uIGRvZXMgbm90IGV4aXN0XG4gICAgICAgIGlmIChjb2x1bW5Eb2VzTm90RXhpc3RFcnJvcikge1xuICAgICAgICAgIC8vIElmIHRoZSBkaXNhYmxlSW5kZXhGaWVsZFZhbGlkYXRpb24gaXMgdHJ1ZSwgd2Ugc2hvdWxkIGlnbm9yZSB0aGUgZXJyb3JcbiAgICAgICAgICBpZiAoIXRoaXMuZGlzYWJsZUluZGV4RmllbGRWYWxpZGF0aW9uKSB7XG4gICAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoZGVsZXRlZEluZGV4ZXMubGVuZ3RoID4gMCkge1xuICAgICAgICBhd2FpdCBzZWxmLmRyb3BJbmRleGVzKGNsYXNzTmFtZSwgZGVsZXRlZEluZGV4ZXMsIHQpO1xuICAgICAgfVxuICAgICAgYXdhaXQgdC5ub25lKFxuICAgICAgICAnVVBEQVRFIFwiX1NDSEVNQVwiIFNFVCAkMjpuYW1lID0ganNvbl9vYmplY3Rfc2V0X2tleSgkMjpuYW1lLCAkMzo6dGV4dCwgJDQ6Ompzb25iKSBXSEVSRSBcImNsYXNzTmFtZVwiID0gJDEnLFxuICAgICAgICBbY2xhc3NOYW1lLCAnc2NoZW1hJywgJ2luZGV4ZXMnLCBKU09OLnN0cmluZ2lmeShleGlzdGluZ0luZGV4ZXMpXVxuICAgICAgKTtcbiAgICB9KTtcbiAgICB0aGlzLl9ub3RpZnlTY2hlbWFDaGFuZ2UoKTtcbiAgfVxuXG4gIGFzeW5jIGNyZWF0ZUNsYXNzKGNsYXNzTmFtZTogc3RyaW5nLCBzY2hlbWE6IFNjaGVtYVR5cGUsIGNvbm46ID9hbnkpIHtcbiAgICBjb25uID0gY29ubiB8fCB0aGlzLl9jbGllbnQ7XG4gICAgY29uc3QgcGFyc2VTY2hlbWEgPSBhd2FpdCBjb25uXG4gICAgICAudHgoJ2NyZWF0ZS1jbGFzcycsIGFzeW5jIHQgPT4ge1xuICAgICAgICBhd2FpdCB0aGlzLmNyZWF0ZVRhYmxlKGNsYXNzTmFtZSwgc2NoZW1hLCB0KTtcbiAgICAgICAgYXdhaXQgdC5ub25lKFxuICAgICAgICAgICdJTlNFUlQgSU5UTyBcIl9TQ0hFTUFcIiAoXCJjbGFzc05hbWVcIiwgXCJzY2hlbWFcIiwgXCJpc1BhcnNlQ2xhc3NcIikgVkFMVUVTICgkPGNsYXNzTmFtZT4sICQ8c2NoZW1hPiwgdHJ1ZSknLFxuICAgICAgICAgIHsgY2xhc3NOYW1lLCBzY2hlbWEgfVxuICAgICAgICApO1xuICAgICAgICBhd2FpdCB0aGlzLnNldEluZGV4ZXNXaXRoU2NoZW1hRm9ybWF0KGNsYXNzTmFtZSwgc2NoZW1hLmluZGV4ZXMsIHt9LCBzY2hlbWEuZmllbGRzLCB0KTtcbiAgICAgICAgcmV0dXJuIHRvUGFyc2VTY2hlbWEoc2NoZW1hKTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyID0+IHtcbiAgICAgICAgaWYgKGVyci5jb2RlID09PSBQb3N0Z3Jlc1VuaXF1ZUluZGV4VmlvbGF0aW9uRXJyb3IgJiYgZXJyLmRldGFpbC5pbmNsdWRlcyhjbGFzc05hbWUpKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLkRVUExJQ0FURV9WQUxVRSwgYENsYXNzICR7Y2xhc3NOYW1lfSBhbHJlYWR5IGV4aXN0cy5gKTtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBlcnI7XG4gICAgICB9KTtcbiAgICB0aGlzLl9ub3RpZnlTY2hlbWFDaGFuZ2UoKTtcbiAgICByZXR1cm4gcGFyc2VTY2hlbWE7XG4gIH1cblxuICAvLyBKdXN0IGNyZWF0ZSBhIHRhYmxlLCBkbyBub3QgaW5zZXJ0IGluIHNjaGVtYVxuICBhc3luYyBjcmVhdGVUYWJsZShjbGFzc05hbWU6IHN0cmluZywgc2NoZW1hOiBTY2hlbWFUeXBlLCBjb25uOiBhbnkpIHtcbiAgICBjb25uID0gY29ubiB8fCB0aGlzLl9jbGllbnQ7XG4gICAgZGVidWcoJ2NyZWF0ZVRhYmxlJyk7XG4gICAgY29uc3QgdmFsdWVzQXJyYXkgPSBbXTtcbiAgICBjb25zdCBwYXR0ZXJuc0FycmF5ID0gW107XG4gICAgY29uc3QgZmllbGRzID0gT2JqZWN0LmFzc2lnbih7fSwgc2NoZW1hLmZpZWxkcyk7XG4gICAgaWYgKGNsYXNzTmFtZSA9PT0gJ19Vc2VyJykge1xuICAgICAgZmllbGRzLl9lbWFpbF92ZXJpZnlfdG9rZW5fZXhwaXJlc19hdCA9IHsgdHlwZTogJ0RhdGUnIH07XG4gICAgICBmaWVsZHMuX2VtYWlsX3ZlcmlmeV90b2tlbiA9IHsgdHlwZTogJ1N0cmluZycgfTtcbiAgICAgIGZpZWxkcy5fYWNjb3VudF9sb2Nrb3V0X2V4cGlyZXNfYXQgPSB7IHR5cGU6ICdEYXRlJyB9O1xuICAgICAgZmllbGRzLl9mYWlsZWRfbG9naW5fY291bnQgPSB7IHR5cGU6ICdOdW1iZXInIH07XG4gICAgICBmaWVsZHMuX3BlcmlzaGFibGVfdG9rZW4gPSB7IHR5cGU6ICdTdHJpbmcnIH07XG4gICAgICBmaWVsZHMuX3BlcmlzaGFibGVfdG9rZW5fZXhwaXJlc19hdCA9IHsgdHlwZTogJ0RhdGUnIH07XG4gICAgICBmaWVsZHMuX3Bhc3N3b3JkX2NoYW5nZWRfYXQgPSB7IHR5cGU6ICdEYXRlJyB9O1xuICAgICAgZmllbGRzLl9wYXNzd29yZF9oaXN0b3J5ID0geyB0eXBlOiAnQXJyYXknIH07XG4gICAgfVxuICAgIGxldCBpbmRleCA9IDI7XG4gICAgY29uc3QgcmVsYXRpb25zID0gW107XG4gICAgT2JqZWN0LmtleXMoZmllbGRzKS5mb3JFYWNoKGZpZWxkTmFtZSA9PiB7XG4gICAgICBjb25zdCBwYXJzZVR5cGUgPSBmaWVsZHNbZmllbGROYW1lXTtcbiAgICAgIC8vIFNraXAgd2hlbiBpdCdzIGEgcmVsYXRpb25cbiAgICAgIC8vIFdlJ2xsIGNyZWF0ZSB0aGUgdGFibGVzIGxhdGVyXG4gICAgICBpZiAocGFyc2VUeXBlLnR5cGUgPT09ICdSZWxhdGlvbicpIHtcbiAgICAgICAgcmVsYXRpb25zLnB1c2goZmllbGROYW1lKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgaWYgKFsnX3JwZXJtJywgJ193cGVybSddLmluZGV4T2YoZmllbGROYW1lKSA+PSAwKSB7XG4gICAgICAgIHBhcnNlVHlwZS5jb250ZW50cyA9IHsgdHlwZTogJ1N0cmluZycgfTtcbiAgICAgIH1cbiAgICAgIHZhbHVlc0FycmF5LnB1c2goZmllbGROYW1lKTtcbiAgICAgIHZhbHVlc0FycmF5LnB1c2gocGFyc2VUeXBlVG9Qb3N0Z3Jlc1R5cGUocGFyc2VUeXBlKSk7XG4gICAgICBwYXR0ZXJuc0FycmF5LnB1c2goYCQke2luZGV4fTpuYW1lICQke2luZGV4ICsgMX06cmF3YCk7XG4gICAgICBpZiAoZmllbGROYW1lID09PSAnb2JqZWN0SWQnKSB7XG4gICAgICAgIHBhdHRlcm5zQXJyYXkucHVzaChgUFJJTUFSWSBLRVkgKCQke2luZGV4fTpuYW1lKWApO1xuICAgICAgfVxuICAgICAgaW5kZXggPSBpbmRleCArIDI7XG4gICAgfSk7XG4gICAgY29uc3QgcXMgPSBgQ1JFQVRFIFRBQkxFIElGIE5PVCBFWElTVFMgJDE6bmFtZSAoJHtwYXR0ZXJuc0FycmF5LmpvaW4oKX0pYDtcbiAgICBjb25zdCB2YWx1ZXMgPSBbY2xhc3NOYW1lLCAuLi52YWx1ZXNBcnJheV07XG5cbiAgICByZXR1cm4gY29ubi50YXNrKCdjcmVhdGUtdGFibGUnLCBhc3luYyB0ID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHQubm9uZShxcywgdmFsdWVzKTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIGlmIChlcnJvci5jb2RlICE9PSBQb3N0Z3Jlc0R1cGxpY2F0ZVJlbGF0aW9uRXJyb3IpIHtcbiAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgfVxuICAgICAgICAvLyBFTFNFOiBUYWJsZSBhbHJlYWR5IGV4aXN0cywgbXVzdCBoYXZlIGJlZW4gY3JlYXRlZCBieSBhIGRpZmZlcmVudCByZXF1ZXN0LiBJZ25vcmUgdGhlIGVycm9yLlxuICAgICAgfVxuICAgICAgYXdhaXQgdC50eCgnY3JlYXRlLXRhYmxlLXR4JywgdHggPT4ge1xuICAgICAgICByZXR1cm4gdHguYmF0Y2goXG4gICAgICAgICAgcmVsYXRpb25zLm1hcChmaWVsZE5hbWUgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIHR4Lm5vbmUoXG4gICAgICAgICAgICAgICdDUkVBVEUgVEFCTEUgSUYgTk9UIEVYSVNUUyAkPGpvaW5UYWJsZTpuYW1lPiAoXCJyZWxhdGVkSWRcIiB2YXJDaGFyKDEyMCksIFwib3duaW5nSWRcIiB2YXJDaGFyKDEyMCksIFBSSU1BUlkgS0VZKFwicmVsYXRlZElkXCIsIFwib3duaW5nSWRcIikgKScsXG4gICAgICAgICAgICAgIHsgam9pblRhYmxlOiBgX0pvaW46JHtmaWVsZE5hbWV9OiR7Y2xhc3NOYW1lfWAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9KVxuICAgICAgICApO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBhc3luYyBzY2hlbWFVcGdyYWRlKGNsYXNzTmFtZTogc3RyaW5nLCBzY2hlbWE6IFNjaGVtYVR5cGUsIGNvbm46IGFueSkge1xuICAgIGRlYnVnKCdzY2hlbWFVcGdyYWRlJyk7XG4gICAgY29ubiA9IGNvbm4gfHwgdGhpcy5fY2xpZW50O1xuICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuXG4gICAgYXdhaXQgY29ubi50YXNrKCdzY2hlbWEtdXBncmFkZScsIGFzeW5jIHQgPT4ge1xuICAgICAgY29uc3QgY29sdW1ucyA9IGF3YWl0IHQubWFwKFxuICAgICAgICAnU0VMRUNUIGNvbHVtbl9uYW1lIEZST00gaW5mb3JtYXRpb25fc2NoZW1hLmNvbHVtbnMgV0hFUkUgdGFibGVfbmFtZSA9ICQ8Y2xhc3NOYW1lPicsXG4gICAgICAgIHsgY2xhc3NOYW1lIH0sXG4gICAgICAgIGEgPT4gYS5jb2x1bW5fbmFtZVxuICAgICAgKTtcbiAgICAgIGNvbnN0IG5ld0NvbHVtbnMgPSBPYmplY3Qua2V5cyhzY2hlbWEuZmllbGRzKVxuICAgICAgICAuZmlsdGVyKGl0ZW0gPT4gY29sdW1ucy5pbmRleE9mKGl0ZW0pID09PSAtMSlcbiAgICAgICAgLm1hcChmaWVsZE5hbWUgPT4gc2VsZi5hZGRGaWVsZElmTm90RXhpc3RzKGNsYXNzTmFtZSwgZmllbGROYW1lLCBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0pKTtcblxuICAgICAgYXdhaXQgdC5iYXRjaChuZXdDb2x1bW5zKTtcbiAgICB9KTtcbiAgfVxuXG4gIGFzeW5jIGFkZEZpZWxkSWZOb3RFeGlzdHMoY2xhc3NOYW1lOiBzdHJpbmcsIGZpZWxkTmFtZTogc3RyaW5nLCB0eXBlOiBhbnkpIHtcbiAgICAvLyBUT0RPOiBNdXN0IGJlIHJldmlzZWQgZm9yIGludmFsaWQgbG9naWMuLi5cbiAgICBkZWJ1ZygnYWRkRmllbGRJZk5vdEV4aXN0cycpO1xuICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgIGF3YWl0IHRoaXMuX2NsaWVudC50eCgnYWRkLWZpZWxkLWlmLW5vdC1leGlzdHMnLCBhc3luYyB0ID0+IHtcbiAgICAgIGlmICh0eXBlLnR5cGUgIT09ICdSZWxhdGlvbicpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCB0Lm5vbmUoXG4gICAgICAgICAgICAnQUxURVIgVEFCTEUgJDxjbGFzc05hbWU6bmFtZT4gQUREIENPTFVNTiBJRiBOT1QgRVhJU1RTICQ8ZmllbGROYW1lOm5hbWU+ICQ8cG9zdGdyZXNUeXBlOnJhdz4nLFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgICAgICAgIGZpZWxkTmFtZSxcbiAgICAgICAgICAgICAgcG9zdGdyZXNUeXBlOiBwYXJzZVR5cGVUb1Bvc3RncmVzVHlwZSh0eXBlKSxcbiAgICAgICAgICAgIH1cbiAgICAgICAgICApO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgIGlmIChlcnJvci5jb2RlID09PSBQb3N0Z3Jlc1JlbGF0aW9uRG9lc05vdEV4aXN0RXJyb3IpIHtcbiAgICAgICAgICAgIHJldHVybiBzZWxmLmNyZWF0ZUNsYXNzKGNsYXNzTmFtZSwgeyBmaWVsZHM6IHsgW2ZpZWxkTmFtZV06IHR5cGUgfSB9LCB0KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKGVycm9yLmNvZGUgIT09IFBvc3RncmVzRHVwbGljYXRlQ29sdW1uRXJyb3IpIHtcbiAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBDb2x1bW4gYWxyZWFkeSBleGlzdHMsIGNyZWF0ZWQgYnkgb3RoZXIgcmVxdWVzdC4gQ2Fycnkgb24gdG8gc2VlIGlmIGl0J3MgdGhlIHJpZ2h0IHR5cGUuXG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGF3YWl0IHQubm9uZShcbiAgICAgICAgICAnQ1JFQVRFIFRBQkxFIElGIE5PVCBFWElTVFMgJDxqb2luVGFibGU6bmFtZT4gKFwicmVsYXRlZElkXCIgdmFyQ2hhcigxMjApLCBcIm93bmluZ0lkXCIgdmFyQ2hhcigxMjApLCBQUklNQVJZIEtFWShcInJlbGF0ZWRJZFwiLCBcIm93bmluZ0lkXCIpICknLFxuICAgICAgICAgIHsgam9pblRhYmxlOiBgX0pvaW46JHtmaWVsZE5hbWV9OiR7Y2xhc3NOYW1lfWAgfVxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0LmFueShcbiAgICAgICAgJ1NFTEVDVCBcInNjaGVtYVwiIEZST00gXCJfU0NIRU1BXCIgV0hFUkUgXCJjbGFzc05hbWVcIiA9ICQ8Y2xhc3NOYW1lPiBhbmQgKFwic2NoZW1hXCI6Ompzb24tPlxcJ2ZpZWxkc1xcJy0+JDxmaWVsZE5hbWU+KSBpcyBub3QgbnVsbCcsXG4gICAgICAgIHsgY2xhc3NOYW1lLCBmaWVsZE5hbWUgfVxuICAgICAgKTtcblxuICAgICAgaWYgKHJlc3VsdFswXSkge1xuICAgICAgICB0aHJvdyAnQXR0ZW1wdGVkIHRvIGFkZCBhIGZpZWxkIHRoYXQgYWxyZWFkeSBleGlzdHMnO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgcGF0aCA9IGB7ZmllbGRzLCR7ZmllbGROYW1lfX1gO1xuICAgICAgICBhd2FpdCB0Lm5vbmUoXG4gICAgICAgICAgJ1VQREFURSBcIl9TQ0hFTUFcIiBTRVQgXCJzY2hlbWFcIj1qc29uYl9zZXQoXCJzY2hlbWFcIiwgJDxwYXRoPiwgJDx0eXBlPikgIFdIRVJFIFwiY2xhc3NOYW1lXCI9JDxjbGFzc05hbWU+JyxcbiAgICAgICAgICB7IHBhdGgsIHR5cGUsIGNsYXNzTmFtZSB9XG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgdGhpcy5fbm90aWZ5U2NoZW1hQ2hhbmdlKCk7XG4gIH1cblxuICBhc3luYyB1cGRhdGVGaWVsZE9wdGlvbnMoY2xhc3NOYW1lOiBzdHJpbmcsIGZpZWxkTmFtZTogc3RyaW5nLCB0eXBlOiBhbnkpIHtcbiAgICBhd2FpdCB0aGlzLl9jbGllbnQudHgoJ3VwZGF0ZS1zY2hlbWEtZmllbGQtb3B0aW9ucycsIGFzeW5jIHQgPT4ge1xuICAgICAgY29uc3QgcGF0aCA9IGB7ZmllbGRzLCR7ZmllbGROYW1lfX1gO1xuICAgICAgYXdhaXQgdC5ub25lKFxuICAgICAgICAnVVBEQVRFIFwiX1NDSEVNQVwiIFNFVCBcInNjaGVtYVwiPWpzb25iX3NldChcInNjaGVtYVwiLCAkPHBhdGg+LCAkPHR5cGU+KSAgV0hFUkUgXCJjbGFzc05hbWVcIj0kPGNsYXNzTmFtZT4nLFxuICAgICAgICB7IHBhdGgsIHR5cGUsIGNsYXNzTmFtZSB9XG4gICAgICApO1xuICAgIH0pO1xuICB9XG5cbiAgLy8gRHJvcHMgYSBjb2xsZWN0aW9uLiBSZXNvbHZlcyB3aXRoIHRydWUgaWYgaXQgd2FzIGEgUGFyc2UgU2NoZW1hIChlZy4gX1VzZXIsIEN1c3RvbSwgZXRjLilcbiAgLy8gYW5kIHJlc29sdmVzIHdpdGggZmFsc2UgaWYgaXQgd2Fzbid0IChlZy4gYSBqb2luIHRhYmxlKS4gUmVqZWN0cyBpZiBkZWxldGlvbiB3YXMgaW1wb3NzaWJsZS5cbiAgYXN5bmMgZGVsZXRlQ2xhc3MoY2xhc3NOYW1lOiBzdHJpbmcpIHtcbiAgICBjb25zdCBvcGVyYXRpb25zID0gW1xuICAgICAgeyBxdWVyeTogYERST1AgVEFCTEUgSUYgRVhJU1RTICQxOm5hbWVgLCB2YWx1ZXM6IFtjbGFzc05hbWVdIH0sXG4gICAgICB7XG4gICAgICAgIHF1ZXJ5OiBgREVMRVRFIEZST00gXCJfU0NIRU1BXCIgV0hFUkUgXCJjbGFzc05hbWVcIiA9ICQxYCxcbiAgICAgICAgdmFsdWVzOiBbY2xhc3NOYW1lXSxcbiAgICAgIH0sXG4gICAgXTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuX2NsaWVudFxuICAgICAgLnR4KHQgPT4gdC5ub25lKHRoaXMuX3BncC5oZWxwZXJzLmNvbmNhdChvcGVyYXRpb25zKSkpXG4gICAgICAudGhlbigoKSA9PiBjbGFzc05hbWUuaW5kZXhPZignX0pvaW46JykgIT0gMCk7IC8vIHJlc29sdmVzIHdpdGggZmFsc2Ugd2hlbiBfSm9pbiB0YWJsZVxuXG4gICAgdGhpcy5fbm90aWZ5U2NoZW1hQ2hhbmdlKCk7XG4gICAgcmV0dXJuIHJlc3BvbnNlO1xuICB9XG5cbiAgLy8gRGVsZXRlIGFsbCBkYXRhIGtub3duIHRvIHRoaXMgYWRhcHRlci4gVXNlZCBmb3IgdGVzdGluZy5cbiAgYXN5bmMgZGVsZXRlQWxsQ2xhc3NlcygpIHtcbiAgICBjb25zdCBub3cgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcbiAgICBjb25zdCBoZWxwZXJzID0gdGhpcy5fcGdwLmhlbHBlcnM7XG4gICAgZGVidWcoJ2RlbGV0ZUFsbENsYXNzZXMnKTtcbiAgICBpZiAodGhpcy5fY2xpZW50Py4kcG9vbC5lbmRlZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBhd2FpdCB0aGlzLl9jbGllbnRcbiAgICAgIC50YXNrKCdkZWxldGUtYWxsLWNsYXNzZXMnLCBhc3luYyB0ID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgdC5hbnkoJ1NFTEVDVCAqIEZST00gXCJfU0NIRU1BXCInKTtcbiAgICAgICAgICBjb25zdCBqb2lucyA9IHJlc3VsdHMucmVkdWNlKChsaXN0OiBBcnJheTxzdHJpbmc+LCBzY2hlbWE6IGFueSkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIGxpc3QuY29uY2F0KGpvaW5UYWJsZXNGb3JTY2hlbWEoc2NoZW1hLnNjaGVtYSkpO1xuICAgICAgICAgIH0sIFtdKTtcbiAgICAgICAgICBjb25zdCBjbGFzc2VzID0gW1xuICAgICAgICAgICAgJ19TQ0hFTUEnLFxuICAgICAgICAgICAgJ19QdXNoU3RhdHVzJyxcbiAgICAgICAgICAgICdfSm9iU3RhdHVzJyxcbiAgICAgICAgICAgICdfSm9iU2NoZWR1bGUnLFxuICAgICAgICAgICAgJ19Ib29rcycsXG4gICAgICAgICAgICAnX0dsb2JhbENvbmZpZycsXG4gICAgICAgICAgICAnX0dyYXBoUUxDb25maWcnLFxuICAgICAgICAgICAgJ19BdWRpZW5jZScsXG4gICAgICAgICAgICAnX0lkZW1wb3RlbmN5JyxcbiAgICAgICAgICAgIC4uLnJlc3VsdHMubWFwKHJlc3VsdCA9PiByZXN1bHQuY2xhc3NOYW1lKSxcbiAgICAgICAgICAgIC4uLmpvaW5zLFxuICAgICAgICAgIF07XG4gICAgICAgICAgY29uc3QgcXVlcmllcyA9IGNsYXNzZXMubWFwKGNsYXNzTmFtZSA9PiAoe1xuICAgICAgICAgICAgcXVlcnk6ICdEUk9QIFRBQkxFIElGIEVYSVNUUyAkPGNsYXNzTmFtZTpuYW1lPicsXG4gICAgICAgICAgICB2YWx1ZXM6IHsgY2xhc3NOYW1lIH0sXG4gICAgICAgICAgfSkpO1xuICAgICAgICAgIGF3YWl0IHQudHgodHggPT4gdHgubm9uZShoZWxwZXJzLmNvbmNhdChxdWVyaWVzKSkpO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgIGlmIChlcnJvci5jb2RlICE9PSBQb3N0Z3Jlc1JlbGF0aW9uRG9lc05vdEV4aXN0RXJyb3IpIHtcbiAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBObyBfU0NIRU1BIGNvbGxlY3Rpb24uIERvbid0IGRlbGV0ZSBhbnl0aGluZy5cbiAgICAgICAgfVxuICAgICAgfSlcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgZGVidWcoYGRlbGV0ZUFsbENsYXNzZXMgZG9uZSBpbiAke25ldyBEYXRlKCkuZ2V0VGltZSgpIC0gbm93fWApO1xuICAgICAgfSk7XG4gIH1cblxuICAvLyBSZW1vdmUgdGhlIGNvbHVtbiBhbmQgYWxsIHRoZSBkYXRhLiBGb3IgUmVsYXRpb25zLCB0aGUgX0pvaW4gY29sbGVjdGlvbiBpcyBoYW5kbGVkXG4gIC8vIHNwZWNpYWxseSwgdGhpcyBmdW5jdGlvbiBkb2VzIG5vdCBkZWxldGUgX0pvaW4gY29sdW1ucy4gSXQgc2hvdWxkLCBob3dldmVyLCBpbmRpY2F0ZVxuICAvLyB0aGF0IHRoZSByZWxhdGlvbiBmaWVsZHMgZG9lcyBub3QgZXhpc3QgYW55bW9yZS4gSW4gbW9uZ28sIHRoaXMgbWVhbnMgcmVtb3ZpbmcgaXQgZnJvbVxuICAvLyB0aGUgX1NDSEVNQSBjb2xsZWN0aW9uLiAgVGhlcmUgc2hvdWxkIGJlIG5vIGFjdHVhbCBkYXRhIGluIHRoZSBjb2xsZWN0aW9uIHVuZGVyIHRoZSBzYW1lIG5hbWVcbiAgLy8gYXMgdGhlIHJlbGF0aW9uIGNvbHVtbiwgc28gaXQncyBmaW5lIHRvIGF0dGVtcHQgdG8gZGVsZXRlIGl0LiBJZiB0aGUgZmllbGRzIGxpc3RlZCB0byBiZVxuICAvLyBkZWxldGVkIGRvIG5vdCBleGlzdCwgdGhpcyBmdW5jdGlvbiBzaG91bGQgcmV0dXJuIHN1Y2Nlc3NmdWxseSBhbnl3YXlzLiBDaGVja2luZyBmb3JcbiAgLy8gYXR0ZW1wdHMgdG8gZGVsZXRlIG5vbi1leGlzdGVudCBmaWVsZHMgaXMgdGhlIHJlc3BvbnNpYmlsaXR5IG9mIFBhcnNlIFNlcnZlci5cblxuICAvLyBUaGlzIGZ1bmN0aW9uIGlzIG5vdCBvYmxpZ2F0ZWQgdG8gZGVsZXRlIGZpZWxkcyBhdG9taWNhbGx5LiBJdCBpcyBnaXZlbiB0aGUgZmllbGRcbiAgLy8gbmFtZXMgaW4gYSBsaXN0IHNvIHRoYXQgZGF0YWJhc2VzIHRoYXQgYXJlIGNhcGFibGUgb2YgZGVsZXRpbmcgZmllbGRzIGF0b21pY2FsbHlcbiAgLy8gbWF5IGRvIHNvLlxuXG4gIC8vIFJldHVybnMgYSBQcm9taXNlLlxuICBhc3luYyBkZWxldGVGaWVsZHMoY2xhc3NOYW1lOiBzdHJpbmcsIHNjaGVtYTogU2NoZW1hVHlwZSwgZmllbGROYW1lczogc3RyaW5nW10pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBkZWJ1ZygnZGVsZXRlRmllbGRzJyk7XG4gICAgZmllbGROYW1lcyA9IGZpZWxkTmFtZXMucmVkdWNlKChsaXN0OiBBcnJheTxzdHJpbmc+LCBmaWVsZE5hbWU6IHN0cmluZykgPT4ge1xuICAgICAgY29uc3QgZmllbGQgPSBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV07XG4gICAgICBpZiAoZmllbGQudHlwZSAhPT0gJ1JlbGF0aW9uJykge1xuICAgICAgICBsaXN0LnB1c2goZmllbGROYW1lKTtcbiAgICAgIH1cbiAgICAgIGRlbGV0ZSBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV07XG4gICAgICByZXR1cm4gbGlzdDtcbiAgICB9LCBbXSk7XG5cbiAgICBjb25zdCB2YWx1ZXMgPSBbY2xhc3NOYW1lLCAuLi5maWVsZE5hbWVzXTtcbiAgICBjb25zdCBjb2x1bW5zID0gZmllbGROYW1lc1xuICAgICAgLm1hcCgobmFtZSwgaWR4KSA9PiB7XG4gICAgICAgIHJldHVybiBgJCR7aWR4ICsgMn06bmFtZWA7XG4gICAgICB9KVxuICAgICAgLmpvaW4oJywgRFJPUCBDT0xVTU4nKTtcblxuICAgIGF3YWl0IHRoaXMuX2NsaWVudC50eCgnZGVsZXRlLWZpZWxkcycsIGFzeW5jIHQgPT4ge1xuICAgICAgYXdhaXQgdC5ub25lKCdVUERBVEUgXCJfU0NIRU1BXCIgU0VUIFwic2NoZW1hXCIgPSAkPHNjaGVtYT4gV0hFUkUgXCJjbGFzc05hbWVcIiA9ICQ8Y2xhc3NOYW1lPicsIHtcbiAgICAgICAgc2NoZW1hLFxuICAgICAgICBjbGFzc05hbWUsXG4gICAgICB9KTtcbiAgICAgIGlmICh2YWx1ZXMubGVuZ3RoID4gMSkge1xuICAgICAgICBhd2FpdCB0Lm5vbmUoYEFMVEVSIFRBQkxFICQxOm5hbWUgRFJPUCBDT0xVTU4gSUYgRVhJU1RTICR7Y29sdW1uc31gLCB2YWx1ZXMpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHRoaXMuX25vdGlmeVNjaGVtYUNoYW5nZSgpO1xuICB9XG5cbiAgLy8gUmV0dXJuIGEgcHJvbWlzZSBmb3IgYWxsIHNjaGVtYXMga25vd24gdG8gdGhpcyBhZGFwdGVyLCBpbiBQYXJzZSBmb3JtYXQuIEluIGNhc2UgdGhlXG4gIC8vIHNjaGVtYXMgY2Fubm90IGJlIHJldHJpZXZlZCwgcmV0dXJucyBhIHByb21pc2UgdGhhdCByZWplY3RzLiBSZXF1aXJlbWVudHMgZm9yIHRoZVxuICAvLyByZWplY3Rpb24gcmVhc29uIGFyZSBUQkQuXG4gIGFzeW5jIGdldEFsbENsYXNzZXMoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2NsaWVudC50YXNrKCdnZXQtYWxsLWNsYXNzZXMnLCBhc3luYyB0ID0+IHtcbiAgICAgIHJldHVybiBhd2FpdCB0Lm1hcCgnU0VMRUNUICogRlJPTSBcIl9TQ0hFTUFcIicsIG51bGwsIHJvdyA9PlxuICAgICAgICB0b1BhcnNlU2NoZW1hKHsgY2xhc3NOYW1lOiByb3cuY2xhc3NOYW1lLCAuLi5yb3cuc2NoZW1hIH0pXG4gICAgICApO1xuICAgIH0pO1xuICB9XG5cbiAgLy8gUmV0dXJuIGEgcHJvbWlzZSBmb3IgdGhlIHNjaGVtYSB3aXRoIHRoZSBnaXZlbiBuYW1lLCBpbiBQYXJzZSBmb3JtYXQuIElmXG4gIC8vIHRoaXMgYWRhcHRlciBkb2Vzbid0IGtub3cgYWJvdXQgdGhlIHNjaGVtYSwgcmV0dXJuIGEgcHJvbWlzZSB0aGF0IHJlamVjdHMgd2l0aFxuICAvLyB1bmRlZmluZWQgYXMgdGhlIHJlYXNvbi5cbiAgYXN5bmMgZ2V0Q2xhc3MoY2xhc3NOYW1lOiBzdHJpbmcpIHtcbiAgICBkZWJ1ZygnZ2V0Q2xhc3MnKTtcbiAgICByZXR1cm4gdGhpcy5fY2xpZW50XG4gICAgICAuYW55KCdTRUxFQ1QgKiBGUk9NIFwiX1NDSEVNQVwiIFdIRVJFIFwiY2xhc3NOYW1lXCIgPSAkPGNsYXNzTmFtZT4nLCB7XG4gICAgICAgIGNsYXNzTmFtZSxcbiAgICAgIH0pXG4gICAgICAudGhlbihyZXN1bHQgPT4ge1xuICAgICAgICBpZiAocmVzdWx0Lmxlbmd0aCAhPT0gMSkge1xuICAgICAgICAgIHRocm93IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0WzBdLnNjaGVtYTtcbiAgICAgIH0pXG4gICAgICAudGhlbih0b1BhcnNlU2NoZW1hKTtcbiAgfVxuXG4gIC8vIFRPRE86IHJlbW92ZSB0aGUgbW9uZ28gZm9ybWF0IGRlcGVuZGVuY3kgaW4gdGhlIHJldHVybiB2YWx1ZVxuICBhc3luYyBjcmVhdGVPYmplY3QoXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgc2NoZW1hOiBTY2hlbWFUeXBlLFxuICAgIG9iamVjdDogYW55LFxuICAgIHRyYW5zYWN0aW9uYWxTZXNzaW9uOiA/YW55XG4gICkge1xuICAgIGRlYnVnKCdjcmVhdGVPYmplY3QnKTtcbiAgICBsZXQgY29sdW1uc0FycmF5ID0gW107XG4gICAgY29uc3QgdmFsdWVzQXJyYXkgPSBbXTtcbiAgICBzY2hlbWEgPSB0b1Bvc3RncmVzU2NoZW1hKHNjaGVtYSk7XG4gICAgY29uc3QgZ2VvUG9pbnRzID0ge307XG5cbiAgICBvYmplY3QgPSBoYW5kbGVEb3RGaWVsZHMob2JqZWN0KTtcblxuICAgIHZhbGlkYXRlS2V5cyhvYmplY3QpO1xuXG4gICAgT2JqZWN0LmtleXMob2JqZWN0KS5mb3JFYWNoKGZpZWxkTmFtZSA9PiB7XG4gICAgICBpZiAob2JqZWN0W2ZpZWxkTmFtZV0gPT09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgdmFyIGF1dGhEYXRhTWF0Y2ggPSBmaWVsZE5hbWUubWF0Y2goL15fYXV0aF9kYXRhXyhbYS16QS1aMC05X10rKSQvKTtcbiAgICAgIGNvbnN0IGF1dGhEYXRhQWxyZWFkeUV4aXN0cyA9ICEhb2JqZWN0LmF1dGhEYXRhO1xuICAgICAgaWYgKGF1dGhEYXRhTWF0Y2gpIHtcbiAgICAgICAgdmFyIHByb3ZpZGVyID0gYXV0aERhdGFNYXRjaFsxXTtcbiAgICAgICAgb2JqZWN0WydhdXRoRGF0YSddID0gb2JqZWN0WydhdXRoRGF0YSddIHx8IHt9O1xuICAgICAgICBvYmplY3RbJ2F1dGhEYXRhJ11bcHJvdmlkZXJdID0gb2JqZWN0W2ZpZWxkTmFtZV07XG4gICAgICAgIGRlbGV0ZSBvYmplY3RbZmllbGROYW1lXTtcbiAgICAgICAgZmllbGROYW1lID0gJ2F1dGhEYXRhJztcbiAgICAgICAgLy8gQXZvaWQgYWRkaW5nIGF1dGhEYXRhIG11bHRpcGxlIHRpbWVzIHRvIHRoZSBxdWVyeVxuICAgICAgICBpZiAoYXV0aERhdGFBbHJlYWR5RXhpc3RzKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNvbHVtbnNBcnJheS5wdXNoKGZpZWxkTmFtZSk7XG4gICAgICBpZiAoIXNjaGVtYS5maWVsZHNbZmllbGROYW1lXSAmJiBjbGFzc05hbWUgPT09ICdfVXNlcicpIHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgIGZpZWxkTmFtZSA9PT0gJ19lbWFpbF92ZXJpZnlfdG9rZW4nIHx8XG4gICAgICAgICAgZmllbGROYW1lID09PSAnX2ZhaWxlZF9sb2dpbl9jb3VudCcgfHxcbiAgICAgICAgICBmaWVsZE5hbWUgPT09ICdfcGVyaXNoYWJsZV90b2tlbicgfHxcbiAgICAgICAgICBmaWVsZE5hbWUgPT09ICdfcGFzc3dvcmRfaGlzdG9yeSdcbiAgICAgICAgKSB7XG4gICAgICAgICAgdmFsdWVzQXJyYXkucHVzaChvYmplY3RbZmllbGROYW1lXSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZmllbGROYW1lID09PSAnX2VtYWlsX3ZlcmlmeV90b2tlbl9leHBpcmVzX2F0Jykge1xuICAgICAgICAgIGlmIChvYmplY3RbZmllbGROYW1lXSkge1xuICAgICAgICAgICAgdmFsdWVzQXJyYXkucHVzaChvYmplY3RbZmllbGROYW1lXS5pc28pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YWx1ZXNBcnJheS5wdXNoKG51bGwpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChcbiAgICAgICAgICBmaWVsZE5hbWUgPT09ICdfYWNjb3VudF9sb2Nrb3V0X2V4cGlyZXNfYXQnIHx8XG4gICAgICAgICAgZmllbGROYW1lID09PSAnX3BlcmlzaGFibGVfdG9rZW5fZXhwaXJlc19hdCcgfHxcbiAgICAgICAgICBmaWVsZE5hbWUgPT09ICdfcGFzc3dvcmRfY2hhbmdlZF9hdCdcbiAgICAgICAgKSB7XG4gICAgICAgICAgaWYgKG9iamVjdFtmaWVsZE5hbWVdKSB7XG4gICAgICAgICAgICB2YWx1ZXNBcnJheS5wdXNoKG9iamVjdFtmaWVsZE5hbWVdLmlzbyk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZhbHVlc0FycmF5LnB1c2gobnVsbCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHN3aXRjaCAoc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdLnR5cGUpIHtcbiAgICAgICAgY2FzZSAnRGF0ZSc6XG4gICAgICAgICAgaWYgKG9iamVjdFtmaWVsZE5hbWVdKSB7XG4gICAgICAgICAgICB2YWx1ZXNBcnJheS5wdXNoKG9iamVjdFtmaWVsZE5hbWVdLmlzbyk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZhbHVlc0FycmF5LnB1c2gobnVsbCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdQb2ludGVyJzpcbiAgICAgICAgICB2YWx1ZXNBcnJheS5wdXNoKG9iamVjdFtmaWVsZE5hbWVdLm9iamVjdElkKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnQXJyYXknOlxuICAgICAgICAgIGlmIChbJ19ycGVybScsICdfd3Blcm0nXS5pbmRleE9mKGZpZWxkTmFtZSkgPj0gMCkge1xuICAgICAgICAgICAgdmFsdWVzQXJyYXkucHVzaChvYmplY3RbZmllbGROYW1lXSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZhbHVlc0FycmF5LnB1c2goSlNPTi5zdHJpbmdpZnkob2JqZWN0W2ZpZWxkTmFtZV0pKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ09iamVjdCc6XG4gICAgICAgIGNhc2UgJ0J5dGVzJzpcbiAgICAgICAgY2FzZSAnU3RyaW5nJzpcbiAgICAgICAgY2FzZSAnTnVtYmVyJzpcbiAgICAgICAgY2FzZSAnQm9vbGVhbic6XG4gICAgICAgICAgdmFsdWVzQXJyYXkucHVzaChvYmplY3RbZmllbGROYW1lXSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ0ZpbGUnOlxuICAgICAgICAgIHZhbHVlc0FycmF5LnB1c2gob2JqZWN0W2ZpZWxkTmFtZV0ubmFtZSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ1BvbHlnb24nOiB7XG4gICAgICAgICAgY29uc3QgdmFsdWUgPSBjb252ZXJ0UG9seWdvblRvU1FMKG9iamVjdFtmaWVsZE5hbWVdLmNvb3JkaW5hdGVzKTtcbiAgICAgICAgICB2YWx1ZXNBcnJheS5wdXNoKHZhbHVlKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBjYXNlICdHZW9Qb2ludCc6XG4gICAgICAgICAgLy8gcG9wIHRoZSBwb2ludCBhbmQgcHJvY2VzcyBsYXRlclxuICAgICAgICAgIGdlb1BvaW50c1tmaWVsZE5hbWVdID0gb2JqZWN0W2ZpZWxkTmFtZV07XG4gICAgICAgICAgY29sdW1uc0FycmF5LnBvcCgpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIHRocm93IGBUeXBlICR7c2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdLnR5cGV9IG5vdCBzdXBwb3J0ZWQgeWV0YDtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGNvbHVtbnNBcnJheSA9IGNvbHVtbnNBcnJheS5jb25jYXQoT2JqZWN0LmtleXMoZ2VvUG9pbnRzKSk7XG4gICAgY29uc3QgaW5pdGlhbFZhbHVlcyA9IHZhbHVlc0FycmF5Lm1hcCgodmFsLCBpbmRleCkgPT4ge1xuICAgICAgbGV0IHRlcm1pbmF0aW9uID0gJyc7XG4gICAgICBjb25zdCBmaWVsZE5hbWUgPSBjb2x1bW5zQXJyYXlbaW5kZXhdO1xuICAgICAgaWYgKFsnX3JwZXJtJywgJ193cGVybSddLmluZGV4T2YoZmllbGROYW1lKSA+PSAwKSB7XG4gICAgICAgIHRlcm1pbmF0aW9uID0gJzo6dGV4dFtdJztcbiAgICAgIH0gZWxzZSBpZiAoc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdICYmIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS50eXBlID09PSAnQXJyYXknKSB7XG4gICAgICAgIHRlcm1pbmF0aW9uID0gJzo6anNvbmInO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGAkJHtpbmRleCArIDIgKyBjb2x1bW5zQXJyYXkubGVuZ3RofSR7dGVybWluYXRpb259YDtcbiAgICB9KTtcbiAgICBjb25zdCBnZW9Qb2ludHNJbmplY3RzID0gT2JqZWN0LmtleXMoZ2VvUG9pbnRzKS5tYXAoa2V5ID0+IHtcbiAgICAgIGNvbnN0IHZhbHVlID0gZ2VvUG9pbnRzW2tleV07XG4gICAgICB2YWx1ZXNBcnJheS5wdXNoKHZhbHVlLmxvbmdpdHVkZSwgdmFsdWUubGF0aXR1ZGUpO1xuICAgICAgY29uc3QgbCA9IHZhbHVlc0FycmF5Lmxlbmd0aCArIGNvbHVtbnNBcnJheS5sZW5ndGg7XG4gICAgICByZXR1cm4gYFBPSU5UKCQke2x9LCAkJHtsICsgMX0pYDtcbiAgICB9KTtcblxuICAgIGNvbnN0IGNvbHVtbnNQYXR0ZXJuID0gY29sdW1uc0FycmF5Lm1hcCgoY29sLCBpbmRleCkgPT4gYCQke2luZGV4ICsgMn06bmFtZWApLmpvaW4oKTtcbiAgICBjb25zdCB2YWx1ZXNQYXR0ZXJuID0gaW5pdGlhbFZhbHVlcy5jb25jYXQoZ2VvUG9pbnRzSW5qZWN0cykuam9pbigpO1xuXG4gICAgY29uc3QgcXMgPSBgSU5TRVJUIElOVE8gJDE6bmFtZSAoJHtjb2x1bW5zUGF0dGVybn0pIFZBTFVFUyAoJHt2YWx1ZXNQYXR0ZXJufSlgO1xuICAgIGNvbnN0IHZhbHVlcyA9IFtjbGFzc05hbWUsIC4uLmNvbHVtbnNBcnJheSwgLi4udmFsdWVzQXJyYXldO1xuICAgIGNvbnN0IHByb21pc2UgPSAodHJhbnNhY3Rpb25hbFNlc3Npb24gPyB0cmFuc2FjdGlvbmFsU2Vzc2lvbi50IDogdGhpcy5fY2xpZW50KVxuICAgICAgLm5vbmUocXMsIHZhbHVlcylcbiAgICAgIC50aGVuKCgpID0+ICh7IG9wczogW29iamVjdF0gfSkpXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gUG9zdGdyZXNVbmlxdWVJbmRleFZpb2xhdGlvbkVycm9yKSB7XG4gICAgICAgICAgY29uc3QgZXJyID0gbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgUGFyc2UuRXJyb3IuRFVQTElDQVRFX1ZBTFVFLFxuICAgICAgICAgICAgJ0EgZHVwbGljYXRlIHZhbHVlIGZvciBhIGZpZWxkIHdpdGggdW5pcXVlIHZhbHVlcyB3YXMgcHJvdmlkZWQnXG4gICAgICAgICAgKTtcbiAgICAgICAgICBlcnIudW5kZXJseWluZ0Vycm9yID0gZXJyb3I7XG4gICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQpIHtcbiAgICAgICAgICAgIC8vIENoZWNrIGZvciBhdXRoRGF0YSB1bmlxdWUgaW5kZXggdmlvbGF0aW9ucyBmaXJzdFxuICAgICAgICAgICAgY29uc3QgYXV0aERhdGFNYXRjaCA9IGVycm9yLmNvbnN0cmFpbnQubWF0Y2goL19Vc2VyX3VuaXF1ZV9hdXRoRGF0YV8oW2EtekEtWjAtOV9dKylfaWQvKTtcbiAgICAgICAgICAgIGlmIChhdXRoRGF0YU1hdGNoKSB7XG4gICAgICAgICAgICAgIGVyci51c2VySW5mbyA9IHsgZHVwbGljYXRlZF9maWVsZDogYF9hdXRoX2RhdGFfJHthdXRoRGF0YU1hdGNoWzFdfWAgfTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGNvbnN0IG1hdGNoZXMgPSBlcnJvci5jb25zdHJhaW50Lm1hdGNoKC91bmlxdWVfKFthLXpBLVpdKykvKTtcbiAgICAgICAgICAgICAgaWYgKG1hdGNoZXMgJiYgQXJyYXkuaXNBcnJheShtYXRjaGVzKSkge1xuICAgICAgICAgICAgICAgIGVyci51c2VySW5mbyA9IHsgZHVwbGljYXRlZF9maWVsZDogbWF0Y2hlc1sxXSB9O1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGVycm9yID0gZXJyO1xuICAgICAgICB9XG4gICAgICAgIHRocm93IGVycm9yO1xuICAgICAgfSk7XG4gICAgaWYgKHRyYW5zYWN0aW9uYWxTZXNzaW9uKSB7XG4gICAgICB0cmFuc2FjdGlvbmFsU2Vzc2lvbi5iYXRjaC5wdXNoKHByb21pc2UpO1xuICAgIH1cbiAgICByZXR1cm4gcHJvbWlzZTtcbiAgfVxuXG4gIC8vIFJlbW92ZSBhbGwgb2JqZWN0cyB0aGF0IG1hdGNoIHRoZSBnaXZlbiBQYXJzZSBRdWVyeS5cbiAgLy8gSWYgbm8gb2JqZWN0cyBtYXRjaCwgcmVqZWN0IHdpdGggT0JKRUNUX05PVF9GT1VORC4gSWYgb2JqZWN0cyBhcmUgZm91bmQgYW5kIGRlbGV0ZWQsIHJlc29sdmUgd2l0aCB1bmRlZmluZWQuXG4gIC8vIElmIHRoZXJlIGlzIHNvbWUgb3RoZXIgZXJyb3IsIHJlamVjdCB3aXRoIElOVEVSTkFMX1NFUlZFUl9FUlJPUi5cbiAgYXN5bmMgZGVsZXRlT2JqZWN0c0J5UXVlcnkoXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgc2NoZW1hOiBTY2hlbWFUeXBlLFxuICAgIHF1ZXJ5OiBRdWVyeVR5cGUsXG4gICAgdHJhbnNhY3Rpb25hbFNlc3Npb246ID9hbnlcbiAgKSB7XG4gICAgZGVidWcoJ2RlbGV0ZU9iamVjdHNCeVF1ZXJ5Jyk7XG4gICAgY29uc3QgdmFsdWVzID0gW2NsYXNzTmFtZV07XG4gICAgY29uc3QgaW5kZXggPSAyO1xuICAgIGNvbnN0IHdoZXJlID0gYnVpbGRXaGVyZUNsYXVzZSh7XG4gICAgICBzY2hlbWEsXG4gICAgICBpbmRleCxcbiAgICAgIHF1ZXJ5LFxuICAgICAgY2FzZUluc2Vuc2l0aXZlOiBmYWxzZSxcbiAgICB9KTtcbiAgICB2YWx1ZXMucHVzaCguLi53aGVyZS52YWx1ZXMpO1xuICAgIGlmIChPYmplY3Qua2V5cyhxdWVyeSkubGVuZ3RoID09PSAwKSB7XG4gICAgICB3aGVyZS5wYXR0ZXJuID0gJ1RSVUUnO1xuICAgIH1cbiAgICBjb25zdCBxcyA9IGBXSVRIIGRlbGV0ZWQgQVMgKERFTEVURSBGUk9NICQxOm5hbWUgV0hFUkUgJHt3aGVyZS5wYXR0ZXJufSBSRVRVUk5JTkcgKikgU0VMRUNUIGNvdW50KCopIEZST00gZGVsZXRlZGA7XG4gICAgY29uc3QgcHJvbWlzZSA9ICh0cmFuc2FjdGlvbmFsU2Vzc2lvbiA/IHRyYW5zYWN0aW9uYWxTZXNzaW9uLnQgOiB0aGlzLl9jbGllbnQpXG4gICAgICAub25lKHFzLCB2YWx1ZXMsIGEgPT4gK2EuY291bnQpXG4gICAgICAudGhlbihjb3VudCA9PiB7XG4gICAgICAgIGlmIChjb3VudCA9PT0gMCkge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELCAnT2JqZWN0IG5vdCBmb3VuZC4nKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gY291bnQ7XG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICBpZiAoZXJyb3IuY29kZSAhPT0gUG9zdGdyZXNSZWxhdGlvbkRvZXNOb3RFeGlzdEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cbiAgICAgICAgLy8gRUxTRTogRG9uJ3QgZGVsZXRlIGFueXRoaW5nIGlmIGRvZXNuJ3QgZXhpc3RcbiAgICAgIH0pO1xuICAgIGlmICh0cmFuc2FjdGlvbmFsU2Vzc2lvbikge1xuICAgICAgdHJhbnNhY3Rpb25hbFNlc3Npb24uYmF0Y2gucHVzaChwcm9taXNlKTtcbiAgICB9XG4gICAgcmV0dXJuIHByb21pc2U7XG4gIH1cbiAgLy8gUmV0dXJuIHZhbHVlIG5vdCBjdXJyZW50bHkgd2VsbCBzcGVjaWZpZWQuXG4gIGFzeW5jIGZpbmRPbmVBbmRVcGRhdGUoXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgc2NoZW1hOiBTY2hlbWFUeXBlLFxuICAgIHF1ZXJ5OiBRdWVyeVR5cGUsXG4gICAgdXBkYXRlOiBhbnksXG4gICAgdHJhbnNhY3Rpb25hbFNlc3Npb246ID9hbnlcbiAgKTogUHJvbWlzZTxhbnk+IHtcbiAgICBkZWJ1ZygnZmluZE9uZUFuZFVwZGF0ZScpO1xuICAgIHJldHVybiB0aGlzLnVwZGF0ZU9iamVjdHNCeVF1ZXJ5KGNsYXNzTmFtZSwgc2NoZW1hLCBxdWVyeSwgdXBkYXRlLCB0cmFuc2FjdGlvbmFsU2Vzc2lvbikudGhlbihcbiAgICAgIHZhbCA9PiB2YWxbMF1cbiAgICApO1xuICB9XG5cbiAgLy8gQXBwbHkgdGhlIHVwZGF0ZSB0byBhbGwgb2JqZWN0cyB0aGF0IG1hdGNoIHRoZSBnaXZlbiBQYXJzZSBRdWVyeS5cbiAgYXN5bmMgdXBkYXRlT2JqZWN0c0J5UXVlcnkoXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgc2NoZW1hOiBTY2hlbWFUeXBlLFxuICAgIHF1ZXJ5OiBRdWVyeVR5cGUsXG4gICAgdXBkYXRlOiBhbnksXG4gICAgdHJhbnNhY3Rpb25hbFNlc3Npb246ID9hbnlcbiAgKTogUHJvbWlzZTxbYW55XT4ge1xuICAgIGRlYnVnKCd1cGRhdGVPYmplY3RzQnlRdWVyeScpO1xuICAgIGNvbnN0IHVwZGF0ZVBhdHRlcm5zID0gW107XG4gICAgY29uc3QgdmFsdWVzID0gW2NsYXNzTmFtZV07XG4gICAgbGV0IGluZGV4ID0gMjtcbiAgICBzY2hlbWEgPSB0b1Bvc3RncmVzU2NoZW1hKHNjaGVtYSk7XG5cbiAgICBjb25zdCBvcmlnaW5hbFVwZGF0ZSA9IHsgLi4udXBkYXRlIH07XG5cbiAgICAvLyBTZXQgZmxhZyBmb3IgZG90IG5vdGF0aW9uIGZpZWxkc1xuICAgIGNvbnN0IGRvdE5vdGF0aW9uT3B0aW9ucyA9IHt9O1xuICAgIE9iamVjdC5rZXlzKHVwZGF0ZSkuZm9yRWFjaChmaWVsZE5hbWUgPT4ge1xuICAgICAgaWYgKGZpZWxkTmFtZS5pbmRleE9mKCcuJykgPiAtMSkge1xuICAgICAgICBjb25zdCBjb21wb25lbnRzID0gZmllbGROYW1lLnNwbGl0KCcuJyk7XG4gICAgICAgIGNvbnN0IGZpcnN0ID0gY29tcG9uZW50cy5zaGlmdCgpO1xuICAgICAgICBkb3ROb3RhdGlvbk9wdGlvbnNbZmlyc3RdID0gdHJ1ZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRvdE5vdGF0aW9uT3B0aW9uc1tmaWVsZE5hbWVdID0gZmFsc2U7XG4gICAgICB9XG4gICAgfSk7XG4gICAgdXBkYXRlID0gaGFuZGxlRG90RmllbGRzKHVwZGF0ZSk7XG4gICAgLy8gUmVzb2x2ZSBhdXRoRGF0YSBmaXJzdCxcbiAgICAvLyBTbyB3ZSBkb24ndCBlbmQgdXAgd2l0aCBtdWx0aXBsZSBrZXkgdXBkYXRlc1xuICAgIGZvciAoY29uc3QgZmllbGROYW1lIGluIHVwZGF0ZSkge1xuICAgICAgY29uc3QgYXV0aERhdGFNYXRjaCA9IGZpZWxkTmFtZS5tYXRjaCgvXl9hdXRoX2RhdGFfKFthLXpBLVowLTlfXSspJC8pO1xuICAgICAgaWYgKGF1dGhEYXRhTWF0Y2gpIHtcbiAgICAgICAgdmFyIHByb3ZpZGVyID0gYXV0aERhdGFNYXRjaFsxXTtcbiAgICAgICAgY29uc3QgdmFsdWUgPSB1cGRhdGVbZmllbGROYW1lXTtcbiAgICAgICAgZGVsZXRlIHVwZGF0ZVtmaWVsZE5hbWVdO1xuICAgICAgICB1cGRhdGVbJ2F1dGhEYXRhJ10gPSB1cGRhdGVbJ2F1dGhEYXRhJ10gfHwge307XG4gICAgICAgIHVwZGF0ZVsnYXV0aERhdGEnXVtwcm92aWRlcl0gPSB2YWx1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IGZpZWxkTmFtZSBpbiB1cGRhdGUpIHtcbiAgICAgIGNvbnN0IGZpZWxkVmFsdWUgPSB1cGRhdGVbZmllbGROYW1lXTtcbiAgICAgIC8vIERyb3AgYW55IHVuZGVmaW5lZCB2YWx1ZXMuXG4gICAgICBpZiAodHlwZW9mIGZpZWxkVmFsdWUgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIGRlbGV0ZSB1cGRhdGVbZmllbGROYW1lXTtcbiAgICAgIH0gZWxzZSBpZiAoZmllbGRWYWx1ZSA9PT0gbnVsbCkge1xuICAgICAgICB1cGRhdGVQYXR0ZXJucy5wdXNoKGAkJHtpbmRleH06bmFtZSA9IE5VTExgKTtcbiAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lKTtcbiAgICAgICAgaW5kZXggKz0gMTtcbiAgICAgIH0gZWxzZSBpZiAoZmllbGROYW1lID09ICdhdXRoRGF0YScpIHtcbiAgICAgICAgLy8gVGhpcyByZWN1cnNpdmVseSBzZXRzIHRoZSBqc29uX29iamVjdFxuICAgICAgICAvLyBPbmx5IDEgbGV2ZWwgZGVlcFxuICAgICAgICBjb25zdCBnZW5lcmF0ZSA9IChqc29uYjogc3RyaW5nLCBrZXk6IHN0cmluZywgdmFsdWU6IGFueSkgPT4ge1xuICAgICAgICAgIHJldHVybiBganNvbl9vYmplY3Rfc2V0X2tleShDT0FMRVNDRSgke2pzb25ifSwgJ3t9Jzo6anNvbmIpLCAke2tleX0sICR7dmFsdWV9KTo6anNvbmJgO1xuICAgICAgICB9O1xuICAgICAgICBjb25zdCBnZW5lcmF0ZVJlbW92ZSA9IChqc29uYjogc3RyaW5nLCBrZXk6IHN0cmluZykgPT4ge1xuICAgICAgICAgIHJldHVybiBgKENPQUxFU0NFKCR7anNvbmJ9LCAne30nOjpqc29uYikgLSAke2tleX0pYDtcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgbGFzdEtleSA9IGAkJHtpbmRleH06bmFtZWA7XG4gICAgICAgIGNvbnN0IGZpZWxkTmFtZUluZGV4ID0gaW5kZXg7XG4gICAgICAgIGluZGV4ICs9IDE7XG4gICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSk7XG4gICAgICAgIGNvbnN0IHVwZGF0ZSA9IE9iamVjdC5rZXlzKGZpZWxkVmFsdWUpLnJlZHVjZSgobGFzdEtleTogc3RyaW5nLCBrZXk6IHN0cmluZykgPT4ge1xuICAgICAgICAgIGxldCB2YWx1ZSA9IGZpZWxkVmFsdWVba2V5XTtcbiAgICAgICAgICBpZiAodmFsdWUgJiYgdmFsdWUuX19vcCA9PT0gJ0RlbGV0ZScpIHtcbiAgICAgICAgICAgIHZhbHVlID0gbnVsbDtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHZhbHVlID09PSBudWxsKSB7XG4gICAgICAgICAgICBjb25zdCBzdHIgPSBnZW5lcmF0ZVJlbW92ZShsYXN0S2V5LCBgJCR7aW5kZXh9Ojp0ZXh0YCk7XG4gICAgICAgICAgICB2YWx1ZXMucHVzaChrZXkpO1xuICAgICAgICAgICAgaW5kZXggKz0gMTtcbiAgICAgICAgICAgIHJldHVybiBzdHI7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnN0IHN0ciA9IGdlbmVyYXRlKGxhc3RLZXksIGAkJHtpbmRleH06OnRleHRgLCBgJCR7aW5kZXggKyAxfTo6anNvbmJgKTtcbiAgICAgICAgICBpbmRleCArPSAyO1xuICAgICAgICAgIGlmICh2YWx1ZSkge1xuICAgICAgICAgICAgdmFsdWUgPSBKU09OLnN0cmluZ2lmeSh2YWx1ZSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHZhbHVlcy5wdXNoKGtleSwgdmFsdWUpO1xuICAgICAgICAgIHJldHVybiBzdHI7XG4gICAgICAgIH0sIGxhc3RLZXkpO1xuICAgICAgICB1cGRhdGVQYXR0ZXJucy5wdXNoKGAkJHtmaWVsZE5hbWVJbmRleH06bmFtZSA9ICR7dXBkYXRlfWApO1xuICAgICAgfSBlbHNlIGlmIChmaWVsZFZhbHVlLl9fb3AgPT09ICdJbmNyZW1lbnQnKSB7XG4gICAgICAgIHVwZGF0ZVBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lID0gQ09BTEVTQ0UoJCR7aW5kZXh9Om5hbWUsIDApICsgJCR7aW5kZXggKyAxfWApO1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIGZpZWxkVmFsdWUuYW1vdW50KTtcbiAgICAgICAgaW5kZXggKz0gMjtcbiAgICAgIH0gZWxzZSBpZiAoZmllbGRWYWx1ZS5fX29wID09PSAnQWRkJykge1xuICAgICAgICB1cGRhdGVQYXR0ZXJucy5wdXNoKFxuICAgICAgICAgIGAkJHtpbmRleH06bmFtZSA9IGFycmF5X2FkZChDT0FMRVNDRSgkJHtpbmRleH06bmFtZSwgJ1tdJzo6anNvbmIpLCAkJHtpbmRleCArIDF9Ojpqc29uYilgXG4gICAgICAgICk7XG4gICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgSlNPTi5zdHJpbmdpZnkoZmllbGRWYWx1ZS5vYmplY3RzKSk7XG4gICAgICAgIGluZGV4ICs9IDI7XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkVmFsdWUuX19vcCA9PT0gJ0RlbGV0ZScpIHtcbiAgICAgICAgdXBkYXRlUGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgPSAkJHtpbmRleCArIDF9YCk7XG4gICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgbnVsbCk7XG4gICAgICAgIGluZGV4ICs9IDI7XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkVmFsdWUuX19vcCA9PT0gJ1JlbW92ZScpIHtcbiAgICAgICAgdXBkYXRlUGF0dGVybnMucHVzaChcbiAgICAgICAgICBgJCR7aW5kZXh9Om5hbWUgPSBhcnJheV9yZW1vdmUoQ09BTEVTQ0UoJCR7aW5kZXh9Om5hbWUsICdbXSc6Ompzb25iKSwgJCR7aW5kZXggKyAxXG4gICAgICAgICAgfTo6anNvbmIpYFxuICAgICAgICApO1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIEpTT04uc3RyaW5naWZ5KGZpZWxkVmFsdWUub2JqZWN0cykpO1xuICAgICAgICBpbmRleCArPSAyO1xuICAgICAgfSBlbHNlIGlmIChmaWVsZFZhbHVlLl9fb3AgPT09ICdBZGRVbmlxdWUnKSB7XG4gICAgICAgIHVwZGF0ZVBhdHRlcm5zLnB1c2goXG4gICAgICAgICAgYCQke2luZGV4fTpuYW1lID0gYXJyYXlfYWRkX3VuaXF1ZShDT0FMRVNDRSgkJHtpbmRleH06bmFtZSwgJ1tdJzo6anNvbmIpLCAkJHtpbmRleCArIDFcbiAgICAgICAgICB9Ojpqc29uYilgXG4gICAgICAgICk7XG4gICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgSlNPTi5zdHJpbmdpZnkoZmllbGRWYWx1ZS5vYmplY3RzKSk7XG4gICAgICAgIGluZGV4ICs9IDI7XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkTmFtZSA9PT0gJ3VwZGF0ZWRBdCcpIHtcbiAgICAgICAgLy9UT0RPOiBzdG9wIHNwZWNpYWwgY2FzaW5nIHRoaXMuIEl0IHNob3VsZCBjaGVjayBmb3IgX190eXBlID09PSAnRGF0ZScgYW5kIHVzZSAuaXNvXG4gICAgICAgIHVwZGF0ZVBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lID0gJCR7aW5kZXggKyAxfWApO1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIGZpZWxkVmFsdWUpO1xuICAgICAgICBpbmRleCArPSAyO1xuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgZmllbGRWYWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgdXBkYXRlUGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgPSAkJHtpbmRleCArIDF9YCk7XG4gICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgZmllbGRWYWx1ZSk7XG4gICAgICAgIGluZGV4ICs9IDI7XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiBmaWVsZFZhbHVlID09PSAnYm9vbGVhbicpIHtcbiAgICAgICAgdXBkYXRlUGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgPSAkJHtpbmRleCArIDF9YCk7XG4gICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgZmllbGRWYWx1ZSk7XG4gICAgICAgIGluZGV4ICs9IDI7XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkVmFsdWUuX190eXBlID09PSAnUG9pbnRlcicpIHtcbiAgICAgICAgdXBkYXRlUGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgPSAkJHtpbmRleCArIDF9YCk7XG4gICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgZmllbGRWYWx1ZS5vYmplY3RJZCk7XG4gICAgICAgIGluZGV4ICs9IDI7XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkVmFsdWUuX190eXBlID09PSAnRGF0ZScpIHtcbiAgICAgICAgdXBkYXRlUGF0dGVybnMucHVzaChgJCR7aW5kZXh9Om5hbWUgPSAkJHtpbmRleCArIDF9YCk7XG4gICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgdG9Qb3N0Z3Jlc1ZhbHVlKGZpZWxkVmFsdWUpKTtcbiAgICAgICAgaW5kZXggKz0gMjtcbiAgICAgIH0gZWxzZSBpZiAoVXRpbHMuaXNEYXRlKGZpZWxkVmFsdWUpKSB7XG4gICAgICAgIHVwZGF0ZVBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lID0gJCR7aW5kZXggKyAxfWApO1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIGZpZWxkVmFsdWUpO1xuICAgICAgICBpbmRleCArPSAyO1xuICAgICAgfSBlbHNlIGlmIChmaWVsZFZhbHVlLl9fdHlwZSA9PT0gJ0ZpbGUnKSB7XG4gICAgICAgIHVwZGF0ZVBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lID0gJCR7aW5kZXggKyAxfWApO1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIHRvUG9zdGdyZXNWYWx1ZShmaWVsZFZhbHVlKSk7XG4gICAgICAgIGluZGV4ICs9IDI7XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkVmFsdWUuX190eXBlID09PSAnR2VvUG9pbnQnKSB7XG4gICAgICAgIHVwZGF0ZVBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lID0gUE9JTlQoJCR7aW5kZXggKyAxfSwgJCR7aW5kZXggKyAyfSlgKTtcbiAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCBmaWVsZFZhbHVlLmxvbmdpdHVkZSwgZmllbGRWYWx1ZS5sYXRpdHVkZSk7XG4gICAgICAgIGluZGV4ICs9IDM7XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkVmFsdWUuX190eXBlID09PSAnUG9seWdvbicpIHtcbiAgICAgICAgY29uc3QgdmFsdWUgPSBjb252ZXJ0UG9seWdvblRvU1FMKGZpZWxkVmFsdWUuY29vcmRpbmF0ZXMpO1xuICAgICAgICB1cGRhdGVQYXR0ZXJucy5wdXNoKGAkJHtpbmRleH06bmFtZSA9ICQke2luZGV4ICsgMX06OnBvbHlnb25gKTtcbiAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCB2YWx1ZSk7XG4gICAgICAgIGluZGV4ICs9IDI7XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkVmFsdWUuX190eXBlID09PSAnUmVsYXRpb24nKSB7XG4gICAgICAgIC8vIG5vb3BcbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGZpZWxkVmFsdWUgPT09ICdudW1iZXInKSB7XG4gICAgICAgIHVwZGF0ZVBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lID0gJCR7aW5kZXggKyAxfWApO1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIGZpZWxkVmFsdWUpO1xuICAgICAgICBpbmRleCArPSAyO1xuICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgdHlwZW9mIGZpZWxkVmFsdWUgPT09ICdvYmplY3QnICYmXG4gICAgICAgIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXSAmJlxuICAgICAgICBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0udHlwZSA9PT0gJ09iamVjdCdcbiAgICAgICkge1xuICAgICAgICAvLyBHYXRoZXIga2V5cyB0byBpbmNyZW1lbnRcbiAgICAgICAgY29uc3Qga2V5c1RvSW5jcmVtZW50ID0gT2JqZWN0LmtleXMob3JpZ2luYWxVcGRhdGUpXG4gICAgICAgICAgLmZpbHRlcihrID0+IHtcbiAgICAgICAgICAgIC8vIGNob29zZSB0b3AgbGV2ZWwgZmllbGRzIHRoYXQgaGF2ZSBhIGRlbGV0ZSBvcGVyYXRpb24gc2V0XG4gICAgICAgICAgICAvLyBOb3RlIHRoYXQgT2JqZWN0LmtleXMgaXMgaXRlcmF0aW5nIG92ZXIgdGhlICoqb3JpZ2luYWwqKiB1cGRhdGUgb2JqZWN0XG4gICAgICAgICAgICAvLyBhbmQgdGhhdCBzb21lIG9mIHRoZSBrZXlzIG9mIHRoZSBvcmlnaW5hbCB1cGRhdGUgY291bGQgYmUgbnVsbCBvciB1bmRlZmluZWQ6XG4gICAgICAgICAgICAvLyAoU2VlIHRoZSBhYm92ZSBjaGVjayBgaWYgKGZpZWxkVmFsdWUgPT09IG51bGwgfHwgdHlwZW9mIGZpZWxkVmFsdWUgPT0gXCJ1bmRlZmluZWRcIilgKVxuICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBvcmlnaW5hbFVwZGF0ZVtrXTtcbiAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgIHZhbHVlICYmXG4gICAgICAgICAgICAgIHZhbHVlLl9fb3AgPT09ICdJbmNyZW1lbnQnICYmXG4gICAgICAgICAgICAgIGsuc3BsaXQoJy4nKS5sZW5ndGggPT09IDIgJiZcbiAgICAgICAgICAgICAgay5zcGxpdCgnLicpWzBdID09PSBmaWVsZE5hbWVcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSlcbiAgICAgICAgICAubWFwKGsgPT4gay5zcGxpdCgnLicpWzFdKTtcblxuICAgICAgICBsZXQgaW5jcmVtZW50UGF0dGVybnMgPSAnJztcbiAgICAgICAgY29uc3QgaW5jcmVtZW50VmFsdWVzID0gW107XG4gICAgICAgIGlmIChrZXlzVG9JbmNyZW1lbnQubGVuZ3RoID4gMCkge1xuICAgICAgICAgIGluY3JlbWVudFBhdHRlcm5zID1cbiAgICAgICAgICAgICcgfHwgJyArXG4gICAgICAgICAgICBrZXlzVG9JbmNyZW1lbnRcbiAgICAgICAgICAgICAgLm1hcChjID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBhbW91bnQgPSBmaWVsZFZhbHVlW2NdLmFtb3VudDtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGFtb3VudCAhPT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sICdpbmNyZW1lbnRpbmcgbXVzdCBwcm92aWRlIGEgbnVtYmVyJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGluY3JlbWVudFZhbHVlcy5wdXNoKGFtb3VudCk7XG4gICAgICAgICAgICAgICAgY29uc3QgYW1vdW50SW5kZXggPSBpbmRleCArIGluY3JlbWVudFZhbHVlcy5sZW5ndGg7XG4gICAgICAgICAgICAgICAgY29uc3QganNvblNhZmVOYW1lID0gZXNjYXBlU3FsU3RyaW5nKGVzY2FwZUpzb25TdHJpbmcoYykpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHNxbFNhZmVOYW1lID0gZXNjYXBlU3FsU3RyaW5nKGMpO1xuICAgICAgICAgICAgICAgIHJldHVybiBgQ09OQ0FUKCd7XCIke2pzb25TYWZlTmFtZX1cIjonLCBDT0FMRVNDRSgkJHtpbmRleH06bmFtZS0+Picke3NxbFNhZmVOYW1lfScsJzAnKTo6aW50ICsgJCR7YW1vdW50SW5kZXh9LCAnfScpOjpqc29uYmA7XG4gICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgIC5qb2luKCcgfHwgJyk7XG4gICAgICAgICAgLy8gU3RyaXAgdGhlIGtleXNcbiAgICAgICAgICBrZXlzVG9JbmNyZW1lbnQuZm9yRWFjaChrZXkgPT4ge1xuICAgICAgICAgICAgZGVsZXRlIGZpZWxkVmFsdWVba2V5XTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGtleXNUb0RlbGV0ZTogQXJyYXk8c3RyaW5nPiA9IE9iamVjdC5rZXlzKG9yaWdpbmFsVXBkYXRlKVxuICAgICAgICAgIC5maWx0ZXIoayA9PiB7XG4gICAgICAgICAgICAvLyBjaG9vc2UgdG9wIGxldmVsIGZpZWxkcyB0aGF0IGhhdmUgYSBkZWxldGUgb3BlcmF0aW9uIHNldC5cbiAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gb3JpZ2luYWxVcGRhdGVba107XG4gICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICB2YWx1ZSAmJlxuICAgICAgICAgICAgICB2YWx1ZS5fX29wID09PSAnRGVsZXRlJyAmJlxuICAgICAgICAgICAgICBrLnNwbGl0KCcuJykubGVuZ3RoID09PSAyICYmXG4gICAgICAgICAgICAgIGsuc3BsaXQoJy4nKVswXSA9PT0gZmllbGROYW1lXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0pXG4gICAgICAgICAgLm1hcChrID0+IGsuc3BsaXQoJy4nKVsxXSk7XG5cbiAgICAgICAgY29uc3QgZGVsZXRlUGF0dGVybnMgPSBrZXlzVG9EZWxldGUucmVkdWNlKChwOiBzdHJpbmcsIGM6IHN0cmluZywgaTogbnVtYmVyKSA9PiB7XG4gICAgICAgICAgcmV0dXJuIHAgKyBgIC0gJyQke2luZGV4ICsgMSArIGluY3JlbWVudFZhbHVlcy5sZW5ndGggKyBpfTp2YWx1ZSdgO1xuICAgICAgICB9LCAnJyk7XG4gICAgICAgIC8vIE92ZXJyaWRlIE9iamVjdFxuICAgICAgICBsZXQgdXBkYXRlT2JqZWN0ID0gXCIne30nOjpqc29uYlwiO1xuXG4gICAgICAgIGlmIChkb3ROb3RhdGlvbk9wdGlvbnNbZmllbGROYW1lXSkge1xuICAgICAgICAgIC8vIE1lcmdlIE9iamVjdFxuICAgICAgICAgIHVwZGF0ZU9iamVjdCA9IGBDT0FMRVNDRSgkJHtpbmRleH06bmFtZSwgJ3t9Jzo6anNvbmIpYDtcbiAgICAgICAgfVxuICAgICAgICB1cGRhdGVQYXR0ZXJucy5wdXNoKFxuICAgICAgICAgIGAkJHtpbmRleH06bmFtZSA9ICgke3VwZGF0ZU9iamVjdH0gJHtkZWxldGVQYXR0ZXJuc30gJHtpbmNyZW1lbnRQYXR0ZXJuc30gfHwgJCR7aW5kZXggKyAxICsgaW5jcmVtZW50VmFsdWVzLmxlbmd0aCArIGtleXNUb0RlbGV0ZS5sZW5ndGhcbiAgICAgICAgICB9Ojpqc29uYiApYFxuICAgICAgICApO1xuICAgICAgICB2YWx1ZXMucHVzaChmaWVsZE5hbWUsIC4uLmluY3JlbWVudFZhbHVlcywgLi4ua2V5c1RvRGVsZXRlLCBKU09OLnN0cmluZ2lmeShmaWVsZFZhbHVlKSk7XG4gICAgICAgIGluZGV4ICs9IDIgKyBpbmNyZW1lbnRWYWx1ZXMubGVuZ3RoICsga2V5c1RvRGVsZXRlLmxlbmd0aDtcbiAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgIEFycmF5LmlzQXJyYXkoZmllbGRWYWx1ZSkgJiZcbiAgICAgICAgc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdICYmXG4gICAgICAgIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS50eXBlID09PSAnQXJyYXknXG4gICAgICApIHtcbiAgICAgICAgY29uc3QgZXhwZWN0ZWRUeXBlID0gcGFyc2VUeXBlVG9Qb3N0Z3Jlc1R5cGUoc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdKTtcbiAgICAgICAgaWYgKGV4cGVjdGVkVHlwZSA9PT0gJ3RleHRbXScpIHtcbiAgICAgICAgICB1cGRhdGVQYXR0ZXJucy5wdXNoKGAkJHtpbmRleH06bmFtZSA9ICQke2luZGV4ICsgMX06OnRleHRbXWApO1xuICAgICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkTmFtZSwgZmllbGRWYWx1ZSk7XG4gICAgICAgICAgaW5kZXggKz0gMjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB1cGRhdGVQYXR0ZXJucy5wdXNoKGAkJHtpbmRleH06bmFtZSA9ICQke2luZGV4ICsgMX06Ompzb25iYCk7XG4gICAgICAgICAgdmFsdWVzLnB1c2goZmllbGROYW1lLCBKU09OLnN0cmluZ2lmeShmaWVsZFZhbHVlKSk7XG4gICAgICAgICAgaW5kZXggKz0gMjtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZGVidWcoJ05vdCBzdXBwb3J0ZWQgdXBkYXRlJywgeyBmaWVsZE5hbWUsIGZpZWxkVmFsdWUgfSk7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChcbiAgICAgICAgICBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICBQYXJzZS5FcnJvci5PUEVSQVRJT05fRk9SQklEREVOLFxuICAgICAgICAgICAgYFBvc3RncmVzIGRvZXNuJ3Qgc3VwcG9ydCB1cGRhdGUgJHtKU09OLnN0cmluZ2lmeShmaWVsZFZhbHVlKX0geWV0YFxuICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCB3aGVyZSA9IGJ1aWxkV2hlcmVDbGF1c2Uoe1xuICAgICAgc2NoZW1hLFxuICAgICAgaW5kZXgsXG4gICAgICBxdWVyeSxcbiAgICAgIGNhc2VJbnNlbnNpdGl2ZTogZmFsc2UsXG4gICAgfSk7XG4gICAgdmFsdWVzLnB1c2goLi4ud2hlcmUudmFsdWVzKTtcblxuICAgIGNvbnN0IHdoZXJlQ2xhdXNlID0gd2hlcmUucGF0dGVybi5sZW5ndGggPiAwID8gYFdIRVJFICR7d2hlcmUucGF0dGVybn1gIDogJyc7XG4gICAgY29uc3QgcXMgPSBgVVBEQVRFICQxOm5hbWUgU0VUICR7dXBkYXRlUGF0dGVybnMuam9pbigpfSAke3doZXJlQ2xhdXNlfSBSRVRVUk5JTkcgKmA7XG4gICAgY29uc3QgcHJvbWlzZSA9ICh0cmFuc2FjdGlvbmFsU2Vzc2lvbiA/IHRyYW5zYWN0aW9uYWxTZXNzaW9uLnQgOiB0aGlzLl9jbGllbnQpXG4gICAgICAuYW55KHFzLCB2YWx1ZXMpXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gUG9zdGdyZXNVbmlxdWVJbmRleFZpb2xhdGlvbkVycm9yKSB7XG4gICAgICAgICAgY29uc3QgZXJyID0gbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgUGFyc2UuRXJyb3IuRFVQTElDQVRFX1ZBTFVFLFxuICAgICAgICAgICAgJ0EgZHVwbGljYXRlIHZhbHVlIGZvciBhIGZpZWxkIHdpdGggdW5pcXVlIHZhbHVlcyB3YXMgcHJvdmlkZWQnXG4gICAgICAgICAgKTtcbiAgICAgICAgICBlcnIudW5kZXJseWluZ0Vycm9yID0gZXJyb3I7XG4gICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQpIHtcbiAgICAgICAgICAgIGNvbnN0IGF1dGhEYXRhTWF0Y2ggPSBlcnJvci5jb25zdHJhaW50Lm1hdGNoKC9fVXNlcl91bmlxdWVfYXV0aERhdGFfKFthLXpBLVowLTlfXSspX2lkLyk7XG4gICAgICAgICAgICBpZiAoYXV0aERhdGFNYXRjaCkge1xuICAgICAgICAgICAgICBlcnIudXNlckluZm8gPSB7IGR1cGxpY2F0ZWRfZmllbGQ6IGBfYXV0aF9kYXRhXyR7YXV0aERhdGFNYXRjaFsxXX1gIH07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBjb25zdCBtYXRjaGVzID0gZXJyb3IuY29uc3RyYWludC5tYXRjaCgvdW5pcXVlXyhbYS16QS1aXSspLyk7XG4gICAgICAgICAgICAgIGlmIChtYXRjaGVzICYmIEFycmF5LmlzQXJyYXkobWF0Y2hlcykpIHtcbiAgICAgICAgICAgICAgICBlcnIudXNlckluZm8gPSB7IGR1cGxpY2F0ZWRfZmllbGQ6IG1hdGNoZXNbMV0gfTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9KTtcbiAgICBpZiAodHJhbnNhY3Rpb25hbFNlc3Npb24pIHtcbiAgICAgIHRyYW5zYWN0aW9uYWxTZXNzaW9uLmJhdGNoLnB1c2gocHJvbWlzZSk7XG4gICAgfVxuICAgIHJldHVybiBwcm9taXNlO1xuICB9XG5cbiAgLy8gSG9wZWZ1bGx5LCB3ZSBjYW4gZ2V0IHJpZCBvZiB0aGlzLiBJdCdzIG9ubHkgdXNlZCBmb3IgY29uZmlnIGFuZCBob29rcy5cbiAgdXBzZXJ0T25lT2JqZWN0KFxuICAgIGNsYXNzTmFtZTogc3RyaW5nLFxuICAgIHNjaGVtYTogU2NoZW1hVHlwZSxcbiAgICBxdWVyeTogUXVlcnlUeXBlLFxuICAgIHVwZGF0ZTogYW55LFxuICAgIHRyYW5zYWN0aW9uYWxTZXNzaW9uOiA/YW55XG4gICkge1xuICAgIGRlYnVnKCd1cHNlcnRPbmVPYmplY3QnKTtcbiAgICBjb25zdCBjcmVhdGVWYWx1ZSA9IE9iamVjdC5hc3NpZ24oe30sIHF1ZXJ5LCB1cGRhdGUpO1xuICAgIHJldHVybiB0aGlzLmNyZWF0ZU9iamVjdChjbGFzc05hbWUsIHNjaGVtYSwgY3JlYXRlVmFsdWUsIHRyYW5zYWN0aW9uYWxTZXNzaW9uKS5jYXRjaChlcnJvciA9PiB7XG4gICAgICAvLyBpZ25vcmUgZHVwbGljYXRlIHZhbHVlIGVycm9ycyBhcyBpdCdzIHVwc2VydFxuICAgICAgaWYgKGVycm9yLmNvZGUgIT09IFBhcnNlLkVycm9yLkRVUExJQ0FURV9WQUxVRSkge1xuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0aGlzLmZpbmRPbmVBbmRVcGRhdGUoY2xhc3NOYW1lLCBzY2hlbWEsIHF1ZXJ5LCB1cGRhdGUsIHRyYW5zYWN0aW9uYWxTZXNzaW9uKTtcbiAgICB9KTtcbiAgfVxuXG4gIGZpbmQoXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgc2NoZW1hOiBTY2hlbWFUeXBlLFxuICAgIHF1ZXJ5OiBRdWVyeVR5cGUsXG4gICAgeyBza2lwLCBsaW1pdCwgc29ydCwga2V5cywgY2FzZUluc2Vuc2l0aXZlLCBleHBsYWluIH06IFF1ZXJ5T3B0aW9uc1xuICApIHtcbiAgICBkZWJ1ZygnZmluZCcpO1xuICAgIGNvbnN0IGhhc0xpbWl0ID0gbGltaXQgIT09IHVuZGVmaW5lZDtcbiAgICBjb25zdCBoYXNTa2lwID0gc2tpcCAhPT0gdW5kZWZpbmVkO1xuICAgIGxldCB2YWx1ZXMgPSBbY2xhc3NOYW1lXTtcbiAgICBjb25zdCB3aGVyZSA9IGJ1aWxkV2hlcmVDbGF1c2Uoe1xuICAgICAgc2NoZW1hLFxuICAgICAgcXVlcnksXG4gICAgICBpbmRleDogMixcbiAgICAgIGNhc2VJbnNlbnNpdGl2ZSxcbiAgICB9KTtcbiAgICB2YWx1ZXMucHVzaCguLi53aGVyZS52YWx1ZXMpO1xuICAgIGNvbnN0IHdoZXJlUGF0dGVybiA9IHdoZXJlLnBhdHRlcm4ubGVuZ3RoID4gMCA/IGBXSEVSRSAke3doZXJlLnBhdHRlcm59YCA6ICcnO1xuICAgIGNvbnN0IGxpbWl0UGF0dGVybiA9IGhhc0xpbWl0ID8gYExJTUlUICQke3ZhbHVlcy5sZW5ndGggKyAxfWAgOiAnJztcbiAgICBpZiAoaGFzTGltaXQpIHtcbiAgICAgIHZhbHVlcy5wdXNoKGxpbWl0KTtcbiAgICB9XG4gICAgY29uc3Qgc2tpcFBhdHRlcm4gPSBoYXNTa2lwID8gYE9GRlNFVCAkJHt2YWx1ZXMubGVuZ3RoICsgMX1gIDogJyc7XG4gICAgaWYgKGhhc1NraXApIHtcbiAgICAgIHZhbHVlcy5wdXNoKHNraXApO1xuICAgIH1cblxuICAgIGxldCBzb3J0UGF0dGVybiA9ICcnO1xuICAgIGlmIChzb3J0KSB7XG4gICAgICBjb25zdCBzb3J0Q29weTogYW55ID0gc29ydDtcbiAgICAgIGNvbnN0IHNvcnRpbmcgPSBPYmplY3Qua2V5cyhzb3J0KVxuICAgICAgICAubWFwKGtleSA9PiB7XG4gICAgICAgICAgY29uc3QgdHJhbnNmb3JtS2V5ID0gdHJhbnNmb3JtRG90RmllbGRUb0NvbXBvbmVudHMoa2V5KS5qb2luKCctPicpO1xuICAgICAgICAgIC8vIFVzaW5nICRpZHggcGF0dGVybiBnaXZlczogIG5vbi1pbnRlZ2VyIGNvbnN0YW50IGluIE9SREVSIEJZXG4gICAgICAgICAgaWYgKHNvcnRDb3B5W2tleV0gPT09IDEpIHtcbiAgICAgICAgICAgIHJldHVybiBgJHt0cmFuc2Zvcm1LZXl9IEFTQ2A7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBgJHt0cmFuc2Zvcm1LZXl9IERFU0NgO1xuICAgICAgICB9KVxuICAgICAgICAuam9pbigpO1xuICAgICAgc29ydFBhdHRlcm4gPSBzb3J0ICE9PSB1bmRlZmluZWQgJiYgT2JqZWN0LmtleXMoc29ydCkubGVuZ3RoID4gMCA/IGBPUkRFUiBCWSAke3NvcnRpbmd9YCA6ICcnO1xuICAgIH1cbiAgICBpZiAod2hlcmUuc29ydHMgJiYgT2JqZWN0LmtleXMoKHdoZXJlLnNvcnRzOiBhbnkpKS5sZW5ndGggPiAwKSB7XG4gICAgICBzb3J0UGF0dGVybiA9IGBPUkRFUiBCWSAke3doZXJlLnNvcnRzLmpvaW4oKX1gO1xuICAgIH1cblxuICAgIGxldCBjb2x1bW5zID0gJyonO1xuICAgIGlmIChrZXlzKSB7XG4gICAgICAvLyBFeGNsdWRlIGVtcHR5IGtleXNcbiAgICAgIC8vIFJlcGxhY2UgQUNMIGJ5IGl0J3Mga2V5c1xuICAgICAga2V5cyA9IGtleXMucmVkdWNlKChtZW1vLCBrZXkpID0+IHtcbiAgICAgICAgaWYgKGtleSA9PT0gJ0FDTCcpIHtcbiAgICAgICAgICBtZW1vLnB1c2goJ19ycGVybScpO1xuICAgICAgICAgIG1lbW8ucHVzaCgnX3dwZXJtJyk7XG4gICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAga2V5Lmxlbmd0aCA+IDAgJiZcbiAgICAgICAgICAvLyBSZW1vdmUgc2VsZWN0ZWQgZmllbGQgbm90IHJlZmVyZW5jZWQgaW4gdGhlIHNjaGVtYVxuICAgICAgICAgIC8vIFJlbGF0aW9uIGlzIG5vdCBhIGNvbHVtbiBpbiBwb3N0Z3Jlc1xuICAgICAgICAgIC8vICRzY29yZSBpcyBhIFBhcnNlIHNwZWNpYWwgZmllbGQgYW5kIGlzIGFsc28gbm90IGEgY29sdW1uXG4gICAgICAgICAgKChzY2hlbWEuZmllbGRzW2tleV0gJiYgc2NoZW1hLmZpZWxkc1trZXldLnR5cGUgIT09ICdSZWxhdGlvbicpIHx8IGtleSA9PT0gJyRzY29yZScpXG4gICAgICAgICkge1xuICAgICAgICAgIG1lbW8ucHVzaChrZXkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtZW1vO1xuICAgICAgfSwgW10pO1xuICAgICAgY29sdW1ucyA9IGtleXNcbiAgICAgICAgLm1hcCgoa2V5LCBpbmRleCkgPT4ge1xuICAgICAgICAgIGlmIChrZXkgPT09ICckc2NvcmUnKSB7XG4gICAgICAgICAgICByZXR1cm4gYHRzX3JhbmtfY2QodG9fdHN2ZWN0b3IoJCR7Mn0sICQkezN9Om5hbWUpLCB0b190c3F1ZXJ5KCQkezR9LCAkJHs1fSksIDMyKSBhcyBzY29yZWA7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBgJCR7aW5kZXggKyB2YWx1ZXMubGVuZ3RoICsgMX06bmFtZWA7XG4gICAgICAgIH0pXG4gICAgICAgIC5qb2luKCk7XG4gICAgICB2YWx1ZXMgPSB2YWx1ZXMuY29uY2F0KGtleXMpO1xuICAgIH1cblxuICAgIGNvbnN0IG9yaWdpbmFsUXVlcnkgPSBgU0VMRUNUICR7Y29sdW1uc30gRlJPTSAkMTpuYW1lICR7d2hlcmVQYXR0ZXJufSAke3NvcnRQYXR0ZXJufSAke2xpbWl0UGF0dGVybn0gJHtza2lwUGF0dGVybn1gO1xuICAgIGNvbnN0IHFzID0gZXhwbGFpbiA/IHRoaXMuY3JlYXRlRXhwbGFpbmFibGVRdWVyeShvcmlnaW5hbFF1ZXJ5KSA6IG9yaWdpbmFsUXVlcnk7XG4gICAgcmV0dXJuIHRoaXMuX2NsaWVudFxuICAgICAgLmFueShxcywgdmFsdWVzKVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgIGVycm9yLmNvZGUgIT09IFBvc3RncmVzUmVsYXRpb25Eb2VzTm90RXhpc3RFcnJvciAmJlxuICAgICAgICAgIGVycm9yLmNvZGUgIT09IFBvc3RncmVzTWlzc2luZ0NvbHVtbkVycm9yXG4gICAgICAgICkge1xuICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH0pXG4gICAgICAudGhlbihyZXN1bHRzID0+IHtcbiAgICAgICAgaWYgKGV4cGxhaW4pIHtcbiAgICAgICAgICByZXR1cm4gcmVzdWx0cztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0cy5tYXAob2JqZWN0ID0+IHRoaXMucG9zdGdyZXNPYmplY3RUb1BhcnNlT2JqZWN0KGNsYXNzTmFtZSwgb2JqZWN0LCBzY2hlbWEpKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgLy8gQ29udmVydHMgZnJvbSBhIHBvc3RncmVzLWZvcm1hdCBvYmplY3QgdG8gYSBSRVNULWZvcm1hdCBvYmplY3QuXG4gIC8vIERvZXMgbm90IHN0cmlwIG91dCBhbnl0aGluZyBiYXNlZCBvbiBhIGxhY2sgb2YgYXV0aGVudGljYXRpb24uXG4gIHBvc3RncmVzT2JqZWN0VG9QYXJzZU9iamVjdChjbGFzc05hbWU6IHN0cmluZywgb2JqZWN0OiBhbnksIHNjaGVtYTogYW55KSB7XG4gICAgT2JqZWN0LmtleXMoc2NoZW1hLmZpZWxkcykuZm9yRWFjaChmaWVsZE5hbWUgPT4ge1xuICAgICAgaWYgKHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS50eXBlID09PSAnUG9pbnRlcicgJiYgb2JqZWN0W2ZpZWxkTmFtZV0pIHtcbiAgICAgICAgb2JqZWN0W2ZpZWxkTmFtZV0gPSB7XG4gICAgICAgICAgb2JqZWN0SWQ6IG9iamVjdFtmaWVsZE5hbWVdLFxuICAgICAgICAgIF9fdHlwZTogJ1BvaW50ZXInLFxuICAgICAgICAgIGNsYXNzTmFtZTogc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdLnRhcmdldENsYXNzLFxuICAgICAgICB9O1xuICAgICAgfVxuICAgICAgaWYgKHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS50eXBlID09PSAnUmVsYXRpb24nKSB7XG4gICAgICAgIG9iamVjdFtmaWVsZE5hbWVdID0ge1xuICAgICAgICAgIF9fdHlwZTogJ1JlbGF0aW9uJyxcbiAgICAgICAgICBjbGFzc05hbWU6IHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS50YXJnZXRDbGFzcyxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIGlmIChvYmplY3RbZmllbGROYW1lXSAmJiBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0udHlwZSA9PT0gJ0dlb1BvaW50Jykge1xuICAgICAgICBvYmplY3RbZmllbGROYW1lXSA9IHtcbiAgICAgICAgICBfX3R5cGU6ICdHZW9Qb2ludCcsXG4gICAgICAgICAgbGF0aXR1ZGU6IG9iamVjdFtmaWVsZE5hbWVdLnksXG4gICAgICAgICAgbG9uZ2l0dWRlOiBvYmplY3RbZmllbGROYW1lXS54LFxuICAgICAgICB9O1xuICAgICAgfVxuICAgICAgaWYgKG9iamVjdFtmaWVsZE5hbWVdICYmIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS50eXBlID09PSAnUG9seWdvbicpIHtcbiAgICAgICAgbGV0IGNvb3JkcyA9IG5ldyBTdHJpbmcob2JqZWN0W2ZpZWxkTmFtZV0pO1xuICAgICAgICBjb29yZHMgPSBjb29yZHMuc3Vic3RyaW5nKDIsIGNvb3Jkcy5sZW5ndGggLSAyKS5zcGxpdCgnKSwoJyk7XG4gICAgICAgIGNvbnN0IHVwZGF0ZWRDb29yZHMgPSBjb29yZHMubWFwKHBvaW50ID0+IHtcbiAgICAgICAgICByZXR1cm4gW3BhcnNlRmxvYXQocG9pbnQuc3BsaXQoJywnKVsxXSksIHBhcnNlRmxvYXQocG9pbnQuc3BsaXQoJywnKVswXSldO1xuICAgICAgICB9KTtcbiAgICAgICAgb2JqZWN0W2ZpZWxkTmFtZV0gPSB7XG4gICAgICAgICAgX190eXBlOiAnUG9seWdvbicsXG4gICAgICAgICAgY29vcmRpbmF0ZXM6IHVwZGF0ZWRDb29yZHMsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBpZiAob2JqZWN0W2ZpZWxkTmFtZV0gJiYgc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdLnR5cGUgPT09ICdGaWxlJykge1xuICAgICAgICBvYmplY3RbZmllbGROYW1lXSA9IHtcbiAgICAgICAgICBfX3R5cGU6ICdGaWxlJyxcbiAgICAgICAgICBuYW1lOiBvYmplY3RbZmllbGROYW1lXSxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICAvL1RPRE86IHJlbW92ZSB0aGlzIHJlbGlhbmNlIG9uIHRoZSBtb25nbyBmb3JtYXQuIERCIGFkYXB0ZXIgc2hvdWxkbid0IGtub3cgdGhlcmUgaXMgYSBkaWZmZXJlbmNlIGJldHdlZW4gY3JlYXRlZCBhdCBhbmQgYW55IG90aGVyIGRhdGUgZmllbGQuXG4gICAgaWYgKG9iamVjdC5jcmVhdGVkQXQpIHtcbiAgICAgIG9iamVjdC5jcmVhdGVkQXQgPSBvYmplY3QuY3JlYXRlZEF0LnRvSVNPU3RyaW5nKCk7XG4gICAgfVxuICAgIGlmIChvYmplY3QudXBkYXRlZEF0KSB7XG4gICAgICBvYmplY3QudXBkYXRlZEF0ID0gb2JqZWN0LnVwZGF0ZWRBdC50b0lTT1N0cmluZygpO1xuICAgIH1cbiAgICBpZiAob2JqZWN0LmV4cGlyZXNBdCkge1xuICAgICAgb2JqZWN0LmV4cGlyZXNBdCA9IHtcbiAgICAgICAgX190eXBlOiAnRGF0ZScsXG4gICAgICAgIGlzbzogb2JqZWN0LmV4cGlyZXNBdC50b0lTT1N0cmluZygpLFxuICAgICAgfTtcbiAgICB9XG4gICAgaWYgKG9iamVjdC5fZW1haWxfdmVyaWZ5X3Rva2VuX2V4cGlyZXNfYXQpIHtcbiAgICAgIG9iamVjdC5fZW1haWxfdmVyaWZ5X3Rva2VuX2V4cGlyZXNfYXQgPSB7XG4gICAgICAgIF9fdHlwZTogJ0RhdGUnLFxuICAgICAgICBpc286IG9iamVjdC5fZW1haWxfdmVyaWZ5X3Rva2VuX2V4cGlyZXNfYXQudG9JU09TdHJpbmcoKSxcbiAgICAgIH07XG4gICAgfVxuICAgIGlmIChvYmplY3QuX2FjY291bnRfbG9ja291dF9leHBpcmVzX2F0KSB7XG4gICAgICBvYmplY3QuX2FjY291bnRfbG9ja291dF9leHBpcmVzX2F0ID0ge1xuICAgICAgICBfX3R5cGU6ICdEYXRlJyxcbiAgICAgICAgaXNvOiBvYmplY3QuX2FjY291bnRfbG9ja291dF9leHBpcmVzX2F0LnRvSVNPU3RyaW5nKCksXG4gICAgICB9O1xuICAgIH1cbiAgICBpZiAob2JqZWN0Ll9wZXJpc2hhYmxlX3Rva2VuX2V4cGlyZXNfYXQpIHtcbiAgICAgIG9iamVjdC5fcGVyaXNoYWJsZV90b2tlbl9leHBpcmVzX2F0ID0ge1xuICAgICAgICBfX3R5cGU6ICdEYXRlJyxcbiAgICAgICAgaXNvOiBvYmplY3QuX3BlcmlzaGFibGVfdG9rZW5fZXhwaXJlc19hdC50b0lTT1N0cmluZygpLFxuICAgICAgfTtcbiAgICB9XG4gICAgaWYgKG9iamVjdC5fcGFzc3dvcmRfY2hhbmdlZF9hdCkge1xuICAgICAgb2JqZWN0Ll9wYXNzd29yZF9jaGFuZ2VkX2F0ID0ge1xuICAgICAgICBfX3R5cGU6ICdEYXRlJyxcbiAgICAgICAgaXNvOiBvYmplY3QuX3Bhc3N3b3JkX2NoYW5nZWRfYXQudG9JU09TdHJpbmcoKSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBmaWVsZE5hbWUgaW4gb2JqZWN0KSB7XG4gICAgICBpZiAob2JqZWN0W2ZpZWxkTmFtZV0gPT09IG51bGwpIHtcbiAgICAgICAgZGVsZXRlIG9iamVjdFtmaWVsZE5hbWVdO1xuICAgICAgfVxuICAgICAgaWYgKFV0aWxzLmlzRGF0ZShvYmplY3RbZmllbGROYW1lXSkpIHtcbiAgICAgICAgb2JqZWN0W2ZpZWxkTmFtZV0gPSB7XG4gICAgICAgICAgX190eXBlOiAnRGF0ZScsXG4gICAgICAgICAgaXNvOiBvYmplY3RbZmllbGROYW1lXS50b0lTT1N0cmluZygpLFxuICAgICAgICB9O1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBvYmplY3Q7XG4gIH1cblxuICAvLyBDcmVhdGUgYSB1bmlxdWUgaW5kZXguIFVuaXF1ZSBpbmRleGVzIG9uIG51bGxhYmxlIGZpZWxkcyBhcmUgbm90IGFsbG93ZWQuIFNpbmNlIHdlIGRvbid0XG4gIC8vIGN1cnJlbnRseSBrbm93IHdoaWNoIGZpZWxkcyBhcmUgbnVsbGFibGUgYW5kIHdoaWNoIGFyZW4ndCwgd2UgaWdub3JlIHRoYXQgY3JpdGVyaWEuXG4gIC8vIEFzIHN1Y2gsIHdlIHNob3VsZG4ndCBleHBvc2UgdGhpcyBmdW5jdGlvbiB0byB1c2VycyBvZiBwYXJzZSB1bnRpbCB3ZSBoYXZlIGFuIG91dC1vZi1iYW5kXG4gIC8vIFdheSBvZiBkZXRlcm1pbmluZyBpZiBhIGZpZWxkIGlzIG51bGxhYmxlLiBVbmRlZmluZWQgZG9lc24ndCBjb3VudCBhZ2FpbnN0IHVuaXF1ZW5lc3MsXG4gIC8vIHdoaWNoIGlzIHdoeSB3ZSB1c2Ugc3BhcnNlIGluZGV4ZXMuXG4gIGFzeW5jIGVuc3VyZVVuaXF1ZW5lc3MoY2xhc3NOYW1lOiBzdHJpbmcsIHNjaGVtYTogU2NoZW1hVHlwZSwgZmllbGROYW1lczogc3RyaW5nW10pIHtcbiAgICBjb25zdCBjb25zdHJhaW50TmFtZSA9IGAke2NsYXNzTmFtZX1fdW5pcXVlXyR7ZmllbGROYW1lcy5zb3J0KCkuam9pbignXycpfWA7XG4gICAgY29uc3QgY29uc3RyYWludFBhdHRlcm5zID0gZmllbGROYW1lcy5tYXAoKGZpZWxkTmFtZSwgaW5kZXgpID0+IGAkJHtpbmRleCArIDN9Om5hbWVgKTtcbiAgICBjb25zdCBxcyA9IGBDUkVBVEUgVU5JUVVFIElOREVYIElGIE5PVCBFWElTVFMgJDI6bmFtZSBPTiAkMTpuYW1lKCR7Y29uc3RyYWludFBhdHRlcm5zLmpvaW4oKX0pYDtcbiAgICByZXR1cm4gdGhpcy5fY2xpZW50Lm5vbmUocXMsIFtjbGFzc05hbWUsIGNvbnN0cmFpbnROYW1lLCAuLi5maWVsZE5hbWVzXSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgaWYgKGVycm9yLmNvZGUgPT09IFBvc3RncmVzRHVwbGljYXRlUmVsYXRpb25FcnJvciAmJiBlcnJvci5tZXNzYWdlLmluY2x1ZGVzKGNvbnN0cmFpbnROYW1lKSkge1xuICAgICAgICAvLyBJbmRleCBhbHJlYWR5IGV4aXN0cy4gSWdub3JlIGVycm9yLlxuICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgZXJyb3IuY29kZSA9PT0gUG9zdGdyZXNVbmlxdWVJbmRleFZpb2xhdGlvbkVycm9yICYmXG4gICAgICAgIGVycm9yLm1lc3NhZ2UuaW5jbHVkZXMoY29uc3RyYWludE5hbWUpXG4gICAgICApIHtcbiAgICAgICAgLy8gQ2FzdCB0aGUgZXJyb3IgaW50byB0aGUgcHJvcGVyIHBhcnNlIGVycm9yXG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5EVVBMSUNBVEVfVkFMVUUsXG4gICAgICAgICAgJ0EgZHVwbGljYXRlIHZhbHVlIGZvciBhIGZpZWxkIHdpdGggdW5pcXVlIHZhbHVlcyB3YXMgcHJvdmlkZWQnXG4gICAgICAgICk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8vIENyZWF0ZXMgYSB1bmlxdWUgaW5kZXggb24gYXV0aERhdGEtPjxwcm92aWRlcj4tPj4naWQnIHRvIHByZXZlbnRcbiAgLy8gcmFjZSBjb25kaXRpb25zIGR1cmluZyBjb25jdXJyZW50IHNpZ251cHMgd2l0aCB0aGUgc2FtZSBhdXRoRGF0YS5cbiAgYXN5bmMgZW5zdXJlQXV0aERhdGFVbmlxdWVuZXNzKHByb3ZpZGVyOiBzdHJpbmcpIHtcbiAgICBjb25zdCBpbmRleE5hbWUgPSBgX1VzZXJfdW5pcXVlX2F1dGhEYXRhXyR7cHJvdmlkZXJ9X2lkYDtcbiAgICBjb25zdCBxcyA9IGBDUkVBVEUgVU5JUVVFIElOREVYIElGIE5PVCBFWElTVFMgJDE6bmFtZSBPTiBcIl9Vc2VyXCIgKChcImF1dGhEYXRhXCItPiQyOjp0ZXh0LT4+J2lkJykpIFdIRVJFIFwiYXV0aERhdGFcIi0+JDI6OnRleHQtPj4naWQnIElTIE5PVCBOVUxMYDtcbiAgICBhd2FpdCB0aGlzLl9jbGllbnQubm9uZShxcywgW2luZGV4TmFtZSwgcHJvdmlkZXJdKS5jYXRjaChlcnJvciA9PiB7XG4gICAgICBpZiAoXG4gICAgICAgIGVycm9yLmNvZGUgPT09IFBvc3RncmVzRHVwbGljYXRlUmVsYXRpb25FcnJvciAmJlxuICAgICAgICBlcnJvci5tZXNzYWdlLmluY2x1ZGVzKGluZGV4TmFtZSlcbiAgICAgICkge1xuICAgICAgICAvLyBJbmRleCBhbHJlYWR5IGV4aXN0cy4gSWdub3JlIGVycm9yLlxuICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgZXJyb3IuY29kZSA9PT0gUG9zdGdyZXNVbmlxdWVJbmRleFZpb2xhdGlvbkVycm9yICYmXG4gICAgICAgIGVycm9yLm1lc3NhZ2UuaW5jbHVkZXMoaW5kZXhOYW1lKVxuICAgICAgKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5EVVBMSUNBVEVfVkFMVUUsXG4gICAgICAgICAgJ1RyaWVkIHRvIGVuc3VyZSBmaWVsZCB1bmlxdWVuZXNzIGZvciBhIGNsYXNzIHRoYXQgYWxyZWFkeSBoYXMgZHVwbGljYXRlcy4nXG4gICAgICAgICk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8vIEV4ZWN1dGVzIGEgY291bnQuXG4gIGFzeW5jIGNvdW50KFxuICAgIGNsYXNzTmFtZTogc3RyaW5nLFxuICAgIHNjaGVtYTogU2NoZW1hVHlwZSxcbiAgICBxdWVyeTogUXVlcnlUeXBlLFxuICAgIHJlYWRQcmVmZXJlbmNlPzogc3RyaW5nLFxuICAgIGVzdGltYXRlPzogYm9vbGVhbiA9IHRydWVcbiAgKSB7XG4gICAgZGVidWcoJ2NvdW50Jyk7XG4gICAgY29uc3QgdmFsdWVzID0gW2NsYXNzTmFtZV07XG4gICAgY29uc3Qgd2hlcmUgPSBidWlsZFdoZXJlQ2xhdXNlKHtcbiAgICAgIHNjaGVtYSxcbiAgICAgIHF1ZXJ5LFxuICAgICAgaW5kZXg6IDIsXG4gICAgICBjYXNlSW5zZW5zaXRpdmU6IGZhbHNlLFxuICAgIH0pO1xuICAgIHZhbHVlcy5wdXNoKC4uLndoZXJlLnZhbHVlcyk7XG5cbiAgICBjb25zdCB3aGVyZVBhdHRlcm4gPSB3aGVyZS5wYXR0ZXJuLmxlbmd0aCA+IDAgPyBgV0hFUkUgJHt3aGVyZS5wYXR0ZXJufWAgOiAnJztcbiAgICBsZXQgcXMgPSAnJztcblxuICAgIGlmICh3aGVyZS5wYXR0ZXJuLmxlbmd0aCA+IDAgfHwgIWVzdGltYXRlKSB7XG4gICAgICBxcyA9IGBTRUxFQ1QgY291bnQoKikgRlJPTSAkMTpuYW1lICR7d2hlcmVQYXR0ZXJufWA7XG4gICAgfSBlbHNlIHtcbiAgICAgIHFzID0gJ1NFTEVDVCByZWx0dXBsZXMgQVMgYXBwcm94aW1hdGVfcm93X2NvdW50IEZST00gcGdfY2xhc3MgV0hFUkUgcmVsbmFtZSA9ICQxJztcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5fY2xpZW50XG4gICAgICAub25lKHFzLCB2YWx1ZXMsIGEgPT4ge1xuICAgICAgICBpZiAoYS5hcHByb3hpbWF0ZV9yb3dfY291bnQgPT0gbnVsbCB8fCBhLmFwcHJveGltYXRlX3Jvd19jb3VudCA9PSAtMSkge1xuICAgICAgICAgIHJldHVybiAhaXNOYU4oK2EuY291bnQpID8gK2EuY291bnQgOiAwO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiArYS5hcHByb3hpbWF0ZV9yb3dfY291bnQ7XG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgZXJyb3IuY29kZSAhPT0gUG9zdGdyZXNSZWxhdGlvbkRvZXNOb3RFeGlzdEVycm9yICYmXG4gICAgICAgICAgZXJyb3IuY29kZSAhPT0gUG9zdGdyZXNNaXNzaW5nQ29sdW1uRXJyb3JcbiAgICAgICAgKSB7XG4gICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIDA7XG4gICAgICB9KTtcbiAgfVxuXG4gIGFzeW5jIGRpc3RpbmN0KGNsYXNzTmFtZTogc3RyaW5nLCBzY2hlbWE6IFNjaGVtYVR5cGUsIHF1ZXJ5OiBRdWVyeVR5cGUsIGZpZWxkTmFtZTogc3RyaW5nKSB7XG4gICAgZGVidWcoJ2Rpc3RpbmN0Jyk7XG4gICAgY29uc3QgZmllbGRTZWdtZW50cyA9IGZpZWxkTmFtZS5zcGxpdCgnLicpO1xuICAgIGZvciAoY29uc3Qgc2VnbWVudCBvZiBmaWVsZFNlZ21lbnRzKSB7XG4gICAgICBpZiAoIXNlZ21lbnQubWF0Y2goL15bYS16QS1aXVthLXpBLVowLTlfXSokLykpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfS0VZX05BTUUsIGBJbnZhbGlkIGZpZWxkIG5hbWU6ICR7ZmllbGROYW1lfWApO1xuICAgICAgfVxuICAgIH1cbiAgICBsZXQgZmllbGQgPSBmaWVsZE5hbWU7XG4gICAgbGV0IGNvbHVtbiA9IGZpZWxkTmFtZTtcbiAgICBjb25zdCBpc05lc3RlZCA9IGZpZWxkTmFtZS5pbmRleE9mKCcuJykgPj0gMDtcbiAgICBpZiAoaXNOZXN0ZWQpIHtcbiAgICAgIGZpZWxkID0gdHJhbnNmb3JtRG90RmllbGRUb0NvbXBvbmVudHMoZmllbGROYW1lKS5qb2luKCctPicpO1xuICAgICAgY29sdW1uID0gZmllbGRTZWdtZW50c1swXTtcbiAgICB9XG4gICAgY29uc3QgaXNBcnJheUZpZWxkID1cbiAgICAgIHNjaGVtYS5maWVsZHMgJiYgc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdICYmIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS50eXBlID09PSAnQXJyYXknO1xuICAgIGNvbnN0IGlzUG9pbnRlckZpZWxkID1cbiAgICAgIHNjaGVtYS5maWVsZHMgJiYgc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdICYmIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS50eXBlID09PSAnUG9pbnRlcic7XG4gICAgY29uc3QgdmFsdWVzID0gW2ZpZWxkLCBjb2x1bW4sIGNsYXNzTmFtZV07XG4gICAgY29uc3Qgd2hlcmUgPSBidWlsZFdoZXJlQ2xhdXNlKHtcbiAgICAgIHNjaGVtYSxcbiAgICAgIHF1ZXJ5LFxuICAgICAgaW5kZXg6IDQsXG4gICAgICBjYXNlSW5zZW5zaXRpdmU6IGZhbHNlLFxuICAgIH0pO1xuICAgIHZhbHVlcy5wdXNoKC4uLndoZXJlLnZhbHVlcyk7XG5cbiAgICBjb25zdCB3aGVyZVBhdHRlcm4gPSB3aGVyZS5wYXR0ZXJuLmxlbmd0aCA+IDAgPyBgV0hFUkUgJHt3aGVyZS5wYXR0ZXJufWAgOiAnJztcbiAgICBjb25zdCB0cmFuc2Zvcm1lciA9IGlzQXJyYXlGaWVsZCA/ICdqc29uYl9hcnJheV9lbGVtZW50cycgOiAnT04nO1xuICAgIGxldCBxcyA9IGBTRUxFQ1QgRElTVElOQ1QgJHt0cmFuc2Zvcm1lcn0oJDE6bmFtZSkgJDI6bmFtZSBGUk9NICQzOm5hbWUgJHt3aGVyZVBhdHRlcm59YDtcbiAgICBpZiAoaXNOZXN0ZWQpIHtcbiAgICAgIHFzID0gYFNFTEVDVCBESVNUSU5DVCAke3RyYW5zZm9ybWVyfSgkMTpyYXcpICQyOnJhdyBGUk9NICQzOm5hbWUgJHt3aGVyZVBhdHRlcm59YDtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX2NsaWVudFxuICAgICAgLmFueShxcywgdmFsdWVzKVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgaWYgKGVycm9yLmNvZGUgPT09IFBvc3RncmVzTWlzc2luZ0NvbHVtbkVycm9yKSB7XG4gICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICB9XG4gICAgICAgIHRocm93IGVycm9yO1xuICAgICAgfSlcbiAgICAgIC50aGVuKHJlc3VsdHMgPT4ge1xuICAgICAgICBpZiAoIWlzTmVzdGVkKSB7XG4gICAgICAgICAgcmVzdWx0cyA9IHJlc3VsdHMuZmlsdGVyKG9iamVjdCA9PiBvYmplY3RbZmllbGRdICE9PSBudWxsKTtcbiAgICAgICAgICByZXR1cm4gcmVzdWx0cy5tYXAob2JqZWN0ID0+IHtcbiAgICAgICAgICAgIGlmICghaXNQb2ludGVyRmllbGQpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIG9iamVjdFtmaWVsZF07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICBfX3R5cGU6ICdQb2ludGVyJyxcbiAgICAgICAgICAgICAgY2xhc3NOYW1lOiBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0udGFyZ2V0Q2xhc3MsXG4gICAgICAgICAgICAgIG9iamVjdElkOiBvYmplY3RbZmllbGRdLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBjaGlsZCA9IGZpZWxkTmFtZS5zcGxpdCgnLicpWzFdO1xuICAgICAgICByZXR1cm4gcmVzdWx0cy5tYXAob2JqZWN0ID0+IG9iamVjdFtjb2x1bW5dW2NoaWxkXSk7XG4gICAgICB9KVxuICAgICAgLnRoZW4ocmVzdWx0cyA9PlxuICAgICAgICByZXN1bHRzLm1hcChvYmplY3QgPT4gdGhpcy5wb3N0Z3Jlc09iamVjdFRvUGFyc2VPYmplY3QoY2xhc3NOYW1lLCBvYmplY3QsIHNjaGVtYSkpXG4gICAgICApO1xuICB9XG5cbiAgYXN5bmMgYWdncmVnYXRlKFxuICAgIGNsYXNzTmFtZTogc3RyaW5nLFxuICAgIHNjaGVtYTogYW55LFxuICAgIHBpcGVsaW5lOiBhbnksXG4gICAgcmVhZFByZWZlcmVuY2U6ID9zdHJpbmcsXG4gICAgaGludDogP21peGVkLFxuICAgIGV4cGxhaW4/OiBib29sZWFuXG4gICkge1xuICAgIGRlYnVnKCdhZ2dyZWdhdGUnKTtcbiAgICBjb25zdCB2YWx1ZXMgPSBbY2xhc3NOYW1lXTtcbiAgICBsZXQgaW5kZXg6IG51bWJlciA9IDI7XG4gICAgbGV0IGNvbHVtbnM6IHN0cmluZ1tdID0gW107XG4gICAgbGV0IGNvdW50RmllbGQgPSBudWxsO1xuICAgIGxldCBncm91cFZhbHVlcyA9IG51bGw7XG4gICAgbGV0IHdoZXJlUGF0dGVybiA9ICcnO1xuICAgIGxldCBsaW1pdFBhdHRlcm4gPSAnJztcbiAgICBsZXQgc2tpcFBhdHRlcm4gPSAnJztcbiAgICBsZXQgc29ydFBhdHRlcm4gPSAnJztcbiAgICBsZXQgZ3JvdXBQYXR0ZXJuID0gJyc7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwaXBlbGluZS5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgY29uc3Qgc3RhZ2UgPSBwaXBlbGluZVtpXTtcbiAgICAgIGlmIChzdGFnZS4kZ3JvdXApIHtcbiAgICAgICAgZm9yIChjb25zdCBmaWVsZCBpbiBzdGFnZS4kZ3JvdXApIHtcbiAgICAgICAgICBjb25zdCB2YWx1ZSA9IHN0YWdlLiRncm91cFtmaWVsZF07XG4gICAgICAgICAgaWYgKHZhbHVlID09PSBudWxsIHx8IHZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoZmllbGQgPT09ICdfaWQnICYmIHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgJiYgdmFsdWUgIT09ICcnKSB7XG4gICAgICAgICAgICBjb2x1bW5zLnB1c2goYCQke2luZGV4fTpuYW1lIEFTIFwib2JqZWN0SWRcImApO1xuICAgICAgICAgICAgZ3JvdXBQYXR0ZXJuID0gYEdST1VQIEJZICQke2luZGV4fTpuYW1lYDtcbiAgICAgICAgICAgIHZhbHVlcy5wdXNoKHRyYW5zZm9ybUFnZ3JlZ2F0ZUZpZWxkKHZhbHVlKSk7XG4gICAgICAgICAgICBpbmRleCArPSAxO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChmaWVsZCA9PT0gJ19pZCcgJiYgdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJiBPYmplY3Qua2V5cyh2YWx1ZSkubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgICBncm91cFZhbHVlcyA9IHZhbHVlO1xuICAgICAgICAgICAgY29uc3QgZ3JvdXBCeUZpZWxkcyA9IFtdO1xuICAgICAgICAgICAgZm9yIChjb25zdCBhbGlhcyBpbiB2YWx1ZSkge1xuICAgICAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlW2FsaWFzXSA9PT0gJ3N0cmluZycgJiYgdmFsdWVbYWxpYXNdKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc291cmNlID0gdHJhbnNmb3JtQWdncmVnYXRlRmllbGQodmFsdWVbYWxpYXNdKTtcbiAgICAgICAgICAgICAgICBpZiAoIWdyb3VwQnlGaWVsZHMuaW5jbHVkZXMoYFwiJHtzb3VyY2V9XCJgKSkge1xuICAgICAgICAgICAgICAgICAgZ3JvdXBCeUZpZWxkcy5wdXNoKGBcIiR7c291cmNlfVwiYCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhbHVlcy5wdXNoKHNvdXJjZSwgYWxpYXMpO1xuICAgICAgICAgICAgICAgIGNvbHVtbnMucHVzaChgJCR7aW5kZXh9Om5hbWUgQVMgJCR7aW5kZXggKyAxfTpuYW1lYCk7XG4gICAgICAgICAgICAgICAgaW5kZXggKz0gMjtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBvcGVyYXRpb24gPSBPYmplY3Qua2V5cyh2YWx1ZVthbGlhc10pWzBdO1xuICAgICAgICAgICAgICAgIGNvbnN0IHNvdXJjZSA9IHRyYW5zZm9ybUFnZ3JlZ2F0ZUZpZWxkKHZhbHVlW2FsaWFzXVtvcGVyYXRpb25dKTtcbiAgICAgICAgICAgICAgICBpZiAobW9uZ29BZ2dyZWdhdGVUb1Bvc3RncmVzW29wZXJhdGlvbl0pIHtcbiAgICAgICAgICAgICAgICAgIGlmICghZ3JvdXBCeUZpZWxkcy5pbmNsdWRlcyhgXCIke3NvdXJjZX1cImApKSB7XG4gICAgICAgICAgICAgICAgICAgIGdyb3VwQnlGaWVsZHMucHVzaChgXCIke3NvdXJjZX1cImApO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgY29sdW1ucy5wdXNoKFxuICAgICAgICAgICAgICAgICAgICBgRVhUUkFDVCgke21vbmdvQWdncmVnYXRlVG9Qb3N0Z3Jlc1tvcGVyYXRpb25dXG4gICAgICAgICAgICAgICAgICAgIH0gRlJPTSAkJHtpbmRleH06bmFtZSBBVCBUSU1FIFpPTkUgJ1VUQycpOjppbnRlZ2VyIEFTICQke2luZGV4ICsgMX06bmFtZWBcbiAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICB2YWx1ZXMucHVzaChzb3VyY2UsIGFsaWFzKTtcbiAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBncm91cFBhdHRlcm4gPSBgR1JPVVAgQlkgJCR7aW5kZXh9OnJhd2A7XG4gICAgICAgICAgICB2YWx1ZXMucHVzaChncm91cEJ5RmllbGRzLmpvaW4oKSk7XG4gICAgICAgICAgICBpbmRleCArPSAxO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICBpZiAodmFsdWUuJHN1bSkge1xuICAgICAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlLiRzdW0gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgY29sdW1ucy5wdXNoKGBTVU0oJCR7aW5kZXh9Om5hbWUpIEFTICQke2luZGV4ICsgMX06bmFtZWApO1xuICAgICAgICAgICAgICAgIHZhbHVlcy5wdXNoKHRyYW5zZm9ybUFnZ3JlZ2F0ZUZpZWxkKHZhbHVlLiRzdW0pLCBmaWVsZCk7XG4gICAgICAgICAgICAgICAgaW5kZXggKz0gMjtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb3VudEZpZWxkID0gZmllbGQ7XG4gICAgICAgICAgICAgICAgY29sdW1ucy5wdXNoKGBDT1VOVCgqKSBBUyAkJHtpbmRleH06bmFtZWApO1xuICAgICAgICAgICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkKTtcbiAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodmFsdWUuJG1heCkge1xuICAgICAgICAgICAgICBjb2x1bW5zLnB1c2goYE1BWCgkJHtpbmRleH06bmFtZSkgQVMgJCR7aW5kZXggKyAxfTpuYW1lYCk7XG4gICAgICAgICAgICAgIHZhbHVlcy5wdXNoKHRyYW5zZm9ybUFnZ3JlZ2F0ZUZpZWxkKHZhbHVlLiRtYXgpLCBmaWVsZCk7XG4gICAgICAgICAgICAgIGluZGV4ICs9IDI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodmFsdWUuJG1pbikge1xuICAgICAgICAgICAgICBjb2x1bW5zLnB1c2goYE1JTigkJHtpbmRleH06bmFtZSkgQVMgJCR7aW5kZXggKyAxfTpuYW1lYCk7XG4gICAgICAgICAgICAgIHZhbHVlcy5wdXNoKHRyYW5zZm9ybUFnZ3JlZ2F0ZUZpZWxkKHZhbHVlLiRtaW4pLCBmaWVsZCk7XG4gICAgICAgICAgICAgIGluZGV4ICs9IDI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodmFsdWUuJGF2Zykge1xuICAgICAgICAgICAgICBjb2x1bW5zLnB1c2goYEFWRygkJHtpbmRleH06bmFtZSkgQVMgJCR7aW5kZXggKyAxfTpuYW1lYCk7XG4gICAgICAgICAgICAgIHZhbHVlcy5wdXNoKHRyYW5zZm9ybUFnZ3JlZ2F0ZUZpZWxkKHZhbHVlLiRhdmcpLCBmaWVsZCk7XG4gICAgICAgICAgICAgIGluZGV4ICs9IDI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb2x1bW5zLnB1c2goJyonKTtcbiAgICAgIH1cbiAgICAgIGlmIChzdGFnZS4kcHJvamVjdCkge1xuICAgICAgICBpZiAoY29sdW1ucy5pbmNsdWRlcygnKicpKSB7XG4gICAgICAgICAgY29sdW1ucyA9IFtdO1xuICAgICAgICB9XG4gICAgICAgIGZvciAoY29uc3QgZmllbGQgaW4gc3RhZ2UuJHByb2plY3QpIHtcbiAgICAgICAgICBjb25zdCB2YWx1ZSA9IHN0YWdlLiRwcm9qZWN0W2ZpZWxkXTtcbiAgICAgICAgICBpZiAodmFsdWUgPT09IDEgfHwgdmFsdWUgPT09IHRydWUpIHtcbiAgICAgICAgICAgIGNvbHVtbnMucHVzaChgJCR7aW5kZXh9Om5hbWVgKTtcbiAgICAgICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkKTtcbiAgICAgICAgICAgIGluZGV4ICs9IDE7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoc3RhZ2UuJG1hdGNoKSB7XG4gICAgICAgIGNvbnN0IHBhdHRlcm5zID0gW107XG4gICAgICAgIGNvbnN0IG9yT3JBbmQgPSBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoc3RhZ2UuJG1hdGNoLCAnJG9yJylcbiAgICAgICAgICA/ICcgT1IgJ1xuICAgICAgICAgIDogJyBBTkQgJztcblxuICAgICAgICBpZiAoc3RhZ2UuJG1hdGNoLiRvcikge1xuICAgICAgICAgIGNvbnN0IGNvbGxhcHNlID0ge307XG4gICAgICAgICAgc3RhZ2UuJG1hdGNoLiRvci5mb3JFYWNoKGVsZW1lbnQgPT4ge1xuICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gZWxlbWVudCkge1xuICAgICAgICAgICAgICBjb2xsYXBzZVtrZXldID0gZWxlbWVudFtrZXldO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHN0YWdlLiRtYXRjaCA9IGNvbGxhcHNlO1xuICAgICAgICB9XG4gICAgICAgIGZvciAobGV0IGZpZWxkIGluIHN0YWdlLiRtYXRjaCkge1xuICAgICAgICAgIGNvbnN0IHZhbHVlID0gc3RhZ2UuJG1hdGNoW2ZpZWxkXTtcbiAgICAgICAgICBpZiAoZmllbGQgPT09ICdfaWQnKSB7XG4gICAgICAgICAgICBmaWVsZCA9ICdvYmplY3RJZCc7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnN0IG1hdGNoUGF0dGVybnMgPSBbXTtcbiAgICAgICAgICBPYmplY3Qua2V5cyhQYXJzZVRvUG9zZ3Jlc0NvbXBhcmF0b3IpLmZvckVhY2goY21wID0+IHtcbiAgICAgICAgICAgIGlmICh2YWx1ZVtjbXBdKSB7XG4gICAgICAgICAgICAgIGNvbnN0IHBnQ29tcGFyYXRvciA9IFBhcnNlVG9Qb3NncmVzQ29tcGFyYXRvcltjbXBdO1xuICAgICAgICAgICAgICBtYXRjaFBhdHRlcm5zLnB1c2goYCQke2luZGV4fTpuYW1lICR7cGdDb21wYXJhdG9yfSAkJHtpbmRleCArIDF9YCk7XG4gICAgICAgICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkLCB0b1Bvc3RncmVzVmFsdWUodmFsdWVbY21wXSkpO1xuICAgICAgICAgICAgICBpbmRleCArPSAyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICAgIGlmIChtYXRjaFBhdHRlcm5zLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIHBhdHRlcm5zLnB1c2goYCgke21hdGNoUGF0dGVybnMuam9pbignIEFORCAnKX0pYCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChzY2hlbWEuZmllbGRzW2ZpZWxkXSAmJiBzY2hlbWEuZmllbGRzW2ZpZWxkXS50eXBlICYmIG1hdGNoUGF0dGVybnMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICBwYXR0ZXJucy5wdXNoKGAkJHtpbmRleH06bmFtZSA9ICQke2luZGV4ICsgMX1gKTtcbiAgICAgICAgICAgIHZhbHVlcy5wdXNoKGZpZWxkLCB2YWx1ZSk7XG4gICAgICAgICAgICBpbmRleCArPSAyO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB3aGVyZVBhdHRlcm4gPSBwYXR0ZXJucy5sZW5ndGggPiAwID8gYFdIRVJFICR7cGF0dGVybnMuam9pbihgICR7b3JPckFuZH0gYCl9YCA6ICcnO1xuICAgICAgfVxuICAgICAgaWYgKHN0YWdlLiRsaW1pdCkge1xuICAgICAgICBsaW1pdFBhdHRlcm4gPSBgTElNSVQgJCR7aW5kZXh9YDtcbiAgICAgICAgdmFsdWVzLnB1c2goc3RhZ2UuJGxpbWl0KTtcbiAgICAgICAgaW5kZXggKz0gMTtcbiAgICAgIH1cbiAgICAgIGlmIChzdGFnZS4kc2tpcCkge1xuICAgICAgICBza2lwUGF0dGVybiA9IGBPRkZTRVQgJCR7aW5kZXh9YDtcbiAgICAgICAgdmFsdWVzLnB1c2goc3RhZ2UuJHNraXApO1xuICAgICAgICBpbmRleCArPSAxO1xuICAgICAgfVxuICAgICAgaWYgKHN0YWdlLiRzb3J0KSB7XG4gICAgICAgIGNvbnN0IHNvcnQgPSBzdGFnZS4kc29ydDtcbiAgICAgICAgY29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKHNvcnQpO1xuICAgICAgICBjb25zdCBzb3J0aW5nID0ga2V5c1xuICAgICAgICAgIC5tYXAoa2V5ID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHRyYW5zZm9ybWVyID0gc29ydFtrZXldID09PSAxID8gJ0FTQycgOiAnREVTQyc7XG4gICAgICAgICAgICBjb25zdCBvcmRlciA9IGAkJHtpbmRleH06bmFtZSAke3RyYW5zZm9ybWVyfWA7XG4gICAgICAgICAgICBpbmRleCArPSAxO1xuICAgICAgICAgICAgcmV0dXJuIG9yZGVyO1xuICAgICAgICAgIH0pXG4gICAgICAgICAgLmpvaW4oKTtcbiAgICAgICAgdmFsdWVzLnB1c2goLi4ua2V5cyk7XG4gICAgICAgIHNvcnRQYXR0ZXJuID0gc29ydCAhPT0gdW5kZWZpbmVkICYmIHNvcnRpbmcubGVuZ3RoID4gMCA/IGBPUkRFUiBCWSAke3NvcnRpbmd9YCA6ICcnO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChncm91cFBhdHRlcm4pIHtcbiAgICAgIGNvbHVtbnMuZm9yRWFjaCgoZSwgaSwgYSkgPT4ge1xuICAgICAgICBpZiAoZSAmJiBlLnRyaW0oKSA9PT0gJyonKSB7XG4gICAgICAgICAgYVtpXSA9ICcnO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBjb25zdCBvcmlnaW5hbFF1ZXJ5ID0gYFNFTEVDVCAke2NvbHVtbnNcbiAgICAgIC5maWx0ZXIoQm9vbGVhbilcbiAgICAgIC5qb2luKCl9IEZST00gJDE6bmFtZSAke3doZXJlUGF0dGVybn0gJHtza2lwUGF0dGVybn0gJHtncm91cFBhdHRlcm59ICR7c29ydFBhdHRlcm59ICR7bGltaXRQYXR0ZXJufWA7XG4gICAgY29uc3QgcXMgPSBleHBsYWluID8gdGhpcy5jcmVhdGVFeHBsYWluYWJsZVF1ZXJ5KG9yaWdpbmFsUXVlcnkpIDogb3JpZ2luYWxRdWVyeTtcbiAgICByZXR1cm4gdGhpcy5fY2xpZW50LmFueShxcywgdmFsdWVzKS50aGVuKGEgPT4ge1xuICAgICAgaWYgKGV4cGxhaW4pIHtcbiAgICAgICAgcmV0dXJuIGE7XG4gICAgICB9XG4gICAgICBjb25zdCByZXN1bHRzID0gYS5tYXAob2JqZWN0ID0+IHRoaXMucG9zdGdyZXNPYmplY3RUb1BhcnNlT2JqZWN0KGNsYXNzTmFtZSwgb2JqZWN0LCBzY2hlbWEpKTtcbiAgICAgIHJlc3VsdHMuZm9yRWFjaChyZXN1bHQgPT4ge1xuICAgICAgICBpZiAoIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChyZXN1bHQsICdvYmplY3RJZCcpKSB7XG4gICAgICAgICAgcmVzdWx0Lm9iamVjdElkID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZ3JvdXBWYWx1ZXMpIHtcbiAgICAgICAgICByZXN1bHQub2JqZWN0SWQgPSB7fTtcbiAgICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiBncm91cFZhbHVlcykge1xuICAgICAgICAgICAgcmVzdWx0Lm9iamVjdElkW2tleV0gPSByZXN1bHRba2V5XTtcbiAgICAgICAgICAgIGRlbGV0ZSByZXN1bHRba2V5XTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNvdW50RmllbGQpIHtcbiAgICAgICAgICByZXN1bHRbY291bnRGaWVsZF0gPSBwYXJzZUludChyZXN1bHRbY291bnRGaWVsZF0sIDEwKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICByZXR1cm4gcmVzdWx0cztcbiAgICB9KTtcbiAgfVxuXG4gIGFzeW5jIHBlcmZvcm1Jbml0aWFsaXphdGlvbih7IFZvbGF0aWxlQ2xhc3Nlc1NjaGVtYXMgfTogYW55KSB7XG4gICAgLy8gVE9ETzogVGhpcyBtZXRob2QgbmVlZHMgdG8gYmUgcmV3cml0dGVuIHRvIG1ha2UgcHJvcGVyIHVzZSBvZiBjb25uZWN0aW9ucyAoQHZpdGFseS10KVxuICAgIGRlYnVnKCdwZXJmb3JtSW5pdGlhbGl6YXRpb24nKTtcbiAgICBhd2FpdCB0aGlzLl9lbnN1cmVTY2hlbWFDb2xsZWN0aW9uRXhpc3RzKCk7XG4gICAgY29uc3QgcHJvbWlzZXMgPSBWb2xhdGlsZUNsYXNzZXNTY2hlbWFzLm1hcChzY2hlbWEgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuY3JlYXRlVGFibGUoc2NoZW1hLmNsYXNzTmFtZSwgc2NoZW1hKVxuICAgICAgICAuY2F0Y2goZXJyID0+IHtcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICBlcnIuY29kZSA9PT0gUG9zdGdyZXNEdXBsaWNhdGVSZWxhdGlvbkVycm9yIHx8XG4gICAgICAgICAgICBlcnIuY29kZSA9PT0gUGFyc2UuRXJyb3IuSU5WQUxJRF9DTEFTU19OQU1FXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgfSlcbiAgICAgICAgLnRoZW4oKCkgPT4gdGhpcy5zY2hlbWFVcGdyYWRlKHNjaGVtYS5jbGFzc05hbWUsIHNjaGVtYSkpO1xuICAgIH0pO1xuICAgIHByb21pc2VzLnB1c2godGhpcy5fbGlzdGVuVG9TY2hlbWEoKSk7XG4gICAgcmV0dXJuIFByb21pc2UuYWxsKHByb21pc2VzKVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5fY2xpZW50LnR4KCdwZXJmb3JtLWluaXRpYWxpemF0aW9uJywgYXN5bmMgdCA9PiB7XG4gICAgICAgICAgYXdhaXQgdC5ub25lKHNxbC5taXNjLmpzb25PYmplY3RTZXRLZXlzKTtcbiAgICAgICAgICBhd2FpdCB0Lm5vbmUoc3FsLmFycmF5LmFkZCk7XG4gICAgICAgICAgYXdhaXQgdC5ub25lKHNxbC5hcnJheS5hZGRVbmlxdWUpO1xuICAgICAgICAgIGF3YWl0IHQubm9uZShzcWwuYXJyYXkucmVtb3ZlKTtcbiAgICAgICAgICBhd2FpdCB0Lm5vbmUoc3FsLmFycmF5LmNvbnRhaW5zQWxsKTtcbiAgICAgICAgICBhd2FpdCB0Lm5vbmUoc3FsLmFycmF5LmNvbnRhaW5zQWxsUmVnZXgpO1xuICAgICAgICAgIGF3YWl0IHQubm9uZShzcWwuYXJyYXkuY29udGFpbnMpO1xuICAgICAgICAgIHJldHVybiB0LmN0eDtcbiAgICAgICAgfSk7XG4gICAgICB9KVxuICAgICAgLnRoZW4oY3R4ID0+IHtcbiAgICAgICAgZGVidWcoYGluaXRpYWxpemF0aW9uRG9uZSBpbiAke2N0eC5kdXJhdGlvbn1gKTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgYXN5bmMgY3JlYXRlSW5kZXhlcyhjbGFzc05hbWU6IHN0cmluZywgaW5kZXhlczogYW55LCBjb25uOiA/YW55KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIChjb25uIHx8IHRoaXMuX2NsaWVudCkudHgodCA9PlxuICAgICAgdC5iYXRjaChcbiAgICAgICAgaW5kZXhlcy5tYXAoaSA9PiB7XG4gICAgICAgICAgcmV0dXJuIHQubm9uZSgnQ1JFQVRFIElOREVYIElGIE5PVCBFWElTVFMgJDE6bmFtZSBPTiAkMjpuYW1lICgkMzpuYW1lKScsIFtcbiAgICAgICAgICAgIGkubmFtZSxcbiAgICAgICAgICAgIGNsYXNzTmFtZSxcbiAgICAgICAgICAgIGkua2V5LFxuICAgICAgICAgIF0pO1xuICAgICAgICB9KVxuICAgICAgKVxuICAgICk7XG4gIH1cblxuICBhc3luYyBjcmVhdGVJbmRleGVzSWZOZWVkZWQoXG4gICAgY2xhc3NOYW1lOiBzdHJpbmcsXG4gICAgZmllbGROYW1lOiBzdHJpbmcsXG4gICAgdHlwZTogYW55LFxuICAgIGNvbm46ID9hbnlcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgKGNvbm4gfHwgdGhpcy5fY2xpZW50KS5ub25lKCdDUkVBVEUgSU5ERVggSUYgTk9UIEVYSVNUUyAkMTpuYW1lIE9OICQyOm5hbWUgKCQzOm5hbWUpJywgW1xuICAgICAgZmllbGROYW1lLFxuICAgICAgY2xhc3NOYW1lLFxuICAgICAgdHlwZSxcbiAgICBdKTtcbiAgfVxuXG4gIGFzeW5jIGRyb3BJbmRleGVzKGNsYXNzTmFtZTogc3RyaW5nLCBpbmRleGVzOiBhbnksIGNvbm46IGFueSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHF1ZXJpZXMgPSBpbmRleGVzLm1hcChpID0+ICh7XG4gICAgICBxdWVyeTogJ0RST1AgSU5ERVggJDE6bmFtZScsXG4gICAgICB2YWx1ZXM6IGksXG4gICAgfSkpO1xuICAgIGF3YWl0IChjb25uIHx8IHRoaXMuX2NsaWVudCkudHgodCA9PiB0Lm5vbmUodGhpcy5fcGdwLmhlbHBlcnMuY29uY2F0KHF1ZXJpZXMpKSk7XG4gIH1cblxuICBhc3luYyBnZXRJbmRleGVzKGNsYXNzTmFtZTogc3RyaW5nKSB7XG4gICAgY29uc3QgcXMgPSAnU0VMRUNUICogRlJPTSBwZ19pbmRleGVzIFdIRVJFIHRhYmxlbmFtZSA9ICR7Y2xhc3NOYW1lfSc7XG4gICAgcmV0dXJuIHRoaXMuX2NsaWVudC5hbnkocXMsIHsgY2xhc3NOYW1lIH0pO1xuICB9XG5cbiAgYXN5bmMgdXBkYXRlU2NoZW1hV2l0aEluZGV4ZXMoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICB9XG5cbiAgLy8gVXNlZCBmb3IgdGVzdGluZyBwdXJwb3Nlc1xuICBhc3luYyB1cGRhdGVFc3RpbWF0ZWRDb3VudChjbGFzc05hbWU6IHN0cmluZykge1xuICAgIHJldHVybiB0aGlzLl9jbGllbnQubm9uZSgnQU5BTFlaRSAkMTpuYW1lJywgW2NsYXNzTmFtZV0pO1xuICB9XG5cbiAgYXN5bmMgY3JlYXRlVHJhbnNhY3Rpb25hbFNlc3Npb24oKTogUHJvbWlzZTxhbnk+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG4gICAgICBjb25zdCB0cmFuc2FjdGlvbmFsU2Vzc2lvbiA9IHt9O1xuICAgICAgdHJhbnNhY3Rpb25hbFNlc3Npb24ucmVzdWx0ID0gdGhpcy5fY2xpZW50LnR4KHQgPT4ge1xuICAgICAgICB0cmFuc2FjdGlvbmFsU2Vzc2lvbi50ID0gdDtcbiAgICAgICAgdHJhbnNhY3Rpb25hbFNlc3Npb24ucHJvbWlzZSA9IG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgICAgIHRyYW5zYWN0aW9uYWxTZXNzaW9uLnJlc29sdmUgPSByZXNvbHZlO1xuICAgICAgICB9KTtcbiAgICAgICAgdHJhbnNhY3Rpb25hbFNlc3Npb24uYmF0Y2ggPSBbXTtcbiAgICAgICAgcmVzb2x2ZSh0cmFuc2FjdGlvbmFsU2Vzc2lvbik7XG4gICAgICAgIHJldHVybiB0cmFuc2FjdGlvbmFsU2Vzc2lvbi5wcm9taXNlO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBjb21taXRUcmFuc2FjdGlvbmFsU2Vzc2lvbih0cmFuc2FjdGlvbmFsU2Vzc2lvbjogYW55KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdHJhbnNhY3Rpb25hbFNlc3Npb24ucmVzb2x2ZSh0cmFuc2FjdGlvbmFsU2Vzc2lvbi50LmJhdGNoKHRyYW5zYWN0aW9uYWxTZXNzaW9uLmJhdGNoKSk7XG4gICAgcmV0dXJuIHRyYW5zYWN0aW9uYWxTZXNzaW9uLnJlc3VsdDtcbiAgfVxuXG4gIGFib3J0VHJhbnNhY3Rpb25hbFNlc3Npb24odHJhbnNhY3Rpb25hbFNlc3Npb246IGFueSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHJlc3VsdCA9IHRyYW5zYWN0aW9uYWxTZXNzaW9uLnJlc3VsdC5jYXRjaCgpO1xuICAgIHRyYW5zYWN0aW9uYWxTZXNzaW9uLmJhdGNoLnB1c2goUHJvbWlzZS5yZWplY3QoKSk7XG4gICAgdHJhbnNhY3Rpb25hbFNlc3Npb24ucmVzb2x2ZSh0cmFuc2FjdGlvbmFsU2Vzc2lvbi50LmJhdGNoKHRyYW5zYWN0aW9uYWxTZXNzaW9uLmJhdGNoKSk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIGFzeW5jIGVuc3VyZUluZGV4KFxuICAgIGNsYXNzTmFtZTogc3RyaW5nLFxuICAgIHNjaGVtYTogU2NoZW1hVHlwZSxcbiAgICBmaWVsZE5hbWVzOiBzdHJpbmdbXSxcbiAgICBpbmRleE5hbWU6ID9zdHJpbmcsXG4gICAgY2FzZUluc2Vuc2l0aXZlOiBib29sZWFuID0gZmFsc2UsXG4gICAgb3B0aW9ucz86IE9iamVjdCA9IHt9XG4gICk6IFByb21pc2U8YW55PiB7XG4gICAgY29uc3QgY29ubiA9IG9wdGlvbnMuY29ubiAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5jb25uIDogdGhpcy5fY2xpZW50O1xuICAgIGNvbnN0IGRlZmF1bHRJbmRleE5hbWUgPSBgcGFyc2VfZGVmYXVsdF8ke2ZpZWxkTmFtZXMuc29ydCgpLmpvaW4oJ18nKX1gO1xuICAgIGNvbnN0IGluZGV4TmFtZU9wdGlvbnM6IE9iamVjdCA9XG4gICAgICBpbmRleE5hbWUgIT0gbnVsbCA/IHsgbmFtZTogaW5kZXhOYW1lIH0gOiB7IG5hbWU6IGRlZmF1bHRJbmRleE5hbWUgfTtcbiAgICBjb25zdCBjb25zdHJhaW50UGF0dGVybnMgPSBjYXNlSW5zZW5zaXRpdmVcbiAgICAgID8gZmllbGROYW1lcy5tYXAoKGZpZWxkTmFtZSwgaW5kZXgpID0+IGBsb3dlcigkJHtpbmRleCArIDN9Om5hbWUpIHZhcmNoYXJfcGF0dGVybl9vcHNgKVxuICAgICAgOiBmaWVsZE5hbWVzLm1hcCgoZmllbGROYW1lLCBpbmRleCkgPT4gYCQke2luZGV4ICsgM306bmFtZWApO1xuICAgIGNvbnN0IHFzID0gYENSRUFURSBJTkRFWCBJRiBOT1QgRVhJU1RTICQxOm5hbWUgT04gJDI6bmFtZSAoJHtjb25zdHJhaW50UGF0dGVybnMuam9pbigpfSlgO1xuICAgIGNvbnN0IHNldElkZW1wb3RlbmN5RnVuY3Rpb24gPVxuICAgICAgb3B0aW9ucy5zZXRJZGVtcG90ZW5jeUZ1bmN0aW9uICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLnNldElkZW1wb3RlbmN5RnVuY3Rpb24gOiBmYWxzZTtcbiAgICBpZiAoc2V0SWRlbXBvdGVuY3lGdW5jdGlvbikge1xuICAgICAgYXdhaXQgdGhpcy5lbnN1cmVJZGVtcG90ZW5jeUZ1bmN0aW9uRXhpc3RzKG9wdGlvbnMpO1xuICAgIH1cbiAgICBhd2FpdCBjb25uLm5vbmUocXMsIFtpbmRleE5hbWVPcHRpb25zLm5hbWUsIGNsYXNzTmFtZSwgLi4uZmllbGROYW1lc10pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgIGlmIChcbiAgICAgICAgZXJyb3IuY29kZSA9PT0gUG9zdGdyZXNEdXBsaWNhdGVSZWxhdGlvbkVycm9yICYmXG4gICAgICAgIGVycm9yLm1lc3NhZ2UuaW5jbHVkZXMoaW5kZXhOYW1lT3B0aW9ucy5uYW1lKVxuICAgICAgKSB7XG4gICAgICAgIC8vIEluZGV4IGFscmVhZHkgZXhpc3RzLiBJZ25vcmUgZXJyb3IuXG4gICAgICB9IGVsc2UgaWYgKFxuICAgICAgICBlcnJvci5jb2RlID09PSBQb3N0Z3Jlc1VuaXF1ZUluZGV4VmlvbGF0aW9uRXJyb3IgJiZcbiAgICAgICAgZXJyb3IubWVzc2FnZS5pbmNsdWRlcyhpbmRleE5hbWVPcHRpb25zLm5hbWUpXG4gICAgICApIHtcbiAgICAgICAgLy8gQ2FzdCB0aGUgZXJyb3IgaW50byB0aGUgcHJvcGVyIHBhcnNlIGVycm9yXG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5EVVBMSUNBVEVfVkFMVUUsXG4gICAgICAgICAgJ0EgZHVwbGljYXRlIHZhbHVlIGZvciBhIGZpZWxkIHdpdGggdW5pcXVlIHZhbHVlcyB3YXMgcHJvdmlkZWQnXG4gICAgICAgICk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIGFzeW5jIGRlbGV0ZUlkZW1wb3RlbmN5RnVuY3Rpb24ob3B0aW9ucz86IE9iamVjdCA9IHt9KTogUHJvbWlzZTxhbnk+IHtcbiAgICBjb25zdCBjb25uID0gb3B0aW9ucy5jb25uICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLmNvbm4gOiB0aGlzLl9jbGllbnQ7XG4gICAgY29uc3QgcXMgPSAnRFJPUCBGVU5DVElPTiBJRiBFWElTVFMgaWRlbXBvdGVuY3lfZGVsZXRlX2V4cGlyZWRfcmVjb3JkcygpJztcbiAgICByZXR1cm4gY29ubi5ub25lKHFzKS5jYXRjaChlcnJvciA9PiB7XG4gICAgICB0aHJvdyBlcnJvcjtcbiAgICB9KTtcbiAgfVxuXG4gIGFzeW5jIGVuc3VyZUlkZW1wb3RlbmN5RnVuY3Rpb25FeGlzdHMob3B0aW9ucz86IE9iamVjdCA9IHt9KTogUHJvbWlzZTxhbnk+IHtcbiAgICBjb25zdCBjb25uID0gb3B0aW9ucy5jb25uICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLmNvbm4gOiB0aGlzLl9jbGllbnQ7XG4gICAgY29uc3QgdHRsT3B0aW9ucyA9IG9wdGlvbnMudHRsICE9PSB1bmRlZmluZWQgPyBgJHtvcHRpb25zLnR0bH0gc2Vjb25kc2AgOiAnNjAgc2Vjb25kcyc7XG4gICAgY29uc3QgcXMgPVxuICAgICAgJ0NSRUFURSBPUiBSRVBMQUNFIEZVTkNUSU9OIGlkZW1wb3RlbmN5X2RlbGV0ZV9leHBpcmVkX3JlY29yZHMoKSBSRVRVUk5TIHZvaWQgTEFOR1VBR0UgcGxwZ3NxbCBBUyAkJCBCRUdJTiBERUxFVEUgRlJPTSBcIl9JZGVtcG90ZW5jeVwiIFdIRVJFIGV4cGlyZSA8IE5PVygpIC0gSU5URVJWQUwgJDE7IEVORDsgJCQ7JztcbiAgICByZXR1cm4gY29ubi5ub25lKHFzLCBbdHRsT3B0aW9uc10pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgIHRocm93IGVycm9yO1xuICAgIH0pO1xuICB9XG59XG5cbmZ1bmN0aW9uIGNvbnZlcnRQb2x5Z29uVG9TUUwocG9seWdvbikge1xuICBpZiAocG9seWdvbi5sZW5ndGggPCAzKSB7XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfSlNPTiwgYFBvbHlnb24gbXVzdCBoYXZlIGF0IGxlYXN0IDMgdmFsdWVzYCk7XG4gIH1cbiAgaWYgKFxuICAgIHBvbHlnb25bMF1bMF0gIT09IHBvbHlnb25bcG9seWdvbi5sZW5ndGggLSAxXVswXSB8fFxuICAgIHBvbHlnb25bMF1bMV0gIT09IHBvbHlnb25bcG9seWdvbi5sZW5ndGggLSAxXVsxXVxuICApIHtcbiAgICBwb2x5Z29uLnB1c2gocG9seWdvblswXSk7XG4gIH1cbiAgY29uc3QgdW5pcXVlID0gcG9seWdvbi5maWx0ZXIoKGl0ZW0sIGluZGV4LCBhcikgPT4ge1xuICAgIGxldCBmb3VuZEluZGV4ID0gLTE7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhci5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgY29uc3QgcHQgPSBhcltpXTtcbiAgICAgIGlmIChwdFswXSA9PT0gaXRlbVswXSAmJiBwdFsxXSA9PT0gaXRlbVsxXSkge1xuICAgICAgICBmb3VuZEluZGV4ID0gaTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmb3VuZEluZGV4ID09PSBpbmRleDtcbiAgfSk7XG4gIGlmICh1bmlxdWUubGVuZ3RoIDwgMykge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgIFBhcnNlLkVycm9yLklOVEVSTkFMX1NFUlZFUl9FUlJPUixcbiAgICAgICdHZW9KU09OOiBMb29wIG11c3QgaGF2ZSBhdCBsZWFzdCAzIGRpZmZlcmVudCB2ZXJ0aWNlcydcbiAgICApO1xuICB9XG4gIGNvbnN0IHBvaW50cyA9IHBvbHlnb25cbiAgICAubWFwKHBvaW50ID0+IHtcbiAgICAgIFBhcnNlLkdlb1BvaW50Ll92YWxpZGF0ZShwYXJzZUZsb2F0KHBvaW50WzFdKSwgcGFyc2VGbG9hdChwb2ludFswXSkpO1xuICAgICAgcmV0dXJuIGAoJHtwb2ludFsxXX0sICR7cG9pbnRbMF19KWA7XG4gICAgfSlcbiAgICAuam9pbignLCAnKTtcbiAgcmV0dXJuIGAoJHtwb2ludHN9KWA7XG59XG5cbmZ1bmN0aW9uIHJlbW92ZVdoaXRlU3BhY2UocmVnZXgpIHtcbiAgaWYgKCFyZWdleC5lbmRzV2l0aCgnXFxuJykpIHtcbiAgICByZWdleCArPSAnXFxuJztcbiAgfVxuXG4gIC8vIHJlbW92ZSBub24gZXNjYXBlZCBjb21tZW50c1xuICByZXR1cm4gKFxuICAgIHJlZ2V4XG4gICAgICAucmVwbGFjZSgvKFteXFxcXF0pIy4qXFxuL2dpbSwgJyQxJylcbiAgICAgIC8vIHJlbW92ZSBsaW5lcyBzdGFydGluZyB3aXRoIGEgY29tbWVudFxuICAgICAgLnJlcGxhY2UoL14jLipcXG4vZ2ltLCAnJylcbiAgICAgIC8vIHJlbW92ZSBub24gZXNjYXBlZCB3aGl0ZXNwYWNlXG4gICAgICAucmVwbGFjZSgvKFteXFxcXF0pXFxzKy9naW0sICckMScpXG4gICAgICAvLyByZW1vdmUgd2hpdGVzcGFjZSBhdCB0aGUgYmVnaW5uaW5nIG9mIGEgbGluZVxuICAgICAgLnJlcGxhY2UoL15cXHMrLywgJycpXG4gICAgICAudHJpbSgpXG4gICk7XG59XG5cbmZ1bmN0aW9uIHByb2Nlc3NSZWdleFBhdHRlcm4ocykge1xuICBpZiAocyAmJiBzLnN0YXJ0c1dpdGgoJ14nKSkge1xuICAgIC8vIHJlZ2V4IGZvciBzdGFydHNXaXRoXG4gICAgcmV0dXJuICdeJyArIGxpdGVyYWxpemVSZWdleFBhcnQocy5zbGljZSgxKSk7XG4gIH0gZWxzZSBpZiAocyAmJiBzLmVuZHNXaXRoKCckJykpIHtcbiAgICAvLyByZWdleCBmb3IgZW5kc1dpdGhcbiAgICByZXR1cm4gbGl0ZXJhbGl6ZVJlZ2V4UGFydChzLnNsaWNlKDAsIHMubGVuZ3RoIC0gMSkpICsgJyQnO1xuICB9XG5cbiAgLy8gcmVnZXggZm9yIGNvbnRhaW5zXG4gIHJldHVybiBsaXRlcmFsaXplUmVnZXhQYXJ0KHMpO1xufVxuXG5mdW5jdGlvbiBpc1N0YXJ0c1dpdGhSZWdleCh2YWx1ZSkge1xuICBpZiAoIXZhbHVlIHx8IHR5cGVvZiB2YWx1ZSAhPT0gJ3N0cmluZycgfHwgIXZhbHVlLnN0YXJ0c1dpdGgoJ14nKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGNvbnN0IG1hdGNoZXMgPSB2YWx1ZS5tYXRjaCgvXFxeXFxcXFEuKlxcXFxFLyk7XG4gIHJldHVybiAhIW1hdGNoZXM7XG59XG5cbmZ1bmN0aW9uIGlzQWxsVmFsdWVzUmVnZXhPck5vbmUodmFsdWVzKSB7XG4gIGlmICghdmFsdWVzIHx8ICFBcnJheS5pc0FycmF5KHZhbHVlcykgfHwgdmFsdWVzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgY29uc3QgZmlyc3RWYWx1ZXNJc1JlZ2V4ID0gaXNTdGFydHNXaXRoUmVnZXgodmFsdWVzWzBdLiRyZWdleCk7XG4gIGlmICh2YWx1ZXMubGVuZ3RoID09PSAxKSB7XG4gICAgcmV0dXJuIGZpcnN0VmFsdWVzSXNSZWdleDtcbiAgfVxuXG4gIGZvciAobGV0IGkgPSAxLCBsZW5ndGggPSB2YWx1ZXMubGVuZ3RoOyBpIDwgbGVuZ3RoOyArK2kpIHtcbiAgICBpZiAoZmlyc3RWYWx1ZXNJc1JlZ2V4ICE9PSBpc1N0YXJ0c1dpdGhSZWdleCh2YWx1ZXNbaV0uJHJlZ2V4KSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBpc0FueVZhbHVlUmVnZXhTdGFydHNXaXRoKHZhbHVlcykge1xuICByZXR1cm4gdmFsdWVzLnNvbWUoZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIGlzU3RhcnRzV2l0aFJlZ2V4KHZhbHVlLiRyZWdleCk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBjcmVhdGVMaXRlcmFsUmVnZXgocmVtYWluaW5nOiBzdHJpbmcpIHtcbiAgcmV0dXJuIHJlbWFpbmluZ1xuICAgIC5zcGxpdCgnJylcbiAgICAubWFwKGMgPT4ge1xuICAgICAgY29uc3QgcmVnZXggPSBSZWdFeHAoJ1swLTkgXXxcXFxccHtMfScsICd1Jyk7IC8vIFN1cHBvcnQgYWxsIFVuaWNvZGUgbGV0dGVyIGNoYXJzXG4gICAgICBpZiAoYy5tYXRjaChyZWdleCkgIT09IG51bGwpIHtcbiAgICAgICAgLy8gRG9uJ3QgZXNjYXBlIGFscGhhbnVtZXJpYyBjaGFyYWN0ZXJzXG4gICAgICAgIHJldHVybiBjO1xuICAgICAgfVxuICAgICAgLy8gRXNjYXBlIGV2ZXJ5dGhpbmcgZWxzZSAoc2luZ2xlIHF1b3RlcyB3aXRoIHNpbmdsZSBxdW90ZXMsIGV2ZXJ5dGhpbmcgZWxzZSB3aXRoIGEgYmFja3NsYXNoKVxuICAgICAgcmV0dXJuIGMgPT09IGAnYCA/IGAnJ2AgOiBgXFxcXCR7Y31gO1xuICAgIH0pXG4gICAgLmpvaW4oJycpO1xufVxuXG5mdW5jdGlvbiBsaXRlcmFsaXplUmVnZXhQYXJ0KHM6IHN0cmluZykge1xuICBjb25zdCBtYXRjaGVyMSA9IC9cXFxcUSgoPyFcXFxcRSkuKilcXFxcRSQvO1xuICBjb25zdCByZXN1bHQxOiBhbnkgPSBzLm1hdGNoKG1hdGNoZXIxKTtcbiAgaWYgKHJlc3VsdDEgJiYgcmVzdWx0MS5sZW5ndGggPiAxICYmIHJlc3VsdDEuaW5kZXggPiAtMSkge1xuICAgIC8vIFByb2Nlc3MgUmVnZXggdGhhdCBoYXMgYSBiZWdpbm5pbmcgYW5kIGFuIGVuZCBzcGVjaWZpZWQgZm9yIHRoZSBsaXRlcmFsIHRleHRcbiAgICBjb25zdCBwcmVmaXggPSBzLnN1YnN0cmluZygwLCByZXN1bHQxLmluZGV4KTtcbiAgICBjb25zdCByZW1haW5pbmcgPSByZXN1bHQxWzFdO1xuXG4gICAgcmV0dXJuIGxpdGVyYWxpemVSZWdleFBhcnQocHJlZml4KSArIGNyZWF0ZUxpdGVyYWxSZWdleChyZW1haW5pbmcpO1xuICB9XG5cbiAgLy8gUHJvY2VzcyBSZWdleCB0aGF0IGhhcyBhIGJlZ2lubmluZyBzcGVjaWZpZWQgZm9yIHRoZSBsaXRlcmFsIHRleHRcbiAgY29uc3QgbWF0Y2hlcjIgPSAvXFxcXFEoKD8hXFxcXEUpLiopJC87XG4gIGNvbnN0IHJlc3VsdDI6IGFueSA9IHMubWF0Y2gobWF0Y2hlcjIpO1xuICBpZiAocmVzdWx0MiAmJiByZXN1bHQyLmxlbmd0aCA+IDEgJiYgcmVzdWx0Mi5pbmRleCA+IC0xKSB7XG4gICAgY29uc3QgcHJlZml4ID0gcy5zdWJzdHJpbmcoMCwgcmVzdWx0Mi5pbmRleCk7XG4gICAgY29uc3QgcmVtYWluaW5nID0gcmVzdWx0MlsxXTtcblxuICAgIHJldHVybiBsaXRlcmFsaXplUmVnZXhQYXJ0KHByZWZpeCkgKyBjcmVhdGVMaXRlcmFsUmVnZXgocmVtYWluaW5nKTtcbiAgfVxuXG4gIC8vIFJlbW92ZSBwcm9ibGVtYXRpYyBjaGFycyBmcm9tIHJlbWFpbmluZyB0ZXh0XG4gIHJldHVybiBzXG4gICAgLy8gUmVtb3ZlIGFsbCBpbnN0YW5jZXMgb2YgXFxRIGFuZCBcXEVcbiAgICAucmVwbGFjZSgvKFteXFxcXF0pKFxcXFxFKS8sICckMScpXG4gICAgLnJlcGxhY2UoLyhbXlxcXFxdKShcXFxcUSkvLCAnJDEnKVxuICAgIC5yZXBsYWNlKC9eXFxcXEUvLCAnJylcbiAgICAucmVwbGFjZSgvXlxcXFxRLywgJycpXG4gICAgLy8gRW5zdXJlIGV2ZW4gbnVtYmVyIG9mIHNpbmdsZSBxdW90ZSBzZXF1ZW5jZXMgYnkgYWRkaW5nIGFuIGV4dHJhIHNpbmdsZSBxdW90ZSBpZiBuZWVkZWQ7XG4gICAgLy8gdGhpcyBlbnN1cmVzIHRoYXQgZXZlcnkgc2luZ2xlIHF1b3RlIGlzIGVzY2FwZWRcbiAgICAucmVwbGFjZSgvJysvZywgbWF0Y2ggPT4ge1xuICAgICAgcmV0dXJuIG1hdGNoLmxlbmd0aCAlIDIgPT09IDAgPyBtYXRjaCA6IG1hdGNoICsgXCInXCI7XG4gICAgfSk7XG59XG5cbnZhciBHZW9Qb2ludENvZGVyID0ge1xuICBpc1ZhbGlkSlNPTih2YWx1ZSkge1xuICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnICYmIHZhbHVlICE9PSBudWxsICYmIHZhbHVlLl9fdHlwZSA9PT0gJ0dlb1BvaW50JztcbiAgfSxcbn07XG5cbmV4cG9ydCBkZWZhdWx0IFBvc3RncmVzU3RvcmFnZUFkYXB0ZXI7XG4iXSwibWFwcGluZ3MiOiI7Ozs7OztBQUNBLElBQUFBLGVBQUEsR0FBQUMsT0FBQTtBQUVBLElBQUFDLEtBQUEsR0FBQUMsc0JBQUEsQ0FBQUYsT0FBQTtBQUVBLElBQUFHLE9BQUEsR0FBQUQsc0JBQUEsQ0FBQUYsT0FBQTtBQUVBLElBQUFJLE9BQUEsR0FBQUosT0FBQTtBQUNBLElBQUFLLElBQUEsR0FBQUgsc0JBQUEsQ0FBQUYsT0FBQTtBQUNBLElBQUFNLGVBQUEsR0FBQU4sT0FBQTtBQUFtRCxTQUFBRSx1QkFBQUssQ0FBQSxXQUFBQSxDQUFBLElBQUFBLENBQUEsQ0FB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