parse-server 2.8.4 → 8.6.2

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 (240) hide show
  1. package/LICENSE +167 -25
  2. package/NOTICE +10 -0
  3. package/README.md +929 -278
  4. package/lib/AccountLockout.js +47 -30
  5. package/lib/Adapters/AdapterLoader.js +21 -6
  6. package/lib/Adapters/Analytics/AnalyticsAdapter.js +15 -12
  7. package/lib/Adapters/Auth/AuthAdapter.js +116 -13
  8. package/lib/Adapters/Auth/BaseCodeAuthAdapter.js +99 -0
  9. package/lib/Adapters/Auth/OAuth1Client.js +27 -46
  10. package/lib/Adapters/Auth/apple.js +123 -0
  11. package/lib/Adapters/Auth/facebook.js +162 -35
  12. package/lib/Adapters/Auth/gcenter.js +217 -0
  13. package/lib/Adapters/Auth/github.js +118 -48
  14. package/lib/Adapters/Auth/google.js +160 -51
  15. package/lib/Adapters/Auth/gpgames.js +125 -0
  16. package/lib/Adapters/Auth/httpsRequest.js +6 -7
  17. package/lib/Adapters/Auth/index.js +170 -62
  18. package/lib/Adapters/Auth/instagram.js +114 -40
  19. package/lib/Adapters/Auth/janraincapture.js +52 -23
  20. package/lib/Adapters/Auth/janrainengage.js +19 -36
  21. package/lib/Adapters/Auth/keycloak.js +148 -0
  22. package/lib/Adapters/Auth/ldap.js +167 -0
  23. package/lib/Adapters/Auth/line.js +125 -0
  24. package/lib/Adapters/Auth/linkedin.js +111 -55
  25. package/lib/Adapters/Auth/meetup.js +24 -34
  26. package/lib/Adapters/Auth/mfa.js +324 -0
  27. package/lib/Adapters/Auth/microsoft.js +111 -0
  28. package/lib/Adapters/Auth/oauth2.js +97 -162
  29. package/lib/Adapters/Auth/phantauth.js +53 -0
  30. package/lib/Adapters/Auth/qq.js +108 -49
  31. package/lib/Adapters/Auth/spotify.js +107 -55
  32. package/lib/Adapters/Auth/twitter.js +188 -48
  33. package/lib/Adapters/Auth/utils.js +28 -0
  34. package/lib/Adapters/Auth/vkontakte.js +26 -39
  35. package/lib/Adapters/Auth/wechat.js +106 -44
  36. package/lib/Adapters/Auth/weibo.js +132 -58
  37. package/lib/Adapters/Cache/CacheAdapter.js +13 -8
  38. package/lib/Adapters/Cache/InMemoryCache.js +3 -13
  39. package/lib/Adapters/Cache/InMemoryCacheAdapter.js +5 -13
  40. package/lib/Adapters/Cache/LRUCache.js +13 -27
  41. package/lib/Adapters/Cache/NullCacheAdapter.js +3 -8
  42. package/lib/Adapters/Cache/RedisCacheAdapter.js +85 -76
  43. package/lib/Adapters/Cache/SchemaCache.js +25 -0
  44. package/lib/Adapters/Email/MailAdapter.js +10 -8
  45. package/lib/Adapters/Files/FilesAdapter.js +83 -25
  46. package/lib/Adapters/Files/GridFSBucketAdapter.js +231 -0
  47. package/lib/Adapters/Files/GridStoreAdapter.js +4 -91
  48. package/lib/Adapters/Logger/LoggerAdapter.js +18 -14
  49. package/lib/Adapters/Logger/WinstonLogger.js +69 -88
  50. package/lib/Adapters/Logger/WinstonLoggerAdapter.js +7 -16
  51. package/lib/Adapters/MessageQueue/EventEmitterMQ.js +8 -26
  52. package/lib/Adapters/PubSub/EventEmitterPubSub.js +12 -25
  53. package/lib/Adapters/PubSub/PubSubAdapter.js +34 -0
  54. package/lib/Adapters/PubSub/RedisPubSub.js +42 -19
  55. package/lib/Adapters/Push/PushAdapter.js +14 -7
  56. package/lib/Adapters/Storage/Mongo/MongoCollection.js +137 -45
  57. package/lib/Adapters/Storage/Mongo/MongoSchemaCollection.js +158 -63
  58. package/lib/Adapters/Storage/Mongo/MongoStorageAdapter.js +320 -168
  59. package/lib/Adapters/Storage/Mongo/MongoTransform.js +279 -306
  60. package/lib/Adapters/Storage/Postgres/PostgresClient.js +14 -10
  61. package/lib/Adapters/Storage/Postgres/PostgresConfigParser.js +47 -21
  62. package/lib/Adapters/Storage/Postgres/PostgresStorageAdapter.js +854 -468
  63. package/lib/Adapters/Storage/Postgres/sql/index.js +4 -6
  64. package/lib/Adapters/Storage/StorageAdapter.js +1 -1
  65. package/lib/Adapters/WebSocketServer/WSAdapter.js +35 -0
  66. package/lib/Adapters/WebSocketServer/WSSAdapter.js +66 -0
  67. package/lib/Auth.js +488 -125
  68. package/lib/ClientSDK.js +2 -6
  69. package/lib/Config.js +525 -94
  70. package/lib/Controllers/AdaptableController.js +5 -25
  71. package/lib/Controllers/AnalyticsController.js +22 -23
  72. package/lib/Controllers/CacheController.js +10 -31
  73. package/lib/Controllers/DatabaseController.js +767 -313
  74. package/lib/Controllers/FilesController.js +49 -54
  75. package/lib/Controllers/HooksController.js +80 -84
  76. package/lib/Controllers/LiveQueryController.js +35 -22
  77. package/lib/Controllers/LoggerController.js +22 -58
  78. package/lib/Controllers/ParseGraphQLController.js +293 -0
  79. package/lib/Controllers/PushController.js +58 -49
  80. package/lib/Controllers/SchemaController.js +916 -422
  81. package/lib/Controllers/UserController.js +265 -180
  82. package/lib/Controllers/index.js +90 -125
  83. package/lib/Controllers/types.js +1 -1
  84. package/lib/Deprecator/Deprecations.js +30 -0
  85. package/lib/Deprecator/Deprecator.js +127 -0
  86. package/lib/Error.js +48 -0
  87. package/lib/GraphQL/ParseGraphQLSchema.js +375 -0
  88. package/lib/GraphQL/ParseGraphQLServer.js +214 -0
  89. package/lib/GraphQL/helpers/objectsMutations.js +30 -0
  90. package/lib/GraphQL/helpers/objectsQueries.js +246 -0
  91. package/lib/GraphQL/loaders/configMutations.js +87 -0
  92. package/lib/GraphQL/loaders/configQueries.js +79 -0
  93. package/lib/GraphQL/loaders/defaultGraphQLMutations.js +21 -0
  94. package/lib/GraphQL/loaders/defaultGraphQLQueries.js +23 -0
  95. package/lib/GraphQL/loaders/defaultGraphQLTypes.js +1098 -0
  96. package/lib/GraphQL/loaders/defaultRelaySchema.js +53 -0
  97. package/lib/GraphQL/loaders/filesMutations.js +107 -0
  98. package/lib/GraphQL/loaders/functionsMutations.js +78 -0
  99. package/lib/GraphQL/loaders/parseClassMutations.js +268 -0
  100. package/lib/GraphQL/loaders/parseClassQueries.js +127 -0
  101. package/lib/GraphQL/loaders/parseClassTypes.js +493 -0
  102. package/lib/GraphQL/loaders/schemaDirectives.js +62 -0
  103. package/lib/GraphQL/loaders/schemaMutations.js +162 -0
  104. package/lib/GraphQL/loaders/schemaQueries.js +81 -0
  105. package/lib/GraphQL/loaders/schemaTypes.js +341 -0
  106. package/lib/GraphQL/loaders/usersMutations.js +433 -0
  107. package/lib/GraphQL/loaders/usersQueries.js +90 -0
  108. package/lib/GraphQL/parseGraphQLUtils.js +63 -0
  109. package/lib/GraphQL/transformers/className.js +14 -0
  110. package/lib/GraphQL/transformers/constraintType.js +53 -0
  111. package/lib/GraphQL/transformers/inputType.js +51 -0
  112. package/lib/GraphQL/transformers/mutation.js +274 -0
  113. package/lib/GraphQL/transformers/outputType.js +51 -0
  114. package/lib/GraphQL/transformers/query.js +237 -0
  115. package/lib/GraphQL/transformers/schemaFields.js +99 -0
  116. package/lib/KeyPromiseQueue.js +48 -0
  117. package/lib/LiveQuery/Client.js +25 -33
  118. package/lib/LiveQuery/Id.js +2 -5
  119. package/lib/LiveQuery/ParseCloudCodePublisher.js +26 -23
  120. package/lib/LiveQuery/ParseLiveQueryServer.js +560 -285
  121. package/lib/LiveQuery/ParsePubSub.js +7 -16
  122. package/lib/LiveQuery/ParseWebSocketServer.js +42 -39
  123. package/lib/LiveQuery/QueryTools.js +76 -15
  124. package/lib/LiveQuery/RequestSchema.js +111 -97
  125. package/lib/LiveQuery/SessionTokenCache.js +23 -36
  126. package/lib/LiveQuery/Subscription.js +8 -17
  127. package/lib/LiveQuery/equalObjects.js +2 -3
  128. package/lib/Options/Definitions.js +1355 -382
  129. package/lib/Options/docs.js +301 -62
  130. package/lib/Options/index.js +11 -1
  131. package/lib/Options/parsers.js +14 -10
  132. package/lib/Page.js +44 -0
  133. package/lib/ParseMessageQueue.js +6 -13
  134. package/lib/ParseServer.js +474 -235
  135. package/lib/ParseServerRESTController.js +102 -40
  136. package/lib/PromiseRouter.js +39 -50
  137. package/lib/Push/PushQueue.js +24 -30
  138. package/lib/Push/PushWorker.js +32 -56
  139. package/lib/Push/utils.js +22 -35
  140. package/lib/RestQuery.js +361 -139
  141. package/lib/RestWrite.js +713 -344
  142. package/lib/Routers/AggregateRouter.js +97 -71
  143. package/lib/Routers/AnalyticsRouter.js +8 -14
  144. package/lib/Routers/AudiencesRouter.js +16 -35
  145. package/lib/Routers/ClassesRouter.js +86 -72
  146. package/lib/Routers/CloudCodeRouter.js +28 -37
  147. package/lib/Routers/FeaturesRouter.js +22 -25
  148. package/lib/Routers/FilesRouter.js +266 -171
  149. package/lib/Routers/FunctionsRouter.js +87 -103
  150. package/lib/Routers/GlobalConfigRouter.js +94 -33
  151. package/lib/Routers/GraphQLRouter.js +41 -0
  152. package/lib/Routers/HooksRouter.js +43 -47
  153. package/lib/Routers/IAPValidationRouter.js +57 -70
  154. package/lib/Routers/InstallationsRouter.js +17 -25
  155. package/lib/Routers/LogsRouter.js +10 -25
  156. package/lib/Routers/PagesRouter.js +647 -0
  157. package/lib/Routers/PublicAPIRouter.js +104 -112
  158. package/lib/Routers/PurgeRouter.js +19 -29
  159. package/lib/Routers/PushRouter.js +14 -28
  160. package/lib/Routers/RolesRouter.js +7 -14
  161. package/lib/Routers/SchemasRouter.js +63 -42
  162. package/lib/Routers/SecurityRouter.js +34 -0
  163. package/lib/Routers/SessionsRouter.js +25 -38
  164. package/lib/Routers/UsersRouter.js +463 -190
  165. package/lib/SchemaMigrations/DefinedSchemas.js +379 -0
  166. package/lib/SchemaMigrations/Migrations.js +30 -0
  167. package/lib/Security/Check.js +109 -0
  168. package/lib/Security/CheckGroup.js +44 -0
  169. package/lib/Security/CheckGroups/CheckGroupDatabase.js +44 -0
  170. package/lib/Security/CheckGroups/CheckGroupServerConfig.js +96 -0
  171. package/lib/Security/CheckGroups/CheckGroups.js +21 -0
  172. package/lib/Security/CheckRunner.js +213 -0
  173. package/lib/SharedRest.js +29 -0
  174. package/lib/StatusHandler.js +96 -93
  175. package/lib/TestUtils.js +70 -14
  176. package/lib/Utils.js +468 -0
  177. package/lib/batch.js +74 -40
  178. package/lib/cache.js +8 -8
  179. package/lib/cli/definitions/parse-live-query-server.js +4 -3
  180. package/lib/cli/definitions/parse-server.js +4 -3
  181. package/lib/cli/parse-live-query-server.js +9 -17
  182. package/lib/cli/parse-server.js +49 -47
  183. package/lib/cli/utils/commander.js +20 -29
  184. package/lib/cli/utils/runner.js +31 -32
  185. package/lib/cloud-code/Parse.Cloud.js +711 -36
  186. package/lib/cloud-code/Parse.Server.js +21 -0
  187. package/lib/cryptoUtils.js +6 -11
  188. package/lib/defaults.js +21 -15
  189. package/lib/deprecated.js +1 -1
  190. package/lib/index.js +78 -67
  191. package/lib/logger.js +12 -20
  192. package/lib/middlewares.js +484 -160
  193. package/lib/password.js +10 -6
  194. package/lib/request.js +175 -0
  195. package/lib/requiredParameter.js +4 -3
  196. package/lib/rest.js +157 -82
  197. package/lib/triggers.js +627 -185
  198. package/lib/vendor/README.md +3 -3
  199. package/lib/vendor/mongodbUrl.js +224 -137
  200. package/package.json +135 -57
  201. package/postinstall.js +38 -50
  202. package/public_html/invalid_verification_link.html +3 -3
  203. package/types/@types/@parse/fs-files-adapter/index.d.ts +5 -0
  204. package/types/@types/deepcopy/index.d.ts +5 -0
  205. package/types/LiveQuery/ParseLiveQueryServer.d.ts +40 -0
  206. package/types/Options/index.d.ts +301 -0
  207. package/types/ParseServer.d.ts +65 -0
  208. package/types/eslint.config.mjs +30 -0
  209. package/types/index.d.ts +21 -0
  210. package/types/logger.d.ts +2 -0
  211. package/types/tests.ts +44 -0
  212. package/types/tsconfig.json +24 -0
  213. package/CHANGELOG.md +0 -1246
  214. package/PATENTS +0 -37
  215. package/bin/dev +0 -37
  216. package/lib/.DS_Store +0 -0
  217. package/lib/Adapters/Auth/common.js +0 -2
  218. package/lib/Adapters/Auth/facebookaccountkit.js +0 -69
  219. package/lib/Controllers/SchemaCache.js +0 -97
  220. package/lib/LiveQuery/.DS_Store +0 -0
  221. package/lib/cli/utils/parsers.js +0 -77
  222. package/lib/cloud-code/.DS_Store +0 -0
  223. package/lib/cloud-code/HTTPResponse.js +0 -57
  224. package/lib/cloud-code/Untitled-1 +0 -123
  225. package/lib/cloud-code/httpRequest.js +0 -102
  226. package/lib/cloud-code/team.html +0 -123
  227. package/lib/graphql/ParseClass.js +0 -234
  228. package/lib/graphql/Schema.js +0 -197
  229. package/lib/graphql/index.js +0 -1
  230. package/lib/graphql/types/ACL.js +0 -35
  231. package/lib/graphql/types/Date.js +0 -25
  232. package/lib/graphql/types/File.js +0 -24
  233. package/lib/graphql/types/GeoPoint.js +0 -35
  234. package/lib/graphql/types/JSONObject.js +0 -30
  235. package/lib/graphql/types/NumberInput.js +0 -43
  236. package/lib/graphql/types/NumberQuery.js +0 -42
  237. package/lib/graphql/types/Pointer.js +0 -35
  238. package/lib/graphql/types/QueryConstraint.js +0 -61
  239. package/lib/graphql/types/StringQuery.js +0 -39
  240. package/lib/graphql/types/index.js +0 -110
@@ -1,168 +1,218 @@
1
- 'use strict';
1
+ "use strict";
2
2
 
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
-
7
- var _Options = require('./Options');
8
-
9
- var _defaults = require('./defaults');
10
-
11
- var _defaults2 = _interopRequireDefault(_defaults);
12
-
13
- var _logger = require('./logger');
14
-
15
- var logging = _interopRequireWildcard(_logger);
16
-
17
- var _Config = require('./Config');
18
-
19
- var _Config2 = _interopRequireDefault(_Config);
20
-
21
- var _PromiseRouter = require('./PromiseRouter');
22
-
23
- var _PromiseRouter2 = _interopRequireDefault(_PromiseRouter);
24
-
25
- var _requiredParameter = require('./requiredParameter');
26
-
27
- var _requiredParameter2 = _interopRequireDefault(_requiredParameter);
28
-
29
- var _AnalyticsRouter = require('./Routers/AnalyticsRouter');
30
-
31
- var _ClassesRouter = require('./Routers/ClassesRouter');
32
-
33
- var _FeaturesRouter = require('./Routers/FeaturesRouter');
34
-
35
- var _FilesRouter = require('./Routers/FilesRouter');
36
-
37
- var _FunctionsRouter = require('./Routers/FunctionsRouter');
38
-
39
- var _GlobalConfigRouter = require('./Routers/GlobalConfigRouter');
40
-
41
- var _HooksRouter = require('./Routers/HooksRouter');
42
-
43
- var _IAPValidationRouter = require('./Routers/IAPValidationRouter');
44
-
45
- var _InstallationsRouter = require('./Routers/InstallationsRouter');
46
-
47
- var _LogsRouter = require('./Routers/LogsRouter');
48
-
49
- var _ParseLiveQueryServer = require('./LiveQuery/ParseLiveQueryServer');
50
-
51
- var _PublicAPIRouter = require('./Routers/PublicAPIRouter');
52
-
53
- var _PushRouter = require('./Routers/PushRouter');
54
-
55
- var _CloudCodeRouter = require('./Routers/CloudCodeRouter');
56
-
57
- var _RolesRouter = require('./Routers/RolesRouter');
58
-
59
- var _SchemasRouter = require('./Routers/SchemasRouter');
60
-
61
- var _SessionsRouter = require('./Routers/SessionsRouter');
62
-
63
- var _UsersRouter = require('./Routers/UsersRouter');
64
-
65
- var _PurgeRouter = require('./Routers/PurgeRouter');
66
-
67
- var _AudiencesRouter = require('./Routers/AudiencesRouter');
68
-
69
- var _AggregateRouter = require('./Routers/AggregateRouter');
70
-
71
- var _ParseServerRESTController = require('./ParseServerRESTController');
72
-
73
- var _Controllers = require('./Controllers');
74
-
75
- var controllers = _interopRequireWildcard(_Controllers);
76
-
77
- function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
78
-
79
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
80
-
6
+ exports.default = void 0;
7
+ var _defaults = _interopRequireDefault(require("./defaults"));
8
+ var logging = _interopRequireWildcard(require("./logger"));
9
+ var _Config = _interopRequireDefault(require("./Config"));
10
+ var _PromiseRouter = _interopRequireDefault(require("./PromiseRouter"));
11
+ var _requiredParameter = _interopRequireDefault(require("./requiredParameter"));
12
+ var _AnalyticsRouter = require("./Routers/AnalyticsRouter");
13
+ var _ClassesRouter = require("./Routers/ClassesRouter");
14
+ var _FeaturesRouter = require("./Routers/FeaturesRouter");
15
+ var _FilesRouter = require("./Routers/FilesRouter");
16
+ var _FunctionsRouter = require("./Routers/FunctionsRouter");
17
+ var _GlobalConfigRouter = require("./Routers/GlobalConfigRouter");
18
+ var _GraphQLRouter = require("./Routers/GraphQLRouter");
19
+ var _HooksRouter = require("./Routers/HooksRouter");
20
+ var _IAPValidationRouter = require("./Routers/IAPValidationRouter");
21
+ var _InstallationsRouter = require("./Routers/InstallationsRouter");
22
+ var _LogsRouter = require("./Routers/LogsRouter");
23
+ var _ParseLiveQueryServer = require("./LiveQuery/ParseLiveQueryServer");
24
+ var _PagesRouter = require("./Routers/PagesRouter");
25
+ var _PublicAPIRouter = require("./Routers/PublicAPIRouter");
26
+ var _PushRouter = require("./Routers/PushRouter");
27
+ var _CloudCodeRouter = require("./Routers/CloudCodeRouter");
28
+ var _RolesRouter = require("./Routers/RolesRouter");
29
+ var _SchemasRouter = require("./Routers/SchemasRouter");
30
+ var _SessionsRouter = require("./Routers/SessionsRouter");
31
+ var _UsersRouter = require("./Routers/UsersRouter");
32
+ var _PurgeRouter = require("./Routers/PurgeRouter");
33
+ var _AudiencesRouter = require("./Routers/AudiencesRouter");
34
+ var _AggregateRouter = require("./Routers/AggregateRouter");
35
+ var _ParseServerRESTController = require("./ParseServerRESTController");
36
+ var controllers = _interopRequireWildcard(require("./Controllers"));
37
+ var _ParseGraphQLServer = require("./GraphQL/ParseGraphQLServer");
38
+ var _SecurityRouter = require("./Routers/SecurityRouter");
39
+ var _CheckRunner = _interopRequireDefault(require("./Security/CheckRunner"));
40
+ var _Deprecator = _interopRequireDefault(require("./Deprecator/Deprecator"));
41
+ var _DefinedSchemas = require("./SchemaMigrations/DefinedSchemas");
42
+ var _Definitions = _interopRequireDefault(require("./Options/Definitions"));
43
+ var _TestUtils = require("./TestUtils");
44
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
45
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
81
46
  // ParseServer - open-source compatible API Server for Parse apps
82
47
 
83
48
  var batch = require('./batch'),
84
- bodyParser = require('body-parser'),
85
- express = require('express'),
86
- middlewares = require('./middlewares'),
87
- Parse = require('parse/node').Parse,
88
- path = require('path');
89
-
49
+ express = require('express'),
50
+ middlewares = require('./middlewares'),
51
+ Parse = require('parse/node').Parse,
52
+ {
53
+ parse
54
+ } = require('graphql'),
55
+ path = require('path'),
56
+ fs = require('fs');
90
57
  // Mutate the Parse object to add the Cloud Code handlers
91
58
  addParseCloud();
92
59
 
93
- // ParseServer works like a constructor of an express app.
94
- // The args that we understand are:
95
- // "analyticsAdapter": an adapter class for analytics
96
- // "filesAdapter": a class like GridStoreAdapter providing create, get,
97
- // and delete
98
- // "loggerAdapter": a class like WinstonLoggerAdapter providing info, error,
99
- // and query
100
- // "jsonLogs": log as structured JSON objects
101
- // "databaseURI": a uri like mongodb://localhost:27017/dbname to tell us
102
- // what database this Parse API connects to.
103
- // "cloud": relative location to cloud code to require, or a function
104
- // that is given an instance of Parse as a parameter. Use this instance of Parse
105
- // to register your cloud code hooks and functions.
106
- // "appId": the application id to host
107
- // "masterKey": the master key for requests to this app
108
- // "collectionPrefix": optional prefix for database collection names
109
- // "fileKey": optional key from Parse dashboard for supporting older files
110
- // hosted by Parse
111
- // "clientKey": optional key from Parse dashboard
112
- // "dotNetKey": optional key from Parse dashboard
113
- // "restAPIKey": optional key from Parse dashboard
114
- // "webhookKey": optional key from Parse dashboard
115
- // "javascriptKey": optional key from Parse dashboard
116
- // "push": optional key from configure push
117
- // "sessionLength": optional length in seconds for how long Sessions should be valid for
118
- // "maxLimit": optional upper bound for what can be specified for the 'limit' parameter on queries
60
+ // Track connections to destroy them on shutdown
61
+ const connections = new _TestUtils.Connections();
119
62
 
