@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.
- package/LICENSE.md +22 -0
- package/README.md +647 -0
- package/dist/for-fabric.cjs +6223 -0
- package/dist/for-fabric.esm.cjs +6180 -0
- package/lib/client/FabricClientAdapter.cjs +760 -0
- package/lib/client/FabricClientAdapter.d.ts +381 -0
- package/lib/client/FabricClientDispatch.cjs +186 -0
- package/lib/client/FabricClientDispatch.d.ts +125 -0
- package/lib/client/FabricClientRepository.cjs +131 -0
- package/lib/client/FabricClientRepository.d.ts +100 -0
- package/lib/client/erc20/erc20ClientRepository.cjs +343 -0
- package/lib/client/erc20/erc20ClientRepository.d.ts +254 -0
- package/lib/client/fabric-fs.cjs +234 -0
- package/lib/client/fabric-fs.d.ts +92 -0
- package/lib/client/index.cjs +30 -0
- package/lib/client/index.d.ts +13 -0
- package/lib/client/logging.cjs +102 -0
- package/lib/client/logging.d.ts +60 -0
- package/lib/client/services/LoggedService.cjs +47 -0
- package/lib/client/services/LoggedService.d.ts +42 -0
- package/lib/client/services/constants.cjs +3 -0
- package/lib/client/services/constants.d.ts +15 -0
- package/lib/client/services/enrollementService.cjs +344 -0
- package/lib/client/services/enrollementService.d.ts +176 -0
- package/lib/client/services/index.cjs +18 -0
- package/lib/client/services/index.d.ts +1 -0
- package/lib/contracts/ContractAdapter.cjs +730 -0
- package/lib/contracts/ContractAdapter.d.ts +296 -0
- package/lib/contracts/ContractContext.cjs +85 -0
- package/lib/contracts/ContractContext.d.ts +64 -0
- package/lib/contracts/ContractPrivateDataAdapter.cjs +281 -0
- package/lib/contracts/ContractPrivateDataAdapter.d.ts +74 -0
- package/lib/contracts/FabricConstruction.cjs +441 -0
- package/lib/contracts/FabricConstruction.d.ts +304 -0
- package/lib/contracts/FabricContractRepository.cjs +306 -0
- package/lib/contracts/FabricContractRepository.d.ts +162 -0
- package/lib/contracts/FabricContractRepositoryObservableHandler.cjs +85 -0
- package/lib/contracts/FabricContractRepositoryObservableHandler.d.ts +62 -0
- package/lib/contracts/FabricContractSequence.cjs +139 -0
- package/lib/contracts/FabricContractSequence.d.ts +61 -0
- package/lib/contracts/FabricContractStatement.cjs +119 -0
- package/lib/contracts/FabricContractStatement.d.ts +34 -0
- package/lib/contracts/PrivateSequence.cjs +36 -0
- package/lib/contracts/PrivateSequence.d.ts +15 -0
- package/lib/contracts/crud/crud-contract.cjs +257 -0
- package/lib/contracts/crud/crud-contract.d.ts +168 -0
- package/lib/contracts/crud/index.cjs +19 -0
- package/lib/contracts/crud/index.d.ts +2 -0
- package/lib/contracts/crud/serialized-crud-contract.cjs +172 -0
- package/lib/contracts/crud/serialized-crud-contract.d.ts +37 -0
- package/lib/contracts/erc20/erc20contract.cjs +569 -0
- package/lib/contracts/erc20/erc20contract.d.ts +151 -0
- package/lib/contracts/erc20/index.cjs +21 -0
- package/lib/contracts/erc20/index.d.ts +2 -0
- package/lib/contracts/erc20/models.cjs +209 -0
- package/lib/contracts/erc20/models.d.ts +114 -0
- package/lib/contracts/index.cjs +32 -0
- package/lib/contracts/index.d.ts +15 -0
- package/lib/contracts/logging.cjs +96 -0
- package/lib/contracts/logging.d.ts +49 -0
- package/lib/contracts/private-data.cjs +121 -0
- package/lib/contracts/private-data.d.ts +16 -0
- package/lib/contracts/types.cjs +3 -0
- package/lib/contracts/types.d.ts +26 -0
- package/lib/esm/client/FabricClientAdapter.d.ts +381 -0
- package/lib/esm/client/FabricClientAdapter.js +723 -0
- package/lib/esm/client/FabricClientDispatch.d.ts +125 -0
- package/lib/esm/client/FabricClientDispatch.js +182 -0
- package/lib/esm/client/FabricClientRepository.d.ts +100 -0
- package/lib/esm/client/FabricClientRepository.js +127 -0
- package/lib/esm/client/erc20/erc20ClientRepository.d.ts +254 -0
- package/lib/esm/client/erc20/erc20ClientRepository.js +339 -0
- package/lib/esm/client/fabric-fs.d.ts +92 -0
- package/lib/esm/client/fabric-fs.js +191 -0
- package/lib/esm/client/index.d.ts +13 -0
- package/lib/esm/client/index.js +14 -0
- package/lib/esm/client/logging.d.ts +60 -0
- package/lib/esm/client/logging.js +98 -0
- package/lib/esm/client/services/LoggedService.d.ts +42 -0
- package/lib/esm/client/services/LoggedService.js +43 -0
- package/lib/esm/client/services/constants.d.ts +15 -0
- package/lib/esm/client/services/constants.js +2 -0
- package/lib/esm/client/services/enrollementService.d.ts +176 -0
- package/lib/esm/client/services/enrollementService.js +337 -0
- package/lib/esm/client/services/index.d.ts +1 -0
- package/lib/esm/client/services/index.js +2 -0
- package/lib/esm/contracts/ContractAdapter.d.ts +296 -0
- package/lib/esm/contracts/ContractAdapter.js +724 -0
- package/lib/esm/contracts/ContractContext.d.ts +64 -0
- package/lib/esm/contracts/ContractContext.js +81 -0
- package/lib/esm/contracts/ContractPrivateDataAdapter.d.ts +74 -0
- package/lib/esm/contracts/ContractPrivateDataAdapter.js +277 -0
- package/lib/esm/contracts/FabricConstruction.d.ts +304 -0
- package/lib/esm/contracts/FabricConstruction.js +433 -0
- package/lib/esm/contracts/FabricContractRepository.d.ts +162 -0
- package/lib/esm/contracts/FabricContractRepository.js +302 -0
- package/lib/esm/contracts/FabricContractRepositoryObservableHandler.d.ts +62 -0
- package/lib/esm/contracts/FabricContractRepositoryObservableHandler.js +81 -0
- package/lib/esm/contracts/FabricContractSequence.d.ts +61 -0
- package/lib/esm/contracts/FabricContractSequence.js +135 -0
- package/lib/esm/contracts/FabricContractStatement.d.ts +34 -0
- package/lib/esm/contracts/FabricContractStatement.js +115 -0
- package/lib/esm/contracts/PrivateSequence.d.ts +15 -0
- package/lib/esm/contracts/PrivateSequence.js +33 -0
- package/lib/esm/contracts/crud/crud-contract.d.ts +168 -0
- package/lib/esm/contracts/crud/crud-contract.js +253 -0
- package/lib/esm/contracts/crud/index.d.ts +2 -0
- package/lib/esm/contracts/crud/index.js +3 -0
- package/lib/esm/contracts/crud/serialized-crud-contract.d.ts +37 -0
- package/lib/esm/contracts/crud/serialized-crud-contract.js +168 -0
- package/lib/esm/contracts/erc20/erc20contract.d.ts +151 -0
- package/lib/esm/contracts/erc20/erc20contract.js +565 -0
- package/lib/esm/contracts/erc20/index.d.ts +2 -0
- package/lib/esm/contracts/erc20/index.js +4 -0
- package/lib/esm/contracts/erc20/models.d.ts +114 -0
- package/lib/esm/contracts/erc20/models.js +206 -0
- package/lib/esm/contracts/index.d.ts +15 -0
- package/lib/esm/contracts/index.js +16 -0
- package/lib/esm/contracts/logging.d.ts +49 -0
- package/lib/esm/contracts/logging.js +92 -0
- package/lib/esm/contracts/private-data.d.ts +16 -0
- package/lib/esm/contracts/private-data.js +113 -0
- package/lib/esm/contracts/types.d.ts +26 -0
- package/lib/esm/contracts/types.js +2 -0
- package/lib/esm/index.d.ts +8 -0
- package/lib/esm/index.js +9 -0
- package/lib/esm/shared/ClientSerializer.d.ts +52 -0
- package/lib/esm/shared/ClientSerializer.js +80 -0
- package/lib/esm/shared/DeterministicSerializer.d.ts +40 -0
- package/lib/esm/shared/DeterministicSerializer.js +50 -0
- package/lib/esm/shared/SimpleDeterministicSerializer.d.ts +7 -0
- package/lib/esm/shared/SimpleDeterministicSerializer.js +42 -0
- package/lib/esm/shared/constants.d.ts +39 -0
- package/lib/esm/shared/constants.js +42 -0
- package/lib/esm/shared/crypto.d.ts +107 -0
- package/lib/esm/shared/crypto.js +331 -0
- package/lib/esm/shared/decorators.d.ts +24 -0
- package/lib/esm/shared/decorators.js +98 -0
- package/lib/esm/shared/erc20/erc20-constants.d.ts +25 -0
- package/lib/esm/shared/erc20/erc20-constants.js +27 -0
- package/lib/esm/shared/errors.d.ts +116 -0
- package/lib/esm/shared/errors.js +132 -0
- package/lib/esm/shared/events.d.ts +39 -0
- package/lib/esm/shared/events.js +47 -0
- package/lib/esm/shared/fabric-types.d.ts +33 -0
- package/lib/esm/shared/fabric-types.js +2 -0
- package/lib/esm/shared/index.d.ts +13 -0
- package/lib/esm/shared/index.js +14 -0
- package/lib/esm/shared/interfaces/Checkable.d.ts +21 -0
- package/lib/esm/shared/interfaces/Checkable.js +2 -0
- package/lib/esm/shared/math.d.ts +34 -0
- package/lib/esm/shared/math.js +61 -0
- package/lib/esm/shared/model/Identity.d.ts +42 -0
- package/lib/esm/shared/model/Identity.js +78 -0
- package/lib/esm/shared/model/IdentityCredentials.d.ts +41 -0
- package/lib/esm/shared/model/IdentityCredentials.js +74 -0
- package/lib/esm/shared/model/index.d.ts +1 -0
- package/lib/esm/shared/model/index.js +2 -0
- package/lib/esm/shared/model/utils.d.ts +60 -0
- package/lib/esm/shared/model/utils.js +108 -0
- package/lib/esm/shared/types.d.ts +79 -0
- package/lib/esm/shared/types.js +2 -0
- package/lib/esm/shared/utils.d.ts +55 -0
- package/lib/esm/shared/utils.js +148 -0
- package/lib/index.cjs +25 -0
- package/lib/index.d.ts +8 -0
- package/lib/shared/ClientSerializer.cjs +84 -0
- package/lib/shared/ClientSerializer.d.ts +52 -0
- package/lib/shared/DeterministicSerializer.cjs +54 -0
- package/lib/shared/DeterministicSerializer.d.ts +40 -0
- package/lib/shared/SimpleDeterministicSerializer.cjs +46 -0
- package/lib/shared/SimpleDeterministicSerializer.d.ts +7 -0
- package/lib/shared/constants.cjs +45 -0
- package/lib/shared/constants.d.ts +39 -0
- package/lib/shared/crypto.cjs +369 -0
- package/lib/shared/crypto.d.ts +107 -0
- package/lib/shared/decorators.cjs +105 -0
- package/lib/shared/decorators.d.ts +24 -0
- package/lib/shared/erc20/erc20-constants.cjs +30 -0
- package/lib/shared/erc20/erc20-constants.d.ts +25 -0
- package/lib/shared/errors.cjs +142 -0
- package/lib/shared/errors.d.ts +116 -0
- package/lib/shared/events.cjs +51 -0
- package/lib/shared/events.d.ts +39 -0
- package/lib/shared/fabric-types.cjs +4 -0
- package/lib/shared/fabric-types.d.ts +33 -0
- package/lib/shared/index.cjs +30 -0
- package/lib/shared/index.d.ts +13 -0
- package/lib/shared/interfaces/Checkable.cjs +3 -0
- package/lib/shared/interfaces/Checkable.d.ts +21 -0
- package/lib/shared/math.cjs +66 -0
- package/lib/shared/math.d.ts +34 -0
- package/lib/shared/model/Identity.cjs +81 -0
- package/lib/shared/model/Identity.d.ts +42 -0
- package/lib/shared/model/IdentityCredentials.cjs +77 -0
- package/lib/shared/model/IdentityCredentials.d.ts +41 -0
- package/lib/shared/model/index.cjs +18 -0
- package/lib/shared/model/index.d.ts +1 -0
- package/lib/shared/model/utils.cjs +114 -0
- package/lib/shared/model/utils.d.ts +60 -0
- package/lib/shared/types.cjs +3 -0
- package/lib/shared/types.d.ts +79 -0
- package/lib/shared/utils.cjs +185 -0
- package/lib/shared/utils.d.ts +55 -0
- package/package.json +166 -0
|
@@ -0,0 +1,724 @@
|
|
|
1
|
+
import { CouchDBAdapter, CouchDBKeys } from "@decaf-ts/for-couchdb";
|
|
2
|
+
import { Decoration, list, Model, prop, propMetadata, required, type, } from "@decaf-ts/decorator-validation";
|
|
3
|
+
import { FabricContractContext } from "./ContractContext.js";
|
|
4
|
+
import { afterAny, DBKeys, InternalError, modelToTransient, NotFoundError, onCreate, onCreateUpdate, onDelete, onUpdate, readonly, SerializationError, } from "@decaf-ts/db-decorators";
|
|
5
|
+
import { Object as FabricObject, Property as FabricProperty, } from "fabric-contract-api";
|
|
6
|
+
import { Logging } from "@decaf-ts/logging";
|
|
7
|
+
import { OrderDirection, PersistenceKeys, Repository, sequenceNameForModel, UnsupportedError, index, NumericSequence, Adapter, oneToManyOnUpdate, } from "@decaf-ts/core";
|
|
8
|
+
import { FabricContractRepository } from "./FabricContractRepository.js";
|
|
9
|
+
import { FabricStatement } from "./FabricContractStatement.js";
|
|
10
|
+
import { FabricContractSequence } from "./FabricContractSequence.js";
|
|
11
|
+
import { MissingContextError } from "./../shared/errors.js";
|
|
12
|
+
import { FabricFlavour } from "./../shared/constants.js";
|
|
13
|
+
import { SimpleDeterministicSerializer } from "./../shared/SimpleDeterministicSerializer.js";
|
|
14
|
+
import { oneToManyOnCreate, oneToManyOnDelete, oneToOneOnCreate, oneToOneOnDelete, oneToOneOnUpdate, populate as pop, } from "./FabricConstruction.js";
|
|
15
|
+
import { apply } from "@decaf-ts/reflection";
|
|
16
|
+
/**
|
|
17
|
+
* @description Sets the creator or updater field in a model based on the user in the context
|
|
18
|
+
* @summary Callback function used in decorators to automatically set the created_by or updated_by fields
|
|
19
|
+
* with the username from the context when a document is created or updated
|
|
20
|
+
* @template M - Type extending Model
|
|
21
|
+
* @template R - Type extending NanoRepository<M>
|
|
22
|
+
* @template V - Type extending RelationsMetadata
|
|
23
|
+
* @param {R} this - The repository instance
|
|
24
|
+
* @param {FabricContractContext} context - The operation context containing user information
|
|
25
|
+
* @param {V} data - The relation metadata
|
|
26
|
+
* @param {string} key - The property key to set with the username
|
|
27
|
+
* @param {M} model - The model instance being created or updated
|
|
28
|
+
* @return {Promise<void>} A promise that resolves when the operation is complete
|
|
29
|
+
* @function createdByOnFabricCreateUpdate
|
|
30
|
+
* @memberOf module:fabric.contracts
|
|
31
|
+
* @mermaid
|
|
32
|
+
* sequenceDiagram
|
|
33
|
+
* participant F as createdByOnNanoCreateUpdate
|
|
34
|
+
* participant C as Context
|
|
35
|
+
* participant M as Model
|
|
36
|
+
* F->>C: get("user")
|
|
37
|
+
* C-->>F: user object
|
|
38
|
+
* F->>M: set key to user.name
|
|
39
|
+
* Note over F: If no user in context
|
|
40
|
+
* F-->>F: throw UnsupportedError
|
|
41
|
+
*/
|
|
42
|
+
export async function createdByOnFabricCreateUpdate(context, data, key, model) {
|
|
43
|
+
try {
|
|
44
|
+
const user = context.get("clientIdentity");
|
|
45
|
+
model[key] = user.getID();
|
|
46
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
47
|
+
}
|
|
48
|
+
catch (e) {
|
|
49
|
+
throw new UnsupportedError("No User found in context. Please provide a user in the context");
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* @description Primary key auto-assignment callback for Fabric models
|
|
54
|
+
* @summary Generates and assigns a primary key value to the specified model property using a Fabric-backed sequence when the model is created. If the sequence name is not provided in options, it is derived from the model via sequenceNameForModel. The assigned key is defined as non-writable and enumerable.
|
|
55
|
+
* @template M - Type extending Model for the target instance
|
|
56
|
+
* @template R - Type extending FabricContractRepository for repository context
|
|
57
|
+
* @template V - Type extending SequenceOptions to configure sequence behavior
|
|
58
|
+
* @template F - Type extending FabricContractFlags for contextual flags
|
|
59
|
+
* @param {R} this - The repository instance invoking the callback
|
|
60
|
+
* @param {FabricContractContext} context - Fabric contract context containing invocation metadata
|
|
61
|
+
* @param {V} data - Sequence options used to configure or locate the sequence
|
|
62
|
+
* @param {string} key - The primary key property name to assign on the model
|
|
63
|
+
* @param {M} model - The model instance to receive the generated primary key
|
|
64
|
+
* @return {Promise<void>} Resolves when the key is assigned or when no action is required
|
|
65
|
+
* @function pkFabricOnCreate
|
|
66
|
+
* @memberOf module:for-fabric.contracts
|
|
67
|
+
* @mermaid
|
|
68
|
+
* sequenceDiagram
|
|
69
|
+
* participant R as Repository
|
|
70
|
+
* participant C as Context<F>
|
|
71
|
+
* participant S as FabricContractDBSequence
|
|
72
|
+
* participant M as Model
|
|
73
|
+
* R->>R: derive sequence name if missing
|
|
74
|
+
* R->>S: adapter.Sequence(options)
|
|
75
|
+
* S-->>R: sequence instance
|
|
76
|
+
* R->>S: next(context)
|
|
77
|
+
* S-->>R: next value
|
|
78
|
+
* R->>M: define non-writable primary key
|
|
79
|
+
*/
|
|
80
|
+
export async function pkFabricOnCreate(context, data, key, model) {
|
|
81
|
+
if (!data.type || model[key]) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const setPrimaryKeyValue = function (target, propertyKey, value) {
|
|
85
|
+
Object.defineProperty(target, propertyKey, {
|
|
86
|
+
enumerable: true,
|
|
87
|
+
writable: false,
|
|
88
|
+
configurable: true,
|
|
89
|
+
value: value,
|
|
90
|
+
});
|
|
91
|
+
};
|
|
92
|
+
if (!data.name)
|
|
93
|
+
data.name = sequenceNameForModel(model, "pk");
|
|
94
|
+
let sequence;
|
|
95
|
+
try {
|
|
96
|
+
sequence = (await this.adapter.Sequence(data));
|
|
97
|
+
}
|
|
98
|
+
catch (e) {
|
|
99
|
+
throw new InternalError(`Failed to instantiate Sequence ${data.name}: ${e}`);
|
|
100
|
+
}
|
|
101
|
+
const next = await sequence.next(context);
|
|
102
|
+
setPrimaryKeyValue(model, key, next);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* @description Adapter for Hyperledger Fabric chaincode state database operations
|
|
106
|
+
* @summary Provides a CouchDB-like interface for interacting with the Fabric state database from within a chaincode contract
|
|
107
|
+
* @template void - No configuration needed for contract adapter
|
|
108
|
+
* @template FabricContractFlags - Flags specific to Fabric contract operations
|
|
109
|
+
* @template FabricContractContext - Context type for Fabric contract operations
|
|
110
|
+
* @class FabricContractAdapter
|
|
111
|
+
* @example
|
|
112
|
+
* ```typescript
|
|
113
|
+
* // In a Fabric chaincode contract class
|
|
114
|
+
* import { FabricContractAdapter } from '@decaf-ts/for-fabric';
|
|
115
|
+
*
|
|
116
|
+
* export class MyContract extends Contract {
|
|
117
|
+
* private adapter = new FabricContractAdapter();
|
|
118
|
+
*
|
|
119
|
+
* @Transaction()
|
|
120
|
+
* async createAsset(ctx: Context, id: string, data: string): Promise<void> {
|
|
121
|
+
* const model = { id, data, timestamp: Date.now() };
|
|
122
|
+
* await this.adapter.create('assets', id, model, {}, { stub: ctx.stub });
|
|
123
|
+
* }
|
|
124
|
+
* }
|
|
125
|
+
* ```
|
|
126
|
+
* @mermaid
|
|
127
|
+
* sequenceDiagram
|
|
128
|
+
* participant Contract
|
|
129
|
+
* participant FabricContractAdapter
|
|
130
|
+
* participant Stub
|
|
131
|
+
* participant StateDB
|
|
132
|
+
*
|
|
133
|
+
* Contract->>FabricContractAdapter: create(tableName, id, model, transient, ctx)
|
|
134
|
+
* FabricContractAdapter->>FabricContractAdapter: Serialize model to JSON
|
|
135
|
+
* FabricContractAdapter->>Stub: putState(id, serializedData)
|
|
136
|
+
* Stub->>StateDB: Write data
|
|
137
|
+
* StateDB-->>Stub: Success
|
|
138
|
+
* Stub-->>FabricContractAdapter: Success
|
|
139
|
+
* FabricContractAdapter-->>Contract: model
|
|
140
|
+
*/
|
|
141
|
+
export class FabricContractAdapter extends CouchDBAdapter {
|
|
142
|
+
getClient() {
|
|
143
|
+
throw new UnsupportedError("Client is not supported in Fabric contracts");
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* @description Text decoder for converting binary data to strings
|
|
147
|
+
*/
|
|
148
|
+
static { this.textDecoder = new TextDecoder("utf8"); }
|
|
149
|
+
static { this.serializer = new SimpleDeterministicSerializer(); }
|
|
150
|
+
/**
|
|
151
|
+
* @description Creates a logger for a specific chaincode context
|
|
152
|
+
* @summary Returns a ContractLogger instance configured for the current context
|
|
153
|
+
* @param {Ctx} ctx - The Fabric chaincode context
|
|
154
|
+
* @return {ContractLogger} The logger instance
|
|
155
|
+
*/
|
|
156
|
+
logFor(ctx) {
|
|
157
|
+
return Logging.for(FabricContractAdapter, {}, ctx);
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* @description Gets the repository constructor for this adapter
|
|
161
|
+
* @summary Returns the FabricContractRepository constructor for creating repositories
|
|
162
|
+
* @template M - Type extending Model
|
|
163
|
+
* @return {Constructor<Repository<M, MangoQuery, FabricContractAdapter, FabricContractFlags, FabricContractContext>>} The repository constructor
|
|
164
|
+
*/
|
|
165
|
+
repository() {
|
|
166
|
+
return FabricContractRepository;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* @description Creates a new FabricContractAdapter instance
|
|
170
|
+
* @summary Initializes an adapter for interacting with the Fabric state database
|
|
171
|
+
* @param {void} scope - Not used in this adapter
|
|
172
|
+
* @param {string} [alias] - Optional alias for the adapter instance
|
|
173
|
+
*/
|
|
174
|
+
constructor(scope, alias) {
|
|
175
|
+
super(scope, FabricFlavour, alias);
|
|
176
|
+
/**
|
|
177
|
+
* @description Context constructor for this adapter
|
|
178
|
+
* @summary Overrides the base Context constructor with FabricContractContext
|
|
179
|
+
*/
|
|
180
|
+
this.Context = FabricContractContext;
|
|
181
|
+
}
|
|
182
|
+
for(config, ...args) {
|
|
183
|
+
return super.for(config, ...args);
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* @description Creates a record in the state database
|
|
187
|
+
* @summary Serializes a model and stores it in the Fabric state database
|
|
188
|
+
* @param {string} tableName - The name of the table/collection
|
|
189
|
+
* @param {string | number} id - The record identifier
|
|
190
|
+
* @param {Record<string, any>} model - The record data
|
|
191
|
+
* @param {Record<string, any>} transient - Transient data (not used in this implementation)
|
|
192
|
+
* @param {...any[]} args - Additional arguments, including the chaincode stub and logger
|
|
193
|
+
* @return {Promise<Record<string, any>>} Promise resolving to the created record
|
|
194
|
+
*/
|
|
195
|
+
async create(tableName, id, model, ...args) {
|
|
196
|
+
const { stub, logger } = args.pop();
|
|
197
|
+
const log = logger.for(this.create);
|
|
198
|
+
try {
|
|
199
|
+
log.info(`adding entry to ${tableName} table with pk ${id}`);
|
|
200
|
+
model = await this.putState(stub, id.toString(), model);
|
|
201
|
+
}
|
|
202
|
+
catch (e) {
|
|
203
|
+
throw this.parseError(e);
|
|
204
|
+
}
|
|
205
|
+
return model;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* @description Reads a record from the state database
|
|
209
|
+
* @summary Retrieves and deserializes a record from the Fabric state database
|
|
210
|
+
* @param {string} tableName - The name of the table/collection
|
|
211
|
+
* @param {string | number} id - The record identifier
|
|
212
|
+
* @param {...any[]} args - Additional arguments, including the chaincode stub and logger
|
|
213
|
+
* @return {Promise<Record<string, any>>} Promise resolving to the retrieved record
|
|
214
|
+
*/
|
|
215
|
+
async read(tableName, id, ...args) {
|
|
216
|
+
const { stub, logger } = args.pop();
|
|
217
|
+
const log = logger.for(this.read);
|
|
218
|
+
let model;
|
|
219
|
+
try {
|
|
220
|
+
const results = await this.readState(stub, tableName, id.toString());
|
|
221
|
+
if (results.length < 1) {
|
|
222
|
+
log.debug(`No record found for id ${id} in ${tableName} table`);
|
|
223
|
+
throw new NotFoundError(`No record found for id ${id} in ${tableName} table`);
|
|
224
|
+
}
|
|
225
|
+
else if (results.length < 2) {
|
|
226
|
+
log.debug(`No record found for id ${id} in ${tableName} table`);
|
|
227
|
+
model = results.pop();
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
model = this.mergeModels(results);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
catch (e) {
|
|
234
|
+
throw this.parseError(e);
|
|
235
|
+
}
|
|
236
|
+
return model;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* @description Updates a record in the state database
|
|
240
|
+
* @summary Serializes a model and updates it in the Fabric state database
|
|
241
|
+
* @param {string} tableName - The name of the table/collection
|
|
242
|
+
* @param {string | number} id - The record identifier
|
|
243
|
+
* @param {Record<string, any>} model - The updated record data
|
|
244
|
+
* @param {Record<string, any>} transient - Transient data (not used in this implementation)
|
|
245
|
+
* @param {...any[]} args - Additional arguments, including the chaincode stub and logger
|
|
246
|
+
* @return {Promise<Record<string, any>>} Promise resolving to the updated record
|
|
247
|
+
*/
|
|
248
|
+
async update(tableName, id, model, ...args) {
|
|
249
|
+
const { stub, logger } = args.pop();
|
|
250
|
+
const log = logger.for(this.update);
|
|
251
|
+
try {
|
|
252
|
+
log.info(`updating entry to ${tableName} table with pk ${id}`);
|
|
253
|
+
model = await this.putState(stub, id.toString(), model);
|
|
254
|
+
}
|
|
255
|
+
catch (e) {
|
|
256
|
+
throw this.parseError(e);
|
|
257
|
+
}
|
|
258
|
+
return model;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* @description Deletes a record from the state database
|
|
262
|
+
* @summary Retrieves a record and then removes it from the Fabric state database
|
|
263
|
+
* @param {string} tableName - The name of the table/collection
|
|
264
|
+
* @param {string | number} id - The record identifier to delete
|
|
265
|
+
* @param {...any[]} args - Additional arguments, including the chaincode stub and logger
|
|
266
|
+
* @return {Promise<Record<string, any>>} Promise resolving to the deleted record
|
|
267
|
+
*/
|
|
268
|
+
async delete(tableName, id, ...args) {
|
|
269
|
+
const ctx = args.pop();
|
|
270
|
+
const { stub, logger } = ctx;
|
|
271
|
+
const log = logger.for(this.delete);
|
|
272
|
+
args.push(ctx);
|
|
273
|
+
let model;
|
|
274
|
+
try {
|
|
275
|
+
model = await this.read(tableName, id, ...args);
|
|
276
|
+
log.verbose(`deleting entry with pk ${id} from ${tableName} table`);
|
|
277
|
+
this.deleteState(stub, tableName, id.toString());
|
|
278
|
+
}
|
|
279
|
+
catch (e) {
|
|
280
|
+
throw this.parseError(e);
|
|
281
|
+
}
|
|
282
|
+
return model;
|
|
283
|
+
}
|
|
284
|
+
async deleteState(stub, tableName, id,
|
|
285
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
286
|
+
...args) {
|
|
287
|
+
const composedKey = stub.createCompositeKey(tableName, [String(id)]);
|
|
288
|
+
await stub.deleteState(composedKey);
|
|
289
|
+
}
|
|
290
|
+
async putState(stub, id, model,
|
|
291
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
292
|
+
...args) {
|
|
293
|
+
let data;
|
|
294
|
+
try {
|
|
295
|
+
data = Buffer.from(FabricContractAdapter.serializer.serialize(model));
|
|
296
|
+
}
|
|
297
|
+
catch (e) {
|
|
298
|
+
throw new SerializationError(`Failed to serialize record with id ${id}: ${e}`);
|
|
299
|
+
}
|
|
300
|
+
await stub.putState(id.toString(), data);
|
|
301
|
+
return model;
|
|
302
|
+
}
|
|
303
|
+
async readState(stub, tableName, id,
|
|
304
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
305
|
+
...args) {
|
|
306
|
+
const composedKey = stub.createCompositeKey(tableName, [String(id)]);
|
|
307
|
+
const results = [];
|
|
308
|
+
let res = await stub.getState(composedKey);
|
|
309
|
+
if (res.toString() === "")
|
|
310
|
+
throw new NotFoundError(`Record with id ${id} not found`);
|
|
311
|
+
try {
|
|
312
|
+
res = FabricContractAdapter.serializer.deserialize(res.toString()
|
|
313
|
+
// model.constructor.name
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
catch (e) {
|
|
317
|
+
throw new SerializationError(`Failed to parse record: ${e}`);
|
|
318
|
+
}
|
|
319
|
+
results.push(res);
|
|
320
|
+
return results;
|
|
321
|
+
}
|
|
322
|
+
async queryResult(stub, rawInput,
|
|
323
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
324
|
+
...args) {
|
|
325
|
+
return (await stub.getQueryResult(JSON.stringify(rawInput)));
|
|
326
|
+
}
|
|
327
|
+
async queryResultPaginated(stub, rawInput, limit = 250, skip,
|
|
328
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
329
|
+
...args) {
|
|
330
|
+
return (await stub.getQueryResultWithPagination(JSON.stringify(rawInput), limit, skip?.toString()));
|
|
331
|
+
}
|
|
332
|
+
mergeModels(results) {
|
|
333
|
+
const extract = (model) => Object.entries(model).reduce((accum, [key, val]) => {
|
|
334
|
+
if (typeof val !== "undefined")
|
|
335
|
+
accum[key] = val;
|
|
336
|
+
return accum;
|
|
337
|
+
}, {});
|
|
338
|
+
let finalModel = results.pop();
|
|
339
|
+
for (const res of results) {
|
|
340
|
+
finalModel = Object.assign({}, extract(finalModel), extract(res));
|
|
341
|
+
}
|
|
342
|
+
return finalModel;
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* @description Decodes binary data to string
|
|
346
|
+
* @summary Converts a Uint8Array to a string using UTF-8 encoding
|
|
347
|
+
* @param {Uint8Array} buffer - The binary data to decode
|
|
348
|
+
* @return {string} The decoded string
|
|
349
|
+
*/
|
|
350
|
+
decode(buffer) {
|
|
351
|
+
return FabricContractAdapter.textDecoder.decode(buffer);
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* @description Creates operation flags for Fabric contract operations
|
|
355
|
+
* @summary Merges default flags with Fabric-specific context information
|
|
356
|
+
* @template M - Type extending Model
|
|
357
|
+
* @param {OperationKeys} operation - The operation being performed
|
|
358
|
+
* @param {Constructor<M>} model - The model constructor
|
|
359
|
+
* @param {Partial<FabricContractFlags>} flags - Partial flags to merge with defaults
|
|
360
|
+
* @param {Ctx} ctx - The Fabric chaincode context
|
|
361
|
+
* @return {FabricContractFlags} The merged flags
|
|
362
|
+
*/
|
|
363
|
+
async flags(operation, model, flags, ctx, ...args) {
|
|
364
|
+
return Object.assign(await super.flags(operation, model, flags, ...args), {
|
|
365
|
+
stub: ctx.stub,
|
|
366
|
+
identity: ctx.clientIdentity,
|
|
367
|
+
logger: this.logFor(ctx),
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* @description Creates an index for a model
|
|
372
|
+
* @summary This method is not implemented for Fabric contracts and returns a resolved promise
|
|
373
|
+
* @template M - Type extending Model
|
|
374
|
+
* @param {Constructor<M>} models - The model constructor
|
|
375
|
+
* @return {Promise<void>} Promise that resolves immediately
|
|
376
|
+
*/
|
|
377
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
378
|
+
index(models) {
|
|
379
|
+
return Promise.resolve(undefined);
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* @description Processes results from a state query iterator
|
|
383
|
+
* @summary Iterates through query results and converts them to a structured format
|
|
384
|
+
* @param {Logger} log - Logger instance for debugging
|
|
385
|
+
* @param {Iterators.StateQueryIterator} iterator - The state query iterator
|
|
386
|
+
* @param {boolean} [isHistory=false] - Whether this is a history query
|
|
387
|
+
* @return {Promise<any[]>} Promise resolving to an array of processed results
|
|
388
|
+
* @mermaid
|
|
389
|
+
* sequenceDiagram
|
|
390
|
+
* participant Caller
|
|
391
|
+
* participant ResultIterator
|
|
392
|
+
* participant Iterator
|
|
393
|
+
*
|
|
394
|
+
* Caller->>ResultIterator: resultIterator(log, iterator, isHistory)
|
|
395
|
+
* loop Until done
|
|
396
|
+
* ResultIterator->>Iterator: next()
|
|
397
|
+
* Iterator-->>ResultIterator: { value, done }
|
|
398
|
+
* alt Has value
|
|
399
|
+
* ResultIterator->>ResultIterator: Process value based on isHistory
|
|
400
|
+
* ResultIterator->>ResultIterator: Add to results array
|
|
401
|
+
* end
|
|
402
|
+
* end
|
|
403
|
+
* ResultIterator->>Iterator: close()
|
|
404
|
+
* ResultIterator-->>Caller: allResults
|
|
405
|
+
*/
|
|
406
|
+
async resultIterator(log, iterator, isHistory = false) {
|
|
407
|
+
const allResults = [];
|
|
408
|
+
let res = await iterator.next();
|
|
409
|
+
while (!res.done) {
|
|
410
|
+
if (res.value && res.value.value.toString()) {
|
|
411
|
+
let jsonRes = {};
|
|
412
|
+
log.debug(res.value.value.toString("utf8"));
|
|
413
|
+
if (isHistory /* && isHistory === true*/) {
|
|
414
|
+
jsonRes.TxId = res.value.txId;
|
|
415
|
+
jsonRes.Timestamp = res.value.timestamp;
|
|
416
|
+
try {
|
|
417
|
+
jsonRes.Value = JSON.parse(res.value.value.toString("utf8"));
|
|
418
|
+
}
|
|
419
|
+
catch (err) {
|
|
420
|
+
log.error(err);
|
|
421
|
+
jsonRes.Value = res.value.value.toString("utf8");
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
else {
|
|
425
|
+
try {
|
|
426
|
+
jsonRes = JSON.parse(res.value.value.toString("utf8"));
|
|
427
|
+
}
|
|
428
|
+
catch (err) {
|
|
429
|
+
log.error(err);
|
|
430
|
+
jsonRes = res.value.value.toString("utf8");
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
allResults.push(jsonRes);
|
|
434
|
+
}
|
|
435
|
+
res = await iterator.next();
|
|
436
|
+
}
|
|
437
|
+
log.debug(`Closing iterator after ${allResults.length} results`);
|
|
438
|
+
iterator.close(); // purposely not await. let iterator close on its own
|
|
439
|
+
return allResults;
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* @description Executes a raw query against the state database
|
|
443
|
+
* @summary Performs a rich query using CouchDB syntax against the Fabric state database
|
|
444
|
+
* @template R - The return type
|
|
445
|
+
* @param {MangoQuery} rawInput - The Mango Query to execute
|
|
446
|
+
* @param {boolean} docsOnly - Whether to return only documents (not used in this implementation)
|
|
447
|
+
* @param {...any[]} args - Additional arguments, including the chaincode stub and logger
|
|
448
|
+
* @return {Promise<R>} Promise resolving to the query results
|
|
449
|
+
* @mermaid
|
|
450
|
+
* sequenceDiagram
|
|
451
|
+
* participant Caller
|
|
452
|
+
* participant FabricContractAdapter
|
|
453
|
+
* participant Stub
|
|
454
|
+
* participant StateDB
|
|
455
|
+
*
|
|
456
|
+
* Caller->>FabricContractAdapter: raw(rawInput, docsOnly, ctx)
|
|
457
|
+
* FabricContractAdapter->>FabricContractAdapter: Extract limit and skip
|
|
458
|
+
* alt With pagination
|
|
459
|
+
* FabricContractAdapter->>Stub: getQueryResultWithPagination(query, limit, skip)
|
|
460
|
+
* else Without pagination
|
|
461
|
+
* FabricContractAdapter->>Stub: getQueryResult(query)
|
|
462
|
+
* end
|
|
463
|
+
* Stub->>StateDB: Execute query
|
|
464
|
+
* StateDB-->>Stub: Iterator
|
|
465
|
+
* Stub-->>FabricContractAdapter: Iterator
|
|
466
|
+
* FabricContractAdapter->>FabricContractAdapter: resultIterator(log, iterator)
|
|
467
|
+
* FabricContractAdapter-->>Caller: results
|
|
468
|
+
*/
|
|
469
|
+
async raw(rawInput, docsOnly, ...args) {
|
|
470
|
+
const { stub, logger } = args.pop();
|
|
471
|
+
const log = logger.for(this.raw);
|
|
472
|
+
const { skip, limit } = rawInput;
|
|
473
|
+
let iterator;
|
|
474
|
+
if (limit || skip) {
|
|
475
|
+
delete rawInput["limit"];
|
|
476
|
+
delete rawInput["skip"];
|
|
477
|
+
log.debug(`Retrieving paginated iterator: limit: ${limit}/ skip: ${skip}`);
|
|
478
|
+
const response = (await this.queryResultPaginated(stub, rawInput, limit || 250, skip?.toString()));
|
|
479
|
+
iterator = response.iterator;
|
|
480
|
+
}
|
|
481
|
+
else {
|
|
482
|
+
log.debug("Retrieving iterator");
|
|
483
|
+
iterator = (await this.queryResult(stub, rawInput));
|
|
484
|
+
}
|
|
485
|
+
log.debug("Iterator acquired");
|
|
486
|
+
const results = (await this.resultIterator(log, iterator));
|
|
487
|
+
log.debug(`returning {0} results`, `${Array.isArray(results) ? results.length : 1}`);
|
|
488
|
+
return results;
|
|
489
|
+
}
|
|
490
|
+
Statement(ctx) {
|
|
491
|
+
if (!ctx) {
|
|
492
|
+
throw new MissingContextError("Context is required");
|
|
493
|
+
}
|
|
494
|
+
return new FabricStatement(this, ctx);
|
|
495
|
+
}
|
|
496
|
+
async Sequence(options) {
|
|
497
|
+
return new FabricContractSequence(options, this);
|
|
498
|
+
}
|
|
499
|
+
async createAll(tableName, id, model, ...args) {
|
|
500
|
+
if (id.length !== model.length)
|
|
501
|
+
throw new InternalError("Ids and models must have the same length");
|
|
502
|
+
const { logger } = args[args.length - 1];
|
|
503
|
+
const log = logger.for(this.createAll);
|
|
504
|
+
log.info(`Creating ${id.length} entries ${tableName} table`);
|
|
505
|
+
log.debug(`pks: ${id}`);
|
|
506
|
+
return Promise.all(id.map(async (i, index) => {
|
|
507
|
+
return this.create(tableName, i, model[index], ...args);
|
|
508
|
+
}));
|
|
509
|
+
}
|
|
510
|
+
async updateAll(tableName, id, model, ...args) {
|
|
511
|
+
if (id.length !== model.length)
|
|
512
|
+
throw new InternalError("Ids and models must have the same length");
|
|
513
|
+
const { logger } = args[args.length - 1];
|
|
514
|
+
const log = logger.for(this.createAll);
|
|
515
|
+
log.info(`Updating ${id.length} entries ${tableName} table`);
|
|
516
|
+
log.debug(`pks: ${id}`);
|
|
517
|
+
return Promise.all(id.map(async (i, index) => {
|
|
518
|
+
return this.update(tableName, i, model[index], ...args);
|
|
519
|
+
}));
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
*
|
|
523
|
+
* @param model
|
|
524
|
+
* @param {string} pk
|
|
525
|
+
* @param args
|
|
526
|
+
*/
|
|
527
|
+
prepare(model, pk, ...args) {
|
|
528
|
+
const { stub, logger } = args.pop();
|
|
529
|
+
const tableName = args.shift();
|
|
530
|
+
const log = logger.for(this.prepare);
|
|
531
|
+
const split = modelToTransient(model);
|
|
532
|
+
const result = Object.entries(split.model).reduce((accum, [key, val]) => {
|
|
533
|
+
if (typeof val === "undefined")
|
|
534
|
+
return accum;
|
|
535
|
+
const mappedProp = Repository.column(model, key);
|
|
536
|
+
if (this.isReserved(mappedProp))
|
|
537
|
+
throw new InternalError(`Property name ${mappedProp} is reserved`);
|
|
538
|
+
accum[mappedProp] = val;
|
|
539
|
+
return accum;
|
|
540
|
+
}, {});
|
|
541
|
+
if (model[PersistenceKeys.METADATA]) {
|
|
542
|
+
log.silly(`Passing along persistence metadata for ${model[PersistenceKeys.METADATA]}`);
|
|
543
|
+
Object.defineProperty(result, PersistenceKeys.METADATA, {
|
|
544
|
+
enumerable: false,
|
|
545
|
+
writable: false,
|
|
546
|
+
configurable: true,
|
|
547
|
+
value: model[PersistenceKeys.METADATA],
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
log.info(`Preparing record for ${tableName} table with pk ${model[pk]}`);
|
|
551
|
+
return {
|
|
552
|
+
record: result,
|
|
553
|
+
id: stub.createCompositeKey(tableName, [String(model[pk])]),
|
|
554
|
+
transient: split.transient,
|
|
555
|
+
};
|
|
556
|
+
}
|
|
557
|
+
revert(obj, clazz, pk, id, transient) {
|
|
558
|
+
const log = this.log.for(this.revert);
|
|
559
|
+
const ob = {};
|
|
560
|
+
ob[pk] = id;
|
|
561
|
+
const m = (typeof clazz === "string" ? Model.build(ob, clazz) : new clazz(ob));
|
|
562
|
+
log.silly(`Rebuilding model ${m.constructor.name} id ${id}`);
|
|
563
|
+
const metadata = obj[PersistenceKeys.METADATA];
|
|
564
|
+
const result = Object.keys(m).reduce((accum, key) => {
|
|
565
|
+
accum[key] = obj[Repository.column(accum, key)];
|
|
566
|
+
return accum;
|
|
567
|
+
}, m);
|
|
568
|
+
if (transient) {
|
|
569
|
+
log.verbose(`re-adding transient properties: ${Object.keys(transient).join(", ")}`);
|
|
570
|
+
Object.entries(transient).forEach(([key, val]) => {
|
|
571
|
+
if (key in result && result[key] !== undefined)
|
|
572
|
+
throw new InternalError(`Transient property ${key} already exists on model ${m.constructor.name}. should be impossible`);
|
|
573
|
+
result[key] = val;
|
|
574
|
+
});
|
|
575
|
+
}
|
|
576
|
+
if (metadata) {
|
|
577
|
+
log.silly(`Passing along ${this.flavour} persistence metadata for ${m.constructor.name} id ${id}: ${metadata}`);
|
|
578
|
+
Object.defineProperty(result, PersistenceKeys.METADATA, {
|
|
579
|
+
enumerable: false,
|
|
580
|
+
configurable: false,
|
|
581
|
+
writable: false,
|
|
582
|
+
value: metadata,
|
|
583
|
+
});
|
|
584
|
+
}
|
|
585
|
+
return result;
|
|
586
|
+
}
|
|
587
|
+
createPrefix(tableName, id, model, ...args) {
|
|
588
|
+
const ctx = args.pop();
|
|
589
|
+
const record = {};
|
|
590
|
+
record[CouchDBKeys.TABLE] = tableName;
|
|
591
|
+
// record[CouchDBKeys.ID] = this.generateId(tableName, id);
|
|
592
|
+
Object.assign(record, model);
|
|
593
|
+
return [tableName, id, record, ctx];
|
|
594
|
+
}
|
|
595
|
+
updatePrefix(tableName, id, model, ...args) {
|
|
596
|
+
const ctx = args.pop();
|
|
597
|
+
const record = {};
|
|
598
|
+
record[CouchDBKeys.TABLE] = tableName;
|
|
599
|
+
// record[CouchDBKeys.ID] = this.generateId(tableName, id);
|
|
600
|
+
Object.assign(record, model);
|
|
601
|
+
return [tableName, id, record, ctx];
|
|
602
|
+
}
|
|
603
|
+
createAllPrefix(tableName, ids, models, ...args) {
|
|
604
|
+
if (ids.length !== models.length)
|
|
605
|
+
throw new InternalError("Ids and models must have the same length");
|
|
606
|
+
const ctx = args.pop();
|
|
607
|
+
const records = ids.map((id, count) => {
|
|
608
|
+
const record = {};
|
|
609
|
+
record[CouchDBKeys.TABLE] = tableName;
|
|
610
|
+
// record[CouchDBKeys.ID] = this.generateId(tableName, id);
|
|
611
|
+
Object.assign(record, models[count]);
|
|
612
|
+
return record;
|
|
613
|
+
});
|
|
614
|
+
return [tableName, ids, records, ctx];
|
|
615
|
+
}
|
|
616
|
+
updateAllPrefix(tableName, ids, models, ...args) {
|
|
617
|
+
if (ids.length !== models.length)
|
|
618
|
+
throw new InternalError("Ids and models must have the same length");
|
|
619
|
+
const ctx = args.pop();
|
|
620
|
+
const records = ids.map((id, count) => {
|
|
621
|
+
const record = {};
|
|
622
|
+
record[CouchDBKeys.TABLE] = tableName;
|
|
623
|
+
Object.assign(record, models[count]);
|
|
624
|
+
return record;
|
|
625
|
+
});
|
|
626
|
+
return [tableName, ids, records, ctx];
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
629
|
+
* @description Static method for decoration overrides
|
|
630
|
+
* @summary Overrides/extends decaf decoration with Fabric-specific functionality
|
|
631
|
+
* @static
|
|
632
|
+
* @override
|
|
633
|
+
* @return {void}
|
|
634
|
+
*/
|
|
635
|
+
static decoration() {
|
|
636
|
+
super.decoration();
|
|
637
|
+
const createdByKey = Repository.key(PersistenceKeys.CREATED_BY);
|
|
638
|
+
const updatedByKey = Repository.key(PersistenceKeys.UPDATED_BY);
|
|
639
|
+
Decoration.flavouredAs(FabricFlavour)
|
|
640
|
+
.for(createdByKey)
|
|
641
|
+
.define(onCreate(createdByOnFabricCreateUpdate), propMetadata(createdByKey, {}))
|
|
642
|
+
.apply();
|
|
643
|
+
Decoration.flavouredAs(FabricFlavour)
|
|
644
|
+
.for(updatedByKey)
|
|
645
|
+
.define(onCreateUpdate(createdByOnFabricCreateUpdate), propMetadata(updatedByKey, {}))
|
|
646
|
+
.apply();
|
|
647
|
+
const pkKey = Repository.key(DBKeys.ID);
|
|
648
|
+
Decoration.flavouredAs(FabricFlavour)
|
|
649
|
+
.for(pkKey)
|
|
650
|
+
.define(index([OrderDirection.ASC, OrderDirection.DSC]), required(), readonly(),
|
|
651
|
+
// type([String.name, Number.name, BigInt.name]),
|
|
652
|
+
propMetadata(pkKey, NumericSequence), onCreate(pkFabricOnCreate, NumericSequence))
|
|
653
|
+
.apply();
|
|
654
|
+
const columnKey = Adapter.key(PersistenceKeys.COLUMN);
|
|
655
|
+
Decoration.flavouredAs(FabricFlavour)
|
|
656
|
+
.for(columnKey)
|
|
657
|
+
.extend(FabricProperty())
|
|
658
|
+
.apply();
|
|
659
|
+
const tableKey = Adapter.key(PersistenceKeys.TABLE);
|
|
660
|
+
Decoration.flavouredAs(FabricFlavour)
|
|
661
|
+
.for(tableKey)
|
|
662
|
+
.extend(function table(obj) {
|
|
663
|
+
// const chain: any[] = [];
|
|
664
|
+
// let current = obj;
|
|
665
|
+
// do {
|
|
666
|
+
// chain.push(current);
|
|
667
|
+
// console.log(`Found class: ${current}`);
|
|
668
|
+
// } while (current && current !== Object.prototype);
|
|
669
|
+
// do {
|
|
670
|
+
// current = chain.pop();
|
|
671
|
+
// console.log(`Applying @Object() to class: ${current}`);
|
|
672
|
+
// //TODO: THIS IS NOT WORKING AND THROWS ERROR
|
|
673
|
+
// // FabricObject()(current);
|
|
674
|
+
// } while (chain.length > 1);
|
|
675
|
+
return FabricObject()(obj);
|
|
676
|
+
})
|
|
677
|
+
.apply();
|
|
678
|
+
const oneToOnekey = Repository.key(PersistenceKeys.ONE_TO_ONE);
|
|
679
|
+
function oneToOneDec(clazz, cascade, populate, joinColumnOpts, fk) {
|
|
680
|
+
const meta = {
|
|
681
|
+
class: clazz.name ? clazz.name : clazz,
|
|
682
|
+
cascade: cascade,
|
|
683
|
+
populate: populate,
|
|
684
|
+
};
|
|
685
|
+
if (joinColumnOpts)
|
|
686
|
+
meta.joinTable = joinColumnOpts;
|
|
687
|
+
if (fk)
|
|
688
|
+
meta.name = fk;
|
|
689
|
+
return apply(prop(PersistenceKeys.RELATIONS), type([
|
|
690
|
+
clazz.name ? clazz.name : clazz,
|
|
691
|
+
String.name,
|
|
692
|
+
Number.name,
|
|
693
|
+
BigInt.name,
|
|
694
|
+
]), onCreate(oneToOneOnCreate, meta), onUpdate(oneToOneOnUpdate, meta), onDelete(oneToOneOnDelete, meta), afterAny(pop, meta), propMetadata(oneToOnekey, meta));
|
|
695
|
+
}
|
|
696
|
+
Decoration.flavouredAs(FabricFlavour)
|
|
697
|
+
.for(oneToOnekey)
|
|
698
|
+
.define({
|
|
699
|
+
decorator: oneToOneDec,
|
|
700
|
+
})
|
|
701
|
+
.apply();
|
|
702
|
+
const oneToManyKey = Repository.key(PersistenceKeys.ONE_TO_MANY);
|
|
703
|
+
function oneToManyDec(clazz, cascade, populate, joinTableOpts, fk) {
|
|
704
|
+
const metadata = {
|
|
705
|
+
class: clazz.name ? clazz.name : clazz,
|
|
706
|
+
cascade: cascade,
|
|
707
|
+
populate: populate,
|
|
708
|
+
};
|
|
709
|
+
if (joinTableOpts)
|
|
710
|
+
metadata.joinTable = joinTableOpts;
|
|
711
|
+
if (fk)
|
|
712
|
+
metadata.name = fk;
|
|
713
|
+
return apply(prop(PersistenceKeys.RELATIONS), list([clazz, String, Number, BigInt]), onCreate(oneToManyOnCreate, metadata), onUpdate(oneToManyOnUpdate, metadata), onDelete(oneToManyOnDelete, metadata), afterAny(pop, metadata), propMetadata(oneToManyKey, metadata));
|
|
714
|
+
}
|
|
715
|
+
Decoration.for(oneToManyKey)
|
|
716
|
+
.define({
|
|
717
|
+
decorator: oneToManyDec,
|
|
718
|
+
})
|
|
719
|
+
.apply();
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
FabricContractAdapter.decoration();
|
|
723
|
+
Adapter.setCurrent(FabricFlavour);
|
|
724
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29udHJhY3RBZGFwdGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NvbnRyYWN0cy9Db250cmFjdEFkYXB0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGNBQWMsRUFBRSxXQUFXLEVBQWMsTUFBTSx1QkFBdUIsQ0FBQztBQUNoRixPQUFPLEVBRUwsVUFBVSxFQUNWLElBQUksRUFDSixLQUFLLEVBQ0wsSUFBSSxFQUNKLFlBQVksRUFDWixRQUFRLEVBQ1IsSUFBSSxHQUNMLE1BQU0sZ0NBQWdDLENBQUM7QUFFeEMsT0FBTyxFQUFFLHFCQUFxQixFQUFFLDZCQUEwQjtBQUMxRCxPQUFPLEVBQ0wsUUFBUSxFQUVSLE1BQU0sRUFDTixhQUFhLEVBQ2IsZ0JBQWdCLEVBQ2hCLGFBQWEsRUFDYixRQUFRLEVBQ1IsY0FBYyxFQUNkLFFBQVEsRUFDUixRQUFRLEVBRVIsUUFBUSxFQUNSLGtCQUFrQixHQUNuQixNQUFNLHlCQUF5QixDQUFDO0FBQ2pDLE9BQU8sRUFFTCxNQUFNLElBQUksWUFBWSxFQUN0QixRQUFRLElBQUksY0FBYyxHQUMzQixNQUFNLHFCQUFxQixDQUFDO0FBQzdCLE9BQU8sRUFBVSxPQUFPLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUVwRCxPQUFPLEVBQ0wsY0FBYyxFQUNkLGVBQWUsRUFFZixVQUFVLEVBRVYsb0JBQW9CLEVBRXBCLGdCQUFnQixFQUNoQixLQUFLLEVBQ0wsZUFBZSxFQUNmLE9BQU8sRUFHUCxpQkFBaUIsR0FHbEIsTUFBTSxnQkFBZ0IsQ0FBQztBQUN4QixPQUFPLEVBQUUsd0JBQXdCLEVBQUUsc0NBQW1DO0FBT3RFLE9BQU8sRUFBRSxlQUFlLEVBQUUscUNBQWtDO0FBQzVELE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxvQ0FBaUM7QUFDbEUsT0FBTyxFQUFFLG1CQUFtQixFQUFFLDhCQUF5QjtBQUN2RCxPQUFPLEVBQUUsYUFBYSxFQUFFLGlDQUE0QjtBQUNw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RSxNQUFNLEVBQUUsTUFBTSxFQUFFLE1BQU0sQ0FBQyxDQUFDLEVBQ3ZELFFBQVEsQ0FBQyxpQkFBaUIsRUFBRSxRQUFRLENBQUMsRUFDckMsUUFBUSxDQUFDLGlCQUFpQixFQUFFLFFBQVEsQ0FBQyxFQUNyQyxRQUFRLENBQUMsaUJBQWlCLEVBQUUsUUFBUSxDQUFDLEVBQ3JDLFFBQVEsQ0FBQyxHQUFHLEVBQUUsUUFBUSxDQUFDLEVBQ3ZCLFlBQVksQ0FBQyxZQUFZLEVBQUUsUUFBUSxDQUFDLENBQ3JDLENBQUM7UUFDSixDQUFDO1FBRUQsVUFBVSxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUM7YUFDekIsTUFBTSxDQUFDO1lBQ04sU0FBUyxFQUFFLFlBQVk7U0FDeEIsQ0FBQzthQUNELEtBQUssRUFBRSxDQUFDO0lBQ2IsQ0FBQzs7QUFHSCxxQkFBcUIsQ0FBQyxVQUFVLEVBQUUsQ0FBQztBQUNuQyxPQUFPLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ291Y2hEQkFkYXB0ZXIsIENvdWNoREJLZXlzLCBNYW5nb1F1ZXJ5IH0gZnJvbSBcIkBkZWNhZi10cy9mb3ItY291Y2hkYlwiO1xuaW1wb3J0IHtcbiAgQ29uc3RydWN0b3IsXG4gIERlY29yYXRpb24sXG4gIGxpc3QsXG4gIE1vZGVsLFxuICBwcm9wLFxuICBwcm9wTWV0YWRhdGEsXG4gIHJlcXVpcmVkLFxuICB0eXBlLFxufSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBGYWJyaWNDb250cmFjdEZsYWdzIH0gZnJvbSBcIi4vdHlwZXNcIjtcbmltcG9ydCB7IEZhYnJpY0NvbnRyYWN0Q29udGV4dCB9IGZyb20gXCIuL0NvbnRyYWN0Q29udGV4dFwiO1xuaW1wb3J0IHtcbiAgYWZ0ZXJBbnksXG4gIENvbnRleHQsXG4gIERCS2V5cyxcbiAgSW50ZXJuYWxFcnJvcixcbiAgbW9kZWxUb1RyYW5zaWVudCxcbiAgTm90Rm91bmRFcnJvcixcbiAgb25DcmVhdGUsXG4gIG9uQ3JlYXRlVXBkYXRlLFxuICBvbkRlbGV0ZSxcbiAgb25VcGRhdGUsXG4gIE9wZXJhdGlvbktleXMsXG4gIHJlYWRvbmx5LFxuICBTZXJpYWxpemF0aW9uRXJyb3IsXG59IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHtcbiAgQ29udGV4dCBhcyBDdHgsXG4gIE9iamVjdCBhcyBGYWJyaWNPYmplY3QsXG4gIFByb3BlcnR5IGFzIEZhYnJpY1Byb3BlcnR5LFxufSBmcm9tIFwiZmFicmljLWNvbnRyYWN0LWFwaVwiO1xuaW1wb3J0IHsgTG9nZ2VyLCBMb2dnaW5nIH0gZnJvbSBcIkBkZWNhZi10cy9sb2dnaW5nXCI7XG5pbXBvcnQgeyBDb250cmFjdExvZ2dlciB9IGZyb20gXCIuL2xvZ2dpbmdcIjtcbmltcG9ydCB7XG4gIE9yZGVyRGlyZWN0aW9uLFxuICBQZXJzaXN0ZW5jZUtleXMsXG4gIFJlbGF0aW9uc01ldGFkYXRhLFxuICBSZXBvc2l0b3J5LFxuICBTZXF1ZW5jZSxcbiAgc2VxdWVuY2VOYW1lRm9yTW9kZWwsXG4gIFNlcXVlbmNlT3B0aW9ucyxcbiAgVW5zdXBwb3J0ZWRFcnJvcixcbiAgaW5kZXgsXG4gIE51bWVyaWNTZXF1ZW5jZSxcbiAgQWRhcHRlcixcbiAgQ2FzY2FkZU1ldGFkYXRhLFxuICBKb2luQ29sdW1uT3B0aW9ucyxcbiAgb25lVG9NYW55T25VcGRhdGUsXG4gIEpvaW5UYWJsZU9wdGlvbnMsXG4gIEpvaW5UYWJsZU11bHRpcGxlQ29sdW1uc09wdGlvbnMsXG59IGZyb20gXCJAZGVjYWYtdHMvY29yZVwiO1xuaW1wb3J0IHsgRmFicmljQ29udHJhY3RSZXBvc2l0b3J5IH0gZnJvbSBcIi4vRmFicmljQ29udHJhY3RSZXBvc2l0b3J5XCI7XG5pbXBvcnQge1xuICBDaGFpbmNvZGVTdHViLFxuICBDbGllbnRJZGVudGl0eSxcbiAgSXRlcmF0b3JzLFxuICBTdGF0ZVF1ZXJ5UmVzcG9uc2UsXG59IGZyb20gXCJmYWJyaWMtc2hpbS1hcGlcIjtcbmltcG9ydCB7IEZhYnJpY1N0YXRlbWVudCB9IGZyb20gXCIuL0ZhYnJpY0NvbnRyYWN0U3RhdGVtZW50XCI7XG5pbXBvcnQgeyBGYWJyaWNDb250cmFjdFNlcXVlbmNlIH0gZnJvbSBcIi4vRmFicmljQ29udHJhY3RTZXF1ZW5jZVwiO1xuaW1wb3J0IHsgTWlzc2luZ0NvbnRleHRFcnJvciB9IGZyb20gXCIuLi9zaGFyZWQvZXJyb3JzXCI7XG5pbXBvcnQgeyBGYWJyaWNGbGF2b3VyIH0gZnJvbSBcIi4uL3NoYXJlZC9jb25zdGFudHNcIjtcbmltcG9ydCB7IFNpbXBsZURldGVybWluaXN0aWNTZXJpYWxpemVyIH0gZnJvbSBcIi4uL3NoYXJlZC9TaW1wbGVEZXRlcm1pbmlzdGljU2VyaWFsaXplclwiO1xuaW1wb3J0IHtcbiAgb25lVG9NYW55T25DcmVhdGUsXG4gIG9uZVRvTWFueU9uRGVsZXRlLFxuICBvbmVUb09uZU9uQ3JlYXRlLFxuICBvbmVUb09uZU9uRGVsZXRlLFxuICBvbmVUb09uZU9uVXBkYXRlLFxuICBwb3B1bGF0ZSBhcyBwb3AsXG59IGZyb20gXCIuL0ZhYnJpY0NvbnN0cnVjdGlvblwiO1xuaW1wb3J0IHsgYXBwbHkgfSBmcm9tIFwiQGRlY2FmLXRzL3JlZmxlY3Rpb25cIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUgY3JlYXRvciBvciB1cGRhdGVyIGZpZWxkIGluIGEgbW9kZWwgYmFzZWQgb24gdGhlIHVzZXIgaW4gdGhlIGNvbnRleHRcbiAqIEBzdW1tYXJ5IENhbGxiYWNrIGZ1bmN0aW9uIHVzZWQgaW4gZGVjb3JhdG9ycyB0byBhdXRvbWF0aWNhbGx5IHNldCB0aGUgY3JlYXRlZF9ieSBvciB1cGRhdGVkX2J5IGZpZWxkc1xuICogd2l0aCB0aGUgdXNlcm5hbWUgZnJvbSB0aGUgY29udGV4dCB3aGVuIGEgZG9jdW1lbnQgaXMgY3JlYXRlZCBvciB1cGRhdGVkXG4gKiBAdGVtcGxhdGUgTSAtIFR5cGUgZXh0ZW5kaW5nIE1vZGVsXG4gKiBAdGVtcGxhdGUgUiAtIFR5cGUgZXh0ZW5kaW5nIE5hbm9SZXBvc2l0b3J5PE0+XG4gKiBAdGVtcGxhdGUgViAtIFR5cGUgZXh0ZW5kaW5nIFJlbGF0aW9uc01ldGFkYXRhXG4gKiBAcGFyYW0ge1J9IHRoaXMgLSBUaGUgcmVwb3NpdG9yeSBpbnN0YW5jZVxuICogQHBhcmFtIHtGYWJyaWNDb250cmFjdENvbnRleHR9IGNvbnRleHQgLSBUaGUgb3BlcmF0aW9uIGNvbnRleHQgY29udGFpbmluZyB1c2VyIGluZm9ybWF0aW9uXG4gKiBAcGFyYW0ge1Z9IGRhdGEgLSBUaGUgcmVsYXRpb24gbWV0YWRhdGFcbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgLSBUaGUgcHJvcGVydHkga2V5IHRvIHNldCB3aXRoIHRoZSB1c2VybmFtZVxuICogQHBhcmFtIHtNfSBtb2RlbCAtIFRoZSBtb2RlbCBpbnN0YW5jZSBiZWluZyBjcmVhdGVkIG9yIHVwZGF0ZWRcbiAqIEByZXR1cm4ge1Byb21pc2U8dm9pZD59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIG9wZXJhdGlvbiBpcyBjb21wbGV0ZVxuICogQGZ1bmN0aW9uIGNyZWF0ZWRCeU9uRmFicmljQ3JlYXRlVXBkYXRlXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZhYnJpYy5jb250cmFjdHNcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgRiBhcyBjcmVhdGVkQnlPbk5hbm9DcmVhdGVVcGRhdGVcbiAqICAgcGFydGljaXBhbnQgQyBhcyBDb250ZXh0XG4gKiAgIHBhcnRpY2lwYW50IE0gYXMgTW9kZWxcbiAqICAgRi0+PkM6IGdldChcInVzZXJcIilcbiAqICAgQy0tPj5GOiB1c2VyIG9iamVjdFxuICogICBGLT4+TTogc2V0IGtleSB0byB1c2VyLm5hbWVcbiAqICAgTm90ZSBvdmVyIEY6IElmIG5vIHVzZXIgaW4gY29udGV4dFxuICogICBGLS0+PkY6IHRocm93IFVuc3VwcG9ydGVkRXJyb3JcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZWRCeU9uRmFicmljQ3JlYXRlVXBkYXRlPFxuICBNIGV4dGVuZHMgTW9kZWwsXG4gIFIgZXh0ZW5kcyBGYWJyaWNDb250cmFjdFJlcG9zaXRvcnk8TT4sXG4gIFYgZXh0ZW5kcyBSZWxhdGlvbnNNZXRhZGF0YSxcbj4oXG4gIHRoaXM6IFIsXG4gIGNvbnRleHQ6IENvbnRleHQ8RmFicmljQ29udHJhY3RGbGFncz4sXG4gIGRhdGE6IFYsXG4gIGtleToga2V5b2YgTSxcbiAgbW9kZWw6IE1cbik6IFByb21pc2U8dm9pZD4ge1xuICB0cnkge1xuICAgIGNvbnN0IHVzZXIgPSBjb250ZXh0LmdldChcImNsaWVudElkZW50aXR5XCIpIGFzIENsaWVudElkZW50aXR5O1xuICAgIG1vZGVsW2tleV0gPSB1c2VyLmdldElEKCkgYXMgTVt0eXBlb2Yga2V5XTtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICB0aHJvdyBuZXcgVW5zdXBwb3J0ZWRFcnJvcihcbiAgICAgIFwiTm8gVXNlciBmb3VuZCBpbiBjb250ZXh0LiBQbGVhc2UgcHJvdmlkZSBhIHVzZXIgaW4gdGhlIGNvbnRleHRcIlxuICAgICk7XG4gIH1cbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUHJpbWFyeSBrZXkgYXV0by1hc3NpZ25tZW50IGNhbGxiYWNrIGZvciBGYWJyaWMgbW9kZWxzXG4gKiBAc3VtbWFyeSBHZW5lcmF0ZXMgYW5kIGFzc2lnbnMgYSBwcmltYXJ5IGtleSB2YWx1ZSB0byB0aGUgc3BlY2lmaWVkIG1vZGVsIHByb3BlcnR5IHVzaW5nIGEgRmFicmljLWJhY2tlZCBzZXF1ZW5jZSB3aGVuIHRoZSBtb2RlbCBpcyBjcmVhdGVkLiBJZiB0aGUgc2VxdWVuY2UgbmFtZSBpcyBub3QgcHJvdmlkZWQgaW4gb3B0aW9ucywgaXQgaXMgZGVyaXZlZCBmcm9tIHRoZSBtb2RlbCB2aWEgc2VxdWVuY2VOYW1lRm9yTW9kZWwuIFRoZSBhc3NpZ25lZCBrZXkgaXMgZGVmaW5lZCBhcyBub24td3JpdGFibGUgYW5kIGVudW1lcmFibGUuXG4gKiBAdGVtcGxhdGUgTSAtIFR5cGUgZXh0ZW5kaW5nIE1vZGVsIGZvciB0aGUgdGFyZ2V0IGluc3RhbmNlXG4gKiBAdGVtcGxhdGUgUiAtIFR5cGUgZXh0ZW5kaW5nIEZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeSBmb3IgcmVwb3NpdG9yeSBjb250ZXh0XG4gKiBAdGVtcGxhdGUgViAtIFR5cGUgZXh0ZW5kaW5nIFNlcXVlbmNlT3B0aW9ucyB0byBjb25maWd1cmUgc2VxdWVuY2UgYmVoYXZpb3JcbiAqIEB0ZW1wbGF0ZSBGIC0gVHlwZSBleHRlbmRpbmcgRmFicmljQ29udHJhY3RGbGFncyBmb3IgY29udGV4dHVhbCBmbGFnc1xuICogQHBhcmFtIHtSfSB0aGlzIC0gVGhlIHJlcG9zaXRvcnkgaW5zdGFuY2UgaW52b2tpbmcgdGhlIGNhbGxiYWNrXG4gKiBAcGFyYW0ge0ZhYnJpY0NvbnRyYWN0Q29udGV4dH0gY29udGV4dCAtIEZhYnJpYyBjb250cmFjdCBjb250ZXh0IGNvbnRhaW5pbmcgaW52b2NhdGlvbiBtZXRhZGF0YVxuICogQHBhcmFtIHtWfSBkYXRhIC0gU2VxdWVuY2Ugb3B0aW9ucyB1c2VkIHRvIGNvbmZpZ3VyZSBvciBsb2NhdGUgdGhlIHNlcXVlbmNlXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IC0gVGhlIHByaW1hcnkga2V5IHByb3BlcnR5IG5hbWUgdG8gYXNzaWduIG9uIHRoZSBtb2RlbFxuICogQHBhcmFtIHtNfSBtb2RlbCAtIFRoZSBtb2RlbCBpbnN0YW5jZSB0byByZWNlaXZlIHRoZSBnZW5lcmF0ZWQgcHJpbWFyeSBrZXlcbiAqIEByZXR1cm4ge1Byb21pc2U8dm9pZD59IFJlc29sdmVzIHdoZW4gdGhlIGtleSBpcyBhc3NpZ25lZCBvciB3aGVuIG5vIGFjdGlvbiBpcyByZXF1aXJlZFxuICogQGZ1bmN0aW9uIHBrRmFicmljT25DcmVhdGVcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Zm9yLWZhYnJpYy5jb250cmFjdHNcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgUiBhcyBSZXBvc2l0b3J5XG4gKiAgIHBhcnRpY2lwYW50IEMgYXMgQ29udGV4dDxGPlxuICogICBwYXJ0aWNpcGFudCBTIGFzIEZhYnJpY0NvbnRyYWN0REJTZXF1ZW5jZVxuICogICBwYXJ0aWNpcGFudCBNIGFzIE1vZGVsXG4gKiAgIFItPj5SOiBkZXJpdmUgc2VxdWVuY2UgbmFtZSBpZiBtaXNzaW5nXG4gKiAgIFItPj5TOiBhZGFwdGVyLlNlcXVlbmNlKG9wdGlvbnMpXG4gKiAgIFMtLT4+Ujogc2VxdWVuY2UgaW5zdGFuY2VcbiAqICAgUi0+PlM6IG5leHQoY29udGV4dClcbiAqICAgUy0tPj5SOiBuZXh0IHZhbHVlXG4gKiAgIFItPj5NOiBkZWZpbmUgbm9uLXdyaXRhYmxlIHByaW1hcnkga2V5XG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBwa0ZhYnJpY09uQ3JlYXRlPFxuICBNIGV4dGVuZHMgTW9kZWwsXG4gIFIgZXh0ZW5kcyBGYWJyaWNDb250cmFjdFJlcG9zaXRvcnk8TT4sXG4gIFYgZXh0ZW5kcyBTZXF1ZW5jZU9wdGlvbnMsXG4gIEYgZXh0ZW5kcyBGYWJyaWNDb250cmFjdEZsYWdzLFxuPihcbiAgdGhpczogUixcbiAgY29udGV4dDogQ29udGV4dDxGPixcbiAgZGF0YTogVixcbiAga2V5OiBrZXlvZiBNLFxuICBtb2RlbDogTVxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGlmICghZGF0YS50eXBlIHx8IG1vZGVsW2tleV0pIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBjb25zdCBzZXRQcmltYXJ5S2V5VmFsdWUgPSBmdW5jdGlvbiA8TSBleHRlbmRzIE1vZGVsPihcbiAgICB0YXJnZXQ6IE0sXG4gICAgcHJvcGVydHlLZXk6IHN0cmluZyxcbiAgICB2YWx1ZTogc3RyaW5nIHwgbnVtYmVyIHwgYmlnaW50XG4gICkge1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIHByb3BlcnR5S2V5LCB7XG4gICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgd3JpdGFibGU6IGZhbHNlLFxuICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgdmFsdWU6IHZhbHVlLFxuICAgIH0pO1xuICB9O1xuICBpZiAoIWRhdGEubmFtZSkgZGF0YS5uYW1lID0gc2VxdWVuY2VOYW1lRm9yTW9kZWwobW9kZWwsIFwicGtcIik7XG4gIGxldCBzZXF1ZW5jZTogRmFicmljQ29udHJhY3RTZXF1ZW5jZTtcbiAgdHJ5IHtcbiAgICBzZXF1ZW5jZSA9IChhd2FpdCB0aGlzLmFkYXB0ZXIuU2VxdWVuY2UoZGF0YSkpIGFzIEZhYnJpY0NvbnRyYWN0U2VxdWVuY2U7XG4gIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFxuICAgICAgYEZhaWxlZCB0byBpbnN0YW50aWF0ZSBTZXF1ZW5jZSAke2RhdGEubmFtZX06ICR7ZX1gXG4gICAgKTtcbiAgfVxuXG4gIGNvbnN0IG5leHQgPSBhd2FpdCBzZXF1ZW5jZS5uZXh0KGNvbnRleHQgYXMgRmFicmljQ29udHJhY3RDb250ZXh0KTtcbiAgc2V0UHJpbWFyeUtleVZhbHVlKG1vZGVsLCBrZXkgYXMgc3RyaW5nLCBuZXh0KTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQWRhcHRlciBmb3IgSHlwZXJsZWRnZXIgRmFicmljIGNoYWluY29kZSBzdGF0ZSBkYXRhYmFzZSBvcGVyYXRpb25zXG4gKiBAc3VtbWFyeSBQcm92aWRlcyBhIENvdWNoREItbGlrZSBpbnRlcmZhY2UgZm9yIGludGVyYWN0aW5nIHdpdGggdGhlIEZhYnJpYyBzdGF0ZSBkYXRhYmFzZSBmcm9tIHdpdGhpbiBhIGNoYWluY29kZSBjb250cmFjdFxuICogQHRlbXBsYXRlIHZvaWQgLSBObyBjb25maWd1cmF0aW9uIG5lZWRlZCBmb3IgY29udHJhY3QgYWRhcHRlclxuICogQHRlbXBsYXRlIEZhYnJpY0NvbnRyYWN0RmxhZ3MgLSBGbGFncyBzcGVjaWZpYyB0byBGYWJyaWMgY29udHJhY3Qgb3BlcmF0aW9uc1xuICogQHRlbXBsYXRlIEZhYnJpY0NvbnRyYWN0Q29udGV4dCAtIENvbnRleHQgdHlwZSBmb3IgRmFicmljIGNvbnRyYWN0IG9wZXJhdGlvbnNcbiAqIEBjbGFzcyBGYWJyaWNDb250cmFjdEFkYXB0ZXJcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBJbiBhIEZhYnJpYyBjaGFpbmNvZGUgY29udHJhY3QgY2xhc3NcbiAqIGltcG9ydCB7IEZhYnJpY0NvbnRyYWN0QWRhcHRlciB9IGZyb20gJ0BkZWNhZi10cy9mb3ItZmFicmljJztcbiAqXG4gKiBleHBvcnQgY2xhc3MgTXlDb250cmFjdCBleHRlbmRzIENvbnRyYWN0IHtcbiAqICAgcHJpdmF0ZSBhZGFwdGVyID0gbmV3IEZhYnJpY0NvbnRyYWN0QWRhcHRlcigpO1xuICpcbiAqICAgQFRyYW5zYWN0aW9uKClcbiAqICAgYXN5bmMgY3JlYXRlQXNzZXQoY3R4OiBDb250ZXh0LCBpZDogc3RyaW5nLCBkYXRhOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAqICAgICBjb25zdCBtb2RlbCA9IHsgaWQsIGRhdGEsIHRpbWVzdGFtcDogRGF0ZS5ub3coKSB9O1xuICogICAgIGF3YWl0IHRoaXMuYWRhcHRlci5jcmVhdGUoJ2Fzc2V0cycsIGlkLCBtb2RlbCwge30sIHsgc3R1YjogY3R4LnN0dWIgfSk7XG4gKiAgIH1cbiAqIH1cbiAqIGBgYFxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDb250cmFjdFxuICogICBwYXJ0aWNpcGFudCBGYWJyaWNDb250cmFjdEFkYXB0ZXJcbiAqICAgcGFydGljaXBhbnQgU3R1YlxuICogICBwYXJ0aWNpcGFudCBTdGF0ZURCXG4gKlxuICogICBDb250cmFjdC0+PkZhYnJpY0NvbnRyYWN0QWRhcHRlcjogY3JlYXRlKHRhYmxlTmFtZSwgaWQsIG1vZGVsLCB0cmFuc2llbnQsIGN0eClcbiAqICAgRmFicmljQ29udHJhY3RBZGFwdGVyLT4+RmFicmljQ29udHJhY3RBZGFwdGVyOiBTZXJpYWxpemUgbW9kZWwgdG8gSlNPTlxuICogICBGYWJyaWNDb250cmFjdEFkYXB0ZXItPj5TdHViOiBwdXRTdGF0ZShpZCwgc2VyaWFsaXplZERhdGEpXG4gKiAgIFN0dWItPj5TdGF0ZURCOiBXcml0ZSBkYXRhXG4gKiAgIFN0YXRlREItLT4+U3R1YjogU3VjY2Vzc1xuICogICBTdHViLS0+PkZhYnJpY0NvbnRyYWN0QWRhcHRlcjogU3VjY2Vzc1xuICogICBGYWJyaWNDb250cmFjdEFkYXB0ZXItLT4+Q29udHJhY3Q6IG1vZGVsXG4gKi9cbmV4cG9ydCBjbGFzcyBGYWJyaWNDb250cmFjdEFkYXB0ZXIgZXh0ZW5kcyBDb3VjaERCQWRhcHRlcjxcbiAgYW55LFxuICB2b2lkLFxuICBGYWJyaWNDb250cmFjdEZsYWdzLFxuICBGYWJyaWNDb250cmFjdENvbnRleHRcbj4ge1xuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgZ2V0Q2xpZW50KCk6IHZvaWQge1xuICAgIHRocm93IG5ldyBVbnN1cHBvcnRlZEVycm9yKFwiQ2xpZW50IGlzIG5vdCBzdXBwb3J0ZWQgaW4gRmFicmljIGNvbnRyYWN0c1wiKTtcbiAgfVxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRleHQgZGVjb2RlciBmb3IgY29udmVydGluZyBiaW5hcnkgZGF0YSB0byBzdHJpbmdzXG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyB0ZXh0RGVjb2RlciA9IG5ldyBUZXh0RGVjb2RlcihcInV0ZjhcIik7XG5cbiAgcHJvdGVjdGVkIHN0YXRpYyByZWFkb25seSBzZXJpYWxpemVyID0gbmV3IFNpbXBsZURldGVybWluaXN0aWNTZXJpYWxpemVyKCk7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgbG9nZ2VyIGZvciBhIHNwZWNpZmljIGNoYWluY29kZSBjb250ZXh0XG4gICAqIEBzdW1tYXJ5IFJldHVybnMgYSBDb250cmFjdExvZ2dlciBpbnN0YW5jZSBjb25maWd1cmVkIGZvciB0aGUgY3VycmVudCBjb250ZXh0XG4gICAqIEBwYXJhbSB7Q3R4fSBjdHggLSBUaGUgRmFicmljIGNoYWluY29kZSBjb250ZXh0XG4gICAqIEByZXR1cm4ge0NvbnRyYWN0TG9nZ2VyfSBUaGUgbG9nZ2VyIGluc3RhbmNlXG4gICAqL1xuICBwdWJsaWMgbG9nRm9yKGN0eDogQ3R4KTogQ29udHJhY3RMb2dnZXIge1xuICAgIHJldHVybiBMb2dnaW5nLmZvcihGYWJyaWNDb250cmFjdEFkYXB0ZXIsIHt9LCBjdHgpIGFzIENvbnRyYWN0TG9nZ2VyO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDb250ZXh0IGNvbnN0cnVjdG9yIGZvciB0aGlzIGFkYXB0ZXJcbiAgICogQHN1bW1hcnkgT3ZlcnJpZGVzIHRoZSBiYXNlIENvbnRleHQgY29uc3RydWN0b3Igd2l0aCBGYWJyaWNDb250cmFjdENvbnRleHRcbiAgICovXG4gIG92ZXJyaWRlIENvbnRleHQgPSBGYWJyaWNDb250cmFjdENvbnRleHQ7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBHZXRzIHRoZSByZXBvc2l0b3J5IGNvbnN0cnVjdG9yIGZvciB0aGlzIGFkYXB0ZXJcbiAgICogQHN1bW1hcnkgUmV0dXJucyB0aGUgRmFicmljQ29udHJhY3RSZXBvc2l0b3J5IGNvbnN0cnVjdG9yIGZvciBjcmVhdGluZyByZXBvc2l0b3JpZXNcbiAgICogQHRlbXBsYXRlIE0gLSBUeXBlIGV4dGVuZGluZyBNb2RlbFxuICAgKiBAcmV0dXJuIHtDb25zdHJ1Y3RvcjxSZXBvc2l0b3J5PE0sIE1hbmdvUXVlcnksIEZhYnJpY0NvbnRyYWN0QWRhcHRlciwgRmFicmljQ29udHJhY3RGbGFncywgRmFicmljQ29udHJhY3RDb250ZXh0Pj59IFRoZSByZXBvc2l0b3J5IGNvbnN0cnVjdG9yXG4gICAqL1xuICBvdmVycmlkZSByZXBvc2l0b3J5PE0gZXh0ZW5kcyBNb2RlbD4oKTogQ29uc3RydWN0b3I8XG4gICAgUmVwb3NpdG9yeTxcbiAgICAgIE0sXG4gICAgICBNYW5nb1F1ZXJ5LFxuICAgICAgQWRhcHRlcjxhbnksIGFueSwgTWFuZ29RdWVyeSwgRmFicmljQ29udHJhY3RGbGFncywgRmFicmljQ29udHJhY3RDb250ZXh0PixcbiAgICAgIEZhYnJpY0NvbnRyYWN0RmxhZ3MsXG4gICAgICBGYWJyaWNDb250cmFjdENvbnRleHRcbiAgICA+XG4gID4ge1xuICAgIHJldHVybiBGYWJyaWNDb250cmFjdFJlcG9zaXRvcnk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYSBuZXcgRmFicmljQ29udHJhY3RBZGFwdGVyIGluc3RhbmNlXG4gICAqIEBzdW1tYXJ5IEluaXRpYWxpemVzIGFuIGFkYXB0ZXIgZm9yIGludGVyYWN0aW5nIHdpdGggdGhlIEZhYnJpYyBzdGF0ZSBkYXRhYmFzZVxuICAgKiBAcGFyYW0ge3ZvaWR9IHNjb3BlIC0gTm90IHVzZWQgaW4gdGhpcyBhZGFwdGVyXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbYWxpYXNdIC0gT3B0aW9uYWwgYWxpYXMgZm9yIHRoZSBhZGFwdGVyIGluc3RhbmNlXG4gICAqL1xuICBjb25zdHJ1Y3RvcihzY29wZTogdm9pZCwgYWxpYXM/OiBzdHJpbmcpIHtcbiAgICBzdXBlcihzY29wZSwgRmFicmljRmxhdm91ciwgYWxpYXMpO1xuICB9XG5cbiAgb3ZlcnJpZGUgZm9yKGNvbmZpZzogUGFydGlhbDxhbnk+LCAuLi5hcmdzOiBhbnkpOiB0eXBlb2YgdGhpcyB7XG4gICAgcmV0dXJuIHN1cGVyLmZvcihjb25maWcsIC4uLmFyZ3MpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgcmVjb3JkIGluIHRoZSBzdGF0ZSBkYXRhYmFzZVxuICAgKiBAc3VtbWFyeSBTZXJpYWxpemVzIGEgbW9kZWwgYW5kIHN0b3JlcyBpdCBpbiB0aGUgRmFicmljIHN0YXRlIGRhdGFiYXNlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0YWJsZU5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgdGFibGUvY29sbGVjdGlvblxuICAgKiBAcGFyYW0ge3N0cmluZyB8IG51bWJlcn0gaWQgLSBUaGUgcmVjb3JkIGlkZW50aWZpZXJcbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBtb2RlbCAtIFRoZSByZWNvcmQgZGF0YVxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIGFueT59IHRyYW5zaWVudCAtIFRyYW5zaWVudCBkYXRhIChub3QgdXNlZCBpbiB0aGlzIGltcGxlbWVudGF0aW9uKVxuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMsIGluY2x1ZGluZyB0aGUgY2hhaW5jb2RlIHN0dWIgYW5kIGxvZ2dlclxuICAgKiBAcmV0dXJuIHtQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+fSBQcm9taXNlIHJlc29sdmluZyB0byB0aGUgY3JlYXRlZCByZWNvcmRcbiAgICovXG4gIG92ZXJyaWRlIGFzeW5jIGNyZWF0ZShcbiAgICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgICBpZDogc3RyaW5nIHwgbnVtYmVyLFxuICAgIG1vZGVsOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgYW55Pj4ge1xuICAgIGNvbnN0IHsgc3R1YiwgbG9nZ2VyIH0gPSBhcmdzLnBvcCgpO1xuICAgIGNvbnN0IGxvZyA9IGxvZ2dlci5mb3IodGhpcy5jcmVhdGUpO1xuXG4gICAgdHJ5IHtcbiAgICAgIGxvZy5pbmZvKGBhZGRpbmcgZW50cnkgdG8gJHt0YWJsZU5hbWV9IHRhYmxlIHdpdGggcGsgJHtpZH1gKTtcbiAgICAgIG1vZGVsID0gYXdhaXQgdGhpcy5wdXRTdGF0ZShzdHViLCBpZC50b1N0cmluZygpLCBtb2RlbCk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgdGhpcy5wYXJzZUVycm9yKGUgYXMgRXJyb3IpO1xuICAgIH1cblxuICAgIHJldHVybiBtb2RlbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmVhZHMgYSByZWNvcmQgZnJvbSB0aGUgc3RhdGUgZGF0YWJhc2VcbiAgICogQHN1bW1hcnkgUmV0cmlldmVzIGFuZCBkZXNlcmlhbGl6ZXMgYSByZWNvcmQgZnJvbSB0aGUgRmFicmljIHN0YXRlIGRhdGFiYXNlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0YWJsZU5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgdGFibGUvY29sbGVjdGlvblxuICAgKiBAcGFyYW0ge3N0cmluZyB8IG51bWJlcn0gaWQgLSBUaGUgcmVjb3JkIGlkZW50aWZpZXJcbiAgICogQHBhcmFtIHsuLi5hbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzLCBpbmNsdWRpbmcgdGhlIGNoYWluY29kZSBzdHViIGFuZCBsb2dnZXJcbiAgICogQHJldHVybiB7UHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+Pn0gUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIHJldHJpZXZlZCByZWNvcmRcbiAgICovXG4gIG92ZXJyaWRlIGFzeW5jIHJlYWQoXG4gICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICAgaWQ6IHN0cmluZyB8IG51bWJlcixcbiAgICAuLi5hcmdzOiBhbnlbXVxuICApOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+IHtcbiAgICBjb25zdCB7IHN0dWIsIGxvZ2dlciB9ID0gYXJncy5wb3AoKTtcbiAgICBjb25zdCBsb2cgPSBsb2dnZXIuZm9yKHRoaXMucmVhZCk7XG5cbiAgICBsZXQgbW9kZWw6IFJlY29yZDxzdHJpbmcsIGFueT47XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCB0aGlzLnJlYWRTdGF0ZShzdHViLCB0YWJsZU5hbWUsIGlkLnRvU3RyaW5nKCkpO1xuXG4gICAgICBpZiAocmVzdWx0cy5sZW5ndGggPCAxKSB7XG4gICAgICAgIGxvZy5kZWJ1ZyhgTm8gcmVjb3JkIGZvdW5kIGZvciBpZCAke2lkfSBpbiAke3RhYmxlTmFtZX0gdGFibGVgKTtcbiAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXJyb3IoXG4gICAgICAgICAgYE5vIHJlY29yZCBmb3VuZCBmb3IgaWQgJHtpZH0gaW4gJHt0YWJsZU5hbWV9IHRhYmxlYFxuICAgICAgICApO1xuICAgICAgfSBlbHNlIGlmIChyZXN1bHRzLmxlbmd0aCA8IDIpIHtcbiAgICAgICAgbG9nLmRlYnVnKGBObyByZWNvcmQgZm91bmQgZm9yIGlkICR7aWR9IGluICR7dGFibGVOYW1lfSB0YWJsZWApO1xuICAgICAgICBtb2RlbCA9IHJlc3VsdHMucG9wKCkgYXMgUmVjb3JkPHN0cmluZywgYW55PjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG1vZGVsID0gdGhpcy5tZXJnZU1vZGVscyhyZXN1bHRzKTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyB0aGlzLnBhcnNlRXJyb3IoZSBhcyBFcnJvcik7XG4gICAgfVxuXG4gICAgcmV0dXJuIG1vZGVsO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBVcGRhdGVzIGEgcmVjb3JkIGluIHRoZSBzdGF0ZSBkYXRhYmFzZVxuICAgKiBAc3VtbWFyeSBTZXJpYWxpemVzIGEgbW9kZWwgYW5kIHVwZGF0ZXMgaXQgaW4gdGhlIEZhYnJpYyBzdGF0ZSBkYXRhYmFzZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGFibGVOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHRhYmxlL2NvbGxlY3Rpb25cbiAgICogQHBhcmFtIHtzdHJpbmcgfCBudW1iZXJ9IGlkIC0gVGhlIHJlY29yZCBpZGVudGlmaWVyXG4gICAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgYW55Pn0gbW9kZWwgLSBUaGUgdXBkYXRlZCByZWNvcmQgZGF0YVxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIGFueT59IHRyYW5zaWVudCAtIFRyYW5zaWVudCBkYXRhIChub3QgdXNlZCBpbiB0aGlzIGltcGxlbWVudGF0aW9uKVxuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMsIGluY2x1ZGluZyB0aGUgY2hhaW5jb2RlIHN0dWIgYW5kIGxvZ2dlclxuICAgKiBAcmV0dXJuIHtQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+fSBQcm9taXNlIHJlc29sdmluZyB0byB0aGUgdXBkYXRlZCByZWNvcmRcbiAgICovXG4gIG92ZXJyaWRlIGFzeW5jIHVwZGF0ZShcbiAgICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgICBpZDogc3RyaW5nIHwgbnVtYmVyLFxuICAgIG1vZGVsOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgYW55Pj4ge1xuICAgIGNvbnN0IHsgc3R1YiwgbG9nZ2VyIH0gPSBhcmdzLnBvcCgpO1xuICAgIGNvbnN0IGxvZyA9IGxvZ2dlci5mb3IodGhpcy51cGRhdGUpO1xuXG4gICAgdHJ5IHtcbiAgICAgIGxvZy5pbmZvKGB1cGRhdGluZyBlbnRyeSB0byAke3RhYmxlTmFtZX0gdGFibGUgd2l0aCBwayAke2lkfWApO1xuICAgICAgbW9kZWwgPSBhd2FpdCB0aGlzLnB1dFN0YXRlKHN0dWIsIGlkLnRvU3RyaW5nKCksIG1vZGVsKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyB0aGlzLnBhcnNlRXJyb3IoZSBhcyBFcnJvcik7XG4gICAgfVxuXG4gICAgcmV0dXJuIG1vZGVsO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBEZWxldGVzIGEgcmVjb3JkIGZyb20gdGhlIHN0YXRlIGRhdGFiYXNlXG4gICAqIEBzdW1tYXJ5IFJldHJpZXZlcyBhIHJlY29yZCBhbmQgdGhlbiByZW1vdmVzIGl0IGZyb20gdGhlIEZhYnJpYyBzdGF0ZSBkYXRhYmFzZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGFibGVOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHRhYmxlL2NvbGxlY3Rpb25cbiAgICogQHBhcmFtIHtzdHJpbmcgfCBudW1iZXJ9IGlkIC0gVGhlIHJlY29yZCBpZGVudGlmaWVyIHRvIGRlbGV0ZVxuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMsIGluY2x1ZGluZyB0aGUgY2hhaW5jb2RlIHN0dWIgYW5kIGxvZ2dlclxuICAgKiBAcmV0dXJuIHtQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT4+fSBQcm9taXNlIHJlc29sdmluZyB0byB0aGUgZGVsZXRlZCByZWNvcmRcbiAgICovXG4gIGFzeW5jIGRlbGV0ZShcbiAgICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgICBpZDogc3RyaW5nIHwgbnVtYmVyLFxuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgYW55Pj4ge1xuICAgIGNvbnN0IGN0eCA9IGFyZ3MucG9wKCk7XG4gICAgY29uc3QgeyBzdHViLCBsb2dnZXIgfSA9IGN0eDtcbiAgICBjb25zdCBsb2cgPSBsb2dnZXIuZm9yKHRoaXMuZGVsZXRlKTtcblxuICAgIGFyZ3MucHVzaChjdHgpO1xuXG4gICAgbGV0IG1vZGVsOiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuICAgIHRyeSB7XG4gICAgICBtb2RlbCA9IGF3YWl0IHRoaXMucmVhZCh0YWJsZU5hbWUsIGlkLCAuLi5hcmdzKTtcbiAgICAgIGxvZy52ZXJib3NlKGBkZWxldGluZyBlbnRyeSB3aXRoIHBrICR7aWR9IGZyb20gJHt0YWJsZU5hbWV9IHRhYmxlYCk7XG4gICAgICB0aGlzLmRlbGV0ZVN0YXRlKHN0dWIsIHRhYmxlTmFtZSwgaWQudG9TdHJpbmcoKSk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgdGhpcy5wYXJzZUVycm9yKGUgYXMgRXJyb3IpO1xuICAgIH1cblxuICAgIHJldHVybiBtb2RlbDtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBkZWxldGVTdGF0ZShcbiAgICBzdHViOiBDaGFpbmNvZGVTdHViLFxuICAgIHRhYmxlTmFtZTogc3RyaW5nLFxuICAgIGlkOiBzdHJpbmcsXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIC4uLmFyZ3M6IGFueVtdXG4gICkge1xuICAgIGNvbnN0IGNvbXBvc2VkS2V5ID0gc3R1Yi5jcmVhdGVDb21wb3NpdGVLZXkodGFibGVOYW1lLCBbU3RyaW5nKGlkKV0pO1xuICAgIGF3YWl0IHN0dWIuZGVsZXRlU3RhdGUoY29tcG9zZWRLZXkpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIHB1dFN0YXRlKFxuICAgIHN0dWI6IENoYWluY29kZVN0dWIsXG4gICAgaWQ6IHN0cmluZyxcbiAgICBtb2RlbDogUmVjb3JkPHN0cmluZywgYW55PixcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgLi4uYXJnczogYW55W11cbiAgKSB7XG4gICAgbGV0IGRhdGE6IEJ1ZmZlcjtcblxuICAgIHRyeSB7XG4gICAgICBkYXRhID0gQnVmZmVyLmZyb20oXG4gICAgICAgIEZhYnJpY0NvbnRyYWN0QWRhcHRlci5zZXJpYWxpemVyLnNlcmlhbGl6ZShtb2RlbCBhcyBNb2RlbClcbiAgICAgICk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgbmV3IFNlcmlhbGl6YXRpb25FcnJvcihcbiAgICAgICAgYEZhaWxlZCB0byBzZXJpYWxpemUgcmVjb3JkIHdpdGggaWQgJHtpZH06ICR7ZX1gXG4gICAgICApO1xuICAgIH1cbiAgICBhd2FpdCBzdHViLnB1dFN0YXRlKGlkLnRvU3RyaW5nKCksIGRhdGEpO1xuXG4gICAgcmV0dXJuIG1vZGVsO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIHJlYWRTdGF0ZShcbiAgICBzdHViOiBDaGFpbmNvZGVTdHViLFxuICAgIHRhYmxlTmFtZTogc3RyaW5nLFxuICAgIGlkOiBzdHJpbmcsXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIC4uLmFyZ3M6IGFueVtdXG4gICkge1xuICAgIGNvbnN0IGNvbXBvc2VkS2V5ID0gc3R1Yi5jcmVhdGVDb21wb3NpdGVLZXkodGFibGVOYW1lLCBbU3RyaW5nKGlkKV0pO1xuICAgIGNvbnN0IHJlc3VsdHM6IGFueVtdID0gW107XG5cbiAgICBsZXQgcmVzOiBCdWZmZXIgfCBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0gYXdhaXQgc3R1Yi5nZXRTdGF0ZShjb21wb3NlZEtleSk7XG5cbiAgICBpZiAocmVzLnRvU3RyaW5nKCkgPT09IFwiXCIpXG4gICAgICB0aHJvdyBuZXcgTm90Rm91bmRFcnJvcihgUmVjb3JkIHdpdGggaWQgJHtpZH0gbm90IGZvdW5kYCk7XG5cbiAgICB0cnkge1xuICAgICAgcmVzID0gRmFicmljQ29udHJhY3RBZGFwdGVyLnNlcmlhbGl6ZXIuZGVzZXJpYWxpemUoXG4gICAgICAgIHJlcy50b1N0cmluZygpXG4gICAgICAgIC8vIG1vZGVsLmNvbnN0cnVjdG9yLm5hbWVcbiAgICAgICk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgbmV3IFNlcmlhbGl6YXRpb25FcnJvcihgRmFpbGVkIHRvIHBhcnNlIHJlY29yZDogJHtlfWApO1xuICAgIH1cblxuICAgIHJlc3VsdHMucHVzaChyZXMpO1xuXG4gICAgcmV0dXJuIHJlc3VsdHM7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgcXVlcnlSZXN1bHQoXG4gICAgc3R1YjogQ2hhaW5jb2RlU3R1YixcbiAgICByYXdJbnB1dDogYW55LFxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICAuLi5hcmdzOiBhbnlbXVxuICApOiBQcm9taXNlPEl0ZXJhdG9ycy5TdGF0ZVF1ZXJ5SXRlcmF0b3I+IHtcbiAgICByZXR1cm4gKGF3YWl0IHN0dWIuZ2V0UXVlcnlSZXN1bHQoXG4gICAgICBKU09OLnN0cmluZ2lmeShyYXdJbnB1dClcbiAgICApKSBhcyBJdGVyYXRvcnMuU3RhdGVRdWVyeUl0ZXJhdG9yO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIHF1ZXJ5UmVzdWx0UGFnaW5hdGVkKFxuICAgIHN0dWI6IENoYWluY29kZVN0dWIsXG4gICAgcmF3SW5wdXQ6IGFueSxcbiAgICBsaW1pdDogbnVtYmVyID0gMjUwLFxuICAgIHNraXA/OiBudW1iZXIsXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IFByb21pc2U8U3RhdGVRdWVyeVJlc3BvbnNlPEl0ZXJhdG9ycy5TdGF0ZVF1ZXJ5SXRlcmF0b3I+PiB7XG4gICAgcmV0dXJuIChhd2FpdCBzdHViLmdldFF1ZXJ5UmVzdWx0V2l0aFBhZ2luYXRpb24oXG4gICAgICBKU09OLnN0cmluZ2lmeShyYXdJbnB1dCksXG4gICAgICBsaW1pdCxcbiAgICAgIHNraXA/LnRvU3RyaW5nKClcbiAgICApKSBhcyBTdGF0ZVF1ZXJ5UmVzcG9uc2U8SXRlcmF0b3JzLlN0YXRlUXVlcnlJdGVyYXRvcj47XG4gIH1cblxuICBwcm90ZWN0ZWQgbWVyZ2VNb2RlbHMocmVzdWx0czogUmVjb3JkPHN0cmluZywgYW55PltdKTogUmVjb3JkPHN0cmluZywgYW55PiB7XG4gICAgY29uc3QgZXh0cmFjdCA9IChtb2RlbDogUmVjb3JkPHN0cmluZywgYW55PikgPT5cbiAgICAgIE9iamVjdC5lbnRyaWVzKG1vZGVsKS5yZWR1Y2UoKGFjY3VtOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LCBba2V5LCB2YWxdKSA9PiB7XG4gICAgICAgIGlmICh0eXBlb2YgdmFsICE9PSBcInVuZGVmaW5lZFwiKSBhY2N1bVtrZXldID0gdmFsO1xuICAgICAgICByZXR1cm4gYWNjdW07XG4gICAgICB9LCB7fSk7XG5cbiAgICBsZXQgZmluYWxNb2RlbDogUmVjb3JkPHN0cmluZywgYW55PiA9IHJlc3VsdHMucG9wKCkgYXMgUmVjb3JkPHN0cmluZywgYW55PjtcblxuICAgIGZvciAoY29uc3QgcmVzIG9mIHJlc3VsdHMpIHtcbiAgICAgIGZpbmFsTW9kZWwgPSBPYmplY3QuYXNzaWduKHt9LCBleHRyYWN0KGZpbmFsTW9kZWwpLCBleHRyYWN0KHJlcykpO1xuICAgIH1cblxuICAgIHJldHVybiBmaW5hbE1vZGVsO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBEZWNvZGVzIGJpbmFyeSBkYXRhIHRvIHN0cmluZ1xuICAgKiBAc3VtbWFyeSBDb252ZXJ0cyBhIFVpbnQ4QXJyYXkgdG8gYSBzdHJpbmcgdXNpbmcgVVRGLTggZW5jb2RpbmdcbiAgICogQHBhcmFtIHtVaW50OEFycmF5fSBidWZmZXIgLSBUaGUgYmluYXJ5IGRhdGEgdG8gZGVjb2RlXG4gICAqIEByZXR1cm4ge3N0cmluZ30gVGhlIGRlY29kZWQgc3RyaW5nXG4gICAqL1xuICBwcm90ZWN0ZWQgZGVjb2RlKGJ1ZmZlcjogVWludDhBcnJheSkge1xuICAgIHJldHVybiBGYWJyaWNDb250cmFjdEFkYXB0ZXIudGV4dERlY29kZXIuZGVjb2RlKGJ1ZmZlcik7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgb3BlcmF0aW9uIGZsYWdzIGZvciBGYWJyaWMgY29udHJhY3Qgb3BlcmF0aW9uc1xuICAgKiBAc3VtbWFyeSBNZXJnZXMgZGVmYXVsdCBmbGFncyB3aXRoIEZhYnJpYy1zcGVjaWZpYyBjb250ZXh0IGluZm9ybWF0aW9uXG4gICAqIEB0ZW1wbGF0ZSBNIC0gVHlwZSBleHRlbmRpbmcgTW9kZWxcbiAgICogQHBhcmFtIHtPcGVyYXRpb25LZXlzfSBvcGVyYXRpb24gLSBUaGUgb3BlcmF0aW9uIGJlaW5nIHBlcmZvcm1lZFxuICAgKiBAcGFyYW0ge0NvbnN0cnVjdG9yPE0+fSBtb2RlbCAtIFRoZSBtb2RlbCBjb25zdHJ1Y3RvclxuICAgKiBAcGFyYW0ge1BhcnRpYWw8RmFicmljQ29udHJhY3RGbGFncz59IGZsYWdzIC0gUGFydGlhbCBmbGFncyB0byBtZXJnZSB3aXRoIGRlZmF1bHRzXG4gICAqIEBwYXJhbSB7Q3R4fSBjdHggLSBUaGUgRmFicmljIGNoYWluY29kZSBjb250ZXh0XG4gICAqIEByZXR1cm4ge0ZhYnJpY0NvbnRyYWN0RmxhZ3N9IFRoZSBtZXJnZWQgZmxhZ3NcbiAgICovXG4gIHByb3RlY3RlZCBvdmVycmlkZSBhc3luYyBmbGFnczxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIG9wZXJhdGlvbjogT3BlcmF0aW9uS2V5cyxcbiAgICBtb2RlbDogQ29uc3RydWN0b3I8TT4sXG4gICAgZmxhZ3M6IFBhcnRpYWw8RmFicmljQ29udHJhY3RGbGFncz4sXG4gICAgY3R4OiBDdHgsXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxGYWJyaWNDb250cmFjdEZsYWdzPiB7XG4gICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oYXdhaXQgc3VwZXIuZmxhZ3Mob3BlcmF0aW9uLCBtb2RlbCwgZmxhZ3MsIC4uLmFyZ3MpLCB7XG4gICAgICBzdHViOiBjdHguc3R1YixcbiAgICAgIGlkZW50aXR5OiBjdHguY2xpZW50SWRlbnRpdHksXG4gICAgICBsb2dnZXI6IHRoaXMubG9nRm9yKGN0eCksXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYW4gaW5kZXggZm9yIGEgbW9kZWxcbiAgICogQHN1bW1hcnkgVGhpcyBtZXRob2QgaXMgbm90IGltcGxlbWVudGVkIGZvciBGYWJyaWMgY29udHJhY3RzIGFuZCByZXR1cm5zIGEgcmVzb2x2ZWQgcHJvbWlzZVxuICAgKiBAdGVtcGxhdGUgTSAtIFR5cGUgZXh0ZW5kaW5nIE1vZGVsXG4gICAqIEBwYXJhbSB7Q29uc3RydWN0b3I8TT59IG1vZGVscyAtIFRoZSBtb2RlbCBjb25zdHJ1Y3RvclxuICAgKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgaW1tZWRpYXRlbHlcbiAgICovXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgcHJvdGVjdGVkIGluZGV4PE0+KG1vZGVsczogQ29uc3RydWN0b3I8TT4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHVuZGVmaW5lZCk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFByb2Nlc3NlcyByZXN1bHRzIGZyb20gYSBzdGF0ZSBxdWVyeSBpdGVyYXRvclxuICAgKiBAc3VtbWFyeSBJdGVyYXRlcyB0aHJvdWdoIHF1ZXJ5IHJlc3VsdHMgYW5kIGNvbnZlcnRzIHRoZW0gdG8gYSBzdHJ1Y3R1cmVkIGZvcm1hdFxuICAgKiBAcGFyYW0ge0xvZ2dlcn0gbG9nIC0gTG9nZ2VyIGluc3RhbmNlIGZvciBkZWJ1Z2dpbmdcbiAgICogQHBhcmFtIHtJdGVyYXRvcnMuU3RhdGVRdWVyeUl0ZXJhdG9yfSBpdGVyYXRvciAtIFRoZSBzdGF0ZSBxdWVyeSBpdGVyYXRvclxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtpc0hpc3Rvcnk9ZmFsc2VdIC0gV2hldGhlciB0aGlzIGlzIGEgaGlzdG9yeSBxdWVyeVxuICAgKiBAcmV0dXJuIHtQcm9taXNlPGFueVtdPn0gUHJvbWlzZSByZXNvbHZpbmcgdG8gYW4gYXJyYXkgb2YgcHJvY2Vzc2VkIHJlc3VsdHNcbiAgICogQG1lcm1haWRcbiAgICogc2VxdWVuY2VEaWFncmFtXG4gICAqICAgcGFydGljaXBhbnQgQ2FsbGVyXG4gICAqICAgcGFydGljaXBhbnQgUmVzdWx0SXRlcmF0b3JcbiAgICogICBwYXJ0aWNpcGFudCBJdGVyYXRvclxuICAgKlxuICAgKiAgIENhbGxlci0+PlJlc3VsdEl0ZXJhdG9yOiByZXN1bHRJdGVyYXRvcihsb2csIGl0ZXJhdG9yLCBpc0hpc3RvcnkpXG4gICAqICAgbG9vcCBVbnRpbCBkb25lXG4gICAqICAgICBSZXN1bHRJdGVyYXRvci0+Pkl0ZXJhdG9yOiBuZXh0KClcbiAgICogICAgIEl0ZXJhdG9yLS0+PlJlc3VsdEl0ZXJhdG9yOiB7IHZhbHVlLCBkb25lIH1cbiAgICogICAgIGFsdCBIYXMgdmFsdWVcbiAgICogICAgICAgUmVzdWx0SXRlcmF0b3ItPj5SZXN1bHRJdGVyYXRvcjogUHJvY2VzcyB2YWx1ZSBiYXNlZCBvbiBpc0hpc3RvcnlcbiAgICogICAgICAgUmVzdWx0SXRlcmF0b3ItPj5SZXN1bHRJdGVyYXRvcjogQWRkIHRvIHJlc3VsdHMgYXJyYXlcbiAgICogICAgIGVuZFxuICAgKiAgIGVuZFxuICAgKiAgIFJlc3VsdEl0ZXJhdG9yLT4+SXRlcmF0b3I6IGNsb3NlKClcbiAgICogICBSZXN1bHRJdGVyYXRvci0tPj5DYWxsZXI6IGFsbFJlc3VsdHNcbiAgICovXG4gIHByb3RlY3RlZCBhc3luYyByZXN1bHRJdGVyYXRvcihcbiAgICBsb2c6IExvZ2dlcixcbiAgICBpdGVyYXRvcjogSXRlcmF0b3JzLlN0YXRlUXVlcnlJdGVyYXRvcixcbiAgICBpc0hpc3RvcnkgPSBmYWxzZVxuICApIHtcbiAgICBjb25zdCBhbGxSZXN1bHRzID0gW107XG4gICAgbGV0IHJlczogeyB2YWx1ZTogYW55OyBkb25lOiBib29sZWFuIH0gPSBhd2FpdCBpdGVyYXRvci5uZXh0KCk7XG4gICAgd2hpbGUgKCFyZXMuZG9uZSkge1xuICAgICAgaWYgKHJlcy52YWx1ZSAmJiByZXMudmFsdWUudmFsdWUudG9TdHJpbmcoKSkge1xuICAgICAgICBsZXQganNvblJlczogYW55ID0ge307XG4gICAgICAgIGxvZy5kZWJ1ZyhyZXMudmFsdWUudmFsdWUudG9TdHJpbmcoXCJ1dGY4XCIpKTtcbiAgICAgICAgaWYgKGlzSGlzdG9yeSAvKiAmJiBpc0hpc3RvcnkgPT09IHRydWUqLykge1xuICAgICAgICAgIGpzb25SZXMuVHhJZCA9IHJlcy52YWx1ZS50eElkO1xuICAgICAgICAgIGpzb25SZXMuVGltZXN0YW1wID0gcmVzLnZhbHVlLnRpbWVzdGFtcDtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAganNvblJlcy5WYWx1ZSA9IEpTT04ucGFyc2UocmVzLnZhbHVlLnZhbHVlLnRvU3RyaW5nKFwidXRmOFwiKSk7XG4gICAgICAgICAgfSBjYXRjaCAoZXJyOiBhbnkpIHtcbiAgICAgICAgICAgIGxvZy5lcnJvcihlcnIpO1xuICAgICAgICAgICAganNvblJlcy5WYWx1ZSA9IHJlcy52YWx1ZS52YWx1ZS50b1N0cmluZyhcInV0ZjhcIik7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBqc29uUmVzID0gSlNPTi5wYXJzZShyZXMudmFsdWUudmFsdWUudG9TdHJpbmcoXCJ1dGY4XCIpKTtcbiAgICAgICAgICB9IGNhdGNoIChlcnI6IGFueSkge1xuICAgICAgICAgICAgbG9nLmVycm9yKGVycik7XG4gICAgICAgICAgICBqc29uUmVzID0gcmVzLnZhbHVlLnZhbHVlLnRvU3RyaW5nKFwidXRmOFwiKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgYWxsUmVzdWx0cy5wdXNoKGpzb25SZXMpO1xuICAgICAgfVxuICAgICAgcmVzID0gYXdhaXQgaXRlcmF0b3IubmV4dCgpO1xuICAgIH1cbiAgICBsb2cuZGVidWcoYENsb3NpbmcgaXRlcmF0b3IgYWZ0ZXIgJHthbGxSZXN1bHRzLmxlbmd0aH0gcmVzdWx0c2ApO1xuICAgIGl0ZXJhdG9yLmNsb3NlKCk7IC8vIHB1cnBvc2VseSBub3QgYXdhaXQuIGxldCBpdGVyYXRvciBjbG9zZSBvbiBpdHMgb3duXG4gICAgcmV0dXJuIGFsbFJlc3VsdHM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEV4ZWN1dGVzIGEgcmF3IHF1ZXJ5IGFnYWluc3QgdGhlIHN0YXRlIGRhdGFiYXNlXG4gICAqIEBzdW1tYXJ5IFBlcmZvcm1zIGEgcmljaCBxdWVyeSB1c2luZyBDb3VjaERCIHN5bnRheCBhZ2FpbnN0IHRoZSBGYWJyaWMgc3RhdGUgZGF0YWJhc2VcbiAgICogQHRlbXBsYXRlIFIgLSBUaGUgcmV0dXJuIHR5cGVcbiAgICogQHBhcmFtIHtNYW5nb1F1ZXJ5fSByYXdJbnB1dCAtIFRoZSBNYW5nbyBRdWVyeSB0byBleGVjdXRlXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gZG9jc09ubHkgLSBXaGV0aGVyIHRvIHJldHVybiBvbmx5IGRvY3VtZW50cyAobm90IHVzZWQgaW4gdGhpcyBpbXBsZW1lbnRhdGlvbilcbiAgICogQHBhcmFtIHsuLi5hbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzLCBpbmNsdWRpbmcgdGhlIGNoYWluY29kZSBzdHViIGFuZCBsb2dnZXJcbiAgICogQHJldHVybiB7UHJvbWlzZTxSPn0gUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIHF1ZXJ5IHJlc3VsdHNcbiAgICogQG1lcm1haWRcbiAgICogc2VxdWVuY2VEaWFncmFtXG4gICAqICAgcGFydGljaXBhbnQgQ2FsbGVyXG4gICAqICAgcGFydGljaXBhbnQgRmFicmljQ29udHJhY3RBZGFwdGVyXG4gICAqICAgcGFydGljaXBhbnQgU3R1YlxuICAgKiAgIHBhcnRpY2lwYW50IFN0YXRlREJcbiAgICpcbiAgICogICBDYWxsZXItPj5GYWJyaWNDb250cmFjdEFkYXB0ZXI6IHJhdyhyYXdJbnB1dCwgZG9jc09ubHksIGN0eClcbiAgICogICBGYWJyaWNDb250cmFjdEFkYXB0ZXItPj5GYWJyaWNDb250cmFjdEFkYXB0ZXI6IEV4dHJhY3QgbGltaXQgYW5kIHNraXBcbiAgICogICBhbHQgV2l0aCBwYWdpbmF0aW9uXG4gICAqICAgICBGYWJyaWNDb250cmFjdEFkYXB0ZXItPj5TdHViOiBnZXRRdWVyeVJlc3VsdFdpdGhQYWdpbmF0aW9uKHF1ZXJ5LCBsaW1pdCwgc2tpcClcbiAgICogICBlbHNlIFdpdGhvdXQgcGFnaW5hdGlvblxuICAgKiAgICAgRmFicmljQ29udHJhY3RBZGFwdGVyLT4+U3R1YjogZ2V0UXVlcnlSZXN1bHQocXVlcnkpXG4gICAqICAgZW5kXG4gICAqICAgU3R1Yi0+PlN0YXRlREI6IEV4ZWN1dGUgcXVlcnlcbiAgICogICBTdGF0ZURCLS0+PlN0dWI6IEl0ZXJhdG9yXG4gICAqICAgU3R1Yi0tPj5GYWJyaWNDb250cmFjdEFkYXB0ZXI6IEl0ZXJhdG9yXG4gICAqICAgRmFicmljQ29udHJhY3RBZGFwdGVyLT4+RmFicmljQ29udHJhY3RBZGFwdGVyOiByZXN1bHRJdGVyYXRvcihsb2csIGl0ZXJhdG9yKVxuICAgKiAgIEZhYnJpY0NvbnRyYWN0QWRhcHRlci0tPj5DYWxsZXI6IHJlc3VsdHNcbiAgICovXG4gIGFzeW5jIHJhdzxSPihcbiAgICByYXdJbnB1dDogTWFuZ29RdWVyeSxcbiAgICBkb2NzT25seTogYm9vbGVhbixcbiAgICAuLi5hcmdzOiBhbnlbXVxuICApOiBQcm9taXNlPFI+IHtcbiAgICBjb25zdCB7IHN0dWIsIGxvZ2dlciB9ID0gYXJncy5wb3AoKTtcbiAgICBjb25zdCBsb2cgPSBsb2dnZXIuZm9yKHRoaXMucmF3KTtcbiAgICBjb25zdCB7IHNraXAsIGxpbWl0IH0gPSByYXdJbnB1dDtcbiAgICBsZXQgaXRlcmF0b3I6IEl0ZXJhdG9ycy5TdGF0ZVF1ZXJ5SXRlcmF0b3I7XG4gICAgaWYgKGxpbWl0IHx8IHNraXApIHtcbiAgICAgIGRlbGV0ZSByYXdJbnB1dFtcImxpbWl0XCJdO1xuICAgICAgZGVsZXRlIHJhd0lucHV0W1wic2tpcFwiXTtcbiAgICAgIGxvZy5kZWJ1ZyhcbiAgICAgICAgYFJldHJpZXZpbmcgcGFnaW5hdGVkIGl0ZXJhdG9yOiBsaW1pdDogJHtsaW1pdH0vIHNraXA6ICR7c2tpcH1gXG4gICAgICApO1xuICAgICAgY29uc3QgcmVzcG9uc2U6IFN0YXRlUXVlcnlSZXNwb25zZTxJdGVyYXRvcnMuU3RhdGVRdWVyeUl0ZXJhdG9yPiA9XG4gICAgICAgIChhd2FpdCB0aGlzLnF1ZXJ5UmVzdWx0UGFnaW5hdGVkKFxuICAgICAgICAgIHN0dWIsXG4gICAgICAgICAgcmF3SW5wdXQsXG4gICAgICAgICAgbGltaXQgfHwgMjUwLFxuICAgICAgICAgIChza2lwIGFzIGFueSk/LnRvU3RyaW5nKClcbiAgICAgICAgKSkgYXMgU3RhdGVRdWVyeVJlc3BvbnNlPEl0ZXJhdG9ycy5TdGF0ZVF1ZXJ5SXRlcmF0b3I+O1xuICAgICAgaXRlcmF0b3IgPSByZXNwb25zZS5pdGVyYXRvcjtcbiAgICB9IGVsc2Uge1xuICAgICAgbG9nLmRlYnVnKFwiUmV0cmlldmluZyBpdGVyYXRvclwiKTtcbiAgICAgIGl0ZXJhdG9yID0gKGF3YWl0IHRoaXMucXVlcnlSZXN1bHQoXG4gICAgICAgIHN0dWIsXG4gICAgICAgIHJhd0lucHV0XG4gICAgICApKSBhcyBJdGVyYXRvcnMuU3RhdGVRdWVyeUl0ZXJhdG9yO1xuICAgIH1cbiAgICBsb2cuZGVidWcoXCJJdGVyYXRvciBhY3F1aXJlZFwiKTtcblxuICAgIGNvbnN0IHJlc3VsdHMgPSAoYXdhaXQgdGhpcy5yZXN1bHRJdGVyYXRvcihsb2csIGl0ZXJhdG9yKSkgYXMgUjtcbiAgICBsb2cuZGVidWcoXG4gICAgICBgcmV0dXJuaW5nIHswfSByZXN1bHRzYCxcbiAgICAgIGAke0FycmF5LmlzQXJyYXkocmVzdWx0cykgPyByZXN1bHRzLmxlbmd0aCA6IDF9YFxuICAgICk7XG4gICAgcmV0dXJuIHJlc3VsdHM7XG4gIH1cblxuICBvdmVycmlkZSBTdGF0ZW1lbnQ8TSBleHRlbmRzIE1vZGVsPihcbiAgICBjdHg/OiBGYWJyaWNDb250cmFjdENvbnRleHRcbiAgKTogRmFicmljU3RhdGVtZW50PE0sIGFueT4ge1xuICAgIGlmICghY3R4KSB7XG4gICAgICB0aHJvdyBuZXcgTWlzc2luZ0NvbnRleHRFcnJvcihcIkNvbnRleHQgaXMgcmVxdWlyZWRcIik7XG4gICAgfVxuICAgIHJldHVybiBuZXcgRmFicmljU3RhdGVtZW50KHRoaXMsIGN0eCk7XG4gIH1cblxuICBvdmVycmlkZSBhc3luYyBTZXF1ZW5jZShvcHRpb25zOiBTZXF1ZW5jZU9wdGlvbnMpOiBQcm9taXNlPFNlcXVlbmNlPiB7XG4gICAgcmV0dXJuIG5ldyBGYWJyaWNDb250cmFjdFNlcXVlbmNlKG9wdGlvbnMsIHRoaXMpO1xuICB9XG5cbiAgb3ZlcnJpZGUgYXN5bmMgY3JlYXRlQWxsKFxuICAgIHRhYmxlTmFtZTogc3RyaW5nLFxuICAgIGlkOiAoc3RyaW5nIHwgbnVtYmVyKVtdLFxuICAgIG1vZGVsOiBSZWNvcmQ8c3RyaW5nLCBhbnk+W10sXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+W10+IHtcbiAgICBpZiAoaWQubGVuZ3RoICE9PSBtb2RlbC5sZW5ndGgpXG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcIklkcyBhbmQgbW9kZWxzIG11c3QgaGF2ZSB0aGUgc2FtZSBsZW5ndGhcIik7XG5cbiAgICBjb25zdCB7IGxvZ2dlciB9ID0gYXJnc1thcmdzLmxlbmd0aCAtIDFdIGFzIEZhYnJpY0NvbnRyYWN0Q29udGV4dDtcbiAgICBjb25zdCBsb2cgPSBsb2dnZXIuZm9yKHRoaXMuY3JlYXRlQWxsKTtcbiAgICBsb2cuaW5mbyhgQ3JlYXRpbmcgJHtpZC5sZW5ndGh9IGVudHJpZXMgJHt0YWJsZU5hbWV9IHRhYmxlYCk7XG4gICAgbG9nLmRlYnVnKGBwa3M6ICR7aWR9YCk7XG5cbiAgICByZXR1cm4gUHJvbWlzZS5hbGwoXG4gICAgICBpZC5tYXAoYXN5bmMgKGksIGluZGV4KSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLmNyZWF0ZSh0YWJsZU5hbWUsIGksIG1vZGVsW2luZGV4XSwgLi4uYXJncyk7XG4gICAgICB9KVxuICAgICk7XG4gIH1cblxuICBvdmVycmlkZSBhc3luYyB1cGRhdGVBbGwoXG4gICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICAgaWQ6IHN0cmluZ1tdIHwgbnVtYmVyW10sXG4gICAgbW9kZWw6IFJlY29yZDxzdHJpbmcsIGFueT5bXSxcbiAgICAuLi5hcmdzOiBhbnlbXVxuICApOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGFueT5bXT4ge1xuICAgIGlmIChpZC5sZW5ndGggIT09IG1vZGVsLmxlbmd0aClcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFwiSWRzIGFuZCBtb2RlbHMgbXVzdCBoYXZlIHRoZSBzYW1lIGxlbmd0aFwiKTtcblxuICAgIGNvbnN0IHsgbG9nZ2VyIH0gPSBhcmdzW2FyZ3MubGVuZ3RoIC0gMV0gYXMgRmFicmljQ29udHJhY3RDb250ZXh0O1xuXG4gICAgY29uc3QgbG9nID0gbG9nZ2VyLmZvcih0aGlzLmNyZWF0ZUFsbCk7XG4gICAgbG9nLmluZm8oYFVwZGF0aW5nICR7aWQubGVuZ3RofSBlbnRyaWVzICR7dGFibGVOYW1lfSB0YWJsZWApO1xuICAgIGxvZy5kZWJ1ZyhgcGtzOiAke2lkfWApO1xuXG4gICAgcmV0dXJuIFByb21pc2UuYWxsKFxuICAgICAgaWQubWFwKGFzeW5jIChpLCBpbmRleCkgPT4ge1xuICAgICAgICByZXR1cm4gdGhpcy51cGRhdGUodGFibGVOYW1lLCBpLCBtb2RlbFtpbmRleF0sIC4uLmFyZ3MpO1xuICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqXG4gICAqIEBwYXJhbSBtb2RlbFxuICAgKiBAcGFyYW0ge3N0cmluZ30gcGtcbiAgICogQHBhcmFtIGFyZ3NcbiAgICovXG4gIG92ZXJyaWRlIHByZXBhcmU8TSBleHRlbmRzIE1vZGVsPihcbiAgICBtb2RlbDogTSxcbiAgICBwazoga2V5b2YgTSxcbiAgICAuLi5hcmdzOiBhbnlbXVxuICApOiB7XG4gICAgcmVjb3JkOiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuICAgIGlkOiBzdHJpbmc7XG4gICAgdHJhbnNpZW50PzogUmVjb3JkPHN0cmluZywgYW55PjtcbiAgfSB7XG4gICAgY29uc3QgeyBzdHViLCBsb2dnZXIgfSA9IGFyZ3MucG9wKCk7XG4gICAgY29uc3QgdGFibGVOYW1lID0gYXJncy5zaGlmdCgpO1xuICAgIGNvbnN0IGxvZyA9IGxvZ2dlci5mb3IodGhpcy5wcmVwYXJlKTtcblxuICAgIGNvbnN0IHNwbGl0ID0gbW9kZWxUb1RyYW5zaWVudChtb2RlbCk7XG4gICAgY29uc3QgcmVzdWx0ID0gT2JqZWN0LmVudHJpZXMoc3BsaXQubW9kZWwpLnJlZHVjZShcbiAgICAgIChhY2N1bTogUmVjb3JkPHN0cmluZywgYW55PiwgW2tleSwgdmFsXSkgPT4ge1xuICAgICAgICBpZiAodHlwZW9mIHZhbCA9PT0gXCJ1bmRlZmluZWRcIikgcmV0dXJuIGFjY3VtO1xuICAgICAgICBjb25zdCBtYXBwZWRQcm9wID0gUmVwb3NpdG9yeS5jb2x1bW4obW9kZWwsIGtleSk7XG4gICAgICAgIGlmICh0aGlzLmlzUmVzZXJ2ZWQobWFwcGVkUHJvcCkpXG4gICAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoYFByb3BlcnR5IG5hbWUgJHttYXBwZWRQcm9wfSBpcyByZXNlcnZlZGApO1xuICAgICAgICBhY2N1bVttYXBwZWRQcm9wXSA9IHZhbDtcbiAgICAgICAgcmV0dXJuIGFjY3VtO1xuICAgICAgfSxcbiAgICAgIHt9XG4gICAgKTtcbiAgICBpZiAoKG1vZGVsIGFzIGFueSlbUGVyc2lzdGVuY2VLZXlzLk1FVEFEQVRBXSkge1xuICAgICAgbG9nLnNpbGx5KFxuICAgICAgICBgUGFzc2luZyBhbG9uZyBwZXJzaXN0ZW5jZSBtZXRhZGF0YSBmb3IgJHsobW9kZWwgYXMgYW55KVtQZXJzaXN0ZW5jZUtleXMuTUVUQURBVEFdfWBcbiAgICAgICk7XG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkocmVzdWx0LCBQZXJzaXN0ZW5jZUtleXMuTUVUQURBVEEsIHtcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgIHdyaXRhYmxlOiBmYWxzZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgICB2YWx1ZTogKG1vZGVsIGFzIGFueSlbUGVyc2lzdGVuY2VLZXlzLk1FVEFEQVRBXSxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGxvZy5pbmZvKGBQcmVwYXJpbmcgcmVjb3JkIGZvciAke3RhYmxlTmFtZX0gdGFibGUgd2l0aCBwayAke21vZGVsW3BrXX1gKTtcblxuICAgIHJldHVybiB7XG4gICAgICByZWNvcmQ6IHJlc3VsdCxcbiAgICAgIGlkOiBzdHViLmNyZWF0ZUNvbXBvc2l0ZUtleSh0YWJsZU5hbWUsIFtTdHJpbmcobW9kZWxbcGtdKV0pLFxuICAgICAgdHJhbnNpZW50OiBzcGxpdC50cmFuc2llbnQsXG4gICAgfTtcbiAgfVxuXG4gIG92ZXJyaWRlIHJldmVydDxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIG9iajogUmVjb3JkPHN0cmluZywgYW55PixcbiAgICBjbGF6ejogc3RyaW5nIHwgQ29uc3RydWN0b3I8TT4sXG4gICAgcGs6IGtleW9mIE0sXG4gICAgaWQ6IHN0cmluZyB8IG51bWJlcixcbiAgICB0cmFuc2llbnQ/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+XG4gICk6IE0ge1xuICAgIGNvbnN0IGxvZyA9IHRoaXMubG9nLmZvcih0aGlzLnJldmVydCk7XG4gICAgY29uc3Qgb2I6IFJlY29yZDxzdHJpbmcsIGFueT4gPSB7fTtcbiAgICBvYltwayBhcyBzdHJpbmddID0gaWQ7XG4gICAgY29uc3QgbSA9IChcbiAgICAgIHR5cGVvZiBjbGF6eiA9PT0gXCJzdHJpbmdcIiA/IE1vZGVsLmJ1aWxkKG9iLCBjbGF6eikgOiBuZXcgY2xhenoob2IpXG4gICAgKSBhcyBNO1xuICAgIGxvZy5zaWxseShgUmVidWlsZGluZyBtb2RlbCAke20uY29uc3RydWN0b3IubmFtZX0gaWQgJHtpZH1gKTtcbiAgICBjb25zdCBtZXRhZGF0YSA9IG9ialtQZXJzaXN0ZW5jZUtleXMuTUVUQURBVEFdO1xuICAgIGNvbnN0IHJlc3VsdCA9IE9iamVjdC5rZXlzKG0pLnJlZHVjZSgoYWNjdW06IE0sIGtleSkgPT4ge1xuICAgICAgKGFjY3VtIGFzIFJlY29yZDxzdHJpbmcsIGFueT4pW2tleV0gPSBvYmpbUmVwb3NpdG9yeS5jb2x1bW4oYWNjdW0sIGtleSldO1xuICAgICAgcmV0dXJuIGFjY3VtO1xuICAgIH0sIG0pO1xuXG4gICAgaWYgKHRyYW5zaWVudCkge1xuICAgICAgbG9nLnZlcmJvc2UoXG4gICAgICAgIGByZS1hZGRpbmcgdHJhbnNpZW50IHByb3BlcnRpZXM6ICR7T2JqZWN0LmtleXModHJhbnNpZW50KS5qb2luKFwiLCBcIil9YFxuICAgICAgKTtcbiAgICAgIE9iamVjdC5lbnRyaWVzKHRyYW5zaWVudCkuZm9yRWFjaCgoW2tleSwgdmFsXSkgPT4ge1xuICAgICAgICBpZiAoa2V5IGluIHJlc3VsdCAmJiAocmVzdWx0IGFzIGFueSlba2V5XSAhPT0gdW5kZWZpbmVkKVxuICAgICAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFxuICAgICAgICAgICAgYFRyYW5zaWVudCBwcm9wZXJ0eSAke2tleX0gYWxyZWFkeSBleGlzdHMgb24gbW9kZWwgJHttLmNvbnN0cnVjdG9yLm5hbWV9LiBzaG91bGQgYmUgaW1wb3NzaWJsZWBcbiAgICAgICAgICApO1xuICAgICAgICByZXN1bHRba2V5IGFzIGtleW9mIE1dID0gdmFsO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWYgKG1ldGFkYXRhKSB7XG4gICAgICBsb2cuc2lsbHkoXG4gICAgICAgIGBQYXNzaW5nIGFsb25nICR7dGhpcy5mbGF2b3VyfSBwZXJzaXN0ZW5jZSBtZXRhZGF0YSBmb3IgJHttLmNvbnN0cnVjdG9yLm5hbWV9IGlkICR7aWR9OiAke21ldGFkYXRhfWBcbiAgICAgICk7XG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkocmVzdWx0LCBQZXJzaXN0ZW5jZUtleXMuTUVUQURBVEEsIHtcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogZmFsc2UsXG4gICAgICAgIHdyaXRhYmxlOiBmYWxzZSxcbiAgICAgICAgdmFsdWU6IG1ldGFkYXRhLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIG92ZXJyaWRlIGNyZWF0ZVByZWZpeChcbiAgICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgICBpZDogc3RyaW5nIHwgbnVtYmVyLFxuICAgIG1vZGVsOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICAgIC4uLmFyZ3M6IGFueVtdXG4gICkge1xuICAgIGNvbnN0IGN0eDogRmFicmljQ29udHJhY3RDb250ZXh0ID0gYXJncy5wb3AoKTtcbiAgICBjb25zdCByZWNvcmQ6IFJlY29yZDxzdHJpbmcsIGFueT4gPSB7fTtcbiAgICByZWNvcmRbQ291Y2hEQktleXMuVEFCTEVdID0gdGFibGVOYW1lO1xuICAgIC8vIHJlY29yZFtDb3VjaERCS2V5cy5JRF0gPSB0aGlzLmdlbmVyYXRlSWQodGFibGVOYW1lLCBpZCk7XG4gICAgT2JqZWN0LmFzc2lnbihyZWNvcmQsIG1vZGVsKTtcbiAgICByZXR1cm4gW3RhYmxlTmFtZSwgaWQsIHJlY29yZCwgY3R4XTtcbiAgfVxuXG4gIG92ZXJyaWRlIHVwZGF0ZVByZWZpeChcbiAgICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgICBpZDogc3RyaW5nIHwgbnVtYmVyLFxuICAgIG1vZGVsOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IChzdHJpbmcgfCBudW1iZXIgfCBSZWNvcmQ8c3RyaW5nLCBhbnk+KVtdIHtcbiAgICBjb25zdCBjdHg6IEZhYnJpY0NvbnRyYWN0Q29udGV4dCA9IGFyZ3MucG9wKCk7XG4gICAgY29uc3QgcmVjb3JkOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge307XG4gICAgcmVjb3JkW0NvdWNoREJLZXlzLlRBQkxFXSA9IHRhYmxlTmFtZTtcbiAgICAvLyByZWNvcmRbQ291Y2hEQktleXMuSURdID0gdGhpcy5nZW5lcmF0ZUlkKHRhYmxlTmFtZSwgaWQpO1xuICAgIE9iamVjdC5hc3NpZ24ocmVjb3JkLCBtb2RlbCk7XG4gICAgcmV0dXJuIFt0YWJsZU5hbWUsIGlkLCByZWNvcmQsIGN0eF07XG4gIH1cblxuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgY3JlYXRlQWxsUHJlZml4KFxuICAgIHRhYmxlTmFtZTogc3RyaW5nLFxuICAgIGlkczogc3RyaW5nW10gfCBudW1iZXJbXSxcbiAgICBtb2RlbHM6IFJlY29yZDxzdHJpbmcsIGFueT5bXSxcbiAgICAuLi5hcmdzOiBhbnlbXVxuICApOiAoc3RyaW5nIHwgc3RyaW5nW10gfCBudW1iZXJbXSB8IFJlY29yZDxzdHJpbmcsIGFueT5bXSlbXSB7XG4gICAgaWYgKGlkcy5sZW5ndGggIT09IG1vZGVscy5sZW5ndGgpXG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcIklkcyBhbmQgbW9kZWxzIG11c3QgaGF2ZSB0aGUgc2FtZSBsZW5ndGhcIik7XG5cbiAgICBjb25zdCBjdHg6IEZhYnJpY0NvbnRyYWN0Q29udGV4dCA9IGFyZ3MucG9wKCk7XG5cbiAgICBjb25zdCByZWNvcmRzID0gaWRzLm1hcCgoaWQsIGNvdW50KSA9PiB7XG4gICAgICBjb25zdCByZWNvcmQ6IFJlY29yZDxzdHJpbmcsIGFueT4gPSB7fTtcbiAgICAgIHJlY29yZFtDb3VjaERCS2V5cy5UQUJMRV0gPSB0YWJsZU5hbWU7XG4gICAgICAvLyByZWNvcmRbQ291Y2hEQktleXMuSURdID0gdGhpcy5nZW5lcmF0ZUlkKHRhYmxlTmFtZSwgaWQpO1xuICAgICAgT2JqZWN0LmFzc2lnbihyZWNvcmQsIG1vZGVsc1tjb3VudF0pO1xuICAgICAgcmV0dXJuIHJlY29yZDtcbiAgICB9KTtcbiAgICByZXR1cm4gW3RhYmxlTmFtZSwgaWRzLCByZWNvcmRzLCBjdHggYXMgYW55XTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvdmVycmlkZSB1cGRhdGVBbGxQcmVmaXgoXG4gICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICAgaWRzOiBzdHJpbmdbXSB8IG51bWJlcltdLFxuICAgIG1vZGVsczogUmVjb3JkPHN0cmluZywgYW55PltdLFxuICAgIC4uLmFyZ3M6IGFueVtdXG4gICkge1xuICAgIGlmIChpZHMubGVuZ3RoICE9PSBtb2RlbHMubGVuZ3RoKVxuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXCJJZHMgYW5kIG1vZGVscyBtdXN0IGhhdmUgdGhlIHNhbWUgbGVuZ3RoXCIpO1xuXG4gICAgY29uc3QgY3R4OiBGYWJyaWNDb250cmFjdENvbnRleHQgPSBhcmdzLnBvcCgpO1xuXG4gICAgY29uc3QgcmVjb3JkcyA9IGlkcy5tYXAoKGlkLCBjb3VudCkgPT4ge1xuICAgICAgY29uc3QgcmVjb3JkOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge307XG4gICAgICByZWNvcmRbQ291Y2hEQktleXMuVEFCTEVdID0gdGFibGVOYW1lO1xuICAgICAgT2JqZWN0LmFzc2lnbihyZWNvcmQsIG1vZGVsc1tjb3VudF0pO1xuICAgICAgcmV0dXJuIHJlY29yZDtcbiAgICB9KTtcbiAgICByZXR1cm4gW3RhYmxlTmFtZSwgaWRzLCByZWNvcmRzLCBjdHggYXMgYW55XTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU3RhdGljIG1ldGhvZCBmb3IgZGVjb3JhdGlvbiBvdmVycmlkZXNcbiAgICogQHN1bW1hcnkgT3ZlcnJpZGVzL2V4dGVuZHMgZGVjYWYgZGVjb3JhdGlvbiB3aXRoIEZhYnJpYy1zcGVjaWZpYyBmdW5jdGlvbmFsaXR5XG4gICAqIEBzdGF0aWNcbiAgICogQG92ZXJyaWRlXG4gICAqIEByZXR1cm4ge3ZvaWR9XG4gICAqL1xuICBzdGF0aWMgb3ZlcnJpZGUgZGVjb3JhdGlvbigpOiB2b2lkIHtcbiAgICBzdXBlci5kZWNvcmF0aW9uKCk7XG4gICAgY29uc3QgY3JlYXRlZEJ5S2V5ID0gUmVwb3NpdG9yeS5rZXkoUGVyc2lzdGVuY2VLZXlzLkNSRUFURURfQlkpO1xuICAgIGNvbnN0IHVwZGF0ZWRCeUtleSA9IFJlcG9zaXRvcnkua2V5KFBlcnNpc3RlbmNlS2V5cy5VUERBVEVEX0JZKTtcbiAgICBEZWNvcmF0aW9uLmZsYXZvdXJlZEFzKEZhYnJpY0ZsYXZvdXIpXG4gICAgICAuZm9yKGNyZWF0ZWRCeUtleSlcbiAgICAgIC5kZWZpbmUoXG4gICAgICAgIG9uQ3JlYXRlKGNyZWF0ZWRCeU9uRmFicmljQ3JlYXRlVXBkYXRlKSxcbiAgICAgICAgcHJvcE1ldGFkYXRhKGNyZWF0ZWRCeUtleSwge30pXG4gICAgICApXG4gICAgICAuYXBwbHkoKTtcblxuICAgIERlY29yYXRpb24uZmxhdm91cmVkQXMoRmFicmljRmxhdm91cilcbiAgICAgIC5mb3IodXBkYXRlZEJ5S2V5KVxuICAgICAgLmRlZmluZShcbiAgICAgICAgb25DcmVhdGVVcGRhdGUoY3JlYXRlZEJ5T25GYWJyaWNDcmVhdGVVcGRhdGUpLFxuICAgICAgICBwcm9wTWV0YWRhdGEodXBkYXRlZEJ5S2V5LCB7fSlcbiAgICAgIClcbiAgICAgIC5hcHBseSgpO1xuXG4gICAgY29uc3QgcGtLZXkgPSBSZXBvc2l0b3J5LmtleShEQktleXMuSUQpO1xuICAgIERlY29yYXRpb24uZmxhdm91cmVkQXMoRmFicmljRmxhdm91cilcbiAgICAgIC5mb3IocGtLZXkpXG4gICAgICAuZGVmaW5lKFxuICAgICAgICBpbmRleChbT3JkZXJEaXJlY3Rpb24uQVNDLCBPcmRlckRpcmVjdGlvbi5EU0NdKSxcbiAgICAgICAgcmVxdWlyZWQoKSxcbiAgICAgICAgcmVhZG9ubHkoKSxcbiAgICAgICAgLy8gdHlwZShbU3RyaW5nLm5hbWUsIE51bWJlci5uYW1lLCBCaWdJbnQubmFtZV0pLFxuICAgICAgICBwcm9wTWV0YWRhdGEocGtLZXksIE51bWVyaWNTZXF1ZW5jZSksXG4gICAgICAgIG9uQ3JlYXRlKHBrRmFicmljT25DcmVhdGUsIE51bWVyaWNTZXF1ZW5jZSlcbiAgICAgIClcbiAgICAgIC5hcHBseSgpO1xuXG4gICAgY29uc3QgY29sdW1uS2V5ID0gQWRhcHRlci5rZXkoUGVyc2lzdGVuY2VLZXlzLkNPTFVNTik7XG4gICAgRGVjb3JhdGlvbi5mbGF2b3VyZWRBcyhGYWJyaWNGbGF2b3VyKVxuICAgICAgLmZvcihjb2x1bW5LZXkpXG4gICAgICAuZXh0ZW5kKEZhYnJpY1Byb3BlcnR5KCkpXG4gICAgICAuYXBwbHkoKTtcblxuICAgIGNvbnN0IHRhYmxlS2V5ID0gQWRhcHRlci5rZXkoUGVyc2lzdGVuY2VLZXlzLlRBQkxFKTtcbiAgICBEZWNvcmF0aW9uLmZsYXZvdXJlZEFzKEZhYnJpY0ZsYXZvdXIpXG4gICAgICAuZm9yKHRhYmxlS2V5KVxuICAgICAgLmV4dGVuZChmdW5jdGlvbiB0YWJsZShvYmo6IGFueSkge1xuICAgICAgICAvLyBjb25zdCBjaGFpbjogYW55W10gPSBbXTtcblxuICAgICAgICAvLyBsZXQgY3VycmVudCA9IG9iajtcblxuICAgICAgICAvLyBkbyB7XG4gICAgICAgIC8vICAgY2hhaW4ucHVzaChjdXJyZW50KTtcbiAgICAgICAgLy8gICBjb25zb2xlLmxvZyhgRm91bmQgY2xhc3M6ICR7Y3VycmVudH1gKTtcbiAgICAgICAgLy8gfSB3aGlsZSAoY3VycmVudCAmJiBjdXJyZW50ICE9PSBPYmplY3QucHJvdG90eXBlKTtcblxuICAgICAgICAvLyBkbyB7XG4gICAgICAgIC8vICAgY3VycmVudCA9IGNoYWluLnBvcCgpO1xuICAgICAgICAvLyAgIGNvbnNvbGUubG9nKGBBcHBseWluZyBAT2JqZWN0KCkgdG8gY2xhc3M6ICR7Y3VycmVudH1gKTtcbiAgICAgICAgLy8gICAvL1RPRE86IFRISVMgSVMgTk9UIFdPUktJTkcgQU5EIFRIUk9XUyBFUlJPUlxuICAgICAgICAvLyAgIC8vIEZhYnJpY09iamVjdCgpKGN1cnJlbnQpO1xuICAgICAgICAvLyB9IHdoaWxlIChjaGFpbi5sZW5ndGggPiAxKTtcblxuICAgICAgICByZXR1cm4gRmFicmljT2JqZWN0KCkob2JqKTtcbiAgICAgIH0pXG4gICAgICAuYXBwbHkoKTtcblxuICAgIGNvbnN0IG9uZVRvT25la2V5ID0gUmVwb3NpdG9yeS5rZXkoUGVyc2lzdGVuY2VLZXlzLk9ORV9UT19PTkUpO1xuXG4gICAgZnVuY3Rpb24gb25lVG9PbmVEZWM8TSBleHRlbmRzIE1vZGVsPihcbiAgICAgIGNsYXp6OiBDb25zdHJ1Y3RvcjxNPiB8ICgoKSA9PiBDb25zdHJ1Y3RvcjxNPiksXG4gICAgICBjYXNjYWRlOiBDYXNjYWRlTWV0YWRhdGEsXG4gICAgICBwb3B1bGF0ZTogYm9vbGVhbixcbiAgICAgIGpvaW5Db2x1bW5PcHRzPzogSm9pbkNvbHVtbk9wdGlvbnMsXG4gICAgICBmaz86IHN0cmluZ1xuICAgICkge1xuICAgICAgY29uc3QgbWV0YTogUmVsYXRpb25zTWV0YWRhdGEgPSB7XG4gICAgICAgIGNsYXNzOiBjbGF6ei5uYW1lID8gY2xhenoubmFtZSA6IChjbGF6eiBhcyBhbnkpLFxuICAgICAgICBjYXNjYWRlOiBjYXNjYWRlLFxuICAgICAgICBwb3B1bGF0ZTogcG9wdWxhdGUsXG4gICAgICB9O1xuICAgICAgaWYgKGpvaW5Db2x1bW5PcHRzKSBtZXRhLmpvaW5UYWJsZSA9IGpvaW5Db2x1bW5PcHRzO1xuICAgICAgaWYgKGZrKSBtZXRhLm5hbWUgPSBmaztcbiAgICAgIHJldHVybiBhcHBseShcbiAgICAgICAgcHJvcChQZXJzaXN0ZW5jZUtleXMuUkVMQVRJT05TKSxcbiAgICAgICAgdHlwZShbXG4gICAgICAgICAgY2xhenoubmFtZSA/IGNsYXp6Lm5hbWUgOiAoY2xhenogYXMgYW55KSxcbiAgICAgICAgICBTdHJpbmcubmFtZSxcbiAgICAgICAgICBOdW1iZXIubmFtZSxcbiAgICAgICAgICBCaWdJbnQubmFtZSxcbiAgICAgICAgXSksXG4gICAgICAgIG9uQ3JlYXRlKG9uZVRvT25lT25DcmVhdGUsIG1ldGEpLFxuICAgICAgICBvblVwZGF0ZShvbmVUb09uZU9uVXBkYXRlLCBtZXRhKSxcbiAgICAgICAgb25EZWxldGUob25lVG9PbmVPbkRlbGV0ZSwgbWV0YSksXG4gICAgICAgIGFmdGVyQW55KHBvcCwgbWV0YSksXG4gICAgICAgIHByb3BNZXRhZGF0YShvbmVUb09uZWtleSwgbWV0YSlcbiAgICAgICk7XG4gICAgfVxuXG4gICAgRGVjb3JhdGlvbi5mbGF2b3VyZWRBcyhGYWJyaWNGbGF2b3VyKVxuICAgICAgLmZvcihvbmVUb09uZWtleSlcbiAgICAgIC5kZWZpbmUoe1xuICAgICAgICBkZWNvcmF0b3I6IG9uZVRvT25lRGVjLFxuICAgICAgfSlcbiAgICAgIC5hcHBseSgpO1xuXG4gICAgY29uc3Qgb25lVG9NYW55S2V5ID0gUmVwb3NpdG9yeS5rZXkoUGVyc2lzdGVuY2VLZXlzLk9ORV9UT19NQU5ZKTtcblxuICAgIGZ1bmN0aW9uIG9uZVRvTWFueURlYzxNIGV4dGVuZHMgTW9kZWw+KFxuICAgICAgY2xheno6IENvbnN0cnVjdG9yPE0+IHwgKCgpID0+IENvbnN0cnVjdG9yPE0+KSxcbiAgICAgIGNhc2NhZGU6IENhc2NhZGVNZXRhZGF0YSxcbiAgICAgIHBvcHVsYXRlOiBib29sZWFuLFxuICAgICAgam9pblRhYmxlT3B0cz86IEpvaW5UYWJsZU9wdGlvbnMgfCBKb2luVGFibGVNdWx0aXBsZUNvbHVtbnNPcHRpb25zLFxuICAgICAgZms/OiBzdHJpbmdcbiAgICApIHtcbiAgICAgIGNvbnN0IG1ldGFkYXRhOiBSZWxhdGlvbnNNZXRhZGF0YSA9IHtcbiAgICAgICAgY2xhc3M6IGNsYXp6Lm5hbWUgPyBjbGF6ei5uYW1lIDogKGNsYXp6IGFzIGFueSksXG4gICAgICAgIGNhc2NhZGU6IGNhc2NhZGUsXG4gICAgICAgIHBvcHVsYXRlOiBwb3B1bGF0ZSxcbiAgICAgIH07XG4gICAgICBpZiAoam9pblRhYmxlT3B0cykgbWV0YWRhdGEuam9pblRhYmxlID0gam9pblRhYmxlT3B0cztcbiAgICAgIGlmIChmaykgbWV0YWRhdGEubmFtZSA9IGZrO1xuICAgICAgcmV0dXJuIGFwcGx5KFxuICAgICAgICBwcm9wKFBlcnNpc3RlbmNlS2V5cy5SRUxBVElPTlMpLFxuICAgICAgICBsaXN0KFtjbGF6eiBhcyBDb25zdHJ1Y3RvcjxNPiwgU3RyaW5nLCBOdW1iZXIsIEJpZ0ludF0pLFxuICAgICAgICBvbkNyZWF0ZShvbmVUb01hbnlPbkNyZWF0ZSwgbWV0YWRhdGEpLFxuICAgICAgICBvblVwZGF0ZShvbmVUb01hbnlPblVwZGF0ZSwgbWV0YWRhdGEpLFxuICAgICAgICBvbkRlbGV0ZShvbmVUb01hbnlPbkRlbGV0ZSwgbWV0YWRhdGEpLFxuICAgICAgICBhZnRlckFueShwb3AsIG1ldGFkYXRhKSxcbiAgICAgICAgcHJvcE1ldGFkYXRhKG9uZVRvTWFueUtleSwgbWV0YWRhdGEpXG4gICAgICApO1xuICAgIH1cblxuICAgIERlY29yYXRpb24uZm9yKG9uZVRvTWFueUtleSlcbiAgICAgIC5kZWZpbmUoe1xuICAgICAgICBkZWNvcmF0b3I6IG9uZVRvTWFueURlYyxcbiAgICAgIH0pXG4gICAgICAuYXBwbHkoKTtcbiAgfVxufVxuXG5GYWJyaWNDb250cmFjdEFkYXB0ZXIuZGVjb3JhdGlvbigpO1xuQWRhcHRlci5zZXRDdXJyZW50KEZhYnJpY0ZsYXZvdXIpO1xuIl19
|