@decaf-ts/for-fabric 0.0.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 (205) hide show
  1. package/LICENSE.md +22 -0
  2. package/README.md +647 -0
  3. package/dist/for-fabric.cjs +6223 -0
  4. package/dist/for-fabric.esm.cjs +6180 -0
  5. package/lib/client/FabricClientAdapter.cjs +760 -0
  6. package/lib/client/FabricClientAdapter.d.ts +381 -0
  7. package/lib/client/FabricClientDispatch.cjs +186 -0
  8. package/lib/client/FabricClientDispatch.d.ts +125 -0
  9. package/lib/client/FabricClientRepository.cjs +131 -0
  10. package/lib/client/FabricClientRepository.d.ts +100 -0
  11. package/lib/client/erc20/erc20ClientRepository.cjs +343 -0
  12. package/lib/client/erc20/erc20ClientRepository.d.ts +254 -0
  13. package/lib/client/fabric-fs.cjs +234 -0
  14. package/lib/client/fabric-fs.d.ts +92 -0
  15. package/lib/client/index.cjs +30 -0
  16. package/lib/client/index.d.ts +13 -0
  17. package/lib/client/logging.cjs +102 -0
  18. package/lib/client/logging.d.ts +60 -0
  19. package/lib/client/services/LoggedService.cjs +47 -0
  20. package/lib/client/services/LoggedService.d.ts +42 -0
  21. package/lib/client/services/constants.cjs +3 -0
  22. package/lib/client/services/constants.d.ts +15 -0
  23. package/lib/client/services/enrollementService.cjs +344 -0
  24. package/lib/client/services/enrollementService.d.ts +176 -0
  25. package/lib/client/services/index.cjs +18 -0
  26. package/lib/client/services/index.d.ts +1 -0
  27. package/lib/contracts/ContractAdapter.cjs +730 -0
  28. package/lib/contracts/ContractAdapter.d.ts +296 -0
  29. package/lib/contracts/ContractContext.cjs +85 -0
  30. package/lib/contracts/ContractContext.d.ts +64 -0
  31. package/lib/contracts/ContractPrivateDataAdapter.cjs +281 -0
  32. package/lib/contracts/ContractPrivateDataAdapter.d.ts +74 -0
  33. package/lib/contracts/FabricConstruction.cjs +441 -0
  34. package/lib/contracts/FabricConstruction.d.ts +304 -0
  35. package/lib/contracts/FabricContractRepository.cjs +306 -0
  36. package/lib/contracts/FabricContractRepository.d.ts +162 -0
  37. package/lib/contracts/FabricContractRepositoryObservableHandler.cjs +85 -0
  38. package/lib/contracts/FabricContractRepositoryObservableHandler.d.ts +62 -0
  39. package/lib/contracts/FabricContractSequence.cjs +139 -0
  40. package/lib/contracts/FabricContractSequence.d.ts +61 -0
  41. package/lib/contracts/FabricContractStatement.cjs +119 -0
  42. package/lib/contracts/FabricContractStatement.d.ts +34 -0
  43. package/lib/contracts/PrivateSequence.cjs +36 -0
  44. package/lib/contracts/PrivateSequence.d.ts +15 -0
  45. package/lib/contracts/crud/crud-contract.cjs +257 -0
  46. package/lib/contracts/crud/crud-contract.d.ts +168 -0
  47. package/lib/contracts/crud/index.cjs +19 -0
  48. package/lib/contracts/crud/index.d.ts +2 -0
  49. package/lib/contracts/crud/serialized-crud-contract.cjs +172 -0
  50. package/lib/contracts/crud/serialized-crud-contract.d.ts +37 -0
  51. package/lib/contracts/erc20/erc20contract.cjs +569 -0
  52. package/lib/contracts/erc20/erc20contract.d.ts +151 -0
  53. package/lib/contracts/erc20/index.cjs +21 -0
  54. package/lib/contracts/erc20/index.d.ts +2 -0
  55. package/lib/contracts/erc20/models.cjs +209 -0
  56. package/lib/contracts/erc20/models.d.ts +114 -0
  57. package/lib/contracts/index.cjs +32 -0
  58. package/lib/contracts/index.d.ts +15 -0
  59. package/lib/contracts/logging.cjs +96 -0
  60. package/lib/contracts/logging.d.ts +49 -0
  61. package/lib/contracts/private-data.cjs +121 -0
  62. package/lib/contracts/private-data.d.ts +16 -0
  63. package/lib/contracts/types.cjs +3 -0
  64. package/lib/contracts/types.d.ts +26 -0
  65. package/lib/esm/client/FabricClientAdapter.d.ts +381 -0
  66. package/lib/esm/client/FabricClientAdapter.js +723 -0
  67. package/lib/esm/client/FabricClientDispatch.d.ts +125 -0
  68. package/lib/esm/client/FabricClientDispatch.js +182 -0
  69. package/lib/esm/client/FabricClientRepository.d.ts +100 -0
  70. package/lib/esm/client/FabricClientRepository.js +127 -0
  71. package/lib/esm/client/erc20/erc20ClientRepository.d.ts +254 -0
  72. package/lib/esm/client/erc20/erc20ClientRepository.js +339 -0
  73. package/lib/esm/client/fabric-fs.d.ts +92 -0
  74. package/lib/esm/client/fabric-fs.js +191 -0
  75. package/lib/esm/client/index.d.ts +13 -0
  76. package/lib/esm/client/index.js +14 -0
  77. package/lib/esm/client/logging.d.ts +60 -0
  78. package/lib/esm/client/logging.js +98 -0
  79. package/lib/esm/client/services/LoggedService.d.ts +42 -0
  80. package/lib/esm/client/services/LoggedService.js +43 -0
  81. package/lib/esm/client/services/constants.d.ts +15 -0
  82. package/lib/esm/client/services/constants.js +2 -0
  83. package/lib/esm/client/services/enrollementService.d.ts +176 -0
  84. package/lib/esm/client/services/enrollementService.js +337 -0
  85. package/lib/esm/client/services/index.d.ts +1 -0
  86. package/lib/esm/client/services/index.js +2 -0
  87. package/lib/esm/contracts/ContractAdapter.d.ts +296 -0
  88. package/lib/esm/contracts/ContractAdapter.js +724 -0
  89. package/lib/esm/contracts/ContractContext.d.ts +64 -0
  90. package/lib/esm/contracts/ContractContext.js +81 -0
  91. package/lib/esm/contracts/ContractPrivateDataAdapter.d.ts +74 -0
  92. package/lib/esm/contracts/ContractPrivateDataAdapter.js +277 -0
  93. package/lib/esm/contracts/FabricConstruction.d.ts +304 -0
  94. package/lib/esm/contracts/FabricConstruction.js +433 -0
  95. package/lib/esm/contracts/FabricContractRepository.d.ts +162 -0
  96. package/lib/esm/contracts/FabricContractRepository.js +302 -0
  97. package/lib/esm/contracts/FabricContractRepositoryObservableHandler.d.ts +62 -0
  98. package/lib/esm/contracts/FabricContractRepositoryObservableHandler.js +81 -0
  99. package/lib/esm/contracts/FabricContractSequence.d.ts +61 -0
  100. package/lib/esm/contracts/FabricContractSequence.js +135 -0
  101. package/lib/esm/contracts/FabricContractStatement.d.ts +34 -0
  102. package/lib/esm/contracts/FabricContractStatement.js +115 -0
  103. package/lib/esm/contracts/PrivateSequence.d.ts +15 -0
  104. package/lib/esm/contracts/PrivateSequence.js +33 -0
  105. package/lib/esm/contracts/crud/crud-contract.d.ts +168 -0
  106. package/lib/esm/contracts/crud/crud-contract.js +253 -0
  107. package/lib/esm/contracts/crud/index.d.ts +2 -0
  108. package/lib/esm/contracts/crud/index.js +3 -0
  109. package/lib/esm/contracts/crud/serialized-crud-contract.d.ts +37 -0
  110. package/lib/esm/contracts/crud/serialized-crud-contract.js +168 -0
  111. package/lib/esm/contracts/erc20/erc20contract.d.ts +151 -0
  112. package/lib/esm/contracts/erc20/erc20contract.js +565 -0
  113. package/lib/esm/contracts/erc20/index.d.ts +2 -0
  114. package/lib/esm/contracts/erc20/index.js +4 -0
  115. package/lib/esm/contracts/erc20/models.d.ts +114 -0
  116. package/lib/esm/contracts/erc20/models.js +206 -0
  117. package/lib/esm/contracts/index.d.ts +15 -0
  118. package/lib/esm/contracts/index.js +16 -0
  119. package/lib/esm/contracts/logging.d.ts +49 -0
  120. package/lib/esm/contracts/logging.js +92 -0
  121. package/lib/esm/contracts/private-data.d.ts +16 -0
  122. package/lib/esm/contracts/private-data.js +113 -0
  123. package/lib/esm/contracts/types.d.ts +26 -0
  124. package/lib/esm/contracts/types.js +2 -0
  125. package/lib/esm/index.d.ts +8 -0
  126. package/lib/esm/index.js +9 -0
  127. package/lib/esm/shared/ClientSerializer.d.ts +52 -0
  128. package/lib/esm/shared/ClientSerializer.js +80 -0
  129. package/lib/esm/shared/DeterministicSerializer.d.ts +40 -0
  130. package/lib/esm/shared/DeterministicSerializer.js +50 -0
  131. package/lib/esm/shared/SimpleDeterministicSerializer.d.ts +7 -0
  132. package/lib/esm/shared/SimpleDeterministicSerializer.js +42 -0
  133. package/lib/esm/shared/constants.d.ts +39 -0
  134. package/lib/esm/shared/constants.js +42 -0
  135. package/lib/esm/shared/crypto.d.ts +107 -0
  136. package/lib/esm/shared/crypto.js +331 -0
  137. package/lib/esm/shared/decorators.d.ts +24 -0
  138. package/lib/esm/shared/decorators.js +98 -0
  139. package/lib/esm/shared/erc20/erc20-constants.d.ts +25 -0
  140. package/lib/esm/shared/erc20/erc20-constants.js +27 -0
  141. package/lib/esm/shared/errors.d.ts +116 -0
  142. package/lib/esm/shared/errors.js +132 -0
  143. package/lib/esm/shared/events.d.ts +39 -0
  144. package/lib/esm/shared/events.js +47 -0
  145. package/lib/esm/shared/fabric-types.d.ts +33 -0
  146. package/lib/esm/shared/fabric-types.js +2 -0
  147. package/lib/esm/shared/index.d.ts +13 -0
  148. package/lib/esm/shared/index.js +14 -0
  149. package/lib/esm/shared/interfaces/Checkable.d.ts +21 -0
  150. package/lib/esm/shared/interfaces/Checkable.js +2 -0
  151. package/lib/esm/shared/math.d.ts +34 -0
  152. package/lib/esm/shared/math.js +61 -0
  153. package/lib/esm/shared/model/Identity.d.ts +42 -0
  154. package/lib/esm/shared/model/Identity.js +78 -0
  155. package/lib/esm/shared/model/IdentityCredentials.d.ts +41 -0
  156. package/lib/esm/shared/model/IdentityCredentials.js +74 -0
  157. package/lib/esm/shared/model/index.d.ts +1 -0
  158. package/lib/esm/shared/model/index.js +2 -0
  159. package/lib/esm/shared/model/utils.d.ts +60 -0
  160. package/lib/esm/shared/model/utils.js +108 -0
  161. package/lib/esm/shared/types.d.ts +79 -0
  162. package/lib/esm/shared/types.js +2 -0
  163. package/lib/esm/shared/utils.d.ts +55 -0
  164. package/lib/esm/shared/utils.js +148 -0
  165. package/lib/index.cjs +25 -0
  166. package/lib/index.d.ts +8 -0
  167. package/lib/shared/ClientSerializer.cjs +84 -0
  168. package/lib/shared/ClientSerializer.d.ts +52 -0
  169. package/lib/shared/DeterministicSerializer.cjs +54 -0
  170. package/lib/shared/DeterministicSerializer.d.ts +40 -0
  171. package/lib/shared/SimpleDeterministicSerializer.cjs +46 -0
  172. package/lib/shared/SimpleDeterministicSerializer.d.ts +7 -0
  173. package/lib/shared/constants.cjs +45 -0
  174. package/lib/shared/constants.d.ts +39 -0
  175. package/lib/shared/crypto.cjs +369 -0
  176. package/lib/shared/crypto.d.ts +107 -0
  177. package/lib/shared/decorators.cjs +105 -0
  178. package/lib/shared/decorators.d.ts +24 -0
  179. package/lib/shared/erc20/erc20-constants.cjs +30 -0
  180. package/lib/shared/erc20/erc20-constants.d.ts +25 -0
  181. package/lib/shared/errors.cjs +142 -0
  182. package/lib/shared/errors.d.ts +116 -0
  183. package/lib/shared/events.cjs +51 -0
  184. package/lib/shared/events.d.ts +39 -0
  185. package/lib/shared/fabric-types.cjs +4 -0
  186. package/lib/shared/fabric-types.d.ts +33 -0
  187. package/lib/shared/index.cjs +30 -0
  188. package/lib/shared/index.d.ts +13 -0
  189. package/lib/shared/interfaces/Checkable.cjs +3 -0
  190. package/lib/shared/interfaces/Checkable.d.ts +21 -0
  191. package/lib/shared/math.cjs +66 -0
  192. package/lib/shared/math.d.ts +34 -0
  193. package/lib/shared/model/Identity.cjs +81 -0
  194. package/lib/shared/model/Identity.d.ts +42 -0
  195. package/lib/shared/model/IdentityCredentials.cjs +77 -0
  196. package/lib/shared/model/IdentityCredentials.d.ts +41 -0
  197. package/lib/shared/model/index.cjs +18 -0
  198. package/lib/shared/model/index.d.ts +1 -0
  199. package/lib/shared/model/utils.cjs +114 -0
  200. package/lib/shared/model/utils.d.ts +60 -0
  201. package/lib/shared/types.cjs +3 -0
  202. package/lib/shared/types.d.ts +79 -0
  203. package/lib/shared/utils.cjs +185 -0
  204. package/lib/shared/utils.d.ts +55 -0
  205. package/package.json +166 -0