63
+ // ParseServer works like a constructor of an express app.
64
+ // https://parseplatform.org/parse-server/api/master/ParseServerOptions.html
120
65
  class ParseServer {
121
-
66
+ /**
67
+ * @constructor
68
+ * @param {ParseServerOptions} options the parse server initialization options
69
+ */
122
70
  constructor(options) {
71
+ // Scan for deprecated Parse Server options
72
+ _Deprecator.default.scanParseServerOptions(options);
73
+ const interfaces = JSON.parse(JSON.stringify(_Definitions.default));
74
+ function getValidObject(root) {
75
+ const result = {};
76
+ for (const key in root) {
77
+ if (Object.prototype.hasOwnProperty.call(root[key], 'type')) {
78
+ if (root[key].type.endsWith('[]')) {
79
+ result[key] = [getValidObject(interfaces[root[key].type.slice(0, -2)])];
80
+ } else {
81
+ result[key] = getValidObject(interfaces[root[key].type]);
82
+ }
83
+ } else {
84
+ result[key] = '';
85
+ }
86
+ }
87
+ return result;
88
+ }
89
+ const optionsBlueprint = getValidObject(interfaces['ParseServerOptions']);
90
+ function validateKeyNames(original, ref, name = '') {
91
+ let result = [];
92
+ const prefix = name + (name !== '' ? '.' : '');
93
+ for (const key in original) {
94
+ if (!Object.prototype.hasOwnProperty.call(ref, key)) {
95
+ result.push(prefix + key);
96
+ } else {
97
+ if (ref[key] === '') {
98
+ continue;
99
+ }
100
+ let res = [];
101
+ if (Array.isArray(original[key]) && Array.isArray(ref[key])) {
102
+ const type = ref[key][0];
103
+ original[key].forEach((item, idx) => {
104
+ if (typeof item === 'object' && item !== null) {
105
+ res = res.concat(validateKeyNames(item, type, prefix + key + `[${idx}]`));
106
+ }
107
+ });
108
+ } else if (typeof original[key] === 'object' && typeof ref[key] === 'object') {
109
+ res = validateKeyNames(original[key], ref[key], prefix + key);
110
+ }
111
+ result = result.concat(res);
112
+ }
113
+ }
114
+ return result;
115
+ }
116
+ const diff = validateKeyNames(options, optionsBlueprint);
117
+ if (diff.length > 0) {
118
+ const logger = logging.logger;
119
+ logger.error(`Invalid key(s) found in Parse Server configuration: ${diff.join(', ')}`);
120
+ }
121
+
122
+ // Set option defaults
123
123
  injectDefaults(options);
124
124
  const {
125
- appId = (0, _requiredParameter2.default)('You must provide an appId!'),
126
- masterKey = (0, _requiredParameter2.default)('You must provide a masterKey!'),
127
- cloud,
125
+ appId = (0, _requiredParameter.default)('You must provide an appId!'),
126
+ masterKey = (0, _requiredParameter.default)('You must provide a masterKey!'),
128
127
  javascriptKey,
129
- serverURL = (0, _requiredParameter2.default)('You must provide a serverURL!'),
130
- __indexBuildCompletionCallbackForTests = () => {}
128
+ serverURL = (0, _requiredParameter.default)('You must provide a serverURL!')
131
129
  } = options;
132
130
  // Initialize the node client SDK automatically
133
131
  Parse.initialize(appId, javascriptKey || 'unused', masterKey);
134
132
  Parse.serverURL = serverURL;
135
-
133
+ _Config.default.validateOptions(options);
136
134
  const allControllers = controllers.getControllers(options);
135
+ options.state = 'initialized';
136
+ this.config = _Config.default.put(Object.assign({}, options, allControllers));
137
+ this.config.masterKeyIpsStore = new Map();
138
+ this.config.maintenanceKeyIpsStore = new Map();
139
+ logging.setLogger(allControllers.loggerController);
140
+ }
137
141
 
138
- const {
139
- loggerController,
140
- databaseController,
141
- hooksController
142
- } = allControllers;
143
- this.config = _Config2.default.put(Object.assign({}, options, allControllers));
144
-
145
- logging.setLogger(loggerController);
146
- const dbInitPromise = databaseController.performInitialization();
147
- hooksController.load();
142
+ /**
143
+ * Starts Parse Server as an express app; this promise resolves when Parse Server is ready to accept requests.
144
+ */
148
145
 
149
- // Note: Tests will start to fail if any validation happens after this is called.
150
- if (process.env.TESTING) {
151
- __indexBuildCompletionCallbackForTests(dbInitPromise);
152
- }
153
-
154
- if (cloud) {
155
- addParseCloud();
156
- if (typeof cloud === 'function') {
157
- cloud(Parse);
158
- } else if (typeof cloud === 'string') {
159
- require(path.resolve(process.cwd(), cloud));
160
- } else {
161
- throw "argument 'cloud' must either be a string or a function";
146
+ async start() {
147
+ try {
148
+ if (this.config.state === 'ok') {
149
+ return this;
150
+ }
151
+ this.config.state = 'starting';
152
+ _Config.default.put(this.config);
153
+ const {
154
+ databaseController,
155
+ hooksController,
156
+ cacheController,
157
+ cloud,
158
+ security,
159
+ schema,
160
+ liveQueryController
161
+ } = this.config;
162
+ try {
163
+ await databaseController.performInitialization();
164
+ } catch (e) {
165
+ if (e.code !== Parse.Error.DUPLICATE_VALUE) {
166
+ throw e;
167
+ }
168
+ }
169
+ const pushController = await controllers.getPushController(this.config);
170
+ await hooksController.load();
171
+ const startupPromises = [this.config.loadMasterKey?.()];
172
+ if (schema) {
173
+ startupPromises.push(new _DefinedSchemas.DefinedSchemas(schema, this.config).execute());
174
+ }
175
+ if (cacheController.adapter?.connect && typeof cacheController.adapter.connect === 'function') {
176
+ startupPromises.push(cacheController.adapter.connect());
162
177
  }
178
+ startupPromises.push(liveQueryController.connect());
179
+ await Promise.all(startupPromises);
180
+ if (cloud) {
181
+ addParseCloud();
182
+ if (typeof cloud === 'function') {
183
+ await Promise.resolve(cloud(Parse));
184
+ } else if (typeof cloud === 'string') {
185
+ let json;
186
+ if (process.env.npm_package_json) {
187
+ json = require(process.env.npm_package_json);
188
+ }
189
+ if (process.env.npm_package_type === 'module' || json?.type === 'module') {
190
+ await import(path.resolve(process.cwd(), cloud));
191
+ } else {
192
+ require(path.resolve(process.cwd(), cloud));
193
+ }
194
+ } else {
195
+ throw "argument 'cloud' must either be a string or a function";
196
+ }
197
+ await new Promise(resolve => setTimeout(resolve, 10));
198
+ }
199
+ if (security && security.enableCheck && security.enableCheckLog) {
200
+ new _CheckRunner.default(security).run();
201
+ }
202
+ this.config.state = 'ok';
203
+ this.config = {
204
+ ...this.config,
205
+ ...pushController
206
+ };
207
+ _Config.default.put(this.config);
208
+ return this;
209
+ } catch (error) {
210
+ // eslint-disable-next-line no-console
211
+ console.error(error);
212
+ this.config.state = 'error';
213
+ throw error;
163
214
  }
164
215
  }
165
-
166
216
  get app() {
167
217
  if (!this._app) {
168
218
  this._app = ParseServer.app(this.config);
@@ -170,39 +220,131 @@ class ParseServer {
170
220
  return this._app;
171
221
  }
172
222
 
173
- handleShutdown() {
174
- const { adapter } = this.config.databaseController;
175
- if (adapter && typeof adapter.handleShutdown === 'function') {
176
- adapter.handleShutdown();
223
+ /**
224
+ * Stops the parse server, cancels any ongoing requests and closes all connections.
225
+ *
226
+ * Currently, express doesn't shut down immediately after receiving SIGINT/SIGTERM
227
+ * if it has client connections that haven't timed out.
228
+ * (This is a known issue with node - https://github.com/nodejs/node/issues/2642)
229
+ *
230
+ * @returns {Promise<void>} a promise that resolves when the server is stopped
231
+ */
232
+ async handleShutdown() {
233
+ const serverClosePromise = (0, _TestUtils.resolvingPromise)();
234
+ const liveQueryServerClosePromise = (0, _TestUtils.resolvingPromise)();
235
+ const promises = [];
236
+ this.server.close(error => {
237
+ /* istanbul ignore next */
238
+ if (error) {
239
+ // eslint-disable-next-line no-console
240
+ console.error('Error while closing parse server', error);
241
+ }
242
+ serverClosePromise.resolve();
243
+ });
244
+ if (this.liveQueryServer?.server?.close && this.liveQueryServer.server !== this.server) {
245
+ this.liveQueryServer.server.close(error => {
246
+ /* istanbul ignore next */
247
+ if (error) {
248
+ // eslint-disable-next-line no-console
249
+ console.error('Error while closing live query server', error);
250
+ }
251
+ liveQueryServerClosePromise.resolve();
252
+ });
253
+ } else {
254
+ liveQueryServerClosePromise.resolve();
255
+ }
256
+ const {
257
+ adapter: databaseAdapter
258
+ } = this.config.databaseController;
259
+ if (databaseAdapter && typeof databaseAdapter.handleShutdown === 'function') {
260
+ promises.push(databaseAdapter.handleShutdown());
261
+ }
262
+ const {
263
+ adapter: fileAdapter
264
+ } = this.config.filesController;
265
+ if (fileAdapter && typeof fileAdapter.handleShutdown === 'function') {
266
+ promises.push(fileAdapter.handleShutdown());
267
+ }
268
+ const {
269
+ adapter: cacheAdapter
270
+ } = this.config.cacheController;
271
+ if (cacheAdapter && typeof cacheAdapter.handleShutdown === 'function') {
272
+ promises.push(cacheAdapter.handleShutdown());
273
+ }
274
+ if (this.liveQueryServer) {
275
+ promises.push(this.liveQueryServer.shutdown());
276
+ }
277
+ await Promise.all(promises);
278
+ connections.destroyAll();
279
+ await Promise.all([serverClosePromise, liveQueryServerClosePromise]);
280
+ if (this.config.serverCloseComplete) {
281
+ this.config.serverCloseComplete();
177
282
  }
178
283
  }
179
284
 
180
- static app({ maxUploadSize = '20mb', appId }) {
285
+ /**
286
+ * @static
287
+ * Allow developers to customize each request with inversion of control/dependency injection
288
+ */
289
+ static applyRequestContextMiddleware(api, options) {
290
+ if (options.requestContextMiddleware) {
291
+ if (typeof options.requestContextMiddleware !== 'function') {
292
+ throw new Error('requestContextMiddleware must be a function');
293
+ }
294
+ api.use(options.requestContextMiddleware);
295
+ }
296
+ }
297
+ /**
298
+ * @static
299
+ * Create an express app for the parse server
300
+ * @param {Object} options let you specify the maxUploadSize when creating the express app */
301
+ static app(options) {
302
+ const {
303
+ maxUploadSize = '20mb',
304
+ appId,
305
+ directAccess,
306
+ pages,
307
+ rateLimit = []
308
+ } = options;
181
309
  // This app serves the Parse API directly.
182
310
  // It's the equivalent of https://api.parse.com/1 in the hosted Parse API.
183
311
  var api = express();
184
312
  //api.use("/apps", express.static(__dirname + "/public"));
313
+ api.use(middlewares.allowCrossDomain(appId));
314
+ api.use(middlewares.allowDoubleForwardSlash);
185
315
  // File handling needs to be before default middlewares are applied
186
- api.use('/', middlewares.allowCrossDomain, new _FilesRouter.FilesRouter().expressRouter({
316
+ api.use('/', new _FilesRouter.FilesRouter().expressRouter({
187
317
  maxUploadSize: maxUploadSize
188
318
  }));
189
-
190
319
  api.use('/health', function (req, res) {
320
+ res.status(options.state === 'ok' ? 200 : 503);
321
+ if (options.state === 'starting') {
322
+ res.set('Retry-After', 1);
323
+ }
191
324
  res.json({
192
- status: 'ok'
325
+ status: options.state
193
326
  });
194
327
  });
195
-
196
- api.use('/', bodyParser.urlencoded({ extended: false }), new _PublicAPIRouter.PublicAPIRouter().expressRouter());
197
-
198
- api.use(bodyParser.json({ 'type': '*/*', limit: maxUploadSize }));
199
- api.use(middlewares.allowCrossDomain);
328
+ api.use('/', express.urlencoded({
329
+ extended: false
330
+ }), pages.enableRouter ? new _PagesRouter.PagesRouter(pages).expressRouter() : new _PublicAPIRouter.PublicAPIRouter().expressRouter());
331
+ api.use(express.json({
332
+ type: '*/*',
333
+ limit: maxUploadSize
334
+ }));
200
335
  api.use(middlewares.allowMethodOverride);
201
336
  api.use(middlewares.handleParseHeaders);
202
-
203
- const appRouter = ParseServer.promiseRouter({ appId });
337
+ api.set('query parser', 'extended');
338
+ const routes = Array.isArray(rateLimit) ? rateLimit : [rateLimit];
339
+ for (const route of routes) {
340
+ middlewares.addRateLimit(route, options);
341
+ }
342
+ api.use(middlewares.handleParseSession);
343
+ this.applyRequestContextMiddleware(api, options);
344
+ const appRouter = ParseServer.promiseRouter({
345
+ appId
346
+ });
204
347
  api.use(appRouter.expressRouter());
205
-
206
348
  api.use(middlewares.handleParseErrors);
207
349
 
208
350
  // run the following when not testing
@@ -210,40 +352,54 @@ class ParseServer {
210
352
  //This causes tests to spew some useless warnings, so disable in test
211
353
  /* istanbul ignore next */
212
354
  process.on('uncaughtException', err => {
213
- if (err.code === "EADDRINUSE") {
355
+ if (err.code === 'EADDRINUSE') {
214
356
  // user-friendly message for this common error
215
357
  process.stderr.write(`Unable to listen on port ${err.port}. The port is already in use.`);
216
358
  process.exit(0);
217
359
  } else {
218
- throw err;
360
+ if (err.message) {
361
+ process.stderr.write('An uncaught exception occurred: ' + err.message);
362
+ }
363
+ if (err.stack) {
364
+ process.stderr.write('Stack Trace:\n' + err.stack);
365
+ } else {
366
+ process.stderr.write(err);
367
+ }
368
+ process.exit(1);
219
369
  }
220
370
  });
221
- // verify the server url after a 'mount' event is received
222
- /* istanbul ignore next */
223
- api.on('mount', function () {
224
- ParseServer.verifyServerUrl();
225
- });
226
371
  }
227
- if (process.env.PARSE_SERVER_ENABLE_EXPERIMENTAL_DIRECT_ACCESS === '1') {
372
+ if (process.env.PARSE_SERVER_ENABLE_EXPERIMENTAL_DIRECT_ACCESS === '1' || directAccess) {
228
373
  Parse.CoreManager.setRESTController((0, _ParseServerRESTController.ParseServerRESTController)(appId, appRouter));
229
374
  }
230
375
  return api;
231
376
  }
232
-
233
- static promiseRouter({ appId }) {
234
- const routers = [new _ClassesRouter.ClassesRouter(), new _UsersRouter.UsersRouter(), new _SessionsRouter.SessionsRouter(), new _RolesRouter.RolesRouter(), new _AnalyticsRouter.AnalyticsRouter(), new _InstallationsRouter.InstallationsRouter(), new _FunctionsRouter.FunctionsRouter(), new _SchemasRouter.SchemasRouter(), new _PushRouter.PushRouter(), new _LogsRouter.LogsRouter(), new _IAPValidationRouter.IAPValidationRouter(), new _FeaturesRouter.FeaturesRouter(), new _GlobalConfigRouter.GlobalConfigRouter(), new _PurgeRouter.PurgeRouter(), new _HooksRouter.HooksRouter(), new _CloudCodeRouter.CloudCodeRouter(), new _AudiencesRouter.AudiencesRouter(), new _AggregateRouter.AggregateRouter()];
235
-
377
+ static promiseRouter({
378
+ appId
379
+ }) {
380
+ const routers = [new _ClassesRouter.ClassesRouter(), new _UsersRouter.UsersRouter(), new _SessionsRouter.SessionsRouter(), new _RolesRouter.RolesRouter(), new _AnalyticsRouter.AnalyticsRouter(), new _InstallationsRouter.InstallationsRouter(), new _FunctionsRouter.FunctionsRouter(), new _SchemasRouter.SchemasRouter(), new _PushRouter.PushRouter(), new _LogsRouter.LogsRouter(), new _IAPValidationRouter.IAPValidationRouter(), new _FeaturesRouter.FeaturesRouter(), new _GlobalConfigRouter.GlobalConfigRouter(), new _GraphQLRouter.GraphQLRouter(), new _PurgeRouter.PurgeRouter(), new _HooksRouter.HooksRouter(), new _CloudCodeRouter.CloudCodeRouter(), new _AudiencesRouter.AudiencesRouter(), new _AggregateRouter.AggregateRouter(), new _SecurityRouter.SecurityRouter()];
236
381
  const routes = routers.reduce((memo, router) => {
237
382
  return memo.concat(router.routes);
238
383
  }, []);
239
-
240
- const appRouter = new _PromiseRouter2.default(routes, appId);
241
-
384
+ const appRouter = new _PromiseRouter.default(routes, appId);
242
385
  batch.mountOnto(appRouter);
243
386
  return appRouter;
244
387
  }
245
388
 
246
- start(options, callback) {
389
+ /**
390
+ * starts the parse server's express app
391
+ * @param {ParseServerOptions} options to use to start the server
392
+ * @returns {ParseServer} the parse server instance
393
+ */
394
+
395
+ async startApp(options) {
396
+ try {
397
+ await this.start();
398
+ } catch (e) {
399
+ // eslint-disable-next-line no-console
400
+ console.error('Error on ParseServer.startApp: ', e);
401
+ throw e;
402
+ }
247
403
  const app = express();
248
404
  if (options.middleware) {
249
405
  let middleware;
@@ -254,118 +410,201 @@ class ParseServer {
254
410
  }
255
411
  app.use(middleware);
256
412
  }
257
-
258
413
  app.use(options.mountPath, this.app);
259
- const server = app.listen(options.port, options.host, callback);
414
+ if (options.mountGraphQL === true || options.mountPlayground === true) {
415
+ let graphQLCustomTypeDefs = undefined;
416
+ if (typeof options.graphQLSchema === 'string') {
417
+ graphQLCustomTypeDefs = parse(fs.readFileSync(options.graphQLSchema, 'utf8'));
418
+ } else if (typeof options.graphQLSchema === 'object' || typeof options.graphQLSchema === 'function') {
419
+ graphQLCustomTypeDefs = options.graphQLSchema;
420
+ }
421
+ const parseGraphQLServer = new _ParseGraphQLServer.ParseGraphQLServer(this, {
422
+ graphQLPath: options.graphQLPath,
423
+ playgroundPath: options.playgroundPath,
424
+ graphQLCustomTypeDefs
425
+ });
426
+ if (options.mountGraphQL) {
427
+ parseGraphQLServer.applyGraphQL(app);
428
+ }
429
+ if (options.mountPlayground) {
430
+ parseGraphQLServer.applyPlayground(app);
431
+ }
432
+ }
433
+ const server = await new Promise(resolve => {
434
+ app.listen(options.port, options.host, function () {
435
+ resolve(this);
436
+ });
437
+ });
260
438
  this.server = server;
261
-
439
+ connections.track(server);
262
440
  if (options.startLiveQueryServer || options.liveQueryServerOptions) {
263
- this.liveQueryServer = ParseServer.createLiveQueryServer(server, options.liveQueryServerOptions);
441
+ this.liveQueryServer = await ParseServer.createLiveQueryServer(server, options.liveQueryServerOptions, options);
442
+ if (this.liveQueryServer.server !== this.server) {
443
+ connections.track(this.liveQueryServer.server);
444
+ }
445
+ }
446
+ if (options.trustProxy) {
447
+ app.set('trust proxy', options.trustProxy);
264
448
  }
265
449
  /* istanbul ignore next */
266
450
  if (!process.env.TESTING) {
267
451
  configureListeners(this);
452
+ if (options.verifyServerUrl !== false) {
453
+ await ParseServer.verifyServerUrl();
454
+ }
268
455
  }
269
456
  this.expressApp = app;
270
457
  return this;
271
458
  }
272
459
 
273
- static start(options, callback) {
460
+ /**
461
+ * Creates a new ParseServer and starts it.
462
+ * @param {ParseServerOptions} options used to start the server
463
+ * @returns {ParseServer} the parse server instance
464
+ */
465
+ static async startApp(options) {
274
466
  const parseServer = new ParseServer(options);
275
- return parseServer.start(options, callback);
467
+ return parseServer.startApp(options);
276
468
  }
277
469
 
278
- static createLiveQueryServer(httpServer, config) {
470
+ /**
471
+ * Helper method to create a liveQuery server
472
+ * @static
473
+ * @param {Server} httpServer an optional http server to pass
474
+ * @param {LiveQueryServerOptions} config options for the liveQueryServer
475
+ * @param {ParseServerOptions} options options for the ParseServer
476
+ * @returns {Promise<ParseLiveQueryServer>} the live query server instance
477
+ */
478
+ static async createLiveQueryServer(httpServer, config, options) {
279
479
  if (!httpServer || config && config.port) {
280
480
  var app = express();
281
481
  httpServer = require('http').createServer(app);
282
482
  httpServer.listen(config.port);
283
483
  }
284
- return new _ParseLiveQueryServer.ParseLiveQueryServer(httpServer, config);
484
+ const server = new _ParseLiveQueryServer.ParseLiveQueryServer(httpServer, config, options);
485
+ await server.connect();
486
+ return server;
285
487
  }
286
-
287
- static verifyServerUrl(callback) {
488
+ static async verifyServerUrl() {
288
489
  // perform a health check on the serverURL value
289
490
  if (Parse.serverURL) {
290
- const request = require('request');
291
- request(Parse.serverURL.replace(/\/$/, "") + "/health", function (error, response, body) {
292
- let json;
491
+ const isValidHttpUrl = string => {
492
+ let url;
293
493
  try {
294
- json = JSON.parse(body);
295
- } catch (e) {
296
- json = null;
494
+ url = new URL(string);
495
+ } catch (_) {
496
+ return false;
297
497
  }
298
- if (error || response.statusCode !== 200 || !json || json && json.status !== 'ok') {
299
- /* eslint-disable no-console */
300
- console.warn(`\nWARNING, Unable to connect to '${Parse.serverURL}'.` + ` Cloud code and push notifications may be unavailable!\n`);
301
- /* eslint-enable no-console */
302
- if (callback) {
303
- callback(false);
304
- }
305
- } else {
306
- if (callback) {
307
- callback(true);
308
- }
309
- }
310
- });
498
+ return url.protocol === 'http:' || url.protocol === 'https:';
499
+ };
500
+ const url = `${Parse.serverURL.replace(/\/$/, '')}/health`;
501
+ if (!isValidHttpUrl(url)) {
502
+ // eslint-disable-next-line no-console
503
+ console.warn(`\nWARNING, Unable to connect to '${Parse.serverURL}' as the URL is invalid.` + ` Cloud code and push notifications may be unavailable!\n`);
504
+ return;
505
+ }
506
+ const request = require('./request');
507
+ const response = await request({
508
+ url
509
+ }).catch(response => response);
510
+ const json = response.data || null;
511
+ const retry = response.headers?.['retry-after'];
512
+ if (retry) {
513
+ await new Promise(resolve => setTimeout(resolve, retry * 1000));
514
+ return this.verifyServerUrl();
515
+ }
516
+ if (response.status !== 200 || json?.status !== 'ok') {
517
+ /* eslint-disable no-console */
518
+ console.warn(`\nWARNING, Unable to connect to '${Parse.serverURL}'.` + ` Cloud code and push notifications may be unavailable!\n`);
519
+ /* eslint-enable no-console */
520
+ return;
521
+ }
522
+ return true;
311
523
  }
312
524
  }
313
525
  }
314
-
315
526
  function addParseCloud() {
316
- const ParseCloud = require("./cloud-code/Parse.Cloud");
527
+ const ParseCloud = require('./cloud-code/Parse.Cloud');
528
+ const ParseServer = require('./cloud-code/Parse.Server');
529
+ Object.defineProperty(Parse, 'Server', {
530
+ get() {
531
+ const conf = _Config.default.get(Parse.applicationId);
532
+ return {
533
+ ...conf,
534
+ ...ParseServer
535
+ };
536
+ },
537
+ set(newVal) {
538
+ newVal.appId = Parse.applicationId;
539
+ _Config.default.put(newVal);
540
+ },
541
+ configurable: true
542
+ });
317
543
  Object.assign(Parse.Cloud, ParseCloud);
318
544
  global.Parse = Parse;
319
545
  }
320
-
321
546
  function injectDefaults(options) {
322
- Object.keys(_defaults2.default).forEach(key => {
323
- if (!options.hasOwnProperty(key)) {
324
- options[key] = _defaults2.default[key];
547
+ Object.keys(_defaults.default).forEach(key => {
548
+ if (!Object.prototype.hasOwnProperty.call(options, key)) {
549
+ options[key] = _defaults.default[key];
325
550
  }
326
551
  });
327
-
328
- if (!options.hasOwnProperty('serverURL')) {
552
+ if (!Object.prototype.hasOwnProperty.call(options, 'serverURL')) {
329
553
  options.serverURL = `http://localhost:${options.port}${options.mountPath}`;
330
554
  }
331
555
 
332
- options.userSensitiveFields = Array.from(new Set(options.userSensitiveFields.concat(_defaults2.default.userSensitiveFields, options.userSensitiveFields)));
556
+ // Reserved Characters
557
+ if (options.appId) {
558
+ const regex = /[!#$%'()*+&/:;=?@[\]{}^,|<>]/g;
559
+ if (options.appId.match(regex)) {
560
+ // eslint-disable-next-line no-console
561
+ console.warn(`\nWARNING, appId that contains special characters can cause issues while using with urls.\n`);
562
+ }
563
+ }
333
564
 
334
- options.masterKeyIps = Array.from(new Set(options.masterKeyIps.concat(_defaults2.default.masterKeyIps, options.masterKeyIps)));
565
+ // Backwards compatibility
566
+ if (options.userSensitiveFields) {
567
+ /* eslint-disable no-console */
568
+ !process.env.TESTING && console.warn(`\nDEPRECATED: userSensitiveFields has been replaced by protectedFields allowing the ability to protect fields in all classes with CLP. \n`);
569
+ /* eslint-enable no-console */
570
+
571
+ const userSensitiveFields = Array.from(new Set([...(_defaults.default.userSensitiveFields || []), ...(options.userSensitiveFields || [])]));
572
+
573
+ // If the options.protectedFields is unset,
574
+ // it'll be assigned the default above.
575
+ // Here, protect against the case where protectedFields
576
+ // is set, but doesn't have _User.
577
+ if (!('_User' in options.protectedFields)) {
578
+ options.protectedFields = Object.assign({
579
+ _User: []
580
+ }, options.protectedFields);
581
+ }
582
+ options.protectedFields['_User']['*'] = Array.from(new Set([...(options.protectedFields['_User']['*'] || []), ...userSensitiveFields]));
583
+ }
584
+
585
+ // Merge protectedFields options with defaults.
586
+ Object.keys(_defaults.default.protectedFields).forEach(c => {
587
+ const cur = options.protectedFields[c];
588
+ if (!cur) {
589
+ options.protectedFields[c] = _defaults.default.protectedFields[c];
590
+ } else {
591
+ Object.keys(_defaults.default.protectedFields[c]).forEach(r => {
592
+ const unq = new Set([...(options.protectedFields[c][r] || []), ..._defaults.default.protectedFields[c][r]]);
593
+ options.protectedFields[c][r] = Array.from(unq);
594
+ });
595
+ }
596
+ });
335
597
  }
336
598
 
337
599
  // Those can't be tested as it requires a subprocess
338
600
  /* istanbul ignore next */
339
601
  function configureListeners(parseServer) {
340
- const server = parseServer.server;
341
- const sockets = {};
342
- /* Currently, express doesn't shut down immediately after receiving SIGINT/SIGTERM if it has client connections that haven't timed out. (This is a known issue with node - https://github.com/nodejs/node/issues/2642)
343
- This function, along with `destroyAliveConnections()`, intend to fix this behavior such that parse server will close all open connections and initiate the shutdown process as soon as it receives a SIGINT/SIGTERM signal. */
344
- server.on('connection', socket => {
345
- const socketId = socket.remoteAddress + ':' + socket.remotePort;
346
- sockets[socketId] = socket;
347
- socket.on('close', () => {
348
- delete sockets[socketId];
349
- });
350
- });
351
-
352
- const destroyAliveConnections = function () {
353
- for (const socketId in sockets) {
354
- try {
355
- sockets[socketId].destroy();
356
- } catch (e) {/* */}
357
- }
358
- };
359
-
360
602
  const handleShutdown = function () {
361
603
  process.stdout.write('Termination signal received. Shutting down.');
362
- destroyAliveConnections();
363
- server.close();
364
604
  parseServer.handleShutdown();
365
605
  };
366
606
  process.on('SIGTERM', handleShutdown);
367
607
  process.on('SIGINT', handleShutdown);
368
608
  }
369
-
370
- exports.default = ParseServer;
371
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9QYXJzZVNlcnZlci5qcyJdLCJuYW1lcyI6WyJsb2dnaW5nIiwiY29udHJvbGxlcnMiLCJiYXRjaCIsInJlcXVpcmUiLCJib2R5UGFyc2VyIiwiZXhwcmVzcyIsIm1pZGRsZXdhcmVzIiwiUGFyc2UiLCJwYXRoIiwiYWRkUGFyc2VDbG91ZCIsIlBhcnNlU2VydmVyIiwiY29uc3RydWN0b3IiLCJvcHRpb25zIiwiaW5qZWN0RGVmYXVsdHMiLCJhcHBJZCIsIm1hc3RlcktleSIsImNsb3VkIiwiamF2YXNjcmlwdEtleSIsInNlcnZlclVSTCIsIl9faW5kZXhCdWlsZENvbXBsZXRpb25DYWxsYmFja0ZvclRlc3RzIiwiaW5pdGlhbGl6ZSIsImFsbENvbnRyb2xsZXJzIiwiZ2V0Q29udHJvbGxlcnMiLCJsb2dnZXJDb250cm9sbGVyIiwiZGF0YWJhc2VDb250cm9sbGVyIiwiaG9va3NDb250cm9sbGVyIiwiY29uZmlnIiwiQ29uZmlnIiwicHV0IiwiT2JqZWN0IiwiYXNzaWduIiwic2V0TG9nZ2VyIiwiZGJJbml0UHJvbWlzZSIsInBlcmZvcm1Jbml0aWFsaXphdGlvbiIsImxvYWQiLCJwcm9jZXNzIiwiZW52IiwiVEVTVElORyIsInJlc29sdmUiLCJjd2QiLCJhcHAiLCJfYXBwIiwiaGFuZGxlU2h1dGRvd24iLCJhZGFwdGVyIiwibWF4VXBsb2FkU2l6ZSIsImFwaSIsInVzZSIsImFsbG93Q3Jvc3NEb21haW4iLCJGaWxlc1JvdXRlciIsImV4cHJlc3NSb3V0ZXIiLCJyZXEiLCJyZXMiLCJqc29uIiwic3RhdHVzIiwidXJsZW5jb2RlZCIsImV4dGVuZGVkIiwiUHVibGljQVBJUm91dGVyIiwibGltaXQiLCJhbGxvd01ldGhvZE92ZXJyaWRlIiwiaGFuZGxlUGFyc2VIZWFkZXJzIiwiYXBwUm91dGVyIiwicHJvbWlzZVJvdXRlciIsImhhbmRsZVBhcnNlRXJyb3JzIiwib24iLCJlcnIiLCJjb2RlIiwic3RkZXJyIiwid3JpdGUiLCJwb3J0IiwiZXhpdCIsInZlcmlmeVNlcnZlclVybCIsIlBBUlNFX1NFUlZFUl9FTkFCTEVfRVhQRVJJTUVOVEFMX0RJUkVDVF9BQ0NFU1MiLCJDb3JlTWFuYWdlciIsInNldFJFU1RDb250cm9sbGVyIiwicm91dGVycyIsIkNsYXNzZXNSb3V0ZXIiLCJVc2Vyc1JvdXRlciIsIlNlc3Npb25zUm91dGVyIiwiUm9sZXNSb3V0ZXIiLCJBbmFseXRpY3NSb3V0ZXIiLCJJbnN0YWxsYXRpb25zUm91dGVyIiwiRnVuY3Rpb25zUm91dGVyIiwiU2NoZW1hc1JvdXRlciIsIlB1c2hSb3V0ZXIiLCJMb2dzUm91dGVyIiwiSUFQVmFsaWRhdGlvblJvdXRlciIsIkZlYXR1cmVzUm91dGVyIiwiR2xvYmFsQ29uZmlnUm91dGVyIiwiUHVyZ2VSb3V0ZXIiLCJIb29rc1JvdXRlciIsIkNsb3VkQ29kZVJvdXRlciIsIkF1ZGllbmNlc1JvdXRlciIsIkFnZ3JlZ2F0ZVJvdXRlciIsInJvdXRlcyIsInJlZHVjZSIsIm1lbW8iLCJyb3V0ZXIiLCJjb25jYXQiLCJQcm9taXNlUm91dGVyIiwibW91bnRPbnRvIiwic3RhcnQiLCJjYWxsYmFjayIsIm1pZGRsZXdhcmUiLCJtb3VudFBhdGgiLCJzZXJ2ZXIiLCJsaXN0ZW4iLCJob3N0Iiwic3RhcnRMaXZlUXVlcnlTZXJ2ZXIiLCJsaXZlUXVlcnlTZXJ2ZXJPcHRpb25zIiwibGl2ZVF1ZXJ5U2VydmVyIiwiY3JlYXRlTGl2ZVF1ZXJ5U2VydmVyIiwiY29uZmlndXJlTGlzdGVuZXJzIiwiZXhwcmVzc0FwcCIsInBhcnNlU2VydmVyIiwiaHR0cFNlcnZlciIsImNyZWF0ZVNlcnZlciIsIlBhcnNlTGl2ZVF1ZXJ5U2VydmVyIiwicmVxdWVzdCIsInJlcGxhY2UiLCJlcnJvciIsInJlc3BvbnNlIiwiYm9keSIsIkpTT04iLCJwYXJzZSIsImUiLCJzdGF0dXNDb2RlIiwiY29uc29sZSIsIndhcm4iLCJQYXJzZUNsb3VkIiwiQ2xvdWQiLCJnbG9iYWwiLCJrZXlzIiwiZGVmYXVsdHMiLCJmb3JFYWNoIiwia2V5IiwiaGFzT3duUHJvcGVydHkiLCJ1c2VyU2Vuc2l0aXZlRmllbGRzIiwiQXJyYXkiLCJmcm9tIiwiU2V0IiwibWFzdGVyS2V5SXBzIiwic29ja2V0cyIsInNvY2tldCIsInNvY2tldElkIiwicmVtb3RlQWRkcmVzcyIsInJlbW90ZVBvcnQiLCJkZXN0cm95QWxpdmVDb25uZWN0aW9ucyIsImRlc3Ryb3kiLCJzdGRvdXQiLCJjbG9zZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBU0E7O0FBRUE7Ozs7QUFDQTs7SUFBWUEsTzs7QUFDWjs7OztBQUNBOzs7O0FBQ0E7Ozs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFFQTs7QUFDQTs7SUFBWUMsVzs7Ozs7O0FBdkNaOztBQUVBLElBQUlDLFFBQVFDLFFBQVEsU0FBUixDQUFaO0FBQUEsSUFDRUMsYUFBYUQsUUFBUSxhQUFSLENBRGY7QUFBQSxJQUVFRSxVQUFVRixRQUFRLFNBQVIsQ0FGWjtBQUFBLElBR0VHLGNBQWNILFFBQVEsZUFBUixDQUhoQjtBQUFBLElBSUVJLFFBQVFKLFFBQVEsWUFBUixFQUFzQkksS0FKaEM7QUFBQSxJQUtFQyxPQUFPTCxRQUFRLE1BQVIsQ0FMVDs7QUFzQ0E7QUFDQU07O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxNQUFNQyxXQUFOLENBQWtCOztBQUVoQkMsY0FBWUMsT0FBWixFQUF5QztBQUN2Q0MsbUJBQWVELE9BQWY7QUFDQSxVQUFNO0FBQ0pFLGNBQVEsaUNBQWtCLDRCQUFsQixDQURKO0FBRUpDLGtCQUFZLGlDQUFrQiwrQkFBbEIs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Q0QsT0FGRCxDQUVFLE9BQU92QixDQUFQLEVBQVUsQ0FBRSxLQUFPO0FBQ3RCO0FBQ0YsR0FORDs7QUFRQSxRQUFNbEYsaUJBQWlCLFlBQVc7QUFDaENQLFlBQVFpSCxNQUFSLENBQWVqRixLQUFmLENBQXFCLDZDQUFyQjtBQUNBK0U7QUFDQTFDLFdBQU82QyxLQUFQO0FBQ0FwQyxnQkFBWXZFLGNBQVo7QUFDRCxHQUxEO0FBTUFQLFVBQVE0QixFQUFSLENBQVcsU0FBWCxFQUFzQnJCLGNBQXRCO0FBQ0FQLFVBQVE0QixFQUFSLENBQVcsUUFBWCxFQUFxQnJCLGNBQXJCO0FBQ0Q7O2tCQUVjaEMsVyIsImZpbGUiOiJQYXJzZVNlcnZlci5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8vIFBhcnNlU2VydmVyIC0gb3Blbi1zb3VyY2UgY29tcGF0aWJsZSBBUEkgU2VydmVyIGZvciBQYXJzZSBhcHBzXG5cbnZhciBiYXRjaCA9IHJlcXVpcmUoJy4vYmF0Y2gnKSxcbiAgYm9keVBhcnNlciA9IHJlcXVpcmUoJ2JvZHktcGFyc2VyJyksXG4gIGV4cHJlc3MgPSByZXF1aXJlKCdleHByZXNzJyksXG4gIG1pZGRsZXdhcmVzID0gcmVxdWlyZSgnLi9taWRkbGV3YXJlcycpLFxuICBQYXJzZSA9IHJlcXVpcmUoJ3BhcnNlL25vZGUnKS5QYXJzZSxcbiAgcGF0aCA9IHJlcXVpcmUoJ3BhdGgnKTtcblxuaW1wb3J0IHsgUGFyc2VTZXJ2ZXJPcHRpb25zLFxuICBMaXZlUXVlcnlTZXJ2ZXJPcHRpb25zIH0gICAgICBmcm9tICcuL09wdGlvbnMnO1xuaW1wb3J0IGRlZmF1bHRzICAgICAgICAgICAgICAgICBmcm9tICcuL2RlZmF1bHRzJztcbmltcG9ydCAqIGFzIGxvZ2dpbmcgICAgICAgICAgICAgZnJvbSAnLi9sb2dnZXInO1xuaW1wb3J0IENvbmZpZyAgICAgICAgICAgICAgICAgICBmcm9tICcuL0NvbmZpZyc7XG5pbXBvcnQgUHJvbWlzZVJvdXRlciAgICAgICAgICAgIGZyb20gJy4vUHJvbWlzZVJvdXRlcic7XG5pbXBvcnQgcmVxdWlyZWRQYXJhbWV0ZXIgICAgICAgIGZyb20gJy4vcmVxdWlyZWRQYXJhbWV0ZXInO1xuaW1wb3J0IHsgQW5hbHl0aWNzUm91dGVyIH0gICAgICBmcm9tICcuL1JvdXRlcnMvQW5hbHl0aWNzUm91dGVyJztcbmltcG9ydCB7IENsYXNzZXNSb3V0ZXIgfSAgICAgICAgZnJvbSAnLi9Sb3V0ZXJzL0NsYXNzZXNSb3V0ZXInO1xuaW1wb3J0IHsgRmVhdHVyZXNSb3V0ZXIgfSAgICAgICBmcm9tICcuL1JvdXRlcnMvRmVhdHVyZXNSb3V0ZXInO1xuaW1wb3J0IHsgRmlsZXNSb3V0ZXIgfSAgICAgICAgICBmcm9tICcuL1JvdXRlcnMvRmlsZXNSb3V0ZXInO1xuaW1wb3J0IHsgRnVuY3Rpb25zUm91dGVyIH0gICAgICBmcm9tICcuL1JvdXRlcnMvRnVuY3Rpb25zUm91dGVyJztcbmltcG9ydCB7IEdsb2JhbENvbmZpZ1JvdXRlciB9ICAgZnJvbSAnLi9Sb3V0ZXJzL0dsb2JhbENvbmZpZ1JvdXRlcic7XG5pbXBvcnQgeyBIb29rc1JvdXRlciB9ICAgICAgICAgIGZyb20gJy4vUm91dGVycy9Ib29rc1JvdXRlcic7XG5pbXBvcnQgeyBJQVBWYWxpZGF0aW9uUm91dGVyIH0gIGZyb20gJy4vUm91dGVycy9JQVBWYWxpZGF0aW9uUm91dGVyJztcbmltcG9ydCB7IEluc3RhbGxhdGlvbnNSb3V0ZXIgfSAgZnJvbSAnLi9Sb3V0ZXJzL0luc3RhbGxhdGlvbnNSb3V0ZXInO1xuaW1wb3J0IHsgTG9nc1JvdXRlciB9ICAgICAgICAgICBmcm9tICcuL1JvdXRlcnMvTG9nc1JvdXRlcic7XG5pbXBvcnQgeyBQYXJzZUxpdmVRdWVyeVNlcnZlciB9IGZyb20gJy4vTGl2ZVF1ZXJ5L1BhcnNlTGl2ZVF1ZXJ5U2VydmVyJztcbmltcG9ydCB7IFB1YmxpY0FQSVJvdXRlciB9ICAgICAgZnJvbSAnLi9Sb3V0ZXJzL1B1YmxpY0FQSVJvdXRlcic7XG5pbXBvcnQgeyBQdXNoUm91dGVyIH0gICAgICAgICAgIGZyb20gJy4vUm91dGVycy9QdXNoUm91dGVyJztcbmltcG9ydCB7IENsb3VkQ29kZVJvdXRlciB9ICAgICAgZnJvbSAnLi9Sb3V0ZXJzL0Nsb3VkQ29kZVJvdXRlcic7XG5pbXBvcnQgeyBSb2xlc1JvdXRlciB9ICAgICAgICAgIGZyb20gJy4vUm91dGVycy9Sb2xlc1JvdXRlcic7XG5pbXBvcnQgeyBTY2hlbWFzUm91dGVyIH0gICAgICAgIGZyb20gJy4vUm91dGVycy9TY2hlbWFzUm91dGVyJztcbmltcG9ydCB7IFNlc3Npb25zUm91dGVyIH0gICAgICAgZnJvbSAnLi9Sb3V0ZXJzL1Nlc3Npb25zUm91dGVyJztcbmltcG9ydCB7IFVzZXJzUm91dGVyIH0gICAgICAgICAgZnJvbSAnLi9Sb3V0ZXJzL1VzZXJzUm91dGVyJztcbmltcG9ydCB7IFB1cmdlUm91dGVyIH0gICAgICAgICAgZnJvbSAnLi9Sb3V0ZXJzL1B1cmdlUm91dGVyJztcbmltcG9ydCB7IEF1ZGllbmNlc1JvdXRlciB9ICAgICAgZnJvbSAnLi9Sb3V0ZXJzL0F1ZGllbmNlc1JvdXRlcic7XG5pbXBvcnQgeyBBZ2dyZWdhdGVSb3V0ZXIgfSAgICAgIGZyb20gJy4vUm91dGVycy9BZ2dyZWdhdGVSb3V0ZXInO1xuXG5pbXBvcnQgeyBQYXJzZVNlcnZlclJFU1RDb250cm9sbGVyIH0gZnJvbSAnLi9QYXJzZVNlcnZlclJFU1RDb250cm9sbGVyJztcbmltcG9ydCAqIGFzIGNvbnRyb2xsZXJzIGZyb20gJy4vQ29udHJvbGxlcnMnO1xuLy8gTXV0YXRlIHRoZSBQYXJzZSBvYmplY3QgdG8gYWRkIHRoZSBDbG91ZCBDb2RlIGhhbmRsZXJzXG5hZGRQYXJzZUNsb3VkKCk7XG5cbi8vIFBhcnNlU2VydmVyIHdvcmtzIGxpa2UgYSBjb25zdHJ1Y3RvciBvZiBhbiBleHByZXNzIGFwcC5cbi8vIFRoZSBhcmdzIHRoYXQgd2UgdW5kZXJzdGFuZCBhcmU6XG4vLyBcImFuYWx5dGljc0FkYXB0ZXJcIjogYW4gYWRhcHRlciBjbGFzcyBmb3IgYW5hbHl0aWNzXG4vLyBcImZpbGVzQWRhcHRlclwiOiBhIGNsYXNzIGxpa2UgR3JpZFN0b3JlQWRhcHRlciBwcm92aWRpbmcgY3JlYXRlLCBnZXQsXG4vLyAgICAgICAgICAgICAgICAgYW5kIGRlbGV0ZVxuLy8gXCJsb2dnZXJBZGFwdGVyXCI6IGEgY2xhc3MgbGlrZSBXaW5zdG9uTG9nZ2VyQWRhcHRlciBwcm92aWRpbmcgaW5mbywgZXJyb3IsXG4vLyAgICAgICAgICAgICAgICAgYW5kIHF1ZXJ5XG4vLyBcImpzb25Mb2dzXCI6IGxvZyBhcyBzdHJ1Y3R1cmVkIEpTT04gb2JqZWN0c1xuLy8gXCJkYXRhYmFzZVVSSVwiOiBhIHVyaSBsaWtlIG1vbmdvZGI6Ly9sb2NhbGhvc3Q6MjcwMTcvZGJuYW1lIHRvIHRlbGwgdXNcbi8vICAgICAgICAgIHdoYXQgZGF0YWJhc2UgdGhpcyBQYXJzZSBBUEkgY29ubmVjdHMgdG8uXG4vLyBcImNsb3VkXCI6IHJlbGF0aXZlIGxvY2F0aW9uIHRvIGNsb3VkIGNvZGUgdG8gcmVxdWlyZSwgb3IgYSBmdW5jdGlvblxuLy8gICAgICAgICAgdGhhdCBpcyBnaXZlbiBhbiBpbnN0YW5jZSBvZiBQYXJzZSBhcyBhIHBhcmFtZXRlci4gIFVzZSB0aGlzIGluc3RhbmNlIG9mIFBhcnNlXG4vLyAgICAgICAgICB0byByZWdpc3RlciB5b3VyIGNsb3VkIGNvZGUgaG9va3MgYW5kIGZ1bmN0aW9ucy5cbi8vIFwiYXBwSWRcIjogdGhlIGFwcGxpY2F0aW9uIGlkIHRvIGhvc3Rcbi8vIFwibWFzdGVyS2V5XCI6IHRoZSBtYXN0ZXIga2V5IGZvciByZXF1ZXN0cyB0byB0aGlzIGFwcFxuLy8gXCJjb2xsZWN0aW9uUHJlZml4XCI6IG9wdGlvbmFsIHByZWZpeCBmb3IgZGF0YWJhc2UgY29sbGVjdGlvbiBuYW1lc1xuLy8gXCJmaWxlS2V5XCI6IG9wdGlvbmFsIGtleSBmcm9tIFBhcnNlIGRhc2hib2FyZCBmb3Igc3VwcG9ydGluZyBvbGRlciBmaWxlc1xuLy8gICAgICAgICAgICBob3N0ZWQgYnkgUGFyc2Vcbi8vIFwiY2xpZW50S2V5XCI6IG9wdGlvbmFsIGtleSBmcm9tIFBhcnNlIGRhc2hib2FyZFxuLy8gXCJkb3ROZXRLZXlcIjogb3B0aW9uYWwga2V5IGZyb20gUGFyc2UgZGFzaGJvYXJkXG4vLyBcInJlc3RBUElLZXlcIjogb3B0aW9uYWwga2V5IGZyb20gUGFyc2UgZGFzaGJvYXJkXG4vLyBcIndlYmhvb2tLZXlcIjogb3B0aW9uYWwga2V5IGZyb20gUGFyc2UgZGFzaGJvYXJkXG4vLyBcImphdmFzY3JpcHRLZXlcIjogb3B0aW9uYWwga2V5IGZyb20gUGFyc2UgZGFzaGJvYXJkXG4vLyBcInB1c2hcIjogb3B0aW9uYWwga2V5IGZyb20gY29uZmlndXJlIHB1c2hcbi8vIFwic2Vzc2lvbkxlbmd0aFwiOiBvcHRpb25hbCBsZW5ndGggaW4gc2Vjb25kcyBmb3IgaG93IGxvbmcgU2Vzc2lvbnMgc2hvdWxkIGJlIHZhbGlkIGZvclxuLy8gXCJtYXhMaW1pdFwiOiBvcHRpb25hbCB1cHBlciBib3VuZCBmb3Igd2hhdCBjYW4gYmUgc3BlY2lmaWVkIGZvciB0aGUgJ2xpbWl0JyBwYXJhbWV0ZXIgb24gcXVlcmllc1xuXG5jbGFzcyBQYXJzZVNlcnZlciB7XG5cbiAgY29uc3RydWN0b3Iob3B0aW9uczogUGFyc2VTZXJ2ZXJPcHRpb25zKSB7XG4gICAgaW5qZWN0RGVmYXVsdHMob3B0aW9ucyk7XG4gICAgY29uc3Qge1xuICAgICAgYXBwSWQgPSByZXF1aXJlZFBhcmFtZXRlcignWW91IG11c3QgcHJvdmlkZSBhbiBhcHBJZCEnKSxcbiAgICAgIG1hc3RlcktleSA9IHJlcXVpcmVkUGFyYW1ldGVyKCdZb3UgbXVzdCBwcm92aWRlIGEgbWFzdGVyS2V5IScpLFxuICAgICAgY2xvdWQsXG4gICAgICBqYXZhc2NyaXB0S2V5LFxuICAgICAgc2VydmVyVVJMID0gcmVxdWlyZWRQYXJhbWV0ZXIoJ1lvdSBtdXN0IHByb3ZpZGUgYSBzZXJ2ZXJVUkwhJyksXG4gICAgICBfX2luZGV4QnVpbGRDb21wbGV0aW9uQ2FsbGJhY2tGb3JUZXN0cyA9ICgpID0+IHt9LFxuICAgIH0gPSBvcHRpb25zO1xuICAgIC8vIEluaXRpYWxpemUgdGhlIG5vZGUgY2xpZW50IFNESyBhdXRvbWF0aWNhbGx5XG4gICAgUGFyc2UuaW5pdGlhbGl6ZShhcHBJZCwgamF2YXNjcmlwdEtleSB8fCAndW51c2VkJywgbWFzdGVyS2V5KTtcbiAgICBQYXJzZS5zZXJ2ZXJVUkwgPSBzZXJ2ZXJVUkw7XG5cbiAgICBjb25zdCBhbGxDb250cm9sbGVycyA9IGNvbnRyb2xsZXJzLmdldENvbnRyb2xsZXJzKG9wdGlvbnMpO1xuXG4gICAgY29uc3Qge1xuICAgICAgbG9nZ2VyQ29udHJvbGxlcixcbiAgICAgIGRhdGFiYXNlQ29udHJvbGxlcixcbiAgICAgIGhvb2tzQ29udHJvbGxlcixcbiAgICB9ID0gYWxsQ29udHJvbGxlcnM7XG4gICAgdGhpcy5jb25maWcgPSBDb25maWcucHV0KE9iamVjdC5hc3NpZ24oe30sIG9wdGlvbnMsIGFsbENvbnRyb2xsZXJzKSk7XG5cbiAgICBsb2dnaW5nLnNldExvZ2dlcihsb2dnZXJDb250cm9sbGVyKTtcbiAgICBjb25zdCBkYkluaXRQcm9taXNlID0gZGF0YWJhc2VDb250cm9sbGVyLnBlcmZvcm1Jbml0aWFsaXphdGlvbigpO1xuICAgIGhvb2tzQ29udHJvbGxlci5sb2FkKCk7XG5cbiAgICAvLyBOb3RlOiBUZXN0cyB3aWxsIHN0YXJ0IHRvIGZhaWwgaWYgYW55IHZhbGlkYXRpb24gaGFwcGVucyBhZnRlciB0aGlzIGlzIGNhbGxlZC5cbiAgICBpZiAocHJvY2Vzcy5lbnYuVEVTVElORykge1xuICAgICAgX19pbmRleEJ1aWxkQ29tcGxldGlvbkNhbGxiYWNrRm9yVGVzdHMoZGJJbml0UHJvbWlzZSk7XG4gICAgfVxuXG4gICAgaWYgKGNsb3VkKSB7XG4gICAgICBhZGRQYXJzZUNsb3VkKCk7XG4gICAgICBpZiAodHlwZW9mIGNsb3VkID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIGNsb3VkKFBhcnNlKVxuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgY2xvdWQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJlcXVpcmUocGF0aC5yZXNvbHZlKHByb2Nlc3MuY3dkKCksIGNsb3VkKSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBcImFyZ3VtZW50ICdjbG91ZCcgbXVzdCBlaXRoZXIgYmUgYSBzdHJpbmcgb3IgYSBmdW5jdGlvblwiO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGdldCBhcHAoKSB7XG4gICAgaWYgKCF0aGlzLl9hcHApIHtcbiAgICAgIHRoaXMuX2FwcCA9IFBhcnNlU2VydmVyLmFwcCh0aGlzLmNvbmZpZyk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9hcHA7XG4gIH1cblxuICBoYW5kbGVTaHV0ZG93bigpIHtcbiAgICBjb25zdCB7IGFkYXB0ZXIgfSA9IHRoaXMuY29uZmlnLmRhdGFiYXNlQ29udHJvbGxlcjtcbiAgICBpZiAoYWRhcHRlciAmJiB0eXBlb2YgYWRhcHRlci5oYW5kbGVTaHV0ZG93biA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgYWRhcHRlci5oYW5kbGVTaHV0ZG93bigpO1xuICAgIH1cbiAgfVxuXG4gIHN0YXRpYyBhcHAoe21heFVwbG9hZFNpemUgPSAnMjBtYicsIGFwcElkfSkge1xuICAgIC8vIFRoaXMgYXBwIHNlcnZlcyB0aGUgUGFyc2UgQVBJIGRpcmVjdGx5LlxuICAgIC8vIEl0J3MgdGhlIGVxdWl2YWxlbnQgb2YgaHR0cHM6Ly9hcGkucGFyc2UuY29tLzEgaW4gdGhlIGhvc3RlZCBQYXJzZSBBUEkuXG4gICAgdmFyIGFwaSA9IGV4cHJlc3MoKTtcbiAgICAvL2FwaS51c2UoXCIvYXBwc1wiLCBleHByZXNzLnN0YXRpYyhfX2Rpcm5hbWUgKyBcIi9wdWJsaWNcIikpO1xuICAgIC8vIEZpbGUgaGFuZGxpbmcgbmVlZHMgdG8gYmUgYmVmb3JlIGRlZmF1bHQgbWlkZGxld2FyZXMgYXJlIGFwcGxpZWRcbiAgICBhcGkudXNlKCcvJywgbWlkZGxld2FyZXMuYWxsb3dDcm9zc0RvbWFpbiwgbmV3IEZpbGVzUm91dGVyKCkuZXhwcmVzc1JvdXRlcih7XG4gICAgICBtYXhVcGxvYWRTaXplOiBtYXhVcGxvYWRTaXplXG4gICAgfSkpO1xuXG4gICAgYXBpLnVzZSgnL2hlYWx0aCcsIChmdW5jdGlvbihyZXEsIHJlcykge1xuICAgICAgcmVzLmpzb24oe1xuICAgICAgICBzdGF0dXM6ICdvaydcbiAgICAgIH0pO1xuICAgIH0pKTtcblxuICAgIGFwaS51c2UoJy8nLCBib2R5UGFyc2VyLnVybGVuY29kZWQoe2V4dGVuZGVkOiBmYWxzZX0pLCBuZXcgUHVibGljQVBJUm91dGVyKCkuZXhwcmVzc1JvdXRlcigpKTtcblxuICAgIGFwaS51c2UoYm9keVBhcnNlci5qc29uKHsgJ3R5cGUnOiAnKi8qJyAsIGxpbWl0OiBtYXhVcGxvYWRTaXplIH0pKTtcbiAgICBhcGkudXNlKG1pZGRsZXdhcmVzLmFsbG93Q3Jvc3NEb21haW4pO1xuICAgIGFwaS51c2UobWlkZGxld2FyZXMuYWxsb3dNZXRob2RPdmVycmlkZSk7XG4gICAgYXBpLnVzZShtaWRkbGV3YXJlcy5oYW5kbGVQYXJzZUhlYWRlcnMpO1xuXG4gICAgY29uc3QgYXBwUm91dGVyID0gUGFyc2VTZXJ2ZXIucHJvbWlzZVJvdXRlcih7IGFwcElkIH0pO1xuICAgIGFwaS51c2UoYXBwUm91dGVyLmV4cHJlc3NSb3V0ZXIoKSk7XG5cbiAgICBhcGkudXNlKG1pZGRsZXdhcmVzLmhhbmRsZVBhcnNlRXJyb3JzKTtcblxuICAgIC8vIHJ1biB0aGUgZm9sbG93aW5nIHdoZW4gbm90IHRlc3RpbmdcbiAgICBpZiAoIXByb2Nlc3MuZW52LlRFU1RJTkcpIHtcbiAgICAgIC8vVGhpcyBjYXVzZXMgdGVzdHMgdG8gc3BldyBzb21lIHVzZWxlc3Mgd2FybmluZ3MsIHNvIGRpc2FibGUgaW4gdGVzdFxuICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICAgIHByb2Nlc3Mub24oJ3VuY2F1Z2h0RXhjZXB0aW9uJywgKGVycikgPT4ge1xuICAgICAgICBpZiAoZXJyLmNvZGUgPT09IFwiRUFERFJJTlVTRVwiKSB7IC8vIHVzZXItZnJpZW5kbHkgbWVzc2FnZSBmb3IgdGhpcyBjb21tb24gZXJyb3JcbiAgICAgICAgICBwcm9jZXNzLnN0ZGVyci53cml0ZShgVW5hYmxlIHRvIGxpc3RlbiBvbiBwb3J0ICR7ZXJyLnBvcnR9LiBUaGUgcG9ydCBpcyBhbHJlYWR5IGluIHVzZS5gKTtcbiAgICAgICAgICBwcm9jZXNzLmV4aXQoMCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIC8vIHZlcmlmeSB0aGUgc2VydmVyIHVybCBhZnRlciBhICdtb3VudCcgZXZlbnQgaXMgcmVjZWl2ZWRcbiAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgICBhcGkub24oJ21vdW50JywgZnVuY3Rpb24oKSB7XG4gICAgICAgIFBhcnNlU2VydmVyLnZlcmlmeVNlcnZlclVybCgpO1xuICAgICAgfSk7XG4gICAgfVxuICAgIGlmIChwcm9jZXNzLmVudi5QQVJTRV9TRVJWRVJfRU5BQkxFX0VYUEVSSU1FTlRBTF9ESVJFQ1RfQUNDRVNTID09PSAnMScpIHtcbiAgICAgIFBhcnNlLkNvcmVNYW5hZ2VyLnNldFJFU1RDb250cm9sbGVyKFBhcnNlU2VydmVyUkVTVENvbnRyb2xsZXIoYXBwSWQsIGFwcFJvdXRlcikpO1xuICAgIH1cbiAgICByZXR1cm4gYXBpO1xuICB9XG5cbiAgc3RhdGljIHByb21pc2VSb3V0ZXIoe2FwcElkfSkge1xuICAgIGNvbnN0IHJvdXRlcnMgPSBbXG4gICAgICBuZXcgQ2xhc3Nlc1JvdXRlcigpLFxuICAgICAgbmV3IFVzZXJzUm91dGVyKCksXG4gICAgICBuZXcgU2Vzc2lvbnNSb3V0ZXIoKSxcbiAgICAgIG5ldyBSb2xlc1JvdXRlcigpLFxuICAgICAgbmV3IEFuYWx5dGljc1JvdXRlcigpLFxuICAgICAgbmV3IEluc3RhbGxhdGlvbnNSb3V0ZXIoKSxcbiAgICAgIG5ldyBGdW5jdGlvbnNSb3V0ZXIoKSxcbiAgICAgIG5ldyBTY2hlbWFzUm91dGVyKCksXG4gICAgICBuZXcgUHVzaFJvdXRlcigpLFxuICAgICAgbmV3IExvZ3NSb3V0ZXIoKSxcbiAgICAgIG5ldyBJQVBWYWxpZGF0aW9uUm91dGVyKCksXG4gICAgICBuZXcgRmVhdHVyZXNSb3V0ZXIoKSxcbiAgICAgIG5ldyBHbG9iYWxDb25maWdSb3V0ZXIoKSxcbiAgICAgIG5ldyBQdXJnZVJvdXRlcigpLFxuICAgICAgbmV3IEhvb2tzUm91dGVyKCksXG4gICAgICBuZXcgQ2xvdWRDb2RlUm91dGVyKCksXG4gICAgICBuZXcgQXVkaWVuY2VzUm91dGVyKCksXG4gICAgICBuZXcgQWdncmVnYXRlUm91dGVyKClcbiAgICBdO1xuXG4gICAgY29uc3Qgcm91dGVzID0gcm91dGVycy5yZWR1Y2UoKG1lbW8sIHJvdXRlcikgPT4ge1xuICAgICAgcmV0dXJuIG1lbW8uY29uY2F0KHJvdXRlci5yb3V0ZXMpO1xuICAgIH0sIFtdKTtcblxuICAgIGNvbnN0IGFwcFJvdXRlciA9IG5ldyBQcm9taXNlUm91dGVyKHJvdXRlcywgYXBwSWQpO1xuXG4gICAgYmF0Y2gubW91bnRPbnRvKGFwcFJvdXRlcik7XG4gICAgcmV0dXJuIGFwcFJvdXRlcjtcbiAgfVxuXG4gIHN0YXJ0KG9wdGlvbnM6IFBhcnNlU2VydmVyT3B0aW9ucywgY2FsbGJhY2s6ID8oKT0+dm9pZCkge1xuICAgIGNvbnN0IGFwcCA9IGV4cHJlc3MoKTtcbiAgICBpZiAob3B0aW9ucy5taWRkbGV3YXJlKSB7XG4gICAgICBsZXQgbWlkZGxld2FyZTtcbiAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5taWRkbGV3YXJlID09ICdzdHJpbmcnKSB7XG4gICAgICAgIG1pZGRsZXdhcmUgPSByZXF1aXJlKHBhdGgucmVzb2x2ZShwcm9jZXNzLmN3ZCgpLCBvcHRpb25zLm1pZGRsZXdhcmUpKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG1pZGRsZXdhcmUgPSBvcHRpb25zLm1pZGRsZXdhcmU7IC8vIHVzZSBhcy1pcyBsZXQgZXhwcmVzcyBmYWlsXG4gICAgICB9XG4gICAgICBhcHAudXNlKG1pZGRsZXdhcmUpO1xuICAgIH1cblxuICAgIGFwcC51c2Uob3B0aW9ucy5tb3VudFBhdGgsIHRoaXMuYXBwKTtcbiAgICBjb25zdCBzZXJ2ZXIgPSBhcHAubGlzdGVuKG9wdGlvbnMucG9ydCwgb3B0aW9ucy5ob3N0LCBjYWxsYmFjayk7XG4gICAgdGhpcy5zZXJ2ZXIgPSBzZXJ2ZXI7XG5cbiAgICBpZiAob3B0aW9ucy5zdGFydExpdmVRdWVyeVNlcnZlciB8fCBvcHRpb25zLmxpdmVRdWVyeVNlcnZlck9wdGlvbnMpIHtcbiAgICAgIHRoaXMubGl2ZVF1ZXJ5U2VydmVyID0gUGFyc2VTZXJ2ZXIuY3JlYXRlTGl2ZVF1ZXJ5U2VydmVyKHNlcnZlciwgb3B0aW9ucy5saXZlUXVlcnlTZXJ2ZXJPcHRpb25zKTtcbiAgICB9XG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICBpZiAoIXByb2Nlc3MuZW52LlRFU1RJTkcpIHtcbiAgICAgIGNvbmZpZ3VyZUxpc3RlbmVycyh0aGlzKTtcbiAgICB9XG4gICAgdGhpcy5leHByZXNzQXBwID0gYXBwO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgc3RhdGljIHN0YXJ0KG9wdGlvbnM6IFBhcnNlU2VydmVyT3B0aW9ucywgY2FsbGJhY2s6ID8oKT0+dm9pZCkge1xuICAgIGNvbnN0IHBhcnNlU2VydmVyID0gbmV3IFBhcnNlU2VydmVyKG9wdGlvbnMpO1xuICAgIHJldHVybiBwYXJzZVNlcnZlci5zdGFydChvcHRpb25zLCBjYWxsYmFjayk7XG4gIH1cblxuICBzdGF0aWMgY3JlYXRlTGl2ZVF1ZXJ5U2VydmVyKGh0dHBTZXJ2ZXIsIGNvbmZpZzogTGl2ZVF1ZXJ5U2VydmVyT3B0aW9ucykge1xuICAgIGlmICghaHR0cFNlcnZlciB8fCAoY29uZmlnICYmIGNvbmZpZy5wb3J0KSkge1xuICAgICAgdmFyIGFwcCA9IGV4cHJlc3MoKTtcbiAgICAgIGh0dHBTZXJ2ZXIgPSByZXF1aXJlKCdodHRwJykuY3JlYXRlU2VydmVyKGFwcCk7XG4gICAgICBodHRwU2VydmVyLmxpc3Rlbihjb25maWcucG9ydCk7XG4gICAgfVxuICAgIHJldHVybiBuZXcgUGFyc2VMaXZlUXVlcnlTZXJ2ZXIoaHR0cFNlcnZlciwgY29uZmlnKTtcbiAgfVxuXG4gIHN0YXRpYyB2ZXJpZnlTZXJ2ZXJVcmwoY2FsbGJhY2spIHtcbiAgICAvLyBwZXJmb3JtIGEgaGVhbHRoIGNoZWNrIG9uIHRoZSBzZXJ2ZXJVUkwgdmFsdWVcbiAgICBpZihQYXJzZS5zZXJ2ZXJVUkwpIHtcbiAgICAgIGNvbnN0IHJlcXVlc3QgPSByZXF1aXJlKCdyZXF1ZXN0Jyk7XG4gICAgICByZXF1ZXN0KFBhcnNlLnNlcnZlclVSTC5yZXBsYWNlKC9cXC8kLywgXCJcIikgKyBcIi9oZWFsdGhcIiwgZnVuY3Rpb24gKGVycm9yLCByZXNwb25zZSwgYm9keSkge1xuICAgICAgICBsZXQganNvbjtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBqc29uID0gSlNPTi5wYXJzZShib2R5KTtcbiAgICAgICAgfSBjYXRjaChlKSB7XG4gICAgICAgICAganNvbiA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGVycm9yIHx8IHJlc3BvbnNlLnN0YXR1c0NvZGUgIT09IDIwMCB8fCAhanNvbiB8fCBqc29uICYmIGpzb24uc3RhdHVzICE9PSAnb2snKSB7XG4gICAgICAgICAgLyogZXNsaW50LWRpc2FibGUgbm8tY29uc29sZSAqL1xuICAgICAgICAgIGNvbnNvbGUud2FybihgXFxuV0FSTklORywgVW5hYmxlIHRvIGNvbm5lY3QgdG8gJyR7UGFyc2Uuc2VydmVyVVJMfScuYCArXG4gICAgICAgICAgICBgIENsb3VkIGNvZGUgYW5kIHB1c2ggbm90aWZpY2F0aW9ucyBtYXkgYmUgdW5hdmFpbGFibGUhXFxuYCk7XG4gICAgICAgICAgLyogZXNsaW50LWVuYWJsZSBuby1jb25zb2xlICovXG4gICAgICAgICAgaWYoY2FsbGJhY2spIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKGZhbHNlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYoY2FsbGJhY2spIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKHRydWUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIGFkZFBhcnNlQ2xvdWQoKSB7XG4gIGNvbnN0IFBhcnNlQ2xvdWQgPSByZXF1aXJlKFwiLi9jbG91ZC1jb2RlL1BhcnNlLkNsb3VkXCIpO1xuICBPYmplY3QuYXNzaWduKFBhcnNlLkNsb3VkLCBQYXJzZUNsb3VkKTtcbiAgZ2xvYmFsLlBhcnNlID0gUGFyc2U7XG59XG5cbmZ1bmN0aW9uIGluamVjdERlZmF1bHRzKG9wdGlvbnM6IFBhcnNlU2VydmVyT3B0aW9ucykge1xuICBPYmplY3Qua2V5cyhkZWZhdWx0cykuZm9yRWFjaCgoa2V5KSA9PiB7XG4gICAgaWYgKCFvcHRpb25zLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgIG9wdGlvbnNba2V5XSA9IGRlZmF1bHRzW2tleV07XG4gICAgfVxuICB9KTtcblxuICBpZiAoIW9wdGlvbnMuaGFzT3duUHJvcGVydHkoJ3NlcnZlclVSTCcpKSB7XG4gICAgb3B0aW9ucy5zZXJ2ZXJVUkwgPSBgaHR0cDovL2xvY2FsaG9zdDoke29wdGlvbnMucG9ydH0ke29wdGlvbnMubW91bnRQYXRofWA7XG4gIH1cblxuICBvcHRpb25zLnVzZXJTZW5zaXRpdmVGaWVsZHMgPSBBcnJheS5mcm9tKG5ldyBTZXQob3B0aW9ucy51c2VyU2Vuc2l0aXZlRmllbGRzLmNvbmNhdChcbiAgICBkZWZhdWx0cy51c2VyU2Vuc2l0aXZlRmllbGRzLFxuICAgIG9wdGlvbnMudXNlclNlbnNpdGl2ZUZpZWxkc1xuICApKSk7XG5cbiAgb3B0aW9ucy5tYXN0ZXJLZXlJcHMgPSBBcnJheS5mcm9tKG5ldyBTZXQob3B0aW9ucy5tYXN0ZXJLZXlJcHMuY29uY2F0KFxuICAgIGRlZmF1bHRzLm1hc3RlcktleUlwcyxcbiAgICBvcHRpb25zLm1hc3RlcktleUlwc1xuICApKSk7XG59XG5cbi8vIFRob3NlIGNhbid0IGJlIHRlc3RlZCBhcyBpdCByZXF1aXJlcyBhIHN1YnByb2Nlc3Ncbi8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG5mdW5jdGlvbiBjb25maWd1cmVMaXN0ZW5lcnMocGFyc2VTZXJ2ZXIpIHtcbiAgY29uc3Qgc2VydmVyID0gcGFyc2VTZXJ2ZXIuc2VydmVyO1xuICBjb25zdCBzb2NrZXRzID0ge307XG4gIC8qIEN1cnJlbnRseSwgZXhwcmVzcyBkb2Vzbid0IHNodXQgZG93biBpbW1lZGlhdGVseSBhZnRlciByZWNlaXZpbmcgU0lHSU5UL1NJR1RFUk0gaWYgaXQgaGFzIGNsaWVudCBjb25uZWN0aW9ucyB0aGF0IGhhdmVuJ3QgdGltZWQgb3V0LiAoVGhpcyBpcyBhIGtub3duIGlzc3VlIHdpdGggbm9kZSAtIGh0dHBzOi8vZ2l0aHViLmNvbS9ub2RlanMvbm9kZS9pc3N1ZXMvMjY0MilcbiAgICBUaGlzIGZ1bmN0aW9uLCBhbG9uZyB3aXRoIGBkZXN0cm95QWxpdmVDb25uZWN0aW9ucygpYCwgaW50ZW5kIHRvIGZpeCB0aGlzIGJlaGF2aW9yIHN1Y2ggdGhhdCBwYXJzZSBzZXJ2ZXIgd2lsbCBjbG9zZSBhbGwgb3BlbiBjb25uZWN0aW9ucyBhbmQgaW5pdGlhdGUgdGhlIHNodXRkb3duIHByb2Nlc3MgYXMgc29vbiBhcyBpdCByZWNlaXZlcyBhIFNJR0lOVC9TSUdURVJNIHNpZ25hbC4gKi9cbiAgc2VydmVyLm9uKCdjb25uZWN0aW9uJywgKHNvY2tldCkgPT4ge1xuICAgIGNvbnN0IHNvY2tldElkID0gc29ja2V0LnJlbW90ZUFkZHJlc3MgKyAnOicgKyBzb2NrZXQucmVtb3RlUG9ydDtcbiAgICBzb2NrZXRzW3NvY2tldElkXSA9IHNvY2tldDtcbiAgICBzb2NrZXQub24oJ2Nsb3NlJywgKCkgPT4ge1xuICAgICAgZGVsZXRlIHNvY2tldHNbc29ja2V0SWRdO1xuICAgIH0pO1xuICB9KTtcblxuICBjb25zdCBkZXN0cm95QWxpdmVDb25uZWN0aW9ucyA9IGZ1bmN0aW9uKCkge1xuICAgIGZvciAoY29uc3Qgc29ja2V0SWQgaW4gc29ja2V0cykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgc29ja2V0c1tzb2NrZXRJZF0uZGVzdHJveSgpO1xuICAgICAgfSBjYXRjaCAoZSkgeyAvKiAqLyB9XG4gICAgfVxuICB9XG5cbiAgY29uc3QgaGFuZGxlU2h1dGRvd24gPSBmdW5jdGlvbigpIHtcbiAgICBwcm9jZXNzLnN0ZG91dC53cml0ZSgnVGVybWluYXRpb24gc2lnbmFsIHJlY2VpdmVkLiBTaHV0dGluZyBkb3duLicpO1xuICAgIGRlc3Ryb3lBbGl2ZUNvbm5lY3Rpb25zKCk7XG4gICAgc2VydmVyLmNsb3NlKCk7XG4gICAgcGFyc2VTZXJ2ZXIuaGFuZGxlU2h1dGRvd24oKTtcbiAgfTtcbiAgcHJvY2Vzcy5vbignU0lHVEVSTScsIGhhbmRsZVNodXRkb3duKTtcbiAgcHJvY2Vzcy5vbignU0lHSU5UJywgaGFuZGxlU2h1dGRvd24pO1xufVxuXG5leHBvcnQgZGVmYXVsdCBQYXJzZVNlcnZlcjtcbiJdfQ==
609
+ var _default = exports.default = ParseServer;
610
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfZGVmYXVsdHMiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsImxvZ2dpbmciLCJfaW50ZXJvcFJlcXVpcmVXaWxkY2FyZCIsIl9Db25maWciLCJfUHJvbWlzZVJvdXRlciIsIl9yZXF1aXJlZFBhcmFtZXRlciIsIl9BbmFseXRpY3NSb3V0ZXIiLCJfQ2xhc3Nlc1JvdXRlciIsIl9GZWF0dXJlc1JvdXRlciIsIl9GaWxlc1JvdXRlciIsIl9GdW5jdGlvbnNSb3V0ZXIiLCJfR2xvYmFsQ29uZmlnUm91dGVyIiwiX0dyYXBoUUxSb3V0ZXIiLCJfSG9va3NSb3V0ZXIiLCJfSUFQVmFsaWRhdGlvblJvdXRlciIsIl9JbnN0YWxsYXRpb25zUm91dGVyIiwiX0xvZ3NSb3V0ZXIiLCJfUGFyc2VMaXZlUXVlcnlTZXJ2ZXIiLCJfUGFnZXNSb3V0ZXIiLCJfUHVibGljQVBJUm91dGVyIiwiX1B1c2hSb3V0ZXIiLCJfQ2xvdWRDb2RlUm91dGVyIiwiX1JvbGVzUm91dGVyIiwiX1NjaGVtYXNSb3V0ZXIiLCJfU2Vzc2lvbnNSb3V0ZXIiLCJfVXNlcnNSb3V0ZXIiLCJfUHVyZ2VSb3V0ZXIiLCJfQXVkaWVuY2VzUm91dGVyIiwiX0FnZ3JlZ2F0ZVJvdXRlciIsIl9QYXJzZVNlcnZlclJFU1RDb250cm9sbGVyIiwiY29udHJvbGxlcnMiLCJfUGFyc2VHcmFwaFFMU2VydmVyIiwiX1NlY3VyaXR5Um91dGVyIiwiX0NoZWNrUnVubmVyIiwiX0RlcHJlY2F0b3IiLCJfRGVmaW5lZFNjaGVtYXMiLCJfRGVmaW5pdGlvbnMiLCJfVGVzdFV0aWxzIiwiZSIsInQiLCJXZWFrTWFwIiwiciIsIm4iLCJfX2VzTW9kdWxlIiwibyIsImkiLCJmIiwiX19wcm90b19fIiwiZGVmYXVsdCIsImhhcyIsImdldCIsInNldCIsImhhc093blByb3BlcnR5IiwiY2FsbCIsIk9iamVjdCIsImRlZmluZVByb3BlcnR5IiwiZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yIiwiYmF0Y2giLCJleHByZXNzIiwibWlkZGxld2FyZXMiLCJQYXJzZSIsInBhcnNlIiwicGF0aCIsImZzIiwiYWRkUGFyc2VDbG91ZCIsImNvbm5lY3Rpb25zIiwiQ29ubmVjdGlvbnMiLCJQYXJzZVNlcnZlciIsImNvbnN0cnVjdG9yIiwib3B0aW9ucyIsIkRlcHJlY2F0b3IiLCJzY2FuUGFyc2VTZXJ2ZXJPcHRpb25zIiwiaW50ZXJmYWNlcyIsIkpTT04iLCJzdHJpbmdpZnkiLCJPcHRpb25zRGVmaW5pdGlvbnMiLCJnZXRWYWxpZE9iamVjdCIsInJvb3QiLCJyZXN1bHQiLCJrZXkiLCJwcm90b3R5cGUiLCJ0eXBlIiwiZW5kc1dpdGgiLCJzbGljZSIsIm9wdGlvbnNCbHVlcHJpbnQiLCJ2YWxpZGF0ZUtleU5hbWVzIiwib3JpZ2luYWwiLCJyZWYiLCJuYW1lIiwicHJlZml4IiwicHVzaCIsInJlcyIsIkFycmF5IiwiaXNBcnJheSIsImZvckVhY2giLCJpdGVtIiwiaWR4IiwiY29uY2F0IiwiZGlmZiIsImxlbmd0aCIsImxvZ2dlciIsImVycm9yIiwiam9pbiIsImluamVjdERlZmF1bHRzIiwiYXBwSWQiLCJyZXF1aXJlZFBhcmFtZXRlciIsIm1hc3RlcktleSIsImphdmFzY3JpcHRLZXkiLCJzZXJ2ZXJVUkwiLCJpbml0aWFsaXplIiwiQ29uZmlnIiwidmFsaWRhdGVPcHRpb25zIiwiYWxsQ29udHJvbGxlcnMiLCJnZXRDb250cm9sbGVycyIsInN0YXRlIiwiY29uZmlnIiwicHV0IiwiYXNzaWduIiwibWFzdGVyS2V5SXBzU3RvcmUiLCJNYXAiLCJtYWludGVuYW5jZUtleUlwc1N0b3JlIiwic2V0TG9nZ2VyIiwibG9nZ2VyQ29udHJvbGxlciIsInN0YXJ0IiwiZGF0YWJhc2VDb250cm9sbGVyIiwiaG9va3NDb250cm9sbGVyIiwiY2FjaGVDb250cm9sbGVyIiwiY2xvdWQiLCJzZWN1cml0eSIsInNjaGVtYSIsImxpdmVRdWVyeUNvbnRyb2xsZXIiLCJwZXJmb3JtSW5pdGlhbGl6YXRpb24iLCJjb2RlIiwiRXJyb3IiLCJEVVBMSUNBVEVfVkFMVUUiLCJwdXNoQ29udHJvbGxlciIsImdldFB1c2hDb250cm9sbGVyIiwibG9hZCIsInN0YXJ0dXBQcm9taXNlcyIsImxvYWRNYXN0ZXJLZXkiLCJEZWZpbmVkU2NoZW1hcyIsImV4ZWN1dGUiLCJhZGFwdGVyIiwiY29ubmVjdCIsIlByb21pc2UiLCJhbGwiLCJyZXNvbHZlIiwianNvbiIsInByb2Nlc3MiLCJlbnYiLCJucG1fcGFja2FnZV9qc29uIiwibnBtX3BhY2thZ2VfdHlwZSIsImN3ZCIsInNldFRpbWVvdXQiLCJlbmFibGVDaGVjayIsImVuYWJsZUNoZWNrTG9nIiwiQ2hlY2tSdW5uZXIiLCJydW4iLCJjb25zb2xlIiwiYXBwIiwiX2FwcCIsImhhbmRsZVNodXRkb3duIiwic2VydmVyQ2xvc2VQcm9taXNlIiwicmVzb2x2aW5nUHJvbWlzZSIsImxpdmVRdWVyeVNlcnZlckNsb3NlUHJvbWlzZSIsInByb21pc2VzIiwic2VydmVyIiwiY2xvc2UiLCJsaXZlUXVlcnlTZXJ2ZXIiLCJkYXRhYmFzZUFkYXB0ZXIiLCJmaWxlQWRhcHRlciIsImZpbGVzQ29udHJvbGxlciIsImNhY2hlQWRhcHRlciIsInNodXRkb3duIiwiZGVzdHJveUFsbCIsInNlcnZlckNsb3NlQ29tcGxldGUiLCJhcHBseVJlcXVlc3RDb250ZXh0TWlkZGxld2FyZSIsImFwaSIsInJlcXVlc3RDb250ZXh0TWlkZGxld2FyZSIsInVzZSIsIm1heFVwbG9hZFNpemUiLCJkaXJlY3RBY2Nlc3MiLCJwYWdlcyIsInJhdGVMaW1pdCIsImFsbG93Q3Jvc3NEb21haW4iLCJhbGxvd0RvdWJsZUZvcndhcmRTbGFzaCIsIkZpbGVzUm91dGVyIiwiZXhwcmVzc1JvdXRlciIsInJlcSIsInN0YXR1cyIsInVybGVuY29kZWQiLCJleHRlbmRlZCIsImVuYWJsZVJvdXRlciIsIlBhZ2VzUm91dGVyIiwiUHVibGljQVBJUm91dGVyIiwibGltaXQiLCJhbGxvd01ldGhvZE92ZXJyaWRlIiwiaGFuZGxlUGFyc2VIZWFkZXJzIiwicm91dGVzIiwicm91dGUiLCJhZGRSYXRlTGltaXQiLCJoYW5kbGVQYXJzZVNlc3Npb24iLCJhcHBSb3V0ZXIiLCJwcm9taXNlUm91dGVyIiwiaGFuZGxlUGFyc2VFcnJvcnMiLCJURVNUSU5HIiwib24iLCJlcnIiLCJzdGRlcnIiLCJ3cml0ZSIsInBvcnQiLCJleGl0IiwibWVzc2FnZSIsInN0YWNrIiwiUEFSU0VfU0VSVkVSX0VOQUJMRV9FWFBFUklNRU5UQUxfRElSRUNUX0FDQ0VTUyIsIkNvcmVNYW5hZ2VyIiwic2V0UkVTVENvbnRyb2xsZXIiLCJQYXJzZVNlcnZlclJFU1RDb250cm9sbGVyIiwicm91dGVycyIsIkNsYXNzZXNSb3V0ZXIiLCJVc2Vyc1JvdXRlciIsIlNlc3Npb25zUm91dGVyIiwiUm9sZXNSb3V0ZXIiLCJBbmFseXRpY3NSb3V0ZXIiLCJJbnN0YWxsYXRpb25zUm91dGVyIiwiRnVuY3Rpb25zUm91dGVyIiwiU2NoZW1hc1JvdXRlciIsIlB1c2hSb3V0ZXIiLCJMb2dzUm91dGVyIiwiSUFQVmFsaWRhdGlvblJvdXRlciIsIkZlYXR1cmVzUm91dGVyIiwiR2xvYmFsQ29uZmlnUm91dGVyIiwiR3JhcGhRTFJvdXRlciIsIlB1cmdlUm91dGVyIiwiSG9va3NSb3V0ZXIiLCJDbG91ZENvZGVSb3V0ZXIiLCJBdWRpZW5jZXNSb3V0ZXIiLCJBZ2dyZWdhdGVSb3V0ZXIiLCJTZWN1cml0eVJvdXRlciIsInJlZHVjZSIsIm1lbW8iLCJyb3V0ZXIiLCJQcm9taXNlUm91dGVyIiwibW91bnRPbnRvIiwic3RhcnRBcHAiLCJtaWRkbGV3YXJlIiwibW91bnRQYXRoIiwibW91bnRHcmFwaFFMIiwibW91bnRQbGF5Z3JvdW5kIiwiZ3JhcGhRTEN1c3RvbVR5cGVEZWZzIiwidW5kZWZpbmVkIiwiZ3JhcGhRTFNjaGVtYSIsInJlYWRGaWxlU3luYyIsInBhcnNlR3JhcGhRTFNlcnZlciIsIlBhcnNlR3JhcGhRTFNlcnZlciIsImdyYXBoUUxQYXRoIiwicGxheWdyb3VuZFBhdGgiLCJhcHBseUdyYXBoUUwiLCJhcHBseVBsYXlncm91bmQiLCJsaXN0ZW4iLCJob3N0IiwidHJhY2siLCJzdGFydExpdmVRdWVyeVNlcnZlciIsImxpdmVRdWVyeVNlcnZlck9wdGlvbnMiLCJjcmVhdGVMaXZlUXVlcnlTZXJ2ZXIiLCJ0cnVzdFByb3h5IiwiY29uZmlndXJlTGlzdGVuZXJzIiwidmVyaWZ5U2VydmVyVXJsIiwiZXhwcmVzc0FwcCIsInBhcnNlU2VydmVyIiwiaHR0cFNlcnZlciIsImNyZWF0ZVNlcnZlciIsIlBhcnNlTGl2ZVF1ZXJ5U2VydmVyIiwiaXNWYWxpZEh0dHBVcmwiLCJzdHJpbmciLCJ1cmwiLCJVUkwiLCJfIiwicHJvdG9jb2wiLCJyZXBsYWNlIiwid2FybiIsInJlcXVlc3QiLCJyZXNwb25zZSIsImNhdGNoIiwiZGF0YSIsInJldHJ5IiwiaGVhZGVycyIsIlBhcnNlQ2xvdWQiLCJjb25mIiwiYXBwbGljYXRpb25JZCIsIm5ld1ZhbCIsImNvbmZpZ3VyYWJsZSIsIkNsb3VkIiwiZ2xvYmFsIiwia2V5cyIsImRlZmF1bHRzIiwicmVnZXgiLCJtYXRjaCIsInVzZXJTZW5zaXRpdmVGaWVsZHMiLCJmcm9tIiwiU2V0IiwicHJvdGVjdGVkRmllbGRzIiwiX1VzZXIiLCJjIiwiY3VyIiwidW5xIiwic3Rkb3V0IiwiX2RlZmF1bHQiLCJleHBvcnRzIl0sInNvdXJjZXMiOlsiLi4vc3JjL1BhcnNlU2VydmVyLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIFBhcnNlU2VydmVyIC0gb3Blbi1zb3VyY2UgY29tcGF0aWJsZSBBUEkgU2VydmVyIGZvciBQYXJzZSBhcHBzXG5cbnZhciBiYXRjaCA9IHJlcXVpcmUoJy4vYmF0Y2gnKSxcbiAgZXhwcmVzcyA9IHJlcXVpcmUoJ2V4cHJlc3MnKSxcbiAgbWlkZGxld2FyZXMgPSByZXF1aXJlKCcuL21pZGRsZXdhcmVzJyksXG4gIFBhcnNlID0gcmVxdWlyZSgncGFyc2Uvbm9kZScpLlBhcnNlLFxuICB7IHBhcnNlIH0gPSByZXF1aXJlKCdncmFwaHFsJyksXG4gIHBhdGggPSByZXF1aXJlKCdwYXRoJyksXG4gIGZzID0gcmVxdWlyZSgnZnMnKTtcblxuaW1wb3J0IHsgUGFyc2VTZXJ2ZXJPcHRpb25zLCBMaXZlUXVlcnlTZXJ2ZXJPcHRpb25zIH0gZnJvbSAnLi9PcHRpb25zJztcbmltcG9ydCBkZWZhdWx0cyBmcm9tICcuL2RlZmF1bHRzJztcbmltcG9ydCAqIGFzIGxvZ2dpbmcgZnJvbSAnLi9sb2dnZXInO1xuaW1wb3J0IENvbmZpZyBmcm9tICcuL0NvbmZpZyc7XG5pbXBvcnQgUHJvbWlzZVJvdXRlciBmcm9tICcuL1Byb21pc2VSb3V0ZXInO1xuaW1wb3J0IHJlcXVpcmVkUGFyYW1ldGVyIGZyb20gJy4vcmVxdWlyZWRQYXJhbWV0ZXInO1xuaW1wb3J0IHsgQW5hbHl0aWNzUm91dGVyIH0gZnJvbSAnLi9Sb3V0ZXJzL0FuYWx5dGljc1JvdXRlcic7XG5pbXBvcnQgeyBDbGFzc2VzUm91dGVyIH0gZnJvbSAnLi9Sb3V0ZXJzL0NsYXNzZXNSb3V0ZXInO1xuaW1wb3J0IHsgRmVhdHVyZXNSb3V0ZXIgfSBmcm9tICcuL1JvdXRlcnMvRmVhdHVyZXNSb3V0ZXInO1xuaW1wb3J0IHsgRmlsZXNSb3V0ZXIgfSBmcm9tICcuL1JvdXRlcnMvRmlsZXNSb3V0ZXInO1xuaW1wb3J0IHsgRnVuY3Rpb25zUm91dGVyIH0gZnJvbSAnLi9Sb3V0ZXJzL0Z1bmN0aW9uc1JvdXRlcic7XG5pbXBvcnQgeyBHbG9iYWxDb25maWdSb3V0ZXIgfSBmcm9tICcuL1JvdXRlcnMvR2xvYmFsQ29uZmlnUm91dGVyJztcbmltcG9ydCB7IEdyYXBoUUxSb3V0ZXIgfSBmcm9tICcuL1JvdXRlcnMvR3JhcGhRTFJvdXRlcic7XG5pbXBvcnQgeyBIb29rc1JvdXRlciB9IGZyb20gJy4vUm91dGVycy9Ib29rc1JvdXRlcic7XG5pbXBvcnQgeyBJQVBWYWxpZGF0aW9uUm91dGVyIH0gZnJvbSAnLi9Sb3V0ZXJzL0lBUFZhbGlkYXRpb25Sb3V0ZXInO1xuaW1wb3J0IHsgSW5zdGFsbGF0aW9uc1JvdXRlciB9IGZyb20gJy4vUm91dGVycy9JbnN0YWxsYXRpb25zUm91dGVyJztcbmltcG9ydCB7IExvZ3NSb3V0ZXIgfSBmcm9tICcuL1JvdXRlcnMvTG9nc1JvdXRlcic7XG5pbXBvcnQgeyBQYXJzZUxpdmVRdWVyeVNlcnZlciB9IGZyb20gJy4vTGl2ZVF1ZXJ5L1BhcnNlTGl2ZVF1ZXJ5U2VydmVyJztcbmltcG9ydCB7IFBhZ2VzUm91dGVyIH0gZnJvbSAnLi9Sb3V0ZXJzL1BhZ2VzUm91dGVyJztcbmltcG9ydCB7IFB1YmxpY0FQSVJvdXRlciB9IGZyb20gJy4vUm91dGVycy9QdWJsaWNBUElSb3V0ZXInO1xuaW1wb3J0IHsgUHVzaFJvdXRlciB9IGZyb20gJy4vUm91dGVycy9QdXNoUm91dGVyJztcbmltcG9ydCB7IENsb3VkQ29kZVJvdXRlciB9IGZyb20gJy4vUm91dGVycy9DbG91ZENvZGVSb3V0ZXInO1xuaW1wb3J0IHsgUm9sZXNSb3V0ZXIgfSBmcm9tICcuL1JvdXRlcnMvUm9sZXNSb3V0ZXInO1xuaW1wb3J0IHsgU2NoZW1hc1JvdXRlciB9IGZyb20gJy4vUm91dGVycy9TY2hlbWFzUm91dGVyJztcbmltcG9ydCB7IFNlc3Npb25zUm91dGVyIH0gZnJvbSAnLi9Sb3V0ZXJzL1Nlc3Npb25zUm91dGVyJztcbmltcG9ydCB7IFVzZXJzUm91dGVyIH0gZnJvbSAnLi9Sb3V0ZXJzL1VzZXJzUm91dGVyJztcbmltcG9ydCB7IFB1cmdlUm91dGVyIH0gZnJvbSAnLi9Sb3V0ZXJzL1B1cmdlUm91dGVyJztcbmltcG9ydCB7IEF1ZGllbmNlc1JvdXRlciB9IGZyb20gJy4vUm91dGVycy9BdWRpZW5jZXNSb3V0ZXInO1xuaW1wb3J0IHsgQWdncmVnYXRlUm91dGVyIH0gZnJvbSAnLi9Sb3V0ZXJzL0FnZ3JlZ2F0ZVJvdXRlcic7XG5pbXBvcnQgeyBQYXJzZVNlcnZlclJFU1RDb250cm9sbGVyIH0gZnJvbSAnLi9QYXJzZVNlcnZlclJFU1RDb250cm9sbGVyJztcbmltcG9ydCAqIGFzIGNvbnRyb2xsZXJzIGZyb20gJy4vQ29udHJvbGxlcnMnO1xuaW1wb3J0IHsgUGFyc2VHcmFwaFFMU2VydmVyIH0gZnJvbSAnLi9HcmFwaFFML1BhcnNlR3JhcGhRTFNlcnZlcic7XG5pbXBvcnQgeyBTZWN1cml0eVJvdXRlciB9IGZyb20gJy4vUm91dGVycy9TZWN1cml0eVJvdXRlcic7XG5pbXBvcnQgQ2hlY2tSdW5uZXIgZnJvbSAnLi9TZWN1cml0eS9DaGVja1J1bm5lcic7XG5pbXBvcnQgRGVwcmVjYXRvciBmcm9tICcuL0RlcHJlY2F0b3IvRGVwcmVjYXRvcic7XG5pbXBvcnQgeyBEZWZpbmVkU2NoZW1hcyB9IGZyb20gJy4vU2NoZW1hTWlncmF0aW9ucy9EZWZpbmVkU2NoZW1hcyc7XG5pbXBvcnQgT3B0aW9uc0RlZmluaXRpb25zIGZyb20gJy4vT3B0aW9ucy9EZWZpbml0aW9ucyc7XG5pbXBvcnQgeyByZXNvbHZpbmdQcm9taXNlLCBDb25uZWN0aW9ucyB9IGZyb20gJy4vVGVzdFV0aWxzJztcblxuLy8gTXV0YXRlIHRoZSBQYXJzZSBvYmplY3QgdG8gYWRkIHRoZSBDbG91ZCBDb2RlIGhhbmRsZXJzXG5hZGRQYXJzZUNsb3VkKCk7XG5cbi8vIFRyYWNrIGNvbm5lY3Rpb25zIHRvIGRlc3Ryb3kgdGhlbSBvbiBzaHV0ZG93blxuY29uc3QgY29ubmVjdGlvbnMgPSBuZXcgQ29ubmVjdGlvbnMoKTtcblxuLy8gUGFyc2VTZXJ2ZXIgd29ya3MgbGlrZSBhIGNvbnN0cnVjdG9yIG9mIGFuIGV4cHJlc3MgYXBwLlxuLy8gaHR0cHM6Ly9wYXJzZXBsYXRmb3JtLm9yZy9wYXJzZS1zZXJ2ZXIvYXBpL21hc3Rlci9QYXJzZVNlcnZlck9wdGlvbnMuaHRtbFxuY2xhc3MgUGFyc2VTZXJ2ZXIge1xuICBfYXBwOiBhbnk7XG4gIGNvbmZpZzogYW55O1xuICBzZXJ2ZXI6IGFueTtcbiAgZXhwcmVzc0FwcDogYW55O1xuICBsaXZlUXVlcnlTZXJ2ZXI6IGFueTtcbiAgLyoqXG4gICAqIEBjb25zdHJ1Y3RvclxuICAgKiBAcGFyYW0ge1BhcnNlU2VydmVyT3B0aW9uc30gb3B0aW9ucyB0aGUgcGFyc2Ugc2VydmVyIGluaXRpYWxpemF0aW9uIG9wdGlvbnNcbiAgICovXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnM6IFBhcnNlU2VydmVyT3B0aW9ucykge1xuICAgIC8vIFNjYW4gZm9yIGRlcHJlY2F0ZWQgUGFyc2UgU2VydmVyIG9wdGlvbnNcbiAgICBEZXByZWNhdG9yLnNjYW5QYXJzZVNlcnZlck9wdGlvbnMob3B0aW9ucyk7XG5cbiAgICBjb25zdCBpbnRlcmZhY2VzID0gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShPcHRpb25zRGVmaW5pdGlvbnMpKTtcblxuICAgIGZ1bmN0aW9uIGdldFZhbGlkT2JqZWN0KHJvb3QpIHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IHt9O1xuICAgICAgZm9yIChjb25zdCBrZXkgaW4gcm9vdCkge1xuICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHJvb3Rba2V5XSwgJ3R5cGUnKSkge1xuICAgICAgICAgIGlmIChyb290W2tleV0udHlwZS5lbmRzV2l0aCgnW10nKSkge1xuICAgICAgICAgICAgcmVzdWx0W2tleV0gPSBbZ2V0VmFsaWRPYmplY3QoaW50ZXJmYWNlc1tyb290W2tleV0udHlwZS5zbGljZSgwLCAtMildKV07XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlc3VsdFtrZXldID0gZ2V0VmFsaWRPYmplY3QoaW50ZXJmYWNlc1tyb290W2tleV0udHlwZV0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXN1bHRba2V5XSA9ICcnO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIGNvbnN0IG9wdGlvbnNCbHVlcHJpbnQgPSBnZXRWYWxpZE9iamVjdChpbnRlcmZhY2VzWydQYXJzZVNlcnZlck9wdGlvbnMnXSk7XG5cbiAgICBmdW5jdGlvbiB2YWxpZGF0ZUtleU5hbWVzKG9yaWdpbmFsLCByZWYsIG5hbWUgPSAnJykge1xuICAgICAgbGV0IHJlc3VsdCA9IFtdO1xuICAgICAgY29uc3QgcHJlZml4ID0gbmFtZSArIChuYW1lICE9PSAnJyA/ICcuJyA6ICcnKTtcbiAgICAgIGZvciAoY29uc3Qga2V5IGluIG9yaWdpbmFsKSB7XG4gICAgICAgIGlmICghT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHJlZiwga2V5KSkge1xuICAgICAgICAgIHJlc3VsdC5wdXNoKHByZWZpeCArIGtleSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKHJlZltrZXldID09PSAnJykgeyBjb250aW51ZTsgfVxuICAgICAgICAgIGxldCByZXMgPSBbXTtcbiAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShvcmlnaW5hbFtrZXldKSAmJiBBcnJheS5pc0FycmF5KHJlZltrZXldKSkge1xuICAgICAgICAgICAgY29uc3QgdHlwZSA9IHJlZltrZXldWzBdO1xuICAgICAgICAgICAgb3JpZ2luYWxba2V5XS5mb3JFYWNoKChpdGVtLCBpZHgpID0+IHtcbiAgICAgICAgICAgICAgaWYgKHR5cGVvZiBpdGVtID09PSAnb2JqZWN0JyAmJiBpdGVtICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmVzID0gcmVzLmNvbmNhdCh2YWxpZGF0ZUtleU5hbWVzKGl0ZW0sIHR5cGUsIHByZWZpeCArIGtleSArIGBbJHtpZHh9XWApKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2Ygb3JpZ2luYWxba2V5XSA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIHJlZltrZXldID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgcmVzID0gdmFsaWRhdGVLZXlOYW1lcyhvcmlnaW5hbFtrZXldLCByZWZba2V5XSwgcHJlZml4ICsga2V5KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmVzdWx0ID0gcmVzdWx0LmNvbmNhdChyZXMpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIGNvbnN0IGRpZmYgPSB2YWxpZGF0ZUtleU5hbWVzKG9wdGlvbnMsIG9wdGlvbnNCbHVlcHJpbnQpO1xuICAgIGlmIChkaWZmLmxlbmd0aCA+IDApIHtcbiAgICAgIGNvbnN0IGxvZ2dlciA9IChsb2dnaW5nIGFzIGFueSkubG9nZ2VyO1xuICAgICAgbG9nZ2VyLmVycm9yKGBJbnZhbGlkIGtleShzKSBmb3VuZCBpbiBQYXJzZSBTZXJ2ZXIgY29uZmlndXJhdGlvbjogJHtkaWZmLmpvaW4oJywgJyl9YCk7XG4gICAgfVxuXG4gICAgLy8gU2V0IG9wdGlvbiBkZWZhdWx0c1xuICAgIGluamVjdERlZmF1bHRzKG9wdGlvbnMpO1xuICAgIGNvbnN0IHtcbiAgICAgIGFwcElkID0gcmVxdWlyZWRQYXJhbWV0ZXIoJ1lvdSBtdXN0IHByb3ZpZGUgYW4gYXBwSWQhJyksXG4gICAgICBtYXN0ZXJLZXkgPSByZXF1aXJlZFBhcmFtZXRlcignWW91IG11c3QgcHJvdmlkZSBhIG1hc3RlcktleSEnKSxcbiAgICAgIGphdmFzY3JpcHRLZXksXG4gICAgICBzZXJ2ZXJVUkwgPSByZXF1aXJlZFBhcmFtZXRlcignWW91IG11c3QgcHJvdmlkZSBhIHNlcnZlclVSTCEnKSxcbiAgICB9ID0gb3B0aW9ucztcbiAgICAvLyBJbml0aWFsaXplIHRoZSBub2RlIGNsaWVudCBTREsgYXV0b21hdGljYWxseVxuICAgIFBhcnNlLmluaXRpYWxpemUoYXBwSWQsIGphdmFzY3JpcHRLZXkgfHwgJ3VudXNlZCcsIG1hc3RlcktleSk7XG4gICAgUGFyc2Uuc2VydmVyVVJMID0gc2VydmVyVVJMO1xuICAgIENvbmZpZy52YWxpZGF0ZU9wdGlvbnMob3B0aW9ucyk7XG4gICAgY29uc3QgYWxsQ29udHJvbGxlcnMgPSBjb250cm9sbGVycy5nZXRDb250cm9sbGVycyhvcHRpb25zKTtcblxuICAgIChvcHRpb25zIGFzIGFueSkuc3RhdGUgPSAnaW5pdGlhbGl6ZWQnO1xuICAgIHRoaXMuY29uZmlnID0gQ29uZmlnLnB1dChPYmplY3QuYXNzaWduKHt9LCBvcHRpb25zLCBhbGxDb250cm9sbGVycykpO1xuICAgIHRoaXMuY29uZmlnLm1hc3RlcktleUlwc1N0b3JlID0gbmV3IE1hcCgpO1xuICAgIHRoaXMuY29uZmlnLm1haW50ZW5hbmNlS2V5SXBzU3RvcmUgPSBuZXcgTWFwKCk7XG4gICAgbG9nZ2luZy5zZXRMb2dnZXIoYWxsQ29udHJvbGxlcnMubG9nZ2VyQ29udHJvbGxlcik7XG4gIH1cblxuICAvKipcbiAgICogU3RhcnRzIFBhcnNlIFNlcnZlciBhcyBhbiBleHByZXNzIGFwcDsgdGhpcyBwcm9taXNlIHJlc29sdmVzIHdoZW4gUGFyc2UgU2VydmVyIGlzIHJlYWR5IHRvIGFjY2VwdCByZXF1ZXN0cy5cbiAgICovXG5cbiAgYXN5bmMgc3RhcnQoKTogUHJvbWlzZTx0aGlzPiB7XG4gICAgdHJ5IHtcbiAgICAgIGlmICh0aGlzLmNvbmZpZy5zdGF0ZSA9PT0gJ29rJykge1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgIH1cbiAgICAgIHRoaXMuY29uZmlnLnN0YXRlID0gJ3N0YXJ0aW5nJztcbiAgICAgIENvbmZpZy5wdXQodGhpcy5jb25maWcpO1xuICAgICAgY29uc3Qge1xuICAgICAgICBkYXRhYmFzZUNvbnRyb2xsZXIsXG4gICAgICAgIGhvb2tzQ29udHJvbGxlcixcbiAgICAgICAgY2FjaGVDb250cm9sbGVyLFxuICAgICAgICBjbG91ZCxcbiAgICAgICAgc2VjdXJpdHksXG4gICAgICAgIHNjaGVtYSxcbiAgICAgICAgbGl2ZVF1ZXJ5Q29udHJvbGxlcixcbiAgICAgIH0gPSB0aGlzLmNvbmZpZztcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IGRhdGFiYXNlQ29udHJvbGxlci5wZXJmb3JtSW5pdGlhbGl6YXRpb24oKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgaWYgKGUuY29kZSAhPT0gUGFyc2UuRXJyb3IuRFVQTElDQVRFX1ZBTFVFKSB7XG4gICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgY29uc3QgcHVzaENvbnRyb2xsZXIgPSBhd2FpdCBjb250cm9sbGVycy5nZXRQdXNoQ29udHJvbGxlcih0aGlzLmNvbmZpZyk7XG4gICAgICBhd2FpdCBob29rc0NvbnRyb2xsZXIubG9hZCgpO1xuICAgICAgY29uc3Qgc3RhcnR1cFByb21pc2VzID0gW3RoaXMuY29uZmlnLmxvYWRNYXN0ZXJLZXk/LigpXTtcbiAgICAgIGlmIChzY2hlbWEpIHtcbiAgICAgICAgc3RhcnR1cFByb21pc2VzLnB1c2gobmV3IERlZmluZWRTY2hlbWFzKHNjaGVtYSwgdGhpcy5jb25maWcpLmV4ZWN1dGUoKSk7XG4gICAgICB9XG4gICAgICBpZiAoXG4gICAgICAgIGNhY2hlQ29udHJvbGxlci5hZGFwdGVyPy5jb25uZWN0ICYmXG4gICAgICAgIHR5cGVvZiBjYWNoZUNvbnRyb2xsZXIuYWRhcHRlci5jb25uZWN0ID09PSAnZnVuY3Rpb24nXG4gICAgICApIHtcbiAgICAgICAgc3RhcnR1cFByb21pc2VzLnB1c2goY2FjaGVDb250cm9sbGVyLmFkYXB0ZXIuY29ubmVjdCgpKTtcbiAgICAgIH1cbiAgICAgIHN0YXJ0dXBQcm9taXNlcy5wdXNoKGxpdmVRdWVyeUNvbnRyb2xsZXIuY29ubmVjdCgpKTtcbiAgICAgIGF3YWl0IFByb21pc2UuYWxsKHN0YXJ0dXBQcm9taXNlcyk7XG4gICAgICBpZiAoY2xvdWQpIHtcbiAgICAgICAgYWRkUGFyc2VDbG91ZCgpO1xuICAgICAgICBpZiAodHlwZW9mIGNsb3VkID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgYXdhaXQgUHJvbWlzZS5yZXNvbHZlKGNsb3VkKFBhcnNlKSk7XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGNsb3VkID09PSAnc3RyaW5nJykge1xuICAgICAgICAgIGxldCBqc29uO1xuICAgICAgICAgIGlmIChwcm9jZXNzLmVudi5ucG1fcGFja2FnZV9qc29uKSB7XG4gICAgICAgICAgICBqc29uID0gcmVxdWlyZShwcm9jZXNzLmVudi5ucG1fcGFja2FnZV9qc29uKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHByb2Nlc3MuZW52Lm5wbV9wYWNrYWdlX3R5cGUgPT09ICdtb2R1bGUnIHx8IGpzb24/LnR5cGUgPT09ICdtb2R1bGUnKSB7XG4gICAgICAgICAgICBhd2FpdCBpbXBvcnQocGF0aC5yZXNvbHZlKHByb2Nlc3MuY3dkKCksIGNsb3VkKSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlcXVpcmUocGF0aC5yZXNvbHZlKHByb2Nlc3MuY3dkKCksIGNsb3VkKSk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IFwiYXJndW1lbnQgJ2Nsb3VkJyBtdXN0IGVpdGhlciBiZSBhIHN0cmluZyBvciBhIGZ1bmN0aW9uXCI7XG4gICAgICAgIH1cbiAgICAgICAgYXdhaXQgbmV3IFByb21pc2UocmVzb2x2ZSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIDEwKSk7XG4gICAgICB9XG4gICAgICBpZiAoc2VjdXJpdHkgJiYgc2VjdXJpdHkuZW5hYmxlQ2hlY2sgJiYgc2VjdXJpdHkuZW5hYmxlQ2hlY2tMb2cpIHtcbiAgICAgICAgbmV3IENoZWNrUnVubmVyKHNlY3VyaXR5KS5ydW4oKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuY29uZmlnLnN0YXRlID0gJ29rJztcbiAgICAgIHRoaXMuY29uZmlnID0geyAuLi50aGlzLmNvbmZpZywgLi4ucHVzaENvbnRyb2xsZXIgfTtcbiAgICAgIENvbmZpZy5wdXQodGhpcy5jb25maWcpO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgIHRoaXMuY29uZmlnLnN0YXRlID0gJ2Vycm9yJztcbiAgICAgIHRocm93IGVycm9yO1xuICAgIH1cbiAgfVxuXG4gIGdldCBhcHAoKSB7XG4gICAgaWYgKCF0aGlzLl9hcHApIHtcbiAgICAgIHRoaXMuX2FwcCA9IFBhcnNlU2VydmVyLmFwcCh0aGlzLmNvbmZpZyk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9hcHA7XG4gIH1cblxuICAvKipcbiAgICogU3RvcHMgdGhlIHBhcnNlIHNlcnZlciwgY2FuY2VscyBhbnkgb25nb2luZyByZXF1ZXN0cyBhbmQgY2xvc2VzIGFsbCBjb25uZWN0aW9ucy5cbiAgICpcbiAgICogQ3VycmVudGx5LCBleHByZXNzIGRvZXNuJ3Qgc2h1dCBkb3duIGltbWVkaWF0ZWx5IGFmdGVyIHJlY2VpdmluZyBTSUdJTlQvU0lHVEVSTVxuICAgKiBpZiBpdCBoYXMgY2xpZW50IGNvbm5lY3Rpb25zIHRoYXQgaGF2ZW4ndCB0aW1lZCBvdXQuXG4gICAqIChUaGlzIGlzIGEga25vd24gaXNzdWUgd2l0aCBub2RlIC0gaHR0cHM6Ly9naXRodWIuY29tL25vZGVqcy9ub2RlL2lzc3Vlcy8yNjQyKVxuICAgKlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgc2VydmVyIGlzIHN0b3BwZWRcbiAgICovXG4gIGFzeW5jIGhhbmRsZVNodXRkb3duKCkge1xuICAgIGNvbnN0IHNlcnZlckNsb3NlUHJvbWlzZSA9IHJlc29sdmluZ1Byb21pc2UoKTtcbiAgICBjb25zdCBsaXZlUXVlcnlTZXJ2ZXJDbG9zZVByb21pc2UgPSByZXNvbHZpbmdQcm9taXNlKCk7XG4gICAgY29uc3QgcHJvbWlzZXMgPSBbXTtcbiAgICB0aGlzLnNlcnZlci5jbG9zZSgoZXJyb3IpID0+IHtcbiAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3Igd2hpbGUgY2xvc2luZyBwYXJzZSBzZXJ2ZXInLCBlcnJvcik7XG4gICAgICB9XG4gICAgICBzZXJ2ZXJDbG9zZVByb21pc2UucmVzb2x2ZSgpO1xuICAgIH0pO1xuICAgIGlmICh0aGlzLmxpdmVRdWVyeVNlcnZlcj8uc2VydmVyPy5jbG9zZSAmJiB0aGlzLmxpdmVRdWVyeVNlcnZlci5zZXJ2ZXIgIT09IHRoaXMuc2VydmVyKSB7XG4gICAgICB0aGlzLmxpdmVRdWVyeVNlcnZlci5zZXJ2ZXIuY2xvc2UoKGVycm9yKSA9PiB7XG4gICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3Igd2hpbGUgY2xvc2luZyBsaXZlIHF1ZXJ5IHNlcnZlcicsIGVycm9yKTtcbiAgICAgICAgfVxuICAgICAgICBsaXZlUXVlcnlTZXJ2ZXJDbG9zZVByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxpdmVRdWVyeVNlcnZlckNsb3NlUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfVxuICAgIGNvbnN0IHsgYWRhcHRlcjogZGF0YWJhc2VBZGFwdGVyIH0gPSB0aGlzLmNvbmZpZy5kYXRhYmFzZUNvbnRyb2xsZXI7XG4gICAgaWYgKGRhdGFiYXNlQWRhcHRlciAmJiB0eXBlb2YgZGF0YWJhc2VBZGFwdGVyLmhhbmRsZVNodXRkb3duID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICBwcm9taXNlcy5wdXNoKGRhdGFiYXNlQWRhcHRlci5oYW5kbGVTaHV0ZG93bigpKTtcbiAgICB9XG4gICAgY29uc3QgeyBhZGFwdGVyOiBmaWxlQWRhcHRlciB9ID0gdGhpcy5jb25maWcuZmlsZXNDb250cm9sbGVyO1xuICAgIGlmIChmaWxlQWRhcHRlciAmJiB0eXBlb2YgZmlsZUFkYXB0ZXIuaGFuZGxlU2h1dGRvd24gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHByb21pc2VzLnB1c2goZmlsZUFkYXB0ZXIuaGFuZGxlU2h1dGRvd24oKSk7XG4gICAgfVxuICAgIGNvbnN0IHsgYWRhcHRlcjogY2FjaGVBZGFwdGVyIH0gPSB0aGlzLmNvbmZpZy5jYWNoZUNvbnRyb2xsZXI7XG4gICAgaWYgKGNhY2hlQWRhcHRlciAmJiB0eXBlb2YgY2FjaGVBZGFwdGVyLmhhbmRsZVNodXRkb3duID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICBwcm9taXNlcy5wdXNoKGNhY2hlQWRhcHRlci5oYW5kbGVTaHV0ZG93bigpKTtcbiAgICB9XG4gICAgaWYgKHRoaXMubGl2ZVF1ZXJ5U2VydmVyKSB7XG4gICAgICBwcm9taXNlcy5wdXNoKHRoaXMubGl2ZVF1ZXJ5U2VydmVyLnNodXRkb3duKCkpO1xuICAgIH1cbiAgICBhd2FpdCBQcm9taXNlLmFsbChwcm9taXNlcyk7XG4gICAgY29ubmVjdGlvbnMuZGVzdHJveUFsbCgpO1xuICAgIGF3YWl0IFByb21pc2UuYWxsKFtzZXJ2ZXJDbG9zZVByb21pc2UsIGxpdmVRdWVyeVNlcnZlckNsb3NlUHJvbWlzZV0pO1xuICAgIGlmICh0aGlzLmNvbmZpZy5zZXJ2ZXJDbG9zZUNvbXBsZXRlKSB7XG4gICAgICB0aGlzLmNvbmZpZy5zZXJ2ZXJDbG9zZUNvbXBsZXRlKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBzdGF0aWNcbiAgICogQWxsb3cgZGV2ZWxvcGVycyB0byBjdXN0b21pemUgZWFjaCByZXF1ZXN0IHdpdGggaW52ZXJzaW9uIG9mIGNvbnRyb2wvZGVwZW5kZW5jeSBpbmplY3Rpb25cbiAgICovXG4gIHN0YXRpYyBhcHBseVJlcXVlc3RDb250ZXh0TWlkZGxld2FyZShhcGksIG9wdGlvbnMpIHtcbiAgICBpZiAob3B0aW9ucy5yZXF1ZXN0Q29udGV4dE1pZGRsZXdhcmUpIHtcbiAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5yZXF1ZXN0Q29udGV4dE1pZGRsZXdhcmUgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdyZXF1ZXN0Q29udGV4dE1pZGRsZXdhcmUgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG4gICAgICB9XG4gICAgICBhcGkudXNlKG9wdGlvbnMucmVxdWVzdENvbnRleHRNaWRkbGV3YXJlKTtcbiAgICB9XG4gIH1cbiAgLyoqXG4gICAqIEBzdGF0aWNcbiAgICogQ3JlYXRlIGFuIGV4cHJlc3MgYXBwIGZvciB0aGUgcGFyc2Ugc2VydmVyXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIGxldCB5b3Ugc3BlY2lmeSB0aGUgbWF4VXBsb2FkU2l6ZSB3aGVuIGNyZWF0aW5nIHRoZSBleHByZXNzIGFwcCAgKi9cbiAgc3RhdGljIGFwcChvcHRpb25zKSB7XG4gICAgY29uc3Qge1xuICAgICAgbWF4VXBsb2FkU2l6ZSA9ICcyMG1iJyxcbiAgICAgIGFwcElkLFxuICAgICAgZGlyZWN0QWNjZXNzLFxuICAgICAgcGFnZXMsXG4gICAgICByYXRlTGltaXQgPSBbXSxcbiAgICB9ID0gb3B0aW9ucztcbiAgICAvLyBUaGlzIGFwcCBzZXJ2ZXMgdGhlIFBhcnNlIEFQSSBkaXJlY3RseS5cbiAgICAvLyBJdCdzIHRoZSBlcXVpdmFsZW50IG9mIGh0dHBzOi8vYXBpLnBhcnNlLmNvbS8xIGluIHRoZSBob3N0ZWQgUGFyc2UgQVBJLlxuICAgIHZhciBhcGkgPSBleHByZXNzKCk7XG4gICAgLy9hcGkudXNlKFwiL2FwcHNcIiwgZXhwcmVzcy5zdGF0aWMoX19kaXJuYW1lICsgXCIvcHVibGljXCIpKTtcbiAgICBhcGkudXNlKG1pZGRsZXdhcmVzLmFsbG93Q3Jvc3NEb21haW4oYXBwSWQpKTtcbiAgICBhcGkudXNlKG1pZGRsZXdhcmVzLmFsbG93RG91YmxlRm9yd2FyZFNsYXNoKTtcbiAgICAvLyBGaWxlIGhhbmRsaW5nIG5lZWRzIHRvIGJlIGJlZm9yZSBkZWZhdWx0IG1pZGRsZXdhcmVzIGFyZSBhcHBsaWVkXG4gICAgYXBpLnVzZShcbiAgICAgICcvJyxcbiAgICAgIG5ldyBGaWxlc1JvdXRlcigpLmV4cHJlc3NSb3V0ZXIoe1xuICAgICAgICBtYXhVcGxvYWRTaXplOiBtYXhVcGxvYWRTaXplLFxuICAgICAgfSlcbiAgICApO1xuXG4gICAgYXBpLnVzZSgnL2hlYWx0aCcsIGZ1bmN0aW9uIChyZXEsIHJlcykge1xuICAgICAgcmVzLnN0YXR1cyhvcHRpb25zLnN0YXRlID09PSAnb2snID8gMjAwIDogNTAzKTtcbiAgICAgIGlmIChvcHRpb25zLnN0YXRlID09PSAnc3RhcnRpbmcnKSB7XG4gICAgICAgIHJlcy5zZXQoJ1JldHJ5LUFmdGVyJywgMSk7XG4gICAgICB9XG4gICAgICByZXMuanNvbih7XG4gICAgICAgIHN0YXR1czogb3B0aW9ucy5zdGF0ZSxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgYXBpLnVzZShcbiAgICAgICcvJyxcbiAgICAgIGV4cHJlc3MudXJsZW5jb2RlZCh7IGV4dGVuZGVkOiBmYWxzZSB9KSxcbiAgICAgIHBhZ2VzLmVuYWJsZVJvdXRlclxuICAgICAgICA/IG5ldyBQYWdlc1JvdXRlcihwYWdlcykuZXhwcmVzc1JvdXRlcigpXG4gICAgICAgIDogbmV3IFB1YmxpY0FQSVJvdXRlcigpLmV4cHJlc3NSb3V0ZXIoKVxuICAgICk7XG5cbiAgICBhcGkudXNlKGV4cHJlc3MuanNvbih7IHR5cGU6ICcqLyonLCBsaW1pdDogbWF4VXBsb2FkU2l6ZSB9KSk7XG4gICAgYXBpLnVzZShtaWRkbGV3YXJlcy5hbGxvd01ldGhvZE92ZXJyaWRlKTtcbiAgICBhcGkudXNlKG1pZGRsZXdhcmVzLmhhbmRsZVBhcnNlSGVhZGVycyk7XG4gICAgYXBpLnNldCgncXVlcnkgcGFyc2VyJywgJ2V4dGVuZGVkJyk7XG4gICAgY29uc3Qgcm91dGVzID0gQXJyYXkuaXNBcnJheShyYXRlTGltaXQpID8gcmF0ZUxpbWl0IDogW3JhdGVMaW1pdF07XG4gICAgZm9yIChjb25zdCByb3V0ZSBvZiByb3V0ZXMpIHtcbiAgICAgIG1pZGRsZXdhcmVzLmFkZFJhdGVMaW1pdChyb3V0ZSwgb3B0aW9ucyk7XG4gICAgfVxuICAgIGFwaS51c2UobWlkZGxld2FyZXMuaGFuZGxlUGFyc2VTZXNzaW9uKTtcbiAgICB0aGlzLmFwcGx5UmVxdWVzdENvbnRleHRNaWRkbGV3YXJlKGFwaSwgb3B0aW9ucyk7XG4gICAgY29uc3QgYXBwUm91dGVyID0gUGFyc2VTZXJ2ZXIucHJvbWlzZVJvdXRlcih7IGFwcElkIH0pO1xuICAgIGFwaS51c2UoYXBwUm91dGVyLmV4cHJlc3NSb3V0ZXIoKSk7XG5cbiAgICBhcGkudXNlKG1pZGRsZXdhcmVzLmhhbmRsZVBhcnNlRXJyb3JzKTtcblxuICAgIC8vIHJ1biB0aGUgZm9sbG93aW5nIHdoZW4gbm90IHRlc3RpbmdcbiAgICBpZiAoIXByb2Nlc3MuZW52LlRFU1RJTkcpIHtcbiAgICAgIC8vVGhpcyBjYXVzZXMgdGVzdHMgdG8gc3BldyBzb21lIHVzZWxlc3Mgd2FybmluZ3MsIHNvIGRpc2FibGUgaW4gdGVzdFxuICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICAgIHByb2Nlc3Mub24oJ3VuY2F1Z2h0RXhjZXB0aW9uJywgKGVycjogYW55KSA9PiB7XG4gICAgICAgIGlmIChlcnIuY29kZSA9PT0gJ0VBRERSSU5VU0UnKSB7XG4gICAgICAgICAgLy8gdXNlci1mcmllbmRseSBtZXNzYWdlIGZvciB0aGlzIGNvbW1vbiBlcnJvclxuICAgICAgICAgIHByb2Nlc3Muc3RkZXJyLndyaXRlKGBVbmFibGUgdG8gbGlzdGVuIG9uIHBvcnQgJHtlcnIucG9ydH0uIFRoZSBwb3J0IGlzIGFscmVhZHkgaW4gdXNlLmApO1xuICAgICAgICAgIHByb2Nlc3MuZXhpdCgwKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZiAoZXJyLm1lc3NhZ2UpIHtcbiAgICAgICAgICAgIHByb2Nlc3Muc3RkZXJyLndyaXRlKCdBbiB1bmNhdWdodCBleGNlcHRpb24gb2NjdXJyZWQ6ICcgKyBlcnIubWVzc2FnZSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChlcnIuc3RhY2spIHtcbiAgICAgICAgICAgIHByb2Nlc3Muc3RkZXJyLndyaXRlKCdTdGFjayBUcmFjZTpcXG4nICsgZXJyLnN0YWNrKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcHJvY2Vzcy5zdGRlcnIud3JpdGUoZXJyKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcHJvY2Vzcy5leGl0KDEpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gICAgaWYgKHByb2Nlc3MuZW52LlBBUlNFX1NFUlZFUl9FTkFCTEVfRVhQRVJJTUVOVEFMX0RJUkVDVF9BQ0NFU1MgPT09ICcxJyB8fCBkaXJlY3RBY2Nlc3MpIHtcbiAgICAgIFBhcnNlLkNvcmVNYW5hZ2VyLnNldFJFU1RDb250cm9sbGVyKFBhcnNlU2VydmVyUkVTVENvbnRyb2xsZXIoYXBwSWQsIGFwcFJvdXRlcikpO1xuICAgIH1cbiAgICByZXR1cm4gYXBpO1xuICB9XG5cbiAgc3RhdGljIHByb21pc2VSb3V0ZXIoeyBhcHBJZCB9KSB7XG4gICAgY29uc3Qgcm91dGVycyA9IFtcbiAgICAgIG5ldyBDbGFzc2VzUm91dGVyKCksXG4gICAgICBuZXcgVXNlcnNSb3V0ZXIoKSxcbiAgICAgIG5ldyBTZXNzaW9uc1JvdXRlcigpLFxuICAgICAgbmV3IFJvbGVzUm91dGVyKCksXG4gICAgICBuZXcgQW5hbHl0aWNzUm91dGVyKCksXG4gICAgICBuZXcgSW5zdGFsbGF0aW9uc1JvdXRlcigpLFxuICAgICAgbmV3IEZ1bmN0aW9uc1JvdXRlcigpLFxuICAgICAgbmV3IFNjaGVtYXNSb3V0ZXIoKSxcbiAgICAgIG5ldyBQdXNoUm91dGVyKCksXG4gICAgICBuZXcgTG9nc1JvdXRlcigpLFxuICAgICAgbmV3IElBUFZhbGlkYXRpb25Sb3V0ZXIoKSxcbiAgICAgIG5ldyBGZWF0dXJlc1JvdXRlcigpLFxuICAgICAgbmV3IEdsb2JhbENvbmZpZ1JvdXRlcigpLFxuICAgICAgbmV3IEdyYXBoUUxSb3V0ZXIoKSxcbiAgICAgIG5ldyBQdXJnZVJvdXRlcigpLFxuICAgICAgbmV3IEhvb2tzUm91dGVyKCksXG4gICAgICBuZXcgQ2xvdWRDb2RlUm91dGVyKCksXG4gICAgICBuZXcgQXVkaWVuY2VzUm91dGVyKCksXG4gICAgICBuZXcgQWdncmVnYXRlUm91dGVyKCksXG4gICAgICBuZXcgU2VjdXJpdHlSb3V0ZXIoKSxcbiAgICBdO1xuXG4gICAgY29uc3Qgcm91dGVzID0gcm91dGVycy5yZWR1Y2UoKG1lbW8sIHJvdXRlcikgPT4ge1xuICAgICAgcmV0dXJuIG1lbW8uY29uY2F0KHJvdXRlci5yb3V0ZXMpO1xuICAgIH0sIFtdKTtcblxuICAgIGNvbnN0IGFwcFJvdXRlciA9IG5ldyBQcm9taXNlUm91dGVyKHJvdXRlcywgYXBwSWQpO1xuXG4gICAgYmF0Y2gubW91bnRPbnRvKGFwcFJvdXRlcik7XG4gICAgcmV0dXJuIGFwcFJvdXRlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBzdGFydHMgdGhlIHBhcnNlIHNlcnZlcidzIGV4cHJlc3MgYXBwXG4gICAqIEBwYXJhbSB7UGFyc2VTZXJ2ZXJPcHRpb25zfSBvcHRpb25zIHRvIHVzZSB0byBzdGFydCB0aGUgc2VydmVyXG4gICAqIEByZXR1cm5zIHtQYXJzZVNlcnZlcn0gdGhlIHBhcnNlIHNlcnZlciBpbnN0YW5jZVxuICAgKi9cblxuICBhc3luYyBzdGFydEFwcChvcHRpb25zOiBQYXJzZVNlcnZlck9wdGlvbnMpIHtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgdGhpcy5zdGFydCgpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBvbiBQYXJzZVNlcnZlci5zdGFydEFwcDogJywgZSk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cbiAgICBjb25zdCBhcHAgPSBleHByZXNzKCk7XG4gICAgaWYgKG9wdGlvbnMubWlkZGxld2FyZSkge1xuICAgICAgbGV0IG1pZGRsZXdhcmU7XG4gICAgICBpZiAodHlwZW9mIG9wdGlvbnMubWlkZGxld2FyZSA9PSAnc3RyaW5nJykge1xuICAgICAgICBtaWRkbGV3YXJlID0gcmVxdWlyZShwYXRoLnJlc29sdmUocHJvY2Vzcy5jd2QoKSwgb3B0aW9ucy5taWRkbGV3YXJlKSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBtaWRkbGV3YXJlID0gb3B0aW9ucy5taWRkbGV3YXJlOyAvLyB1c2UgYXMtaXMgbGV0IGV4cHJlc3MgZmFpbFxuICAgICAgfVxuICAgICAgYXBwLnVzZShtaWRkbGV3YXJlKTtcbiAgICB9XG4gICAgYXBwLnVzZShvcHRpb25zLm1vdW50UGF0aCwgdGhpcy5hcHApO1xuXG4gICAgaWYgKG9wdGlvbnMubW91bnRHcmFwaFFMID09PSB0cnVlIHx8IG9wdGlvbnMubW91bnRQbGF5Z3JvdW5kID09PSB0cnVlKSB7XG4gICAgICBsZXQgZ3JhcGhRTEN1c3RvbVR5cGVEZWZzID0gdW5kZWZpbmVkO1xuICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLmdyYXBoUUxTY2hlbWEgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGdyYXBoUUxDdXN0b21UeXBlRGVmcyA9IHBhcnNlKGZzLnJlYWRGaWxlU3luYyhvcHRpb25zLmdyYXBoUUxTY2hlbWEsICd1dGY4JykpO1xuICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgdHlwZW9mIG9wdGlvbnMuZ3JhcGhRTFNjaGVtYSA9PT0gJ29iamVjdCcgfHxcbiAgICAgICAgdHlwZW9mIG9wdGlvbnMuZ3JhcGhRTFNjaGVtYSA9PT0gJ2Z1bmN0aW9uJ1xuICAgICAgKSB7XG4gICAgICAgIGdyYXBoUUxDdXN0b21UeXBlRGVmcyA9IG9wdGlvbnMuZ3JhcGhRTFNjaGVtYTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgcGFyc2VHcmFwaFFMU2VydmVyID0gbmV3IFBhcnNlR3JhcGhRTFNlcnZlcih0aGlzLCB7XG4gICAgICAgIGdyYXBoUUxQYXRoOiBvcHRpb25zLmdyYXBoUUxQYXRoLFxuICAgICAgICBwbGF5Z3JvdW5kUGF0aDogb3B0aW9ucy5wbGF5Z3JvdW5kUGF0aCxcbiAgICAgICAgZ3JhcGhRTEN1c3RvbVR5cGVEZWZzLFxuICAgICAgfSk7XG5cbiAgICAgIGlmIChvcHRpb25zLm1vdW50R3JhcGhRTCkge1xuICAgICAgICBwYXJzZUdyYXBoUUxTZXJ2ZXIuYXBwbHlHcmFwaFFMKGFwcCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChvcHRpb25zLm1vdW50UGxheWdyb3VuZCkge1xuICAgICAgICBwYXJzZUdyYXBoUUxTZXJ2ZXIuYXBwbHlQbGF5Z3JvdW5kKGFwcCk7XG4gICAgICB9XG4gICAgfVxuICAgIGNvbnN0IHNlcnZlciA9IGF3YWl0IG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgYXBwLmxpc3RlbihvcHRpb25zLnBvcnQsIG9wdGlvbnMuaG9zdCwgZnVuY3Rpb24gKCkge1xuICAgICAgICByZXNvbHZlKHRoaXMpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gICAgdGhpcy5zZXJ2ZXIgPSBzZXJ2ZXI7XG4gICAgY29ubmVjdGlvbnMudHJhY2soc2VydmVyKTtcblxuICAgIGlmIChvcHRpb25zLnN0YXJ0TGl2ZVF1ZXJ5U2VydmVyIHx8IG9wdGlvbnMubGl2ZVF1ZXJ5U2VydmVyT3B0aW9ucykge1xuICAgICAgdGhpcy5saXZlUXVlcnlTZXJ2ZXIgPSBhd2FpdCBQYXJzZVNlcnZlci5jcmVhdGVMaXZlUXVlcnlTZXJ2ZXIoXG4gICAgICAgIHNlcnZlcixcbiAgICAgICAgb3B0aW9ucy5saXZlUXVlcnlTZXJ2ZXJPcHRpb25zLFxuICAgICAgICBvcHRpb25zXG4gICAgICApO1xuICAgICAgaWYgKHRoaXMubGl2ZVF1ZXJ5U2VydmVyLnNlcnZlciAhPT0gdGhpcy5zZXJ2ZXIpIHtcbiAgICAgICAgY29ubmVjdGlvbnMudHJhY2sodGhpcy5saXZlUXVlcnlTZXJ2ZXIuc2VydmVyKTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKG9wdGlvbnMudHJ1c3RQcm94eSkge1xuICAgICAgYXBwLnNldCgndHJ1c3QgcHJveHknLCBvcHRpb25zLnRydXN0UHJveHkpO1xuICAgIH1cbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgIGlmICghcHJvY2Vzcy5lbnYuVEVTVElORykge1xuICAgICAgY29uZmlndXJlTGlzdGVuZXJzKHRoaXMpO1xuICAgICAgaWYgKG9wdGlvbnMudmVyaWZ5U2VydmVyVXJsICE9PSBmYWxzZSkge1xuICAgICAgICBhd2FpdCBQYXJzZVNlcnZlci52ZXJpZnlTZXJ2ZXJVcmwoKTtcbiAgICAgIH1cbiAgICB9XG4gICAgdGhpcy5leHByZXNzQXBwID0gYXBwO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBuZXcgUGFyc2VTZXJ2ZXIgYW5kIHN0YXJ0cyBpdC5cbiAgICogQHBhcmFtIHtQYXJzZVNlcnZlck9wdGlvbnN9IG9wdGlvbnMgdXNlZCB0byBzdGFydCB0aGUgc2VydmVyXG4gICAqIEByZXR1cm5zIHtQYXJzZVNlcnZlcn0gdGhlIHBhcnNlIHNlcnZlciBpbnN0YW5jZVxuICAgKi9cbiAgc3RhdGljIGFzeW5jIHN0YXJ0QXBwKG9wdGlvbnM6IFBhcnNlU2VydmVyT3B0aW9ucykge1xuICAgIGNvbnN0IHBhcnNlU2VydmVyID0gbmV3IFBhcnNlU2VydmVyKG9wdGlvbnMpO1xuICAgIHJldHVybiBwYXJzZVNlcnZlci5zdGFydEFwcChvcHRpb25zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBIZWxwZXIgbWV0aG9kIHRvIGNyZWF0ZSBhIGxpdmVRdWVyeSBzZXJ2ZXJcbiAgICogQHN0YXRpY1xuICAgKiBAcGFyYW0ge1NlcnZlcn0gaHR0cFNlcnZlciBhbiBvcHRpb25hbCBodHRwIHNlcnZlciB0byBwYXNzXG4gICAqIEBwYXJhbSB7TGl2ZVF1ZXJ5U2VydmVyT3B0aW9uc30gY29uZmlnIG9wdGlvbnMgZm9yIHRoZSBsaXZlUXVlcnlTZXJ2ZXJcbiAgICogQHBhcmFtIHtQYXJzZVNlcnZlck9wdGlvbnN9IG9wdGlvbnMgb3B0aW9ucyBmb3IgdGhlIFBhcnNlU2VydmVyXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPFBhcnNlTGl2ZVF1ZXJ5U2VydmVyPn0gdGhlIGxpdmUgcXVlcnkgc2VydmVyIGluc3RhbmNlXG4gICAqL1xuICBzdGF0aWMgYXN5bmMgY3JlYXRlTGl2ZVF1ZXJ5U2VydmVyKFxuICAgIGh0dHBTZXJ2ZXIsXG4gICAgY29uZmlnOiBMaXZlUXVlcnlTZXJ2ZXJPcHRpb25zLFxuICAgIG9wdGlvbnM6IFBhcnNlU2VydmVyT3B0aW9uc1xuICApOiBQcm9taXNlPFBhcnNlTGl2ZVF1ZXJ5U2VydmVyPiB7XG4gICAgaWYgKCFodHRwU2VydmVyIHx8IChjb25maWcgJiYgY29uZmlnLnBvcnQpKSB7XG4gICAgICB2YXIgYXBwID0gZXhwcmVzcygpO1xuICAgICAgaHR0cFNlcnZlciA9IHJlcXVpcmUoJ2h0dHAnKS5jcmVhdGVTZXJ2ZXIoYXBwKTtcbiAgICAgIGh0dHBTZXJ2ZXIubGlzdGVuKGNvbmZpZy5wb3J0KTtcbiAgICB9XG4gICAgY29uc3Qgc2VydmVyID0gbmV3IFBhcnNlTGl2ZVF1ZXJ5U2VydmVyKGh0dHBTZXJ2ZXIsIGNvbmZpZywgb3B0aW9ucyk7XG4gICAgYXdhaXQgc2VydmVyLmNvbm5lY3QoKTtcbiAgICByZXR1cm4gc2VydmVyO1xuICB9XG5cbiAgc3RhdGljIGFzeW5jIHZlcmlmeVNlcnZlclVybCgpIHtcbiAgICAvLyBwZXJmb3JtIGEgaGVhbHRoIGNoZWNrIG9uIHRoZSBzZXJ2ZXJVUkwgdmFsdWVcbiAgICBpZiAoUGFyc2Uuc2VydmVyVVJMKSB7XG4gICAgICBjb25zdCBpc1ZhbGlkSHR0cFVybCA9IHN0cmluZyA9PiB7XG4gICAgICAgIGxldCB1cmw7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgdXJsID0gbmV3IFVSTChzdHJpbmcpO1xuICAgICAgICB9IGNhdGNoIChfKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB1cmwucHJvdG9jb2wgPT09ICdodHRwOicgfHwgdXJsLnByb3RvY29sID09PSAnaHR0cHM6JztcbiAgICAgIH07XG4gICAgICBjb25zdCB1cmwgPSBgJHtQYXJzZS5zZXJ2ZXJVUkwucmVwbGFjZSgvXFwvJC8sICcnKX0vaGVhbHRoYDtcbiAgICAgIGlmICghaXNWYWxpZEh0dHBVcmwodXJsKSkge1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgYFxcbldBUk5JTkcsIFVuYWJsZSB0byBjb25uZWN0IHRvICcke1BhcnNlLnNlcnZlclVSTH0nIGFzIHRoZSBVUkwgaXMgaW52YWxpZC5gICtcbiAgICAgICAgICAgIGAgQ2xvdWQgY29kZSBhbmQgcHVzaCBub3RpZmljYXRpb25zIG1heSBiZSB1bmF2YWlsYWJsZSFcXG5gXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHJlcXVlc3QgPSByZXF1aXJlKCcuL3JlcXVlc3QnKTtcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgcmVxdWVzdCh7IHVybCB9KS5jYXRjaChyZXNwb25zZSA9PiByZXNwb25zZSk7XG4gICAgICBjb25zdCBqc29uID0gcmVzcG9uc2UuZGF0YSB8fCBudWxsO1xuICAgICAgY29uc3QgcmV0cnkgPSByZXNwb25zZS5oZWFkZXJzPy5bJ3JldHJ5LWFmdGVyJ107XG4gICAgICBpZiAocmV0cnkpIHtcbiAgICAgICAgYXdhaXQgbmV3IFByb21pc2UocmVzb2x2ZSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIHJldHJ5ICogMTAwMCkpO1xuICAgICAgICByZXR1cm4gdGhpcy52ZXJpZnlTZXJ2ZXJVcmwoKTtcbiAgICAgIH1cbiAgICAgIGlmIChyZXNwb25zZS5zdGF0dXMgIT09IDIwMCB8fCBqc29uPy5zdGF0dXMgIT09ICdvaycpIHtcbiAgICAgICAgLyogZXNsaW50LWRpc2FibGUgbm8tY29uc29sZSAqL1xuICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgYFxcbldBUk5JTkcsIFVuYWJsZSB0byBjb25uZWN0IHRvICcke1BhcnNlLnNlcnZlclVSTH0nLmAgK1xuICAgICAgICAgICAgYCBDbG91ZCBjb2RlIGFuZCBwdXNoIG5vdGlmaWNhdGlvbnMgbWF5IGJlIHVuYXZhaWxhYmxlIVxcbmBcbiAgICAgICAgKTtcbiAgICAgICAgLyogZXNsaW50LWVuYWJsZSBuby1jb25zb2xlICovXG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBhZGRQYXJzZUNsb3VkKCkge1xuICBjb25zdCBQYXJzZUNsb3VkID0gcmVxdWlyZSgnLi9jbG91ZC1jb2RlL1BhcnNlLkNsb3VkJyk7XG4gIGNvbnN0IFBhcnNlU2VydmVyID0gcmVxdWlyZSgnLi9jbG91ZC1jb2RlL1BhcnNlLlNlcnZlcicpO1xuICBPYmplY3QuZGVmaW5lUHJvcGVydHkoUGFyc2UsICdTZXJ2ZXInLCB7XG4gICAgZ2V0KCkge1xuICAgICAgY29uc3QgY29uZiA9IENvbmZpZy5nZXQoUGFyc2UuYXBwbGljYXRpb25JZCk7XG4gICAgICByZXR1cm4geyAuLi5jb25mLCAuLi5QYXJzZVNlcnZlciB9O1xuICAgIH0sXG4gICAgc2V0KG5ld1ZhbCkge1xuICAgICAgbmV3VmFsLmFwcElkID0gUGFyc2UuYXBwbGljYXRpb25JZDtcbiAgICAgIENvbmZpZy5wdXQobmV3VmFsKTtcbiAgICB9LFxuICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgfSk7XG4gIE9iamVjdC5hc3NpZ24oUGFyc2UuQ2xvdWQsIFBhcnNlQ2xvdWQpO1xuICBnbG9iYWwuUGFyc2UgPSBQYXJzZTtcbn1cblxuZnVuY3Rpb24gaW5qZWN0RGVmYXVsdHMob3B0aW9uczogUGFyc2VTZXJ2ZXJPcHRpb25zKSB7XG4gIE9iamVjdC5rZXlzKGRlZmF1bHRzKS5mb3JFYWNoKGtleSA9PiB7XG4gICAgaWYgKCFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob3B0aW9ucywga2V5KSkge1xuICAgICAgb3B0aW9uc1trZXldID0gZGVmYXVsdHNba2V5XTtcbiAgICB9XG4gIH0pO1xuXG4gIGlmICghT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9wdGlvbnMsICdzZXJ2ZXJVUkwnKSkge1xuICAgIG9wdGlvbnMuc2VydmVyVVJMID0gYGh0dHA6Ly9sb2NhbGhvc3Q6JHtvcHRpb25zLnBvcnR9JHtvcHRpb25zLm1vdW50UGF0aH1gO1xuICB9XG5cbiAgLy8gUmVzZXJ2ZWQgQ2hhcmFjdGVyc1xuICBpZiAob3B0aW9ucy5hcHBJZCkge1xuICAgIGNvbnN0IHJlZ2V4ID0gL1shIyQlJygpKismLzo7PT9AW1xcXXt9Xix8PD5dL2c7XG4gICAgaWYgKG9wdGlvbnMuYXBwSWQubWF0Y2gocmVnZXgpKSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICBgXFxuV0FSTklORywgYXBwSWQgdGhhdCBjb250YWlucyBzcGVjaWFsIGNoYXJhY3RlcnMgY2FuIGNhdXNlIGlzc3VlcyB3aGlsZSB1c2luZyB3aXRoIHVybHMuXFxuYFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICAvLyBCYWNrd2FyZHMgY29tcGF0aWJpbGl0eVxuICBpZiAob3B0aW9ucy51c2VyU2Vuc2l0aXZlRmllbGRzKSB7XG4gICAgLyogZXNsaW50LWRpc2FibGUgbm8tY29uc29sZSAqL1xuICAgICFwcm9jZXNzLmVudi5URVNUSU5HICYmXG4gICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgIGBcXG5ERVBSRUNBVEVEOiB1c2VyU2Vuc2l0aXZlRmllbGRzIGhhcyBiZWVuIHJlcGxhY2VkIGJ5IHByb3RlY3RlZEZpZWxkcyBhbGxvd2luZyB0aGUgYWJpbGl0eSB0byBwcm90ZWN0IGZpZWxkcyBpbiBhbGwgY2xhc3NlcyB3aXRoIENMUC4gXFxuYFxuICAgICAgKTtcbiAgICAvKiBlc2xpbnQtZW5hYmxlIG5vLWNvbnNvbGUgKi9cblxuICAgIGNvbnN0IHVzZXJTZW5zaXRpdmVGaWVsZHMgPSBBcnJheS5mcm9tKFxuICAgICAgbmV3IFNldChbLi4uKGRlZmF1bHRzLnVzZXJTZW5zaXRpdmVGaWVsZHMgfHwgW10pLCAuLi4ob3B0aW9ucy51c2VyU2Vuc2l0aXZlRmllbGRzIHx8IFtdKV0pXG4gICAgKTtcblxuICAgIC8vIElmIHRoZSBvcHRpb25zLnByb3RlY3RlZEZpZWxkcyBpcyB1bnNldCxcbiAgICAvLyBpdCdsbCBiZSBhc3NpZ25lZCB0aGUgZGVmYXVsdCBhYm92ZS5cbiAgICAvLyBIZXJlLCBwcm90ZWN0IGFnYWluc3QgdGhlIGNhc2Ugd2hlcmUgcHJvdGVjdGVkRmllbGRzXG4gICAgLy8gaXMgc2V0LCBidXQgZG9lc24ndCBoYXZlIF9Vc2VyLlxuICAgIGlmICghKCdfVXNlcicgaW4gb3B0aW9ucy5wcm90ZWN0ZWRGaWVsZHMpKSB7XG4gICAgICBvcHRpb25zLnByb3RlY3RlZEZpZWxkcyA9IE9iamVjdC5hc3NpZ24oeyBfVXNlcjogW10gfSwgb3B0aW9ucy5wcm90ZWN0ZWRGaWVsZHMpO1xuICAgIH1cblxuICAgIG9wdGlvbnMucHJvdGVjdGVkRmllbGRzWydfVXNlciddWycqJ10gPSBBcnJheS5mcm9tKFxuICAgICAgbmV3IFNldChbLi4uKG9wdGlvbnMucHJvdGVjdGVkRmllbGRzWydfVXNlciddWycqJ10gfHwgW10pLCAuLi51c2VyU2Vuc2l0aXZlRmllbGRzXSlcbiAgICApO1xuICB9XG5cbiAgLy8gTWVyZ2UgcHJvdGVjdGVkRmllbGRzIG9wdGlvbnMgd2l0aCBkZWZhdWx0cy5cbiAgT2JqZWN0LmtleXMoZGVmYXVsdHMucHJvdGVjdGVkRmllbGRzKS5mb3JFYWNoKGMgPT4ge1xuICAgIGNvbnN0IGN1ciA9IG9wdGlvbnMucHJvdGVjdGVkRmllbGRzW2NdO1xuICAgIGlmICghY3VyKSB7XG4gICAgICBvcHRpb25zLnByb3RlY3RlZEZpZWxkc1tjXSA9IGRlZmF1bHRzLnByb3RlY3RlZEZpZWxkc1tjXTtcbiAgICB9IGVsc2Uge1xuICAgICAgT2JqZWN0LmtleXMoZGVmYXVsdHMucHJvdGVjdGVkRmllbGRzW2NdKS5mb3JFYWNoKHIgPT4ge1xuICAgICAgICBjb25zdCB1bnEgPSBuZXcgU2V0KFtcbiAgICAgICAgICAuLi4ob3B0aW9ucy5wcm90ZWN0ZWRGaWVsZHNbY11bcl0gfHwgW10pLFxuICAgICAgICAgIC4uLmRlZmF1bHRzLnByb3RlY3RlZEZpZWxkc1tjXVtyXSxcbiAgICAgICAgXSk7XG4gICAgICAgIG9wdGlvbnMucHJvdGVjdGVkRmllbGRzW2NdW3JdID0gQXJyYXkuZnJvbSh1bnEpO1xuICAgICAgfSk7XG4gICAgfVxuICB9KTtcbn1cblxuLy8gVGhvc2UgY2FuJ3QgYmUgdGVzdGVkIGFzIGl0IHJlcXVpcmVzIGEgc3VicHJvY2Vzc1xuLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbmZ1bmN0aW9uIGNvbmZpZ3VyZUxpc3RlbmVycyhwYXJzZVNlcnZlcikge1xuICBjb25zdCBoYW5kbGVTaHV0ZG93biA9IGZ1bmN0aW9uICgpIHtcbiAgICBwcm9jZXNzLnN0ZG91dC53cml0ZSgnVGVybWluYXRpb24gc2lnbmFsIHJlY2VpdmVkLiBTaHV0dGluZyBkb3duLicpO1xuICAgIHBhcnNlU2VydmVyLmhhbmRsZVNodXRkb3duKCk7XG4gIH07XG4gIHByb2Nlc3Mub24oJ1NJR1RFUk0nLCBoYW5kbGVTaHV0ZG93bik7XG4gIHByb2Nlc3Mub24oJ1NJR0lOVCcsIGhhbmRsZVNodXRkb3duKTtcbn1cblxuZXhwb3J0IGRlZmF1bHQgUGFyc2VTZXJ2ZXI7XG4iXSwibWFwcGluZ3MiOiI7Ozs7OztBQVdBLElBQUFBLFNBQUEsR0FBQUMsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFDLE9BQUEsR0FBQUMsdUJBQUEsQ0FBQUYsT0FBQTtBQUNBLElBQUFHLE9BQUEsR0FBQUosc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFJLGNBQUEsR0FBQUwsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFLLGtCQUFBLEdBQUFOLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBTSxnQkFBQSxHQUFBTixPQUFBO0FBQ0EsSUFBQU8sY0FBQSxHQUFBUCxPQUFBO0FBQ0EsSUFBQVEsZUFBQSxHQUFBUixPQUFBO0FBQ0EsSUFBQVMsWUFBQSxHQUFBVCxPQUFBO0FBQ0EsSUFBQVUsZ0JBQUEsR0FBQVYsT0FBQTtBQUNBLElBQUFXLG1CQUFBLEdBQUFYLE9BQUE7QUFDQSxJQUFBWSxjQUFBLEdBQUFaLE9BQUE7QUFDQSxJQUFBYSxZQUFBLEdBQUFiLE9BQUE7QUFDQSxJQUFBYyxvQkFBQSxHQUFBZCxPQUFBO0FBQ0EsSUFBQWUsb0JBQUEsR0FBQWYsT0FBQTtBQUNBLElBQUFnQixXQUFBLEdBQUFoQixPQUFBO0FBQ0EsSUFBQWlCLHFCQUFBLEdBQUFqQixPQUFBO0FBQ0EsSUFBQWtCLFlBQUEsR0FBQWxCLE9BQUE7QUFDQSxJQUFBbUIsZ0JBQUEsR0FBQW5CLE9BQUE7QUFDQSxJQUFBb0IsV0FBQSxHQUFBcEIsT0FBQTtBQUNBLElBQUFxQixnQkFBQSxHQUFBckIsT0FBQTtBQUNBLElBQUFzQixZQUFBLEdBQUF0QixPQUFBO0FBQ0EsSUFBQXVCLGNBQUEsR0FBQXZCLE9BQUE7QUFDQSxJQUFBd0IsZUFBQSxHQUFBeEIsT0FBQTtBQUNBLElBQUF5QixZQUFBLEdBQUF6QixPQUFBO0FBQ0EsSUFBQTBCLFlBQUEsR0FBQTFCLE9BQUE7QUFDQSxJQUFBMkIsZ0JBQUEsR0FBQTNCLE9BQUE7QUFDQSxJQUFBNEIsZ0JBQUEsR0FBQTVCLE9BQUE7QUFDQSxJQUFBNkIsMEJBQUEsR0FBQTdCLE9BQUE7QUFDQSxJQUFBOEIsV0FBQSxHQUFBNUIsdUJBQUEsQ0FBQUYsT0FBQTtBQUNBLElBQUErQixtQkFBQSxHQUFBL0IsT0FBQTtBQUNBLElBQUFnQyxlQUFBLEdBQUFoQyxPQUFBO0FBQ0EsSUFBQWlDLFlBQUEsR0FBQWxDLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBa0MsV0FBQSxHQUFBbkMsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFtQyxlQUFBLEdBQUFuQyxPQUFBO0FBQ0EsSUFBQW9DLFlBQUEsR0FBQXJDLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBcUMsVUFBQSxHQUFBckMsT0FBQTtBQUE0RCxTQUFBRSx3QkFBQW9DLENBQUEsRUFBQUMsQ0FBQSw2QkFBQUMsT0FBQSxNQUFBQyxDQUFBLE9BQUFELE9BQUEsSUFBQUUsQ0FBQSxPQUFBRixPQUFBLFlBQUF0Qyx1QkFBQSxZQUFBQSxDQUFBb0MsQ0FBQSxFQUFBQyxDQUFBLFNBQUFBLENBQUEsSUFBQUQsQ0FBQSxJQUFBQSxDQUFBLENBQUFLLFVBQUEsU0FBQUwsQ0FBQSxNQUFBTSxDQUFBLEVBQUFDLENBQUEsRUFBQUMsQ0FBQSxLQUFBQyxTQUFBLFFBQUFDLE9BQUEsRUFBQVYsQ0FBQSxpQkFBQUEsQ0FBQSx1QkFBQUEsQ0FBQSx5QkFBQUEsQ0FBQSxTQUFBUSxDQUFBLE1BQUFGLENBQUEsR0FBQUwsQ0FBQSxHQUFBRyxDQUFBLEdBQUFELENBQUEsUUFBQUcsQ0FBQSxDQUFBSyxHQUFBLENBQUFYLENBQUEsVUFBQU0sQ0FBQSxDQUFBTSxHQUFBLENBQUFaLENBQUEsR0FBQU0sQ0FBQSxDQUFBTyxHQUFBLENBQUFiLENBQUEsRUFBQVEsQ0FBQSxnQkFBQVAsQ0FBQSxJQUFBRCxDQUFBLGdCQUFBQyxDQUFBLE9BQUFhLGNBQUEsQ0FBQUMsSUFBQSxDQUFBZixDQUFBLEVBQUFDLENBQUEsT0FBQU0sQ0FBQSxJQUFBRCxDQUFBLEdBQUFVLE1BQUEsQ0FBQUMsY0FBQSxLQUFBRCxNQUFBLENBQUFFLHdCQUFBLENBQUFsQixDQUFBLEVBQUFDLENBQUEsT0FBQU0sQ0FBQSxDQUFBSyxHQUFBLElBQUFMLENBQUEsQ0FBQU0sR0FBQSxJQUFBUCxDQUFBLENBQUFFLENBQUEsRUFBQVAsQ0FBQSxFQUFBTSxDQUFBLElBQUFDLENBQUEsQ0FBQVAsQ0FBQSxJQUFBRCxDQUFBLENBQUFDLENBQUEsV0FBQU8sQ0FBQSxLQUFBUixDQUFBLEVBQUFDLENBQUE7QUFBQSxTQUFBeEMsdUJBQUF1QyxDQUFBLFdBQUFBLENBQUEsSUFBQUEsQ0FBQSxDQUFBSyxVQUFBLEdBQUFMLENBQUEsS0FBQVUsT0FBQSxFQUFBVixDQUFBO0FBL0M1RDs7QUFFQSxJQUFJbUIsS0FBSyxHQUFHekQsT0FBTyxDQUFDLFNBQVMsQ0FBQztFQUM1QjBELE9BQU8sR0FBRzFELE9BQU8sQ0FBQyxTQUFTLENBQUM7RUFDNUIyRCxXQUFXLEdBQUczRCxPQUFPLENBQUMsZUFBZSxDQUFDO0VBQ3RDNEQsS0FBSyxHQUFHNUQsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDNEQsS0FBSztFQUNuQztJQUFFQztFQUFNLENBQUMsR0FBRzdELE9BQU8sQ0FBQyxTQUFTLENBQUM7RUFDOUI4RCxJQUFJLEdBQUc5RCxPQUFPLENBQUMsTUFBTSxDQUFDO0VBQ3RCK0QsRUFBRSxHQUFHL0QsT0FBTyxDQUFDLElBQUksQ0FBQztBQXlDcEI7QUFDQWdFLGFBQWEsQ0FBQyxDQUFDOztBQUVmO0FBQ0EsTUFBTUMsV0FBVyxHQUFHLElBQUlDLHNCQUFXLENBQUMsQ0FBQzs7QUFFckM7QUFDQTtBQUNBLE1BQU1DLFdBQVcsQ0FBQztFQU1oQjtBQUNGO0FBQ0E7QUFDQTtFQUNFQyxXQUFXQSxDQUFDQyxPQUEyQixFQUFFO0lBQ3ZDO0lBQ0FDLG1CQUFVLENBQUNDLHNCQUFzQixDQUFDRixPQUFPLENBQUM7SUFFMUMsTUFBTUcsVUFBVSxHQUFHQyxJQUFJLENBQUNaLEtBQUssQ0FBQ1ksSUFBSSxDQUFDQyxTQUFTLENBQUNDLG9CQUFrQixDQUFDLENBQUM7SUFFakUsU0FBU0MsY0FBY0EsQ0FBQ0MsSUFBSSxFQUFFO01BQzVCLE1BQU1DLE1BQU0sR0FBRyxDQUFDLENBQUM7TUFDakIsS0FBSyxNQUFNQyxHQUFHLElBQUlGLElBQUksRUFBRTtRQUN0QixJQUFJdkIsTUFBTSxDQUFDMEIsU0FBUyxDQUFDNUIsY0FBYyxDQUFDQyxJQUFJLENBQUN3QixJQUFJLENBQUNFLEdBQUcsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxFQUFFO1VBQzNELElBQUlGLElBQUksQ0FBQ0UsR0FBRyxDQUFDLENBQUNFLElBQUksQ0FBQ0MsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFO1lBQ2pDSixNQUFNLENBQUNDLEdBQUcsQ0FBQyxHQUFHLENBQUNILGNBQWMsQ0FBQ0osVUFBVSxDQUFDSyxJQUFJLENBQUNFLEdBQUcsQ0FBQyxDQUFDRSxJQUFJLENBQUNFLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7VUFDekUsQ0FBQyxNQUFNO1lBQ0xMLE1BQU0sQ0FBQ0MsR0FBRyxDQUFDLEdBQUdILGNBQWMsQ0FBQ0osVUFBVSxDQUFDSyxJQUFJLENBQUNFLEdBQUcsQ0FBQyxDQUFDRSxJQUFJLENBQUMsQ0FBQztVQUMxRDtRQUNGLENBQUMsTUFBTTtVQUNMSCxNQUFNLENBQUNDLEdBQUcsQ0FBQyxHQUFHLEVBQUU7UUFDbEI7TUFDRjtNQUNBLE9BQU9ELE1BQU07SUFDZjtJQUVBLE1BQU1NLGdCQUFnQixHQUFHUixjQUFjLENBQUNKLFVBQVUsQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO0lBRXpFLFNBQVNhLGdCQUFnQkEsQ0FBQ0MsUUFBUSxFQUFFQyxHQUFHLEVBQUVDLElBQUksR0FBRyxFQUFFLEVBQUU7TUFDbEQsSUFBSVYsTUFBTSxHQUFHLEVBQUU7TUFDZixNQUFNVyxNQUFNLEdBQUdELElBQUksSUFBSUEsSUFBSSxLQUFLLEVBQUUsR0FBRyxHQUFHLEdBQUcsRUFBRSxDQUFDO01BQzlDLEtBQUssTUFBTVQsR0FBRyxJQUFJTyxRQUFRLEVBQUU7UUFDMUIsSUFBSSxDQUFDaEMsTUFBTSxDQUFDMEIsU0FBUyxDQUFDNUIsY0FBYyxDQUFDQyxJQUFJLENBQUNrQyxHQUFHLEVBQUVSLEdBQUcsQ0FBQyxFQUFFO1VBQ25ERCxNQUFNLENBQUNZLElBQUksQ0FBQ0QsTUFBTSxHQUFHVixHQUFHLENBQUM7UUFDM0IsQ0FBQyxNQUFNO1VBQ0wsSUFBSVEsR0FBRyxDQUFDUixHQUFHLENBQUMsS0FBSyxFQUFFLEVBQUU7WUFBRTtVQUFVO1VBQ2pDLElBQUlZLEdBQUcsR0FBRyxFQUFFO1VBQ1osSUFBSUMsS0FBSyxDQUFDQyxPQUFPLENBQUNQLFFBQVEsQ0FBQ1AsR0FBRyxDQUFDLENBQUMsSUFBSWEsS0FBSyxDQUFDQyxPQUFPLENBQUNOLEdBQUcsQ0FBQ1IsR0FBRyxDQUFDLENBQUMsRUFBRTtZQUMzRCxNQUFNRSxJQUFJLEdBQUdNLEdBQUcsQ0FBQ1IsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3hCTyxRQUFRLENBQUNQLEdBQUcsQ0FBQyxDQUFDZSxPQUFPLENBQUMsQ0FBQ0MsSUFBSSxFQUFFQyxHQUFHLEtBQUs7Y0FDbkMsSUFBSSxPQUFPRCxJQUFJLEtBQUssUUFBUSxJQUFJQSxJQUFJLEtBQUssSUFBSSxFQUFFO2dCQUM3Q0osR0FBRyxHQUFHQSxHQUFHLENBQUNNLE1BQU0sQ0FBQ1osZ0JBQWdCLENBQUNVLElBQUksRUFBRWQsSUFBSSxFQUFFUSxNQUFNLEdBQUdWLEdBQUcsR0FBRyxJQUFJaUIsR0FBRyxHQUFHLENBQUMsQ0FBQztjQUMzRTtZQUNGLENBQUMsQ0FBQztVQUNKLENBQUMsTUFBTSxJQUFJLE9BQU9WLFFBQVEsQ0FBQ1AsR0FBRyxDQUFDLEtBQUssUUFBUSxJQUFJLE9BQU9RLEdBQUcsQ0FBQ1IsR0FBRyxDQUFDLEtBQUssUUFBUSxFQUFFO1lBQzVFWSxHQUFHLEdBQUdOLGdCQUFnQixDQUFDQyxRQUFRLENBQUNQLEdBQUcsQ0FBQyxFQUFFUSxHQUFHLENBQUNSLEdBQUcsQ0FBQyxFQUFFVSxNQUFNLEdBQUdWLEdBQUcsQ0FBQztVQUMvRDtVQUNBRCxNQUFNLEdBQUdBLE1BQU0sQ0FBQ21CLE1BQU0sQ0FBQ04sR0FBRyxDQUFDO1FBQzdCO01BQ0Y7TUFDQSxPQUFPYixNQUFNO0lBQ2Y7SUFFQSxNQUFNb0IsSUFBSSxHQUFHYixnQkFBZ0IsQ0FBQ2hCLE9BQU8sRUFBRWUsZ0JBQWdCLENBQUM7SUFDeEQsSUFBSWMsSUFBSSxDQUFDQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO01BQ25CLE1BQU1DLE1BQU0sR0FBSW5HLE9BQU8sQ0FBU21HLE1BQU07TUFDdENBLE1BQU0sQ0FBQ0MsS0FBSyxDQUFDLHVEQUF1REgsSUFBSSxDQUFDSSxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztJQUN4Rjs7SUFFQTtJQUNBQyxjQUFjLENBQUNsQyxPQUFPLENBQUM7SUFDdkIsTUFBTTtNQUNKbUMsS0FBSyxHQUFHLElBQUFDLDBCQUFpQixFQUFDLDRCQUE0QixDQUFDO01BQ3ZEQyxTQUFTLEdBQUcsSUFBQUQsMEJBQWlCLEVBQUMsK0JBQStCLENBQUM7TUFDOURFLGFBQWE7TUFDYkMsU0FBUyxHQUFHLElBQUFILDBCQUFpQixFQUFDLCtCQUErQjtJQUMvRCxDQUFDLEdBQUdwQyxPQUFPO0lBQ1g7SUFDQVQsS0FBSyxDQUFDaUQsVUFBVSxDQUFDTCxLQUFLLEVBQUVHLGFBQWEsSUFBSSxRQUFRLEVBQUVELFNBQVMsQ0FBQztJQUM3RDlDLEtBQUssQ0FBQ2dELFNBQVMsR0FBR0EsU0FBUztJQUMzQkUsZUFBTSxDQUFDQyxlQUFlLENBQUMxQyxPQUFPLENBQUM7SUFDL0IsTUFBTTJDLGNBQWMsR0FBR2xGLFdBQVcsQ0FBQ21GLGNBQWMsQ0FBQzVDLE9BQU8sQ0FBQztJQUV6REEsT0FBTyxDQUFTNkMsS0FBSyxHQUFHLGFBQWE7SUFDdEMsSUFBSSxDQUFDQyxNQUFNLEdBQUdMLGVBQU0sQ0FBQ00sR0FBRyxDQUFDOUQsTUFBTSxDQUFDK0QsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFaEQsT0FBTyxFQUFFMkMsY0FBYyxDQUFDLENBQUM7SUFDcEUsSUFBSSxDQUFDRyxNQUFNLENBQUNHLGlCQUFpQixHQUFHLElBQUlDLEdBQUcsQ0FBQyxDQUFDO0lBQ3pDLElBQUksQ0FBQ0osTUFBTSxDQUFDSyxzQkFBc0IsR0FBRyxJQUFJRCxHQUFHLENBQUMsQ0FBQztJQUM5Q3RILE9BQU8sQ0FBQ3dILFNBQVMsQ0FBQ1QsY0FBYyxDQUFDVSxnQkFBZ0IsQ0FBQztFQUNwRDs7RUFFQTtBQUNGO0FBQ0E7O0VBRUUsTUFBTUMsS0FBS0EsQ0FBQSxFQUFrQjtJQUMzQixJQUFJO01BQ0YsSUFBSSxJQUFJLENBQUNSLE1BQU0sQ0FBQ0QsS0FBSyxLQUFLLElBQUksRUFBRTtRQUM5QixPQUFPLElBQUk7TUFDYjtNQUNBLElBQUksQ0FBQ0MsTUFBTSxDQUFDRCxLQUFLLEdBQUcsVUFBVTtNQUM5QkosZUFBTSxDQUFDTSxHQUFHLENBQUMsSUFBSSxDQUFDRCxNQUFNLENBQUM7TUFDdkIsTUFBTTtRQUNKUyxrQkFBa0I7UUFDbEJDLGVBQWU7UUFDZkMsZUFBZTtRQUNmQyxLQUFLO1FBQ0xDLFFBQVE7UUFDUkMsTUFBTTtRQUNOQztNQUNGLENBQUMsR0FBRyxJQUFJLENBQUNmLE1BQU07TUFDZixJQUFJO1FBQ0YsTUFBTVMsa0JBQWtCLENBQUNPLHFCQUFxQixDQUFDLENBQUM7TUFDbEQsQ0FBQyxDQUFDLE9BQU83RixDQUFDLEVBQUU7UUFDVixJQUFJQSxDQUFDLENBQUM4RixJQUFJLEtBQUt4RSxLQUFLLENBQUN5RSxLQUFLLENBQUNDLGVBQWUsRUFBRTtVQUMxQyxNQUFNaEcsQ0FBQztRQUNUO01BQ0Y7TUFDQSxNQUFNaUcsY0FBYyxHQUFHLE1BQU16RyxXQUFXLENBQUMwRyxpQkFBaUIsQ0FBQyxJQUFJLENBQUNyQixNQUFNLENBQUM7TUFDdkUsTUFBTVUsZUFBZSxDQUFDWSxJQUFJLENBQUMsQ0FBQztNQUM1QixNQUFNQyxlQUFlLEdBQUcsQ0FBQyxJQUFJLENBQUN2QixNQUFNLENBQUN3QixhQUFhLEdBQUcsQ0FBQyxDQUFDO01BQ3ZELElBQUlWLE1BQU0sRUFBRTtRQUNWUyxlQUFlLENBQUNoRCxJQUFJLENBQUMsSUFBSWtELDhCQUFjLENBQUNYLE1BQU0sRUFBRSxJQUFJLENBQUNkLE1BQU0sQ0FBQyxDQUFDMEIsT0FBTyxDQUFDLENBQUMsQ0FBQztNQUN6RTtNQUNBLElBQ0VmLGVBQWUsQ0FBQ2dCLE9BQU8sRUFBRUMsT0FBTyxJQUNoQyxPQUFPakIsZUFBZSxDQUFDZ0IsT0FBTyxDQUFDQyxPQUFPLEtBQUssVUFBVSxFQUNyRDtRQUNBTCxlQUFlLENBQUNoRCxJQUFJLENBQUNvQyxlQUFlLENBQUNnQixPQUFPLENBQUNDLE9BQU8sQ0FBQyxDQUFDLENBQUM7TUFDekQ7TUFDQUwsZUFBZSxDQUFDaEQsSUFBSSxDQUFDd0MsbUJBQW1CLENBQUNhLE9BQU8sQ0FBQyxDQUFDLENBQUM7TUFDbkQsTUFBTUMsT0FBTyxDQUFDQyxHQUFHLENBQUNQLGVBQWUsQ0FBQztNQUNsQyxJQUFJWCxLQUFLLEVBQUU7UUFDVC9ELGFBQWEsQ0FBQyxDQUFDO1FBQ2YsSUFBSSxPQUFPK0QsS0FBSyxLQUFLLFVBQVUsRUFBRTtVQUMvQixNQUFNaUIsT0FBTyxDQUFDRSxPQUFPLENBQUNuQixLQUFLLENBQUNuRSxLQUFLLENBQUMsQ0FBQztRQUNyQyxDQUFDLE1BQU0sSUFBSSxPQUFPbUUsS0FBSyxLQUFLLFFBQVEsRUFBRTtVQUNwQyxJQUFJb0IsSUFBSTtVQUNSLElBQUlDLE9BQU8sQ0FBQ0MsR0FBRyxDQUFDQyxnQkFBZ0IsRUFBRTtZQUNoQ0gsSUFBSSxHQUFHbkosT0FBTyxDQUFDb0osT0FBTyxDQUFDQyxHQUFHLENBQUNDLGdCQUFnQixDQUFDO1VBQzlDO1VBQ0EsSUFBSUYsT0FBTyxDQUFDQyxHQUFHLENBQUNFLGdCQUFnQixLQUFLLFFBQVEsSUFBSUosSUFBSSxFQUFFbEUsSUFBSSxLQUFLLFFBQVEsRUFBRTtZQUN4RSxNQUFNLE1BQU0sQ0FBQ25CLElBQUksQ0FBQ29GLE9BQU8sQ0FBQ0UsT0FBTyxDQUFDSSxHQUFHLENBQUMsQ0FBQyxFQUFFekIsS0FBSyxDQUFDLENBQUM7VUFDbEQsQ0FBQyxNQUFNO1lBQ0wvSCxPQUFPLENBQUM4RCxJQUFJLENBQUNvRixPQUFPLENBQUNFLE9BQU8sQ0FBQ0ksR0FBRyxDQUFDLENBQUMsRUFBRXpCLEtBQUssQ0FBQyxDQUFDO1VBQzdDO1FBQ0YsQ0FBQyxNQUFNO1VBQ0wsTUFBTSx3REFBd0Q7UUFDaEU7UUFDQSxNQUFNLElBQUlpQixPQUFPLENBQUNFLE9BQU8sSUFBSU8sVUFBVSxDQUFDUCxPQUFPLEVBQUUsRUFBRSxDQUFDLENBQUM7TUFDdkQ7TUFDQSxJQUFJbEIsUUFBUSxJQUFJQSxRQUFRLENBQUMwQixXQUFXLElBQUkxQixRQUFRLENBQUMyQixjQUFjLEVBQUU7UUFDL0QsSUFBSUMsb0JBQVcsQ0FBQzVCLFFBQVEsQ0FBQyxDQUFDNkIsR0FBRyxDQUFDLENBQUM7TUFDakM7TUFDQSxJQUFJLENBQUMxQyxNQUFNLENBQUNELEtBQUssR0FBRyxJQUFJO01BQ3hCLElBQUksQ0FBQ0MsTUFBTSxHQUFHO1FBQUUsR0FBRyxJQUFJLENBQUNBLE1BQU07UUFBRSxHQUFHb0I7TUFBZSxDQUFDO01BQ25EekIsZUFBTSxDQUFDTSxHQUFHLENBQUMsSUFBSSxDQUFDRCxNQUFNLENBQUM7TUFDdkIsT0FBTyxJQUFJO0lBQ2IsQ0FBQyxDQUFDLE9BQU9kLEtBQUssRUFBRTtNQUNkO01BQ0F5RCxPQUFPLENBQUN6RCxLQUFLLENBQUNBLEtBQUssQ0FBQztNQUNwQixJQUFJLENBQUNjLE1BQU0sQ0FBQ0QsS0FBSyxHQUFHLE9BQU87TUFDM0IsTUFBTWIsS0FBSztJQUNiO0VBQ0Y7RUFFQSxJQUFJMEQsR0FBR0EsQ0FBQSxFQUFHO0lBQ1IsSUFBSSxDQUFDLElBQUksQ0FBQ0MsSUFBSSxFQUFFO01BQ2QsSUFBSSxDQUFDQSxJQUFJLEdBQUc3RixXQUFXLENBQUM0RixHQUFHLENBQUMsSUFBSSxDQUFDNUMsTUFBTSxDQUFDO0lBQzFDO0lBQ0EsT0FBTyxJQUFJLENBQUM2QyxJQUFJO0VBQ2xCOztFQUVBO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtFQUNFLE1BQU1DLGNBQWNBLENBQUEsRUFBRztJQUNyQixNQUFNQyxrQkFBa0IsR0FBRyxJQUFBQywyQkFBZ0IsRUFBQyxDQUFDO0lBQzdDLE1BQU1DLDJCQUEyQixHQUFHLElBQUFELDJCQUFnQixFQUFDLENBQUM7SUFDdEQsTUFBTUUsUUFBUSxHQUFHLEVBQUU7SUFDbkIsSUFBSSxDQUFDQyxNQUFNLENBQUNDLEtBQUssQ0FBRWxFLEtBQUssSUFBSztNQUMzQjtNQUNBLElBQUlBLEtBQUssRUFBRTtRQUNUO1FBQ0F5RCxPQUFPLENBQUN6RCxLQUFLLENBQUMsa0NBQWtDLEVBQUVBLEtBQUssQ0FBQztNQUMxRDtNQUNBNkQsa0JBQWtCLENBQUNoQixPQUFPLENBQUMsQ0FBQztJQUM5QixDQUFDLENBQUM7SUFDRixJQUFJLElBQUksQ0FBQ3NCLGVBQWUsRUFBRUYsTUFBTSxFQUFFQyxLQUFLLElBQUksSUFBSSxDQUFDQyxlQUFlLENBQUNGLE1BQU0sS0FBSyxJQUFJLENBQUNBLE1BQU0sRUFBRTtNQUN0RixJQUFJLENBQUNFLGVBQWUsQ0FBQ0YsTUFBTSxDQUFDQyxLQUFLLENBQUVsRSxLQUFLLElBQUs7UUFDM0M7UUFDQSxJQUFJQSxLQUFLLEVBQUU7VUFDVDtVQUNBeUQsT0FBTyxDQUFDekQsS0FBSyxDQUFDLHVDQUF1QyxFQUFFQSxLQUFLLENBQUM7UUFDL0Q7UUFDQStELDJCQUEyQixDQUFDbEIsT0FBTyxDQUFDLENBQUM7TUFDdkMsQ0FBQyxDQUFDO0lBQ0osQ0FBQyxNQUFNO01BQ0xrQiwyQkFBMkIsQ0FBQ2xCLE9BQU8sQ0FBQyxDQUFDO0lBQ3ZDO0lBQ0EsTUFBTTtNQUFFSixPQUFPLEVBQUUyQjtJQUFnQixDQUFDLEdBQUcsSUFBSSxDQUFDdEQsTUFBTSxDQUFDUyxrQkFBa0I7SUFDbkUsSUFBSTZDLGVBQWUsSUFBSSxPQUFPQSxlQUFlLENBQUNSLGNBQWMsS0FBSyxVQUFVLEVBQUU7TUFDM0VJLFFBQVEsQ0FBQzNFLElBQUksQ0FBQytFLGVBQWUsQ0FBQ1IsY0FBYyxDQUFDLENBQUMsQ0FBQztJQUNqRDtJQUNBLE1BQU07TUFBRW5CLE9BQU8sRUFBRTRCO0lBQVksQ0FBQyxHQUFHLElBQUksQ0FBQ3ZELE1BQU0sQ0FBQ3dELGVBQWU7SUFDNUQsSUFBSUQsV0FBVyxJQUFJLE9BQU9BLFdBQVcsQ0FBQ1QsY0FBYyxLQUFLLFVBQVUsRUFBRTtNQUNuRUksUUFBUSxDQUFDM0UsSUFBSSxDQUFDZ0YsV0FBVyxDQUFDVCxjQUFjLENBQUMsQ0FBQyxDQUFDO0lBQzdDO0lBQ0EsTUFBTTtNQUFFbkIsT0FBTyxFQUFFOEI7SUFBYSxDQUFDLEdBQUcsSUFBSSxDQUFDekQsTUFBTSxDQUFDVyxlQUFlO0lBQzdELElBQUk4QyxZQUFZLElBQUksT0FBT0EsWUFBWSxDQUFDWCxjQUFjLEtBQUssVUFBVSxFQUFFO01BQ3JFSSxRQUFRLENBQUMzRSxJQUFJLENBQUNrRixZQUFZLENBQUNYLGNBQWMsQ0FBQyxDQUFDLENBQUM7SUFDOUM7SUFDQSxJQUFJLElBQUksQ0FBQ08sZUFBZSxFQUFFO01BQ3hCSCxRQUFRLENBQUMzRSxJQUFJLENBQUMsSUFBSSxDQUFDOEUsZUFBZSxDQUFDSyxRQUFRLENBQUMsQ0FBQyxDQUFDO0lBQ2hEO0lBQ0EsTUFBTTdCLE9BQU8sQ0FBQ0MsR0FBRyxDQUFDb0IsUUFBUSxDQUFDO0lBQzNCcEcsV0FBVyxDQUFDNkcsVUFBVSxDQUFDLENBQUM7SUFDeEIsTUFBTTlCLE9BQU8sQ0FBQ0MsR0FBRyxDQUFDLENBQUNpQixrQkFBa0IsRUFBRUUsMkJBQTJCLENBQUMsQ0FBQztJQUNwRSxJQUFJLElBQUksQ0FBQ2pELE1BQU0sQ0FBQzRELG1CQUFtQixFQUFFO01BQ25DLElBQUksQ0FBQzVELE1BQU0sQ0FBQzRELG1CQUFtQixDQUFDLENBQUM7SUFDbkM7RUFDRjs7RUFFQTtBQUNGO0FBQ0E7QUFDQTtFQUNFLE9BQU9DLDZCQUE2QkEsQ0FBQ0MsR0FBRyxFQUFFNUcsT0FBTyxFQUFFO0lBQ2pELElBQUlBLE9BQU8sQ0FBQzZHLHdCQUF3QixFQUFFO01BQ3BDLElBQUksT0FBTzdHLE9BQU8sQ0FBQzZHLHdCQUF3QixLQUFLLFVBQVUsRUFBRTtRQUMxRCxNQUFNLElBQUk3QyxLQUFLLENBQUMsNkNBQTZDLENBQUM7TUFDaEU7TUFDQTRDLEdBQUcsQ0FBQ0UsR0FBRyxDQUFDOUcsT0FBTyxDQUFDNkcsd0JBQXdCLENBQUM7SUFDM0M7RUFDRjtFQUNBO0FBQ0Y7QUFDQTtBQUNBO0VBQ0UsT0FBT25CLEdBQUdBLENBQUMxRixPQUFPLEVBQUU7SUFDbEIsTUFBTTtNQUNKK0csYUFBYSxHQUFHLE1BQU07TUFDdEI1RSxLQUFLO01BQ0w2RSxZQUFZO01BQ1pDLEtBQUs7TUFDTEMsU0FBUyxHQUFHO0lBQ2QsQ0FBQyxHQUFHbEgsT0FBTztJQUNYO0lBQ0E7SUFDQSxJQUFJNEcsR0FBRyxHQUFHdkgsT0FBTyxDQUFDLENBQUM7SUFDbkI7SUFDQXVILEdBQUcsQ0FBQ0UsR0FBRyxDQUFDeEgsV0FBVyxDQUFDNkgsZ0JBQWdCLENBQUNoRixLQUFLLENBQUMsQ0FBQztJQUM1Q3lFLEdBQUcsQ0FBQ0UsR0FBRyxDQUFDeEgsV0FBVyxDQUFDOEgsdUJBQXVCLENBQUM7SUFDNUM7SUFDQVIsR0FBRyxDQUFDRSxHQUFHLENBQ0wsR0FBRyxFQUNILElBQUlPLHdCQUFXLENBQUMsQ0FBQyxDQUFDQyxhQUFhLENBQUM7TUFDOUJQLGFBQWEsRUFBRUE7SUFDakIsQ0FBQyxDQUNILENBQUM7SUFFREgsR0FBRyxDQUFDRSxHQUFHLENBQUMsU0FBUyxFQUFFLFVBQVVTLEdBQUcsRUFBRWpHLEdBQUcsRUFBRTtNQUNyQ0EsR0FBRyxDQUFDa0csTUFBTSxDQUFDeEgsT0FBTyxDQUFDNkMsS0FBSyxLQUFLLElBQUksR0FBRyxHQUFHLEdBQUcsR0FBRyxDQUFDO01BQzlDLElBQUk3QyxPQUFPLENBQUM2QyxLQUFLLEtBQUssVUFBVSxFQUFFO1FBQ2hDdkIsR0FBRyxDQUFDeEMsR0FBRyxDQUFDLGFBQWEsRUFBRSxDQUFDLENBQUM7TUFDM0I7TUFDQXdDLEdBQUcsQ0FBQ3dELElBQUksQ0FBQztRQUNQMEMsTUFBTSxFQUFFeEgsT0FBTyxDQUFDNkM7TUFDbEIsQ0FBQyxDQUFDO0lBQ0osQ0FBQyxDQUFDO0lBRUYrRCxHQUFHLENBQUNFLEdBQUcsQ0FDTCxHQUFHLEVBQ0h6SCxPQUFPLENBQUNvSSxVQUFVLENBQUM7TUFBRUMsUUFBUSxFQUFFO0lBQU0sQ0FBQyxDQUFDLEVBQ3ZDVCxLQUFLLENBQUNVLFlBQVksR0FDZCxJQUFJQyx3QkFBVyxDQUFDWCxLQUFLLENBQUMsQ0FBQ0ssYUFBYSxDQUFDLENBQUMsR0FDdEMsSUFBSU8sZ0NBQWUsQ0FBQyxDQUFDLENBQUNQLGFBQWEsQ0FBQyxDQUMxQyxDQUFDO0lBRURWLEdBQUcsQ0FBQ0UsR0FBRyxDQUFDekgsT0FBTyxDQUFDeUYsSUFBSSxDQUFDO01BQUVsRSxJQUFJLEVBQUUsS0FBSztNQUFFa0gsS0FBSyxFQUFFZjtJQUFjLENBQUMsQ0FBQyxDQUFDO0lBQzVESCxHQUFHLENBQUNFLEdBQUcsQ0FBQ3hILFdBQVcsQ0FBQ3lJLG1CQUFtQixDQUFDO0lBQ3hDbkIsR0FBRyxDQUFDRSxHQUFHLENBQUN4SCxXQUFXLENBQUMwSSxrQkFBa0IsQ0FBQztJQUN2Q3BCLEdBQUcsQ0FBQzlILEdBQUcsQ0FBQyxjQUFjLEVBQUUsVUFBVSxDQUFDO0lBQ25DLE1BQU1tSixNQUFNLEdBQUcxRyxLQUFLLENBQUNDLE9BQU8sQ0FBQzBGLFNBQVMsQ0FBQyxHQUFHQSxTQUFTLEdBQUcsQ0FBQ0EsU0FBUyxDQUFDO0lBQ2pFLEtBQUssTUFBTWdCLEtBQUssSUFBSUQsTUFBTSxFQUFFO01BQzFCM0ksV0FBVyxDQUFDNkksWUFBWSxDQUFDRCxLQUFLLEVBQUVsSSxPQUFPLENBQUM7SUFDMUM7SUFDQTRHLEdBQUcsQ0FBQ0UsR0FBRyxDQUFDeEgsV0FBVyxDQUFDOEksa0JBQWtCLENBQUM7SUFDdkMsSUFBSSxDQUFDekIsNkJBQTZCLENBQUNDLEdBQUcsRUFBRTVHLE9BQU8sQ0FBQztJQUNoRCxNQUFNcUksU0FBUyxHQUFHdkksV0FBVyxDQUFDd0ksYUFBYSxDQUFDO01BQUVuRztJQUFNLENBQUMsQ0FBQztJQUN0RHlFLEdBQUcsQ0FBQ0UsR0FBRyxDQUFDdUIsU0FBUyxDQUFDZixhQUFhLENBQUMsQ0FBQyxDQUFDO0lBRWxDVixHQUFHLENBQUNFLEdBQUcsQ0FBQ3hILFdBQVcsQ0FBQ2lKLGlCQUFpQixDQUFDOztJQUV0QztJQUNBLElBQUksQ0FBQ3hELE9BQU8sQ0FBQ0MsR0FBRyxDQUFDd0QsT0FBTyxFQUFFO01BQ3hCO01BQ0E7TUFDQXpELE9BQU8sQ0FBQzBELEVBQUUsQ0FBQyxtQkFBbUIsRUFBR0MsR0FBUSxJQUFLO1FBQzVDLElBQUlBLEdBQUcsQ0FBQzNFLElBQUksS0FBSyxZQUFZLEVBQUU7VUFDN0I7VUFDQWdCLE9BQU8sQ0FBQzRELE1BQU0sQ0FBQ0MsS0FBSyxDQUFDLDRCQUE0QkYsR0FBRyxDQUFDRyxJQUFJLCtCQUErQixDQUFDO1VBQ3pGOUQsT0FBTyxDQUFDK0QsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUNqQixDQUFDLE1BQU07VUFDTCxJQUFJSixHQUFHLENBQUNLLE9BQU8sRUFBRTtZQUNmaEUsT0FBTyxDQUFDNEQsTUFBTSxDQUFDQyxLQUFLLENBQUMsa0NBQWtDLEdBQUdGLEdBQUcsQ0FBQ0ssT0FBTyxDQUFDO1VBQ3hFO1VBQ0EsSUFBSUwsR0FBRyxDQUFDTSxLQUFLLEVBQUU7WUFDYmpFLE9BQU8sQ0FBQzRELE1BQU0sQ0FBQ0MsS0FBSyxDQUFDLGdCQUFnQixHQUFHRixHQUFHLENBQUNNLEtBQUssQ0FBQztVQUNwRCxDQUFDLE1BQU07WUFDTGpFLE9BQU8sQ0FBQzRELE1BQU0sQ0FBQ0MsS0FBSyxDQUFDRixHQUFHLENBQUM7VUFDM0I7VUFDQTNELE9BQU8sQ0FBQytELElBQUksQ0FBQyxDQUFDLENBQUM7UUFDakI7TUFDRixDQUFDLENBQUM7SUFDSjtJQUNBLElBQUkvRCxPQUFPLENBQUNDLEdBQUcsQ0FBQ2lFLDhDQUE4QyxLQUFLLEdBQUcsSUFBSWpDLFlBQVksRUFBRTtNQUN0RnpILEtBQUssQ0FBQzJKLFdBQVcsQ0FBQ0MsaUJBQWlCLENBQUMsSUFBQUMsb0RBQXlCLEVBQUNqSCxLQUFLLEVBQUVrRyxTQUFTLENBQUMsQ0FBQztJQUNsRjtJQUNBLE9BQU96QixHQUFHO0VBQ1o7RUFFQSxPQUFPMEIsYUFBYUEsQ0FBQztJQUFFbkc7RUFBTSxDQUFDLEVBQUU7SUFDOUIsTUFBTWtILE9BQU8sR0FBRyxDQUNkLElBQUlDLDRCQUFhLENBQUMsQ0FBQyxFQUNuQixJQUFJQyx3QkFBVyxDQUFDLENBQUMsRUFDakIsSUFBSUMsOEJBQWMsQ0FBQyxDQUFDLEVBQ3BCLElBQUlDLHdCQUFXLENBQUMsQ0FBQyxFQUNqQixJQUFJQyxnQ0FBZSxDQUFDLENBQUMsRUFDckIsSUFBSUMsd0NBQW1CLENBQUMsQ0FBQyxFQUN6QixJQUFJQyxnQ0FBZSxDQUFDLENBQUMsRUFDckIsSUFBSUMsNEJBQWEsQ0FBQyxDQUFDLEVBQ25CLElBQUlDLHNCQUFVLENBQUMsQ0FBQyxFQUNoQixJQUFJQyxzQkFBVSxDQUFDLENBQUMsRUFDaEIsSUFBSUMsd0NBQW1CLENBQUMsQ0FBQyxFQUN6QixJQUFJQyw4QkFBYyxDQUFDLENBQUMsRUFDcEIsSUFBSUMsc0NBQWtCLENBQUMsQ0FBQyxFQUN4QixJQUFJQyw0QkFBYSxDQUFDLENBQUMsRUFDbkIsSUFBSUMsd0JBQVcsQ0FBQyxDQUFDLEVBQ2pCLElBQUlDLHdCQUFXLENBQUMsQ0FBQyxFQUNqQixJQUFJQyxnQ0FBZSxDQUFDLENBQUMsRUFDckIsSUFBSUMsZ0NBQWUsQ0FBQyxDQUFDLEVBQ3JCLElBQUlDLGdDQUFlLENBQUMsQ0FBQyxFQUNyQixJQUFJQyw4QkFBYyxDQUFDLENBQUMsQ0FDckI7SUFFRCxNQUFNeEMsTUFBTSxHQUFHb0IsT0FBTyxDQUFDcUIsTUFBTSxDQUFDLENBQUNDLElBQUksRUFBRUMsTUFBTSxLQUFLO01BQzlDLE9BQU9ELElBQUksQ0FBQy9JLE1BQU0sQ0FBQ2dKLE1BQU0sQ0FBQzNDLE1BQU0sQ0FBQztJQUNuQyxDQUFDLEVBQUUsRUFBRSxDQUFDO0lBRU4sTUFBTUksU0FBUyxHQUFHLElBQUl3QyxzQkFBYSxDQUFDNUMsTUFBTSxFQUFFOUYsS0FBSyxDQUFDO0lBRWxEL0MsS0FBSyxDQUFDMEwsU0FBUyxDQUFDekMsU0FBUyxDQUFDO0lBQzFCLE9BQU9BLFNBQVM7RUFDbEI7O0VBRUE7QUFDRjtBQUNBO0FBQ0E7QUFDQTs7RUFFRSxNQUFNMEMsUUFBUUEsQ0FBQy9LLE9BQTJCLEVBQUU7SUFDMUMsSUFBSTtNQUNGLE1BQU0sSUFBSSxDQUFDc0QsS0FBSyxDQUFDLENBQUM7SUFDcEIsQ0FBQyxDQUFDLE9BQU9yRixDQUFDLEVBQUU7TUFDVjtNQUNBd0gsT0FBTyxDQUFDekQsS0FBSyxDQUFDLGlDQUFpQyxFQUFFL0QsQ0FBQyxDQUFDO01BQ25ELE1BQU1BLENBQUM7SUFDVDtJQUNBLE1BQU15SCxHQUFHLEdBQUdyRyxPQUFPLENBQUMsQ0FBQztJQUNyQixJQUFJVyxPQUFPLENBQUNnTCxVQUFVLEVBQUU7TUFDdEIsSUFBSUEsVUFBVTtNQUNkLElBQUksT0FBT2hMLE9BQU8sQ0FBQ2dMLFVBQVUsSUFBSSxRQUFRLEVBQUU7UUFDekNBLFVBQVUsR0FBR3JQLE9BQU8sQ0FBQzhELElBQUksQ0FBQ29GLE9BQU8sQ0FBQ0UsT0FBTyxDQUFDSSxHQUFHLENBQUMsQ0FBQyxFQUFFbkYsT0FBTyxDQUFDZ0wsVUFBVSxDQUFDLENBQUM7TUFDdkUsQ0FBQyxNQUFNO1FBQ0xBLFVBQVUsR0FBR2hMLE9BQU8sQ0FBQ2dMLFVBQVUsQ0FBQyxDQUFDO01BQ25DO01BQ0F0RixHQUFHLENBQUNvQixHQUFHLENBQUNrRSxVQUFVLENBQUM7SUFDckI7SUFDQXRGLEdBQUcsQ0FBQ29CLEdBQUcsQ0FBQzlHLE9BQU8sQ0FBQ2lMLFNBQVMsRUFBRSxJQUFJLENBQUN2RixHQUFHLENBQUM7SUFFcEMsSUFBSTFGLE9BQU8sQ0FBQ2tMLFlBQVksS0FBSyxJQUFJLElBQUlsTCxPQUFPLENBQUNtTCxlQUFlLEtBQUssSUFBSSxFQUFFO01BQ3JFLElBQUlDLHFCQUFxQixHQUFHQyxTQUFTO01BQ3JDLElBQUksT0FBT3JMLE9BQU8sQ0FBQ3NMLGFBQWEsS0FBSyxRQUFRLEVBQUU7UUFDN0NGLHFCQUFxQixHQUFHNUwsS0FBSyxDQUFDRSxFQUFFLENBQUM2TCxZQUFZLENBQUN2TCxPQUFPLENBQUNzTCxhQUFhLEVBQUUsTUFBTSxDQUFDLENBQUM7TUFDL0UsQ0FBQyxNQUFNLElBQ0wsT0FBT3RMLE9BQU8sQ0FBQ3NMLGFBQWEsS0FBSyxRQUFRLElBQ3pDLE9BQU90TCxPQUFPLENBQUNzTCxhQUFhLEtBQUssVUFBVSxFQUMzQztRQUNBRixxQkFBcUIsR0FBR3BMLE9BQU8sQ0FBQ3NMLGFBQWE7TUFDL0M7TUFFQSxNQUFNRSxrQkFBa0IsR0FBRyxJQUFJQyxzQ0FBa0IsQ0FBQyxJQUFJLEVBQUU7UUFDdERDLFdBQVcsRUFBRTFMLE9BQU8sQ0FBQzBMLFdBQVc7UUFDaENDLGNBQWMsRUFBRTNMLE9BQU8sQ0FBQzJMLGNBQWM7UUFDdENQO01BQ0YsQ0FBQyxDQUFDO01BRUYsSUFBSXBMLE9BQU8sQ0FBQ2tMLFlBQVksRUFBRTtRQUN4Qk0sa0JBQWtCLENBQUNJLFlBQVksQ0FBQ2xHLEdBQUcsQ0FBQztNQUN0QztNQUVBLElBQUkxRixPQUFPLENBQUNtTCxlQUFlLEVBQUU7UUFDM0JLLGtCQUFrQixDQUFDSyxlQUFlLENBQUNuRyxHQUFHLENBQUM7TUFDekM7SUFDRjtJQUNBLE1BQU1PLE1BQU0sR0FBRyxNQUFNLElBQUl0QixPQUFPLENBQUNFLE9BQU8sSUFBSTtNQUMxQ2EsR0FBRyxDQUFDb0csTUFBTSxDQUFDOUwsT0FBTyxDQUFDNkksSUFBSSxFQUFFN0ksT0FBTyxDQUFDK0wsSUFBSSxFQUFFLFlBQVk7UUFDakRsSCxPQUFPLENBQUMsSUFBSSxDQUFDO01BQ2YsQ0FBQyxDQUFDO0lBQ0osQ0FBQyxDQUFDO0lBQ0YsSUFBSSxDQUFDb0IsTUFBTSxHQUFHQSxNQUFNO0lBQ3BCckcsV0FBVyxDQUFDb00sS0FBSyxDQUFDL0YsTUFBTSxDQUFDO0lBRXpCLElBQUlqRyxPQUFPLENBQUNpTSxvQkFBb0IsSUFBSWpNLE9BQU8sQ0FBQ2tNLHNCQUFzQixFQUFFO01BQ2xFLElBQUksQ0FBQy9GLGVBQWUsR0FBRyxNQUFNckcsV0FBVyxDQUFDcU0scUJBQXFCLENBQzVEbEcsTUFBTSxFQUNOakcsT0FBTyxDQUFDa00sc0JBQXNCLEVBQzlCbE0sT0FDRixDQUFDO01BQ0QsSUFBSSxJQUFJLENBQUNtRyxlQUFlLENBQUNGLE1BQU0sS0FBSyxJQUFJLENBQUNBLE1BQU0sRUFBRTtRQUMvQ3JHLFdBQVcsQ0FBQ29NLEtBQUssQ0FBQyxJQUFJLENBQUM3RixlQUFlLENBQUNGLE1BQU0sQ0FBQztNQUNoRDtJQUNGO0lBQ0EsSUFBSWpHLE9BQU8sQ0FBQ29NLFVBQVUsRUFBRTtNQUN0QjFHLEdBQUcsQ0FBQzVHLEdBQUcsQ0FBQyxhQUFhLEVBQUVrQixPQUFPLENBQUNvTSxVQUFVLENBQUM7SUFDNUM7SUFDQTtJQUNBLElBQUksQ0FBQ3JILE9BQU8sQ0FBQ0MsR0FBRyxDQUFDd0QsT0FBTyxFQUFFO01BQ3hCNkQsa0JBQWtCLENBQUMsSUFBSSxDQUFDO01BQ3hCLElBQUlyTSxPQUFPLENBQUNzTSxlQUFlLEtBQUssS0FBSyxFQUFFO1FBQ3JDLE1BQU14TSxXQUFXLENBQUN3TSxlQUFlLENBQUMsQ0FBQztNQUNyQztJQUNGO0lBQ0EsSUFBSSxDQUFDQyxVQUFVLEdBQUc3RyxHQUFHO0lBQ3JCLE9BQU8sSUFBSTtFQUNiOztFQUVBO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7RUFDRSxhQUFhcUYsUUFBUUEsQ0FBQy9LLE9BQTJCLEVBQUU7SUFDakQsTUFBTXdNLFdBQVcsR0FBRyxJQUFJMU0sV0FBVyxDQUFDRSxPQUFPLENBQUM7SUFDNUMsT0FBT3dNLFdBQVcsQ0FBQ3pCLFFBQVEsQ0FBQy9LLE9BQU8sQ0FBQztFQUN0Qzs7RUFFQTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0VBQ0UsYUFBYW1NLHFCQUFxQkEsQ0FDaENNLFVBQVUsRUFDVjNKLE1BQThCLEVBQzlCOUMsT0FBMkIsRUFDSTtJQUMvQixJQUFJLENBQUN5TSxVQUFVLElBQUszSixNQUFNLElBQUlBLE1BQU0sQ0FBQytGLElBQUssRUFBRTtNQUMxQyxJQUFJbkQsR0FBRyxHQUFHckcsT0FBTyxDQUFDLENBQUM7TUFDbkJvTixVQUFVLEdBQUc5USxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMrUSxZQUFZLENBQUNoSCxHQUFHLENBQUM7TUFDOUMrRyxVQUFVLENBQUNYLE1BQU0sQ0FBQ2hKLE1BQU0sQ0FBQytGLElBQUksQ0FBQztJQUNoQztJQUNBLE1BQU01QyxNQUFNLEdBQUcsSUFBSTBHLDBDQUFvQixDQUFDRixVQUFVLEVBQUUzSixNQUFNLEVBQUU5QyxPQUFPLENBQUM7SUFDcEUsTUFBTWlHLE1BQU0sQ0FBQ3ZCLE9BQU8sQ0FBQyxDQUFDO0lBQ3RCLE9BQU91QixNQUFNO0VBQ2Y7RUFFQSxhQUFhcUcsZUFBZUEsQ0FBQSxFQUFHO0lBQzdCO0lBQ0EsSUFBSS9NLEtBQUssQ0FBQ2dELFNBQVMsRUFBRTtNQUNuQixNQUFNcUssY0FBYyxHQUFHQyxNQUFNLElBQUk7UUFDL0IsSUFBSUMsR0FBRztRQUNQLElBQUk7VUFDRkEsR0FBRyxHQUFHLElBQUlDLEdBQUcsQ0FBQ0YsTUFBTSxDQUFDO1FBQ3ZCLENBQUMsQ0FBQyxPQUFPRyxDQUFDLEVBQUU7VUFDVixPQUFPLEtBQUs7UUFDZDtRQUNBLE9BQU9GLEdBQUcsQ0FBQ0csUUFBUSxLQUFLLE9BQU8sSUFBSUgsR0FBRyxDQUFDRyxRQUFRLEtBQUssUUFBUTtNQUM5RCxDQUFDO01BQ0QsTUFBTUgsR0FBRyxHQUFHLEdBQUd2TixLQUFLLENBQUNnRCxTQUFTLENBQUMySyxPQUFPLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxTQUFTO01BQzFELElBQUksQ0FBQ04sY0FBYyxDQUFDRSxHQUFHLENBQUMsRUFBRTtRQUN4QjtRQUNBckgsT0FBTyxDQUFDMEgsSUFBSSxDQUNWLG9DQUFvQzVOLEtBQUssQ0FBQ2dELFNBQVMsMEJBQTBCLEdBQzNFLDBEQUNKLENBQUM7UUFDRDtNQUNGO01BQ0EsTUFBTTZLLE9BQU8sR0FBR3pSLE9BQU8sQ0FBQyxXQUFXLENBQUM7TUFDcEMsTUFBTTBSLFFBQVEsR0FBRyxNQUFNRCxPQUFPLENBQUM7UUFBRU47TUFBSSxDQUFDLENBQUMsQ0FBQ1EsS0FBSyxDQUFDRCxRQUFRLElBQUlBLFFBQVEsQ0FBQztNQUNuRSxNQUFNdkksSUFBSSxHQUFHdUksUUFBUSxDQUFDRSxJQUFJLElBQUksSUFBSTtNQUNsQyxNQUFNQyxLQUFLLEdBQUdILFFBQVEsQ0FBQ0ksT0FBTyxHQUFHLGFBQWEsQ0FBQztNQUMvQyxJQUFJRCxLQUFLLEVBQUU7UUFDVCxNQUFNLElBQUk3SSxPQUFPLENBQUNFLE9BQU8sSUFBSU8sVUFBVSxDQUFDUCxPQUFPLEVBQUUySSxLQUFLLEdBQUcsSUFBSSxDQUFDLENBQUM7UUFDL0QsT0FBTyxJQUFJLENBQUNsQixlQUFlLENBQUMsQ0FBQztNQUMvQjtNQUNBLElBQUllLFFBQVEsQ0FBQzdGLE1BQU0sS0FBSyxHQUFHLElBQUkxQyxJQUFJLEVBQUUwQyxNQUFNLEtBQUssSUFBSSxFQUFFO1FBQ3BEO1FBQ0EvQixPQUFPLENBQUMwSCxJQUFJLENBQ1Ysb0NBQW9DNU4sS0FBSyxDQUFDZ0QsU0FBUyxJQUFJLEdBQ3JELDBEQUNKLENBQUM7UUFDRDtRQUNBO01BQ0Y7TUFDQSxPQUFPLElBQUk7SUFDYjtFQUNGO0FBQ0Y7QUFFQSxTQUFTNUMsYUFBYUEsQ0FBQSxFQUFHO0VBQ3ZCLE1BQU0rTixVQUFVLEdBQUcvUixPQUFPLENBQUMsMEJBQTBCLENBQUM7RUFDdEQsTUFBTW1FLFdBQVcsR0FBR25FLE9BQU8sQ0FBQywyQkFBMkIsQ0FBQztFQUN4RHNELE1BQU0sQ0FBQ0MsY0FBYyxDQUFDSyxLQUFLLEVBQUUsUUFBUSxFQUFFO0lBQ3JDVixHQUFHQSxDQUFBLEVBQUc7TUFDSixNQUFNOE8sSUFBSSxHQUFHbEwsZUFBTSxDQUFDNUQsR0FBRyxDQUFDVSxLQUFLLENBQUNxTyxhQUFhLENBQUM7TUFDNUMsT0FBTztRQUFFLEdBQUdELElBQUk7UUFBRSxHQUFHN047TUFBWSxDQUFDO0lBQ3BDLENBQUM7SUFDRGhCLEdBQUdBLENBQUMrTyxNQUFNLEVBQUU7TUFDVkEsTUFBTSxDQUFDMUwsS0FBSyxHQUFHNUMsS0FBSyxDQUFDcU8sYUFBYTtNQUNsQ25MLGVBQU0sQ0FBQ00sR0FBRyxDQUFDOEssTUFBTSxDQUFDO0lBQ3BCLENBQUM7SUFDREMsWUFBWSxFQUFFO0VBQ2hCLENBQUMsQ0FBQztFQUNGN08sTUFBTSxDQUFDK0QsTUFBTSxDQUFDekQsS0FBSyxDQUFDd08sS0FBSyxFQUFFTCxVQUFVLENBQUM7RUFDdENNLE1BQU0sQ0FBQ3pPLEtBQUssR0FBR0EsS0FBSztBQUN0QjtBQUVBLFNBQVMyQyxjQUFjQSxDQUFDbEMsT0FBMkIsRUFBRTtFQUNuRGYsTUFBTSxDQUFDZ1AsSUFBSSxDQUFDQyxpQkFBUSxDQUFDLENBQUN6TSxPQUFPLENBQUNmLEdBQUcsSUFBSTtJQUNuQyxJQUFJLENBQUN6QixNQUFNLENBQUMwQixTQUFTLENBQUM1QixjQUFjLENBQUNDLElBQUksQ0FBQ2dCLE9BQU8sRUFBRVUsR0FBRyxDQUFDLEVBQUU7TUFDdkRWLE9BQU8sQ0FBQ1UsR0FBRyxDQUFDLEdBQUd3TixpQkFBUSxDQUFDeE4sR0FBRyxDQUFDO0lBQzlCO0VBQ0YsQ0FBQyxDQUFDO0VBRUYsSUFBSSxDQUFDekIsTUFBTSxDQUFDMEIsU0FBUyxDQUFDNUIsY0FBYyxDQUFDQyxJQUFJLENBQUNnQixPQUFPLEVBQUUsV0FBVyxDQUFDLEVBQUU7SUFDL0RBLE9BQU8sQ0FBQ3VDLFNBQVMsR0FBRyxvQkFBb0J2QyxPQUFPLENBQUM2SSxJQUFJLEdBQUc3SSxPQUFPLENBQUNpTCxTQUFTLEVBQUU7RUFDNUU7O0VBRUE7RUFDQSxJQUFJakwsT0FBTyxDQUFDbUMsS0FBSyxFQUFFO0lBQ2pCLE1BQU1nTSxLQUFLLEdBQUcsK0JBQStCO0lBQzdDLElBQUluTyxPQUFPLENBQUNtQyxLQUFLLENBQUNpTSxLQUFLLENBQUNELEtBQUssQ0FBQyxFQUFFO01BQzlCO01BQ0ExSSxPQUFPLENBQUMwSCxJQUFJLENBQ1YsNkZBQ0YsQ0FBQztJQUNIO0VBQ0Y7O0VBRUE7RUFDQSxJQUFJbk4sT0FBTyxDQUFDcU8sbUJBQW1CLEVBQUU7SUFDL0I7SUFDQSxDQUFDdEosT0FBTyxDQUFDQyxHQUFHLENBQUN3RCxPQUFPLElBQ2xCL0MsT0FBTyxDQUFDMEgsSUFBSSxDQUNWLDJJQUNGLENBQUM7SUFDSDs7SUFFQSxNQUFNa0IsbUJBQW1CLEdBQUc5TSxLQUFLLENBQUMrTSxJQUFJLENBQ3BDLElBQUlDLEdBQUcsQ0FBQyxDQUFDLElBQUlMLGlCQUFRLENBQUNHLG1CQUFtQixJQUFJLEVBQUUsQ0FBQyxFQUFFLElBQUlyTyxPQUFPLENBQUNxTyxtQkFBbUIsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUMzRixDQUFDOztJQUVEO0lBQ0E7SUFDQTtJQUNBO0lBQ0EsSUFBSSxFQUFFLE9BQU8sSUFBSXJPLE9BQU8sQ0FBQ3dPLGVBQWUsQ0FBQyxFQUFFO01BQ3pDeE8sT0FBTyxDQUFDd08sZUFBZSxHQUFHdlAsTUFBTSxDQUFDK0QsTUFBTSxDQUFDO1FBQUV5TCxLQUFLLEVBQUU7TUFBRyxDQUFDLEVBQUV6TyxPQUFPLENBQUN3TyxlQUFlLENBQUM7SUFDakY7SUFFQXhPLE9BQU8sQ0FBQ3dPLGVBQWUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBR2pOLEtBQUssQ0FBQytNLElBQUksQ0FDaEQsSUFBSUMsR0FBRyxDQUFDLENBQUMsSUFBSXZPLE9BQU8sQ0FBQ3dPLGVBQWUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLENBQUMsRUFBRSxHQUFHSCxtQkFBbUIsQ0FBQyxDQUNwRixDQUFDO0VBQ0g7O0VBRUE7RUFDQXBQLE1BQU0sQ0FBQ2dQLElBQUksQ0FBQ0MsaUJBQVEsQ0FBQ00sZUFBZSxDQUFDLENBQUMvTSxPQUFPLENBQUNpTixDQUFDLElBQUk7SUFDakQsTUFBTUMsR0FBRyxHQUFHM08sT0FBTyxDQUFDd08sZUFBZSxDQUFDRSxDQUFDLENBQUM7SUFDdEMsSUFBSSxDQUFDQyxHQUFHLEVBQUU7TUFDUjNPLE9BQU8sQ0FBQ3dPLGVBQWUsQ0FBQ0UsQ0FBQyxDQUFDLEdBQUdSLGlCQUFRLENBQUNNLGVBQWUsQ0FBQ0UsQ0FBQyxDQUFDO0lBQzFELENBQUMsTUFBTTtNQUNMelAsTUFBTSxDQUFDZ1AsSUFBSSxDQUFDQyxpQkFBUSxDQUFDTSxlQUFlLENBQUNFLENBQUMsQ0FBQyxDQUFDLENBQUNqTixPQUFPLENBQUNyRCxDQUFDLElBQUk7UUFDcEQsTUFBTXdRLEdBQUcsR0FBRyxJQUFJTCxHQUFHLENBQUMsQ0FDbEIsSUFBSXZPLE9BQU8sQ0FBQ3dPLGVBQWUsQ0FBQ0UsQ0FBQyxDQUFDLENBQUN0USxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsRUFDeEMsR0FBRzhQLGlCQUFRLENBQUNNLGVBQWUsQ0FBQ0UsQ0FBQyxDQUFDLENBQUN0USxDQUFDLENBQUMsQ0FDbEMsQ0FBQztRQUNGNEIsT0FBTyxDQUFDd08sZUFBZSxDQUFDRSxDQUFDLENBQUMsQ0FBQ3RRLENBQUMsQ0FBQyxHQUFHbUQsS0FBSyxDQUFDK00sSUFBSSxDQUFDTSxHQUFHLENBQUM7TUFDakQsQ0FBQyxDQUFDO0lBQ0o7RUFDRixDQUFDLENBQUM7QUFDSjs7QUFFQTtBQUNBO0FBQ0EsU0FBU3ZDLGtCQUFrQkEsQ0FBQ0csV0FBVyxFQUFFO0VBQ3ZDLE1BQU01RyxjQUFjLEdBQUcsU0FBQUEsQ0FBQSxFQUFZO0lBQ2pDYixPQUFPLENBQUM4SixNQUFNLENBQUNqRyxLQUFLLENBQUMsNkNBQTZDLENBQUM7SUFDbkU0RCxXQUFXLENBQUM1RyxjQUFjLENBQUMsQ0FBQztFQUM5QixDQUFDO0VBQ0RiLE9BQU8sQ0FBQzBELEVBQUUsQ0FBQyxTQUFTLEVBQUU3QyxjQUFjLENBQUM7RUFDckNiLE9BQU8sQ0FBQzBELEVBQUUsQ0FBQyxRQUFRLEVBQUU3QyxjQUFjLENBQUM7QUFDdEM7QUFBQyxJQUFBa0osUUFBQSxHQUFBQyxPQUFBLENBQUFwUSxPQUFBLEdBRWNtQixXQUFXIiwiaWdub3JlTGlzdCI6W119