@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,162 @@
|
|
|
1
|
+
import { EventIds, ObserverHandler, Repository, WhereOption } from "@decaf-ts/core";
|
|
2
|
+
import { FabricContractAdapter } from "./ContractAdapter";
|
|
3
|
+
import { FabricContractFlags } from "./types";
|
|
4
|
+
import { FabricContractContext } from "./ContractContext";
|
|
5
|
+
import { Constructor, Model } from "@decaf-ts/decorator-validation";
|
|
6
|
+
import { BulkCrudOperationKeys, OperationKeys } from "@decaf-ts/db-decorators";
|
|
7
|
+
import { MangoQuery } from "@decaf-ts/for-couchdb";
|
|
8
|
+
import { Context } from "fabric-contract-api";
|
|
9
|
+
import { ContractLogger } from "./logging";
|
|
10
|
+
/**
|
|
11
|
+
* @description Repository for Hyperledger Fabric chaincode models
|
|
12
|
+
* @summary Provides CRUD operations for models within Fabric chaincode contracts
|
|
13
|
+
* @template M - Type extending Model
|
|
14
|
+
* @template MangoQuery - Query type for CouchDB-like queries
|
|
15
|
+
* @template FabricContractAdapter - Adapter type for Fabric contract operations
|
|
16
|
+
* @template FabricContractFlags - Flags specific to Fabric contract operations
|
|
17
|
+
* @template FabricContractContext - Context type for Fabric contract operations
|
|
18
|
+
*
|
|
19
|
+
* @param {FabricContractAdapter} [adapter] - The adapter for interacting with the state database
|
|
20
|
+
* @param {Constructor<M>} [clazz] - The model constructor
|
|
21
|
+
* @param {Array<OperationKeys | BulkCrudOperationKeys | string>} [trackedEvents] - Events to track for observer notifications
|
|
22
|
+
*
|
|
23
|
+
* @class FabricContractRepository
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* // In a Fabric chaincode contract class
|
|
27
|
+
* import { FabricContractRepository, FabricContractAdapter } from '@decaf-ts/for-fabric';
|
|
28
|
+
*
|
|
29
|
+
* @table('assets')
|
|
30
|
+
* class Asset extends Model {
|
|
31
|
+
* @id()
|
|
32
|
+
* id: string;
|
|
33
|
+
*
|
|
34
|
+
* @property()
|
|
35
|
+
* data: string;
|
|
36
|
+
* }
|
|
37
|
+
*
|
|
38
|
+
* export class MyContract extends Contract {
|
|
39
|
+
* private adapter = new FabricContractAdapter();
|
|
40
|
+
* private repository: FabricContractRepository<Asset>;
|
|
41
|
+
*
|
|
42
|
+
* constructor() {
|
|
43
|
+
* super('MyContract');
|
|
44
|
+
* this.repository = new FabricContractRepository<Asset>(this.adapter, Asset);
|
|
45
|
+
* }
|
|
46
|
+
*
|
|
47
|
+
* @Transaction()
|
|
48
|
+
* async createAsset(ctx: Context, id: string, data: string): Promise<void> {
|
|
49
|
+
* const asset = new Asset();
|
|
50
|
+
* asset.id = id;
|
|
51
|
+
* asset.data = data;
|
|
52
|
+
*
|
|
53
|
+
* await this.repository.create(asset, { stub: ctx.stub });
|
|
54
|
+
* }
|
|
55
|
+
* }
|
|
56
|
+
* ```
|
|
57
|
+
* @mermaid
|
|
58
|
+
* sequenceDiagram
|
|
59
|
+
* participant Contract
|
|
60
|
+
* participant Repository
|
|
61
|
+
* participant Adapter
|
|
62
|
+
* participant StateDB
|
|
63
|
+
*
|
|
64
|
+
* Contract->>Repository: create(model, ctx)
|
|
65
|
+
* Repository->>Adapter: prepare(model, pk)
|
|
66
|
+
* Repository->>Adapter: create(tableName, id, record, transient, ctx)
|
|
67
|
+
* Adapter->>StateDB: putState(id, serializedData)
|
|
68
|
+
* StateDB-->>Adapter: Success
|
|
69
|
+
* Adapter-->>Repository: record
|
|
70
|
+
* Repository->>Adapter: revert(record, class, pk, id, transient)
|
|
71
|
+
* Adapter-->>Repository: model
|
|
72
|
+
* Repository-->>Contract: model
|
|
73
|
+
*/
|
|
74
|
+
export declare class FabricContractRepository<M extends Model> extends Repository<M, MangoQuery, FabricContractAdapter, FabricContractFlags, FabricContractContext> {
|
|
75
|
+
protected trackedEvents?: (OperationKeys | BulkCrudOperationKeys | string)[] | undefined;
|
|
76
|
+
constructor(adapter?: FabricContractAdapter, clazz?: Constructor<M>, trackedEvents?: (OperationKeys | BulkCrudOperationKeys | string)[] | undefined);
|
|
77
|
+
/**
|
|
78
|
+
* @description Creates a logger for a specific chaincode context
|
|
79
|
+
* @summary Returns a ContractLogger instance configured for the current context
|
|
80
|
+
* @param {Ctx} ctx - The Fabric chaincode context
|
|
81
|
+
* @return {ContractLogger} The logger instance
|
|
82
|
+
*/
|
|
83
|
+
logFor(ctx: Context): ContractLogger;
|
|
84
|
+
/**
|
|
85
|
+
* @description Creates a single model in the state database
|
|
86
|
+
* @summary Prepares, creates, and reverts a model using the adapter
|
|
87
|
+
* @param {M} model - The model to create
|
|
88
|
+
* @param {...any[]} args - Additional arguments, including the chaincode context
|
|
89
|
+
* @return {Promise<M>} Promise resolving to the created model
|
|
90
|
+
*/
|
|
91
|
+
create(model: M, ...args: any[]): Promise<M>;
|
|
92
|
+
read(id: string | number | bigint, ...args: any[]): Promise<M>;
|
|
93
|
+
/**
|
|
94
|
+
* @description Deletes a model from the database by ID.
|
|
95
|
+
* @summary Removes a model instance from the database using its primary key.
|
|
96
|
+
* @param {string|number|bigint} id - The primary key of the model to delete.
|
|
97
|
+
* @param {...any[]} args - Additional arguments.
|
|
98
|
+
* @return {Promise<M>} The deleted model instance.
|
|
99
|
+
*/
|
|
100
|
+
delete(id: string, ...args: any[]): Promise<M>;
|
|
101
|
+
/**
|
|
102
|
+
* @description Updates a single model in the state database
|
|
103
|
+
* @summary Prepares, updates, and reverts a model using the adapter
|
|
104
|
+
* @param {M} model - The model to update
|
|
105
|
+
* @param {...any[]} args - Additional arguments, including the chaincode context
|
|
106
|
+
* @return {Promise<M>} Promise resolving to the updated model
|
|
107
|
+
*/
|
|
108
|
+
update(model: M, ...args: any[]): Promise<M>;
|
|
109
|
+
/**
|
|
110
|
+
* @description Gets the observer handler for this repository
|
|
111
|
+
* @summary Returns a FabricContractRepositoryObservableHandler instance
|
|
112
|
+
* @return {ObserverHandler} The observer handler
|
|
113
|
+
*/
|
|
114
|
+
ObserverHandler(): ObserverHandler;
|
|
115
|
+
/**
|
|
116
|
+
* @description Creates multiple models in the state database
|
|
117
|
+
* @summary Prepares, creates, and reverts multiple models using the adapter
|
|
118
|
+
* @param {M[]} models - The models to create
|
|
119
|
+
* @param {...any[]} args - Additional arguments, including the chaincode context
|
|
120
|
+
* @return {Promise<M[]>} Promise resolving to the created models
|
|
121
|
+
*/
|
|
122
|
+
createAll(models: M[], ...args: any[]): Promise<M[]>;
|
|
123
|
+
/**
|
|
124
|
+
* @description Updates multiple models in the state database
|
|
125
|
+
* @summary Prepares, updates, and reverts multiple models using the adapter
|
|
126
|
+
* @param {M[]} models - The models to update
|
|
127
|
+
* @param {...any[]} args - Additional arguments, including the chaincode context
|
|
128
|
+
* @return {Promise<M[]>} Promise resolving to the updated models
|
|
129
|
+
*/
|
|
130
|
+
updateAll(models: M[], ...args: any[]): Promise<M[]>;
|
|
131
|
+
/**
|
|
132
|
+
* @description Executes a raw query against the state database
|
|
133
|
+
* @summary Delegates to the adapter's raw method
|
|
134
|
+
* @param {MangoQuery} rawInput - The Mango Query to execute
|
|
135
|
+
* @param {boolean} docsOnly - Whether to return only documents
|
|
136
|
+
* @param {...any[]} args - Additional arguments, including the chaincode context
|
|
137
|
+
* @return {Promise<any>} Promise resolving to the query results
|
|
138
|
+
*/
|
|
139
|
+
raw(rawInput: MangoQuery, docsOnly: boolean, ...args: any[]): Promise<unknown>;
|
|
140
|
+
/**
|
|
141
|
+
* @description Updates observers based on tracked events
|
|
142
|
+
* @summary Filters events based on trackedEvents and delegates to the parent method
|
|
143
|
+
* @param {string} table - The table/collection name
|
|
144
|
+
* @param {OperationKeys | BulkCrudOperationKeys | string} event - The event type
|
|
145
|
+
* @param {EventIds} id - The event identifier
|
|
146
|
+
* @param {FabricContractContext} ctx - The Fabric contract context
|
|
147
|
+
* @param {...any[]} args - Additional arguments
|
|
148
|
+
* @return {Promise<void>} Promise that resolves when observers are updated
|
|
149
|
+
*/
|
|
150
|
+
updateObservers(table: string, event: OperationKeys | BulkCrudOperationKeys | string, id: EventIds, ctx: FabricContractContext, ...args: any[]): Promise<void>;
|
|
151
|
+
selectWithContext<S extends readonly (keyof M)[]>(selector?: readonly [...S], ctx?: FabricContractContext | Context): Promise<WhereOption<M, M[]> | WhereOption<M, Pick<M, S[number]>[]>>;
|
|
152
|
+
/**
|
|
153
|
+
* @description Prepares multiple models for creation.
|
|
154
|
+
* @summary Validates multiple models and prepares them for creation in the database.
|
|
155
|
+
* @param {M[]} models - The models to create.
|
|
156
|
+
* @param {...any[]} args - Additional arguments.
|
|
157
|
+
* @return The prepared models and context arguments.
|
|
158
|
+
* @throws {ValidationError} If any model fails validation.
|
|
159
|
+
*/
|
|
160
|
+
protected createAllPrefix(models: M[], ...args: any[]): Promise<any[]>;
|
|
161
|
+
protected createPrefix(model: M, ...args: any[]): Promise<[M, ...any[]]>;
|
|
162
|
+
}
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
import { Repository, } from "@decaf-ts/core";
|
|
2
|
+
import { FabricContractContext } from "./ContractContext.js";
|
|
3
|
+
import { ConflictError, Context as Ctx, Context as CTX, enforceDBDecorators, InternalError, OperationKeys, ValidationError, } from "@decaf-ts/db-decorators";
|
|
4
|
+
import { FabricContractRepositoryObservableHandler } from "./FabricContractRepositoryObservableHandler.js";
|
|
5
|
+
import { FabricContractSequence } from "./FabricContractSequence.js";
|
|
6
|
+
import { Logging } from "@decaf-ts/logging";
|
|
7
|
+
/**
|
|
8
|
+
* @description Repository for Hyperledger Fabric chaincode models
|
|
9
|
+
* @summary Provides CRUD operations for models within Fabric chaincode contracts
|
|
10
|
+
* @template M - Type extending Model
|
|
11
|
+
* @template MangoQuery - Query type for CouchDB-like queries
|
|
12
|
+
* @template FabricContractAdapter - Adapter type for Fabric contract operations
|
|
13
|
+
* @template FabricContractFlags - Flags specific to Fabric contract operations
|
|
14
|
+
* @template FabricContractContext - Context type for Fabric contract operations
|
|
15
|
+
*
|
|
16
|
+
* @param {FabricContractAdapter} [adapter] - The adapter for interacting with the state database
|
|
17
|
+
* @param {Constructor<M>} [clazz] - The model constructor
|
|
18
|
+
* @param {Array<OperationKeys | BulkCrudOperationKeys | string>} [trackedEvents] - Events to track for observer notifications
|
|
19
|
+
*
|
|
20
|
+
* @class FabricContractRepository
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* // In a Fabric chaincode contract class
|
|
24
|
+
* import { FabricContractRepository, FabricContractAdapter } from '@decaf-ts/for-fabric';
|
|
25
|
+
*
|
|
26
|
+
* @table('assets')
|
|
27
|
+
* class Asset extends Model {
|
|
28
|
+
* @id()
|
|
29
|
+
* id: string;
|
|
30
|
+
*
|
|
31
|
+
* @property()
|
|
32
|
+
* data: string;
|
|
33
|
+
* }
|
|
34
|
+
*
|
|
35
|
+
* export class MyContract extends Contract {
|
|
36
|
+
* private adapter = new FabricContractAdapter();
|
|
37
|
+
* private repository: FabricContractRepository<Asset>;
|
|
38
|
+
*
|
|
39
|
+
* constructor() {
|
|
40
|
+
* super('MyContract');
|
|
41
|
+
* this.repository = new FabricContractRepository<Asset>(this.adapter, Asset);
|
|
42
|
+
* }
|
|
43
|
+
*
|
|
44
|
+
* @Transaction()
|
|
45
|
+
* async createAsset(ctx: Context, id: string, data: string): Promise<void> {
|
|
46
|
+
* const asset = new Asset();
|
|
47
|
+
* asset.id = id;
|
|
48
|
+
* asset.data = data;
|
|
49
|
+
*
|
|
50
|
+
* await this.repository.create(asset, { stub: ctx.stub });
|
|
51
|
+
* }
|
|
52
|
+
* }
|
|
53
|
+
* ```
|
|
54
|
+
* @mermaid
|
|
55
|
+
* sequenceDiagram
|
|
56
|
+
* participant Contract
|
|
57
|
+
* participant Repository
|
|
58
|
+
* participant Adapter
|
|
59
|
+
* participant StateDB
|
|
60
|
+
*
|
|
61
|
+
* Contract->>Repository: create(model, ctx)
|
|
62
|
+
* Repository->>Adapter: prepare(model, pk)
|
|
63
|
+
* Repository->>Adapter: create(tableName, id, record, transient, ctx)
|
|
64
|
+
* Adapter->>StateDB: putState(id, serializedData)
|
|
65
|
+
* StateDB-->>Adapter: Success
|
|
66
|
+
* Adapter-->>Repository: record
|
|
67
|
+
* Repository->>Adapter: revert(record, class, pk, id, transient)
|
|
68
|
+
* Adapter-->>Repository: model
|
|
69
|
+
* Repository-->>Contract: model
|
|
70
|
+
*/
|
|
71
|
+
export class FabricContractRepository extends Repository {
|
|
72
|
+
constructor(adapter, clazz, trackedEvents) {
|
|
73
|
+
super(adapter, clazz);
|
|
74
|
+
this.trackedEvents = trackedEvents;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* @description Creates a logger for a specific chaincode context
|
|
78
|
+
* @summary Returns a ContractLogger instance configured for the current context
|
|
79
|
+
* @param {Ctx} ctx - The Fabric chaincode context
|
|
80
|
+
* @return {ContractLogger} The logger instance
|
|
81
|
+
*/
|
|
82
|
+
logFor(ctx) {
|
|
83
|
+
return Logging.for(FabricContractRepository, {}, ctx);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* @description Creates a single model in the state database
|
|
87
|
+
* @summary Prepares, creates, and reverts a model using the adapter
|
|
88
|
+
* @param {M} model - The model to create
|
|
89
|
+
* @param {...any[]} args - Additional arguments, including the chaincode context
|
|
90
|
+
* @return {Promise<M>} Promise resolving to the created model
|
|
91
|
+
*/
|
|
92
|
+
async create(model, ...args) {
|
|
93
|
+
const ctx = args[args.length - 1];
|
|
94
|
+
const log = this.logFor(ctx).for(this.create);
|
|
95
|
+
log.info(`Preparing model: ${JSON.stringify(model)}`);
|
|
96
|
+
// eslint-disable-next-line prefer-const
|
|
97
|
+
let { record, id, transient } = this.adapter.prepare(model, this.pk, this.tableName, ...args);
|
|
98
|
+
log.info(`Creating model: ${JSON.stringify(model)}`);
|
|
99
|
+
record = await this.adapter.create(this.tableName, id, record, ...args);
|
|
100
|
+
let c = undefined;
|
|
101
|
+
if (args.length)
|
|
102
|
+
c = args[args.length - 1];
|
|
103
|
+
log.info(`Reverting model: ${JSON.stringify(model)}`);
|
|
104
|
+
return this.adapter.revert(record, this.class, this.pk, id, c && c.get("rebuildWithTransient") ? transient : undefined);
|
|
105
|
+
}
|
|
106
|
+
async read(id, ...args) {
|
|
107
|
+
const m = await this.adapter.read(this.tableName, id, new this.class(), ...args);
|
|
108
|
+
return this.adapter.revert(m, this.class, this.pk, id);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* @description Deletes a model from the database by ID.
|
|
112
|
+
* @summary Removes a model instance from the database using its primary key.
|
|
113
|
+
* @param {string|number|bigint} id - The primary key of the model to delete.
|
|
114
|
+
* @param {...any[]} args - Additional arguments.
|
|
115
|
+
* @return {Promise<M>} The deleted model instance.
|
|
116
|
+
*/
|
|
117
|
+
async delete(id, ...args) {
|
|
118
|
+
const m = await this.adapter.delete(this.tableName, id, new this.class(), ...args);
|
|
119
|
+
return this.adapter.revert(m, this.class, this.pk, id);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* @description Updates a single model in the state database
|
|
123
|
+
* @summary Prepares, updates, and reverts a model using the adapter
|
|
124
|
+
* @param {M} model - The model to update
|
|
125
|
+
* @param {...any[]} args - Additional arguments, including the chaincode context
|
|
126
|
+
* @return {Promise<M>} Promise resolving to the updated model
|
|
127
|
+
*/
|
|
128
|
+
async update(model, ...args) {
|
|
129
|
+
const ctx = args[args.length - 1];
|
|
130
|
+
const log = this.logFor(ctx).for(this.update);
|
|
131
|
+
log.info(`Preparing model: ${JSON.stringify(model)}`);
|
|
132
|
+
// eslint-disable-next-line prefer-const
|
|
133
|
+
let { record, id, transient } = this.adapter.prepare(model, this.pk, this.tableName, ...args);
|
|
134
|
+
log.info(`Updating model: ${JSON.stringify(model)}`);
|
|
135
|
+
record = await this.adapter.update(this.tableName, id, record, ...args);
|
|
136
|
+
let c = undefined;
|
|
137
|
+
if (args.length)
|
|
138
|
+
c = args[args.length - 1];
|
|
139
|
+
log.info(`Reverting model: ${JSON.stringify(model)}`);
|
|
140
|
+
return this.adapter.revert(record, this.class, this.pk, id, c && c.get("rebuildWithTransient") ? transient : undefined);
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* @description Gets the observer handler for this repository
|
|
144
|
+
* @summary Returns a FabricContractRepositoryObservableHandler instance
|
|
145
|
+
* @return {ObserverHandler} The observer handler
|
|
146
|
+
*/
|
|
147
|
+
ObserverHandler() {
|
|
148
|
+
return new FabricContractRepositoryObservableHandler();
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* @description Creates multiple models in the state database
|
|
152
|
+
* @summary Prepares, creates, and reverts multiple models using the adapter
|
|
153
|
+
* @param {M[]} models - The models to create
|
|
154
|
+
* @param {...any[]} args - Additional arguments, including the chaincode context
|
|
155
|
+
* @return {Promise<M[]>} Promise resolving to the created models
|
|
156
|
+
*/
|
|
157
|
+
async createAll(models, ...args) {
|
|
158
|
+
if (!models.length)
|
|
159
|
+
return models;
|
|
160
|
+
const prepared = models.map((m) => this.adapter.prepare(m, this.pk, this.tableName, ...args));
|
|
161
|
+
const ids = prepared.map((p) => p.id);
|
|
162
|
+
let records = prepared.map((p) => p.record);
|
|
163
|
+
const transients = prepared.map((p) => p.transient).filter((e) => !!e);
|
|
164
|
+
let c = undefined;
|
|
165
|
+
if (args.length)
|
|
166
|
+
c = args[args.length - 1];
|
|
167
|
+
records = await this.adapter.createAll(this.tableName, ids, records, ...args);
|
|
168
|
+
return records.map((r, i) => this.adapter.revert(r, this.class, this.pk, ids[i], c && c.get("rebuildWithTransient") ? transients : undefined));
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* @description Updates multiple models in the state database
|
|
172
|
+
* @summary Prepares, updates, and reverts multiple models using the adapter
|
|
173
|
+
* @param {M[]} models - The models to update
|
|
174
|
+
* @param {...any[]} args - Additional arguments, including the chaincode context
|
|
175
|
+
* @return {Promise<M[]>} Promise resolving to the updated models
|
|
176
|
+
*/
|
|
177
|
+
async updateAll(models, ...args) {
|
|
178
|
+
if (!models.length)
|
|
179
|
+
return models;
|
|
180
|
+
const records = models.map((m) => this.adapter.prepare(m, this.pk, this.tableName, ...args));
|
|
181
|
+
const transients = records.map((p) => p.transient).filter((e) => !!e);
|
|
182
|
+
let c = undefined;
|
|
183
|
+
if (args.length)
|
|
184
|
+
c = args[args.length - 1];
|
|
185
|
+
const updated = await this.adapter.updateAll(this.tableName, records.map((r) => r.id), records.map((r) => r.record), ...args);
|
|
186
|
+
return updated.map((u, i) => this.adapter.revert(u, this.class, this.pk, records[i].id, c && c.get("rebuildWithTransient") ? transients : undefined));
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* @description Executes a raw query against the state database
|
|
190
|
+
* @summary Delegates to the adapter's raw method
|
|
191
|
+
* @param {MangoQuery} rawInput - The Mango Query to execute
|
|
192
|
+
* @param {boolean} docsOnly - Whether to return only documents
|
|
193
|
+
* @param {...any[]} args - Additional arguments, including the chaincode context
|
|
194
|
+
* @return {Promise<any>} Promise resolving to the query results
|
|
195
|
+
*/
|
|
196
|
+
async raw(rawInput, docsOnly, ...args) {
|
|
197
|
+
const ctx = args.pop();
|
|
198
|
+
const transformedArgs = await CTX.args("QUERY", this.class, [ctx], this["adapter"], {});
|
|
199
|
+
return this.adapter.raw(rawInput, docsOnly, new this.class(), ...transformedArgs.args);
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* @description Updates observers based on tracked events
|
|
203
|
+
* @summary Filters events based on trackedEvents and delegates to the parent method
|
|
204
|
+
* @param {string} table - The table/collection name
|
|
205
|
+
* @param {OperationKeys | BulkCrudOperationKeys | string} event - The event type
|
|
206
|
+
* @param {EventIds} id - The event identifier
|
|
207
|
+
* @param {FabricContractContext} ctx - The Fabric contract context
|
|
208
|
+
* @param {...any[]} args - Additional arguments
|
|
209
|
+
* @return {Promise<void>} Promise that resolves when observers are updated
|
|
210
|
+
*/
|
|
211
|
+
async updateObservers(table, event, id, ctx, ...args) {
|
|
212
|
+
if (!this.trackedEvents || this.trackedEvents.indexOf(event) !== -1)
|
|
213
|
+
return await super.updateObservers(table, event, id, ctx, ...args);
|
|
214
|
+
}
|
|
215
|
+
async selectWithContext(selector, ctx) {
|
|
216
|
+
let contextArgs;
|
|
217
|
+
if (ctx instanceof FabricContractContext) {
|
|
218
|
+
contextArgs.context = ctx;
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
contextArgs = await Ctx.args(OperationKeys.CREATE, this.class, [ctx], this.adapter, this._overrides || {});
|
|
222
|
+
}
|
|
223
|
+
if (!selector) {
|
|
224
|
+
return this.adapter
|
|
225
|
+
.Statement(contextArgs.context)
|
|
226
|
+
.select()
|
|
227
|
+
.from(this.class);
|
|
228
|
+
}
|
|
229
|
+
return this.adapter
|
|
230
|
+
.Statement(contextArgs.context)
|
|
231
|
+
.select(selector)
|
|
232
|
+
.from(this.class);
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* @description Prepares multiple models for creation.
|
|
236
|
+
* @summary Validates multiple models and prepares them for creation in the database.
|
|
237
|
+
* @param {M[]} models - The models to create.
|
|
238
|
+
* @param {...any[]} args - Additional arguments.
|
|
239
|
+
* @return The prepared models and context arguments.
|
|
240
|
+
* @throws {ValidationError} If any model fails validation.
|
|
241
|
+
*/
|
|
242
|
+
async createAllPrefix(models, ...args) {
|
|
243
|
+
const ctx = args[args.length - 1];
|
|
244
|
+
const contextArgs = await Ctx.args(OperationKeys.CREATE, this.class, args, this.adapter, this._overrides || {});
|
|
245
|
+
if (!models.length)
|
|
246
|
+
return [models, ...contextArgs.args];
|
|
247
|
+
const opts = Repository.getSequenceOptions(models[0]);
|
|
248
|
+
let ids = [];
|
|
249
|
+
if (opts.type) {
|
|
250
|
+
if (!opts.name)
|
|
251
|
+
opts.name = FabricContractSequence.pk(models[0]);
|
|
252
|
+
ids = await (await this.adapter.Sequence(opts)).range(models.length, ctx);
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
ids = models.map((m, i) => {
|
|
256
|
+
if (typeof m[this.pk] === "undefined")
|
|
257
|
+
throw new InternalError(`Primary key is not defined for model in position ${i}`);
|
|
258
|
+
return m[this.pk];
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
models = await Promise.all(models.map(async (m, i) => {
|
|
262
|
+
m = new this.class(m);
|
|
263
|
+
if (opts.type)
|
|
264
|
+
m[this.pk] = ids[i];
|
|
265
|
+
await enforceDBDecorators(this, contextArgs.context, m, OperationKeys.CREATE, OperationKeys.ON);
|
|
266
|
+
return m;
|
|
267
|
+
}));
|
|
268
|
+
const ignoredProps = contextArgs.context.get("ignoredValidationProperties") || [];
|
|
269
|
+
const errors = await Promise.all(models.map((m) => Promise.resolve(m.hasErrors(...ignoredProps))));
|
|
270
|
+
const errorMessages = errors.reduce((accum, e, i) => {
|
|
271
|
+
if (e)
|
|
272
|
+
accum =
|
|
273
|
+
typeof accum === "string"
|
|
274
|
+
? accum + `\n - ${i}: ${e.toString()}`
|
|
275
|
+
: ` - ${i}: ${e.toString()}`;
|
|
276
|
+
return accum;
|
|
277
|
+
}, undefined);
|
|
278
|
+
if (errorMessages)
|
|
279
|
+
throw new ValidationError(errorMessages);
|
|
280
|
+
return [models, ...contextArgs.args];
|
|
281
|
+
}
|
|
282
|
+
async createPrefix(model, ...args) {
|
|
283
|
+
const result = await super.createPrefix(model, ...args);
|
|
284
|
+
const id = result[0][this.pk];
|
|
285
|
+
try {
|
|
286
|
+
const res = await this.read(String(id), ...args);
|
|
287
|
+
if (res) {
|
|
288
|
+
throw new ConflictError(`Conflict detected while creating model with id: ${id} already exists`);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
catch (e) {
|
|
292
|
+
if (e.code === 404) {
|
|
293
|
+
this.logFor(args[args.length - 1]).info(`Record entry with pk ${id} does not exist, creating it now...`);
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
throw e;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
return result;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRmFicmljQ29udHJhY3RSZXBvc2l0b3J5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NvbnRyYWN0cy9GYWJyaWNDb250cmFjdFJlcG9zaXRvcnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUdMLFVBQVUsR0FFWCxNQUFNLGdCQUFnQixDQUFDO0FBR3hCLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSw2QkFBMEI7QUFFMUQsT0FBTyxFQUVMLGFBQWEsRUFDYixPQUFPLElBQUksR0FBRyxFQUNkLE9BQU8sSUFBSSxHQUFHLEVBQ2QsbUJBQW1CLEVBQ25CLGFBQWEsRUFDYixhQUFhLEVBQ2IsZUFBZSxHQUNoQixNQUFNLHlCQUF5QixDQUFDO0FBRWpDLE9BQU8sRUFBRSx5Q0FBeUMsRUFBRSx1REFBb0Q7QUFFeEcsT0FBTyxFQUFFLHNCQUFzQixFQUFFLG9DQUFpQztBQUVsRSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFFNUM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQStERztBQUNILE1BQU0sT0FBTyx3QkFBMEMsU0FBUSxVQU05RDtJQUNDLFlBQ0UsT0FBK0IsRUFDL0IsS0FBc0IsRUFDWixhQUFrRTtRQUU1RSxLQUFLLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBRlosa0JBQWEsR0FBYixhQUFhLENBQXFEO0lBRzlFLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNJLE1BQU0sQ0FBQyxHQUFZO1FBQ3hCLE9BQU8sT0FBTyxDQUFDLEdBQUcsQ0FBQyx3QkFBd0IsRUFBRSxFQUFFLEVBQUUsR0FBRyxDQUFtQixDQUFDO0lBQzFFLENBQUM7SUFFRDs7Ozs7O09BTUc7SUFDTSxLQUFLLENBQUMsTUFBTSxDQUFDLEtBQVEsRUFBRSxHQUFHLElBQVc7UUFDNUMsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFD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Q2hCLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEV2ZW50SWRzLFxuICBPYnNlcnZlckhhbmRsZXIsXG4gIFJlcG9zaXRvcnksXG4gIFdoZXJlT3B0aW9uLFxufSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbmltcG9ydCB7IEZhYnJpY0NvbnRyYWN0QWRhcHRlciB9IGZyb20gXCIuL0NvbnRyYWN0QWRhcHRlclwiO1xuaW1wb3J0IHsgRmFicmljQ29udHJhY3RGbGFncyB9IGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyBGYWJyaWNDb250cmFjdENvbnRleHQgfSBmcm9tIFwiLi9Db250cmFjdENvbnRleHRcIjtcbmltcG9ydCB7IENvbnN0cnVjdG9yLCBNb2RlbCB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7XG4gIEJ1bGtDcnVkT3BlcmF0aW9uS2V5cyxcbiAgQ29uZmxpY3RFcnJvcixcbiAgQ29udGV4dCBhcyBDdHgsXG4gIENvbnRleHQgYXMgQ1RYLFxuICBlbmZvcmNlREJEZWNvcmF0b3JzLFxuICBJbnRlcm5hbEVycm9yLFxuICBPcGVyYXRpb25LZXlzLFxuICBWYWxpZGF0aW9uRXJyb3IsXG59IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHsgTWFuZ29RdWVyeSB9IGZyb20gXCJAZGVjYWYtdHMvZm9yLWNvdWNoZGJcIjtcbmltcG9ydCB7IEZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeU9ic2VydmFibGVIYW5kbGVyIH0gZnJvbSBcIi4vRmFicmljQ29udHJhY3RSZXBvc2l0b3J5T2JzZXJ2YWJsZUhhbmRsZXJcIjtcbmltcG9ydCB7IENvbnRleHQgfSBmcm9tIFwiZmFicmljLWNvbnRyYWN0LWFwaVwiO1xuaW1wb3J0IHsgRmFicmljQ29udHJhY3RTZXF1ZW5jZSB9IGZyb20gXCIuL0ZhYnJpY0NvbnRyYWN0U2VxdWVuY2VcIjtcbmltcG9ydCB7IENvbnRyYWN0TG9nZ2VyIH0gZnJvbSBcIi4vbG9nZ2luZ1wiO1xuaW1wb3J0IHsgTG9nZ2luZyB9IGZyb20gXCJAZGVjYWYtdHMvbG9nZ2luZ1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBSZXBvc2l0b3J5IGZvciBIeXBlcmxlZGdlciBGYWJyaWMgY2hhaW5jb2RlIG1vZGVsc1xuICogQHN1bW1hcnkgUHJvdmlkZXMgQ1JVRCBvcGVyYXRpb25zIGZvciBtb2RlbHMgd2l0aGluIEZhYnJpYyBjaGFpbmNvZGUgY29udHJhY3RzXG4gKiBAdGVtcGxhdGUgTSAtIFR5cGUgZXh0ZW5kaW5nIE1vZGVsXG4gKiBAdGVtcGxhdGUgTWFuZ29RdWVyeSAtIFF1ZXJ5IHR5cGUgZm9yIENvdWNoREItbGlrZSBxdWVyaWVzXG4gKiBAdGVtcGxhdGUgRmFicmljQ29udHJhY3RBZGFwdGVyIC0gQWRhcHRlciB0eXBlIGZvciBGYWJyaWMgY29udHJhY3Qgb3BlcmF0aW9uc1xuICogQHRlbXBsYXRlIEZhYnJpY0NvbnRyYWN0RmxhZ3MgLSBGbGFncyBzcGVjaWZpYyB0byBGYWJyaWMgY29udHJhY3Qgb3BlcmF0aW9uc1xuICogQHRlbXBsYXRlIEZhYnJpY0NvbnRyYWN0Q29udGV4dCAtIENvbnRleHQgdHlwZSBmb3IgRmFicmljIGNvbnRyYWN0IG9wZXJhdGlvbnNcbiAqXG4gKiBAcGFyYW0ge0ZhYnJpY0NvbnRyYWN0QWRhcHRlcn0gW2FkYXB0ZXJdIC0gVGhlIGFkYXB0ZXIgZm9yIGludGVyYWN0aW5nIHdpdGggdGhlIHN0YXRlIGRhdGFiYXNlXG4gKiBAcGFyYW0ge0NvbnN0cnVjdG9yPE0+fSBbY2xhenpdIC0gVGhlIG1vZGVsIGNvbnN0cnVjdG9yXG4gKiBAcGFyYW0ge0FycmF5PE9wZXJhdGlvbktleXMgfCBCdWxrQ3J1ZE9wZXJhdGlvbktleXMgfCBzdHJpbmc+fSBbdHJhY2tlZEV2ZW50c10gLSBFdmVudHMgdG8gdHJhY2sgZm9yIG9ic2VydmVyIG5vdGlmaWNhdGlvbnNcbiAqXG4gKiBAY2xhc3MgRmFicmljQ29udHJhY3RSZXBvc2l0b3J5XG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogLy8gSW4gYSBGYWJyaWMgY2hhaW5jb2RlIGNvbnRyYWN0IGNsYXNzXG4gKiBpbXBvcnQgeyBGYWJyaWNDb250cmFjdFJlcG9zaXRvcnksIEZhYnJpY0NvbnRyYWN0QWRhcHRlciB9IGZyb20gJ0BkZWNhZi10cy9mb3ItZmFicmljJztcbiAqXG4gKiBAdGFibGUoJ2Fzc2V0cycpXG4gKiBjbGFzcyBBc3NldCBleHRlbmRzIE1vZGVsIHtcbiAqICAgQGlkKClcbiAqICAgaWQ6IHN0cmluZztcbiAqXG4gKiAgIEBwcm9wZXJ0eSgpXG4gKiAgIGRhdGE6IHN0cmluZztcbiAqIH1cbiAqXG4gKiBleHBvcnQgY2xhc3MgTXlDb250cmFjdCBleHRlbmRzIENvbnRyYWN0IHtcbiAqICAgcHJpdmF0ZSBhZGFwdGVyID0gbmV3IEZhYnJpY0NvbnRyYWN0QWRhcHRlcigpO1xuICogICBwcml2YXRlIHJlcG9zaXRvcnk6IEZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeTxBc3NldD47XG4gKlxuICogICBjb25zdHJ1Y3RvcigpIHtcbiAqICAgICBzdXBlcignTXlDb250cmFjdCcpO1xuICogICAgIHRoaXMucmVwb3NpdG9yeSA9IG5ldyBGYWJyaWNDb250cmFjdFJlcG9zaXRvcnk8QXNzZXQ+KHRoaXMuYWRhcHRlciwgQXNzZXQpO1xuICogICB9XG4gKlxuICogICBAVHJhbnNhY3Rpb24oKVxuICogICBhc3luYyBjcmVhdGVBc3NldChjdHg6IENvbnRleHQsIGlkOiBzdHJpbmcsIGRhdGE6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICogICAgIGNvbnN0IGFzc2V0ID0gbmV3IEFzc2V0KCk7XG4gKiAgICAgYXNzZXQuaWQgPSBpZDtcbiAqICAgICBhc3NldC5kYXRhID0gZGF0YTtcbiAqXG4gKiAgICAgYXdhaXQgdGhpcy5yZXBvc2l0b3J5LmNyZWF0ZShhc3NldCwgeyBzdHViOiBjdHguc3R1YiB9KTtcbiAqICAgfVxuICogfVxuICogYGBgXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENvbnRyYWN0XG4gKiAgIHBhcnRpY2lwYW50IFJlcG9zaXRvcnlcbiAqICAgcGFydGljaXBhbnQgQWRhcHRlclxuICogICBwYXJ0aWNpcGFudCBTdGF0ZURCXG4gKlxuICogICBDb250cmFjdC0+PlJlcG9zaXRvcnk6IGNyZWF0ZShtb2RlbCwgY3R4KVxuICogICBSZXBvc2l0b3J5LT4+QWRhcHRlcjogcHJlcGFyZShtb2RlbCwgcGspXG4gKiAgIFJlcG9zaXRvcnktPj5BZGFwdGVyOiBjcmVhdGUodGFibGVOYW1lLCBpZCwgcmVjb3JkLCB0cmFuc2llbnQsIGN0eClcbiAqICAgQWRhcHRlci0+PlN0YXRlREI6IHB1dFN0YXRlKGlkLCBzZXJpYWxpemVkRGF0YSlcbiAqICAgU3RhdGVEQi0tPj5BZGFwdGVyOiBTdWNjZXNzXG4gKiAgIEFkYXB0ZXItLT4+UmVwb3NpdG9yeTogcmVjb3JkXG4gKiAgIFJlcG9zaXRvcnktPj5BZGFwdGVyOiByZXZlcnQocmVjb3JkLCBjbGFzcywgcGssIGlkLCB0cmFuc2llbnQpXG4gKiAgIEFkYXB0ZXItLT4+UmVwb3NpdG9yeTogbW9kZWxcbiAqICAgUmVwb3NpdG9yeS0tPj5Db250cmFjdDogbW9kZWxcbiAqL1xuZXhwb3J0IGNsYXNzIEZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeTxNIGV4dGVuZHMgTW9kZWw+IGV4dGVuZHMgUmVwb3NpdG9yeTxcbiAgTSxcbiAgTWFuZ29RdWVyeSxcbiAgRmFicmljQ29udHJhY3RBZGFwdGVyLFxuICBGYWJyaWNDb250cmFjdEZsYWdzLFxuICBGYWJyaWNDb250cmFjdENvbnRleHRcbj4ge1xuICBjb25zdHJ1Y3RvcihcbiAgICBhZGFwdGVyPzogRmFicmljQ29udHJhY3RBZGFwdGVyLFxuICAgIGNsYXp6PzogQ29uc3RydWN0b3I8TT4sXG4gICAgcHJvdGVjdGVkIHRyYWNrZWRFdmVudHM/OiAoT3BlcmF0aW9uS2V5cyB8IEJ1bGtDcnVkT3BlcmF0aW9uS2V5cyB8IHN0cmluZylbXVxuICApIHtcbiAgICBzdXBlcihhZGFwdGVyLCBjbGF6eik7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYSBsb2dnZXIgZm9yIGEgc3BlY2lmaWMgY2hhaW5jb2RlIGNvbnRleHRcbiAgICogQHN1bW1hcnkgUmV0dXJucyBhIENvbnRyYWN0TG9nZ2VyIGluc3RhbmNlIGNvbmZpZ3VyZWQgZm9yIHRoZSBjdXJyZW50IGNvbnRleHRcbiAgICogQHBhcmFtIHtDdHh9IGN0eCAtIFRoZSBGYWJyaWMgY2hhaW5jb2RlIGNvbnRleHRcbiAgICogQHJldHVybiB7Q29udHJhY3RMb2dnZXJ9IFRoZSBsb2dnZXIgaW5zdGFuY2VcbiAgICovXG4gIHB1YmxpYyBsb2dGb3IoY3R4OiBDb250ZXh0KTogQ29udHJhY3RMb2dnZXIge1xuICAgIHJldHVybiBMb2dnaW5nLmZvcihGYWJyaWNDb250cmFjdFJlcG9zaXRvcnksIHt9LCBjdHgpIGFzIENvbnRyYWN0TG9nZ2VyO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgc2luZ2xlIG1vZGVsIGluIHRoZSBzdGF0ZSBkYXRhYmFzZVxuICAgKiBAc3VtbWFyeSBQcmVwYXJlcywgY3JlYXRlcywgYW5kIHJldmVydHMgYSBtb2RlbCB1c2luZyB0aGUgYWRhcHRlclxuICAgKiBAcGFyYW0ge019IG1vZGVsIC0gVGhlIG1vZGVsIHRvIGNyZWF0ZVxuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMsIGluY2x1ZGluZyB0aGUgY2hhaW5jb2RlIGNvbnRleHRcbiAgICogQHJldHVybiB7UHJvbWlzZTxNPn0gUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIGNyZWF0ZWQgbW9kZWxcbiAgICovXG4gIG92ZXJyaWRlIGFzeW5jIGNyZWF0ZShtb2RlbDogTSwgLi4uYXJnczogYW55W10pOiBQcm9taXNlPE0+IHtcbiAgICBjb25zdCBjdHggPSBhcmdzW2FyZ3MubGVuZ3RoIC0gMV0gYXMgQ29udGV4dDtcbiAgICBjb25zdCBsb2cgPSB0aGlzLmxvZ0ZvcihjdHgpLmZvcih0aGlzLmNyZWF0ZSk7XG4gICAgbG9nLmluZm8oYFByZXBhcmluZyBtb2RlbDogJHtKU09OLnN0cmluZ2lmeShtb2RlbCl9YCk7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIHByZWZlci1jb25zdFxuICAgIGxldCB7IHJlY29yZCwgaWQsIHRyYW5zaWVudCB9ID0gdGhpcy5hZGFwdGVyLnByZXBhcmUoXG4gICAgICBtb2RlbCxcbiAgICAgIHRoaXMucGssXG4gICAgICB0aGlzLnRhYmxlTmFtZSxcbiAgICAgIC4uLmFyZ3NcbiAgICApO1xuICAgIGxvZy5pbmZvKGBDcmVhdGluZyBtb2RlbDogJHtKU09OLnN0cmluZ2lmeShtb2RlbCl9YCk7XG4gICAgcmVjb3JkID0gYXdhaXQgdGhpcy5hZGFwdGVyLmNyZWF0ZSh0aGlzLnRhYmxlTmFtZSwgaWQsIHJlY29yZCwgLi4uYXJncyk7XG4gICAgbGV0IGM6IEZhYnJpY0NvbnRyYWN0Q29udGV4dCB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZDtcbiAgICBpZiAoYXJncy5sZW5ndGgpIGMgPSBhcmdzW2FyZ3MubGVuZ3RoIC0gMV0gYXMgRmFicmljQ29udHJhY3RDb250ZXh0O1xuICAgIGxvZy5pbmZvKGBSZXZlcnRpbmcgbW9kZWw6ICR7SlNPTi5zdHJpbmdpZnkobW9kZWwpfWApO1xuICAgIHJldHVybiB0aGlzLmFkYXB0ZXIucmV2ZXJ0PE0+KFxuICAgICAgcmVjb3JkLFxuICAgICAgdGhpcy5jbGFzcyxcbiAgICAgIHRoaXMucGssXG4gICAgICBpZCxcbiAgICAgIGMgJiYgYy5nZXQoXCJyZWJ1aWxkV2l0aFRyYW5zaWVudFwiKSA/IHRyYW5zaWVudCA6IHVuZGVmaW5lZFxuICAgICk7XG4gIH1cblxuICBvdmVycmlkZSBhc3luYyByZWFkKFxuICAgIGlkOiBzdHJpbmcgfCBudW1iZXIgfCBiaWdpbnQsXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxNPiB7XG4gICAgY29uc3QgbSA9IGF3YWl0IHRoaXMuYWRhcHRlci5yZWFkKFxuICAgICAgdGhpcy50YWJsZU5hbWUsXG4gICAgICBpZCBhcyBzdHJpbmcsXG4gICAgICBuZXcgdGhpcy5jbGFzcygpLFxuICAgICAgLi4uYXJnc1xuICAgICk7XG4gICAgcmV0dXJuIHRoaXMuYWRhcHRlci5yZXZlcnQ8TT4obSwgdGhpcy5jbGFzcywgdGhpcy5waywgaWQgYXMgc3RyaW5nKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRGVsZXRlcyBhIG1vZGVsIGZyb20gdGhlIGRhdGFiYXNlIGJ5IElELlxuICAgKiBAc3VtbWFyeSBSZW1vdmVzIGEgbW9kZWwgaW5zdGFuY2UgZnJvbSB0aGUgZGF0YWJhc2UgdXNpbmcgaXRzIHByaW1hcnkga2V5LlxuICAgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ8YmlnaW50fSBpZCAtIFRoZSBwcmltYXJ5IGtleSBvZiB0aGUgbW9kZWwgdG8gZGVsZXRlLlxuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMuXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TT59IFRoZSBkZWxldGVkIG1vZGVsIGluc3RhbmNlLlxuICAgKi9cbiAgb3ZlcnJpZGUgYXN5bmMgZGVsZXRlKGlkOiBzdHJpbmcsIC4uLmFyZ3M6IGFueVtdKSB7XG4gICAgY29uc3QgbSA9IGF3YWl0IHRoaXMuYWRhcHRlci5kZWxldGUoXG4gICAgICB0aGlzLnRhYmxlTmFtZSxcbiAgICAgIGlkLFxuICAgICAgbmV3IHRoaXMuY2xhc3MoKSxcbiAgICAgIC4uLmFyZ3NcbiAgICApO1xuICAgIHJldHVybiB0aGlzLmFkYXB0ZXIucmV2ZXJ0KG0sIHRoaXMuY2xhc3MsIHRoaXMucGssIGlkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVXBkYXRlcyBhIHNpbmdsZSBtb2RlbCBpbiB0aGUgc3RhdGUgZGF0YWJhc2VcbiAgICogQHN1bW1hcnkgUHJlcGFyZXMsIHVwZGF0ZXMsIGFuZCByZXZlcnRzIGEgbW9kZWwgdXNpbmcgdGhlIGFkYXB0ZXJcbiAgICogQHBhcmFtIHtNfSBtb2RlbCAtIFRoZSBtb2RlbCB0byB1cGRhdGVcbiAgICogQHBhcmFtIHsuLi5hbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzLCBpbmNsdWRpbmcgdGhlIGNoYWluY29kZSBjb250ZXh0XG4gICAqIEByZXR1cm4ge1Byb21pc2U8TT59IFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSB1cGRhdGVkIG1vZGVsXG4gICAqL1xuICBvdmVycmlkZSBhc3luYyB1cGRhdGUobW9kZWw6IE0sIC4uLmFyZ3M6IGFueVtdKTogUHJvbWlzZTxNPiB7XG4gICAgY29uc3QgY3R4ID0gYXJnc1thcmdzLmxlbmd0aCAtIDFdIGFzIENvbnRleHQ7XG4gICAgY29uc3QgbG9nID0gdGhpcy5sb2dGb3IoY3R4KS5mb3IodGhpcy51cGRhdGUpO1xuICAgIGxvZy5pbmZvKGBQcmVwYXJpbmcgbW9kZWw6ICR7SlNPTi5zdHJpbmdpZnkobW9kZWwpfWApO1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBwcmVmZXItY29uc3RcbiAgICBsZXQgeyByZWNvcmQsIGlkLCB0cmFuc2llbnQgfSA9IHRoaXMuYWRhcHRlci5wcmVwYXJlKFxuICAgICAgbW9kZWwsXG4gICAgICB0aGlzLnBrLFxuICAgICAgdGhpcy50YWJsZU5hbWUsXG4gICAgICAuLi5hcmdzXG4gICAgKTtcbiAgICBsb2cuaW5mbyhgVXBkYXRpbmcgbW9kZWw6ICR7SlNPTi5zdHJpbmdpZnkobW9kZWwpfWApO1xuICAgIHJlY29yZCA9IGF3YWl0IHRoaXMuYWRhcHRlci51cGRhdGUodGhpcy50YWJsZU5hbWUsIGlkLCByZWNvcmQsIC4uLmFyZ3MpO1xuICAgIGxldCBjOiBGYWJyaWNDb250cmFjdENvbnRleHQgfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG4gICAgaWYgKGFyZ3MubGVuZ3RoKSBjID0gYXJnc1thcmdzLmxlbmd0aCAtIDFdIGFzIEZhYnJpY0NvbnRyYWN0Q29udGV4dDtcbiAgICBsb2cuaW5mbyhgUmV2ZXJ0aW5nIG1vZGVsOiAke0pTT04uc3RyaW5naWZ5KG1vZGVsKX1gKTtcbiAgICByZXR1cm4gdGhpcy5hZGFwdGVyLnJldmVydDxNPihcbiAgICAgIHJlY29yZCxcbiAgICAgIHRoaXMuY2xhc3MsXG4gICAgICB0aGlzLnBrLFxuICAgICAgaWQsXG4gICAgICBjICYmIGMuZ2V0KFwicmVidWlsZFdpdGhUcmFuc2llbnRcIikgPyB0cmFuc2llbnQgOiB1bmRlZmluZWRcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBHZXRzIHRoZSBvYnNlcnZlciBoYW5kbGVyIGZvciB0aGlzIHJlcG9zaXRvcnlcbiAgICogQHN1bW1hcnkgUmV0dXJucyBhIEZhYnJpY0NvbnRyYWN0UmVwb3NpdG9yeU9ic2VydmFibGVIYW5kbGVyIGluc3RhbmNlXG4gICAqIEByZXR1cm4ge09ic2VydmVySGFuZGxlcn0gVGhlIG9ic2VydmVyIGhhbmRsZXJcbiAgICovXG4gIG92ZXJyaWRlIE9ic2VydmVySGFuZGxlcigpOiBPYnNlcnZlckhhbmRsZXIge1xuICAgIHJldHVybiBuZXcgRmFicmljQ29udHJhY3RSZXBvc2l0b3J5T2JzZXJ2YWJsZUhhbmRsZXIoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBtdWx0aXBsZSBtb2RlbHMgaW4gdGhlIHN0YXRlIGRhdGFiYXNlXG4gICAqIEBzdW1tYXJ5IFByZXBhcmVzLCBjcmVhdGVzLCBhbmQgcmV2ZXJ0cyBtdWx0aXBsZSBtb2RlbHMgdXNpbmcgdGhlIGFkYXB0ZXJcbiAgICogQHBhcmFtIHtNW119IG1vZGVscyAtIFRoZSBtb2RlbHMgdG8gY3JlYXRlXG4gICAqIEBwYXJhbSB7Li4uYW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50cywgaW5jbHVkaW5nIHRoZSBjaGFpbmNvZGUgY29udGV4dFxuICAgKiBAcmV0dXJuIHtQcm9taXNlPE1bXT59IFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSBjcmVhdGVkIG1vZGVsc1xuICAgKi9cbiAgb3ZlcnJpZGUgYXN5bmMgY3JlYXRlQWxsKG1vZGVsczogTVtdLCAuLi5hcmdzOiBhbnlbXSk6IFByb21pc2U8TVtdPiB7XG4gICAgaWYgKCFtb2RlbHMubGVuZ3RoKSByZXR1cm4gbW9kZWxzO1xuICAgIGNvbnN0IHByZXBhcmVkID0gbW9kZWxzLm1hcCgobSkgPT5cbiAgICAgIHRoaXMuYWRhcHRlci5wcmVwYXJlKG0sIHRoaXMucGssIHRoaXMudGFibGVOYW1lLCAuLi5hcmdzKVxuICAgICk7XG4gICAgY29uc3QgaWRzID0gcHJlcGFyZWQubWFwKChwKSA9PiBwLmlkKTtcbiAgICBsZXQgcmVjb3JkcyA9IHByZXBhcmVkLm1hcCgocCkgPT4gcC5yZWNvcmQpO1xuICAgIGNvbnN0IHRyYW5zaWVudHMgPSBwcmVwYXJlZC5tYXAoKHApID0+IHAudHJhbnNpZW50KS5maWx0ZXIoKGUpID0+ICEhZSk7XG4gICAgbGV0IGM6IEZhYnJpY0NvbnRyYWN0Q29udGV4dCB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZDtcbiAgICBpZiAoYXJncy5sZW5ndGgpIGMgPSBhcmdzW2FyZ3MubGVuZ3RoIC0gMV0gYXMgRmFicmljQ29udHJhY3RDb250ZXh0O1xuICAgIHJlY29yZHMgPSBhd2FpdCB0aGlzLmFkYXB0ZXIuY3JlYXRlQWxsKFxuICAgICAgdGhpcy50YWJsZU5hbWUsXG4gICAgICBpZHMsXG4gICAgICByZWNvcmRzLFxuICAgICAgLi4uYXJnc1xuICAgICk7XG4gICAgcmV0dXJuIHJlY29yZHMubWFwKChyLCBpKSA9PlxuICAgICAgdGhpcy5hZGFwdGVyLnJldmVydChcbiAgICAgICAgcixcbiAgICAgICAgdGhpcy5jbGFzcyxcbiAgICAgICAgdGhpcy5wayxcbiAgICAgICAgaWRzW2ldIGFzIHN0cmluZyB8IG51bWJlcixcbiAgICAgICAgYyAmJiBjLmdldChcInJlYnVpbGRXaXRoVHJhbnNpZW50XCIpID8gdHJhbnNpZW50cyA6IHVuZGVmaW5lZFxuICAgICAgKVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFVwZGF0ZXMgbXVsdGlwbGUgbW9kZWxzIGluIHRoZSBzdGF0ZSBkYXRhYmFzZVxuICAgKiBAc3VtbWFyeSBQcmVwYXJlcywgdXBkYXRlcywgYW5kIHJldmVydHMgbXVsdGlwbGUgbW9kZWxzIHVzaW5nIHRoZSBhZGFwdGVyXG4gICAqIEBwYXJhbSB7TVtdfSBtb2RlbHMgLSBUaGUgbW9kZWxzIHRvIHVwZGF0ZVxuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMsIGluY2x1ZGluZyB0aGUgY2hhaW5jb2RlIGNvbnRleHRcbiAgICogQHJldHVybiB7UHJvbWlzZTxNW10+fSBQcm9taXNlIHJlc29sdmluZyB0byB0aGUgdXBkYXRlZCBtb2RlbHNcbiAgICovXG4gIG92ZXJyaWRlIGFzeW5jIHVwZGF0ZUFsbChtb2RlbHM6IE1bXSwgLi4uYXJnczogYW55W10pOiBQcm9taXNlPE1bXT4ge1xuICAgIGlmICghbW9kZWxzLmxlbmd0aCkgcmV0dXJuIG1vZGVscztcbiAgICBjb25zdCByZWNvcmRzID0gbW9kZWxzLm1hcCgobSkgPT5cbiAgICAgIHRoaXMuYWRhcHRlci5wcmVwYXJlKG0sIHRoaXMucGssIHRoaXMudGFibGVOYW1lLCAuLi5hcmdzKVxuICAgICk7XG4gICAgY29uc3QgdHJhbnNpZW50cyA9IHJlY29yZHMubWFwKChwKSA9PiBwLnRyYW5zaWVudCkuZmlsdGVyKChlKSA9PiAhIWUpO1xuICAgIGxldCBjOiBGYWJyaWNDb250cmFjdENvbnRleHQgfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG4gICAgaWYgKGFyZ3MubGVuZ3RoKSBjID0gYXJnc1thcmdzLmxlbmd0aCAtIDFdIGFzIEZhYnJpY0NvbnRyYWN0Q29udGV4dDtcblxuICAgIGNvbnN0IHVwZGF0ZWQgPSBhd2FpdCB0aGlzLmFkYXB0ZXIudXBkYXRlQWxsKFxuICAgICAgdGhpcy50YWJsZU5hbWUsXG4gICAgICByZWNvcmRzLm1hcCgocikgPT4gci5pZCksXG4gICAgICByZWNvcmRzLm1hcCgocikgPT4gci5yZWNvcmQpLFxuICAgICAgLi4uYXJnc1xuICAgICk7XG4gICAgcmV0dXJuIHVwZGF0ZWQubWFwKCh1LCBpKSA9PlxuICAgICAgdGhpcy5hZGFwdGVyLnJldmVydChcbiAgICAgICAgdSxcbiAgICAgICAgdGhpcy5jbGFzcyxcbiAgICAgICAgdGhpcy5wayxcbiAgICAgICAgcmVjb3Jkc1tpXS5pZCxcbiAgICAgICAgYyAmJiBjLmdldChcInJlYnVpbGRXaXRoVHJhbnNpZW50XCIpID8gdHJhbnNpZW50cyA6IHVuZGVmaW5lZFxuICAgICAgKVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEV4ZWN1dGVzIGEgcmF3IHF1ZXJ5IGFnYWluc3QgdGhlIHN0YXRlIGRhdGFiYXNlXG4gICAqIEBzdW1tYXJ5IERlbGVnYXRlcyB0byB0aGUgYWRhcHRlcidzIHJhdyBtZXRob2RcbiAgICogQHBhcmFtIHtNYW5nb1F1ZXJ5fSByYXdJbnB1dCAtIFRoZSBNYW5nbyBRdWVyeSB0byBleGVjdXRlXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gZG9jc09ubHkgLSBXaGV0aGVyIHRvIHJldHVybiBvbmx5IGRvY3VtZW50c1xuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMsIGluY2x1ZGluZyB0aGUgY2hhaW5jb2RlIGNvbnRleHRcbiAgICogQHJldHVybiB7UHJvbWlzZTxhbnk+fSBQcm9taXNlIHJlc29sdmluZyB0byB0aGUgcXVlcnkgcmVzdWx0c1xuICAgKi9cbiAgYXN5bmMgcmF3KHJhd0lucHV0OiBNYW5nb1F1ZXJ5LCBkb2NzT25seTogYm9vbGVhbiwgLi4uYXJnczogYW55W10pIHtcbiAgICBjb25zdCBjdHggPSBhcmdzLnBvcCgpO1xuICAgIGNvbnN0IHRyYW5zZm9ybWVkQXJncyA9IGF3YWl0IENUWC5hcmdzKFxuICAgICAgXCJRVUVSWVwiIGFzIE9wZXJhdGlvbktleXMuQ1JFQVRFLFxuICAgICAgdGhpcy5jbGFzcyxcbiAgICAgIFtjdHhdLFxuICAgICAgdGhpc1tcImFkYXB0ZXJcIl0gYXMgYW55LFxuICAgICAge31cbiAgICApO1xuXG4gICAgcmV0dXJuIHRoaXMuYWRhcHRlci5yYXcoXG4gICAgICByYXdJbnB1dCxcbiAgICAgIGRvY3NPbmx5LFxuICAgICAgbmV3IHRoaXMuY2xhc3MoKSxcbiAgICAgIC4uLnRyYW5zZm9ybWVkQXJncy5hcmdzXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVXBkYXRlcyBvYnNlcnZlcnMgYmFzZWQgb24gdHJhY2tlZCBldmVudHNcbiAgICogQHN1bW1hcnkgRmlsdGVycyBldmVudHMgYmFzZWQgb24gdHJhY2tlZEV2ZW50cyBhbmQgZGVsZWdhdGVzIHRvIHRoZSBwYXJlbnQgbWV0aG9kXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0YWJsZSAtIFRoZSB0YWJsZS9jb2xsZWN0aW9uIG5hbWVcbiAgICogQHBhcmFtIHtPcGVyYXRpb25LZXlzIHwgQnVsa0NydWRPcGVyYXRpb25LZXlzIHwgc3RyaW5nfSBldmVudCAtIFRoZSBldmVudCB0eXBlXG4gICAqIEBwYXJhbSB7RXZlbnRJZHN9IGlkIC0gVGhlIGV2ZW50IGlkZW50aWZpZXJcbiAgICogQHBhcmFtIHtGYWJyaWNDb250cmFjdENvbnRleHR9IGN0eCAtIFRoZSBGYWJyaWMgY29udHJhY3QgY29udGV4dFxuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHNcbiAgICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn0gUHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gb2JzZXJ2ZXJzIGFyZSB1cGRhdGVkXG4gICAqL1xuICBvdmVycmlkZSBhc3luYyB1cGRhdGVPYnNlcnZlcnMoXG4gICAgdGFibGU6IHN0cmluZyxcbiAgICBldmVudDogT3BlcmF0aW9uS2V5cyB8IEJ1bGtDcnVkT3BlcmF0aW9uS2V5cyB8IHN0cmluZyxcbiAgICBpZDogRXZlbnRJZHMsXG4gICAgY3R4OiBGYWJyaWNDb250cmFjdENvbnRleHQsXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKCF0aGlzLnRyYWNrZWRFdmVudHMgfHwgdGhpcy50cmFja2VkRXZlbnRzLmluZGV4T2YoZXZlbnQpICE9PSAtMSlcbiAgICAgIHJldHVybiBhd2FpdCBzdXBlci51cGRhdGVPYnNlcnZlcnModGFibGUsIGV2ZW50LCBpZCwgY3R4LCAuLi5hcmdzKTtcbiAgfVxuXG4gIGFzeW5jIHNlbGVjdFdpdGhDb250ZXh0PFMgZXh0ZW5kcyByZWFkb25seSAoa2V5b2YgTSlbXT4oXG4gICAgc2VsZWN0b3I/OiByZWFkb25seSBbLi4uU10sXG4gICAgY3R4PzogRmFicmljQ29udHJhY3RDb250ZXh0IHwgQ29udGV4dFxuICApOiBQcm9taXNlPFdoZXJlT3B0aW9uPE0sIE1bXT4gfCBXaGVyZU9wdGlvbjxNLCBQaWNrPE0sIFNbbnVtYmVyXT5bXT4+IHtcbiAgICBsZXQgY29udGV4dEFyZ3M6IGFueTtcbiAgICBpZiAoY3R4IGluc3RhbmNlb2YgRmFicmljQ29udHJhY3RDb250ZXh0KSB7XG4gICAgICBjb250ZXh0QXJncy5jb250ZXh0ID0gY3R4O1xuICAgIH0gZWxzZSB7XG4gICAgICBjb250ZXh0QXJncyA9IGF3YWl0IEN0eC5hcmdzKFxuICAgICAgICBPcGVyYXRpb25LZXlzLkNSRUFURSxcbiAgICAgICAgdGhpcy5jbGFzcyxcbiAgICAgICAgW2N0eF0sXG4gICAgICAgIHRoaXMuYWRhcHRlcixcbiAgICAgICAgdGhpcy5fb3ZlcnJpZGVzIHx8IHt9XG4gICAgICApO1xuICAgIH1cbiAgICBpZiAoIXNlbGVjdG9yKSB7XG4gICAgICByZXR1cm4gdGhpcy5hZGFwdGVyXG4gICAgICAgIC5TdGF0ZW1lbnQ8TT4oY29udGV4dEFyZ3MuY29udGV4dCBhcyBGYWJyaWNDb250cmFjdENvbnRleHQpXG4gICAgICAgIC5zZWxlY3QoKVxuICAgICAgICAuZnJvbSh0aGlzLmNsYXNzKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuYWRhcHRlclxuICAgICAgLlN0YXRlbWVudDxNPihjb250ZXh0QXJncy5jb250ZXh0IGFzIEZhYnJpY0NvbnRyYWN0Q29udGV4dClcbiAgICAgIC5zZWxlY3Qoc2VsZWN0b3IpXG4gICAgICAuZnJvbSh0aGlzLmNsYXNzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUHJlcGFyZXMgbXVsdGlwbGUgbW9kZWxzIGZvciBjcmVhdGlvbi5cbiAgICogQHN1bW1hcnkgVmFsaWRhdGVzIG11bHRpcGxlIG1vZGVscyBhbmQgcHJlcGFyZXMgdGhlbSBmb3IgY3JlYXRpb24gaW4gdGhlIGRhdGFiYXNlLlxuICAgKiBAcGFyYW0ge01bXX0gbW9kZWxzIC0gVGhlIG1vZGVscyB0byBjcmVhdGUuXG4gICAqIEBwYXJhbSB7Li4uYW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50cy5cbiAgICogQHJldHVybiBUaGUgcHJlcGFyZWQgbW9kZWxzIGFuZCBjb250ZXh0IGFyZ3VtZW50cy5cbiAgICogQHRocm93cyB7VmFsaWRhdGlvbkVycm9yfSBJZiBhbnkgbW9kZWwgZmFpbHMgdmFsaWRhdGlvbi5cbiAgICovXG4gIHByb3RlY3RlZCBvdmVycmlkZSBhc3luYyBjcmVhdGVBbGxQcmVmaXgobW9kZWxzOiBNW10sIC4uLmFyZ3M6IGFueVtdKSB7XG4gICAgY29uc3QgY3R4ID0gYXJnc1thcmdzLmxlbmd0aCAtIDFdIGFzIENvbnRleHQ7XG5cbiAgICBjb25zdCBjb250ZXh0QXJncyA9IGF3YWl0IEN0eC5hcmdzKFxuICAgICAgT3BlcmF0aW9uS2V5cy5DUkVBVEUsXG4gICAgICB0aGlzLmNsYXNzLFxuICAgICAgYXJncyxcbiAgICAgIHRoaXMuYWRhcHRlcixcbiAgICAgIHRoaXMuX292ZXJyaWRlcyB8fCB7fVxuICAgICk7XG4gICAgaWYgKCFtb2RlbHMubGVuZ3RoKSByZXR1cm4gW21vZGVscywgLi4uY29udGV4dEFyZ3MuYXJnc107XG4gICAgY29uc3Qgb3B0cyA9IFJlcG9zaXRvcnkuZ2V0U2VxdWVuY2VPcHRpb25zKG1vZGVsc1swXSk7XG4gICAgbGV0IGlkczogKHN0cmluZyB8IG51bWJlciB8IGJpZ2ludCB8IHVuZGVmaW5lZClbXSA9IFtdO1xuICAgIGlmIChvcHRzLnR5cGUpIHtcbiAgICAgIGlmICghb3B0cy5uYW1lKSBvcHRzLm5hbWUgPSBGYWJyaWNDb250cmFjdFNlcXVlbmNlLnBrKG1vZGVsc1swXSk7XG4gICAgICBpZHMgPSBhd2FpdCAoXG4gICAgICAgIChhd2FpdCB0aGlzLmFkYXB0ZXIuU2VxdWVuY2Uob3B0cykpIGFzIEZhYnJpY0NvbnRyYWN0U2VxdWVuY2VcbiAgICAgICkucmFuZ2UobW9kZWxzLmxlbmd0aCwgY3R4IGFzIHVua25vd24gYXMgRmFicmljQ29udHJhY3RDb250ZXh0KTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWRzID0gbW9kZWxzLm1hcCgobSwgaSkgPT4ge1xuICAgICAgICBpZiAodHlwZW9mIG1bdGhpcy5wa10gPT09IFwidW5kZWZpbmVkXCIpXG4gICAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgICAgICBgUHJpbWFyeSBrZXkgaXMgbm90IGRlZmluZWQgZm9yIG1vZGVsIGluIHBvc2l0aW9uICR7aX1gXG4gICAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIG1bdGhpcy5wa10gYXMgc3RyaW5nO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgbW9kZWxzID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBtb2RlbHMubWFwKGFzeW5jIChtLCBpKSA9PiB7XG4gICAgICAgIG0gPSBuZXcgdGhpcy5jbGFzcyhtKTtcbiAgICAgICAgaWYgKG9wdHMudHlwZSkgbVt0aGlzLnBrXSA9IGlkc1tpXSBhcyBNW2tleW9mIE1dO1xuICAgICAgICBhd2FpdCBlbmZvcmNlREJEZWNvcmF0b3JzKFxuICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgY29udGV4dEFyZ3MuY29udGV4dCxcbiAgICAgICAgICBtLFxuICAgICAgICAgIE9wZXJhdGlvbktleXMuQ1JFQVRFLFxuICAgICAgICAgIE9wZXJhdGlvbktleXMuT05cbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIG07XG4gICAgICB9KVxuICAgICk7XG5cbiAgICBjb25zdCBpZ25vcmVkUHJvcHMgPVxuICAgICAgY29udGV4dEFyZ3MuY29udGV4dC5nZXQoXCJpZ25vcmVkVmFsaWRhdGlvblByb3BlcnRpZXNcIikgfHwgW107XG5cbiAgICBjb25zdCBlcnJvcnMgPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIG1vZGVscy5tYXAoKG0pID0+IFByb21pc2UucmVzb2x2ZShtLmhhc0Vycm9ycyguLi5pZ25vcmVkUHJvcHMpKSlcbiAgICApO1xuXG4gICAgY29uc3QgZXJyb3JNZXNzYWdlcyA9IGVycm9ycy5yZWR1Y2UoKGFjY3VtOiBzdHJpbmcgfCB1bmRlZmluZWQsIGUsIGkpID0+IHtcbiAgICAgIGlmIChlKVxuICAgICAgICBhY2N1bSA9XG4gICAgICAgICAgdHlwZW9mIGFjY3VtID09PSBcInN0cmluZ1wiXG4gICAgICAgICAgICA/IGFjY3VtICsgYFxcbiAtICR7aX06ICR7ZS50b1N0cmluZygpfWBcbiAgICAgICAgICAgIDogYCAtICR7aX06ICR7ZS50b1N0cmluZygpfWA7XG4gICAgICByZXR1cm4gYWNjdW07XG4gICAgfSwgdW5kZWZpbmVkKTtcblxuICAgIGlmIChlcnJvck1lc3NhZ2VzKSB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKGVycm9yTWVzc2FnZXMpO1xuICAgIHJldHVybiBbbW9kZWxzLCAuLi5jb250ZXh0QXJncy5hcmdzXTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvdmVycmlkZSBhc3luYyBjcmVhdGVQcmVmaXgoXG4gICAgbW9kZWw6IE0sXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxbTSwgLi4uYW55W11dPiB7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc3VwZXIuY3JlYXRlUHJlZml4KG1vZGVsLCAuLi5hcmdzKTtcbiAgICBjb25zdCBpZCA9IHJlc3VsdFswXVt0aGlzLnBrXTtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzID0gYXdhaXQgdGhpcy5yZWFkKFN0cmluZyhpZCksIC4uLmFyZ3MpO1xuICAgICAgaWYgKHJlcykge1xuICAgICAgICB0aHJvdyBuZXcgQ29uZmxpY3RFcnJvcihcbiAgICAgICAgICBgQ29uZmxpY3QgZGV0ZWN0ZWQgd2hpbGUgY3JlYXRpbmcgbW9kZWwgd2l0aCBpZDogJHtpZH0gYWxyZWFkeSBleGlzdHNgXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKChlIGFzIGFueSkuY29kZSA9PT0gNDA0KSB7XG4gICAgICAgIHRoaXMubG9nRm9yKGFyZ3NbYXJncy5sZW5ndGggLSAxXSkuaW5mbyhcbiAgICAgICAgICBgUmVjb3JkIGVudHJ5IHdpdGggcGsgJHtpZH0gZG9lcyBub3QgZXhpc3QsIGNyZWF0aW5nIGl0IG5vdy4uLmBcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbn1cbiJdfQ==
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { BulkCrudOperationKeys, OperationKeys } from "@decaf-ts/db-decorators";
|
|
2
|
+
import { EventIds, ObserverHandler } from "@decaf-ts/core";
|
|
3
|
+
import { Logger } from "@decaf-ts/logging";
|
|
4
|
+
import { Context } from "fabric-contract-api";
|
|
5
|
+
/**
|
|
6
|
+
* @description Observer handler for Fabric chaincode events
|
|
7
|
+
* @summary Emits events on the Fabric ledger when repository operations occur
|
|
8
|
+
* @class FabricContractRepositoryObservableHandler
|
|
9
|
+
* @extends {ObserverHandler}
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* // In a Fabric chaincode contract
|
|
13
|
+
* import { FabricContractRepositoryObservableHandler } from '@decaf-ts/for-fabric';
|
|
14
|
+
*
|
|
15
|
+
* // Create a handler with default supported events
|
|
16
|
+
* const handler = new FabricContractRepositoryObservableHandler();
|
|
17
|
+
*
|
|
18
|
+
* // Emit an event
|
|
19
|
+
* await handler.updateObservers(
|
|
20
|
+
* logger,
|
|
21
|
+
* 'assets',
|
|
22
|
+
* OperationKeys.CREATE,
|
|
23
|
+
* 'asset1',
|
|
24
|
+
* context
|
|
25
|
+
* );
|
|
26
|
+
* ```
|
|
27
|
+
* @mermaid
|
|
28
|
+
* sequenceDiagram
|
|
29
|
+
* participant Repository
|
|
30
|
+
* participant ObservableHandler
|
|
31
|
+
* participant Stub
|
|
32
|
+
* participant Ledger
|
|
33
|
+
*
|
|
34
|
+
* Repository->>ObservableHandler: updateObservers(log, table, event, id, ctx)
|
|
35
|
+
* ObservableHandler->>ObservableHandler: Check if event is supported
|
|
36
|
+
* ObservableHandler->>ObservableHandler: generateFabricEventName(table, event, owner)
|
|
37
|
+
* ObservableHandler->>Stub: setEvent(eventName, payload)
|
|
38
|
+
* Stub->>Ledger: Record event
|
|
39
|
+
*/
|
|
40
|
+
export declare class FabricContractRepositoryObservableHandler extends ObserverHandler {
|
|
41
|
+
private supportedEvents;
|
|
42
|
+
/**
|
|
43
|
+
* @description Creates a new FabricContractRepositoryObservableHandler instance
|
|
44
|
+
* @summary Initializes the handler with a list of supported events
|
|
45
|
+
* @param {Array<OperationKeys | BulkCrudOperationKeys | string>} [supportedEvents] - Events that will trigger Fabric events
|
|
46
|
+
*/
|
|
47
|
+
constructor(supportedEvents?: (OperationKeys | BulkCrudOperationKeys | string)[]);
|
|
48
|
+
/**
|
|
49
|
+
* @description Updates observers by emitting Fabric events
|
|
50
|
+
* @summary Emits events on the Fabric ledger for supported event types
|
|
51
|
+
* @param {Logger} log - Logger instance for debugging
|
|
52
|
+
* @param {string} table - The table/collection name
|
|
53
|
+
* @param {OperationKeys | BulkCrudOperationKeys | string} event - The event type
|
|
54
|
+
* @param {EventIds} id - The event identifier
|
|
55
|
+
* @param {FabricContractContext} ctx - The Fabric contract context
|
|
56
|
+
* @param {string} [owner] - Optional owner identifier for the event
|
|
57
|
+
* @param {object | string | undefined} [owner] - Optional payload for the event
|
|
58
|
+
*
|
|
59
|
+
* @return {Promise<void>} Promise that resolves when the event is emitted
|
|
60
|
+
*/
|
|
61
|
+
updateObservers(log: Logger, table: string, event: OperationKeys | BulkCrudOperationKeys | string, id: EventIds, ctx: Context, owner?: string, payload?: object | string | undefined): Promise<void>;
|
|
62
|
+
}
|