@@ -0,0 +1,441 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.oneToOneOnCreate = oneToOneOnCreate;
4
+ exports.oneToOneOnUpdate = oneToOneOnUpdate;
5
+ exports.oneToOneOnDelete = oneToOneOnDelete;
6
+ exports.oneToManyOnCreate = oneToManyOnCreate;
7
+ exports.oneToManyOnDelete = oneToManyOnDelete;
8
+ exports.populate = populate;
9
+ const core_1 = require("@decaf-ts/core");
10
+ const decorator_validation_1 = require("@decaf-ts/decorator-validation");
11
+ const db_decorators_1 = require("@decaf-ts/db-decorators");
12
+ /**
13
+ * @description Handles one-to-one relationship creation
14
+ * @summary Processes a one-to-one relationship when creating a model, either by referencing an existing model or creating a new one
15
+ * @template M - The model type extending Model
16
+ * @template R - The repository type extending Repo<M, F, C>
17
+ * @template V - The relations metadata type extending RelationsMetadata
18
+ * @template F - The repository flags type
19
+ * @template C - The context type extending Context<F>
20
+ * @param {R} this - The repository instance
21
+ * @param {Context<F>} context - The context for the operation
22
+ * @param {V} data - The relations metadata
23
+ * @param {string} key - The property key of the relationship
24
+ * @param {M} model - The model instance
25
+ * @return {Promise<void>} A promise that resolves when the operation is complete
26
+ * @function oneToOneOnCreate
27
+ * @memberOf module:core
28
+ * @mermaid
29
+ * sequenceDiagram
30
+ * participant Caller
31
+ * participant oneToOneOnCreate
32
+ * participant repositoryFromTypeMetadata
33
+ * participant Model
34
+ * participant Repository
35
+ * participant cacheModelForPopulate
36
+ *
37
+ * Caller->>oneToOneOnCreate: this, context, data, key, model
38
+ * oneToOneOnCreate->>oneToOneOnCreate: check if propertyValue exists
39
+ *
40
+ * alt propertyValue is not an object
41
+ * oneToOneOnCreate->>repositoryFromTypeMetadata: model, key
42
+ * repositoryFromTypeMetadata-->>oneToOneOnCreate: innerRepo
43
+ * oneToOneOnCreate->>innerRepo: read(propertyValue)
44
+ * innerRepo-->>oneToOneOnCreate: read
45
+ * oneToOneOnCreate->>cacheModelForPopulate: context, model, key, propertyValue, read
46
+ * oneToOneOnCreate->>oneToOneOnCreate: set model[key] = propertyValue
47
+ * else propertyValue is an object
48
+ * oneToOneOnCreate->>Model: get(data.class)
49
+ * Model-->>oneToOneOnCreate: constructor
50
+ * oneToOneOnCreate->>Repository: forModel(constructor)
51
+ * Repository-->>oneToOneOnCreate: repo
52
+ * oneToOneOnCreate->>repo: create(propertyValue)
53
+ * repo-->>oneToOneOnCreate: created
54
+ * oneToOneOnCreate->>findPrimaryKey: created
55
+ * findPrimaryKey-->>oneToOneOnCreate: pk
56
+ * oneToOneOnCreate->>cacheModelForPopulate: context, model, key, created[pk], created
57
+ * oneToOneOnCreate->>oneToOneOnCreate: set model[key] = created[pk]
58
+ * end
59
+ *
60
+ * oneToOneOnCreate-->>Caller: void
61
+ */
62
+ async function oneToOneOnCreate(context, data, key, model) {
63
+ const propertyValue = model[key];
64
+ if (!propertyValue)
65
+ return;
66
+ if (typeof propertyValue !== "object") {
67
+ const innerRepo = (0, core_1.repositoryFromTypeMetadata)(model, key, this.adapter.alias);
68
+ const read = await innerRepo.read(propertyValue, context);
69
+ await (0, core_1.cacheModelForPopulate)(context, model, key, propertyValue, read);
70
+ model[key] = propertyValue;
71
+ return;
72
+ }
73
+ data.class =
74
+ typeof data.class === "string" ? data.class : data.class().name;
75
+ const constructor = decorator_validation_1.Model.get(data.class);
76
+ if (!constructor)
77
+ throw new db_decorators_1.InternalError(`Could not find model ${data.class}`);
78
+ const repo = core_1.Repository.forModel(constructor, this.adapter.alias);
79
+ const created = await repo.create(propertyValue, context);
80
+ const pk = (0, db_decorators_1.findPrimaryKey)(created).id;
81
+ await (0, core_1.cacheModelForPopulate)(context, model, key, created[pk], created);
82
+ model[key] = created[pk];
83
+ }
84
+ /**
85
+ * @description Handles one-to-one relationship updates
86
+ * @summary Processes a one-to-one relationship when updating a model, either by referencing an existing model or updating the related model
87
+ * @template M - The model type extending Model
88
+ * @template R - The repository type extending Repo<M, F, C>
89
+ * @template V - The relations metadata type extending RelationsMetadata
90
+ * @template F - The repository flags type
91
+ * @template C - The context type extending Context<F>
92
+ * @param {R} this - The repository instance
93
+ * @param {Context<F>} context - The context for the operation
94
+ * @param {V} data - The relations metadata
95
+ * @param key - The property key of the relationship
96
+ * @param {M} model - The model instance
97
+ * @return {Promise<void>} A promise that resolves when the operation is complete
98
+ * @function oneToOneOnUpdate
99
+ * @memberOf module:core
100
+ * @mermaid
101
+ * sequenceDiagram
102
+ * participant Caller
103
+ * participant oneToOneOnUpdate
104
+ * participant repositoryFromTypeMetadata
105
+ * participant createOrUpdate
106
+ * participant findPrimaryKey
107
+ * participant cacheModelForPopulate
108
+ *
109
+ * Caller->>oneToOneOnUpdate: this, context, data, key, model
110
+ * oneToOneOnUpdate->>oneToOneOnUpdate: check if propertyValue exists
111
+ * oneToOneOnUpdate->>oneToOneOnUpdate: check if cascade.update is CASCADE
112
+ *
113
+ * alt propertyValue is not an object
114
+ * oneToOneOnUpdate->>repositoryFromTypeMetadata: model, key
115
+ * repositoryFromTypeMetadata-->>oneToOneOnUpdate: innerRepo
116
+ * oneToOneOnUpdate->>innerRepo: read(propertyValue)
117
+ * innerRepo-->>oneToOneOnUpdate: read
118
+ * oneToOneOnUpdate->>cacheModelForPopulate: context, model, key, propertyValue, read
119
+ * oneToOneOnUpdate->>oneToOneOnUpdate: set model[key] = propertyValue
120
+ * else propertyValue is an object
121
+ * oneToOneOnUpdate->>createOrUpdate: model[key], context
122
+ * createOrUpdate-->>oneToOneOnUpdate: updated
123
+ * oneToOneOnUpdate->>findPrimaryKey: updated
124
+ * findPrimaryKey-->>oneToOneOnUpdate: pk
125
+ * oneToOneOnUpdate->>cacheModelForPopulate: context, model, key, updated[pk], updated
126
+ * oneToOneOnUpdate->>oneToOneOnUpdate: set model[key] = updated[pk]
127
+ * end
128
+ *
129
+ * oneToOneOnUpdate-->>Caller: void
130
+ */
131
+ async function oneToOneOnUpdate(context, data, key, model) {
132
+ const propertyValue = model[key];
133
+ if (!propertyValue)
134
+ return;
135
+ if (data.cascade.update !== core_1.Cascade.CASCADE)
136
+ return;
137
+ if (typeof propertyValue !== "object") {
138
+ const innerRepo = (0, core_1.repositoryFromTypeMetadata)(model, key, this.adapter.alias);
139
+ const read = await innerRepo.read(propertyValue, context);
140
+ await (0, core_1.cacheModelForPopulate)(context, model, key, propertyValue, read);
141
+ model[key] = propertyValue;
142
+ return;
143
+ }
144
+ const updated = await (0, core_1.createOrUpdate)(model[key], context, this.adapter.alias);
145
+ const pk = (0, db_decorators_1.findPrimaryKey)(updated).id;
146
+ await (0, core_1.cacheModelForPopulate)(context, model, key, updated[pk], updated);
147
+ model[key] = updated[pk];
148
+ }
149
+ /**
150
+ * @description Handles one-to-one relationship deletion
151
+ * @summary Processes a one-to-one relationship when deleting a model, deleting the related model if cascade is enabled
152
+ * @template M - The model type extending Model
153
+ * @template R - The repository type extending Repo<M, F, C>
154
+ * @template V - The relations metadata type extending RelationsMetadata
155
+ * @template F - The repository flags type
156
+ * @template C - The context type extending Context<F>
157
+ * @param {R} this - The repository instance
158
+ * @param {Context<F>} context - The context for the operation
159
+ * @param {V} data - The relations metadata
160
+ * @param key - The property key of the relationship
161
+ * @param {M} model - The model instance
162
+ * @return {Promise<void>} A promise that resolves when the operation is complete
163
+ * @function oneToOneOnDelete
164
+ * @memberOf module:core
165
+ * @mermaid
166
+ * sequenceDiagram
167
+ * participant Caller
168
+ * participant oneToOneOnDelete
169
+ * participant repositoryFromTypeMetadata
170
+ * participant cacheModelForPopulate
171
+ *
172
+ * Caller->>oneToOneOnDelete: this, context, data, key, model
173
+ * oneToOneOnDelete->>oneToOneOnDelete: check if propertyValue exists
174
+ * oneToOneOnDelete->>oneToOneOnDelete: check if cascade.update is CASCADE
175
+ *
176
+ * oneToOneOnDelete->>repositoryFromTypeMetadata: model, key
177
+ * repositoryFromTypeMetadata-->>oneToOneOnDelete: innerRepo
178
+ *
179
+ * alt propertyValue is not a Model instance
180
+ * oneToOneOnDelete->>innerRepo: delete(model[key], context)
181
+ * innerRepo-->>oneToOneOnDelete: deleted
182
+ * else propertyValue is a Model instance
183
+ * oneToOneOnDelete->>innerRepo: delete(model[key][innerRepo.pk], context)
184
+ * innerRepo-->>oneToOneOnDelete: deleted
185
+ * end
186
+ *
187
+ * oneToOneOnDelete->>cacheModelForPopulate: context, model, key, deleted[innerRepo.pk], deleted
188
+ * oneToOneOnDelete-->>Caller: void
189
+ */
190
+ async function oneToOneOnDelete(context, data, key, model) {
191
+ const propertyValue = model[key];
192
+ if (!propertyValue)
193
+ return;
194
+ if (data.cascade.update !== core_1.Cascade.CASCADE)
195
+ return;
196
+ const innerRepo = (0, core_1.repositoryFromTypeMetadata)(model, key, this.adapter.alias);
197
+ let deleted;
198
+ if (!(propertyValue instanceof decorator_validation_1.Model))
199
+ deleted = await innerRepo.delete(model[key], context);
200
+ else
201
+ deleted = await innerRepo.delete(model[key][innerRepo.pk], context);
202
+ await (0, core_1.cacheModelForPopulate)(context, model, key, deleted[innerRepo.pk], deleted);
203
+ }
204
+ /**
205
+ * @description Handles one-to-many relationship creation
206
+ * @summary Processes a one-to-many relationship when creating a model, either by referencing existing models or creating new ones
207
+ * @template M - The model type extending Model
208
+ * @template R - The repository type extending Repo<M, F, C>
209
+ * @template V - The relations metadata type extending RelationsMetadata
210
+ * @template F - The repository flags type
211
+ * @template C - The context type extending Context<F>
212
+ * @param {R} this - The repository instance
213
+ * @param {Context<F>} context - The context for the operation
214
+ * @param {V} data - The relations metadata
215
+ * @param key - The property key of the relationship
216
+ * @param {M} model - The model instance
217
+ * @return {Promise<void>} A promise that resolves when the operation is complete
218
+ * @function oneToManyOnCreate
219
+ * @memberOf module:core
220
+ * @mermaid
221
+ * sequenceDiagram
222
+ * participant Caller
223
+ * participant oneToManyOnCreate
224
+ * participant repositoryFromTypeMetadata
225
+ * participant createOrUpdate
226
+ * participant findPrimaryKey
227
+ * participant cacheModelForPopulate
228
+ *
229
+ * Caller->>oneToManyOnCreate: this, context, data, key, model
230
+ * oneToManyOnCreate->>oneToManyOnCreate: check if propertyValues exists and has length
231
+ * oneToManyOnCreate->>oneToManyOnCreate: check if all elements have same type
232
+ * oneToManyOnCreate->>oneToManyOnCreate: create uniqueValues set
233
+ *
234
+ * alt arrayType is not "object"
235
+ * oneToManyOnCreate->>repositoryFromTypeMetadata: model, key
236
+ * repositoryFromTypeMetadata-->>oneToManyOnCreate: repo
237
+ * loop for each id in uniqueValues
238
+ * oneToManyOnCreate->>repo: read(id)
239
+ * repo-->>oneToManyOnCreate: read
240
+ * oneToManyOnCreate->>cacheModelForPopulate: context, model, key, id, read
241
+ * end
242
+ * oneToManyOnCreate->>oneToManyOnCreate: set model[key] = [...uniqueValues]
243
+ * else arrayType is "object"
244
+ * oneToManyOnCreate->>findPrimaryKey: propertyValues[0]
245
+ * findPrimaryKey-->>oneToManyOnCreate: pkName
246
+ * oneToManyOnCreate->>oneToManyOnCreate: create result set
247
+ * loop for each m in propertyValues
248
+ * oneToManyOnCreate->>createOrUpdate: m, context
249
+ * createOrUpdate-->>oneToManyOnCreate: record
250
+ * oneToManyOnCreate->>cacheModelForPopulate: context, model, key, record[pkName], record
251
+ * oneToManyOnCreate->>oneToManyOnCreate: add record[pkName] to result
252
+ * end
253
+ * oneToManyOnCreate->>oneToManyOnCreate: set model[key] = [...result]
254
+ * end
255
+ *
256
+ * oneToManyOnCreate-->>Caller: void
257
+ */
258
+ async function oneToManyOnCreate(context, data, key, model) {
259
+ const propertyValues = model[key];
260
+ if (!propertyValues || !propertyValues.length)
261
+ return;
262
+ const arrayType = typeof propertyValues[0];
263
+ if (!propertyValues.every((item) => typeof item === arrayType))
264
+ throw new db_decorators_1.InternalError(`Invalid operation. All elements of property ${key} must match the same type.`);
265
+ const uniqueValues = new Set([...propertyValues]);
266
+ if (arrayType !== "object") {
267
+ const repo = (0, core_1.repositoryFromTypeMetadata)(model, key, this.adapter.alias);
268
+ for (const id of uniqueValues) {
269
+ const read = await repo.read(id, context);
270
+ await (0, core_1.cacheModelForPopulate)(context, model, key, id, read);
271
+ }
272
+ model[key] = [...uniqueValues];
273
+ return;
274
+ }
275
+ const pkName = (0, db_decorators_1.findPrimaryKey)(propertyValues[0]).id;
276
+ const result = new Set();
277
+ for (const m of propertyValues) {
278
+ const record = await (0, core_1.createOrUpdate)(m, context, this.adapter.alias);
279
+ await (0, core_1.cacheModelForPopulate)(context, model, key, record[pkName], record);
280
+ result.add(record[pkName]);
281
+ }
282
+ model[key] = [...result];
283
+ }
284
+ /**
285
+ * @description Handles one-to-many relationship deletion
286
+ * @summary Processes a one-to-many relationship when deleting a model, deleting all related models if cascade delete is enabled
287
+ * @template M - The model type extending Model
288
+ * @template R - The repository type extending Repo<M, F, C>
289
+ * @template V - The relations metadata type extending RelationsMetadata
290
+ * @template F - The repository flags type
291
+ * @template C - The context type extending Context<F>
292
+ * @param {R} this - The repository instance
293
+ * @param {Context<F>} context - The context for the operation
294
+ * @param {V} data - The relations metadata
295
+ * @param key - The property key of the relationship
296
+ * @param {M} model - The model instance
297
+ * @return {Promise<void>} A promise that resolves when the operation is complete
298
+ * @function oneToManyOnDelete
299
+ * @memberOf module:core
300
+ * @mermaid
301
+ * sequenceDiagram
302
+ * participant Caller
303
+ * participant oneToManyOnDelete
304
+ * participant Repository
305
+ * participant repositoryFromTypeMetadata
306
+ * participant cacheModelForPopulate
307
+ *
308
+ * Caller->>oneToManyOnDelete: this, context, data, key, model
309
+ * oneToManyOnDelete->>oneToManyOnDelete: check if cascade.delete is CASCADE
310
+ * oneToManyOnDelete->>oneToManyOnDelete: check if values exists and has length
311
+ * oneToManyOnDelete->>oneToManyOnDelete: check if all elements have same type
312
+ *
313
+ * alt isInstantiated (arrayType is "object")
314
+ * oneToManyOnDelete->>Repository: forModel(values[0])
315
+ * Repository-->>oneToManyOnDelete: repo
316
+ * else not instantiated
317
+ * oneToManyOnDelete->>repositoryFromTypeMetadata: model, key
318
+ * repositoryFromTypeMetadata-->>oneToManyOnDelete: repo
319
+ * end
320
+ *
321
+ * oneToManyOnDelete->>oneToManyOnDelete: create uniqueValues set
322
+ *
323
+ * loop for each id in uniqueValues
324
+ * oneToManyOnDelete->>repo: delete(id, context)
325
+ * repo-->>oneToManyOnDelete: deleted
326
+ * oneToManyOnDelete->>cacheModelForPopulate: context, model, key, id, deleted
327
+ * end
328
+ *
329
+ * oneToManyOnDelete->>oneToManyOnDelete: set model[key] = [...uniqueValues]
330
+ * oneToManyOnDelete-->>Caller: void
331
+ */
332
+ async function oneToManyOnDelete(context, data, key, model) {
333
+ if (data.cascade.delete !== core_1.Cascade.CASCADE)
334
+ return;
335
+ const values = model[key];
336
+ if (!values || !values.length)
337
+ return;
338
+ const arrayType = typeof values[0];
339
+ const areAllSameType = values.every((item) => typeof item === arrayType);
340
+ if (!areAllSameType)
341
+ throw new db_decorators_1.InternalError(`Invalid operation. All elements of property ${key} must match the same type.`);
342
+ const isInstantiated = arrayType === "object";
343
+ const repo = isInstantiated
344
+ ? core_1.Repository.forModel(values[0], this.adapter.alias)
345
+ : (0, core_1.repositoryFromTypeMetadata)(model, key, this.adapter.alias);
346
+ const uniqueValues = new Set([
347
+ ...(isInstantiated
348
+ ? values.map((v) => v[repo.pk])
349
+ : values),
350
+ ]);
351
+ for (const id of uniqueValues.values()) {
352
+ const deleted = await repo.delete(id, context);
353
+ await (0, core_1.cacheModelForPopulate)(context, model, key, id, deleted);
354
+ }
355
+ model[key] = [...uniqueValues];
356
+ }
357
+ /**
358
+ * @description Populates a model's relationship
359
+ * @summary Retrieves and attaches related models to a model's relationship property
360
+ * @template M - The model type extending Model
361
+ * @template R - The repository type extending Repo<M, F, C>
362
+ * @template V - The relations metadata type extending RelationsMetadata
363
+ * @template F - The repository flags type
364
+ * @template C - The context type extending Context<F>
365
+ * @param {R} this - The repository instance
366
+ * @param {Context<F>} context - The context for the operation
367
+ * @param {V} data - The relations metadata
368
+ * @param key - The property key of the relationship
369
+ * @param {M} model - The model instance
370
+ * @return {Promise<void>} A promise that resolves when the operation is complete
371
+ * @function populate
372
+ * @memberOf module:core
373
+ * @mermaid
374
+ * sequenceDiagram
375
+ * participant Caller
376
+ * participant populate
377
+ * participant fetchPopulateValues
378
+ * participant getPopulateKey
379
+ * participant Context
380
+ * participant repositoryFromTypeMetadata
381
+ *
382
+ * Caller->>populate: this, context, data, key, model
383
+ * populate->>populate: check if data.populate is true
384
+ * populate->>populate: get nested value and check if it exists
385
+ *
386
+ * populate->>fetchPopulateValues: context, model, key, isArr ? nested : [nested]
387
+ *
388
+ * fetchPopulateValues->>fetchPopulateValues: initialize variables
389
+ *
390
+ * loop for each proKeyValue in propKeyValues
391
+ * fetchPopulateValues->>getPopulateKey: model.constructor.name, propName, proKeyValue
392
+ * getPopulateKey-->>fetchPopulateValues: cacheKey
393
+ *
394
+ * alt try to get from cache
395
+ * fetchPopulateValues->>Context: get(cacheKey)
396
+ * Context-->>fetchPopulateValues: val
397
+ * else catch error
398
+ * fetchPopulateValues->>repositoryFromTypeMetadata: model, propName
399
+ * repositoryFromTypeMetadata-->>fetchPopulateValues: repo
400
+ * fetchPopulateValues->>repo: read(proKeyValue)
401
+ * repo-->>fetchPopulateValues: val
402
+ * end
403
+ *
404
+ * fetchPopulateValues->>fetchPopulateValues: add val to results
405
+ * end
406
+ *
407
+ * fetchPopulateValues-->>populate: results
408
+ * populate->>populate: set model[key] = isArr ? res : res[0]
409
+ * populate-->>Caller: void
410
+ */
411
+ async function populate(context, data, key, model) {
412
+ if (!data.populate)
413
+ return;
414
+ const nested = model[key];
415
+ const isArr = Array.isArray(nested);
416
+ if (typeof nested === "undefined" || (isArr && nested.length === 0))
417
+ return;
418
+ async function fetchPopulateValues(c, model, propName, propKeyValues, alias) {
419
+ let cacheKey;
420
+ let val;
421
+ const results = [];
422
+ for (const proKeyValue of propKeyValues) {
423
+ cacheKey = (0, core_1.getPopulateKey)(model.constructor.name, propName, proKeyValue);
424
+ try {
425
+ val = await c.get(cacheKey);
426
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
427
+ }
428
+ catch (e) {
429
+ const repo = (0, core_1.repositoryFromTypeMetadata)(model, propName, alias);
430
+ if (!repo)
431
+ throw new db_decorators_1.InternalError("Could not find repo");
432
+ val = await repo.read(proKeyValue, context);
433
+ }
434
+ results.push(val);
435
+ }
436
+ return results;
437
+ }
438
+ const res = await fetchPopulateValues(context, model, key, isArr ? nested : [nested], this.adapter.alias);
439
+ model[key] = isArr ? res : res[0];
440
+ }
441
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRmFicmljQ29uc3RydWN0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbnRyYWN0cy9GYWJyaWNDb25zdHJ1Y3Rpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFvRUEsNENBdUNDO0FBaURELDRDQTJDQztBQTJDRCw0Q0FvQ0M7QUF3REQsOENBMENDO0FBa0RELDhDQXNDQztBQXdERCw0QkFrREM7QUExakJELHlDQVN3QjtBQUN4Qix5RUFBdUQ7QUFFdkQsMkRBSWlDO0FBRWpDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBaURHO0FBQ0ksS0FBSyxVQUFVLGdCQUFnQixDQVFwQyxPQUFtQixFQUNuQixJQUFPLEVBQ1AsR0FBWSxFQUNaLEtBQVE7SUFFUixNQUFNLGFBQWEsR0FBUSxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDdEMsSUFBSSxDQUFDLGFBQWE7UUFBRSxPQUFPO0lBRTNCLElBQUksT0FBTyxhQUFhLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDdEMsTUFBTSxTQUFTLEdBQUcsSUFBQSxpQ0FBMEIsRUFDMUMsS0FBSyxFQUNMLEdBQUcsRUFDSCxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FDbkIsQ0FBQztRQUNGLE1BQU0sSUFBSSxHQUFHLE1BQU0sU0FBUyxDQUFDLElBQUksQ0FBQyxhQUFhLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDMUQsTUFBTSxJQUFBLDRCQUFxQixFQUFDLE9BQU8sRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFLGFBQWEsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUNyRSxLQUFhLENBQUMsR0FBRyxDQUFDLEdBQUcsYUFBYSxDQUFDO1FBQ3BDLE9BQU87SUFDVCxDQUFDO0lBRUQsSUFBSSxDQUFDLEtBQUs7UUFDUixPQUFPLElBQUksQ0FBQyxLQUFLLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFD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QixLQUFLLE1BQU0sV0FBVyxJQUFJLGFBQWEsRUFBRSxDQUFDO1lBQ3hDLFFBQVEsR0FBRyxJQUFBLHFCQUFjLEVBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsUUFBUSxFQUFFLFdBQVcsQ0FBQyxDQUFDO1lBQ3pFLElBQUksQ0FBQztnQkFDSCxHQUFHLEdBQUcsTUFBTSxDQUFDLENBQUMsR0FBRyxDQUFDLFFBQWUsQ0FBQyxDQUFDO2dCQUNuQyw2REFBNkQ7WUFDL0QsQ0FBQztZQUFDLE9BQU8sQ0FBTSxFQUFFLENBQUM7Z0JBQ2hCLE1BQU0sSUFBSSxHQUFHLElBQUEsaUNBQTBCLEVBQUMsS0FBSyxFQUFFLFFBQVEsRUFBRSxLQUFLLENBQUMsQ0FBQztnQkFDaEUsSUFBSSxDQUFDLElBQUk7b0JBQUUsTUFBTSxJQUFJLDZCQUFhLENBQUMscUJBQXFCLENBQUMsQ0FBQztnQkFDMUQsR0FBRyxHQUFHLE1BQU0sSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsT0FBTyxDQUFDLENBQUM7WUFDOUMsQ0FBQztZQUNELE9BQU8sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDcEIsQ0FBQztRQUNELE9BQU8sT0FBTyxDQUFDO0lBQ2pCLENBQUM7SUFDRCxNQUFNLEdBQUcsR0FBRyxNQUFNLG1CQUFtQixDQUNuQyxPQUFPLEVBQ1AsS0FBSyxFQUNMLEdBQWEsRUFDYixLQUFLLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsRUFDekIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQ25CLENBQUM7SUFDRCxLQUFhLENBQUMsR0FBRyxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUM3QyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgY2FjaGVNb2RlbEZvclBvcHVsYXRlLFxuICBDYXNjYWRlLFxuICBjcmVhdGVPclVwZGF0ZSxcbiAgZ2V0UG9wdWxhdGVLZXksXG4gIFJlbGF0aW9uc01ldGFkYXRhLFxuICBSZXBvLFxuICBSZXBvc2l0b3J5LFxuICByZXBvc2l0b3J5RnJvbVR5cGVNZXRhZGF0YSxcbn0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQgeyBNb2RlbCB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IEZhYnJpY0NvbnRyYWN0RmxhZ3MgfSBmcm9tIFwiLi90eXBlc1wiO1xuaW1wb3J0IHtcbiAgQ29udGV4dCxcbiAgZmluZFByaW1hcnlLZXksXG4gIEludGVybmFsRXJyb3IsXG59IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBIYW5kbGVzIG9uZS10by1vbmUgcmVsYXRpb25zaGlwIGNyZWF0aW9uXG4gKiBAc3VtbWFyeSBQcm9jZXNzZXMgYSBvbmUtdG8tb25lIHJlbGF0aW9uc2hpcCB3aGVuIGNyZWF0aW5nIGEgbW9kZWwsIGVpdGhlciBieSByZWZlcmVuY2luZyBhbiBleGlzdGluZyBtb2RlbCBvciBjcmVhdGluZyBhIG5ldyBvbmVcbiAqIEB0ZW1wbGF0ZSBNIC0gVGhlIG1vZGVsIHR5cGUgZXh0ZW5kaW5nIE1vZGVsXG4gKiBAdGVtcGxhdGUgUiAtIFRoZSByZXBvc2l0b3J5IHR5cGUgZXh0ZW5kaW5nIFJlcG88TSwgRiwgQz5cbiAqIEB0ZW1wbGF0ZSBWIC0gVGhlIHJlbGF0aW9ucyBtZXRhZGF0YSB0eXBlIGV4dGVuZGluZyBSZWxhdGlvbnNNZXRhZGF0YVxuICogQHRlbXBsYXRlIEYgLSBUaGUgcmVwb3NpdG9yeSBmbGFncyB0eXBlXG4gKiBAdGVtcGxhdGUgQyAtIFRoZSBjb250ZXh0IHR5cGUgZXh0ZW5kaW5nIENvbnRleHQ8Rj5cbiAqIEBwYXJhbSB7Un0gdGhpcyAtIFRoZSByZXBvc2l0b3J5IGluc3RhbmNlXG4gKiBAcGFyYW0ge0NvbnRleHQ8Rj59IGNvbnRleHQgLSBUaGUgY29udGV4dCBmb3IgdGhlIG9wZXJhdGlvblxuICogQHBhcmFtIHtWfSBkYXRhIC0gVGhlIHJlbGF0aW9ucyBtZXRhZGF0YVxuICogQHBhcmFtIHtzdHJpbmd9IGtleSAtIFRoZSBwcm9wZXJ0eSBrZXkgb2YgdGhlIHJlbGF0aW9uc2hpcFxuICogQHBhcmFtIHtNfSBtb2RlbCAtIFRoZSBtb2RlbCBpbnN0YW5jZVxuICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgb3BlcmF0aW9uIGlzIGNvbXBsZXRlXG4gKiBAZnVuY3Rpb24gb25lVG9PbmVPbkNyZWF0ZVxuICogQG1lbWJlck9mIG1vZHVsZTpjb3JlXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENhbGxlclxuICogICBwYXJ0aWNpcGFudCBvbmVUb09uZU9uQ3JlYXRlXG4gKiAgIHBhcnRpY2lwYW50IHJlcG9zaXRvcnlGcm9tVHlwZU1ldGFkYXRhXG4gKiAgIHBhcnRpY2lwYW50IE1vZGVsXG4gKiAgIHBhcnRpY2lwYW50IFJlcG9zaXRvcnlcbiAqICAgcGFydGljaXBhbnQgY2FjaGVNb2RlbEZvclBvcHVsYXRlXG4gKlxuICogICBDYWxsZXItPj5vbmVUb09uZU9uQ3JlYXRlOiB0aGlzLCBjb250ZXh0LCBkYXRhLCBrZXksIG1vZGVsXG4gKiAgIG9uZVRvT25lT25DcmVhdGUtPj5vbmVUb09uZU9uQ3JlYXRlOiBjaGVjayBpZiBwcm9wZXJ0eVZhbHVlIGV4aXN0c1xuICpcbiAqICAgYWx0IHByb3BlcnR5VmFsdWUgaXMgbm90IGFuIG9iamVjdFxuICogICAgIG9uZVRvT25lT25DcmVhdGUtPj5yZXBvc2l0b3J5RnJvbVR5cGVNZXRhZGF0YTogbW9kZWwsIGtleVxuICogICAgIHJlcG9zaXRvcnlGcm9tVHlwZU1ldGFkYXRhLS0+Pm9uZVRvT25lT25DcmVhdGU6IGlubmVyUmVwb1xuICogICAgIG9uZVRvT25lT25DcmVhdGUtPj5pbm5lclJlcG86IHJlYWQocHJvcGVydHlWYWx1ZSlcbiAqICAgICBpbm5lclJlcG8tLT4+b25lVG9PbmVPbkNyZWF0ZTogcmVhZFxuICogICAgIG9uZVRvT25lT25DcmVhdGUtPj5jYWNoZU1vZGVsRm9yUG9wdWxhdGU6IGNvbnRleHQsIG1vZGVsLCBrZXksIHByb3BlcnR5VmFsdWUsIHJlYWRcbiAqICAgICBvbmVUb09uZU9uQ3JlYXRlLT4+b25lVG9PbmVPbkNyZWF0ZTogc2V0IG1vZGVsW2tleV0gPSBwcm9wZXJ0eVZhbHVlXG4gKiAgIGVsc2UgcHJvcGVydHlWYWx1ZSBpcyBhbiBvYmplY3RcbiAqICAgICBvbmVUb09uZU9uQ3JlYXRlLT4+TW9kZWw6IGdldChkYXRhLmNsYXNzKVxuICogICAgIE1vZGVsLS0+Pm9uZVRvT25lT25DcmVhdGU6IGNvbnN0cnVjdG9yXG4gKiAgICAgb25lVG9PbmVPbkNyZWF0ZS0+PlJlcG9zaXRvcnk6IGZvck1vZGVsKGNvbnN0cnVjdG9yKVxuICogICAgIFJlcG9zaXRvcnktLT4+b25lVG9PbmVPbkNyZWF0ZTogcmVwb1xuICogICAgIG9uZVRvT25lT25DcmVhdGUtPj5yZXBvOiBjcmVhdGUocHJvcGVydHlWYWx1ZSlcbiAqICAgICByZXBvLS0+Pm9uZVRvT25lT25DcmVhdGU6IGNyZWF0ZWRcbiAqICAgICBvbmVUb09uZU9uQ3JlYXRlLT4+ZmluZFByaW1hcnlLZXk6IGNyZWF0ZWRcbiAqICAgICBmaW5kUHJpbWFyeUtleS0tPj5vbmVUb09uZU9uQ3JlYXRlOiBwa1xuICogICAgIG9uZVRvT25lT25DcmVhdGUtPj5jYWNoZU1vZGVsRm9yUG9wdWxhdGU6IGNvbnRleHQsIG1vZGVsLCBrZXksIGNyZWF0ZWRbcGtdLCBjcmVhdGVkXG4gKiAgICAgb25lVG9PbmVPbkNyZWF0ZS0+Pm9uZVRvT25lT25DcmVhdGU6IHNldCBtb2RlbFtrZXldID0gY3JlYXRlZFtwa11cbiAqICAgZW5kXG4gKlxuICogICBvbmVUb09uZU9uQ3JlYXRlLS0+PkNhbGxlcjogdm9pZFxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gb25lVG9PbmVPbkNyZWF0ZTxcbiAgTSBleHRlbmRzIE1vZGVsLFxuICBSIGV4dGVuZHMgUmVwbzxNLCBGLCBDPixcbiAgViBleHRlbmRzIFJlbGF0aW9uc01ldGFkYXRhLFxuICBGIGV4dGVuZHMgRmFicmljQ29udHJhY3RGbGFncyxcbiAgQyBleHRlbmRzIENvbnRleHQ8Rj4sXG4+KFxuICB0aGlzOiBSLFxuICBjb250ZXh0OiBDb250ZXh0PEY+LFxuICBkYXRhOiBWLFxuICBrZXk6IGtleW9mIE0sXG4gIG1vZGVsOiBNXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgcHJvcGVydHlWYWx1ZTogYW55ID0gbW9kZWxba2V5XTtcbiAgaWYgKCFwcm9wZXJ0eVZhbHVlKSByZXR1cm47XG5cbiAgaWYgKHR5cGVvZiBwcm9wZXJ0eVZhbHVlICE9PSBcIm9iamVjdFwiKSB7XG4gICAgY29uc3QgaW5uZXJSZXBvID0gcmVwb3NpdG9yeUZyb21UeXBlTWV0YWRhdGEoXG4gICAgICBtb2RlbCxcbiAgICAgIGtleSxcbiAgICAgIHRoaXMuYWRhcHRlci5hbGlhc1xuICAgICk7XG4gICAgY29uc3QgcmVhZCA9IGF3YWl0IGlubmVyUmVwby5yZWFkKHByb3BlcnR5VmFsdWUsIGNvbnRleHQpO1xuICAgIGF3YWl0IGNhY2hlTW9kZWxGb3JQb3B1bGF0ZShjb250ZXh0LCBtb2RlbCwga2V5LCBwcm9wZXJ0eVZhbHVlLCByZWFkKTtcbiAgICAobW9kZWwgYXMgYW55KVtrZXldID0gcHJvcGVydHlWYWx1ZTtcbiAgICByZXR1cm47XG4gIH1cblxuICBkYXRhLmNsYXNzID1cbiAgICB0eXBlb2YgZGF0YS5jbGFzcyA9PT0gXCJzdHJpbmdcIiA/IGRhdGEuY2xhc3MgOiAoZGF0YS5jbGFzcyBhcyBhbnkpKCkubmFtZTtcblxuICBjb25zdCBjb25zdHJ1Y3RvciA9IE1vZGVsLmdldChkYXRhLmNsYXNzIGFzIHN0cmluZyk7XG4gIGlmICghY29uc3RydWN0b3IpXG4gICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoYENvdWxkIG5vdCBmaW5kIG1vZGVsICR7ZGF0YS5jbGFzc31gKTtcbiAgY29uc3QgcmVwbzogUmVwbzxhbnk+ID0gUmVwb3NpdG9yeS5mb3JNb2RlbChjb25zdHJ1Y3RvciwgdGhpcy5hZGFwdGVyLmFsaWFzKTtcbiAgY29uc3QgY3JlYXRlZCA9IGF3YWl0IHJlcG8uY3JlYXRlKHByb3BlcnR5VmFsdWUsIGNvbnRleHQpO1xuICBjb25zdCBwayA9IGZpbmRQcmltYXJ5S2V5KGNyZWF0ZWQpLmlkO1xuICBhd2FpdCBjYWNoZU1vZGVsRm9yUG9wdWxhdGUoY29udGV4dCwgbW9kZWwsIGtleSwgY3JlYXRlZFtwa10sIGNyZWF0ZWQpO1xuICAobW9kZWwgYXMgYW55KVtrZXldID0gY3JlYXRlZFtwa107XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEhhbmRsZXMgb25lLXRvLW9uZSByZWxhdGlvbnNoaXAgdXBkYXRlc1xuICogQHN1bW1hcnkgUHJvY2Vzc2VzIGEgb25lLXRvLW9uZSByZWxhdGlvbnNoaXAgd2hlbiB1cGRhdGluZyBhIG1vZGVsLCBlaXRoZXIgYnkgcmVmZXJlbmNpbmcgYW4gZXhpc3RpbmcgbW9kZWwgb3IgdXBkYXRpbmcgdGhlIHJlbGF0ZWQgbW9kZWxcbiAqIEB0ZW1wbGF0ZSBNIC0gVGhlIG1vZGVsIHR5cGUgZXh0ZW5kaW5nIE1vZGVsXG4gKiBAdGVtcGxhdGUgUiAtIFRoZSByZXBvc2l0b3J5IHR5cGUgZXh0ZW5kaW5nIFJlcG88TSwgRiwgQz5cbiAqIEB0ZW1wbGF0ZSBWIC0gVGhlIHJlbGF0aW9ucyBtZXRhZGF0YSB0eXBlIGV4dGVuZGluZyBSZWxhdGlvbnNNZXRhZGF0YVxuICogQHRlbXBsYXRlIEYgLSBUaGUgcmVwb3NpdG9yeSBmbGFncyB0eXBlXG4gKiBAdGVtcGxhdGUgQyAtIFRoZSBjb250ZXh0IHR5cGUgZXh0ZW5kaW5nIENvbnRleHQ8Rj5cbiAqIEBwYXJhbSB7Un0gdGhpcyAtIFRoZSByZXBvc2l0b3J5IGluc3RhbmNlXG4gKiBAcGFyYW0ge0NvbnRleHQ8Rj59IGNvbnRleHQgLSBUaGUgY29udGV4dCBmb3IgdGhlIG9wZXJhdGlvblxuICogQHBhcmFtIHtWfSBkYXRhIC0gVGhlIHJlbGF0aW9ucyBtZXRhZGF0YVxuICogQHBhcmFtIGtleSAtIFRoZSBwcm9wZXJ0eSBrZXkgb2YgdGhlIHJlbGF0aW9uc2hpcFxuICogQHBhcmFtIHtNfSBtb2RlbCAtIFRoZSBtb2RlbCBpbnN0YW5jZVxuICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgb3BlcmF0aW9uIGlzIGNvbXBsZXRlXG4gKiBAZnVuY3Rpb24gb25lVG9PbmVPblVwZGF0ZVxuICogQG1lbWJlck9mIG1vZHVsZTpjb3JlXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENhbGxlclxuICogICBwYXJ0aWNpcGFudCBvbmVUb09uZU9uVXBkYXRlXG4gKiAgIHBhcnRpY2lwYW50IHJlcG9zaXRvcnlGcm9tVHlwZU1ldGFkYXRhXG4gKiAgIHBhcnRpY2lwYW50IGNyZWF0ZU9yVXBkYXRlXG4gKiAgIHBhcnRpY2lwYW50IGZpbmRQcmltYXJ5S2V5XG4gKiAgIHBhcnRpY2lwYW50IGNhY2hlTW9kZWxGb3JQb3B1bGF0ZVxuICpcbiAqICAgQ2FsbGVyLT4+b25lVG9PbmVPblVwZGF0ZTogdGhpcywgY29udGV4dCwgZGF0YSwga2V5LCBtb2RlbFxuICogICBvbmVUb09uZU9uVXBkYXRlLT4+b25lVG9PbmVPblVwZGF0ZTogY2hlY2sgaWYgcHJvcGVydHlWYWx1ZSBleGlzdHNcbiAqICAgb25lVG9PbmVPblVwZGF0ZS0+Pm9uZVRvT25lT25VcGRhdGU6IGNoZWNrIGlmIGNhc2NhZGUudXBkYXRlIGlzIENBU0NBREVcbiAqXG4gKiAgIGFsdCBwcm9wZXJ0eVZhbHVlIGlzIG5vdCBhbiBvYmplY3RcbiAqICAgICBvbmVUb09uZU9uVXBkYXRlLT4+cmVwb3NpdG9yeUZyb21UeXBlTWV0YWRhdGE6IG1vZGVsLCBrZXlcbiAqICAgICByZXBvc2l0b3J5RnJvbVR5cGVNZXRhZGF0YS0tPj5vbmVUb09uZU9uVXBkYXRlOiBpbm5lclJlcG9cbiAqICAgICBvbmVUb09uZU9uVXBkYXRlLT4+aW5uZXJSZXBvOiByZWFkKHByb3BlcnR5VmFsdWUpXG4gKiAgICAgaW5uZXJSZXBvLS0+Pm9uZVRvT25lT25VcGRhdGU6IHJlYWRcbiAqICAgICBvbmVUb09uZU9uVXBkYXRlLT4+Y2FjaGVNb2RlbEZvclBvcHVsYXRlOiBjb250ZXh0LCBtb2RlbCwga2V5LCBwcm9wZXJ0eVZhbHVlLCByZWFkXG4gKiAgICAgb25lVG9PbmVPblVwZGF0ZS0+Pm9uZVRvT25lT25VcGRhdGU6IHNldCBtb2RlbFtrZXldID0gcHJvcGVydHlWYWx1ZVxuICogICBlbHNlIHByb3BlcnR5VmFsdWUgaXMgYW4gb2JqZWN0XG4gKiAgICAgb25lVG9PbmVPblVwZGF0ZS0+PmNyZWF0ZU9yVXBkYXRlOiBtb2RlbFtrZXldLCBjb250ZXh0XG4gKiAgICAgY3JlYXRlT3JVcGRhdGUtLT4+b25lVG9PbmVPblVwZGF0ZTogdXBkYXRlZFxuICogICAgIG9uZVRvT25lT25VcGRhdGUtPj5maW5kUHJpbWFyeUtleTogdXBkYXRlZFxuICogICAgIGZpbmRQcmltYXJ5S2V5LS0+Pm9uZVRvT25lT25VcGRhdGU6IHBrXG4gKiAgICAgb25lVG9PbmVPblVwZGF0ZS0+PmNhY2hlTW9kZWxGb3JQb3B1bGF0ZTogY29udGV4dCwgbW9kZWwsIGtleSwgdXBkYXRlZFtwa10sIHVwZGF0ZWRcbiAqICAgICBvbmVUb09uZU9uVXBkYXRlLT4+b25lVG9PbmVPblVwZGF0ZTogc2V0IG1vZGVsW2tleV0gPSB1cGRhdGVkW3BrXVxuICogICBlbmRcbiAqXG4gKiAgIG9uZVRvT25lT25VcGRhdGUtLT4+Q2FsbGVyOiB2b2lkXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBvbmVUb09uZU9uVXBkYXRlPFxuICBNIGV4dGVuZHMgTW9kZWwsXG4gIFIgZXh0ZW5kcyBSZXBvPE0sIEYsIEM+LFxuICBWIGV4dGVuZHMgUmVsYXRpb25zTWV0YWRhdGEsXG4gIEYgZXh0ZW5kcyBGYWJyaWNDb250cmFjdEZsYWdzLFxuICBDIGV4dGVuZHMgQ29udGV4dDxGPixcbj4oXG4gIHRoaXM6IFIsXG4gIGNvbnRleHQ6IENvbnRleHQ8Rj4sXG4gIGRhdGE6IFYsXG4gIGtleToga2V5b2YgTSxcbiAgbW9kZWw6IE1cbik6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBwcm9wZXJ0eVZhbHVlOiBhbnkgPSBtb2RlbFtrZXldO1xuICBpZiAoIXByb3BlcnR5VmFsdWUpIHJldHVybjtcbiAgaWYgKGRhdGEuY2FzY2FkZS51cGRhdGUgIT09IENhc2NhZGUuQ0FTQ0FERSkgcmV0dXJuO1xuXG4gIGlmICh0eXBlb2YgcHJvcGVydHlWYWx1ZSAhPT0gXCJvYmplY3RcIikge1xuICAgIGNvbnN0IGlubmVyUmVwbyA9IHJlcG9zaXRvcnlGcm9tVHlwZU1ldGFkYXRhKFxuICAgICAgbW9kZWwsXG4gICAgICBrZXksXG4gICAgICB0aGlzLmFkYXB0ZXIuYWxpYXNcbiAgICApO1xuICAgIGNvbnN0IHJlYWQgPSBhd2FpdCBpbm5lclJlcG8ucmVhZChwcm9wZXJ0eVZhbHVlLCBjb250ZXh0KTtcbiAgICBhd2FpdCBjYWNoZU1vZGVsRm9yUG9wdWxhdGUoY29udGV4dCwgbW9kZWwsIGtleSwgcHJvcGVydHlWYWx1ZSwgcmVhZCk7XG4gICAgKG1vZGVsIGFzIGFueSlba2V5XSA9IHByb3BlcnR5VmFsdWU7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc3QgdXBkYXRlZCA9IGF3YWl0IGNyZWF0ZU9yVXBkYXRlKFxuICAgIG1vZGVsW2tleV0gYXMgTSxcbiAgICBjb250ZXh0LFxuICAgIHRoaXMuYWRhcHRlci5hbGlhc1xuICApO1xuICBjb25zdCBwayA9IGZpbmRQcmltYXJ5S2V5KHVwZGF0ZWQpLmlkO1xuICBhd2FpdCBjYWNoZU1vZGVsRm9yUG9wdWxhdGUoXG4gICAgY29udGV4dCxcbiAgICBtb2RlbCxcbiAgICBrZXksXG4gICAgdXBkYXRlZFtwa10gYXMgc3RyaW5nLFxuICAgIHVwZGF0ZWRcbiAgKTtcbiAgbW9kZWxba2V5XSA9IHVwZGF0ZWRbcGtdO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBIYW5kbGVzIG9uZS10by1vbmUgcmVsYXRpb25zaGlwIGRlbGV0aW9uXG4gKiBAc3VtbWFyeSBQcm9jZXNzZXMgYSBvbmUtdG8tb25lIHJlbGF0aW9uc2hpcCB3aGVuIGRlbGV0aW5nIGEgbW9kZWwsIGRlbGV0aW5nIHRoZSByZWxhdGVkIG1vZGVsIGlmIGNhc2NhZGUgaXMgZW5hYmxlZFxuICogQHRlbXBsYXRlIE0gLSBUaGUgbW9kZWwgdHlwZSBleHRlbmRpbmcgTW9kZWxcbiAqIEB0ZW1wbGF0ZSBSIC0gVGhlIHJlcG9zaXRvcnkgdHlwZSBleHRlbmRpbmcgUmVwbzxNLCBGLCBDPlxuICogQHRlbXBsYXRlIFYgLSBUaGUgcmVsYXRpb25zIG1ldGFkYXRhIHR5cGUgZXh0ZW5kaW5nIFJlbGF0aW9uc01ldGFkYXRhXG4gKiBAdGVtcGxhdGUgRiAtIFRoZSByZXBvc2l0b3J5IGZsYWdzIHR5cGVcbiAqIEB0ZW1wbGF0ZSBDIC0gVGhlIGNvbnRleHQgdHlwZSBleHRlbmRpbmcgQ29udGV4dDxGPlxuICogQHBhcmFtIHtSfSB0aGlzIC0gVGhlIHJlcG9zaXRvcnkgaW5zdGFuY2VcbiAqIEBwYXJhbSB7Q29udGV4dDxGPn0gY29udGV4dCAtIFRoZSBjb250ZXh0IGZvciB0aGUgb3BlcmF0aW9uXG4gKiBAcGFyYW0ge1Z9IGRhdGEgLSBUaGUgcmVsYXRpb25zIG1ldGFkYXRhXG4gKiBAcGFyYW0ga2V5IC0gVGhlIHByb3BlcnR5IGtleSBvZiB0aGUgcmVsYXRpb25zaGlwXG4gKiBAcGFyYW0ge019IG1vZGVsIC0gVGhlIG1vZGVsIGluc3RhbmNlXG4gKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBvcGVyYXRpb24gaXMgY29tcGxldGVcbiAqIEBmdW5jdGlvbiBvbmVUb09uZU9uRGVsZXRlXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmNvcmVcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQ2FsbGVyXG4gKiAgIHBhcnRpY2lwYW50IG9uZVRvT25lT25EZWxldGVcbiAqICAgcGFydGljaXBhbnQgcmVwb3NpdG9yeUZyb21UeXBlTWV0YWRhdGFcbiAqICAgcGFydGljaXBhbnQgY2FjaGVNb2RlbEZvclBvcHVsYXRlXG4gKlxuICogICBDYWxsZXItPj5vbmVUb09uZU9uRGVsZXRlOiB0aGlzLCBjb250ZXh0LCBkYXRhLCBrZXksIG1vZGVsXG4gKiAgIG9uZVRvT25lT25EZWxldGUtPj5vbmVUb09uZU9uRGVsZXRlOiBjaGVjayBpZiBwcm9wZXJ0eVZhbHVlIGV4aXN0c1xuICogICBvbmVUb09uZU9uRGVsZXRlLT4+b25lVG9PbmVPbkRlbGV0ZTogY2hlY2sgaWYgY2FzY2FkZS51cGRhdGUgaXMgQ0FTQ0FERVxuICpcbiAqICAgb25lVG9PbmVPbkRlbGV0ZS0+PnJlcG9zaXRvcnlGcm9tVHlwZU1ldGFkYXRhOiBtb2RlbCwga2V5XG4gKiAgIHJlcG9zaXRvcnlGcm9tVHlwZU1ldGFkYXRhLS0+Pm9uZVRvT25lT25EZWxldGU6IGlubmVyUmVwb1xuICpcbiAqICAgYWx0IHByb3BlcnR5VmFsdWUgaXMgbm90IGEgTW9kZWwgaW5zdGFuY2VcbiAqICAgICBvbmVUb09uZU9uRGVsZXRlLT4+aW5uZXJSZXBvOiBkZWxldGUobW9kZWxba2V5XSwgY29udGV4dClcbiAqICAgICBpbm5lclJlcG8tLT4+b25lVG9PbmVPbkRlbGV0ZTogZGVsZXRlZFxuICogICBlbHNlIHByb3BlcnR5VmFsdWUgaXMgYSBNb2RlbCBpbnN0YW5jZVxuICogICAgIG9uZVRvT25lT25EZWxldGUtPj5pbm5lclJlcG86IGRlbGV0ZShtb2RlbFtrZXldW2lubmVyUmVwby5wa10sIGNvbnRleHQpXG4gKiAgICAgaW5uZXJSZXBvLS0+Pm9uZVRvT25lT25EZWxldGU6IGRlbGV0ZWRcbiAqICAgZW5kXG4gKlxuICogICBvbmVUb09uZU9uRGVsZXRlLT4+Y2FjaGVNb2RlbEZvclBvcHVsYXRlOiBjb250ZXh0LCBtb2RlbCwga2V5LCBkZWxldGVkW2lubmVyUmVwby5wa10sIGRlbGV0ZWRcbiAqICAgb25lVG9PbmVPbkRlbGV0ZS0tPj5DYWxsZXI6IHZvaWRcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIG9uZVRvT25lT25EZWxldGU8XG4gIE0gZXh0ZW5kcyBNb2RlbCxcbiAgUiBleHRlbmRzIFJlcG88TSwgRiwgQz4sXG4gIFYgZXh0ZW5kcyBSZWxhdGlvbnNNZXRhZGF0YSxcbiAgRiBleHRlbmRzIEZhYnJpY0NvbnRyYWN0RmxhZ3MsXG4gIEMgZXh0ZW5kcyBDb250ZXh0PEY+LFxuPihcbiAgdGhpczogUixcbiAgY29udGV4dDogQ29udGV4dDxGPixcbiAgZGF0YTogVixcbiAga2V5OiBrZXlvZiBNLFxuICBtb2RlbDogTVxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IHByb3BlcnR5VmFsdWU6IGFueSA9IG1vZGVsW2tleV07XG4gIGlmICghcHJvcGVydHlWYWx1ZSkgcmV0dXJuO1xuICBpZiAoZGF0YS5jYXNjYWRlLnVwZGF0ZSAhPT0gQ2FzY2FkZS5DQVNDQURFKSByZXR1cm47XG4gIGNvbnN0IGlubmVyUmVwbzogUmVwbzxNPiA9IHJlcG9zaXRvcnlGcm9tVHlwZU1ldGFkYXRhKFxuICAgIG1vZGVsLFxuICAgIGtleSxcbiAgICB0aGlzLmFkYXB0ZXIuYWxpYXNcbiAgKTtcbiAgbGV0IGRlbGV0ZWQ6IE07XG4gIGlmICghKHByb3BlcnR5VmFsdWUgaW5zdGFuY2VvZiBNb2RlbCkpXG4gICAgZGVsZXRlZCA9IGF3YWl0IGlubmVyUmVwby5kZWxldGUobW9kZWxba2V5XSBhcyBzdHJpbmcsIGNvbnRleHQpO1xuICBlbHNlXG4gICAgZGVsZXRlZCA9IGF3YWl0IGlubmVyUmVwby5kZWxldGUoXG4gICAgICAobW9kZWxba2V5XSBhcyBNKVtpbm5lclJlcG8ucGsgYXMga2V5b2YgTV0gYXMgc3RyaW5nLFxuICAgICAgY29udGV4dFxuICAgICk7XG4gIGF3YWl0IGNhY2hlTW9kZWxGb3JQb3B1bGF0ZShcbiAgICBjb250ZXh0LFxuICAgIG1vZGVsLFxuICAgIGtleSxcbiAgICBkZWxldGVkW2lubmVyUmVwby5wa10gYXMgc3RyaW5nLFxuICAgIGRlbGV0ZWRcbiAgKTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gSGFuZGxlcyBvbmUtdG8tbWFueSByZWxhdGlvbnNoaXAgY3JlYXRpb25cbiAqIEBzdW1tYXJ5IFByb2Nlc3NlcyBhIG9uZS10by1tYW55IHJlbGF0aW9uc2hpcCB3aGVuIGNyZWF0aW5nIGEgbW9kZWwsIGVpdGhlciBieSByZWZlcmVuY2luZyBleGlzdGluZyBtb2RlbHMgb3IgY3JlYXRpbmcgbmV3IG9uZXNcbiAqIEB0ZW1wbGF0ZSBNIC0gVGhlIG1vZGVsIHR5cGUgZXh0ZW5kaW5nIE1vZGVsXG4gKiBAdGVtcGxhdGUgUiAtIFRoZSByZXBvc2l0b3J5IHR5cGUgZXh0ZW5kaW5nIFJlcG88TSwgRiwgQz5cbiAqIEB0ZW1wbGF0ZSBWIC0gVGhlIHJlbGF0aW9ucyBtZXRhZGF0YSB0eXBlIGV4dGVuZGluZyBSZWxhdGlvbnNNZXRhZGF0YVxuICogQHRlbXBsYXRlIEYgLSBUaGUgcmVwb3NpdG9yeSBmbGFncyB0eXBlXG4gKiBAdGVtcGxhdGUgQyAtIFRoZSBjb250ZXh0IHR5cGUgZXh0ZW5kaW5nIENvbnRleHQ8Rj5cbiAqIEBwYXJhbSB7Un0gdGhpcyAtIFRoZSByZXBvc2l0b3J5IGluc3RhbmNlXG4gKiBAcGFyYW0ge0NvbnRleHQ8Rj59IGNvbnRleHQgLSBUaGUgY29udGV4dCBmb3IgdGhlIG9wZXJhdGlvblxuICogQHBhcmFtIHtWfSBkYXRhIC0gVGhlIHJlbGF0aW9ucyBtZXRhZGF0YVxuICogQHBhcmFtIGtleSAtIFRoZSBwcm9wZXJ0eSBrZXkgb2YgdGhlIHJlbGF0aW9uc2hpcFxuICogQHBhcmFtIHtNfSBtb2RlbCAtIFRoZSBtb2RlbCBpbnN0YW5jZVxuICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgb3BlcmF0aW9uIGlzIGNvbXBsZXRlXG4gKiBAZnVuY3Rpb24gb25lVG9NYW55T25DcmVhdGVcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Y29yZVxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDYWxsZXJcbiAqICAgcGFydGljaXBhbnQgb25lVG9NYW55T25DcmVhdGVcbiAqICAgcGFydGljaXBhbnQgcmVwb3NpdG9yeUZyb21UeXBlTWV0YWRhdGFcbiAqICAgcGFydGljaXBhbnQgY3JlYXRlT3JVcGRhdGVcbiAqICAgcGFydGljaXBhbnQgZmluZFByaW1hcnlLZXlcbiAqICAgcGFydGljaXBhbnQgY2FjaGVNb2RlbEZvclBvcHVsYXRlXG4gKlxuICogICBDYWxsZXItPj5vbmVUb01hbnlPbkNyZWF0ZTogdGhpcywgY29udGV4dCwgZGF0YSwga2V5LCBtb2RlbFxuICogICBvbmVUb01hbnlPbkNyZWF0ZS0+Pm9uZVRvTWFueU9uQ3JlYXRlOiBjaGVjayBpZiBwcm9wZXJ0eVZhbHVlcyBleGlzdHMgYW5kIGhhcyBsZW5ndGhcbiAqICAgb25lVG9NYW55T25DcmVhdGUtPj5vbmVUb01hbnlPbkNyZWF0ZTogY2hlY2sgaWYgYWxsIGVsZW1lbnRzIGhhdmUgc2FtZSB0eXBlXG4gKiAgIG9uZVRvTWFueU9uQ3JlYXRlLT4+b25lVG9NYW55T25DcmVhdGU6IGNyZWF0ZSB1bmlxdWVWYWx1ZXMgc2V0XG4gKlxuICogICBhbHQgYXJyYXlUeXBlIGlzIG5vdCBcIm9iamVjdFwiXG4gKiAgICAgb25lVG9NYW55T25DcmVhdGUtPj5yZXBvc2l0b3J5RnJvbVR5cGVNZXRhZGF0YTogbW9kZWwsIGtleVxuICogICAgIHJlcG9zaXRvcnlGcm9tVHlwZU1ldGFkYXRhLS0+Pm9uZVRvTWFueU9uQ3JlYXRlOiByZXBvXG4gKiAgICAgbG9vcCBmb3IgZWFjaCBpZCBpbiB1bmlxdWVWYWx1ZXNcbiAqICAgICAgIG9uZVRvTWFueU9uQ3JlYXRlLT4+cmVwbzogcmVhZChpZClcbiAqICAgICAgIHJlcG8tLT4+b25lVG9NYW55T25DcmVhdGU6IHJlYWRcbiAqICAgICAgIG9uZVRvTWFueU9uQ3JlYXRlLT4+Y2FjaGVNb2RlbEZvclBvcHVsYXRlOiBjb250ZXh0LCBtb2RlbCwga2V5LCBpZCwgcmVhZFxuICogICAgIGVuZFxuICogICAgIG9uZVRvTWFueU9uQ3JlYXRlLT4+b25lVG9NYW55T25DcmVhdGU6IHNldCBtb2RlbFtrZXldID0gWy4uLnVuaXF1ZVZhbHVlc11cbiAqICAgZWxzZSBhcnJheVR5cGUgaXMgXCJvYmplY3RcIlxuICogICAgIG9uZVRvTWFueU9uQ3JlYXRlLT4+ZmluZFByaW1hcnlLZXk6IHByb3BlcnR5VmFsdWVzWzBdXG4gKiAgICAgZmluZFByaW1hcnlLZXktLT4+b25lVG9NYW55T25DcmVhdGU6IHBrTmFtZVxuICogICAgIG9uZVRvTWFueU9uQ3JlYXRlLT4+b25lVG9NYW55T25DcmVhdGU6IGNyZWF0ZSByZXN1bHQgc2V0XG4gKiAgICAgbG9vcCBmb3IgZWFjaCBtIGluIHByb3BlcnR5VmFsdWVzXG4gKiAgICAgICBvbmVUb01hbnlPbkNyZWF0ZS0+PmNyZWF0ZU9yVXBkYXRlOiBtLCBjb250ZXh0XG4gKiAgICAgICBjcmVhdGVPclVwZGF0ZS0tPj5vbmVUb01hbnlPbkNyZWF0ZTogcmVjb3JkXG4gKiAgICAgICBvbmVUb01hbnlPbkNyZWF0ZS0+PmNhY2hlTW9kZWxGb3JQb3B1bGF0ZTogY29udGV4dCwgbW9kZWwsIGtleSwgcmVjb3JkW3BrTmFtZV0sIHJlY29yZFxuICogICAgICAgb25lVG9NYW55T25DcmVhdGUtPj5vbmVUb01hbnlPbkNyZWF0ZTogYWRkIHJlY29yZFtwa05hbWVdIHRvIHJlc3VsdFxuICogICAgIGVuZFxuICogICAgIG9uZVRvTWFueU9uQ3JlYXRlLT4+b25lVG9NYW55T25DcmVhdGU6IHNldCBtb2RlbFtrZXldID0gWy4uLnJlc3VsdF1cbiAqICAgZW5kXG4gKlxuICogICBvbmVUb01hbnlPbkNyZWF0ZS0tPj5DYWxsZXI6IHZvaWRcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIG9uZVRvTWFueU9uQ3JlYXRlPFxuICBNIGV4dGVuZHMgTW9kZWwsXG4gIFIgZXh0ZW5kcyBSZXBvPE0sIEYsIEM+LFxuICBWIGV4dGVuZHMgUmVsYXRpb25zTWV0YWRhdGEsXG4gIEYgZXh0ZW5kcyBGYWJyaWNDb250cmFjdEZsYWdzLFxuICBDIGV4dGVuZHMgQ29udGV4dDxGPixcbj4oXG4gIHRoaXM6IFIsXG4gIGNvbnRleHQ6IENvbnRleHQ8Rj4sXG4gIGRhdGE6IFYsXG4gIGtleToga2V5b2YgTSxcbiAgbW9kZWw6IE1cbik6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBwcm9wZXJ0eVZhbHVlczogYW55ID0gbW9kZWxba2V5XTtcbiAgaWYgKCFwcm9wZXJ0eVZhbHVlcyB8fCAhcHJvcGVydHlWYWx1ZXMubGVuZ3RoKSByZXR1cm47XG4gIGNvbnN0IGFycmF5VHlwZSA9IHR5cGVvZiBwcm9wZXJ0eVZhbHVlc1swXTtcbiAgaWYgKCFwcm9wZXJ0eVZhbHVlcy5ldmVyeSgoaXRlbTogYW55KSA9PiB0eXBlb2YgaXRlbSA9PT0gYXJyYXlUeXBlKSlcbiAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgIGBJbnZhbGlkIG9wZXJhdGlvbi4gQWxsIGVsZW1lbnRzIG9mIHByb3BlcnR5ICR7a2V5IGFzIHN0cmluZ30gbXVzdCBtYXRjaCB0aGUgc2FtZSB0eXBlLmBcbiAgICApO1xuICBjb25zdCB1bmlxdWVWYWx1ZXMgPSBuZXcgU2V0KFsuLi5wcm9wZXJ0eVZhbHVlc10pO1xuICBpZiAoYXJyYXlUeXBlICE9PSBcIm9iamVjdFwiKSB7XG4gICAgY29uc3QgcmVwbyA9IHJlcG9zaXRvcnlGcm9tVHlwZU1ldGFkYXRhKG1vZGVsLCBrZXksIHRoaXMuYWRhcHRlci5hbGlhcyk7XG4gICAgZm9yIChjb25zdCBpZCBvZiB1bmlxdWVWYWx1ZXMpIHtcbiAgICAgIGNvbnN0IHJlYWQgPSBhd2FpdCByZXBvLnJlYWQoaWQsIGNvbnRleHQpO1xuICAgICAgYXdhaXQgY2FjaGVNb2RlbEZvclBvcHVsYXRlKGNvbnRleHQsIG1vZGVsLCBrZXksIGlkLCByZWFkKTtcbiAgICB9XG4gICAgKG1vZGVsIGFzIGFueSlba2V5XSA9IFsuLi51bmlxdWVWYWx1ZXNdO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IHBrTmFtZSA9IGZpbmRQcmltYXJ5S2V5KHByb3BlcnR5VmFsdWVzWzBdKS5pZDtcblxuICBjb25zdCByZXN1bHQ6IFNldDxzdHJpbmc+ID0gbmV3IFNldCgpO1xuXG4gIGZvciAoY29uc3QgbSBvZiBwcm9wZXJ0eVZhbHVlcykge1xuICAgIGNvbnN0IHJlY29yZCA9IGF3YWl0IGNyZWF0ZU9yVXBkYXRlKG0sIGNvbnRleHQsIHRoaXMuYWRhcHRlci5hbGlhcyk7XG4gICAgYXdhaXQgY2FjaGVNb2RlbEZvclBvcHVsYXRlKGNvbnRleHQsIG1vZGVsLCBrZXksIHJlY29yZFtwa05hbWVdLCByZWNvcmQpO1xuICAgIHJlc3VsdC5hZGQocmVjb3JkW3BrTmFtZV0pO1xuICB9XG5cbiAgKG1vZGVsIGFzIGFueSlba2V5XSA9IFsuLi5yZXN1bHRdO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBIYW5kbGVzIG9uZS10by1tYW55IHJlbGF0aW9uc2hpcCBkZWxldGlvblxuICogQHN1bW1hcnkgUHJvY2Vzc2VzIGEgb25lLXRvLW1hbnkgcmVsYXRpb25zaGlwIHdoZW4gZGVsZXRpbmcgYSBtb2RlbCwgZGVsZXRpbmcgYWxsIHJlbGF0ZWQgbW9kZWxzIGlmIGNhc2NhZGUgZGVsZXRlIGlzIGVuYWJsZWRcbiAqIEB0ZW1wbGF0ZSBNIC0gVGhlIG1vZGVsIHR5cGUgZXh0ZW5kaW5nIE1vZGVsXG4gKiBAdGVtcGxhdGUgUiAtIFRoZSByZXBvc2l0b3J5IHR5cGUgZXh0ZW5kaW5nIFJlcG88TSwgRiwgQz5cbiAqIEB0ZW1wbGF0ZSBWIC0gVGhlIHJlbGF0aW9ucyBtZXRhZGF0YSB0eXBlIGV4dGVuZGluZyBSZWxhdGlvbnNNZXRhZGF0YVxuICogQHRlbXBsYXRlIEYgLSBUaGUgcmVwb3NpdG9yeSBmbGFncyB0eXBlXG4gKiBAdGVtcGxhdGUgQyAtIFRoZSBjb250ZXh0IHR5cGUgZXh0ZW5kaW5nIENvbnRleHQ8Rj5cbiAqIEBwYXJhbSB7Un0gdGhpcyAtIFRoZSByZXBvc2l0b3J5IGluc3RhbmNlXG4gKiBAcGFyYW0ge0NvbnRleHQ8Rj59IGNvbnRleHQgLSBUaGUgY29udGV4dCBmb3IgdGhlIG9wZXJhdGlvblxuICogQHBhcmFtIHtWfSBkYXRhIC0gVGhlIHJlbGF0aW9ucyBtZXRhZGF0YVxuICogQHBhcmFtIGtleSAtIFRoZSBwcm9wZXJ0eSBrZXkgb2YgdGhlIHJlbGF0aW9uc2hpcFxuICogQHBhcmFtIHtNfSBtb2RlbCAtIFRoZSBtb2RlbCBpbnN0YW5jZVxuICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgb3BlcmF0aW9uIGlzIGNvbXBsZXRlXG4gKiBAZnVuY3Rpb24gb25lVG9NYW55T25EZWxldGVcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Y29yZVxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDYWxsZXJcbiAqICAgcGFydGljaXBhbnQgb25lVG9NYW55T25EZWxldGVcbiAqICAgcGFydGljaXBhbnQgUmVwb3NpdG9yeVxuICogICBwYXJ0aWNpcGFudCByZXBvc2l0b3J5RnJvbVR5cGVNZXRhZGF0YVxuICogICBwYXJ0aWNpcGFudCBjYWNoZU1vZGVsRm9yUG9wdWxhdGVcbiAqXG4gKiAgIENhbGxlci0+Pm9uZVRvTWFueU9uRGVsZXRlOiB0aGlzLCBjb250ZXh0LCBkYXRhLCBrZXksIG1vZGVsXG4gKiAgIG9uZVRvTWFueU9uRGVsZXRlLT4+b25lVG9NYW55T25EZWxldGU6IGNoZWNrIGlmIGNhc2NhZGUuZGVsZXRlIGlzIENBU0NBREVcbiAqICAgb25lVG9NYW55T25EZWxldGUtPj5vbmVUb01hbnlPbkRlbGV0ZTogY2hlY2sgaWYgdmFsdWVzIGV4aXN0cyBhbmQgaGFzIGxlbmd0aFxuICogICBvbmVUb01hbnlPbkRlbGV0ZS0+Pm9uZVRvTWFueU9uRGVsZXRlOiBjaGVjayBpZiBhbGwgZWxlbWVudHMgaGF2ZSBzYW1lIHR5cGVcbiAqXG4gKiAgIGFsdCBpc0luc3RhbnRpYXRlZCAoYXJyYXlUeXBlIGlzIFwib2JqZWN0XCIpXG4gKiAgICAgb25lVG9NYW55T25EZWxldGUtPj5SZXBvc2l0b3J5OiBmb3JNb2RlbCh2YWx1ZXNbMF0pXG4gKiAgICAgUmVwb3NpdG9yeS0tPj5vbmVUb01hbnlPbkRlbGV0ZTogcmVwb1xuICogICBlbHNlIG5vdCBpbnN0YW50aWF0ZWRcbiAqICAgICBvbmVUb01hbnlPbkRlbGV0ZS0+PnJlcG9zaXRvcnlGcm9tVHlwZU1ldGFkYXRhOiBtb2RlbCwga2V5XG4gKiAgICAgcmVwb3NpdG9yeUZyb21UeXBlTWV0YWRhdGEtLT4+b25lVG9NYW55T25EZWxldGU6IHJlcG9cbiAqICAgZW5kXG4gKlxuICogICBvbmVUb01hbnlPbkRlbGV0ZS0+Pm9uZVRvTWFueU9uRGVsZXRlOiBjcmVhdGUgdW5pcXVlVmFsdWVzIHNldFxuICpcbiAqICAgbG9vcCBmb3IgZWFjaCBpZCBpbiB1bmlxdWVWYWx1ZXNcbiAqICAgICBvbmVUb01hbnlPbkRlbGV0ZS0+PnJlcG86IGRlbGV0ZShpZCwgY29udGV4dClcbiAqICAgICByZXBvLS0+Pm9uZVRvTWFueU9uRGVsZXRlOiBkZWxldGVkXG4gKiAgICAgb25lVG9NYW55T25EZWxldGUtPj5jYWNoZU1vZGVsRm9yUG9wdWxhdGU6IGNvbnRleHQsIG1vZGVsLCBrZXksIGlkLCBkZWxldGVkXG4gKiAgIGVuZFxuICpcbiAqICAgb25lVG9NYW55T25EZWxldGUtPj5vbmVUb01hbnlPbkRlbGV0ZTogc2V0IG1vZGVsW2tleV0gPSBbLi4udW5pcXVlVmFsdWVzXVxuICogICBvbmVUb01hbnlPbkRlbGV0ZS0tPj5DYWxsZXI6IHZvaWRcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIG9uZVRvTWFueU9uRGVsZXRlPFxuICBNIGV4dGVuZHMgTW9kZWwsXG4gIFIgZXh0ZW5kcyBSZXBvPE0sIEYsIEM+LFxuICBWIGV4dGVuZHMgUmVsYXRpb25zTWV0YWRhdGEsXG4gIEYgZXh0ZW5kcyBGYWJyaWNDb250cmFjdEZsYWdzLFxuICBDIGV4dGVuZHMgQ29udGV4dDxGPixcbj4oXG4gIHRoaXM6IFIsXG4gIGNvbnRleHQ6IENvbnRleHQ8Rj4sXG4gIGRhdGE6IFYsXG4gIGtleToga2V5b2YgTSxcbiAgbW9kZWw6IE1cbik6IFByb21pc2U8dm9pZD4ge1xuICBpZiAoZGF0YS5jYXNjYWRlLmRlbGV0ZSAhPT0gQ2FzY2FkZS5DQVNDQURFKSByZXR1cm47XG4gIGNvbnN0IHZhbHVlcyA9IG1vZGVsW2tleV0gYXMgYW55O1xuICBpZiAoIXZhbHVlcyB8fCAhdmFsdWVzLmxlbmd0aCkgcmV0dXJuO1xuICBjb25zdCBhcnJheVR5cGUgPSB0eXBlb2YgdmFsdWVzWzBdO1xuICBjb25zdCBhcmVBbGxTYW1lVHlwZSA9IHZhbHVlcy5ldmVyeSgoaXRlbTogYW55KSA9PiB0eXBlb2YgaXRlbSA9PT0gYXJyYXlUeXBlKTtcbiAgaWYgKCFhcmVBbGxTYW1lVHlwZSlcbiAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgIGBJbnZhbGlkIG9wZXJhdGlvbi4gQWxsIGVsZW1lbnRzIG9mIHByb3BlcnR5ICR7a2V5IGFzIHN0cmluZ30gbXVzdCBtYXRjaCB0aGUgc2FtZSB0eXBlLmBcbiAgICApO1xuICBjb25zdCBpc0luc3RhbnRpYXRlZCA9IGFycmF5VHlwZSA9PT0gXCJvYmplY3RcIjtcbiAgY29uc3QgcmVwbyA9IGlzSW5zdGFudGlhdGVkXG4gICAgPyBSZXBvc2l0b3J5LmZvck1vZGVsKHZhbHVlc1swXSwgdGhpcy5hZGFwdGVyLmFsaWFzKVxuICAgIDogcmVwb3NpdG9yeUZyb21UeXBlTWV0YWRhdGEobW9kZWwsIGtleSwgdGhpcy5hZGFwdGVyLmFsaWFzKTtcblxuICBjb25zdCB1bmlxdWVWYWx1ZXMgPSBuZXcgU2V0KFtcbiAgICAuLi4oaXNJbnN0YW50aWF0ZWRcbiAgICAgID8gdmFsdWVzLm1hcCgodjogUmVjb3JkPHN0cmluZywgYW55PikgPT4gdltyZXBvLnBrIGFzIHN0cmluZ10pXG4gICAgICA6IHZhbHVlcyksXG4gIF0pO1xuXG4gIGZvciAoY29uc3QgaWQgb2YgdW5pcXVlVmFsdWVzLnZhbHVlcygpKSB7XG4gICAgY29uc3QgZGVsZXRlZCA9IGF3YWl0IHJlcG8uZGVsZXRlKGlkLCBjb250ZXh0KTtcbiAgICBhd2FpdCBjYWNoZU1vZGVsRm9yUG9wdWxhdGUoY29udGV4dCwgbW9kZWwsIGtleSwgaWQsIGRlbGV0ZWQpO1xuICB9XG4gIChtb2RlbCBhcyBhbnkpW2tleV0gPSBbLi4udW5pcXVlVmFsdWVzXTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUG9wdWxhdGVzIGEgbW9kZWwncyByZWxhdGlvbnNoaXBcbiAqIEBzdW1tYXJ5IFJldHJpZXZlcyBhbmQgYXR0YWNoZXMgcmVsYXRlZCBtb2RlbHMgdG8gYSBtb2RlbCdzIHJlbGF0aW9uc2hpcCBwcm9wZXJ0eVxuICogQHRlbXBsYXRlIE0gLSBUaGUgbW9kZWwgdHlwZSBleHRlbmRpbmcgTW9kZWxcbiAqIEB0ZW1wbGF0ZSBSIC0gVGhlIHJlcG9zaXRvcnkgdHlwZSBleHRlbmRpbmcgUmVwbzxNLCBGLCBDPlxuICogQHRlbXBsYXRlIFYgLSBUaGUgcmVsYXRpb25zIG1ldGFkYXRhIHR5cGUgZXh0ZW5kaW5nIFJlbGF0aW9uc01ldGFkYXRhXG4gKiBAdGVtcGxhdGUgRiAtIFRoZSByZXBvc2l0b3J5IGZsYWdzIHR5cGVcbiAqIEB0ZW1wbGF0ZSBDIC0gVGhlIGNvbnRleHQgdHlwZSBleHRlbmRpbmcgQ29udGV4dDxGPlxuICogQHBhcmFtIHtSfSB0aGlzIC0gVGhlIHJlcG9zaXRvcnkgaW5zdGFuY2VcbiAqIEBwYXJhbSB7Q29udGV4dDxGPn0gY29udGV4dCAtIFRoZSBjb250ZXh0IGZvciB0aGUgb3BlcmF0aW9uXG4gKiBAcGFyYW0ge1Z9IGRhdGEgLSBUaGUgcmVsYXRpb25zIG1ldGFkYXRhXG4gKiBAcGFyYW0ga2V5IC0gVGhlIHByb3BlcnR5IGtleSBvZiB0aGUgcmVsYXRpb25zaGlwXG4gKiBAcGFyYW0ge019IG1vZGVsIC0gVGhlIG1vZGVsIGluc3RhbmNlXG4gKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBvcGVyYXRpb24gaXMgY29tcGxldGVcbiAqIEBmdW5jdGlvbiBwb3B1bGF0ZVxuICogQG1lbWJlck9mIG1vZHVsZTpjb3JlXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENhbGxlclxuICogICBwYXJ0aWNpcGFudCBwb3B1bGF0ZVxuICogICBwYXJ0aWNpcGFudCBmZXRjaFBvcHVsYXRlVmFsdWVzXG4gKiAgIHBhcnRpY2lwYW50IGdldFBvcHVsYXRlS2V5XG4gKiAgIHBhcnRpY2lwYW50IENvbnRleHRcbiAqICAgcGFydGljaXBhbnQgcmVwb3NpdG9yeUZyb21UeXBlTWV0YWRhdGFcbiAqXG4gKiAgIENhbGxlci0+PnBvcHVsYXRlOiB0aGlzLCBjb250ZXh0LCBkYXRhLCBrZXksIG1vZGVsXG4gKiAgIHBvcHVsYXRlLT4+cG9wdWxhdGU6IGNoZWNrIGlmIGRhdGEucG9wdWxhdGUgaXMgdHJ1ZVxuICogICBwb3B1bGF0ZS0+PnBvcHVsYXRlOiBnZXQgbmVzdGVkIHZhbHVlIGFuZCBjaGVjayBpZiBpdCBleGlzdHNcbiAqXG4gKiAgIHBvcHVsYXRlLT4+ZmV0Y2hQb3B1bGF0ZVZhbHVlczogY29udGV4dCwgbW9kZWwsIGtleSwgaXNBcnIgPyBuZXN0ZWQgOiBbbmVzdGVkXVxuICpcbiAqICAgZmV0Y2hQb3B1bGF0ZVZhbHVlcy0+PmZldGNoUG9wdWxhdGVWYWx1ZXM6IGluaXRpYWxpemUgdmFyaWFibGVzXG4gKlxuICogICBsb29wIGZvciBlYWNoIHByb0tleVZhbHVlIGluIHByb3BLZXlWYWx1ZXNcbiAqICAgICBmZXRjaFBvcHVsYXRlVmFsdWVzLT4+Z2V0UG9wdWxhdGVLZXk6IG1vZGVsLmNvbnN0cnVjdG9yLm5hbWUsIHByb3BOYW1lLCBwcm9LZXlWYWx1ZVxuICogICAgIGdldFBvcHVsYXRlS2V5LS0+PmZldGNoUG9wdWxhdGVWYWx1ZXM6IGNhY2hlS2V5XG4gKlxuICogICAgIGFsdCB0cnkgdG8gZ2V0IGZyb20gY2FjaGVcbiAqICAgICAgIGZldGNoUG9wdWxhdGVWYWx1ZXMtPj5Db250ZXh0OiBnZXQoY2FjaGVLZXkpXG4gKiAgICAgICBDb250ZXh0LS0+PmZldGNoUG9wdWxhdGVWYWx1ZXM6IHZhbFxuICogICAgIGVsc2UgY2F0Y2ggZXJyb3JcbiAqICAgICAgIGZldGNoUG9wdWxhdGVWYWx1ZXMtPj5yZXBvc2l0b3J5RnJvbVR5cGVNZXRhZGF0YTogbW9kZWwsIHByb3BOYW1lXG4gKiAgICAgICByZXBvc2l0b3J5RnJvbVR5cGVNZXRhZGF0YS0tPj5mZXRjaFBvcHVsYXRlVmFsdWVzOiByZXBvXG4gKiAgICAgICBmZXRjaFBvcHVsYXRlVmFsdWVzLT4+cmVwbzogcmVhZChwcm9LZXlWYWx1ZSlcbiAqICAgICAgIHJlcG8tLT4+ZmV0Y2hQb3B1bGF0ZVZhbHVlczogdmFsXG4gKiAgICAgZW5kXG4gKlxuICogICAgIGZldGNoUG9wdWxhdGVWYWx1ZXMtPj5mZXRjaFBvcHVsYXRlVmFsdWVzOiBhZGQgdmFsIHRvIHJlc3VsdHNcbiAqICAgZW5kXG4gKlxuICogICBmZXRjaFBvcHVsYXRlVmFsdWVzLS0+PnBvcHVsYXRlOiByZXN1bHRzXG4gKiAgIHBvcHVsYXRlLT4+cG9wdWxhdGU6IHNldCBtb2RlbFtrZXldID0gaXNBcnIgPyByZXMgOiByZXNbMF1cbiAqICAgcG9wdWxhdGUtLT4+Q2FsbGVyOiB2b2lkXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBwb3B1bGF0ZTxcbiAgTSBleHRlbmRzIE1vZGVsLFxuICBSIGV4dGVuZHMgUmVwbzxNLCBGLCBDPixcbiAgViBleHRlbmRzIFJlbGF0aW9uc01ldGFkYXRhLFxuICBGIGV4dGVuZHMgRmFicmljQ29udHJhY3RGbGFncyxcbiAgQyBleHRlbmRzIENvbnRleHQ8Rj4sXG4+KFxuICB0aGlzOiBSLFxuICBjb250ZXh0OiBDb250ZXh0PEY+LFxuICBkYXRhOiBWLFxuICBrZXk6IGtleW9mIE0sXG4gIG1vZGVsOiBNXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgaWYgKCFkYXRhLnBvcHVsYXRlKSByZXR1cm47XG4gIGNvbnN0IG5lc3RlZDogYW55ID0gbW9kZWxba2V5XTtcbiAgY29uc3QgaXNBcnIgPSBBcnJheS5pc0FycmF5KG5lc3RlZCk7XG4gIGlmICh0eXBlb2YgbmVzdGVkID09PSBcInVuZGVmaW5lZFwiIHx8IChpc0FyciAmJiBuZXN0ZWQubGVuZ3RoID09PSAwKSkgcmV0dXJuO1xuXG4gIGFzeW5jIGZ1bmN0aW9uIGZldGNoUG9wdWxhdGVWYWx1ZXMoXG4gICAgYzogQ29udGV4dDxGPixcbiAgICBtb2RlbDogTSxcbiAgICBwcm9wTmFtZTogc3RyaW5nLFxuICAgIHByb3BLZXlWYWx1ZXM6IGFueVtdLFxuICAgIGFsaWFzPzogc3RyaW5nXG4gICkge1xuICAgIGxldCBjYWNoZUtleTogc3RyaW5nO1xuICAgIGxldCB2YWw6IGFueTtcbiAgICBjb25zdCByZXN1bHRzOiBNW10gPSBbXTtcbiAgICBmb3IgKGNvbnN0IHByb0tleVZhbHVlIG9mIHByb3BLZXlWYWx1ZXMpIHtcbiAgICAgIGNhY2hlS2V5ID0gZ2V0UG9wdWxhdGVLZXkobW9kZWwuY29uc3RydWN0b3IubmFtZSwgcHJvcE5hbWUsIHByb0tleVZhbHVlKTtcbiAgICAgIHRyeSB7XG4gICAgICAgIHZhbCA9IGF3YWl0IGMuZ2V0KGNhY2hlS2V5IGFzIGFueSk7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgICBjb25zdCByZXBvID0gcmVwb3NpdG9yeUZyb21UeXBlTWV0YWRhdGEobW9kZWwsIHByb3BOYW1lLCBhbGlhcyk7XG4gICAgICAgIGlmICghcmVwbykgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXCJDb3VsZCBub3QgZmluZCByZXBvXCIpO1xuICAgICAgICB2YWwgPSBhd2FpdCByZXBvLnJlYWQocHJvS2V5VmFsdWUsIGNvbnRleHQpO1xuICAgICAgfVxuICAgICAgcmVzdWx0cy5wdXNoKHZhbCk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHRzO1xuICB9XG4gIGNvbnN0IHJlcyA9IGF3YWl0IGZldGNoUG9wdWxhdGVWYWx1ZXMoXG4gICAgY29udGV4dCxcbiAgICBtb2RlbCxcbiAgICBrZXkgYXMgc3RyaW5nLFxuICAgIGlzQXJyID8gbmVzdGVkIDogW25lc3RlZF0sXG4gICAgdGhpcy5hZGFwdGVyLmFsaWFzXG4gICk7XG4gIChtb2RlbCBhcyBhbnkpW2tleV0gPSBpc0FyciA/IHJlcyA6IHJlc1swXTtcbn1cbiJdfQ==