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
@@ -0,0 +1,379 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.DefinedSchemas = void 0;
7
+ var _logger = require("../logger");
8
+ var _Config = _interopRequireDefault(require("../Config"));
9
+ var _SchemasRouter = require("../Routers/SchemasRouter");
10
+ var _SchemaController = require("../Controllers/SchemaController");
11
+ var _Options = require("../Options");
12
+ var Migrations = _interopRequireWildcard(require("./Migrations"));
13
+ var _Auth = _interopRequireDefault(require("../Auth"));
14
+ var _rest = _interopRequireDefault(require("../rest"));
15
+ 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); }
16
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
17
+ // -disable-next Cannot resolve module `parse/node`.
18
+ const Parse = require('parse/node');
19
+ class DefinedSchemas {
20
+ constructor(schemaOptions, config) {
21
+ this.localSchemas = [];
22
+ this.config = _Config.default.get(config.appId);
23
+ this.schemaOptions = schemaOptions;
24
+ if (schemaOptions && schemaOptions.definitions) {
25
+ if (!Array.isArray(schemaOptions.definitions)) {
26
+ throw `"schema.definitions" must be an array of schemas`;
27
+ }
28
+ this.localSchemas = schemaOptions.definitions;
29
+ }
30
+ this.retries = 0;
31
+ this.maxRetries = 3;
32
+ }
33
+ async saveSchemaToDB(schema) {
34
+ const payload = {
35
+ className: schema.className,
36
+ fields: schema._fields,
37
+ indexes: schema._indexes,
38
+ classLevelPermissions: schema._clp
39
+ };
40
+ await (0, _SchemasRouter.internalCreateSchema)(schema.className, payload, this.config);
41
+ this.resetSchemaOps(schema);
42
+ }
43
+ resetSchemaOps(schema) {
44
+ // Reset ops like SDK
45
+ schema._fields = {};
46
+ schema._indexes = {};
47
+ }
48
+
49
+ // Simulate update like the SDK
50
+ // We cannot use SDK since routes are disabled
51
+ async updateSchemaToDB(schema) {
52
+ const payload = {
53
+ className: schema.className,
54
+ fields: schema._fields,
55
+ indexes: schema._indexes,
56
+ classLevelPermissions: schema._clp
57
+ };
58
+ await (0, _SchemasRouter.internalUpdateSchema)(schema.className, payload, this.config);
59
+ this.resetSchemaOps(schema);
60
+ }
61
+ async execute() {
62
+ try {
63
+ _logger.logger.info('Running Migrations');
64
+ if (this.schemaOptions && this.schemaOptions.beforeMigration) {
65
+ await Promise.resolve(this.schemaOptions.beforeMigration());
66
+ }
67
+ await this.executeMigrations();
68
+ if (this.schemaOptions && this.schemaOptions.afterMigration) {
69
+ await Promise.resolve(this.schemaOptions.afterMigration());
70
+ }
71
+ _logger.logger.info('Running Migrations Completed');
72
+ } catch (e) {
73
+ _logger.logger.error(`Failed to run migrations: ${e}`);
74
+ if (process.env.NODE_ENV === 'production') {
75
+ process.exit(1);
76
+ }
77
+ }
78
+ }
79
+ async executeMigrations() {
80
+ let timeout = null;
81
+ try {
82
+ // Set up a time out in production
83
+ // if we fail to get schema
84
+ // pm2 or K8s and many other process managers will try to restart the process
85
+ // after the exit
86
+ if (process.env.NODE_ENV === 'production') {
87
+ timeout = setTimeout(() => {
88
+ _logger.logger.error('Timeout occurred during execution of migrations. Exiting...');
89
+ process.exit(1);
90
+ }, 20000);
91
+ }
92
+ await this.createDeleteSession();
93
+ // -disable-next-line
94
+ const schemaController = await this.config.database.loadSchema();
95
+ this.allCloudSchemas = await schemaController.getAllClasses();
96
+ clearTimeout(timeout);
97
+ await Promise.all(this.localSchemas.map(async localSchema => this.saveOrUpdate(localSchema)));
98
+ this.checkForMissingSchemas();
99
+ await this.enforceCLPForNonProvidedClass();
100
+ } catch (e) {
101
+ if (timeout) {
102
+ clearTimeout(timeout);
103
+ }
104
+ if (this.retries < this.maxRetries) {
105
+ this.retries++;
106
+ // first retry 1sec, 2sec, 3sec total 6sec retry sequence
107
+ // retry will only happen in case of deploying multi parse server instance
108
+ // at the same time. Modern systems like k8 avoid this by doing rolling updates
109
+ await this.wait(1000 * this.retries);
110
+ await this.executeMigrations();
111
+ } else {
112
+ _logger.logger.error(`Failed to run migrations: ${e}`);
113
+ if (process.env.NODE_ENV === 'production') {
114
+ process.exit(1);
115
+ }
116
+ }
117
+ }
118
+ }
119
+ checkForMissingSchemas() {
120
+ if (this.schemaOptions.strict !== true) {
121
+ return;
122
+ }
123
+ const cloudSchemas = this.allCloudSchemas.map(s => s.className);
124
+ const localSchemas = this.localSchemas.map(s => s.className);
125
+ const missingSchemas = cloudSchemas.filter(c => !localSchemas.includes(c) && !_SchemaController.systemClasses.includes(c));
126
+ if (new Set(localSchemas).size !== localSchemas.length) {
127
+ _logger.logger.error(`The list of schemas provided contains duplicated "className" "${localSchemas.join('","')}"`);
128
+ process.exit(1);
129
+ }
130
+ if (this.schemaOptions.strict && missingSchemas.length) {
131
+ _logger.logger.warn(`The following schemas are currently present in the database, but not explicitly defined in a schema: "${missingSchemas.join('", "')}"`);
132
+ }
133
+ }
134
+
135
+ // Required for testing purpose
136
+ wait(time) {
137
+ return new Promise(resolve => setTimeout(resolve, time));
138
+ }
139
+ async enforceCLPForNonProvidedClass() {
140
+ const nonProvidedClasses = this.allCloudSchemas.filter(cloudSchema => !this.localSchemas.some(localSchema => localSchema.className === cloudSchema.className));
141
+ await Promise.all(nonProvidedClasses.map(async schema => {
142
+ const parseSchema = new Parse.Schema(schema.className);
143
+ this.handleCLP(schema, parseSchema);
144
+ await this.updateSchemaToDB(parseSchema);
145
+ }));
146
+ }
147
+
148
+ // Create a fake session since Parse do not create the _Session until
149
+ // a session is created
150
+ async createDeleteSession() {
151
+ const {
152
+ response
153
+ } = await _rest.default.create(this.config, _Auth.default.master(this.config), '_Session', {});
154
+ await _rest.default.del(this.config, _Auth.default.master(this.config), '_Session', response.objectId);
155
+ }
156
+ async saveOrUpdate(localSchema) {
157
+ const cloudSchema = this.allCloudSchemas.find(sc => sc.className === localSchema.className);
158
+ if (cloudSchema) {
159
+ try {
160
+ await this.updateSchema(localSchema, cloudSchema);
161
+ } catch (e) {
162
+ throw `Error during update of schema for type ${cloudSchema.className}: ${e}`;
163
+ }
164
+ } else {
165
+ try {
166
+ await this.saveSchema(localSchema);
167
+ } catch (e) {
168
+ throw `Error while saving Schema for type ${localSchema.className}: ${e}`;
169
+ }
170
+ }
171
+ }
172
+ async saveSchema(localSchema) {
173
+ const newLocalSchema = new Parse.Schema(localSchema.className);
174
+ if (localSchema.fields) {
175
+ // Handle fields
176
+ Object.keys(localSchema.fields).filter(fieldName => !this.isProtectedFields(localSchema.className, fieldName)).forEach(fieldName => {
177
+ if (localSchema.fields) {
178
+ const field = localSchema.fields[fieldName];
179
+ this.handleFields(newLocalSchema, fieldName, field);
180
+ }
181
+ });
182
+ }
183
+ // Handle indexes
184
+ if (localSchema.indexes) {
185
+ Object.keys(localSchema.indexes).forEach(indexName => {
186
+ if (localSchema.indexes && !this.isProtectedIndex(localSchema.className, indexName)) {
187
+ newLocalSchema.addIndex(indexName, localSchema.indexes[indexName]);
188
+ }
189
+ });
190
+ }
191
+ this.handleCLP(localSchema, newLocalSchema);
192
+ return await this.saveSchemaToDB(newLocalSchema);
193
+ }
194
+ async updateSchema(localSchema, cloudSchema) {
195
+ const newLocalSchema = new Parse.Schema(localSchema.className);
196
+
197
+ // Handle fields
198
+ // Check addition
199
+ if (localSchema.fields) {
200
+ Object.keys(localSchema.fields).filter(fieldName => !this.isProtectedFields(localSchema.className, fieldName)).forEach(fieldName => {
201
+ // -disable-next
202
+ const field = localSchema.fields[fieldName];
203
+ if (!cloudSchema.fields[fieldName]) {
204
+ this.handleFields(newLocalSchema, fieldName, field);
205
+ }
206
+ });
207
+ }
208
+ const fieldsToDelete = [];
209
+ const fieldsToRecreate = [];
210
+ const fieldsWithChangedParams = [];
211
+
212
+ // Check deletion
213
+ Object.keys(cloudSchema.fields).filter(fieldName => !this.isProtectedFields(localSchema.className, fieldName)).forEach(fieldName => {
214
+ const field = cloudSchema.fields[fieldName];
215
+ if (!localSchema.fields || !localSchema.fields[fieldName]) {
216
+ fieldsToDelete.push(fieldName);
217
+ return;
218
+ }
219
+ const localField = localSchema.fields[fieldName];
220
+ // Check if field has a changed type
221
+ if (!this.paramsAreEquals({
222
+ type: field.type,
223
+ targetClass: field.targetClass
224
+ }, {
225
+ type: localField.type,
226
+ targetClass: localField.targetClass
227
+ })) {
228
+ fieldsToRecreate.push({
229
+ fieldName,
230
+ from: {
231
+ type: field.type,
232
+ targetClass: field.targetClass
233
+ },
234
+ to: {
235
+ type: localField.type,
236
+ targetClass: localField.targetClass
237
+ }
238
+ });
239
+ return;
240
+ }
241
+
242
+ // Check if something changed other than the type (like required, defaultValue)
243
+ if (!this.paramsAreEquals(field, localField)) {
244
+ fieldsWithChangedParams.push(fieldName);
245
+ }
246
+ });
247
+ if (this.schemaOptions.deleteExtraFields === true) {
248
+ fieldsToDelete.forEach(fieldName => {
249
+ newLocalSchema.deleteField(fieldName);
250
+ });
251
+
252
+ // Delete fields from the schema then apply changes
253
+ await this.updateSchemaToDB(newLocalSchema);
254
+ } else if (this.schemaOptions.strict === true && fieldsToDelete.length) {
255
+ _logger.logger.warn(`The following fields exist in the database for "${localSchema.className}", but are missing in the schema : "${fieldsToDelete.join('" ,"')}"`);
256
+ }
257
+ if (this.schemaOptions.recreateModifiedFields === true) {
258
+ fieldsToRecreate.forEach(field => {
259
+ newLocalSchema.deleteField(field.fieldName);
260
+ });
261
+
262
+ // Delete fields from the schema then apply changes
263
+ await this.updateSchemaToDB(newLocalSchema);
264
+ fieldsToRecreate.forEach(fieldInfo => {
265
+ if (localSchema.fields) {
266
+ const field = localSchema.fields[fieldInfo.fieldName];
267
+ this.handleFields(newLocalSchema, fieldInfo.fieldName, field);
268
+ }
269
+ });
270
+ } else if (this.schemaOptions.strict === true && fieldsToRecreate.length) {
271
+ fieldsToRecreate.forEach(field => {
272
+ const from = field.from.type + (field.from.targetClass ? ` (${field.from.targetClass})` : '');
273
+ const to = field.to.type + (field.to.targetClass ? ` (${field.to.targetClass})` : '');
274
+ _logger.logger.warn(`The field "${field.fieldName}" type differ between the schema and the database for "${localSchema.className}"; Schema is defined as "${to}" and current database type is "${from}"`);
275
+ });
276
+ }
277
+ fieldsWithChangedParams.forEach(fieldName => {
278
+ if (localSchema.fields) {
279
+ const field = localSchema.fields[fieldName];
280
+ this.handleFields(newLocalSchema, fieldName, field);
281
+ }
282
+ });
283
+
284
+ // Handle Indexes
285
+ // Check addition
286
+ if (localSchema.indexes) {
287
+ Object.keys(localSchema.indexes).forEach(indexName => {
288
+ if ((!cloudSchema.indexes || !cloudSchema.indexes[indexName]) && !this.isProtectedIndex(localSchema.className, indexName)) {
289
+ if (localSchema.indexes) {
290
+ newLocalSchema.addIndex(indexName, localSchema.indexes[indexName]);
291
+ }
292
+ }
293
+ });
294
+ }
295
+ const indexesToAdd = [];
296
+
297
+ // Check deletion
298
+ if (cloudSchema.indexes) {
299
+ Object.keys(cloudSchema.indexes).forEach(indexName => {
300
+ if (!this.isProtectedIndex(localSchema.className, indexName)) {
301
+ if (!localSchema.indexes || !localSchema.indexes[indexName]) {
302
+ // If keepUnknownIndex is falsy, then delete all unknown indexes from the db.
303
+ if (!this.schemaOptions.keepUnknownIndexes) {
304
+ newLocalSchema.deleteIndex(indexName);
305
+ }
306
+ } else if (!this.paramsAreEquals(localSchema.indexes[indexName], cloudSchema.indexes[indexName])) {
307
+ newLocalSchema.deleteIndex(indexName);
308
+ if (localSchema.indexes) {
309
+ indexesToAdd.push({
310
+ indexName,
311
+ index: localSchema.indexes[indexName]
312
+ });
313
+ }
314
+ }
315
+ }
316
+ });
317
+ }
318
+ this.handleCLP(localSchema, newLocalSchema, cloudSchema);
319
+ // Apply changes
320
+ await this.updateSchemaToDB(newLocalSchema);
321
+ // Apply new/changed indexes
322
+ if (indexesToAdd.length) {
323
+ _logger.logger.debug(`Updating indexes for "${newLocalSchema.className}" : ${indexesToAdd.join(' ,')}`);
324
+ indexesToAdd.forEach(o => newLocalSchema.addIndex(o.indexName, o.index));
325
+ await this.updateSchemaToDB(newLocalSchema);
326
+ }
327
+ }
328
+ handleCLP(localSchema, newLocalSchema, cloudSchema) {
329
+ if (!localSchema.classLevelPermissions && !cloudSchema) {
330
+ _logger.logger.warn(`classLevelPermissions not provided for ${localSchema.className}.`);
331
+ }
332
+ // Use spread to avoid read only issue (encountered by Moumouls using directAccess)
333
+ const clp = {
334
+ ...(localSchema.classLevelPermissions || {})
335
+ };
336
+ // To avoid inconsistency we need to remove all rights on addField
337
+ clp.addField = {};
338
+ newLocalSchema.setCLP(clp);
339
+ }
340
+ isProtectedFields(className, fieldName) {
341
+ return !!_SchemaController.defaultColumns._Default[fieldName] || !!(_SchemaController.defaultColumns[className] && _SchemaController.defaultColumns[className][fieldName]);
342
+ }
343
+ isProtectedIndex(className, indexName) {
344
+ const indexes = ['_id_'];
345
+ switch (className) {
346
+ case '_User':
347
+ indexes.push('case_insensitive_username', 'case_insensitive_email', 'username_1', 'email_1');
348
+ break;
349
+ case '_Role':
350
+ indexes.push('name_1');
351
+ break;
352
+ case '_Idempotency':
353
+ indexes.push('reqId_1');
354
+ break;
355
+ }
356
+ return indexes.indexOf(indexName) !== -1;
357
+ }
358
+ paramsAreEquals(objA, objB) {
359
+ const keysA = Object.keys(objA);
360
+ const keysB = Object.keys(objB);
361
+
362
+ // Check key name
363
+ if (keysA.length !== keysB.length) {
364
+ return false;
365
+ }
366
+ return keysA.every(k => objA[k] === objB[k]);
367
+ }
368
+ handleFields(newLocalSchema, fieldName, field) {
369
+ if (field.type === 'Relation') {
370
+ newLocalSchema.addRelation(fieldName, field.targetClass);
371
+ } else if (field.type === 'Pointer') {
372
+ newLocalSchema.addPointer(fieldName, field.targetClass, field);
373
+ } else {
374
+ newLocalSchema.addField(fieldName, field.type, field);
375
+ }
376
+ }
377
+ }
378
+ exports.DefinedSchemas = DefinedSchemas;
379
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbG9nZ2VyIiwicmVxdWlyZSIsIl9Db25maWciLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwiX1NjaGVtYXNSb3V0ZXIiLCJfU2NoZW1hQ29udHJvbGxlciIsIl9PcHRpb25zIiwiTWlncmF0aW9ucyIsIl9pbnRlcm9wUmVxdWlyZVdpbGRjYXJkIiwiX0F1dGgiLCJfcmVzdCIsImUiLCJ0IiwiV2Vha01hcCIsInIiLCJuIiwiX19lc01vZHVsZSIsIm8iLCJpIiwiZiIsIl9fcHJvdG9fXyIsImRlZmF1bHQiLCJoYXMiLCJnZXQiLCJzZXQiLCJoYXNPd25Qcm9wZXJ0eSIsImNhbGwiLCJPYmplY3QiLCJkZWZpbmVQcm9wZXJ0eSIsImdldE93blByb3BlcnR5RGVzY3JpcHRvciIsIlBhcnNlIiwiRGVmaW5lZFNjaGVtYXMiLCJjb25zdHJ1Y3RvciIsInNjaGVtYU9wdGlvbnMiLCJjb25maWciLCJsb2NhbFNjaGVtYXMiLCJDb25maWciLCJhcHBJZCIsImRlZmluaXRpb25zIiwiQXJyYXkiLCJpc0FycmF5IiwicmV0cmllcyIsIm1heFJldHJpZXMiLCJzYXZlU2NoZW1hVG9EQiIsInNjaGVtYSIsInBheWxvYWQiLCJjbGFzc05hbWUiLCJmaWVsZHMiLCJfZmllbGRzIiwiaW5kZXhlcyIsIl9pbmRleGVzIiwiY2xhc3NMZXZlbFBlcm1pc3Npb25zIiwiX2NscCIsImludGVybmFsQ3JlYXRlU2NoZW1hIiwicmVzZXRTY2hlbWFPcHMiLCJ1cGRhdGVTY2hlbWFUb0RCIiwiaW50ZXJuYWxVcGRhdGVTY2hlbWEiLCJleGVjdXRlIiwibG9nZ2VyIiwiaW5mbyIsImJlZm9yZU1pZ3JhdGlvbiIsIlByb21pc2UiLCJyZXNvbHZlIiwiZXhlY3V0ZU1pZ3JhdGlvbnMiLCJhZnRlck1pZ3JhdGlvbiIsImVycm9yIiwicHJvY2VzcyIsImVudiIsIk5PREVfRU5WIiwiZXhpdCIsInRpbWVvdXQiLCJzZXRUaW1lb3V0IiwiY3JlYXRlRGVsZXRlU2Vzc2lvbiIsInNjaGVtYUNvbnRyb2xsZXIiLCJkYXRhYmFzZSIsImxvYWRTY2hlbWEiLCJhbGxDbG91ZFNjaGVtYXMiLCJnZXRBbGxDbGFzc2VzIiwiY2xlYXJUaW1lb3V0IiwiYWxsIiwibWFwIiwibG9jYWxTY2hlbWEiLCJzYXZlT3JVcGRhdGUiLCJjaGVja0Zvck1pc3NpbmdTY2hlbWFzIiwiZW5mb3JjZUNMUEZvck5vblByb3ZpZGVkQ2xhc3MiLCJ3YWl0Iiwic3RyaWN0IiwiY2xvdWRTY2hlbWFzIiwicyIsIm1pc3NpbmdTY2hlbWFzIiwiZmlsdGVyIiwiYyIsImluY2x1ZGVzIiwic3lzdGVtQ2xhc3NlcyIsIlNldCIsInNpemUiLCJsZW5ndGgiLCJqb2luIiwid2FybiIsInRpbWUiLCJub25Qcm92aWRlZENsYXNzZXMiLCJjbG91ZFNjaGVtYSIsInNvbWUiLCJwYXJzZVNjaGVtYSIsIlNjaGVtYSIsImhhbmRsZUNMUCIsInJlc3BvbnNlIiwicmVzdCIsImNyZWF0ZSIsIkF1dGgiLCJtYXN0ZXIiLCJkZWwiLCJvYmplY3RJZCIsImZpbmQiLCJzYyIsInVwZGF0ZVNjaGVtYSIsInNhdmVTY2hlbWEiLCJuZXdMb2NhbFNjaGVtYSIsImtleXMiLCJmaWVsZE5hbWUiLCJpc1Byb3RlY3RlZEZpZWxkcyIsImZvckVhY2giLCJmaWVsZCIsImhhbmRsZUZpZWxkcyIsImluZGV4TmFtZSIsImlzUHJvdGVjdGVkSW5kZXgiLCJhZGRJbmRleCIsImZpZWxkc1RvRGVsZXRlIiwiZmllbGRzVG9SZWNyZWF0ZSIsImZpZWxkc1dpdGhDaGFuZ2VkUGFyYW1zIiwicHVzaCIsImxvY2FsRmllbGQiLCJwYXJhbXNBcmVFcXVhbHMiLCJ0eXBlIiwidGFyZ2V0Q2xhc3MiLCJmcm9tIiwidG8iLCJkZWxldGVFeHRyYUZpZWxkcyIsImRlbGV0ZUZpZWxkIiwicmVjcmVhdGVNb2RpZmllZEZpZWxkcyIsImZpZWxkSW5mbyIsImluZGV4ZXNUb0FkZCIsImtlZXBVbmtub3duSW5kZXhlcyIsImRlbGV0ZUluZGV4IiwiaW5kZXgiLCJkZWJ1ZyIsImNscCIsImFkZEZpZWxkIiwic2V0Q0xQIiwiZGVmYXVsdENvbHVtbnMiLCJfRGVmYXVsdCIsImluZGV4T2YiLCJvYmpBIiwib2JqQiIsImtleXNBIiwia2V5c0IiLCJldmVyeSIsImsiLCJhZGRSZWxhdGlvbiIsImFkZFBvaW50ZXIiLCJleHBvcnRzIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL1NjaGVtYU1pZ3JhdGlvbnMvRGVmaW5lZFNjaGVtYXMuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gQGZsb3dcbi8vIEBmbG93LWRpc2FibGUtbmV4dCBDYW5ub3QgcmVzb2x2ZSBtb2R1bGUgYHBhcnNlL25vZGVgLlxuY29uc3QgUGFyc2UgPSByZXF1aXJlKCdwYXJzZS9ub2RlJyk7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tICcuLi9sb2dnZXInO1xuaW1wb3J0IENvbmZpZyBmcm9tICcuLi9Db25maWcnO1xuaW1wb3J0IHsgaW50ZXJuYWxDcmVhdGVTY2hlbWEsIGludGVybmFsVXBkYXRlU2NoZW1hIH0gZnJvbSAnLi4vUm91dGVycy9TY2hlbWFzUm91dGVyJztcbmltcG9ydCB7IGRlZmF1bHRDb2x1bW5zLCBzeXN0ZW1DbGFzc2VzIH0gZnJvbSAnLi4vQ29udHJvbGxlcnMvU2NoZW1hQ29udHJvbGxlcic7XG5pbXBvcnQgeyBQYXJzZVNlcnZlck9wdGlvbnMgfSBmcm9tICcuLi9PcHRpb25zJztcbmltcG9ydCAqIGFzIE1pZ3JhdGlvbnMgZnJvbSAnLi9NaWdyYXRpb25zJztcbmltcG9ydCBBdXRoIGZyb20gJy4uL0F1dGgnO1xuaW1wb3J0IHJlc3QgZnJvbSAnLi4vcmVzdCc7XG5cbmV4cG9ydCBjbGFzcyBEZWZpbmVkU2NoZW1hcyB7XG4gIGNvbmZpZzogUGFyc2VTZXJ2ZXJPcHRpb25zO1xuICBzY2hlbWFPcHRpb25zOiBNaWdyYXRpb25zLlNjaGVtYU9wdGlvbnM7XG4gIGxvY2FsU2NoZW1hczogTWlncmF0aW9ucy5KU09OU2NoZW1hW107XG4gIHJldHJpZXM6IG51bWJlcjtcbiAgbWF4UmV0cmllczogbnVtYmVyO1xuICBhbGxDbG91ZFNjaGVtYXM6IFBhcnNlLlNjaGVtYVtdO1xuXG4gIGNvbnN0cnVjdG9yKHNjaGVtYU9wdGlvbnM6IE1pZ3JhdGlvbnMuU2NoZW1hT3B0aW9ucywgY29uZmlnOiBQYXJzZVNlcnZlck9wdGlvbnMpIHtcbiAgICB0aGlzLmxvY2FsU2NoZW1hcyA9IFtdO1xuICAgIHRoaXMuY29uZmlnID0gQ29uZmlnLmdldChjb25maWcuYXBwSWQpO1xuICAgIHRoaXMuc2NoZW1hT3B0aW9ucyA9IHNjaGVtYU9wdGlvbnM7XG4gICAgaWYgKHNjaGVtYU9wdGlvbnMgJiYgc2NoZW1hT3B0aW9ucy5kZWZpbml0aW9ucykge1xuICAgICAgaWYgKCFBcnJheS5pc0FycmF5KHNjaGVtYU9wdGlvbnMuZGVmaW5pdGlvbnMpKSB7XG4gICAgICAgIHRocm93IGBcInNjaGVtYS5kZWZpbml0aW9uc1wiIG11c3QgYmUgYW4gYXJyYXkgb2Ygc2NoZW1hc2A7XG4gICAgICB9XG5cbiAgICAgIHRoaXMubG9jYWxTY2hlbWFzID0gc2NoZW1hT3B0aW9ucy5kZWZpbml0aW9ucztcbiAgICB9XG5cbiAgICB0aGlzLnJldHJpZXMgPSAwO1xuICAgIHRoaXMubWF4UmV0cmllcyA9IDM7XG4gIH1cblxuICBhc3luYyBzYXZlU2NoZW1hVG9EQihzY2hlbWE6IFBhcnNlLlNjaGVtYSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHBheWxvYWQgPSB7XG4gICAgICBjbGFzc05hbWU6IHNjaGVtYS5jbGFzc05hbWUsXG4gICAgICBmaWVsZHM6IHNjaGVtYS5fZmllbGRzLFxuICAgICAgaW5kZXhlczogc2NoZW1hLl9pbmRleGVzLFxuICAgICAgY2xhc3NMZXZlbFBlcm1pc3Npb25zOiBzY2hlbWEuX2NscCxcbiAgICB9O1xuICAgIGF3YWl0IGludGVybmFsQ3JlYXRlU2NoZW1hKHNjaGVtYS5jbGFzc05hbWUsIHBheWxvYWQsIHRoaXMuY29uZmlnKTtcbiAgICB0aGlzLnJlc2V0U2NoZW1hT3BzKHNjaGVtYSk7XG4gIH1cblxuICByZXNldFNjaGVtYU9wcyhzY2hlbWE6IFBhcnNlLlNjaGVtYSkge1xuICAgIC8vIFJlc2V0IG9wcyBsaWtlIFNES1xuICAgIHNjaGVtYS5fZmllbGRzID0ge307XG4gICAgc2NoZW1hLl9pbmRleGVzID0ge307XG4gIH1cblxuICAvLyBTaW11bGF0ZSB1cGRhdGUgbGlrZSB0aGUgU0RLXG4gIC8vIFdlIGNhbm5vdCB1c2UgU0RLIHNpbmNlIHJvdXRlcyBhcmUgZGlzYWJsZWRcbiAgYXN5bmMgdXBkYXRlU2NoZW1hVG9EQihzY2hlbWE6IFBhcnNlLlNjaGVtYSkge1xuICAgIGNvbnN0IHBheWxvYWQgPSB7XG4gICAgICBjbGFzc05hbWU6IHNjaGVtYS5jbGFzc05hbWUsXG4gICAgICBmaWVsZHM6IHNjaGVtYS5fZmllbGRzLFxuICAgICAgaW5kZXhlczogc2NoZW1hLl9pbmRleGVzLFxuICAgICAgY2xhc3NMZXZlbFBlcm1pc3Npb25zOiBzY2hlbWEuX2NscCxcbiAgICB9O1xuICAgIGF3YWl0IGludGVybmFsVXBkYXRlU2NoZW1hKHNjaGVtYS5jbGFzc05hbWUsIHBheWxvYWQsIHRoaXMuY29uZmlnKTtcbiAgICB0aGlzLnJlc2V0U2NoZW1hT3BzKHNjaGVtYSk7XG4gIH1cblxuICBhc3luYyBleGVjdXRlKCkge1xuICAgIHRyeSB7XG4gICAgICBsb2dnZXIuaW5mbygnUnVubmluZyBNaWdyYXRpb25zJyk7XG4gICAgICBpZiAodGhpcy5zY2hlbWFPcHRpb25zICYmIHRoaXMuc2NoZW1hT3B0aW9ucy5iZWZvcmVNaWdyYXRpb24pIHtcbiAgICAgICAgYXdhaXQgUHJvbWlzZS5yZXNvbHZlKHRoaXMuc2NoZW1hT3B0aW9ucy5iZWZvcmVNaWdyYXRpb24oKSk7XG4gICAgICB9XG5cbiAgICAgIGF3YWl0IHRoaXMuZXhlY3V0ZU1pZ3JhdGlvbnMoKTtcblxuICAgICAgaWYgKHRoaXMuc2NoZW1hT3B0aW9ucyAmJiB0aGlzLnNjaGVtYU9wdGlvbnMuYWZ0ZXJNaWdyYXRpb24pIHtcbiAgICAgICAgYXdhaXQgUHJvbWlzZS5yZXNvbHZlKHRoaXMuc2NoZW1hT3B0aW9ucy5hZnRlck1pZ3JhdGlvbigpKTtcbiAgICAgIH1cblxuICAgICAgbG9nZ2VyLmluZm8oJ1J1bm5pbmcgTWlncmF0aW9ucyBDb21wbGV0ZWQnKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBsb2dnZXIuZXJyb3IoYEZhaWxlZCB0byBydW4gbWlncmF0aW9uczogJHtlfWApO1xuICAgICAgaWYgKHByb2Nlc3MuZW52Lk5PREVfRU5WID09PSAncHJvZHVjdGlvbicpIHsgcHJvY2Vzcy5leGl0KDEpOyB9XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgZXhlY3V0ZU1pZ3JhdGlvbnMoKSB7XG4gICAgbGV0IHRpbWVvdXQgPSBudWxsO1xuICAgIHRyeSB7XG4gICAgICAvLyBTZXQgdXAgYSB0aW1lIG91dCBpbiBwcm9kdWN0aW9uXG4gICAgICAvLyBpZiB3ZSBmYWlsIHRvIGdldCBzY2hlbWFcbiAgICAgIC8vIHBtMiBvciBLOHMgYW5kIG1hbnkgb3RoZXIgcHJvY2VzcyBtYW5hZ2VycyB3aWxsIHRyeSB0byByZXN0YXJ0IHRoZSBwcm9jZXNzXG4gICAgICAvLyBhZnRlciB0aGUgZXhpdFxuICAgICAgaWYgKHByb2Nlc3MuZW52Lk5PREVfRU5WID09PSAncHJvZHVjdGlvbicpIHtcbiAgICAgICAgdGltZW91dCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgIGxvZ2dlci5lcnJvcignVGltZW91dCBvY2N1cnJlZCBkdXJpbmcgZXhlY3V0aW9uIG9mIG1pZ3JhdGlvbnMuIEV4aXRpbmcuLi4nKTtcbiAgICAgICAgICBwcm9jZXNzLmV4aXQoMSk7XG4gICAgICAgIH0sIDIwMDAwKTtcbiAgICAgIH1cblxuICAgICAgYXdhaXQgdGhpcy5jcmVhdGVEZWxldGVTZXNzaW9uKCk7XG4gICAgICAvLyBAZmxvdy1kaXNhYmxlLW5leHQtbGluZVxuICAgICAgY29uc3Qgc2NoZW1hQ29udHJvbGxlciA9IGF3YWl0IHRoaXMuY29uZmlnLmRhdGFiYXNlLmxvYWRTY2hlbWEoKTtcbiAgICAgIHRoaXMuYWxsQ2xvdWRTY2hlbWFzID0gYXdhaXQgc2NoZW1hQ29udHJvbGxlci5nZXRBbGxDbGFzc2VzKCk7XG4gICAgICBjbGVhclRpbWVvdXQodGltZW91dCk7XG4gICAgICBhd2FpdCBQcm9taXNlLmFsbCh0aGlzLmxvY2FsU2NoZW1hcy5tYXAoYXN5bmMgbG9jYWxTY2hlbWEgPT4gdGhpcy5zYXZlT3JVcGRhdGUobG9jYWxTY2hlbWEpKSk7XG5cbiAgICAgIHRoaXMuY2hlY2tGb3JNaXNzaW5nU2NoZW1hcygpO1xuICAgICAgYXdhaXQgdGhpcy5lbmZvcmNlQ0xQRm9yTm9uUHJvdmlkZWRDbGFzcygpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICh0aW1lb3V0KSB7IGNsZWFyVGltZW91dCh0aW1lb3V0KTsgfVxuICAgICAgaWYgKHRoaXMucmV0cmllcyA8IHRoaXMubWF4UmV0cmllcykge1xuICAgICAgICB0aGlzLnJldHJpZXMrKztcbiAgICAgICAgLy8gZmlyc3QgcmV0cnkgMXNlYywgMnNlYywgM3NlYyB0b3RhbCA2c2VjIHJldHJ5IHNlcXVlbmNlXG4gICAgICAgIC8vIHJldHJ5IHdpbGwgb25seSBoYXBwZW4gaW4gY2FzZSBvZiBkZXBsb3lpbmcgbXVsdGkgcGFyc2Ugc2VydmVyIGluc3RhbmNlXG4gICAgICAgIC8vIGF0IHRoZSBzYW1lIHRpbWUuIE1vZGVybiBzeXN0ZW1zIGxpa2UgazggYXZvaWQgdGhpcyBieSBkb2luZyByb2xsaW5nIHVwZGF0ZXNcbiAgICAgICAgYXdhaXQgdGhpcy53YWl0KDEwMDAgKiB0aGlzLnJldHJpZXMpO1xuICAgICAgICBhd2FpdCB0aGlzLmV4ZWN1dGVNaWdyYXRpb25zKCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsb2dnZXIuZXJyb3IoYEZhaWxlZCB0byBydW4gbWlncmF0aW9uczogJHtlfWApO1xuICAgICAgICBpZiAocHJvY2Vzcy5lbnYuTk9ERV9FTlYgPT09ICdwcm9kdWN0aW9uJykgeyBwcm9jZXNzLmV4aXQoMSk7IH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBjaGVja0Zvck1pc3NpbmdTY2hlbWFzKCkge1xuICAgIGlmICh0aGlzLnNjaGVtYU9wdGlvbnMuc3RyaWN0ICE9PSB0cnVlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgY2xvdWRTY2hlbWFzID0gdGhpcy5hbGxDbG91ZFNjaGVtYXMubWFwKHMgPT4gcy5jbGFzc05hbWUpO1xuICAgIGNvbnN0IGxvY2FsU2NoZW1hcyA9IHRoaXMubG9jYWxTY2hlbWFzLm1hcChzID0+IHMuY2xhc3NOYW1lKTtcbiAgICBjb25zdCBtaXNzaW5nU2NoZW1hcyA9IGNsb3VkU2NoZW1hcy5maWx0ZXIoXG4gICAgICBjID0+ICFsb2NhbFNjaGVtYXMuaW5jbHVkZXMoYykgJiYgIXN5c3RlbUNsYXNzZXMuaW5jbHVkZXMoYylcbiAgICApO1xuXG4gICAgaWYgKG5ldyBTZXQobG9jYWxTY2hlbWFzKS5zaXplICE9PSBsb2NhbFNjaGVtYXMubGVuZ3RoKSB7XG4gICAgICBsb2dnZXIuZXJyb3IoXG4gICAgICAgIGBUaGUgbGlzdCBvZiBzY2hlbWFzIHByb3ZpZGVkIGNvbnRhaW5zIGR1cGxpY2F0ZWQgXCJjbGFzc05hbWVcIiAgXCIke2xvY2FsU2NoZW1hcy5qb2luKFxuICAgICAgICAgICdcIixcIidcbiAgICAgICAgKX1cImBcbiAgICAgICk7XG4gICAgICBwcm9jZXNzLmV4aXQoMSk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuc2NoZW1hT3B0aW9ucy5zdHJpY3QgJiYgbWlzc2luZ1NjaGVtYXMubGVuZ3RoKSB7XG4gICAgICBsb2dnZXIud2FybihcbiAgICAgICAgYFRoZSBmb2xsb3dpbmcgc2NoZW1hcyBhcmUgY3VycmVudGx5IHByZXNlbnQgaW4gdGhlIGRhdGFiYXNlLCBidXQgbm90IGV4cGxpY2l0bHkgZGVmaW5lZCBpbiBhIHNjaGVtYTogXCIke21pc3NpbmdTY2hlbWFzLmpvaW4oXG4gICAgICAgICAgJ1wiLCBcIidcbiAgICAgICAgKX1cImBcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLy8gUmVxdWlyZWQgZm9yIHRlc3RpbmcgcHVycG9zZVxuICB3YWl0KHRpbWU6IG51bWJlcikge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTx2b2lkPihyZXNvbHZlID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgdGltZSkpO1xuICB9XG5cbiAgYXN5bmMgZW5mb3JjZUNMUEZvck5vblByb3ZpZGVkQ2xhc3MoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3Qgbm9uUHJvdmlkZWRDbGFzc2VzID0gdGhpcy5hbGxDbG91ZFNjaGVtYXMuZmlsdGVyKFxuICAgICAgY2xvdWRTY2hlbWEgPT5cbiAgICAgICAgIXRoaXMubG9jYWxTY2hlbWFzLnNvbWUobG9jYWxTY2hlbWEgPT4gbG9jYWxTY2hlbWEuY2xhc3NOYW1lID09PSBjbG91ZFNjaGVtYS5jbGFzc05hbWUpXG4gICAgKTtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIG5vblByb3ZpZGVkQ2xhc3Nlcy5tYXAoYXN5bmMgc2NoZW1hID0+IHtcbiAgICAgICAgY29uc3QgcGFyc2VTY2hlbWEgPSBuZXcgUGFyc2UuU2NoZW1hKHNjaGVtYS5jbGFzc05hbWUpO1xuICAgICAgICB0aGlzLmhhbmRsZUNMUChzY2hlbWEsIHBhcnNlU2NoZW1hKTtcbiAgICAgICAgYXdhaXQgdGhpcy51cGRhdGVTY2hlbWFUb0RCKHBhcnNlU2NoZW1hKTtcbiAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIC8vIENyZWF0ZSBhIGZha2Ugc2Vzc2lvbiBzaW5jZSBQYXJzZSBkbyBub3QgY3JlYXRlIHRoZSBfU2Vzc2lvbiB1bnRpbFxuICAvLyBhIHNlc3Npb24gaXMgY3JlYXRlZFxuICBhc3luYyBjcmVhdGVEZWxldGVTZXNzaW9uKCkge1xuICAgIGNvbnN0IHsgcmVzcG9uc2UgfSA9IGF3YWl0IHJlc3QuY3JlYXRlKHRoaXMuY29uZmlnLCBBdXRoLm1hc3Rlcih0aGlzLmNvbmZpZyksICdfU2Vzc2lvbicsIHt9KTtcbiAgICBhd2FpdCByZXN0LmRlbCh0aGlzLmNvbmZpZywgQXV0aC5tYXN0ZXIodGhpcy5jb25maWcpLCAnX1Nlc3Npb24nLCByZXNwb25zZS5vYmplY3RJZCk7XG4gIH1cblxuICBhc3luYyBzYXZlT3JVcGRhdGUobG9jYWxTY2hlbWE6IE1pZ3JhdGlvbnMuSlNPTlNjaGVtYSkge1xuICAgIGNvbnN0IGNsb3VkU2NoZW1hID0gdGhpcy5hbGxDbG91ZFNjaGVtYXMuZmluZChzYyA9PiBzYy5jbGFzc05hbWUgPT09IGxvY2FsU2NoZW1hLmNsYXNzTmFtZSk7XG4gICAgaWYgKGNsb3VkU2NoZW1hKSB7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCB0aGlzLnVwZGF0ZVNjaGVtYShsb2NhbFNjaGVtYSwgY2xvdWRTY2hlbWEpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICB0aHJvdyBgRXJyb3IgZHVyaW5nIHVwZGF0ZSBvZiBzY2hlbWEgZm9yIHR5cGUgJHtjbG91ZFNjaGVtYS5jbGFzc05hbWV9OiAke2V9YDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgdGhpcy5zYXZlU2NoZW1hKGxvY2FsU2NoZW1hKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgdGhyb3cgYEVycm9yIHdoaWxlIHNhdmluZyBTY2hlbWEgZm9yIHR5cGUgJHtsb2NhbFNjaGVtYS5jbGFzc05hbWV9OiAke2V9YDtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBhc3luYyBzYXZlU2NoZW1hKGxvY2FsU2NoZW1hOiBNaWdyYXRpb25zLkpTT05TY2hlbWEpIHtcbiAgICBjb25zdCBuZXdMb2NhbFNjaGVtYSA9IG5ldyBQYXJzZS5TY2hlbWEobG9jYWxTY2hlbWEuY2xhc3NOYW1lKTtcbiAgICBpZiAobG9jYWxTY2hlbWEuZmllbGRzKSB7XG4gICAgICAvLyBIYW5kbGUgZmllbGRzXG4gICAgICBPYmplY3Qua2V5cyhsb2NhbFNjaGVtYS5maWVsZHMpXG4gICAgICAgIC5maWx0ZXIoZmllbGROYW1lID0+ICF0aGlzLmlzUHJvdGVjdGVkRmllbGRzKGxvY2FsU2NoZW1hLmNsYXNzTmFtZSwgZmllbGROYW1lKSlcbiAgICAgICAgLmZvckVhY2goZmllbGROYW1lID0+IHtcbiAgICAgICAgICBpZiAobG9jYWxTY2hlbWEuZmllbGRzKSB7XG4gICAgICAgICAgICBjb25zdCBmaWVsZCA9IGxvY2FsU2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdO1xuICAgICAgICAgICAgdGhpcy5oYW5kbGVGaWVsZHMobmV3TG9jYWxTY2hlbWEsIGZpZWxkTmFtZSwgZmllbGQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuICAgIC8vIEhhbmRsZSBpbmRleGVzXG4gICAgaWYgKGxvY2FsU2NoZW1hLmluZGV4ZXMpIHtcbiAgICAgIE9iamVjdC5rZXlzKGxvY2FsU2NoZW1hLmluZGV4ZXMpLmZvckVhY2goaW5kZXhOYW1lID0+IHtcbiAgICAgICAgaWYgKGxvY2FsU2NoZW1hLmluZGV4ZXMgJiYgIXRoaXMuaXNQcm90ZWN0ZWRJbmRleChsb2NhbFNjaGVtYS5jbGFzc05hbWUsIGluZGV4TmFtZSkpIHtcbiAgICAgICAgICBuZXdMb2NhbFNjaGVtYS5hZGRJbmRleChpbmRleE5hbWUsIGxvY2FsU2NoZW1hLmluZGV4ZXNbaW5kZXhOYW1lXSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHRoaXMuaGFuZGxlQ0xQKGxvY2FsU2NoZW1hLCBuZXdMb2NhbFNjaGVtYSk7XG5cbiAgICByZXR1cm4gYXdhaXQgdGhpcy5zYXZlU2NoZW1hVG9EQihuZXdMb2NhbFNjaGVtYSk7XG4gIH1cblxuICBhc3luYyB1cGRhdGVTY2hlbWEobG9jYWxTY2hlbWE6IE1pZ3JhdGlvbnMuSlNPTlNjaGVtYSwgY2xvdWRTY2hlbWE6IFBhcnNlLlNjaGVtYSkge1xuICAgIGNvbnN0IG5ld0xvY2FsU2NoZW1hID0gbmV3IFBhcnNlLlNjaGVtYShsb2NhbFNjaGVtYS5jbGFzc05hbWUpO1xuXG4gICAgLy8gSGFuZGxlIGZpZWxkc1xuICAgIC8vIENoZWNrIGFkZGl0aW9uXG4gICAgaWYgKGxvY2FsU2NoZW1hLmZpZWxkcykge1xuICAgICAgT2JqZWN0LmtleXMobG9jYWxTY2hlbWEuZmllbGRzKVxuICAgICAgICAuZmlsdGVyKGZpZWxkTmFtZSA9PiAhdGhpcy5pc1Byb3RlY3RlZEZpZWxkcyhsb2NhbFNjaGVtYS5jbGFzc05hbWUsIGZpZWxkTmFtZSkpXG4gICAgICAgIC5mb3JFYWNoKGZpZWxkTmFtZSA9PiB7XG4gICAgICAgICAgLy8gQGZsb3ctZGlzYWJsZS1uZXh0XG4gICAgICAgICAgY29uc3QgZmllbGQgPSBsb2NhbFNjaGVtYS5maWVsZHNbZmllbGROYW1lXTtcbiAgICAgICAgICBpZiAoIWNsb3VkU2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdKSB7XG4gICAgICAgICAgICB0aGlzLmhhbmRsZUZpZWxkcyhuZXdMb2NhbFNjaGVtYSwgZmllbGROYW1lLCBmaWVsZCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBjb25zdCBmaWVsZHNUb0RlbGV0ZTogc3RyaW5nW10gPSBbXTtcbiAgICBjb25zdCBmaWVsZHNUb1JlY3JlYXRlOiB7XG4gICAgICBmaWVsZE5hbWU6IHN0cmluZyxcbiAgICAgIGZyb206IHsgdHlwZTogc3RyaW5nLCB0YXJnZXRDbGFzcz86IHN0cmluZyB9LFxuICAgICAgdG86IHsgdHlwZTogc3RyaW5nLCB0YXJnZXRDbGFzcz86IHN0cmluZyB9LFxuICAgIH1bXSA9IFtdO1xuICAgIGNvbnN0IGZpZWxkc1dpdGhDaGFuZ2VkUGFyYW1zOiBzdHJpbmdbXSA9IFtdO1xuXG4gICAgLy8gQ2hlY2sgZGVsZXRpb25cbiAgICBPYmplY3Qua2V5cyhjbG91ZFNjaGVtYS5maWVsZHMpXG4gICAgICAuZmlsdGVyKGZpZWxkTmFtZSA9PiAhdGhpcy5pc1Byb3RlY3RlZEZpZWxkcyhsb2NhbFNjaGVtYS5jbGFzc05hbWUsIGZpZWxkTmFtZSkpXG4gICAgICAuZm9yRWFjaChmaWVsZE5hbWUgPT4ge1xuICAgICAgICBjb25zdCBmaWVsZCA9IGNsb3VkU2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdO1xuICAgICAgICBpZiAoIWxvY2FsU2NoZW1hLmZpZWxkcyB8fCAhbG9jYWxTY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0pIHtcbiAgICAgICAgICBmaWVsZHNUb0RlbGV0ZS5wdXNoKGZpZWxkTmFtZSk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgbG9jYWxGaWVsZCA9IGxvY2FsU2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdO1xuICAgICAgICAvLyBDaGVjayBpZiBmaWVsZCBoYXMgYSBjaGFuZ2VkIHR5cGVcbiAgICAgICAgaWYgKFxuICAgICAgICAgICF0aGlzLnBhcmFtc0FyZUVxdWFscyhcbiAgICAgICAgICAgIHsgdHlwZTogZmllbGQudHlwZSwgdGFyZ2V0Q2xhc3M6IGZpZWxkLnRhcmdldENsYXNzIH0sXG4gICAgICAgICAgICB7IHR5cGU6IGxvY2FsRmllbGQudHlwZSwgdGFyZ2V0Q2xhc3M6IGxvY2FsRmllbGQudGFyZ2V0Q2xhc3MgfVxuICAgICAgICAgIClcbiAgICAgICAgKSB7XG4gICAgICAgICAgZmllbGRzVG9SZWNyZWF0ZS5wdXNoKHtcbiAgICAgICAgICAgIGZpZWxkTmFtZSxcbiAgICAgICAgICAgIGZyb206IHsgdHlwZTogZmllbGQudHlwZSwgdGFyZ2V0Q2xhc3M6IGZpZWxkLnRhcmdldENsYXNzIH0sXG4gICAgICAgICAgICB0bzogeyB0eXBlOiBsb2NhbEZpZWxkLnR5cGUsIHRhcmdldENsYXNzOiBsb2NhbEZpZWxkLnRhcmdldENsYXNzIH0sXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ2hlY2sgaWYgc29tZXRoaW5nIGNoYW5nZWQgb3RoZXIgdGhhbiB0aGUgdHlwZSAobGlrZSByZXF1aXJlZCwgZGVmYXVsdFZhbHVlKVxuICAgICAgICBpZiAoIXRoaXMucGFyYW1zQXJlRXF1YWxzKGZpZWxkLCBsb2NhbEZpZWxkKSkge1xuICAgICAgICAgIGZpZWxkc1dpdGhDaGFuZ2VkUGFyYW1zLnB1c2goZmllbGROYW1lKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICBpZiAodGhpcy5zY2hlbWFPcHRpb25zLmRlbGV0ZUV4dHJhRmllbGRzID09PSB0cnVlKSB7XG4gICAgICBmaWVsZHNUb0RlbGV0ZS5mb3JFYWNoKGZpZWxkTmFtZSA9PiB7XG4gICAgICAgIG5ld0xvY2FsU2NoZW1hLmRlbGV0ZUZpZWxkKGZpZWxkTmFtZSk7XG4gICAgICB9KTtcblxuICAgICAgLy8gRGVsZXRlIGZpZWxkcyBmcm9tIHRoZSBzY2hlbWEgdGhlbiBhcHBseSBjaGFuZ2VzXG4gICAgICBhd2FpdCB0aGlzLnVwZGF0ZVNjaGVtYVRvREIobmV3TG9jYWxTY2hlbWEpO1xuICAgIH0gZWxzZSBpZiAodGhpcy5zY2hlbWFPcHRpb25zLnN0cmljdCA9PT0gdHJ1ZSAmJiBmaWVsZHNUb0RlbGV0ZS5sZW5ndGgpIHtcbiAgICAgIGxvZ2dlci53YXJuKFxuICAgICAgICBgVGhlIGZvbGxvd2luZyBmaWVsZHMgZXhpc3QgaW4gdGhlIGRhdGFiYXNlIGZvciBcIiR7XG4gICAgICAgICAgbG9jYWxTY2hlbWEuY2xhc3NOYW1lXG4gICAgICAgIH1cIiwgYnV0IGFyZSBtaXNzaW5nIGluIHRoZSBzY2hlbWEgOiBcIiR7ZmllbGRzVG9EZWxldGUuam9pbignXCIgLFwiJyl9XCJgXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnNjaGVtYU9wdGlvbnMucmVjcmVhdGVNb2RpZmllZEZpZWxkcyA9PT0gdHJ1ZSkge1xuICAgICAgZmllbGRzVG9SZWNyZWF0ZS5mb3JFYWNoKGZpZWxkID0+IHtcbiAgICAgICAgbmV3TG9jYWxTY2hlbWEuZGVsZXRlRmllbGQoZmllbGQuZmllbGROYW1lKTtcbiAgICAgIH0pO1xuXG4gICAgICAvLyBEZWxldGUgZmllbGRzIGZyb20gdGhlIHNjaGVtYSB0aGVuIGFwcGx5IGNoYW5nZXNcbiAgICAgIGF3YWl0IHRoaXMudXBkYXRlU2NoZW1hVG9EQihuZXdMb2NhbFNjaGVtYSk7XG5cbiAgICAgIGZpZWxkc1RvUmVjcmVhdGUuZm9yRWFjaChmaWVsZEluZm8gPT4ge1xuICAgICAgICBpZiAobG9jYWxTY2hlbWEuZmllbGRzKSB7XG4gICAgICAgICAgY29uc3QgZmllbGQgPSBsb2NhbFNjaGVtYS5maWVsZHNbZmllbGRJbmZvLmZpZWxkTmFtZV07XG4gICAgICAgICAgdGhpcy5oYW5kbGVGaWVsZHMobmV3TG9jYWxTY2hlbWEsIGZpZWxkSW5mby5maWVsZE5hbWUsIGZpZWxkKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSBlbHNlIGlmICh0aGlzLnNjaGVtYU9wdGlvbnMuc3RyaWN0ID09PSB0cnVlICYmIGZpZWxkc1RvUmVjcmVhdGUubGVuZ3RoKSB7XG4gICAgICBmaWVsZHNUb1JlY3JlYXRlLmZvckVhY2goZmllbGQgPT4ge1xuICAgICAgICBjb25zdCBmcm9tID1cbiAgICAgICAgICBmaWVsZC5mcm9tLnR5cGUgKyAoZmllbGQuZnJvbS50YXJnZXRDbGFzcyA/IGAgKCR7ZmllbGQuZnJvbS50YXJnZXRDbGFzc30pYCA6ICcnKTtcbiAgICAgICAgY29uc3QgdG8gPSBmaWVsZC50by50eXBlICsgKGZpZWxkLnRvLnRhcmdldENsYXNzID8gYCAoJHtmaWVsZC50by50YXJnZXRDbGFzc30pYCA6ICcnKTtcblxuICAgICAgICBsb2dnZXIud2FybihcbiAgICAgICAgICBgVGhlIGZpZWxkIFwiJHtmaWVsZC5maWVsZE5hbWV9XCIgdHlwZSBkaWZmZXIgYmV0d2VlbiB0aGUgc2NoZW1hIGFuZCB0aGUgZGF0YWJhc2UgZm9yIFwiJHtsb2NhbFNjaGVtYS5jbGFzc05hbWV9XCI7IFNjaGVtYSBpcyBkZWZpbmVkIGFzIFwiJHt0b31cIiBhbmQgY3VycmVudCBkYXRhYmFzZSB0eXBlIGlzIFwiJHtmcm9tfVwiYFxuICAgICAgICApO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgZmllbGRzV2l0aENoYW5nZWRQYXJhbXMuZm9yRWFjaChmaWVsZE5hbWUgPT4ge1xuICAgICAgaWYgKGxvY2FsU2NoZW1hLmZpZWxkcykge1xuICAgICAgICBjb25zdCBmaWVsZCA9IGxvY2FsU2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdO1xuICAgICAgICB0aGlzLmhhbmRsZUZpZWxkcyhuZXdMb2NhbFNjaGVtYSwgZmllbGROYW1lLCBmaWVsZCk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyBIYW5kbGUgSW5kZXhlc1xuICAgIC8vIENoZWNrIGFkZGl0aW9uXG4gICAgaWYgKGxvY2FsU2NoZW1hLmluZGV4ZXMpIHtcbiAgICAgIE9iamVjdC5rZXlzKGxvY2FsU2NoZW1hLmluZGV4ZXMpLmZvckVhY2goaW5kZXhOYW1lID0+IHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgICghY2xvdWRTY2hlbWEuaW5kZXhlcyB8fCAhY2xvdWRTY2hlbWEuaW5kZXhlc1tpbmRleE5hbWVdKSAmJlxuICAgICAgICAgICF0aGlzLmlzUHJvdGVjdGVkSW5kZXgobG9jYWxTY2hlbWEuY2xhc3NOYW1lLCBpbmRleE5hbWUpXG4gICAgICAgICkge1xuICAgICAgICAgIGlmIChsb2NhbFNjaGVtYS5pbmRleGVzKSB7XG4gICAgICAgICAgICBuZXdMb2NhbFNjaGVtYS5hZGRJbmRleChpbmRleE5hbWUsIGxvY2FsU2NoZW1hLmluZGV4ZXNbaW5kZXhOYW1lXSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBjb25zdCBpbmRleGVzVG9BZGQgPSBbXTtcblxuICAgIC8vIENoZWNrIGRlbGV0aW9uXG4gICAgaWYgKGNsb3VkU2NoZW1hLmluZGV4ZXMpIHtcbiAgICAgIE9iamVjdC5rZXlzKGNsb3VkU2NoZW1hLmluZGV4ZXMpLmZvckVhY2goaW5kZXhOYW1lID0+IHtcbiAgICAgICAgaWYgKCF0aGlzLmlzUHJvdGVjdGVkSW5kZXgobG9jYWxTY2hlbWEuY2xhc3NOYW1lLCBpbmRleE5hbWUpKSB7XG4gICAgICAgICAgaWYgKCFsb2NhbFNjaGVtYS5pbmRleGVzIHx8ICFsb2NhbFNjaGVtYS5pbmRleGVzW2luZGV4TmFtZV0pIHtcbiAgICAgICAgICAgIC8vIElmIGtlZXBVbmtub3duSW5kZXggaXMgZmFsc3ksIHRoZW4gZGVsZXRlIGFsbCB1bmtub3duIGluZGV4ZXMgZnJvbSB0aGUgZGIuXG4gICAgICAgICAgICBpZighdGhpcy5zY2hlbWFPcHRpb25zLmtlZXBVbmtub3duSW5kZXhlcyl7XG4gICAgICAgICAgICAgIG5ld0xvY2FsU2NoZW1hLmRlbGV0ZUluZGV4KGluZGV4TmFtZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICAgICF0aGlzLnBhcmFtc0FyZUVxdWFscyhsb2NhbFNjaGVtYS5pbmRleGVzW2luZGV4TmFtZV0sIGNsb3VkU2NoZW1hLmluZGV4ZXNbaW5kZXhOYW1lXSlcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIG5ld0xvY2FsU2NoZW1hLmRlbGV0ZUluZGV4KGluZGV4TmFtZSk7XG4gICAgICAgICAgICBpZiAobG9jYWxTY2hlbWEuaW5kZXhlcykge1xuICAgICAgICAgICAgICBpbmRleGVzVG9BZGQucHVzaCh7XG4gICAgICAgICAgICAgICAgaW5kZXhOYW1lLFxuICAgICAgICAgICAgICAgIGluZGV4OiBsb2NhbFNjaGVtYS5pbmRleGVzW2luZGV4TmFtZV0sXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgdGhpcy5oYW5kbGVDTFAobG9jYWxTY2hlbWEsIG5ld0xvY2FsU2NoZW1hLCBjbG91ZFNjaGVtYSk7XG4gICAgLy8gQXBwbHkgY2hhbmdlc1xuICAgIGF3YWl0IHRoaXMudXBkYXRlU2NoZW1hVG9EQihuZXdMb2NhbFNjaGVtYSk7XG4gICAgLy8gQXBwbHkgbmV3L2NoYW5nZWQgaW5kZXhlc1xuICAgIGlmIChpbmRleGVzVG9BZGQubGVuZ3RoKSB7XG4gICAgICBsb2dnZXIuZGVidWcoXG4gICAgICAgIGBVcGRhdGluZyBpbmRleGVzIGZvciBcIiR7bmV3TG9jYWxTY2hlbWEuY2xhc3NOYW1lfVwiIDogICR7aW5kZXhlc1RvQWRkLmpvaW4oJyAsJyl9YFxuICAgICAgKTtcbiAgICAgIGluZGV4ZXNUb0FkZC5mb3JFYWNoKG8gPT4gbmV3TG9jYWxTY2hlbWEuYWRkSW5kZXgoby5pbmRleE5hbWUsIG8uaW5kZXgpKTtcbiAgICAgIGF3YWl0IHRoaXMudXBkYXRlU2NoZW1hVG9EQihuZXdMb2NhbFNjaGVtYSk7XG4gICAgfVxuICB9XG5cbiAgaGFuZGxlQ0xQKFxuICAgIGxvY2FsU2NoZW1hOiBNaWdyYXRpb25zLkpTT05TY2hlbWEsXG4gICAgbmV3TG9jYWxTY2hlbWE6IFBhcnNlLlNjaGVtYSxcbiAgICBjbG91ZFNjaGVtYTogUGFyc2UuU2NoZW1hXG4gICkge1xuICAgIGlmICghbG9jYWxTY2hlbWEuY2xhc3NMZXZlbFBlcm1pc3Npb25zICYmICFjbG91ZFNjaGVtYSkge1xuICAgICAgbG9nZ2VyLndhcm4oYGNsYXNzTGV2ZWxQZXJtaXNzaW9ucyBub3QgcHJvdmlkZWQgZm9yICR7bG9jYWxTY2hlbWEuY2xhc3NOYW1lfS5gKTtcbiAgICB9XG4gICAgLy8gVXNlIHNwcmVhZCB0byBhdm9pZCByZWFkIG9ubHkgaXNzdWUgKGVuY291bnRlcmVkIGJ5IE1vdW1vdWxzIHVzaW5nIGRpcmVjdEFjY2VzcylcbiAgICBjb25zdCBjbHAgPSAoeyAuLi5sb2NhbFNjaGVtYS5jbGFzc0xldmVsUGVybWlzc2lvbnMgfHwge30gfTogUGFyc2UuQ0xQLlBlcm1pc3Npb25zTWFwKTtcbiAgICAvLyBUbyBhdm9pZCBpbmNvbnNpc3RlbmN5IHdlIG5lZWQgdG8gcmVtb3ZlIGFsbCByaWdodHMgb24gYWRkRmllbGRcbiAgICBjbHAuYWRkRmllbGQgPSB7fTtcbiAgICBuZXdMb2NhbFNjaGVtYS5zZXRDTFAoY2xwKTtcbiAgfVxuXG4gIGlzUHJvdGVjdGVkRmllbGRzKGNsYXNzTmFtZTogc3RyaW5nLCBmaWVsZE5hbWU6IHN0cmluZykge1xuICAgIHJldHVybiAoXG4gICAgICAhIWRlZmF1bHRDb2x1bW5zLl9EZWZhdWx0W2ZpZWxkTmFtZV0gfHxcbiAgICAgICEhKGRlZmF1bHRDb2x1bW5zW2NsYXNzTmFtZV0gJiYgZGVmYXVsdENvbHVtbnNbY2xhc3NOYW1lXVtmaWVsZE5hbWVdKVxuICAgICk7XG4gIH1cblxuICBpc1Byb3RlY3RlZEluZGV4KGNsYXNzTmFtZTogc3RyaW5nLCBpbmRleE5hbWU6IHN0cmluZykge1xuICAgIGNvbnN0IGluZGV4ZXMgPSBbJ19pZF8nXTtcbiAgICBzd2l0Y2ggKGNsYXNzTmFtZSkge1xuICAgICAgY2FzZSAnX1VzZXInOlxuICAgICAgICBpbmRleGVzLnB1c2goXG4gICAgICAgICAgJ2Nhc2VfaW5zZW5zaXRpdmVfdXNlcm5hbWUnLFxuICAgICAgICAgICdjYXNlX2luc2Vuc2l0aXZlX2VtYWlsJyxcbiAgICAgICAgICAndXNlcm5hbWVfMScsXG4gICAgICAgICAgJ2VtYWlsXzEnXG4gICAgICAgICk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnX1JvbGUnOlxuICAgICAgICBpbmRleGVzLnB1c2goJ25hbWVfMScpO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSAnX0lkZW1wb3RlbmN5JzpcbiAgICAgICAgaW5kZXhlcy5wdXNoKCdyZXFJZF8xJyk7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cblxuICAgIHJldHVybiBpbmRleGVzLmluZGV4T2YoaW5kZXhOYW1lKSAhPT0gLTE7XG4gIH1cblxuICBwYXJhbXNBcmVFcXVhbHM8VDogeyBba2V5OiBzdHJpbmddOiBhbnkgfT4ob2JqQTogVCwgb2JqQjogVCkge1xuICAgIGNvbnN0IGtleXNBOiBzdHJpbmdbXSA9IE9iamVjdC5rZXlzKG9iakEpO1xuICAgIGNvbnN0IGtleXNCOiBzdHJpbmdbXSA9IE9iamVjdC5rZXlzKG9iakIpO1xuXG4gICAgLy8gQ2hlY2sga2V5IG5hbWVcbiAgICBpZiAoa2V5c0EubGVuZ3RoICE9PSBrZXlzQi5sZW5ndGgpIHsgcmV0dXJuIGZhbHNlOyB9XG4gICAgcmV0dXJuIGtleXNBLmV2ZXJ5KGsgPT4gb2JqQVtrXSA9PT0gb2JqQltrXSk7XG4gIH1cblxuICBoYW5kbGVGaWVsZHMobmV3TG9jYWxTY2hlbWE6IFBhcnNlLlNjaGVtYSwgZmllbGROYW1lOiBzdHJpbmcsIGZpZWxkOiBNaWdyYXRpb25zLkZpZWxkVHlwZSkge1xuICAgIGlmIChmaWVsZC50eXBlID09PSAnUmVsYXRpb24nKSB7XG4gICAgICBuZXdMb2NhbFNjaGVtYS5hZGRSZWxhdGlvbihmaWVsZE5hbWUsIGZpZWxkLnRhcmdldENsYXNzKTtcbiAgICB9IGVsc2UgaWYgKGZpZWxkLnR5cGUgPT09ICdQb2ludGVyJykge1xuICAgICAgbmV3TG9jYWxTY2hlbWEuYWRkUG9pbnRlcihmaWVsZE5hbWUsIGZpZWxkLnRhcmdldENsYXNzLCBmaWVsZCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld0xvY2FsU2NoZW1hLmFkZEZpZWxkKGZpZWxkTmFtZSwgZmllbGQudHlwZSwgZmllbGQpO1xuICAgIH1cbiAgfVxufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7QUFHQSxJQUFBQSxPQUFBLEdBQUFDLE9BQUE7QUFDQSxJQUFBQyxPQUFBLEdBQUFDLHNCQUFBLENBQUFGLE9BQUE7QUFDQSxJQUFBRyxjQUFBLEdBQUFILE9BQUE7QUFDQSxJQUFBSSxpQkFBQSxHQUFBSixPQUFBO0FBQ0EsSUFBQUssUUFBQSxHQUFBTCxPQUFBO0FBQ0EsSUFBQU0sVUFBQSxHQUFBQyx1QkFBQSxDQUFBUCxPQUFBO0FBQ0EsSUFBQVEsS0FBQSxHQUFBTixzQkFBQSxDQUFBRixPQUFBO0FBQ0EsSUFBQVMsS0FBQSxHQUFBUCxzQkFBQSxDQUFBRixPQUFBO0FBQTJCLFNB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
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.CLP = void 0;
7
+ exports.makeSchema = makeSchema;
8
+ // @Typescript 4.1+ // type CLPPermission = 'requiresAuthentication' | '*' | `user:${string}` | `role:${string}`
9
+ class CLP {
10
+ static allow(perms) {
11
+ const out = {};
12
+ for (const [perm, ops] of Object.entries(perms)) {
13
+ // -disable-next Property `@@iterator` is missing in mixed [1] but exists in `$Iterable` [2].
14
+ for (const op of ops) {
15
+ out[op] = out[op] || {};
16
+ out[op][perm] = true;
17
+ }
18
+ }
19
+ return out;
20
+ }
21
+ }
22
+ exports.CLP = CLP;
23
+ function makeSchema(className, schema) {
24
+ // This function solve two things:
25
+ // 1. It provides auto-completion to the users who are implementing schemas
26
+ // 2. It allows forward-compatible point in order to allow future changes to the internal structure of JSONSchema without affecting all the users
27
+ schema.className = className;
28
+ return schema;
29
+ }
30
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJDTFAiLCJhbGxvdyIsInBlcm1zIiwib3V0IiwicGVybSIsIm9wcyIsIk9iamVjdCIsImVudHJpZXMiLCJvcCIsImV4cG9ydHMiLCJtYWtlU2NoZW1hIiwiY2xhc3NOYW1lIiwic2NoZW1hIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL1NjaGVtYU1pZ3JhdGlvbnMvTWlncmF0aW9ucy5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAZmxvd1xuXG5leHBvcnQgaW50ZXJmYWNlIFNjaGVtYU9wdGlvbnMge1xuICBkZWZpbml0aW9uczogSlNPTlNjaGVtYVtdO1xuICBzdHJpY3Q6ID9ib29sZWFuO1xuICBkZWxldGVFeHRyYUZpZWxkczogP2Jvb2xlYW47XG4gIHJlY3JlYXRlTW9kaWZpZWRGaWVsZHM6ID9ib29sZWFuO1xuICBsb2NrU2NoZW1hczogP2Jvb2xlYW47XG4gIGtlZXBVbmtub3duSW5kZXhlczogP2Jvb2xlYW47XG4gIGJlZm9yZU1pZ3JhdGlvbjogPygpID0+IHZvaWQgfCBQcm9taXNlPHZvaWQ+O1xuICBhZnRlck1pZ3JhdGlvbjogPygpID0+IHZvaWQgfCBQcm9taXNlPHZvaWQ+O1xufVxuXG5leHBvcnQgdHlwZSBGaWVsZFZhbHVlVHlwZSA9XG4gIHwgJ1N0cmluZydcbiAgfCAnQm9vbGVhbidcbiAgfCAnRmlsZSdcbiAgfCAnTnVtYmVyJ1xuICB8ICdSZWxhdGlvbidcbiAgfCAnUG9pbnRlcidcbiAgfCAnRGF0ZSdcbiAgfCAnR2VvUG9pbnQnXG4gIHwgJ1BvbHlnb24nXG4gIHwgJ0FycmF5J1xuICB8ICdPYmplY3QnXG4gIHwgJ0FDTCc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgRmllbGRUeXBlIHtcbiAgdHlwZTogRmllbGRWYWx1ZVR5cGU7XG4gIHJlcXVpcmVkPzogYm9vbGVhbjtcbiAgZGVmYXVsdFZhbHVlPzogbWl4ZWQ7XG4gIHRhcmdldENsYXNzPzogc3RyaW5nO1xufVxuXG50eXBlIENsYXNzTmFtZVR5cGUgPSAnX1VzZXInIHwgJ19Sb2xlJyB8IHN0cmluZztcblxuZXhwb3J0IGludGVyZmFjZSBQcm90ZWN0ZWRGaWVsZHNJbnRlcmZhY2Uge1xuICBba2V5OiBzdHJpbmddOiBzdHJpbmdbXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJbmRleEludGVyZmFjZSB7XG4gIFtrZXk6IHN0cmluZ106IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJbmRleGVzSW50ZXJmYWNlIHtcbiAgW2tleTogc3RyaW5nXTogSW5kZXhJbnRlcmZhY2U7XG59XG5cbmV4cG9ydCB0eXBlIENMUE9wZXJhdGlvbiA9ICdmaW5kJyB8ICdjb3VudCcgfCAnZ2V0JyB8ICd1cGRhdGUnIHwgJ2NyZWF0ZScgfCAnZGVsZXRlJztcbi8vIEBUeXBlc2NyaXB0IDQuMSsgLy8gdHlwZSBDTFBQZXJtaXNzaW9uID0gJ3JlcXVpcmVzQXV0aGVudGljYXRpb24nIHwgJyonIHwgIGB1c2VyOiR7c3RyaW5nfWAgfCBgcm9sZToke3N0cmluZ31gXG5cbnR5cGUgQ0xQVmFsdWUgPSB7IFtrZXk6IHN0cmluZ106IGJvb2xlYW4gfTtcbnR5cGUgQ0xQRGF0YSA9IHsgW2tleTogc3RyaW5nXTogQ0xQT3BlcmF0aW9uW10gfTtcbnR5cGUgQ0xQSW50ZXJmYWNlID0geyBba2V5OiBzdHJpbmddOiBDTFBWYWx1ZSB9O1xuXG5leHBvcnQgaW50ZXJmYWNlIEpTT05TY2hlbWEge1xuICBjbGFzc05hbWU6IENsYXNzTmFtZVR5cGU7XG4gIGZpZWxkcz86IHsgW2tleTogc3RyaW5nXTogRmllbGRUeXBlIH07XG4gIGluZGV4ZXM/OiBJbmRleGVzSW50ZXJmYWNlO1xuICBjbGFzc0xldmVsUGVybWlzc2lvbnM/OiB7XG4gICAgZmluZD86IENMUFZhbHVlLFxuICAgIGNvdW50PzogQ0xQVmFsdWUsXG4gICAgZ2V0PzogQ0xQVmFsdWUsXG4gICAgdXBkYXRlPzogQ0xQVmFsdWUsXG4gICAgY3JlYXRlPzogQ0xQVmFsdWUsXG4gICAgZGVsZXRlPzogQ0xQVmFsdWUsXG4gICAgYWRkRmllbGQ/OiBDTFBWYWx1ZSxcbiAgICBwcm90ZWN0ZWRGaWVsZHM/OiBQcm90ZWN0ZWRGaWVsZHNJbnRlcmZhY2UsXG4gIH07XG59XG5cbmV4cG9ydCBjbGFzcyBDTFAge1xuICBzdGF0aWMgYWxsb3cocGVybXM6IHsgW2tleTogc3RyaW5nXTogQ0xQRGF0YSB9KTogQ0xQSW50ZXJmYWNlIHtcbiAgICBjb25zdCBvdXQgPSB7fTtcblxuICAgIGZvciAoY29uc3QgW3Blcm0sIG9wc10gb2YgT2JqZWN0LmVudHJpZXMocGVybXMpKSB7XG4gICAgICAvLyBAZmxvdy1kaXNhYmxlLW5leHQgUHJvcGVydHkgYEBAaXRlcmF0b3JgIGlzIG1pc3NpbmcgaW4gbWl4ZWQgWzFdIGJ1dCBleGlzdHMgaW4gYCRJdGVyYWJsZWAgWzJdLlxuICAgICAgZm9yIChjb25zdCBvcCBvZiBvcHMpIHtcbiAgICAgICAgb3V0W29wXSA9IG91dFtvcF0gfHwge307XG4gICAgICAgIG91dFtvcF1bcGVybV0gPSB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBvdXQ7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG1ha2VTY2hlbWEoY2xhc3NOYW1lOiBDbGFzc05hbWVUeXBlLCBzY2hlbWE6IEpTT05TY2hlbWEpOiBKU09OU2NoZW1hIHtcbiAgLy8gVGhpcyBmdW5jdGlvbiBzb2x2ZSB0d28gdGhpbmdzOlxuICAvLyAxLiBJdCBwcm92aWRlcyBhdXRvLWNvbXBsZXRpb24gdG8gdGhlIHVzZXJzIHdobyBhcmUgaW1wbGVtZW50aW5nIHNjaGVtYXNcbiAgLy8gMi4gSXQgYWxsb3dzIGZvcndhcmQtY29tcGF0aWJsZSBwb2ludCBpbiBvcmRlciB0byBhbGxvdyBmdXR1cmUgY2hhbmdlcyB0byB0aGUgaW50ZXJuYWwgc3RydWN0dXJlIG9mIEpTT05TY2hlbWEgd2l0aG91dCBhZmZlY3RpbmcgYWxsIHRoZSB1c2Vyc1xuICBzY2hlbWEuY2xhc3NOYW1lID0gY2xhc3NOYW1lO1xuXG4gIHJldHVybiBzY2hlbWE7XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFpREE7QUFzQk8sTUFBTUEsR0FBRyxDQUFDO0VBQ2YsT0FBT0MsS0FBS0EsQ0FBQ0MsS0FBaUMsRUFBZ0I7SUFDNUQsTUFBTUMsR0FBRyxHQUFHLENBQUMsQ0FBQztJQUVkLEtBQUssTUFBTSxDQUFDQyxJQUFJLEVBQUVDLEdBQUcsQ0FBQyxJQUFJQyxNQUFNLENBQUNDLE9BQU8sQ0FBQ0wsS0FBSyxDQUFDLEVBQUU7TUFDL0M7TUFDQSxLQUFLLE1BQU1NLEVBQUUsSUFBSUgsR0FBRyxFQUFFO1FBQ3BCRixHQUFHLENBQUNLLEVBQUUsQ0FBQyxHQUFHTCxHQUFHLENBQUNLLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN2QkwsR0FBRyxDQUFDSyxFQUFFLENBQUMsQ0FBQ0osSUFBSSxDQUFDLEdBQUcsSUFBSTtNQUN0QjtJQUNGO0lBRUEsT0FBT0QsR0FBRztFQUNaO0FBQ0Y7QUFBQ00sT0FBQSxDQUFBVCxHQUFBLEdBQUFBLEdBQUE7QUFFTSxTQUFTVSxVQUFVQSxDQUFDQyxTQUF3QixFQUFFQyxNQUFrQixFQUFjO0VBQ25GO0VBQ0E7RUFDQTtFQUNBQSxNQUFNLENBQUNELFNBQVMsR0FBR0EsU0FBUztFQUU1QixPQUFPQyxNQUFNO0FBQ2YiLCJpZ25vcmVMaXN0IjpbXX0=
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _Utils = _interopRequireDefault(require("../Utils"));
8
+ var _lodash = require("lodash");
9
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
10
+ /**
11
+ * @module SecurityCheck
12
+ */
13
+
14
+ /**
15
+ * A security check.
16
+ * @class
17
+ */
18
+ class Check {
19
+ /**
20
+ * Constructs a new security check.
21
+ * @param {Object} params The parameters.
22
+ * @param {String} params.title The title.
23
+ * @param {String} params.warning The warning message if the check fails.
24
+ * @param {String} params.solution The solution to fix the check.
25
+ * @param {Promise} params.check The check as synchronous or asynchronous function.
26
+ */
27
+ constructor(params) {
28
+ this._validateParams(params);
29
+ const {
30
+ title,
31
+ warning,
32
+ solution,
33
+ check
34
+ } = params;
35
+ this.title = title;
36
+ this.warning = warning;
37
+ this.solution = solution;
38
+ this.check = check;
39
+
40
+ // Set default properties
41
+ this._checkState = CheckState.none;
42
+ this.error;
43
+ }
44
+
45
+ /**
46
+ * Returns the current check state.
47
+ * @return {CheckState} The check state.
48
+ */
49
+ checkState() {
50
+ return this._checkState;
51
+ }
52
+ async run() {
53
+ // Get check as synchronous or asynchronous function
54
+ const check = this.check instanceof Promise ? await this.check : this.check;
55
+
56
+ // Run check
57
+ try {
58
+ check();
59
+ this._checkState = CheckState.success;
60
+ } catch (e) {
61
+ this.stateFailError = e;
62
+ this._checkState = CheckState.fail;
63
+ }
64
+ }
65
+
66
+ /**
67
+ * Validates the constructor parameters.
68
+ * @param {Object} params The parameters to validate.
69
+ */
70
+ _validateParams(params) {
71
+ _Utils.default.validateParams(params, {
72
+ group: {
73
+ t: 'string',
74
+ v: _lodash.isString
75
+ },
76
+ title: {
77
+ t: 'string',
78
+ v: _lodash.isString
79
+ },
80
+ warning: {
81
+ t: 'string',
82
+ v: _lodash.isString
83
+ },
84
+ solution: {
85
+ t: 'string',
86
+ v: _lodash.isString
87
+ },
88
+ check: {
89
+ t: 'function',
90
+ v: _lodash.isFunction
91
+ }
92
+ });
93
+ }
94
+ }
95
+
96
+ /**
97
+ * The check state.
98
+ */
99
+ const CheckState = Object.freeze({
100
+ none: 'none',
101
+ fail: 'fail',
102
+ success: 'success'
103
+ });
104
+ var _default = exports.default = Check;
105
+ module.exports = {
106
+ Check,
107
+ CheckState
108
+ };
109
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfVXRpbHMiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsIl9sb2Rhc2giLCJlIiwiX19lc01vZHVsZSIsImRlZmF1bHQiLCJDaGVjayIsImNvbnN0cnVjdG9yIiwicGFyYW1zIiwiX3ZhbGlkYXRlUGFyYW1zIiwidGl0bGUiLCJ3YXJuaW5nIiwic29sdXRpb24iLCJjaGVjayIsIl9jaGVja1N0YXRlIiwiQ2hlY2tTdGF0ZSIsIm5vbmUiLCJlcnJvciIsImNoZWNrU3RhdGUiLCJydW4iLCJQcm9taXNlIiwic3VjY2VzcyIsInN0YXRlRmFpbEVycm9yIiwiZmFpbCIsIlV0aWxzIiwidmFsaWRhdGVQYXJhbXMiLCJncm91cCIsInQiLCJ2IiwiaXNTdHJpbmciLCJpc0Z1bmN0aW9uIiwiT2JqZWN0IiwiZnJlZXplIiwiX2RlZmF1bHQiLCJleHBvcnRzIiwibW9kdWxlIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL1NlY3VyaXR5L0NoZWNrLmpzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQG1vZHVsZSBTZWN1cml0eUNoZWNrXG4gKi9cblxuaW1wb3J0IFV0aWxzIGZyb20gJy4uL1V0aWxzJztcbmltcG9ydCB7IGlzRnVuY3Rpb24sIGlzU3RyaW5nIH0gZnJvbSAnbG9kYXNoJztcblxuLyoqXG4gKiBBIHNlY3VyaXR5IGNoZWNrLlxuICogQGNsYXNzXG4gKi9cbmNsYXNzIENoZWNrIHtcbiAgLyoqXG4gICAqIENvbnN0cnVjdHMgYSBuZXcgc2VjdXJpdHkgY2hlY2suXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBwYXJhbXMgVGhlIHBhcmFtZXRlcnMuXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBwYXJhbXMudGl0bGUgVGhlIHRpdGxlLlxuICAgKiBAcGFyYW0ge1N0cmluZ30gcGFyYW1zLndhcm5pbmcgVGhlIHdhcm5pbmcgbWVzc2FnZSBpZiB0aGUgY2hlY2sgZmFpbHMuXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBwYXJhbXMuc29sdXRpb24gVGhlIHNvbHV0aW9uIHRvIGZpeCB0aGUgY2hlY2suXG4gICAqIEBwYXJhbSB7UHJvbWlzZX0gcGFyYW1zLmNoZWNrIFRoZSBjaGVjayBhcyBzeW5jaHJvbm91cyBvciBhc3luY2hyb25vdXMgZnVuY3Rpb24uXG4gICAqL1xuICBjb25zdHJ1Y3RvcihwYXJhbXMpIHtcbiAgICB0aGlzLl92YWxpZGF0ZVBhcmFtcyhwYXJhbXMpO1xuICAgIGNvbnN0IHsgdGl0bGUsIHdhcm5pbmcsIHNvbHV0aW9uLCBjaGVjayB9ID0gcGFyYW1zO1xuXG4gICAgdGhpcy50aXRsZSA9IHRpdGxlO1xuICAgIHRoaXMud2FybmluZyA9IHdhcm5pbmc7XG4gICAgdGhpcy5zb2x1dGlvbiA9IHNvbHV0aW9uO1xuICAgIHRoaXMuY2hlY2sgPSBjaGVjaztcblxuICAgIC8vIFNldCBkZWZhdWx0IHByb3BlcnRpZXNcbiAgICB0aGlzLl9jaGVja1N0YXRlID0gQ2hlY2tTdGF0ZS5ub25lO1xuICAgIHRoaXMuZXJyb3I7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgY3VycmVudCBjaGVjayBzdGF0ZS5cbiAgICogQHJldHVybiB7Q2hlY2tTdGF0ZX0gVGhlIGNoZWNrIHN0YXRlLlxuICAgKi9cbiAgY2hlY2tTdGF0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fY2hlY2tTdGF0ZTtcbiAgfVxuXG4gIGFzeW5jIHJ1bigpIHtcbiAgICAvLyBHZXQgY2hlY2sgYXMgc3luY2hyb25vdXMgb3IgYXN5bmNocm9ub3VzIGZ1bmN0aW9uXG4gICAgY29uc3QgY2hlY2sgPSB0aGlzLmNoZWNrIGluc3RhbmNlb2YgUHJvbWlzZSA/IGF3YWl0IHRoaXMuY2hlY2sgOiB0aGlzLmNoZWNrO1xuXG4gICAgLy8gUnVuIGNoZWNrXG4gICAgdHJ5IHtcbiAgICAgIGNoZWNrKCk7XG4gICAgICB0aGlzLl9jaGVja1N0YXRlID0gQ2hlY2tTdGF0ZS5zdWNjZXNzO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHRoaXMuc3RhdGVGYWlsRXJyb3IgPSBlO1xuICAgICAgdGhpcy5fY2hlY2tTdGF0ZSA9IENoZWNrU3RhdGUuZmFpbDtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGVzIHRoZSBjb25zdHJ1Y3RvciBwYXJhbWV0ZXJzLlxuICAgKiBAcGFyYW0ge09iamVjdH0gcGFyYW1zIFRoZSBwYXJhbWV0ZXJzIHRvIHZhbGlkYXRlLlxuICAgKi9cbiAgX3ZhbGlkYXRlUGFyYW1zKHBhcmFtcykge1xuICAgIFV0aWxzLnZhbGlkYXRlUGFyYW1zKHBhcmFtcywge1xuICAgICAgZ3JvdXA6IHsgdDogJ3N0cmluZycsIHY6IGlzU3RyaW5nIH0sXG4gICAgICB0aXRsZTogeyB0OiAnc3RyaW5nJywgdjogaXNTdHJpbmcgfSxcbiAgICAgIHdhcm5pbmc6IHsgdDogJ3N0cmluZycsIHY6IGlzU3RyaW5nIH0sXG4gICAgICBzb2x1dGlvbjogeyB0OiAnc3RyaW5nJywgdjogaXNTdHJpbmcgfSxcbiAgICAgIGNoZWNrOiB7IHQ6ICdmdW5jdGlvbicsIHY6IGlzRnVuY3Rpb24gfSxcbiAgICB9KTtcbiAgfVxufVxuXG4vKipcbiAqIFRoZSBjaGVjayBzdGF0ZS5cbiAqL1xuY29uc3QgQ2hlY2tTdGF0ZSA9IE9iamVjdC5mcmVlemUoe1xuICBub25lOiAnbm9uZScsXG4gIGZhaWw6ICdmYWlsJyxcbiAgc3VjY2VzczogJ3N1Y2Nlc3MnLFxufSk7XG5cbmV4cG9ydCBkZWZhdWx0IENoZWNrO1xubW9kdWxlLmV4cG9ydHMgPSB7XG4gIENoZWNrLFxuICBDaGVja1N0YXRlLFxufTtcbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBSUEsSUFBQUEsTUFBQSxHQUFBQyxzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUMsT0FBQSxHQUFBRCxPQUFBO0FBQThDLFNBQUFELHVCQUFBRyxDQUFBLFdBQUFBLENBQUEsSUFBQUEsQ0FBQSxDQUFBQyxVQUFBLEdBQUFELENBQUEsS0FBQUUsT0FBQSxFQUFBRixDQUFBO0FBTDlDO0FBQ0E7QUFDQTs7QUFLQTtBQUNBO0FBQ0E7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