@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,381 @@
1
+ import { CouchDBAdapter, type MangoQuery } from "@decaf-ts/for-couchdb";
2
+ import { Client } from "@grpc/grpc-js";
3
+ import { type Constructor, Model, type Serializer } from "@decaf-ts/decorator-validation";
4
+ import { Logger } from "@decaf-ts/logging";
5
+ import { FabricFlags, PeerConfig } from "../shared/types";
6
+ import { Gateway, Network, Contract as Contrakt } from "@hyperledger/fabric-gateway";
7
+ import { BaseError, Context } from "@decaf-ts/db-decorators";
8
+ import { Adapter, Dispatch, Repository } from "@decaf-ts/core";
9
+ /**
10
+ * @description Adapter for interacting with Hyperledger Fabric networks
11
+ * @summary The FabricAdapter extends CouchDBAdapter to provide a seamless interface for interacting with Hyperledger Fabric networks.
12
+ * It handles connection management, transaction submission, and CRUD operations against Fabric chaincode.
13
+ * @template PeerConfig - Configuration type for connecting to a Fabric peer
14
+ * @template FabricFlags - Flags specific to Fabric operations
15
+ * @template Context<FabricFlags> - Context type containing Fabric-specific flags
16
+ * @param config - Configuration for connecting to a Fabric peer
17
+ * @param alias - Optional alias for the adapter instance
18
+ * @class FabricClientAdapter
19
+ * @example
20
+ * ```typescript
21
+ * // Create a new FabricAdapter instance
22
+ * const config: PeerConfig = {
23
+ * mspId: 'Org1MSP',
24
+ * peerEndpoint: 'localhost:7051',
25
+ * channelName: 'mychannel',
26
+ * chaincodeName: 'mycc',
27
+ * contractName: 'mycontract',
28
+ * tlsCertPath: '/path/to/tls/cert',
29
+ * certDirectoryPath: '/path/to/cert/dir',
30
+ * keyDirectoryPath: '/path/to/key/dir'
31
+ * };
32
+ *
33
+ * const adapter = new FabricAdapter(config, 'org1-adapter');
34
+ *
35
+ * // Use the adapter to interact with the Fabric network
36
+ * const result = await adapter.read('users', 'user1', mySerializer);
37
+ * ```
38
+ * @mermaid
39
+ * sequenceDiagram
40
+ * participant Client
41
+ * participant FabricAdapter
42
+ * participant Gateway
43
+ * participant Network
44
+ * participant Contract
45
+ * participant Chaincode
46
+ *
47
+ * Client->>FabricAdapter: create(tableName, id, model, transient, serializer)
48
+ * FabricAdapter->>FabricAdapter: submitTransaction(OperationKeys.CREATE, [serializedModel], transient)
49
+ * FabricAdapter->>Gateway: connect()
50
+ * Gateway->>Network: getNetwork(channelName)
51
+ * Network->>Contract: getContract(chaincodeName, contractName)
52
+ * FabricAdapter->>Contract: submit(api, proposalOptions)
53
+ * Contract->>Chaincode: invoke
54
+ * Chaincode-->>Contract: response
55
+ * Contract-->>FabricAdapter: result
56
+ * FabricAdapter->>FabricAdapter: decode(result)
57
+ * FabricAdapter->>FabricAdapter: serializer.deserialize(decodedResult)
58
+ * FabricAdapter-->>Client: deserializedResult
59
+ */
60
+ export declare class FabricClientAdapter extends CouchDBAdapter<PeerConfig, Client, FabricFlags, Context<FabricFlags>> {
61
+ /**
62
+ * @description Static text decoder for converting Uint8Array to string
63
+ */
64
+ private static decoder;
65
+ private static serializer;
66
+ /**
67
+ * @description Static logger instance for the FabricAdapter class
68
+ */
69
+ private static log;
70
+ /**
71
+ * @description Gets the logger instance for this adapter
72
+ * @summary Returns the static logger instance for the FabricAdapter class
73
+ * @return {Logger} The logger instance
74
+ */
75
+ protected get log(): Logger;
76
+ protected readonly serializer: Serializer<any>;
77
+ /**
78
+ * @description Creates a new FabricAdapter instance
79
+ * @summary Initializes a new adapter for interacting with a Hyperledger Fabric network
80
+ * @param {PeerConfig} config - Configuration for connecting to a Fabric peer
81
+ * @param {string} [alias] - Optional alias for the adapter instance
82
+ */
83
+ constructor(config: PeerConfig, alias?: string);
84
+ /**
85
+ * @description Decodes a Uint8Array to a string
86
+ * @summary Converts binary data received from Fabric to a string using UTF-8 encoding
87
+ * @param {Uint8Array} data - The binary data to decode
88
+ * @return {string} The decoded string
89
+ */
90
+ decode(data: Uint8Array): string;
91
+ repository<M extends Model<true | false>>(): Constructor<Repository<M, MangoQuery, Adapter<PeerConfig, Client, MangoQuery, FabricFlags, Context<FabricFlags>>, FabricFlags, Context<FabricFlags>>>;
92
+ /**
93
+ * @description Creates multiple records in a single transaction
94
+ * @summary Submits a transaction to create multiple records in the Fabric ledger
95
+ * @param {string} tableName - The name of the table/collection
96
+ * @param {string[] | number[]} ids - Array of record identifiers
97
+ * @param {Array<Record<string, any>>} models - Array of record data
98
+ * @param {Record<string, any>} transient - Transient data for the transaction
99
+ * @return {Promise<Array<Record<string, any>>>} Promise resolving to the created records
100
+ */
101
+ createAll(tableName: string, ids: string[] | number[], models: Record<string, any>[], transient: Record<string, any>): Promise<Record<string, any>[]>;
102
+ /**
103
+ * @description Reads multiple records in a single transaction
104
+ * @summary Submits a transaction to read multiple records from the Fabric ledger
105
+ * @param {string} tableName - The name of the table/collection
106
+ * @param {string[] | number[]} ids - Array of record identifiers to read
107
+ * @return {Promise<Array<Record<string, any>>>} Promise resolving to the retrieved records
108
+ */
109
+ readAll(tableName: string, ids: string[] | number[]): Promise<Record<string, any>[]>;
110
+ /**
111
+ * @description Updates multiple records in a single transaction
112
+ * @summary Submits a transaction to update multiple records in the Fabric ledger
113
+ * @param {string} tableName - The name of the table/collection
114
+ * @param {string[] | number[]} ids - Array of record identifiers
115
+ * @param {Array<Record<string, any>>} models - Array of updated record data
116
+ * @param {Record<string, any>} transient - Transient data for the transaction
117
+ * @return {Promise<Array<Record<string, any>>>} Promise resolving to the updated records
118
+ */
119
+ updateAll(tableName: string, ids: string[] | number[], models: Record<string, any>[], transient: Record<string, any>): Promise<Record<string, any>[]>;
120
+ /**
121
+ * @description Deletes multiple records in a single transaction
122
+ * @summary Submits a transaction to delete multiple records from the Fabric ledger
123
+ * @param {string} tableName - The name of the table/collection
124
+ * @param {Array<string | number | bigint>} ids - Array of record identifiers to delete
125
+ * @param {Serializer<any>} serializer - Serializer for the model data
126
+ * @return {Promise<Array<Record<string, any>>>} Promise resolving to the deleted records
127
+ */
128
+ deleteAll(tableName: string, ids: (string | number | bigint)[]): Promise<Record<string, any>[]>;
129
+ /**
130
+ * @description Prepares a model for persistence
131
+ * @summary Converts a model instance into a format suitable for database storage,
132
+ * handling column mapping and separating transient properties
133
+ * @template M - The model type
134
+ * @param {M} model - The model instance to prepare
135
+ * @param pk - The primary key property name
136
+ * @return The prepared data
137
+ */
138
+ prepare<M extends Model>(model: M, pk: keyof M): {
139
+ record: Record<string, any>;
140
+ id: string;
141
+ transient?: Record<string, any>;
142
+ };
143
+ /**
144
+ * @description Converts database data back into a model instance
145
+ * @summary Reconstructs a model instance from database data, handling column mapping
146
+ * and reattaching transient properties
147
+ * @template M - The model type
148
+ * @param obj - The database record
149
+ * @param {string|Constructor<M>} clazz - The model class or name
150
+ * @param pk - The primary key property name
151
+ * @param {string|number|bigint} id - The primary key value
152
+ * @param [transient] - Transient properties to reattach
153
+ * @return {M} The reconstructed model instance
154
+ */
155
+ revert<M extends Model>(obj: Record<string, any>, clazz: string | Constructor<M>, pk: keyof M, id: string | number | bigint, transient?: Record<string, any>): M;
156
+ /**
157
+ * @description Creates an index for a model
158
+ * @summary This method is not implemented for Fabric and will throw an error
159
+ * @template M - Type extending Model
160
+ * @param {Constructor<M>} models - The model constructor
161
+ * @return {Promise<void>} Promise that will throw an error
162
+ */
163
+ protected index<M>(models: Constructor<M>): Promise<void>;
164
+ /**
165
+ * @description Creates a single record
166
+ * @summary Submits a transaction to create a record in the Fabric ledger
167
+ * @param {string} tableName - The name of the table/collection
168
+ * @param {string | number} id - The record identifier
169
+ * @param {Record<string, any>} model - The record data
170
+ * @param {Record<string, any>} transient - Transient data for the transaction
171
+ * @return {Promise<Record<string, any>>} Promise resolving to the created record
172
+ */
173
+ create(tableName: string, id: string | number, model: Record<string, any>, transient: Record<string, any>): Promise<Record<string, any>>;
174
+ /**
175
+ * @description Reads a single record
176
+ * @summary Evaluates a transaction to read a record from the Fabric ledger
177
+ * @param {string} tableName - The name of the table/collection
178
+ * @param {string | number} id - The record identifier
179
+ * @return {Promise<Record<string, any>>} Promise resolving to the retrieved record
180
+ */
181
+ read(tableName: string, id: string | number): Promise<Record<string, any>>;
182
+ /**
183
+ * @description Updates a single record
184
+ * @summary Submits a transaction to update a record in the Fabric ledger
185
+ * @param {string} tableName - The name of the table/collection
186
+ * @param {string | number} id - The record identifier
187
+ * @param {Record<string, any>} model - The updated record data
188
+ * @param {Record<string, any>} transient - Transient data for the transaction
189
+ * @return {Promise<Record<string, any>>} Promise resolving to the updated record
190
+ */
191
+ update(tableName: string, id: string | number, model: Record<string, any>, transient: Record<string, any>): Promise<Record<string, any>>;
192
+ /**
193
+ * @description Deletes a single record
194
+ * @summary Submits a transaction to delete a record from the Fabric ledger
195
+ * @param {string} tableName - The name of the table/collection
196
+ * @param {string | number} id - The record identifier to delete
197
+ * @return {Promise<Record<string, any>>} Promise resolving to the deleted record
198
+ */
199
+ delete(tableName: string, id: string | number): Promise<Record<string, any>>;
200
+ /**
201
+ * @description Executes a raw query against the Fabric ledger
202
+ * @summary Evaluates a transaction to perform a query using Mango Query syntax
203
+ * @template V - The return type
204
+ * @param {MangoQuery} rawInput - The Mango Query to execute
205
+ * @param {boolean} process - Whether to process the result
206
+ * @return {Promise<V>} Promise resolving to the query result
207
+ * @mermaid
208
+ * sequenceDiagram
209
+ * participant Client
210
+ * participant FabricAdapter
211
+ * participant Contract
212
+ * participant Chaincode
213
+ *
214
+ * Client->>FabricAdapter: raw(rawInput, process)
215
+ * FabricAdapter->>FabricAdapter: JSON.stringify(rawInput)
216
+ * FabricAdapter->>FabricAdapter: evaluateTransaction("query", [input])
217
+ * FabricAdapter->>Contract: evaluate("query", proposalOptions)
218
+ * Contract->>Chaincode: invoke
219
+ * Chaincode-->>Contract: response
220
+ * Contract-->>FabricAdapter: result
221
+ * FabricAdapter->>FabricAdapter: JSON.parse(decode(result))
222
+ * FabricAdapter->>FabricAdapter: Process result based on type
223
+ * FabricAdapter-->>Client: processed result
224
+ */
225
+ raw<V>(rawInput: MangoQuery, process: boolean): Promise<V>;
226
+ /**
227
+ * @description Gets or creates a gRPC client for the Fabric peer
228
+ * @summary Returns a cached client or creates a new one if none exists
229
+ * @return {Promise<Client>} Promise resolving to the gRPC client
230
+ */
231
+ getClient(): Client;
232
+ /**
233
+ * @description Gets a Gateway instance for the Fabric network
234
+ * @summary Creates a new Gateway instance using the current client
235
+ * @return {Promise<Gateway>} Promise resolving to the Gateway instance
236
+ */
237
+ protected Gateway(): Promise<Gateway>;
238
+ /**
239
+ * @description Gets a Contract instance for the Fabric chaincode
240
+ * @summary Creates a new Contract instance using the current Gateway
241
+ * @return {Promise<Contrakt>} Promise resolving to the Contract instance
242
+ */
243
+ protected Contract(): Promise<Contrakt>;
244
+ /**
245
+ * @description Executes a transaction on the Fabric network
246
+ * @summary Submits or evaluates a transaction on the Fabric chaincode
247
+ * @param {string} api - The chaincode function to call
248
+ * @param {boolean} submit - Whether to submit (true) or evaluate (false) the transaction
249
+ * @param {any[]} [args] - Arguments to pass to the chaincode function
250
+ * @param {Record<string, string>} [transientData] - Transient data for the transaction
251
+ * @param {Array<string>} [endorsingOrganizations] - Organizations that must endorse the transaction
252
+ * @return {Promise<Uint8Array>} Promise resolving to the transaction result
253
+ * @mermaid
254
+ * sequenceDiagram
255
+ * participant FabricAdapter
256
+ * participant Gateway
257
+ * participant Contract
258
+ * participant Chaincode
259
+ *
260
+ * FabricAdapter->>Gateway: connect()
261
+ * FabricAdapter->>Contract: getContract()
262
+ * alt submit transaction
263
+ * FabricAdapter->>Contract: submit(api, proposalOptions)
264
+ * else evaluate transaction
265
+ * FabricAdapter->>Contract: evaluate(api, proposalOptions)
266
+ * end
267
+ * Contract->>Chaincode: invoke
268
+ * Chaincode-->>Contract: response
269
+ * Contract-->>FabricAdapter: result
270
+ * FabricAdapter->>Gateway: close()
271
+ */
272
+ protected transaction(api: string, submit?: boolean, args?: any[], transientData?: Record<string, string>, endorsingOrganizations?: Array<string>): Promise<Uint8Array>;
273
+ /**
274
+ * @description Parses an error into a BaseError
275
+ * @summary Converts any error into a standardized BaseError
276
+ * @param {Error | string} err - The error to parse
277
+ * @param {string} [reason] - Optional reason for the error
278
+ * @return {BaseError} The parsed error
279
+ */
280
+ parseError(err: Error | string, reason?: string): BaseError;
281
+ /**
282
+ * @description Submits a transaction to the Fabric network
283
+ * @summary Executes a transaction that modifies the ledger state
284
+ * @param {string} api - The chaincode function to call
285
+ * @param {any[]} [args] - Arguments to pass to the chaincode function
286
+ * @param {Record<string, string>} [transientData] - Transient data for the transaction
287
+ * @param {Array<string>} [endorsingOrganizations] - Organizations that must endorse the transaction
288
+ * @return {Promise<Uint8Array>} Promise resolving to the transaction result
289
+ */
290
+ submitTransaction(api: string, args?: any[], transientData?: Record<string, string>, endorsingOrganizations?: Array<string>): Promise<Uint8Array>;
291
+ /**
292
+ * @description Evaluates a transaction on the Fabric network
293
+ * @summary Executes a transaction that does not modify the ledger state
294
+ * @param {string} api - The chaincode function to call
295
+ * @param {any[]} [args] - Arguments to pass to the chaincode function
296
+ * @param {Record<string, string>} [transientData] - Transient data for the transaction
297
+ * @param {Array<string>} [endorsingOrganizations] - Organizations that must endorse the transaction
298
+ * @return {Promise<Uint8Array>} Promise resolving to the transaction result
299
+ */
300
+ evaluateTransaction(api: string, args?: any[], transientData?: Record<string, string>, endorsingOrganizations?: Array<string>): Promise<Uint8Array>;
301
+ /**
302
+ * @description Closes the connection to the Fabric network
303
+ * @summary Closes the gRPC client if it exists
304
+ * @return {Promise<void>} Promise that resolves when the client is closed
305
+ */
306
+ close(): Promise<void>;
307
+ /**
308
+ * @description Gets a Contract instance from a Gateway
309
+ * @summary Retrieves a chaincode contract from the specified network
310
+ * @param {Gateway} gateway - The Gateway instance
311
+ * @param {PeerConfig} config - The peer configuration
312
+ * @return {Contrakt} The Contract instance
313
+ */
314
+ static getContract(gateway: Gateway, config: PeerConfig): Contrakt;
315
+ /**
316
+ * @description Gets a Network instance from a Gateway
317
+ * @summary Connects to a specific channel on the Fabric network
318
+ * @param {Gateway} gateway - The Gateway instance
319
+ * @param {string} channelName - The name of the channel to connect to
320
+ * @return {Network} The Network instance
321
+ */
322
+ static getNetwork(gateway: Gateway, channelName: string): Network;
323
+ /**
324
+ * @description Gets a Gateway instance for connecting to the Fabric network
325
+ * @summary Creates a Gateway using the provided configuration and client
326
+ * @param {PeerConfig} config - The peer configuration
327
+ * @param {Client} [client] - Optional gRPC client, will be created if not provided
328
+ * @return {Promise<Gateway>} Promise resolving to the Gateway instance
329
+ */
330
+ static getGateway(config: PeerConfig, client?: Client): Promise<Gateway>;
331
+ /**
332
+ * @description Creates a gRPC client for connecting to a Fabric peer
333
+ * @summary Initializes a client with TLS credentials for secure communication
334
+ * @param {PeerConfig} config - The peer configuration
335
+ * @return {Client} Promise resolving to the gRPC client
336
+ */
337
+ static getClient(config: PeerConfig): Client;
338
+ /**
339
+ * @description Establishes a connection to the Fabric network
340
+ * @summary Creates a Gateway connection with identity and signer
341
+ * @param {Client} client - The gRPC client
342
+ * @param {PeerConfig} config - The peer configuration
343
+ * @return {Promise<Gateway>} Promise resolving to the connected Gateway
344
+ * @mermaid
345
+ * sequenceDiagram
346
+ * participant Caller
347
+ * participant FabricAdapter
348
+ * participant Identity
349
+ * participant Signer
350
+ * participant Gateway
351
+ *
352
+ * Caller->>FabricAdapter: getConnection(client, config)
353
+ * FabricAdapter->>Identity: getIdentity(mspId, certDirectoryPath)
354
+ * Identity-->>FabricAdapter: identity
355
+ * FabricAdapter->>Signer: getSigner(keyDirectoryPath)
356
+ * Signer-->>FabricAdapter: signer
357
+ * FabricAdapter->>FabricAdapter: Create ConnectOptions
358
+ * FabricAdapter->>Gateway: connect(options)
359
+ * Gateway-->>FabricAdapter: gateway
360
+ * FabricAdapter-->>Caller: gateway
361
+ */
362
+ static getConnection(client: Client, config: PeerConfig): Promise<Gateway>;
363
+ /**
364
+ * @description Creates a new Dispatch instance for the Fabric client.
365
+ * @summary This function is responsible for creating a new FabricClientDispatch instance that can be used to interact with the Fabric network.
366
+ * @returns {Dispatch} A new Dispatch instance configured for the Fabric client.
367
+ * @remarks The Dispatch instance is used to encapsulate the logic for interacting with the Fabric network, such as submitting transactions or querying data.
368
+ * @example
369
+ * const fabricDispatch = fabricClientAdapter.Dispatch();
370
+ * fabricDispatch.submitTransaction('createProduct', { name: 'Product A', price: 100 });
371
+ */
372
+ Dispatch(): Dispatch;
373
+ /**
374
+ * @description Parses an error into a BaseError
375
+ * @summary Converts any error into a standardized BaseError using the parent class implementation
376
+ * @param {Error | string} err - The error to parse
377
+ * @param {string} [reason] - Optional reason for the error
378
+ * @return {BaseError} The parsed error
379
+ */
380
+ protected static parseError(err: Error | string, reason?: string): BaseError;
381
+ }
@@ -0,0 +1,186 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FabricClientDispatch = void 0;
4
+ const core_1 = require("@decaf-ts/core");
5
+ const FabricClientAdapter_1 = require("./FabricClientAdapter.cjs");
6
+ const db_decorators_1 = require("@decaf-ts/db-decorators");
7
+ const events_1 = require("./../shared/events.cjs");
8
+ /**
9
+ * @description Event dispatcher for Hyperledger Fabric chaincode events
10
+ * @summary Listens for and processes events emitted by Fabric chaincode, dispatching them to registered observers
11
+ * @template PeerConfig - Configuration type for connecting to a Fabric peer
12
+ * @param client - gRPC client for connecting to the Fabric network
13
+ * @class FabricClientDispatch
14
+ * @example
15
+ * ```typescript
16
+ * // Create a new FabricDispatch instance
17
+ * const client = await FabricAdapter.getClient(peerConfig);
18
+ * const dispatch = new FabricDispatch(client);
19
+ *
20
+ * // Configure the dispatch with peer configuration
21
+ * dispatch.configure(peerConfig);
22
+ *
23
+ * // Register an observer for a specific table and event
24
+ * dispatch.observe('users', 'create', (id) => {
25
+ * console.log(`User created: ${id}`);
26
+ * });
27
+ *
28
+ * // Start listening for events
29
+ * await dispatch.start();
30
+ * ```
31
+ * @mermaid
32
+ * sequenceDiagram
33
+ * participant Client
34
+ * participant FabricDispatch
35
+ * participant Gateway
36
+ * participant Network
37
+ * participant Chaincode
38
+ *
39
+ * Client->>FabricDispatch: new FabricDispatch(client)
40
+ * Client->>FabricDispatch: configure(peerConfig)
41
+ * Client->>FabricDispatch: observe(table, event, callback)
42
+ * Client->>FabricDispatch: start()
43
+ * FabricDispatch->>FabricDispatch: initialize()
44
+ * FabricDispatch->>Gateway: getGateway(config, client)
45
+ * Gateway->>Network: getNetwork(channel)
46
+ * Network->>Network: getChaincodeEvents(chaincodeName)
47
+ * FabricDispatch->>FabricDispatch: handleEvents()
48
+ * loop For each event
49
+ * Chaincode-->>FabricDispatch: ChaincodeEvent
50
+ * FabricDispatch->>FabricDispatch: parseEventName(eventName)
51
+ * FabricDispatch->>FabricDispatch: parsePayload(payload)
52
+ * FabricDispatch->>FabricDispatch: updateObservers(table, event, id)
53
+ * FabricDispatch-->>Client: callback(id)
54
+ * end
55
+ */
56
+ class FabricClientDispatch extends core_1.Dispatch {
57
+ /**
58
+ * @description Creates a new FabricDispatch instance
59
+ * @summary Initializes a dispatcher for Fabric chaincode events
60
+ * @param {Client} client - gRPC client for connecting to the Fabric network
61
+ */
62
+ constructor(client) {
63
+ super();
64
+ this.client = client;
65
+ /**
66
+ * @description Text decoder for converting event payloads from bytes to strings
67
+ */
68
+ this.decoder = new TextDecoder("utf8");
69
+ }
70
+ /**
71
+ * @description Closes the event listening connection
72
+ * @summary Stops listening for chaincode events and releases resources
73
+ * @return {Promise<void>} Promise that resolves when the connection is closed
74
+ */
75
+ async close() {
76
+ if (this.listeningStack)
77
+ this.listeningStack.close();
78
+ }
79
+ /**
80
+ * @description Parses event payload from binary format
81
+ * @summary Converts a Uint8Array containing JSON to an object with an id property
82
+ * @param {Uint8Array} jsonBytes - The binary payload from the chaincode event
83
+ * @return {{ id: string }} The parsed payload containing the record ID
84
+ */
85
+ parsePayload(jsonBytes) {
86
+ const json = this.decoder.decode(jsonBytes);
87
+ return JSON.parse(json);
88
+ }
89
+ /**
90
+ * @description Starts observing an adapter
91
+ * @summary Connects this dispatch to an adapter to monitor its operations
92
+ * @param {Adapter<any, any, any, any>} observer - The adapter to observe
93
+ * @return {void}
94
+ */
95
+ observe(observer) {
96
+ if (!(observer instanceof FabricClientAdapter_1.FabricClientAdapter))
97
+ throw new core_1.UnsupportedError("Only FabricClientAdapter can be observed by dispatch");
98
+ this.adapter = observer;
99
+ this.models = core_1.Adapter.models(this.adapter.alias);
100
+ this.initialize().then(() => this.log.verbose(`Dispatch initialized for ${this.adapter.alias} adapter`));
101
+ }
102
+ /**
103
+ * @description Updates observers about a database event
104
+ * @summary Notifies observers about a change in the database
105
+ * @param {string} table - The name of the table where the change occurred
106
+ * @param {OperationKeys|BulkCrudOperationKeys|string} event - The type of operation that occurred
107
+ * @param {any} payload - The event payload
108
+ * @return {Promise<void>} A promise that resolves when all observers have been notified
109
+ */
110
+ async updateObservers(table, event, payload) {
111
+ if (!this.adapter) {
112
+ this.log.verbose(`No adapter observed for dispatch; skipping observer update for ${table}:${event}`);
113
+ return;
114
+ }
115
+ try {
116
+ await this.adapter.refresh(table, event, payload.id ? payload.id : undefined, payload);
117
+ }
118
+ catch (e) {
119
+ throw new db_decorators_1.InternalError(`Failed to refresh dispatch: ${e}`);
120
+ }
121
+ }
122
+ /**
123
+ * @description Processes incoming chaincode events
124
+ * @summary Listens for events from the chaincode and dispatches them to registered observers
125
+ * @return {Promise<void>} Promise that resolves when event handling stops
126
+ * @mermaid
127
+ * sequenceDiagram
128
+ * participant FabricDispatch
129
+ * participant EventStack
130
+ * participant EventParser
131
+ * participant Observers
132
+ *
133
+ * FabricDispatch->>FabricDispatch: handleEvents()
134
+ * FabricDispatch->>EventStack: for await (const evt of listeningStack)
135
+ * EventStack-->>FabricDispatch: ChaincodeEvent
136
+ * FabricDispatch->>EventParser: parseEventName(evt.eventName)
137
+ * EventParser-->>FabricDispatch: { table, event, owner }
138
+ * FabricDispatch->>FabricDispatch: Check if event is for this MSP
139
+ * FabricDispatch->>FabricDispatch: parsePayload(evt.payload)
140
+ * FabricDispatch->>Observers: updateObservers(table, event, payload.id)
141
+ * Observers-->>FabricDispatch: Callbacks executed
142
+ */
143
+ async handleEvents() {
144
+ if (!this.listeningStack)
145
+ throw new db_decorators_1.InternalError(`Event stack not initialized. Ensure that "startListening" is called before attempting this operation.`);
146
+ if (!this.adapter || !this.adapter.config)
147
+ throw new db_decorators_1.InternalError(`No adapter found. should be impossible`);
148
+ const log = this.log.for(this.handleEvents);
149
+ log.info(`Listening for incoming events on chaincode "${this.adapter.config.chaincodeName}" on channel "${this.adapter.config.channel}"...`);
150
+ try {
151
+ for await (const evt of this.listeningStack) {
152
+ const { table, event, owner } = (0, events_1.parseEventName)(evt.eventName);
153
+ if (owner && owner !== this.adapter.config?.mspId)
154
+ continue;
155
+ const payload = this.parsePayload(evt.payload);
156
+ try {
157
+ await this.updateObservers(table ? table : this.models[0].name, event, payload);
158
+ }
159
+ catch (e) {
160
+ log.error(`Failed update observables for table ${table} event ${event} id: ${payload.id}: ${e}`);
161
+ }
162
+ }
163
+ }
164
+ catch (e) {
165
+ log.error(`Failed to read event for chaincode "${this.adapter.config.chaincodeName}" on channel "${this.adapter.config.channel}": ${e}`);
166
+ await this.close();
167
+ }
168
+ }
169
+ /**
170
+ * @description Initializes the event listener
171
+ * @summary Sets up the connection to the Fabric network and starts listening for chaincode events
172
+ * @return {Promise<void>} Promise that resolves when initialization is complete
173
+ */
174
+ async initialize() {
175
+ if (!this.adapter)
176
+ throw new db_decorators_1.InternalError(`No adapter or config observed for dispatch`);
177
+ const gateway = await FabricClientAdapter_1.FabricClientAdapter.getGateway(this.adapter.config, this.client);
178
+ const network = gateway.getNetwork(this.adapter.config.channel);
179
+ if (!this.adapter)
180
+ throw new db_decorators_1.InternalError(`No adapter observed for dispatch`);
181
+ this.listeningStack = await network.getChaincodeEvents(this.adapter.config.chaincodeName);
182
+ this.handleEvents();
183
+ }
184
+ }
185
+ exports.FabricClientDispatch = FabricClientDispatch;
186
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRmFicmljQ2xpZW50RGlzcGF0Y2guanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY2xpZW50L0ZhYnJpY0NsaWVudERpc3BhdGNoLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHlDQUFxRTtBQUdyRSxtRUFBNEQ7QUFDNUQsMkRBQXdEO0FBS3hELG1EQUFrRDtBQUVsRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0ErQ0c7QUFDSCxNQUFhLG9CQUFxQixTQUFRLGVBQVE7SUFXaEQ7Ozs7T0FJRztJQUNILFlBQXNCLE1BQWM7UUFDbEMsS0FBSyxFQUFFLENBQUM7UUFEWSxXQUFNLEdBQU4sTUFBTSxDQUFRO1FBVnBDOztXQUVHO1FBQ0ssWUFBTyxHQUFHLElBQUksV0FBVyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBUzFDLENBQUM7SUFFRDs7OztPQUlHO0lBQ00sS0FBSyxDQUFDLEtBQUs7UUFDbEIsSUFBSSxJQUFJLENBQUMsY0FBYztZQUFFLElBQUksQ0FBQyxjQUFjLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDdkQsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0ssWUFBWSxDQUFDLFNBQXFCO1FBQ3hDLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQzVDLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMxQixDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDTSxPQUFPLENBQUMsUUFBNkI7UUFDNUMsSUFBSSxDQUFDLENBQUMsUUFBUSxZQUFZLHlDQUFtQixDQUFDO1lBQzVDLE1BQU0sSUFBSSx1QkFBZ0IsQ0FDeEIsc0RBQXNELENBQ3ZELENBQUM7UUFDSixJQUFJLENBQUMsT0FBTyxHQUFHLFFBQVEsQ0FBQztRQUN4QixJQUFJLENBQUMsTUFBTSxHQUFHLGNBQU8sQ0FBQyxNQUFNLENBQUMsSUFB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QU8sQ0FBQyxNQUFNLENBQUMsYUFBYSxpQkFBaUIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsT0FBTyxNQUFNLENBQUMsRUFBRSxDQUM5SCxDQUFDO1lBQ0YsTUFBTSxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDckIsQ0FBQztJQUNILENBQUM7SUFFRDs7OztPQUlHO0lBQ2dCLEtBQUssQ0FBQyxVQUFVO1FBQ2pDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTztZQUNmLE1BQU0sSUFBSSw2QkFBYSxDQUFDLDRDQUE0QyxDQUFDLENBQUM7UUFDeEUsTUFBTSxPQUFPLEdBQUcsTUFBTSx5Q0FBbUIsQ0FBQyxVQUFVLENBQ2xELElBQUksQ0FBQyxPQUFPLENBQUMsTUFBb0IsRUFDakMsSUFBSSxDQUFDLE1BQU0sQ0FDWixDQUFDO1FBQ0YsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNoRSxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU87WUFDZixNQUFNLElBQUksNkJBQWEsQ0FBQyxrQ0FBa0MsQ0FBQyxDQUFDO1FBQzlELElBQUksQ0FBQyxjQUFjLEdBQUcsTUFBTSxPQUFPLENBQUMsa0JBQWtCLENBQ3BELElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FDbEMsQ0FBQztRQUNGLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztJQUN0QixDQUFDO0NBQ0Y7QUEzS0Qsb0RBMktDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQWRhcHRlciwgRGlzcGF0Y2gsIFVuc3VwcG9ydGVkRXJyb3IgfSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbmltcG9ydCB7IFBlZXJDb25maWcgfSBmcm9tIFwiLi4vc2hhcmVkL3R5cGVzXCI7XG5pbXBvcnQgeyBDbGllbnQgfSBmcm9tIFwiQGdycGMvZ3JwYy1qc1wiO1xuaW1wb3J0IHsgRmFicmljQ2xpZW50QWRhcHRlciB9IGZyb20gXCIuL0ZhYnJpY0NsaWVudEFkYXB0ZXJcIjtcbmltcG9ydCB7IEludGVybmFsRXJyb3IgfSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcbmltcG9ydCB7XG4gIENoYWluY29kZUV2ZW50LFxuICBDbG9zZWFibGVBc3luY0l0ZXJhYmxlLFxufSBmcm9tIFwiQGh5cGVybGVkZ2VyL2ZhYnJpYy1nYXRld2F5XCI7XG5pbXBvcnQgeyBwYXJzZUV2ZW50TmFtZSB9IGZyb20gXCIuLi9zaGFyZWQvZXZlbnRzXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEV2ZW50IGRpc3BhdGNoZXIgZm9yIEh5cGVybGVkZ2VyIEZhYnJpYyBjaGFpbmNvZGUgZXZlbnRzXG4gKiBAc3VtbWFyeSBMaXN0ZW5zIGZvciBhbmQgcHJvY2Vzc2VzIGV2ZW50cyBlbWl0dGVkIGJ5IEZhYnJpYyBjaGFpbmNvZGUsIGRpc3BhdGNoaW5nIHRoZW0gdG8gcmVnaXN0ZXJlZCBvYnNlcnZlcnNcbiAqIEB0ZW1wbGF0ZSBQZWVyQ29uZmlnIC0gQ29uZmlndXJhdGlvbiB0eXBlIGZvciBjb25uZWN0aW5nIHRvIGEgRmFicmljIHBlZXJcbiAqIEBwYXJhbSBjbGllbnQgLSBnUlBDIGNsaWVudCBmb3IgY29ubmVjdGluZyB0byB0aGUgRmFicmljIG5ldHdvcmtcbiAqIEBjbGFzcyBGYWJyaWNDbGllbnREaXNwYXRjaFxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIC8vIENyZWF0ZSBhIG5ldyBGYWJyaWNEaXNwYXRjaCBpbnN0YW5jZVxuICogY29uc3QgY2xpZW50ID0gYXdhaXQgRmFicmljQWRhcHRlci5nZXRDbGllbnQocGVlckNvbmZpZyk7XG4gKiBjb25zdCBkaXNwYXRjaCA9IG5ldyBGYWJyaWNEaXNwYXRjaChjbGllbnQpO1xuICpcbiAqIC8vIENvbmZpZ3VyZSB0aGUgZGlzcGF0Y2ggd2l0aCBwZWVyIGNvbmZpZ3VyYXRpb25cbiAqIGRpc3BhdGNoLmNvbmZpZ3VyZShwZWVyQ29uZmlnKTtcbiAqXG4gKiAvLyBSZWdpc3RlciBhbiBvYnNlcnZlciBmb3IgYSBzcGVjaWZpYyB0YWJsZSBhbmQgZXZlbnRcbiAqIGRpc3BhdGNoLm9ic2VydmUoJ3VzZXJzJywgJ2NyZWF0ZScsIChpZCkgPT4ge1xuICogICBjb25zb2xlLmxvZyhgVXNlciBjcmVhdGVkOiAke2lkfWApO1xuICogfSk7XG4gKlxuICogLy8gU3RhcnQgbGlzdGVuaW5nIGZvciBldmVudHNcbiAqIGF3YWl0IGRpc3BhdGNoLnN0YXJ0KCk7XG4gKiBgYGBcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQ2xpZW50XG4gKiAgIHBhcnRpY2lwYW50IEZhYnJpY0Rpc3BhdGNoXG4gKiAgIHBhcnRpY2lwYW50IEdhdGV3YXlcbiAqICAgcGFydGljaXBhbnQgTmV0d29ya1xuICogICBwYXJ0aWNpcGFudCBDaGFpbmNvZGVcbiAqXG4gKiAgIENsaWVudC0+PkZhYnJpY0Rpc3BhdGNoOiBuZXcgRmFicmljRGlzcGF0Y2goY2xpZW50KVxuICogICBDbGllbnQtPj5GYWJyaWNEaXNwYXRjaDogY29uZmlndXJlKHBlZXJDb25maWcpXG4gKiAgIENsaWVudC0+PkZhYnJpY0Rpc3BhdGNoOiBvYnNlcnZlKHRhYmxlLCBldmVudCwgY2FsbGJhY2spXG4gKiAgIENsaWVudC0+PkZhYnJpY0Rpc3BhdGNoOiBzdGFydCgpXG4gKiAgIEZhYnJpY0Rpc3BhdGNoLT4+RmFicmljRGlzcGF0Y2g6IGluaXRpYWxpemUoKVxuICogICBGYWJyaWNEaXNwYXRjaC0+PkdhdGV3YXk6IGdldEdhdGV3YXkoY29uZmlnLCBjbGllbnQpXG4gKiAgIEdhdGV3YXktPj5OZXR3b3JrOiBnZXROZXR3b3JrKGNoYW5uZWwpXG4gKiAgIE5ldHdvcmstPj5OZXR3b3JrOiBnZXRDaGFpbmNvZGVFdmVudHMoY2hhaW5jb2RlTmFtZSlcbiAqICAgRmFicmljRGlzcGF0Y2gtPj5GYWJyaWNEaXNwYXRjaDogaGFuZGxlRXZlbnRzKClcbiAqICAgbG9vcCBGb3IgZWFjaCBldmVudFxuICogICAgIENoYWluY29kZS0tPj5GYWJyaWNEaXNwYXRjaDogQ2hhaW5jb2RlRXZlbnRcbiAqICAgICBGYWJyaWNEaXNwYXRjaC0+PkZhYnJpY0Rpc3BhdGNoOiBwYXJzZUV2ZW50TmFtZShldmVudE5hbWUpXG4gKiAgICAgRmFicmljRGlzcGF0Y2gtPj5GYWJyaWNEaXNwYXRjaDogcGFyc2VQYXlsb2FkKHBheWxvYWQpXG4gKiAgICAgRmFicmljRGlzcGF0Y2gtPj5GYWJyaWNEaXNwYXRjaDogdXBkYXRlT2JzZXJ2ZXJzKHRhYmxlLCBldmVudCwgaWQpXG4gKiAgICAgRmFicmljRGlzcGF0Y2gtLT4+Q2xpZW50OiBjYWxsYmFjayhpZClcbiAqICAgZW5kXG4gKi9cbmV4cG9ydCBjbGFzcyBGYWJyaWNDbGllbnREaXNwYXRjaCBleHRlbmRzIERpc3BhdGNoIHtcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBFdmVudCBsaXN0ZW5pbmcgc3RhY2sgZm9yIGNoYWluY29kZSBldmVudHNcbiAgICovXG4gIHByaXZhdGUgbGlzdGVuaW5nU3RhY2s/OiBDbG9zZWFibGVBc3luY0l0ZXJhYmxlPENoYWluY29kZUV2ZW50PjtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRleHQgZGVjb2RlciBmb3IgY29udmVydGluZyBldmVudCBwYXlsb2FkcyBmcm9tIGJ5dGVzIHRvIHN0cmluZ3NcbiAgICovXG4gIHByaXZhdGUgZGVjb2RlciA9IG5ldyBUZXh0RGVjb2RlcihcInV0ZjhcIik7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgbmV3IEZhYnJpY0Rpc3BhdGNoIGluc3RhbmNlXG4gICAqIEBzdW1tYXJ5IEluaXRpYWxpemVzIGEgZGlzcGF0Y2hlciBmb3IgRmFicmljIGNoYWluY29kZSBldmVudHNcbiAgICogQHBhcmFtIHtDbGllbnR9IGNsaWVudCAtIGdSUEMgY2xpZW50IGZvciBjb25uZWN0aW5nIHRvIHRoZSBGYWJyaWMgbmV0d29ya1xuICAgKi9cbiAgY29uc3RydWN0b3IocHJvdGVjdGVkIGNsaWVudDogQ2xpZW50KSB7XG4gICAgc3VwZXIoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ2xvc2VzIHRoZSBldmVudCBsaXN0ZW5pbmcgY29ubmVjdGlvblxuICAgKiBAc3VtbWFyeSBTdG9wcyBsaXN0ZW5pbmcgZm9yIGNoYWluY29kZSBldmVudHMgYW5kIHJlbGVhc2VzIHJlc291cmNlc1xuICAgKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgY29ubmVjdGlvbiBpcyBjbG9zZWRcbiAgICovXG4gIG92ZXJyaWRlIGFzeW5jIGNsb3NlKCkge1xuICAgIGlmICh0aGlzLmxpc3RlbmluZ1N0YWNrKSB0aGlzLmxpc3RlbmluZ1N0YWNrLmNsb3NlKCk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFBhcnNlcyBldmVudCBwYXlsb2FkIGZyb20gYmluYXJ5IGZvcm1hdFxuICAgKiBAc3VtbWFyeSBDb252ZXJ0cyBhIFVpbnQ4QXJyYXkgY29udGFpbmluZyBKU09OIHRvIGFuIG9iamVjdCB3aXRoIGFuIGlkIHByb3BlcnR5XG4gICAqIEBwYXJhbSB7VWludDhBcnJheX0ganNvbkJ5dGVzIC0gVGhlIGJpbmFyeSBwYXlsb2FkIGZyb20gdGhlIGNoYWluY29kZSBldmVudFxuICAgKiBAcmV0dXJuIHt7IGlkOiBzdHJpbmcgfX0gVGhlIHBhcnNlZCBwYXlsb2FkIGNvbnRhaW5pbmcgdGhlIHJlY29yZCBJRFxuICAgKi9cbiAgcHJpdmF0ZSBwYXJzZVBheWxvYWQoanNvbkJ5dGVzOiBVaW50OEFycmF5KTogeyBpZDogc3RyaW5nIH0ge1xuICAgIGNvbnN0IGpzb24gPSB0aGlzLmRlY29kZXIuZGVjb2RlKGpzb25CeXRlcyk7XG4gICAgcmV0dXJuIEpTT04ucGFyc2UoanNvbik7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFN0YXJ0cyBvYnNlcnZpbmcgYW4gYWRhcHRlclxuICAgKiBAc3VtbWFyeSBDb25uZWN0cyB0aGlzIGRpc3BhdGNoIHRvIGFuIGFkYXB0ZXIgdG8gbW9uaXRvciBpdHMgb3BlcmF0aW9uc1xuICAgKiBAcGFyYW0ge0FkYXB0ZXI8YW55LCBhbnksIGFueSwgYW55Pn0gb2JzZXJ2ZXIgLSBUaGUgYWRhcHRlciB0byBvYnNlcnZlXG4gICAqIEByZXR1cm4ge3ZvaWR9XG4gICAqL1xuICBvdmVycmlkZSBvYnNlcnZlKG9ic2VydmVyOiBGYWJyaWNDbGllbnRBZGFwdGVyKTogdm9pZCB7XG4gICAgaWYgKCEob2JzZXJ2ZXIgaW5zdGFuY2VvZiBGYWJyaWNDbGllbnRBZGFwdGVyKSlcbiAgICAgIHRocm93IG5ldyBVbnN1cHBvcnRlZEVycm9yKFxuICAgICAgICBcIk9ubHkgRmFicmljQ2xpZW50QWRhcHRlciBjYW4gYmUgb2JzZXJ2ZWQgYnkgZGlzcGF0Y2hcIlxuICAgICAgKTtcbiAgICB0aGlzLmFkYXB0ZXIgPSBvYnNlcnZlcjtcbiAgICB0aGlzLm1vZGVscyA9IEFkYXB0ZXIubW9kZWxzKHRoaXMuYWRhcHRlci5hbGlhcyk7XG4gICAgdGhpcy5pbml0aWFsaXplKCkudGhlbigoKSA9PlxuICAgICAgdGhpcy5sb2cudmVyYm9zZShcbiAgICAgICAgYERpc3BhdGNoIGluaXRpYWxpemVkIGZvciAke3RoaXMuYWRhcHRlciEuYWxpYXN9IGFkYXB0ZXJgXG4gICAgICApXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVXBkYXRlcyBvYnNlcnZlcnMgYWJvdXQgYSBkYXRhYmFzZSBldmVudFxuICAgKiBAc3VtbWFyeSBOb3RpZmllcyBvYnNlcnZlcnMgYWJvdXQgYSBjaGFuZ2UgaW4gdGhlIGRhdGFiYXNlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0YWJsZSAtIFRoZSBuYW1lIG9mIHRoZSB0YWJsZSB3aGVyZSB0aGUgY2hhbmdlIG9jY3VycmVkXG4gICAqIEBwYXJhbSB7T3BlcmF0aW9uS2V5c3xCdWxrQ3J1ZE9wZXJhdGlvbktleXN8c3RyaW5nfSBldmVudCAtIFRoZSB0eXBlIG9mIG9wZXJhdGlvbiB0aGF0IG9jY3VycmVkXG4gICAqIEBwYXJhbSB7YW55fSBwYXlsb2FkIC0gVGhlIGV2ZW50IHBheWxvYWRcbiAgICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiBhbGwgb2JzZXJ2ZXJzIGhhdmUgYmVlbiBub3RpZmllZFxuICAgKi9cbiAgb3ZlcnJpZGUgYXN5bmMgdXBkYXRlT2JzZXJ2ZXJzKFxuICAgIHRhYmxlOiBzdHJpbmcsXG4gICAgZXZlbnQ6IHN0cmluZyxcbiAgICBwYXlsb2FkOiBhbnlcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKCF0aGlzLmFkYXB0ZXIpIHtcbiAgICAgIHRoaXMubG9nLnZlcmJvc2UoXG4gICAgICAgIGBObyBhZGFwdGVyIG9ic2VydmVkIGZvciBkaXNwYXRjaDsgc2tpcHBpbmcgb2JzZXJ2ZXIgdXBkYXRlIGZvciAke3RhYmxlfToke2V2ZW50fWBcbiAgICAgICk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmFkYXB0ZXIucmVmcmVzaChcbiAgICAgICAgdGFibGUsXG4gICAgICAgIGV2ZW50LFxuICAgICAgICBwYXlsb2FkLmlkID8gcGF5bG9hZC5pZCA6IHVuZGVmaW5lZCxcbiAgICAgICAgcGF5bG9hZFxuICAgICAgKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihgRmFpbGVkIHRvIHJlZnJlc2ggZGlzcGF0Y2g6ICR7ZX1gKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFByb2Nlc3NlcyBpbmNvbWluZyBjaGFpbmNvZGUgZXZlbnRzXG4gICAqIEBzdW1tYXJ5IExpc3RlbnMgZm9yIGV2ZW50cyBmcm9tIHRoZSBjaGFpbmNvZGUgYW5kIGRpc3BhdGNoZXMgdGhlbSB0byByZWdpc3RlcmVkIG9ic2VydmVyc1xuICAgKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiBldmVudCBoYW5kbGluZyBzdG9wc1xuICAgKiBAbWVybWFpZFxuICAgKiBzZXF1ZW5jZURpYWdyYW1cbiAgICogICBwYXJ0aWNpcGFudCBGYWJyaWNEaXNwYXRjaFxuICAgKiAgIHBhcnRpY2lwYW50IEV2ZW50U3RhY2tcbiAgICogICBwYXJ0aWNpcGFudCBFdmVudFBhcnNlclxuICAgKiAgIHBhcnRpY2lwYW50IE9ic2VydmVyc1xuICAgKlxuICAgKiAgIEZhYnJpY0Rpc3BhdGNoLT4+RmFicmljRGlzcGF0Y2g6IGhhbmRsZUV2ZW50cygpXG4gICAqICAgRmFicmljRGlzcGF0Y2gtPj5FdmVudFN0YWNrOiBmb3IgYXdhaXQgKGNvbnN0IGV2dCBvZiBsaXN0ZW5pbmdTdGFjaylcbiAgICogICBFdmVudFN0YWNrLS0+PkZhYnJpY0Rpc3BhdGNoOiBDaGFpbmNvZGVFdmVudFxuICAgKiAgIEZhYnJpY0Rpc3BhdGNoLT4+RXZlbnRQYXJzZXI6IHBhcnNlRXZlbnROYW1lKGV2dC5ldmVudE5hbWUpXG4gICAqICAgRXZlbnRQYXJzZXItLT4+RmFicmljRGlzcGF0Y2g6IHsgdGFibGUsIGV2ZW50LCBvd25lciB9XG4gICAqICAgRmFicmljRGlzcGF0Y2gtPj5GYWJyaWNEaXNwYXRjaDogQ2hlY2sgaWYgZXZlbnQgaXMgZm9yIHRoaXMgTVNQXG4gICAqICAgRmFicmljRGlzcGF0Y2gtPj5GYWJyaWNEaXNwYXRjaDogcGFyc2VQYXlsb2FkKGV2dC5wYXlsb2FkKVxuICAgKiAgIEZhYnJpY0Rpc3BhdGNoLT4+T2JzZXJ2ZXJzOiB1cGRhdGVPYnNlcnZlcnModGFibGUsIGV2ZW50LCBwYXlsb2FkLmlkKVxuICAgKiAgIE9ic2VydmVycy0tPj5GYWJyaWNEaXNwYXRjaDogQ2FsbGJhY2tzIGV4ZWN1dGVkXG4gICAqL1xuICBwcm90ZWN0ZWQgYXN5bmMgaGFuZGxlRXZlbnRzKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICghdGhpcy5saXN0ZW5pbmdTdGFjaylcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFxuICAgICAgICBgRXZlbnQgc3RhY2sgbm90IGluaXRpYWxpemVkLiBFbnN1cmUgdGhhdCBcInN0YXJ0TGlzdGVuaW5nXCIgaXMgY2FsbGVkIGJlZm9yZSBhdHRlbXB0aW5nIHRoaXMgb3BlcmF0aW9uLmBcbiAgICAgICk7XG5cbiAgICBpZiAoIXRoaXMuYWRhcHRlciB8fCAhdGhpcy5hZGFwdGVyLmNvbmZpZylcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKGBObyBhZGFwdGVyIGZvdW5kLiBzaG91bGQgYmUgaW1wb3NzaWJsZWApO1xuXG4gICAgY29uc3QgbG9nID0gdGhpcy5sb2cuZm9yKHRoaXMuaGFuZGxlRXZlbnRzKTtcbiAgICBsb2cuaW5mbyhcbiAgICAgIGBMaXN0ZW5pbmcgZm9yIGluY29taW5nIGV2ZW50cyBvbiBjaGFpbmNvZGUgXCIke3RoaXMuYWRhcHRlci5jb25maWcuY2hhaW5jb2RlTmFtZX1cIiBvbiBjaGFubmVsIFwiJHt0aGlzLmFkYXB0ZXIuY29uZmlnLmNoYW5uZWx9XCIuLi5gXG4gICAgKTtcblxuICAgIHRyeSB7XG4gICAgICBmb3IgYXdhaXQgKGNvbnN0IGV2dCBvZiB0aGlzLmxpc3RlbmluZ1N0YWNrKSB7XG4gICAgICAgIGNvbnN0IHsgdGFibGUsIGV2ZW50LCBvd25lciB9ID0gcGFyc2VFdmVudE5hbWUoZXZ0LmV2ZW50TmFtZSk7XG4gICAgICAgIGlmIChvd25lciAmJiBvd25lciAhPT0gdGhpcy5hZGFwdGVyLmNvbmZpZz8ubXNwSWQpIGNvbnRpbnVlO1xuICAgICAgICBjb25zdCBwYXlsb2FkOiB7IGlkOiBzdHJpbmcgfSA9IHRoaXMucGFyc2VQYXlsb2FkKGV2dC5wYXlsb2FkKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCB0aGlzLnVwZGF0ZU9ic2VydmVycyhcbiAgICAgICAgICAgIHRhYmxlID8gdGFibGUgOiB0aGlzLm1vZGVsc1swXS5uYW1lLFxuICAgICAgICAgICAgZXZlbnQsXG4gICAgICAgICAgICBwYXlsb2FkXG4gICAgICAgICAgKTtcbiAgICAgICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgICAgIGxvZy5lcnJvcihcbiAgICAgICAgICAgIGBGYWlsZWQgdXBkYXRlIG9ic2VydmFibGVzIGZvciB0YWJsZSAke3RhYmxlfSBldmVudCAke2V2ZW50fSBpZDogJHtwYXlsb2FkLmlkfTogJHtlfWBcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICBsb2cuZXJyb3IoXG4gICAgICAgIGBGYWlsZWQgdG8gcmVhZCBldmVudCBmb3IgY2hhaW5jb2RlIFwiJHt0aGlzLmFkYXB0ZXIuY29uZmlnLmNoYWluY29kZU5hbWV9XCIgb24gY2hhbm5lbCBcIiR7dGhpcy5hZGFwdGVyLmNvbmZpZy5jaGFubmVsfVwiOiAke2V9YFxuICAgICAgKTtcbiAgICAgIGF3YWl0IHRoaXMuY2xvc2UoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEluaXRpYWxpemVzIHRoZSBldmVudCBsaXN0ZW5lclxuICAgKiBAc3VtbWFyeSBTZXRzIHVwIHRoZSBjb25uZWN0aW9uIHRvIHRoZSBGYWJyaWMgbmV0d29yayBhbmQgc3RhcnRzIGxpc3RlbmluZyBmb3IgY2hhaW5jb2RlIGV2ZW50c1xuICAgKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiBpbml0aWFsaXphdGlvbiBpcyBjb21wbGV0ZVxuICAgKi9cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIGFzeW5jIGluaXRpYWxpemUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKCF0aGlzLmFkYXB0ZXIpXG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihgTm8gYWRhcHRlciBvciBjb25maWcgb2JzZXJ2ZWQgZm9yIGRpc3BhdGNoYCk7XG4gICAgY29uc3QgZ2F0ZXdheSA9IGF3YWl0IEZhYnJpY0NsaWVudEFkYXB0ZXIuZ2V0R2F0ZXdheShcbiAgICAgIHRoaXMuYWRhcHRlci5jb25maWcgYXMgUGVlckNvbmZpZyxcbiAgICAgIHRoaXMuY2xpZW50XG4gICAgKTtcbiAgICBjb25zdCBuZXR3b3JrID0gZ2F0ZXdheS5nZXROZXR3b3JrKHRoaXMuYWRhcHRlci5jb25maWcuY2hhbm5lbCk7XG4gICAgaWYgKCF0aGlzLmFkYXB0ZXIpXG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihgTm8gYWRhcHRlciBvYnNlcnZlZCBmb3IgZGlzcGF0Y2hgKTtcbiAgICB0aGlzLmxpc3RlbmluZ1N0YWNrID0gYXdhaXQgbmV0d29yay5nZXRDaGFpbmNvZGVFdmVudHMoXG4gICAgICB0aGlzLmFkYXB0ZXIuY29uZmlnLmNoYWluY29kZU5hbWVcbiAgICApO1xuICAgIHRoaXMuaGFuZGxlRXZlbnRzKCk7XG4gIH1cbn1cbiJdfQ==