parse-server 6.0.0-alpha.9 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (192) hide show
  1. package/LICENSE +167 -25
  2. package/NOTICE +10 -0
  3. package/README.md +57 -33
  4. package/lib/AccountLockout.js +11 -26
  5. package/lib/Adapters/AdapterLoader.js +8 -14
  6. package/lib/Adapters/Analytics/AnalyticsAdapter.js +2 -8
  7. package/lib/Adapters/Auth/AuthAdapter.js +7 -16
  8. package/lib/Adapters/Auth/OAuth1Client.js +32 -57
  9. package/lib/Adapters/Auth/apple.js +6 -22
  10. package/lib/Adapters/Auth/facebook.js +7 -37
  11. package/lib/Adapters/Auth/gcenter.js +8 -37
  12. package/lib/Adapters/Auth/github.js +7 -10
  13. package/lib/Adapters/Auth/google.js +11 -34
  14. package/lib/Adapters/Auth/gpgames.js +5 -8
  15. package/lib/Adapters/Auth/httpsRequest.js +1 -7
  16. package/lib/Adapters/Auth/index.js +20 -65
  17. package/lib/Adapters/Auth/instagram.js +5 -9
  18. package/lib/Adapters/Auth/janraincapture.js +8 -12
  19. package/lib/Adapters/Auth/janrainengage.js +7 -11
  20. package/lib/Adapters/Auth/keycloak.js +5 -19
  21. package/lib/Adapters/Auth/ldap.js +1 -15
  22. package/lib/Adapters/Auth/line.js +7 -10
  23. package/lib/Adapters/Auth/linkedin.js +7 -12
  24. package/lib/Adapters/Auth/meetup.js +7 -10
  25. package/lib/Adapters/Auth/microsoft.js +7 -10
  26. package/lib/Adapters/Auth/oauth2.js +6 -18
  27. package/lib/Adapters/Auth/phantauth.js +8 -10
  28. package/lib/Adapters/Auth/qq.js +7 -13
  29. package/lib/Adapters/Auth/spotify.js +7 -14
  30. package/lib/Adapters/Auth/twitter.js +5 -15
  31. package/lib/Adapters/Auth/vkontakte.js +9 -15
  32. package/lib/Adapters/Auth/wechat.js +7 -10
  33. package/lib/Adapters/Auth/weibo.js +7 -11
  34. package/lib/Adapters/Cache/CacheAdapter.js +4 -12
  35. package/lib/Adapters/Cache/InMemoryCache.js +5 -19
  36. package/lib/Adapters/Cache/InMemoryCacheAdapter.js +1 -11
  37. package/lib/Adapters/Cache/LRUCache.js +1 -11
  38. package/lib/Adapters/Cache/NullCacheAdapter.js +1 -8
  39. package/lib/Adapters/Cache/RedisCacheAdapter.js +3 -30
  40. package/lib/Adapters/Cache/SchemaCache.js +1 -6
  41. package/lib/Adapters/Email/MailAdapter.js +2 -7
  42. package/lib/Adapters/Files/FilesAdapter.js +7 -21
  43. package/lib/Adapters/Files/GridFSBucketAdapter.js +6 -44
  44. package/lib/Adapters/Files/GridStoreAdapter.js +1 -1
  45. package/lib/Adapters/Logger/LoggerAdapter.js +2 -11
  46. package/lib/Adapters/Logger/WinstonLogger.js +3 -30
  47. package/lib/Adapters/Logger/WinstonLoggerAdapter.js +5 -16
  48. package/lib/Adapters/MessageQueue/EventEmitterMQ.js +3 -20
  49. package/lib/Adapters/PubSub/EventEmitterPubSub.js +1 -16
  50. package/lib/Adapters/PubSub/PubSubAdapter.js +2 -9
  51. package/lib/Adapters/PubSub/RedisPubSub.js +12 -7
  52. package/lib/Adapters/Push/PushAdapter.js +2 -8
  53. package/lib/Adapters/Storage/Mongo/MongoCollection.js +12 -37
  54. package/lib/Adapters/Storage/Mongo/MongoSchemaCollection.js +26 -79
  55. package/lib/Adapters/Storage/Mongo/MongoStorageAdapter.js +78 -209
  56. package/lib/Adapters/Storage/Mongo/MongoTransform.js +82 -371
  57. package/lib/Adapters/Storage/Postgres/PostgresClient.js +1 -13
  58. package/lib/Adapters/Storage/Postgres/PostgresConfigParser.js +1 -20
  59. package/lib/Adapters/Storage/Postgres/PostgresStorageAdapter.js +119 -446
  60. package/lib/Adapters/Storage/Postgres/sql/index.js +4 -7
  61. package/lib/Adapters/Storage/StorageAdapter.js +1 -1
  62. package/lib/Adapters/WebSocketServer/WSAdapter.js +3 -12
  63. package/lib/Adapters/WebSocketServer/WSSAdapter.js +7 -12
  64. package/lib/Auth.js +68 -121
  65. package/lib/ClientSDK.js +3 -11
  66. package/lib/Config.js +73 -115
  67. package/lib/Controllers/AdaptableController.js +6 -18
  68. package/lib/Controllers/AnalyticsController.js +1 -9
  69. package/lib/Controllers/CacheController.js +3 -23
  70. package/lib/Controllers/DatabaseController.js +171 -364
  71. package/lib/Controllers/FilesController.js +5 -34
  72. package/lib/Controllers/HooksController.js +1 -51
  73. package/lib/Controllers/LiveQueryController.js +4 -23
  74. package/lib/Controllers/LoggerController.js +15 -54
  75. package/lib/Controllers/ParseGraphQLController.js +49 -104
  76. package/lib/Controllers/PushController.js +20 -59
  77. package/lib/Controllers/SchemaController.js +162 -348
  78. package/lib/Controllers/UserController.js +17 -78
  79. package/lib/Controllers/index.js +19 -68
  80. package/lib/Controllers/types.js +1 -1
  81. package/lib/Deprecator/Deprecations.js +1 -1
  82. package/lib/Deprecator/Deprecator.js +9 -18
  83. package/lib/GraphQL/ParseGraphQLSchema.js +16 -100
  84. package/lib/GraphQL/ParseGraphQLServer.js +2 -29
  85. package/lib/GraphQL/helpers/objectsMutations.js +2 -12
  86. package/lib/GraphQL/helpers/objectsQueries.js +18 -76
  87. package/lib/GraphQL/loaders/defaultGraphQLMutations.js +1 -9
  88. package/lib/GraphQL/loaders/defaultGraphQLQueries.js +1 -8
  89. package/lib/GraphQL/loaders/defaultGraphQLTypes.js +9 -115
  90. package/lib/GraphQL/loaders/defaultRelaySchema.js +6 -18
  91. package/lib/GraphQL/loaders/filesMutations.js +2 -19
  92. package/lib/GraphQL/loaders/functionsMutations.js +6 -17
  93. package/lib/GraphQL/loaders/parseClassMutations.js +6 -44
  94. package/lib/GraphQL/loaders/parseClassQueries.js +1 -26
  95. package/lib/GraphQL/loaders/parseClassTypes.js +10 -64
  96. package/lib/GraphQL/loaders/schemaDirectives.js +1 -17
  97. package/lib/GraphQL/loaders/schemaMutations.js +1 -20
  98. package/lib/GraphQL/loaders/schemaQueries.js +1 -14
  99. package/lib/GraphQL/loaders/schemaTypes.js +2 -6
  100. package/lib/GraphQL/loaders/usersMutations.js +6 -28
  101. package/lib/GraphQL/loaders/usersQueries.js +4 -26
  102. package/lib/GraphQL/parseGraphQLUtils.js +6 -19
  103. package/lib/GraphQL/transformers/className.js +1 -4
  104. package/lib/GraphQL/transformers/constraintType.js +1 -20
  105. package/lib/GraphQL/transformers/inputType.js +1 -20
  106. package/lib/GraphQL/transformers/mutation.js +6 -51
  107. package/lib/GraphQL/transformers/outputType.js +1 -20
  108. package/lib/GraphQL/transformers/query.js +6 -42
  109. package/lib/GraphQL/transformers/schemaFields.js +7 -34
  110. package/lib/KeyPromiseQueue.js +1 -12
  111. package/lib/LiveQuery/Client.js +1 -25
  112. package/lib/LiveQuery/Id.js +1 -7
  113. package/lib/LiveQuery/ParseCloudCodePublisher.js +13 -19
  114. package/lib/LiveQuery/ParseLiveQueryServer.js +111 -307
  115. package/lib/LiveQuery/ParsePubSub.js +1 -12
  116. package/lib/LiveQuery/ParseWebSocketServer.js +4 -26
  117. package/lib/LiveQuery/QueryTools.js +14 -116
  118. package/lib/LiveQuery/RequestSchema.js +1 -1
  119. package/lib/LiveQuery/SessionTokenCache.js +1 -17
  120. package/lib/LiveQuery/Subscription.js +4 -18
  121. package/lib/LiveQuery/equalObjects.js +2 -14
  122. package/lib/Options/Definitions.js +88 -8
  123. package/lib/Options/docs.js +25 -3
  124. package/lib/Options/index.js +4 -12
  125. package/lib/Options/parsers.js +1 -18
  126. package/lib/Page.js +1 -9
  127. package/lib/ParseMessageQueue.js +1 -10
  128. package/lib/ParseServer.js +175 -207
  129. package/lib/ParseServerRESTController.js +6 -33
  130. package/lib/PromiseRouter.js +16 -50
  131. package/lib/Push/PushQueue.js +3 -15
  132. package/lib/Push/PushWorker.js +7 -32
  133. package/lib/Push/utils.js +9 -38
  134. package/lib/RestQuery.js +105 -242
  135. package/lib/RestWrite.js +224 -389
  136. package/lib/Routers/AggregateRouter.js +14 -51
  137. package/lib/Routers/AnalyticsRouter.js +2 -8
  138. package/lib/Routers/AudiencesRouter.js +1 -15
  139. package/lib/Routers/ClassesRouter.js +3 -53
  140. package/lib/Routers/CloudCodeRouter.js +1 -19
  141. package/lib/Routers/FeaturesRouter.js +1 -10
  142. package/lib/Routers/FilesRouter.js +29 -76
  143. package/lib/Routers/FunctionsRouter.js +5 -28
  144. package/lib/Routers/GlobalConfigRouter.js +4 -18
  145. package/lib/Routers/GraphQLRouter.js +1 -14
  146. package/lib/Routers/HooksRouter.js +1 -29
  147. package/lib/Routers/IAPValidationRouter.js +6 -29
  148. package/lib/Routers/InstallationsRouter.js +2 -12
  149. package/lib/Routers/LogsRouter.js +4 -16
  150. package/lib/Routers/PagesRouter.js +69 -129
  151. package/lib/Routers/PublicAPIRouter.js +3 -62
  152. package/lib/Routers/PurgeRouter.js +1 -15
  153. package/lib/Routers/PushRouter.js +2 -18
  154. package/lib/Routers/RolesRouter.js +1 -7
  155. package/lib/Routers/SchemasRouter.js +4 -34
  156. package/lib/Routers/SecurityRouter.js +1 -12
  157. package/lib/Routers/SessionsRouter.js +3 -19
  158. package/lib/Routers/UsersRouter.js +48 -135
  159. package/lib/SchemaMigrations/DefinedSchemas.js +56 -115
  160. package/lib/SchemaMigrations/Migrations.js +2 -8
  161. package/lib/Security/Check.js +8 -16
  162. package/lib/Security/CheckGroup.js +4 -11
  163. package/lib/Security/CheckGroups/CheckGroupDatabase.js +8 -18
  164. package/lib/Security/CheckGroups/CheckGroupServerConfig.js +5 -15
  165. package/lib/Security/CheckGroups/CheckGroups.js +1 -4
  166. package/lib/Security/CheckRunner.js +22 -41
  167. package/lib/StatusHandler.js +12 -69
  168. package/lib/TestUtils.js +1 -6
  169. package/lib/Utils.js +27 -66
  170. package/lib/batch.js +17 -28
  171. package/lib/cache.js +1 -3
  172. package/lib/cli/definitions/parse-live-query-server.js +1 -3
  173. package/lib/cli/definitions/parse-server.js +1 -3
  174. package/lib/cli/parse-live-query-server.js +1 -6
  175. package/lib/cli/parse-server.js +11 -21
  176. package/lib/cli/utils/commander.js +13 -51
  177. package/lib/cli/utils/runner.js +1 -14
  178. package/lib/cloud-code/Parse.Cloud.js +71 -81
  179. package/lib/cryptoUtils.js +11 -19
  180. package/lib/defaults.js +2 -14
  181. package/lib/deprecated.js +1 -2
  182. package/lib/index.js +16 -34
  183. package/lib/logger.js +6 -13
  184. package/lib/middlewares.js +166 -148
  185. package/lib/password.js +6 -10
  186. package/lib/request.js +8 -42
  187. package/lib/requiredParameter.js +1 -3
  188. package/lib/rest.js +25 -47
  189. package/lib/triggers.js +54 -252
  190. package/lib/vendor/mongodbUrl.js +129 -310
  191. package/package.json +13 -10
  192. package/PATENTS +0 -37
