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