package/LICENSE CHANGED
@@ -1,34 +1,176 @@
1
- BSD License
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
2
4
 
3
- For Parse Server software
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
4
6
 
5
- Copyright (c) 2015-present, Parse, LLC. All rights reserved.
7
+ 1. Definitions.
6
8
 
7
- Redistribution and use in source and binary forms, with or without modification,
8
- are permitted provided that the following conditions are met:
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
9
11
 
10
- * Redistributions of source code must retain the above copyright notice, this
11
- list of conditions and the following disclaimer.
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
12
14
 
13
- * Redistributions in binary form must reproduce the above copyright notice,
14
- this list of conditions and the following disclaimer in the documentation
15
- and/or other materials provided with the distribution.
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
16
22
 
17
- * Neither the name Parse nor the names of its contributors may be used to
18
- endorse or promote products derived from this software without specific
19
- prior written permission.
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
20
25
 
21
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
22
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
25
- ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
28
- ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
31
29
 
32
- -----
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
33
34
 
34
- As of April 5, 2017, Parse, LLC has transferred this code to the parse-community organization, and will no longer be contributing to or distributing this code.
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
package/NOTICE ADDED
@@ -0,0 +1,10 @@
1
+ Parse Server
2
+
3
+ Copyright 2015-present Parse Platform
4
+
5
+ This product includes software developed at Parse Platform.
6
+ www.parseplatform.org
7
+
8
+ ---
9
+
10
+ As of April 5, 2017, Parse, LLC has transferred this code to the Parse Platform organization, and will no longer be contributing to or distributing this code.
package/README.md CHANGED
@@ -19,7 +19,6 @@
19
19
 
20
20
  [![Backers on Open Collective](https://opencollective.com/parse-server/backers/badge.svg)][open-collective-link]
21
21
  [![Sponsors on Open Collective](https://opencollective.com/parse-server/sponsors/badge.svg)][open-collective-link]
22
- [![License][license-svg]][license-link]
23
22
  [![Forum](https://img.shields.io/discourse/https/community.parseplatform.org/topics.svg)](https://community.parseplatform.org/c/parse-server)
24
23
  [![Twitter](https://img.shields.io/twitter/follow/ParsePlatform.svg?label=Follow&style=social)](https://twitter.com/intent/follow?screen_name=ParsePlatform)
25
24
  [![Chat](https://img.shields.io/badge/Chat-Join!-%23fff?style=social&logo=slack)](https://chat.parseplatform.org)
@@ -40,7 +39,7 @@ A big *thank you* 🙏 to our [sponsors](#sponsors) and [backers](#backers) who
40
39
 
41
40
  ---
42
41
 
43
- - [Flavors & Branches](#flavors--branches)
42
+ - [Flavors \& Branches](#flavors--branches)
44
43
  - [Long Term Support](#long-term-support)
45
44
  - [Getting Started](#getting-started)
46
45
  - [Running Parse Server](#running-parse-server)
@@ -55,9 +54,12 @@ A big *thank you* 🙏 to our [sponsors](#sponsors) and [backers](#backers) who
55
54
  - [Running Parse Server elsewhere](#running-parse-server-elsewhere)
56
55
  - [Sample Application](#sample-application)
57
56
  - [Parse Server + Express](#parse-server--express)
57
+ - [Parse Server Health](#parse-server-health)
58
+ - [Status Values](#status-values)
58
59
  - [Configuration](#configuration)
59
60
  - [Basic Options](#basic-options)
60
61
  - [Client Key Options](#client-key-options)
62
+ - [Access Scopes](#access-scopes)
61
63
  - [Email Verification and Password Reset](#email-verification-and-password-reset)
62
64
  - [Password and Account Policy](#password-and-account-policy)
63
65
  - [Custom Routes](#custom-routes)
@@ -89,7 +91,6 @@ A big *thank you* 🙏 to our [sponsors](#sponsors) and [backers](#backers) who
89
91
  - [Using automatically generated operations](#using-automatically-generated-operations)
90
92
  - [Customizing your GraphQL Schema](#customizing-your-graphql-schema)
91
93
  - [Learning more](#learning-more)
92
- - [Upgrading to Parse Server 3.0](#upgrading-to-parse-server-30)
93
94
  - [Contributing](#contributing)
94
95
  - [Contributors](#contributors)
95
96
  - [Sponsors](#sponsors)
@@ -100,13 +101,13 @@ A big *thank you* 🙏 to our [sponsors](#sponsors) and [backers](#backers) who
100
101
  Parse Server is available in different flavors on different branches:
101
102
 
102
103
  - The main branches are [release][log_release], [beta][log_beta] and [alpha][log_alpha]. See the [changelog overview](CHANGELOG.md) for details.
103
- - The long-term-support (LTS) branches are named `release-<version>.x.x`, for example `release-4.x.x`. LTS branches do not have pre-release branches.
104
+ - The long-term-support (LTS) branches are named `release-<version>.x.x`, for example `release-5.x.x`. LTS branches do not have pre-release branches.
104
105
 
105
106
  ## Long Term Support
106
107
 
107
- Long-Term-Support (LTS) is provided for the previous Parse Server major version. For example, Parse Server 4.x will receive security updates until Parse Server 5.x is superseded by Parse Server 6.x and becomes the new LTS version. While the current major version is published on branch `release`, a LTS version is published on branch `release-#.x.x`, for example `release-4.x.x` for the Parse Server 4.x LTS branch.
108
+ Long-Term-Support (LTS) is provided for the previous Parse Server major version. For example, Parse Server 5.x will receive security updates until Parse Server 6.x is superseded by Parse Server 7.x and becomes the new LTS version. While the current major version is published on branch `release`, a LTS version is published on branch `release-#.x.x`, for example `release-5.x.x` for the Parse Server 5.x LTS branch.
108
109
 
109
- ⚠️ LTS versions are provided to help you transition as soon as possible to the current major version. While we aim to fix security vulnerabilities in the LTS version, our main focus is on developing the current major version and preparing the next major release. Therefore we may leave certain vulnerabilities up to the community to fix. Search for [pull requests with the specific LTS base branch](https://github.com/parse-community/parse-server/pulls?q=is%3Aopen+is%3Apr+base%3Arelease-4.x.x) to see the current open vulnerabilities for that LTS branch.
110
+ ⚠️ LTS versions are provided to help you transition as soon as possible to the current major version. While we aim to fix security vulnerabilities in the LTS version, our main focus is on developing the current major version and preparing the next major release. Therefore we may leave certain vulnerabilities up to the community to fix. Search for [pull requests with the specific LTS base branch](https://github.com/parse-community/parse-server/pulls?q=is%3Aopen+is%3Apr+base%3Arelease-5.x.x) to see the current open vulnerabilities for that LTS branch.
110
111
 
111
112
  # Getting Started
112
113
 
@@ -130,19 +131,20 @@ Parse Server is continuously tested with the most recent releases of Node.js to
130
131
  |------------|----------------|-------------|------------|
131
132
  | Node.js 14 | 14.19.1 | April 2023 | ✅ Yes |
132
133
  | Node.js 16 | 16.14.2 | April 2024 | ✅ Yes |
133
- | Node.js 18 | 18.1.0 | April 2025 | ✅ Yes |
134
+ | Node.js 18 | 18.12.1 | April 2025 | ✅ Yes |
135
+ | Node.js 19 | 19.3.0 | June 2023 | ✅ Yes |
134
136
 
135
137
  #### MongoDB
136
138
 
137
139
  Parse Server is continuously tested with the most recent releases of MongoDB to ensure compatibility. We follow the [MongoDB support schedule](https://www.mongodb.com/support-policy) and [MongoDB lifecycle schedule](https://www.mongodb.com/support-policy/lifecycles) and only test against versions that are officially supported and have not reached their end-of-life date. We consider the end-of-life date of a MongoDB "rapid release" to be the same as its major version release.
138
140
 
139
- | Version | Latest Version | End-of-Life | Compatible |
140
- |-------------|----------------|---------------|--------------|
141
- | MongoDB 4.0 | 4.0.28 | April 2022 | ✅ Yes |
142
- | MongoDB 4.2 | 4.2.19 | April 2023 | ✅ Yes |
143
- | MongoDB 4.4 | 4.4.13 | February 2024 | ✅ Yes |
144
- | MongoDB 5 | 5.3.2 | October 2024 | ✅ Yes |
145
- | MongoDB 6 | 6.0.2 | July 2025 | ✅ Yes |
141
+ | Version | Latest Version | End-of-Life | Compatible |
142
+ |-------------|----------------|---------------|------------|
143
+ | MongoDB 4.0 | 4.0.28 | April 2022 | ✅ Yes |
144
+ | MongoDB 4.2 | 4.2.19 | April 2023 | ✅ Yes |
145
+ | MongoDB 4.4 | 4.4.13 | February 2024 | ✅ Yes |
146
+ | MongoDB 5 | 5.3.2 | October 2024 | ✅ Yes |
147
+ | MongoDB 6 | 6.0.2 | July 2025 | ✅ Yes |
146
148
 
147
149
  #### PostgreSQL
148
150
 
@@ -282,11 +284,11 @@ We have provided a basic [Node.js application](https://github.com/parse-communit
282
284
  You can also create an instance of Parse Server, and mount it on a new or existing Express website:
283
285
 
284
286
  ```js
285
- var express = require('express');
286
- var ParseServer = require('parse-server').ParseServer;
287
- var app = express();
287
+ const express = require('express');
288
+ const ParseServer = require('parse-server').ParseServer;
289
+ const app = express();
288
290
 
289
- var api = new ParseServer({
291
+ const server = new ParseServer({
290
292
  databaseURI: 'mongodb://localhost:27017/dev', // Connection string for your MongoDB database
291
293
  cloud: './cloud/main.js', // Path to your Cloud Code
292
294
  appId: 'myAppId',
@@ -295,8 +297,11 @@ var api = new ParseServer({
295
297
  serverURL: 'http://localhost:1337/parse' // Don't forget to change to https if needed
296
298
  });
297
299
 
300
+ // Start server
301
+ await server.start();
302
+
298
303
  // Serve the Parse API on the /parse URL prefix
299
- app.use('/parse', api);
304
+ app.use('/parse', server.app);
300
305
 
301
306
  app.listen(1337, function() {
302
307
  console.log('parse-server-example running on port 1337.');
@@ -305,6 +310,27 @@ app.listen(1337, function() {
305
310
 
306
311
  For a full list of available options, run `parse-server --help` or take a look at [Parse Server Configurations](http://parseplatform.org/parse-server/api/master/ParseServerOptions.html).
307
312
 
313
+ ## Parse Server Health
314
+
315
+ Check the Parse Server health by sending a request to the `/parse/health` endpoint.
316
+
317
+ The response looks like this:
318
+
319
+ ```json
320
+ {
321
+ "status": "ok"
322
+ }
323
+ ```
324
+
325
+ ### Status Values
326
+
327
+ | Value | Description |
328
+ |---------------|-----------------------------------------------------------------------------|
329
+ | `initialized` | The server has been created but the `start` method has not been called yet. |
330
+ | `starting` | The server is starting up. |
331
+ | `ok` | The server started and is running. |
332
+ | `error` | There was a startup error, see the logs for details. |
333
+
308
334
  # Configuration
309
335
 
310
336
  Parse Server can be configured using the following options. You may pass these as parameters when running a standalone `parse-server`, or by loading a configuration file in JSON format using `parse-server path/to/configuration.json`. If you're using Parse Server on Express, you may also pass these to the `ParseServer` object as options.
@@ -330,6 +356,15 @@ The client keys used with Parse are no longer necessary with Parse Server. If yo
330
356
  * `restAPIKey`
331
357
  * `dotNetKey`
332
358
 
359
+ ## Access Scopes
360
+
361
+ | Scope | Internal data | Custom data | Restricted by CLP, ACL | Key |
362
+ |----------------|---------------|-------------|------------------------|---------------------|
363
+ | Internal | r/w | r/w | no | `maintenanceKey` |
364
+ | Master | -/- | r/w | no | `masterKey` |
365
+ | ReadOnlyMaster | -/- | r/- | no | `readOnlyMasterKey` |
366
+ | Session | -/- | r/w | yes | `sessionToken` |
367
+
333
368
  ## Email Verification and Password Reset
334
369
 
335
370
  Verifying user email addresses and enabling password reset via email requires an email adapter. There are many email adapters provided and maintained by the community. The following is an example configuration with an example email adapter. See the [Parse Server Options](https://parseplatform.org/parse-server/api/master/ParseServerOptions.html) for more details and a full list of available options.
@@ -461,7 +496,7 @@ The following paths are already used by Parse Server's built-in features and are
461
496
  It’s possible to change the default pages of the app and redirect the user to another path or domain.
462
497
 
463
498
  ```js
464
- var server = ParseServer({
499
+ const server = ParseServer({
465
500
  ...otherOptions,
466
501
 
467
502
  customPages: {
@@ -851,7 +886,7 @@ Then, create an `index.js` file with the following content:
851
886
 
852
887
  ```js
853
888
  const express = require('express');
854
- const { default: ParseServer, ParseGraphQLServer } = require('parse-server');
889
+ const { ParseServer, ParseGraphQLServer } = require('parse-server');
855
890
 
856
891
  const app = express();
857
892
 
@@ -875,6 +910,7 @@ app.use('/parse', parseServer.app); // (Optional) Mounts the REST API
875
910
  parseGraphQLServer.applyGraphQL(app); // Mounts the GraphQL API
876
911
  parseGraphQLServer.applyPlayground(app); // (Optional) Mounts the GraphQL Playground - do NOT use in Production
877
912
 
913
+ await parseServer.start();
878
914
  app.listen(1337, function() {
879
915
  console.log('REST API running on http://localhost:1337/parse');
880
916
  console.log('GraphQL API running on http://localhost:1337/graphql');
@@ -1116,12 +1152,6 @@ You also have a very powerful tool inside your GraphQL Playground. Please look a
1116
1152
 
1117
1153
  Additionally, the [GraphQL Learn Section](https://graphql.org/learn/) is a very good source to learn more about the power of the GraphQL language.
1118
1154
 
1119
- # Upgrading to Parse Server 3.0
1120
-
1121
- Starting Parse Server 3.0, Parse Server uses the Parse JavaScript SDK 2.0. In short, the Parse JavaScript SDK 2.0 removes the backbone style callbacks as well as the `Parse.Promise` object in favor of native promises. All the Cloud Code interfaces also have been updated to reflect those changes, and all backbone style response objects are removed and replaced by promise style resolution.
1122
-
1123
- We have written up a [migration guide](3.0.0.md) to help you transition to the next major release.
1124
-
1125
1155
  # Contributing
1126
1156
 
1127
1157
  Please see the [Contributing Guide](CONTRIBUTING.md).
@@ -1173,12 +1203,6 @@ Support us with a monthly donation and help us continue our activities. [Become
1173
1203
 
1174
1204
  <a href="https://opencollective.com/parse-server#backers" target="_blank"><img src="https://opencollective.com/parse-server/backers.svg?width=890" /></a>
1175
1205
 
1176
- -----
1177
-
1178
- As of April 5, 2017, Parse, LLC has transferred this code to the parse-community organization, and will no longer be contributing to or distributing this code.
1179
-
1180
- [license-svg]: https://img.shields.io/badge/license-BSD-lightgrey.svg
1181
- [license-link]: LICENSE
1182
1206
  [open-collective-link]: https://opencollective.com/parse-server
1183
1207
  [log_release]: https://github.com/parse-community/parse-server/blob/release/changelogs/CHANGELOG_release.md
1184
1208
  [log_beta]: https://github.com/parse-community/parse-server/blob/beta/changelogs/CHANGELOG_beta.md
@@ -4,22 +4,19 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = exports.AccountLockout = void 0;
7
-
8
7
  var _node = _interopRequireDefault(require("parse/node"));
9
-
10
8
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
-
12
9
  // This class handles the Account Lockout Policy settings.
10
+
13
11
  class AccountLockout {
14
12
  constructor(user, config) {
15
13
  this._user = user;
16
14
  this._config = config;
17
15
  }
16
+
18
17
  /**
19
18
  * set _failed_login_count to value
20
19
  */
21
-
22
-
23
20
  _setFailedLoginCount(value) {
24
21
  const query = {
25
22
  username: this._user.username
@@ -29,11 +26,10 @@ class AccountLockout {
29
26
  };
30
27
  return this._config.database.update('_User', query, updateFields);
31
28
  }
29
+
32
30
  /**
33
31
  * check if the _failed_login_count field has been set
34
32
  */
35
-
36
-
37
33
  _isFailedLoginCountSet() {
38
34
  const query = {
39
35
  username: this._user.username,
@@ -49,12 +45,11 @@ class AccountLockout {
49
45
  }
50
46
  });
51
47
  }
48
+
52
49
  /**
53
50
  * if _failed_login_count is NOT set then set it to 0
54
51
  * else do nothing
55
52
  */
56
-
57
-
58
53
  _initFailedLoginCount() {
59
54
  return this._isFailedLoginCountSet().then(failedLoginCountIsSet => {
60
55
  if (!failedLoginCountIsSet) {
@@ -62,11 +57,10 @@ class AccountLockout {
62
57
  }
63
58
  });
64
59
  }
60
+
65
61
  /**
66
62
  * increment _failed_login_count by 1
67
63
  */
68
-
69
-
70
64
  _incrementFailedLoginCount() {
71
65
  const query = {
72
66
  username: this._user.username
@@ -79,13 +73,12 @@ class AccountLockout {
79
73
  };
80
74
  return this._config.database.update('_User', query, updateFields);
81
75
  }
76
+
82
77
  /**
83
78
  * if the failed login count is greater than the threshold
84
79
  * then sets lockout expiration to 'currenttime + accountPolicy.duration', i.e., account is locked out for the next 'accountPolicy.duration' minutes
85
80
  * else do nothing
86
81
  */
87
-
88
-
89
82
  _setLockoutExpiration() {
90
83
  const query = {
91
84
  username: this._user.username,
@@ -105,14 +98,13 @@ class AccountLockout {
105
98
  }
106
99
  });
107
100
  }
101
+
108
102
  /**
109
103
  * if _account_lockout_expires_at > current_time and _failed_login_count > threshold
110
104
  * reject with account locked error
111
105
  * else
112
106
  * resolve
113
107
  */
114
-
115
-
116
108
  _notLocked() {
117
109
  const query = {
118
110
  username: this._user.username,
@@ -129,6 +121,7 @@ class AccountLockout {
129
121
  }
130
122
  });
131
123
  }
124
+
132
125
  /**
133
126
  * set and/or increment _failed_login_count
134
127
  * if _failed_login_count > threshold
@@ -136,8 +129,6 @@ class AccountLockout {
136
129
  * else
137
130
  * do nothing
138
131
  */
139
-
140
-
141
132
  _handleFailedLoginAttempt() {
142
133
  return this._initFailedLoginCount().then(() => {
143
134
  return this._incrementFailedLoginCount();
@@ -145,16 +136,14 @@ class AccountLockout {
145
136
  return this._setLockoutExpiration();
146
137
  });
147
138
  }
139
+
148
140
  /**
149
141
  * handle login attempt if the Account Lockout Policy is enabled
150
142
  */
151
-
152
-
153
143
  handleLoginAttempt(loginSuccessful) {
154
144
  if (!this._config.accountLockout) {
155
145
  return Promise.resolve();
156
146
  }
157
-
158
147
  return this._notLocked().then(() => {
159
148
  if (loginSuccessful) {
160
149
  return this._setFailedLoginCount(0);
@@ -163,16 +152,14 @@ class AccountLockout {
163
152
  }
164
153
  });
165
154
  }
155
+
166
156
  /**
167
157
  * Removes the account lockout.
168
158
  */
169
-
170
-
171
159
  unlockAccount() {
172
160
  if (!this._config.accountLockout || !this._config.accountLockout.unlockOnPasswordReset) {
173
161
  return Promise.resolve();
174
162
  }
175
-
176
163
  return this._config.database.update('_User', {
177
164
  username: this._user.username
178
165
  }, {
@@ -184,10 +171,8 @@ class AccountLockout {
184
171
  }
185
172
  });
186
173
  }
187
-
188
174
  }
189
-
190
175
  exports.AccountLockout = AccountLockout;
191
176
  var _default = AccountLockout;
192
177
  exports.default = _default;
193
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9BY2NvdW50TG9ja291dC5qcyJdLCJuYW1lcyI6WyJBY2NvdW50TG9ja291dCIsImNvbnN0cnVjdG9yIiwidXNlciIsImNvbmZpZyIsIl91c2VyIiwiX2NvbmZpZyIsIl9zZXRGYWlsZWRMb2dpbkNvdW50IiwidmFsdWUiLCJxdWVyeSIsInVzZXJuYW1lIiwidXBkYXRlRmllbGRzIiwiX2ZhaWxlZF9sb2dpbl9jb3VudCIsImRhdGFiYXNlIiwidXBkYXRlIiwiX2lzRmFpbGVkTG9naW5Db3VudFNldCIsIiRleGlzdHMiLCJmaW5kIiwidGhlbiIsInVzZXJzIiwiQXJyYXkiLCJpc0FycmF5IiwibGVuZ3RoIiwiX2luaXRGYWlsZWRMb2dpbkNvdW50IiwiZmFpbGVkTG9naW5Db3VudElzU2V0IiwiX2luY3JlbWVudEZhaWxlZExvZ2luQ291bnQiLCJfX29wIiwiYW1vdW50IiwiX3NldExvY2tvdXRFeHBpcmF0aW9uIiwiJGd0ZSIsImFjY291bnRMb2Nrb3V0IiwidGhyZXNob2xkIiwibm93IiwiRGF0ZSIsIl9hY2NvdW50X2xvY2tvdXRfZXhwaXJlc19hdCIsIlBhcnNlIiwiX2VuY29kZSIsImdldFRpbWUiLCJkdXJhdGlvbiIsImNhdGNoIiwiZXJyIiwiY29kZSIsIm1lc3NhZ2UiLCJFcnJvciIsIk9CSkVDVF9OT1RfRk9VTkQiLCJfbm90TG9ja2VkIiwiJGd0IiwiX2hhbmRsZUZhaWxlZExvZ2luQXR0ZW1wdCIsImhhbmRsZUxvZ2luQXR0ZW1wdCIsImxvZ2luU3VjY2Vzc2Z1bCIsIlByb21pc2UiLCJyZXNvbHZlIiwidW5sb2NrQWNjb3VudCIsInVubG9ja09uUGFzc3dvcmRSZXNldCJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUNBOzs7O0FBREE7QUFHTyxNQUFNQSxjQUFOLENBQXFCO0FBQzFCQyxFQUFBQSxXQUFXLENBQUNDLElBQUQsRUFBT0MsTUFBUCxFQUFlO0FBQ3hCLFNBQUtDLEtBQUwsR0FBYUYsSUFBYjtBQUNBLFNBQUtHLE9BQUws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TGJ6QixjIiwic291cmNlc0NvbnRlbnQiOlsiLy8gVGhpcyBjbGFzcyBoYW5kbGVzIHRoZSBBY2NvdW50IExvY2tvdXQgUG9saWN5IHNldHRpbmdzLlxuaW1wb3J0IFBhcnNlIGZyb20gJ3BhcnNlL25vZGUnO1xuXG5leHBvcnQgY2xhc3MgQWNjb3VudExvY2tvdXQge1xuICBjb25zdHJ1Y3Rvcih1c2VyLCBjb25maWcpIHtcbiAgICB0aGlzLl91c2VyID0gdXNlcjtcbiAgICB0aGlzLl9jb25maWcgPSBjb25maWc7XG4gIH1cblxuICAvKipcbiAgICogc2V0IF9mYWlsZWRfbG9naW5fY291bnQgdG8gdmFsdWVcbiAgICovXG4gIF9zZXRGYWlsZWRMb2dpbkNvdW50KHZhbHVlKSB7XG4gICAgY29uc3QgcXVlcnkgPSB7XG4gICAgICB1c2VybmFtZTogdGhpcy5fdXNlci51c2VybmFtZSxcbiAgICB9O1xuXG4gICAgY29uc3QgdXBkYXRlRmllbGRzID0ge1xuICAgICAgX2ZhaWxlZF9sb2dpbl9jb3VudDogdmFsdWUsXG4gICAgfTtcblxuICAgIHJldHVybiB0aGlzLl9jb25maWcuZGF0YWJhc2UudXBkYXRlKCdfVXNlcicsIHF1ZXJ5LCB1cGRhdGVGaWVsZHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIGNoZWNrIGlmIHRoZSBfZmFpbGVkX2xvZ2luX2NvdW50IGZpZWxkIGhhcyBiZWVuIHNldFxuICAgKi9cbiAgX2lzRmFpbGVkTG9naW5Db3VudFNldCgpIHtcbiAgICBjb25zdCBxdWVyeSA9IHtcbiAgICAgIHVzZXJuYW1lOiB0aGlzLl91c2VyLnVzZXJuYW1lLFxuICAgICAgX2ZhaWxlZF9sb2dpbl9jb3VudDogeyAkZXhpc3RzOiB0cnVlIH0sXG4gICAgfTtcblxuICAgIHJldHVybiB0aGlzLl9jb25maWcuZGF0YWJhc2UuZmluZCgnX1VzZXInLCBxdWVyeSkudGhlbih1c2VycyA9PiB7XG4gICAgICBpZiAoQXJyYXkuaXNBcnJheSh1c2VycykgJiYgdXNlcnMubGVuZ3RoID4gMCkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBpZiBfZmFpbGVkX2xvZ2luX2NvdW50IGlzIE5PVCBzZXQgdGhlbiBzZXQgaXQgdG8gMFxuICAgKiBlbHNlIGRvIG5vdGhpbmdcbiAgICovXG4gIF9pbml0RmFpbGVkTG9naW5Db3VudCgpIHtcbiAgICByZXR1cm4gdGhpcy5faXNGYWlsZWRMb2dpbkNvdW50U2V0KCkudGhlbihmYWlsZWRMb2dpbkNvdW50SXNTZXQgPT4ge1xuICAgICAgaWYgKCFmYWlsZWRMb2dpbkNvdW50SXNTZXQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3NldEZhaWxlZExvZ2luQ291bnQoMCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogaW5jcmVtZW50IF9mYWlsZWRfbG9naW5fY291bnQgYnkgMVxuICAgKi9cbiAgX2luY3JlbWVudEZhaWxlZExvZ2luQ291bnQoKSB7XG4gICAgY29uc3QgcXVlcnkgPSB7XG4gICAgICB1c2VybmFtZTogdGhpcy5fdXNlci51c2VybmFtZSxcbiAgICB9O1xuXG4gICAgY29uc3QgdXBkYXRlRmllbGRzID0ge1xuICAgICAgX2ZhaWxlZF9sb2dpbl9jb3VudDogeyBfX29wOiAnSW5jcmVtZW50JywgYW1vdW50OiAxIH0sXG4gICAgfTtcblxuICAgIHJldHVybiB0aGlzLl9jb25maWcuZGF0YWJhc2UudXBkYXRlKCdfVXNlcicsIHF1ZXJ5LCB1cGRhdGVGaWVsZHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIGlmIHRoZSBmYWlsZWQgbG9naW4gY291bnQgaXMgZ3JlYXRlciB0aGFuIHRoZSB0aHJlc2hvbGRcbiAgICogdGhlbiBzZXRzIGxvY2tvdXQgZXhwaXJhdGlvbiB0byAnY3VycmVudHRpbWUgKyBhY2NvdW50UG9saWN5LmR1cmF0aW9uJywgaS5lLiwgYWNjb3VudCBpcyBsb2NrZWQgb3V0IGZvciB0aGUgbmV4dCAnYWNjb3VudFBvbGljeS5kdXJhdGlvbicgbWludXRlc1xuICAgKiBlbHNlIGRvIG5vdGhpbmdcbiAgICovXG4gIF9zZXRMb2Nrb3V0RXhwaXJhdGlvbigpIHtcbiAgICBjb25zdCBxdWVyeSA9IHtcbiAgICAgIHVzZXJuYW1lOiB0aGlzLl91c2VyLnVzZXJuYW1lLFxuICAgICAgX2ZhaWxlZF9sb2dpbl9jb3VudDogeyAkZ3RlOiB0aGlzLl9jb25maWcuYWNjb3VudExvY2tvdXQudGhyZXNob2xkIH0sXG4gICAgfTtcblxuICAgIGNvbnN0IG5vdyA9IG5ldyBEYXRlKCk7XG5cbiAgICBjb25zdCB1cGRhdGVGaWVsZHMgPSB7XG4gICAgICBfYWNjb3VudF9sb2Nrb3V0X2V4cGlyZXNfYXQ6IFBhcnNlLl9lbmNvZGUoXG4gICAgICAgIG5ldyBEYXRlKG5vdy5nZXRUaW1lKCkgKyB0aGlzLl9jb25maWcuYWNjb3VudExvY2tvdXQuZHVyYXRpb24gKiA2MCAqIDEwMDApXG4gICAgICApLFxuICAgIH07XG5cbiAgICByZXR1cm4gdGhpcy5fY29uZmlnLmRhdGFiYXNlLnVwZGF0ZSgnX1VzZXInLCBxdWVyeSwgdXBkYXRlRmllbGRzKS5jYXRjaChlcnIgPT4ge1xuICAgICAgaWYgKFxuICAgICAgICBlcnIgJiZcbiAgICAgICAgZXJyLmNvZGUgJiZcbiAgICAgICAgZXJyLm1lc3NhZ2UgJiZcbiAgICAgICAgZXJyLmNvZGUgPT09IFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQgJiZcbiAgICAgICAgZXJyLm1lc3NhZ2UgPT09ICdPYmplY3Qgbm90IGZvdW5kLidcbiAgICAgICkge1xuICAgICAgICByZXR1cm47IC8vIG5vdGhpbmcgdG8gdXBkYXRlIHNvIHdlIGFyZSBnb29kXG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBlcnI7IC8vIHVua25vd24gZXJyb3JcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBpZiBfYWNjb3VudF9sb2Nrb3V0X2V4cGlyZXNfYXQgPiBjdXJyZW50X3RpbWUgYW5kIF9mYWlsZWRfbG9naW5fY291bnQgPiB0aHJlc2hvbGRcbiAgICogICByZWplY3Qgd2l0aCBhY2NvdW50IGxvY2tlZCBlcnJvclxuICAgKiBlbHNlXG4gICAqICAgcmVzb2x2ZVxuICAgKi9cbiAgX25vdExvY2tlZCgpIHtcbiAgICBjb25zdCBxdWVyeSA9IHtcbiAgICAgIHVzZXJuYW1lOiB0aGlzLl91c2VyLnVzZXJuYW1lLFxuICAgICAgX2FjY291bnRfbG9ja291dF9leHBpcmVzX2F0OiB7ICRndDogUGFyc2UuX2VuY29kZShuZXcgRGF0ZSgpKSB9LFxuICAgICAgX2ZhaWxlZF9sb2dpbl9jb3VudDogeyAkZ3RlOiB0aGlzLl9jb25maWcuYWNjb3VudExvY2tvdXQudGhyZXNob2xkIH0sXG4gICAgfTtcblxuICAgIHJldHVybiB0aGlzLl9jb25maWcuZGF0YWJhc2UuZmluZCgnX1VzZXInLCBxdWVyeSkudGhlbih1c2VycyA9PiB7XG4gICAgICBpZiAoQXJyYXkuaXNBcnJheSh1c2VycykgJiYgdXNlcnMubGVuZ3RoID4gMCkge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCxcbiAgICAgICAgICAnWW91ciBhY2NvdW50IGlzIGxvY2tlZCBkdWUgdG8gbXVsdGlwbGUgZmFpbGVkIGxvZ2luIGF0dGVtcHRzLiBQbGVhc2UgdHJ5IGFnYWluIGFmdGVyICcgK1xuICAgICAgICAgICAgdGhpcy5fY29uZmlnLmFjY291bnRMb2Nrb3V0LmR1cmF0aW9uICtcbiAgICAgICAgICAgICcgbWludXRlKHMpJ1xuICAgICAgICApO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIHNldCBhbmQvb3IgaW5jcmVtZW50IF9mYWlsZWRfbG9naW5fY291bnRcbiAgICogaWYgX2ZhaWxlZF9sb2dpbl9jb3VudCA+IHRocmVzaG9sZFxuICAgKiAgIHNldCB0aGUgX2FjY291bnRfbG9ja291dF9leHBpcmVzX2F0IHRvIGN1cnJlbnRfdGltZSArIGFjY291bnRQb2xpY3kuZHVyYXRpb25cbiAgICogZWxzZVxuICAgKiAgIGRvIG5vdGhpbmdcbiAgICovXG4gIF9oYW5kbGVGYWlsZWRMb2dpbkF0dGVtcHQoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2luaXRGYWlsZWRMb2dpbkNvdW50KClcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2luY3JlbWVudEZhaWxlZExvZ2luQ291bnQoKTtcbiAgICAgIH0pXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9zZXRMb2Nrb3V0RXhwaXJhdGlvbigpO1xuICAgICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogaGFuZGxlIGxvZ2luIGF0dGVtcHQgaWYgdGhlIEFjY291bnQgTG9ja291dCBQb2xpY3kgaXMgZW5hYmxlZFxuICAgKi9cbiAgaGFuZGxlTG9naW5BdHRlbXB0KGxvZ2luU3VjY2Vzc2Z1bCkge1xuICAgIGlmICghdGhpcy5fY29uZmlnLmFjY291bnRMb2Nrb3V0KSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9ub3RMb2NrZWQoKS50aGVuKCgpID0+IHtcbiAgICAgIGlmIChsb2dpblN1Y2Nlc3NmdWwpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3NldEZhaWxlZExvZ2luQ291bnQoMCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gdGhpcy5faGFuZGxlRmFpbGVkTG9naW5BdHRlbXB0KCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlcyB0aGUgYWNjb3VudCBsb2Nrb3V0LlxuICAgKi9cbiAgdW5sb2NrQWNjb3VudCgpIHtcbiAgICBpZiAoIXRoaXMuX2NvbmZpZy5hY2NvdW50TG9ja291dCB8fCAhdGhpcy5fY29uZmlnLmFjY291bnRMb2Nrb3V0LnVubG9ja09uUGFzc3dvcmRSZXNldCkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fY29uZmlnLmRhdGFiYXNlLnVwZGF0ZShcbiAgICAgICdfVXNlcicsXG4gICAgICB7IHVzZXJuYW1lOiB0aGlzLl91c2VyLnVzZXJuYW1lIH0sXG4gICAgICB7XG4gICAgICAgIF9mYWlsZWRfbG9naW5fY291bnQ6IHsgX19vcDogJ0RlbGV0ZScgfSxcbiAgICAgICAgX2FjY291bnRfbG9ja291dF9leHBpcmVzX2F0OiB7IF9fb3A6ICdEZWxldGUnIH0sXG4gICAgICB9XG4gICAgKTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBBY2NvdW50TG9ja291dDtcbiJdfQ==
178
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJBY2NvdW50TG9ja291dCIsImNvbnN0cnVjdG9yIiwidXNlciIsImNvbmZpZyIsIl91c2VyIiwiX2NvbmZpZyIsIl9zZXRGYWlsZWRMb2dpbkNvdW50IiwidmFsdWUiLCJxdWVyeSIsInVzZXJuYW1lIiwidXBkYXRlRmllbGRzIiwiX2ZhaWxlZF9sb2dpbl9jb3VudCIsImRhdGFiYXNlIiwidXBkYXRlIiwiX2lzRmFpbGVkTG9naW5Db3VudFNldCIsIiRleGlzdHMiLCJmaW5kIiwidGhlbiIsInVzZXJzIiwiQXJyYXkiLCJpc0FycmF5IiwibGVuZ3RoIiwiX2luaXRGYWlsZWRMb2dpbkNvdW50IiwiZmFpbGVkTG9naW5Db3VudElzU2V0IiwiX2luY3JlbWVudEZhaWxlZExvZ2luQ291bnQiLCJfX29wIiwiYW1vdW50IiwiX3NldExvY2tvdXRFeHBpcmF0aW9uIiwiJGd0ZSIsImFjY291bnRMb2Nrb3V0IiwidGhyZXNob2xkIiwibm93IiwiRGF0ZSIsIl9hY2NvdW50X2xvY2tvdXRfZXhwaXJlc19hdCIsIlBhcnNlIiwiX2VuY29kZSIsImdldFRpbWUiLCJkdXJhdGlvbiIsImNhdGNoIiwiZXJyIiwiY29kZSIsIm1lc3NhZ2UiLCJFcnJvciIsIk9CSkVDVF9OT1RfRk9VTkQiLCJfbm90TG9ja2VkIiwiJGd0IiwiX2hhbmRsZUZhaWxlZExvZ2luQXR0ZW1wdCIsImhhbmRsZUxvZ2luQXR0ZW1wdCIsImxvZ2luU3VjY2Vzc2Z1bCIsIlByb21pc2UiLCJyZXNvbHZlIiwidW5sb2NrQWNjb3VudCIsInVubG9ja09uUGFzc3dvcmRSZXNldCJdLCJzb3VyY2VzIjpbIi4uL3NyYy9BY2NvdW50TG9ja291dC5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBUaGlzIGNsYXNzIGhhbmRsZXMgdGhlIEFjY291bnQgTG9ja291dCBQb2xpY3kgc2V0dGluZ3MuXG5pbXBvcnQgUGFyc2UgZnJvbSAncGFyc2Uvbm9kZSc7XG5cbmV4cG9ydCBjbGFzcyBBY2NvdW50TG9ja291dCB7XG4gIGNvbnN0cnVjdG9yKHVzZXIsIGNvbmZpZykge1xuICAgIHRoaXMuX3VzZXIgPSB1c2VyO1xuICAgIHRoaXMuX2NvbmZpZyA9IGNvbmZpZztcbiAgfVxuXG4gIC8qKlxuICAgKiBzZXQgX2ZhaWxlZF9sb2dpbl9jb3VudCB0byB2YWx1ZVxuICAgKi9cbiAgX3NldEZhaWxlZExvZ2luQ291bnQodmFsdWUpIHtcbiAgICBjb25zdCBxdWVyeSA9IHtcbiAgICAgIHVzZXJuYW1lOiB0aGlzLl91c2VyLnVzZXJuYW1lLFxuICAgIH07XG5cbiAgICBjb25zdCB1cGRhdGVGaWVsZHMgPSB7XG4gICAgICBfZmFpbGVkX2xvZ2luX2NvdW50OiB2YWx1ZSxcbiAgICB9O1xuXG4gICAgcmV0dXJuIHRoaXMuX2NvbmZpZy5kYXRhYmFzZS51cGRhdGUoJ19Vc2VyJywgcXVlcnksIHVwZGF0ZUZpZWxkcyk7XG4gIH1cblxuICAvKipcbiAgICogY2hlY2sgaWYgdGhlIF9mYWlsZWRfbG9naW5fY291bnQgZmllbGQgaGFzIGJlZW4gc2V0XG4gICAqL1xuICBfaXNGYWlsZWRMb2dpbkNvdW50U2V0KCkge1xuICAgIGNvbnN0IHF1ZXJ5ID0ge1xuICAgICAgdXNlcm5hbWU6IHRoaXMuX3VzZXIudXNlcm5hbWUsXG4gICAgICBfZmFpbGVkX2xvZ2luX2NvdW50OiB7ICRleGlzdHM6IHRydWUgfSxcbiAgICB9O1xuXG4gICAgcmV0dXJuIHRoaXMuX2NvbmZpZy5kYXRhYmFzZS5maW5kKCdfVXNlcicsIHF1ZXJ5KS50aGVuKHVzZXJzID0+IHtcbiAgICAgIGlmIChBcnJheS5pc0FycmF5KHVzZXJzKSAmJiB1c2Vycy5sZW5ndGggPiAwKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIGlmIF9mYWlsZWRfbG9naW5fY291bnQgaXMgTk9UIHNldCB0aGVuIHNldCBpdCB0byAwXG4gICAqIGVsc2UgZG8gbm90aGluZ1xuICAgKi9cbiAgX2luaXRGYWlsZWRMb2dpbkNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLl9pc0ZhaWxlZExvZ2luQ291bnRTZXQoKS50aGVuKGZhaWxlZExvZ2luQ291bnRJc1NldCA9PiB7XG4gICAgICBpZiAoIWZhaWxlZExvZ2luQ291bnRJc1NldCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fc2V0RmFpbGVkTG9naW5Db3VudCgwKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBpbmNyZW1lbnQgX2ZhaWxlZF9sb2dpbl9jb3VudCBieSAxXG4gICAqL1xuICBfaW5jcmVtZW50RmFpbGVkTG9naW5Db3VudCgpIHtcbiAgICBjb25zdCBxdWVyeSA9IHtcbiAgICAgIHVzZXJuYW1lOiB0aGlzLl91c2VyLnVzZXJuYW1lLFxuICAgIH07XG5cbiAgICBjb25zdCB1cGRhdGVGaWVsZHMgPSB7XG4gICAgICBfZmFpbGVkX2xvZ2luX2NvdW50OiB7IF9fb3A6ICdJbmNyZW1lbnQnLCBhbW91bnQ6IDEgfSxcbiAgICB9O1xuXG4gICAgcmV0dXJuIHRoaXMuX2NvbmZpZy5kYXRhYmFzZS51cGRhdGUoJ19Vc2VyJywgcXVlcnksIHVwZGF0ZUZpZWxkcyk7XG4gIH1cblxuICAvKipcbiAgICogaWYgdGhlIGZhaWxlZCBsb2dpbiBjb3VudCBpcyBncmVhdGVyIHRoYW4gdGhlIHRocmVzaG9sZFxuICAgKiB0aGVuIHNldHMgbG9ja291dCBleHBpcmF0aW9uIHRvICdjdXJyZW50dGltZSArIGFjY291bnRQb2xpY3kuZHVyYXRpb24nLCBpLmUuLCBhY2NvdW50IGlzIGxvY2tlZCBvdXQgZm9yIHRoZSBuZXh0ICdhY2NvdW50UG9saWN5LmR1cmF0aW9uJyBtaW51dGVzXG4gICAqIGVsc2UgZG8gbm90aGluZ1xuICAgKi9cbiAgX3NldExvY2tvdXRFeHBpcmF0aW9uKCkge1xuICAgIGNvbnN0IHF1ZXJ5ID0ge1xuICAgICAgdXNlcm5hbWU6IHRoaXMuX3VzZXIudXNlcm5hbWUsXG4gICAgICBfZmFpbGVkX2xvZ2luX2NvdW50OiB7ICRndGU6IHRoaXMuX2NvbmZpZy5hY2NvdW50TG9ja291dC50aHJlc2hvbGQgfSxcbiAgICB9O1xuXG4gICAgY29uc3Qgbm93ID0gbmV3IERhdGUoKTtcblxuICAgIGNvbnN0IHVwZGF0ZUZpZWxkcyA9IHtcbiAgICAgIF9hY2NvdW50X2xvY2tvdXRfZXhwaXJlc19hdDogUGFyc2UuX2VuY29kZShcbiAgICAgICAgbmV3IERhdGUobm93LmdldFRpbWUoKSArIHRoaXMuX2NvbmZpZy5hY2NvdW50TG9ja291dC5kdXJhdGlvbiAqIDYwICogMTAwMClcbiAgICAgICksXG4gICAgfTtcblxuICAgIHJldHVybiB0aGlzLl9jb25maWcuZGF0YWJhc2UudXBkYXRlKCdfVXNlcicsIHF1ZXJ5LCB1cGRhdGVGaWVsZHMpLmNhdGNoKGVyciA9PiB7XG4gICAgICBpZiAoXG4gICAgICAgIGVyciAmJlxuICAgICAgICBlcnIuY29kZSAmJlxuICAgICAgICBlcnIubWVzc2FnZSAmJlxuICAgICAgICBlcnIuY29kZSA9PT0gUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCAmJlxuICAgICAgICBlcnIubWVzc2FnZSA9PT0gJ09iamVjdCBub3QgZm91bmQuJ1xuICAgICAgKSB7XG4gICAgICAgIHJldHVybjsgLy8gbm90aGluZyB0byB1cGRhdGUgc28gd2UgYXJlIGdvb2RcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IGVycjsgLy8gdW5rbm93biBlcnJvclxuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIGlmIF9hY2NvdW50X2xvY2tvdXRfZXhwaXJlc19hdCA+IGN1cnJlbnRfdGltZSBhbmQgX2ZhaWxlZF9sb2dpbl9jb3VudCA+IHRocmVzaG9sZFxuICAgKiAgIHJlamVjdCB3aXRoIGFjY291bnQgbG9ja2VkIGVycm9yXG4gICAqIGVsc2VcbiAgICogICByZXNvbHZlXG4gICAqL1xuICBfbm90TG9ja2VkKCkge1xuICAgIGNvbnN0IHF1ZXJ5ID0ge1xuICAgICAgdXNlcm5hbWU6IHRoaXMuX3VzZXIudXNlcm5hbWUsXG4gICAgICBfYWNjb3VudF9sb2Nrb3V0X2V4cGlyZXNfYXQ6IHsgJGd0OiBQYXJzZS5fZW5jb2RlKG5ldyBEYXRlKCkpIH0sXG4gICAgICBfZmFpbGVkX2xvZ2luX2NvdW50OiB7ICRndGU6IHRoaXMuX2NvbmZpZy5hY2NvdW50TG9ja291dC50aHJlc2hvbGQgfSxcbiAgICB9O1xuXG4gICAgcmV0dXJuIHRoaXMuX2NvbmZpZy5kYXRhYmFzZS5maW5kKCdfVXNlcicsIHF1ZXJ5KS50aGVuKHVzZXJzID0+IHtcbiAgICAgIGlmIChBcnJheS5pc0FycmF5KHVzZXJzKSAmJiB1c2Vycy5sZW5ndGggPiAwKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELFxuICAgICAgICAgICdZb3VyIGFjY291bnQgaXMgbG9ja2VkIGR1ZSB0byBtdWx0aXBsZSBmYWlsZWQgbG9naW4gYXR0ZW1wdHMuIFBsZWFzZSB0cnkgYWdhaW4gYWZ0ZXIgJyArXG4gICAgICAgICAgICB0aGlzLl9jb25maWcuYWNjb3VudExvY2tvdXQuZHVyYXRpb24gK1xuICAgICAgICAgICAgJyBtaW51dGUocyknXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogc2V0IGFuZC9vciBpbmNyZW1lbnQgX2ZhaWxlZF9sb2dpbl9jb3VudFxuICAgKiBpZiBfZmFpbGVkX2xvZ2luX2NvdW50ID4gdGhyZXNob2xkXG4gICAqICAgc2V0IHRoZSBfYWNjb3VudF9sb2Nrb3V0X2V4cGlyZXNfYXQgdG8gY3VycmVudF90aW1lICsgYWNjb3VudFBvbGljeS5kdXJhdGlvblxuICAgKiBlbHNlXG4gICAqICAgZG8gbm90aGluZ1xuICAgKi9cbiAgX2hhbmRsZUZhaWxlZExvZ2luQXR0ZW1wdCgpIHtcbiAgICByZXR1cm4gdGhpcy5faW5pdEZhaWxlZExvZ2luQ291bnQoKVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5faW5jcmVtZW50RmFpbGVkTG9naW5Db3VudCgpO1xuICAgICAgfSlcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3NldExvY2tvdXRFeHBpcmF0aW9uKCk7XG4gICAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBoYW5kbGUgbG9naW4gYXR0ZW1wdCBpZiB0aGUgQWNjb3VudCBMb2Nrb3V0IFBvbGljeSBpcyBlbmFibGVkXG4gICAqL1xuICBoYW5kbGVMb2dpbkF0dGVtcHQobG9naW5TdWNjZXNzZnVsKSB7XG4gICAgaWYgKCF0aGlzLl9jb25maWcuYWNjb3VudExvY2tvdXQpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX25vdExvY2tlZCgpLnRoZW4oKCkgPT4ge1xuICAgICAgaWYgKGxvZ2luU3VjY2Vzc2Z1bCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fc2V0RmFpbGVkTG9naW5Db3VudCgwKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9oYW5kbGVGYWlsZWRMb2dpbkF0dGVtcHQoKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmVzIHRoZSBhY2NvdW50IGxvY2tvdXQuXG4gICAqL1xuICB1bmxvY2tBY2NvdW50KCkge1xuICAgIGlmICghdGhpcy5fY29uZmlnLmFjY291bnRMb2Nrb3V0IHx8ICF0aGlzLl9jb25maWcuYWNjb3VudExvY2tvdXQudW5sb2NrT25QYXNzd29yZFJlc2V0KSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9jb25maWcuZGF0YWJhc2UudXBkYXRlKFxuICAgICAgJ19Vc2VyJyxcbiAgICAgIHsgdXNlcm5hbWU6IHRoaXMuX3VzZXIudXNlcm5hbWUgfSxcbiAgICAgIHtcbiAgICAgICAgX2ZhaWxlZF9sb2dpbl9jb3VudDogeyBfX29wOiAnRGVsZXRlJyB9LFxuICAgICAgICBfYWNjb3VudF9sb2Nrb3V0X2V4cGlyZXNfYXQ6IHsgX19vcDogJ0RlbGV0ZScgfSxcbiAgICAgIH1cbiAgICApO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IEFjY291bnRMb2Nrb3V0O1xuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7QUFDQTtBQUErQjtBQUQvQjs7QUFHTyxNQUFNQSxjQUFjLENBQUM7RUFDMUJDLFdBQVcsQ0FBQ0MsSUFBSSxFQUFFQyxNQUFNLEVBQUU7SUFDeEIsSUFBSSxDQUFDQyxLQUFLLEdBQUdGLElBQUk7SUFDakIsSUFBSSxDQUFDRyxPQUFPLEdBQUdGLE1BQU07RUFDdkI7O0VBRUE7QUFDRjtBQUNBO0VBQ0VHLG9CQUFvQixDQUFDQyxLQUFLLEVBQUU7SUFDMUIsTUFBTUMsS0FBSyxHQUFHO01BQ1pDLFFBQVEsRUFBRSxJQUFJLENBQUNMLEtBQUssQ0FBQ0s7SUFDdkIsQ0FBQztJQUVELE1BQU1DLFlBQVksR0FBRztNQUNuQkMsbUJBQW1CLEVBQUVKO0lBQ3ZCLENBQUM7SUFFRCxPQUFPLElBQUksQ0FBQ0YsT0FBTyxDQUFDTyxRQUFRLENBQUNDLE1BQU0sQ0FBQyxPQUFPLEVBQUVMLEtBQUssRUFBRUUsWUFBWSxDQUFDO0VBQ25FOztFQUVBO0FBQ0Y7QUFDQTtFQUNFSSxzQkFBc0IsR0FBRztJQUN2QixNQUFNTixLQUFLLEdBQUc7TUFDWkMsUUFBUSxFQUFFLElBQUksQ0FBQ0wsS0FBSyxDQUFDSyxRQUFRO01BQzdCRSxtQkFBbUIsRUFBRTtRQUFFSSxPQUFPLEVBQUU7TUFBSztJQUN2QyxDQUFDO0lBRUQsT0FBTyxJQUFJLENBQUNWLE9BQU8sQ0FBQ08sUUFBUSxDQUFDSSxJQUFJLENBQUMsT0FBTyxFQUFFUixLQUFLLENBQUMsQ0FBQ1MsSUFBSSxDQUFDQyxLQUFLLElBQUk7TUFDOUQsSUFBSUMsS0FBSyxDQUFDQyxPQUFPLENBQUNGLEtB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