@configura/web-api 1.6.0-alpha.0 → 1.6.0-iotest.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/dist/CfgProduct.d.ts +12 -31
- package/dist/CfgProduct.js +41 -130
- package/dist/index.d.ts +4 -2
- package/dist/index.js +4 -2
- package/dist/io/CfgHistoryManager.d.ts +30 -0
- package/dist/io/CfgHistoryManager.js +62 -0
- package/dist/io/CfgHistoryToProdConfConnector.d.ts +10 -0
- package/dist/io/CfgHistoryToProdConfConnector.js +20 -0
- package/dist/io/CfgIOManager.d.ts +29 -0
- package/dist/io/CfgIOManager.js +89 -0
- package/dist/io/CfgIOProdConfConnector.d.ts +33 -0
- package/dist/io/CfgIOProdConfConnector.js +100 -0
- package/dist/io/CfgWindowMessageManager.d.ts +13 -0
- package/dist/io/CfgWindowMessageManager.js +28 -0
- package/dist/io/CfgWindowMessageToProdConfConnector.d.ts +13 -0
- package/dist/io/CfgWindowMessageToProdConfConnector.js +17 -0
- package/dist/productConfiguration/CfgFeature.d.ts +2 -5
- package/dist/productConfiguration/CfgFeature.js +7 -44
- package/dist/productConfiguration/CfgOption.d.ts +1 -12
- package/dist/productConfiguration/CfgOption.js +3 -30
- package/dist/productConfiguration/CfgProductConfiguration.d.ts +4 -5
- package/dist/productConfiguration/CfgProductConfiguration.js +8 -26
- package/dist/tests/testData/testDataAdditionalProductInAdditionalProductInProductForTest.js +95 -24
- package/dist/tests/testData/testDataCachedGetProduct.js +19 -8
- package/dist/tests/testData/testDataProductAggregatedPrice.js +23 -12
- package/dist/tests/testData/testDataUpcharge.js +48 -16
- package/dist/utilitiesCatalogueData.js +4 -3
- package/package.json +3 -3
- package/dist/syncGroups/SyncGroupsApplier.d.ts +0 -20
- package/dist/syncGroups/SyncGroupsApplier.js +0 -518
- package/dist/syncGroups/SyncGroupsApplyMode.d.ts +0 -15
- package/dist/syncGroups/SyncGroupsApplyMode.js +0 -15
- package/dist/syncGroups/SyncGroupsHandler.d.ts +0 -30
- package/dist/syncGroups/SyncGroupsHandler.js +0 -71
- package/dist/syncGroups/SyncGroupsState.d.ts +0 -20
- package/dist/syncGroups/SyncGroupsState.js +0 -61
- package/dist/syncGroups/SyncGroupsTransaction.d.ts +0 -50
- package/dist/syncGroups/SyncGroupsTransaction.js +0 -106
- package/dist/tests/testData/testDataOptions.d.ts +0 -13
- package/dist/tests/testData/testDataOptions.js +0 -60
|
@@ -1,518 +0,0 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
|
-
import { CfgProductBubbleMode } from "../CfgProduct.js";
|
|
11
|
-
import { SelectionType, } from "../productConfiguration/CfgFeature.js";
|
|
12
|
-
import { ProductConfigurationBubbleMode, } from "../productConfiguration/CfgOption.js";
|
|
13
|
-
import { SyncGroupsApplyMode } from "./SyncGroupsApplyMode.js";
|
|
14
|
-
export class SyncGroupsApplier {
|
|
15
|
-
/**
|
|
16
|
-
* At load of a new product this is used to move it into a synced state
|
|
17
|
-
*/
|
|
18
|
-
static init(transaction) {
|
|
19
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
20
|
-
return yield OntoSyncState.rootProduct(transaction);
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* At an active select of an option this is the entry point
|
|
25
|
-
*/
|
|
26
|
-
static selectOption(transaction, option, on) {
|
|
27
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
28
|
-
const feature = option.parent;
|
|
29
|
-
const productsToValidate = new Set();
|
|
30
|
-
let change = false;
|
|
31
|
-
// Here we sort of hand back to normal selecting. This is because after a normal selection has happened
|
|
32
|
-
// this can have brought features into scope which should pull or push to the Sync State. (Push if the
|
|
33
|
-
// SyncGroup is yet undefined)
|
|
34
|
-
// We use BubbleSelected as we can then delay the validation until after we have applied the sync group (if any)
|
|
35
|
-
if (yield feature.selectOption(option, on, ProductConfigurationBubbleMode.BubbleSelected)) {
|
|
36
|
-
productsToValidate.add(feature.parentProduct);
|
|
37
|
-
switch (feature.selectionType) {
|
|
38
|
-
case SelectionType.SelectOne:
|
|
39
|
-
transaction.addSelectOneFeatureAffected(feature);
|
|
40
|
-
break;
|
|
41
|
-
case SelectionType.SelectMany:
|
|
42
|
-
transaction.addSelectManyOptionAffected(option);
|
|
43
|
-
break;
|
|
44
|
-
default:
|
|
45
|
-
throw new Error("Should not happen");
|
|
46
|
-
}
|
|
47
|
-
change = true;
|
|
48
|
-
}
|
|
49
|
-
switch (feature.selectionType) {
|
|
50
|
-
case SelectionType.SelectOne:
|
|
51
|
-
OntoSyncState.selectOneFeature(transaction, feature, true, false);
|
|
52
|
-
break;
|
|
53
|
-
case SelectionType.SelectMany:
|
|
54
|
-
OntoSyncState.selectManyOption(transaction, option, true);
|
|
55
|
-
break;
|
|
56
|
-
}
|
|
57
|
-
if (yield SyncStateOnto.rootProduct(transaction, productsToValidate)) {
|
|
58
|
-
change = true;
|
|
59
|
-
}
|
|
60
|
-
return change;
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* @returns undefined if the @syncGroup is undefined, false if
|
|
65
|
-
* the @mustSupport is not fulfilled or the syncCode if all is ok
|
|
66
|
-
*/
|
|
67
|
-
static getSyncCode(syncGroup, mustSupport) {
|
|
68
|
-
if (syncGroup === undefined) {
|
|
69
|
-
return undefined;
|
|
70
|
-
}
|
|
71
|
-
const { syncGroupCode, syncMethod } = syncGroup;
|
|
72
|
-
if (syncMethod !== mustSupport && syncMethod !== "twoWay") {
|
|
73
|
-
return false;
|
|
74
|
-
}
|
|
75
|
-
return syncGroupCode;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
class SyncStateOnto {
|
|
79
|
-
/**
|
|
80
|
-
* Apply current sync groups on those who wants to listen until no more to settle
|
|
81
|
-
* @returns true if at least one Feature changed selected Option
|
|
82
|
-
*/
|
|
83
|
-
static rootProduct(transaction, productsToValidate) {
|
|
84
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
85
|
-
productsToValidate = productsToValidate !== null && productsToValidate !== void 0 ? productsToValidate : new Set();
|
|
86
|
-
yield SyncStateOnto.product(transaction, transaction, productsToValidate);
|
|
87
|
-
if (productsToValidate.size === 0) {
|
|
88
|
-
// All settled, continue to pullPhase
|
|
89
|
-
return yield OntoSyncState.rootProduct(transaction);
|
|
90
|
-
}
|
|
91
|
-
if (transaction.isAborted) {
|
|
92
|
-
// We could exit in more places when the transaction has been aborted,
|
|
93
|
-
// but as revalidate is really the only thing that could be expensive /
|
|
94
|
-
// time consuming we only check here.
|
|
95
|
-
return false;
|
|
96
|
-
}
|
|
97
|
-
const promises = [];
|
|
98
|
-
for (const product of productsToValidate) {
|
|
99
|
-
promises.push(product._revalidate(CfgProductBubbleMode.ToRoot, transaction.productLoader));
|
|
100
|
-
}
|
|
101
|
-
const revalidationResults = yield Promise.all(promises);
|
|
102
|
-
// When using SyncGroups we require each and every validate call to validate on the
|
|
103
|
-
// server. Without SyncGroups we let these pass through, because any diversion from
|
|
104
|
-
// what you did chose should be immediately visible. With SyncGroups the end result
|
|
105
|
-
// is the combination of potentially many different validate calls, and so errors
|
|
106
|
-
// could accumulate and what is cause and effect be hard to know.
|
|
107
|
-
if (revalidationResults.some((r) => r.wasAborted || !r.requestDidValidate)) {
|
|
108
|
-
transaction.abort();
|
|
109
|
-
return false;
|
|
110
|
-
}
|
|
111
|
-
// Apply over again, to settle deeper down. Our theory is that the front of
|
|
112
|
-
// "settled" will move deeper and deeper into the tree.
|
|
113
|
-
yield SyncStateOnto.rootProduct(transaction, undefined);
|
|
114
|
-
// We had productsToValidate, and so there must have been a change
|
|
115
|
-
return true;
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
/**
|
|
119
|
-
* Applies the SyncState to the Product and it's AdditionalProducts (sub-products)
|
|
120
|
-
* @param productsToValidate To this all products that will need validation are added
|
|
121
|
-
*/
|
|
122
|
-
static product(transaction, product, productsToValidate) {
|
|
123
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
124
|
-
const promises = [];
|
|
125
|
-
promises.push(SyncStateOnto.features(transaction, getFeaturesFromProduct(product), productsToValidate));
|
|
126
|
-
for (const additionalProduct of getAdditionalProducts(product)) {
|
|
127
|
-
promises.push(SyncStateOnto.product(transaction, additionalProduct, productsToValidate));
|
|
128
|
-
}
|
|
129
|
-
yield Promise.all(promises);
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* Applies the SyncState to an array of Features
|
|
134
|
-
* @param productsToValidate To this all products that will need validation are added
|
|
135
|
-
*/
|
|
136
|
-
static features(transaction, features, productsToValidate) {
|
|
137
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
138
|
-
yield Promise.all(features.map((feature) => __awaiter(this, void 0, void 0, function* () {
|
|
139
|
-
switch (yield SyncStateOnto.feature(transaction, feature, productsToValidate)) {
|
|
140
|
-
case "stop":
|
|
141
|
-
return;
|
|
142
|
-
case "recurseDown":
|
|
143
|
-
yield SyncStateOnto.options(transaction, getSelectedOptions(feature), productsToValidate);
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
})));
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
/**
|
|
150
|
-
* Applies the SyncState to an array of Options
|
|
151
|
-
* @param productsToValidate To this all products that will need validation are added
|
|
152
|
-
*/
|
|
153
|
-
static options(transaction, options, productsToValidate) {
|
|
154
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
155
|
-
yield Promise.all(options.map((option) => {
|
|
156
|
-
return SyncStateOnto.features(transaction, getFeaturesFromOption(option), productsToValidate);
|
|
157
|
-
}));
|
|
158
|
-
});
|
|
159
|
-
}
|
|
160
|
-
/**
|
|
161
|
-
* Applies the SyncState to a Feature
|
|
162
|
-
* @param productsToValidate To this all products that will need validation are added
|
|
163
|
-
* @returns Whether we shall stop recursing down (because we are in a state which we
|
|
164
|
-
* expect to be resolved later), we shall continue recursing down.
|
|
165
|
-
*/
|
|
166
|
-
static feature(transaction, featureWithInitial, productsToValidate) {
|
|
167
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
168
|
-
const feature = featureWithInitial.target;
|
|
169
|
-
const syncCode = SyncGroupsApplier.getSyncCode(feature.syncGroup, "pull");
|
|
170
|
-
if (syncCode === undefined) {
|
|
171
|
-
// Just continue down, features with no sync groups are always settled
|
|
172
|
-
return "recurseDown";
|
|
173
|
-
}
|
|
174
|
-
if (syncCode === false) {
|
|
175
|
-
// Here we only handle pull. Initializing those missing in SyncMap
|
|
176
|
-
// we do later. We wait until we have settled as much as we can with what
|
|
177
|
-
// we have now, to increase chances of the values being written to the
|
|
178
|
-
// SyncState being the right ones.
|
|
179
|
-
return "stop";
|
|
180
|
-
}
|
|
181
|
-
switch (feature.selectionType) {
|
|
182
|
-
case SelectionType.Group:
|
|
183
|
-
return "recurseDown";
|
|
184
|
-
case SelectionType.SelectOne:
|
|
185
|
-
return yield SyncStateOnto.selectOneFeature(transaction, syncCode, featureWithInitial, productsToValidate);
|
|
186
|
-
case SelectionType.SelectMany:
|
|
187
|
-
return yield SyncStateOnto.selectManyFeature(transaction, syncCode, featureWithInitial, productsToValidate);
|
|
188
|
-
}
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
/**
|
|
192
|
-
* Decides if the SyncState can be applied to the SelectOne Feature, and then changes
|
|
193
|
-
* the state of the Feature if so.
|
|
194
|
-
* @param syncCode What SyncGroup the Feature belongs to
|
|
195
|
-
* @param productsToValidate To this all products that will need validation are added
|
|
196
|
-
* @returns Whether we shall stop recursing down (because we are in a state which we
|
|
197
|
-
* expect to be resolved later), we shall continue recursing down.
|
|
198
|
-
*/
|
|
199
|
-
static selectOneFeature(transaction, syncCode, featureWithInitial, productsToValidate) {
|
|
200
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
201
|
-
const feature = featureWithInitial.target;
|
|
202
|
-
const featureDidJustComeIntoScope = featureWithInitial.initial === undefined;
|
|
203
|
-
if (transaction.hasSelectOneFeatureBeenAffected(feature)) {
|
|
204
|
-
// This feature has already changed selection once for this transaction. We expect
|
|
205
|
-
// this to happen very rarely, as the algorithm should settle the selection tree
|
|
206
|
-
// further and further out. Nevertheless, this safeguard is needed to avoid infinite
|
|
207
|
-
// looping if for example the server would return the same data over and over.
|
|
208
|
-
return "recurseDown";
|
|
209
|
-
}
|
|
210
|
-
if (!(featureDidJustComeIntoScope || transaction.isSyncGroupAffectedForSelectOne(syncCode))) {
|
|
211
|
-
return "recurseDown";
|
|
212
|
-
}
|
|
213
|
-
const currentSyncGroupValue = transaction.syncState.getForSelectOne(syncCode);
|
|
214
|
-
if (currentSyncGroupValue === undefined) {
|
|
215
|
-
// This branch will have to be settled later. Don't go further down here.
|
|
216
|
-
return "stop";
|
|
217
|
-
}
|
|
218
|
-
const selectedOption = feature.selectedOptions[0];
|
|
219
|
-
if (selectedOption !== undefined && selectedOption.code === currentSyncGroupValue) {
|
|
220
|
-
// Settled, continue
|
|
221
|
-
return "recurseDown";
|
|
222
|
-
}
|
|
223
|
-
const optionToSelect = feature.options.find((o) => o.code === currentSyncGroupValue);
|
|
224
|
-
if (optionToSelect === undefined) {
|
|
225
|
-
// No option which can be selected (keep current value and recurse down)
|
|
226
|
-
return "recurseDown";
|
|
227
|
-
}
|
|
228
|
-
// Update the value. Validations are collected so that we do not
|
|
229
|
-
// send more than necessary. Do not recurse further as we will change
|
|
230
|
-
// the state and so what is selected now won't be selected then.
|
|
231
|
-
yield feature.selectOption(optionToSelect._internal, true, ProductConfigurationBubbleMode.ToRoot);
|
|
232
|
-
transaction.addSelectOneFeatureAffected(feature);
|
|
233
|
-
productsToValidate.add(feature.parentProduct);
|
|
234
|
-
return "stop";
|
|
235
|
-
});
|
|
236
|
-
}
|
|
237
|
-
/**
|
|
238
|
-
* Decides if the SyncState can be applied to Options in the SelectMany Feature, and
|
|
239
|
-
* then changes the state of the Options if so.
|
|
240
|
-
* @param syncCode What SyncGroup the Feature belongs to
|
|
241
|
-
* @param productsToValidate To this all products that will need validation are added
|
|
242
|
-
* @returns Always "stop" as recursion is handled internally. Return for consistency.
|
|
243
|
-
*/
|
|
244
|
-
static selectManyFeature(transaction, syncCode, feature, productsToValidate) {
|
|
245
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
246
|
-
const optionsToContinueDown = [];
|
|
247
|
-
for (const option of getOptions(feature)) {
|
|
248
|
-
switch (yield SyncStateOnto.selectManyOption(transaction, syncCode, option, productsToValidate)) {
|
|
249
|
-
case "stop":
|
|
250
|
-
continue;
|
|
251
|
-
case "recurseDown":
|
|
252
|
-
optionsToContinueDown.push(option);
|
|
253
|
-
continue;
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
yield SyncStateOnto.options(transaction, optionsToContinueDown, productsToValidate);
|
|
257
|
-
// stop as the method above handles the recursion down
|
|
258
|
-
return "stop";
|
|
259
|
-
});
|
|
260
|
-
}
|
|
261
|
-
/**
|
|
262
|
-
* Decides if the SyncState can be applied to the SelectMany Option, and then changes
|
|
263
|
-
* the state of the Option if so.
|
|
264
|
-
* @param syncCode What SyncGroup the Feature belongs to
|
|
265
|
-
* @param productsToValidate To this all products that will need validation are added
|
|
266
|
-
* @returns Whether we shall stop recursing down (because we are in a state which we
|
|
267
|
-
* expect to be resolved later), we shall continue recursing down.
|
|
268
|
-
*/
|
|
269
|
-
static selectManyOption(transaction, syncCode, optionWithInitial, productsToValidate) {
|
|
270
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
271
|
-
const option = optionWithInitial.target;
|
|
272
|
-
const featureDidJustComeIntoScope = optionWithInitial.initial === undefined;
|
|
273
|
-
const optionSelected = option.selected;
|
|
274
|
-
const recurseOrStopIfNoChange = optionSelected ? "recurseDown" : "stop";
|
|
275
|
-
if (transaction.hasSelectManyOptionBeenAffected(option)) {
|
|
276
|
-
// This option has already changed selection once for this transaction. We expect
|
|
277
|
-
// this to happen very rarely, as the algorithm should settle the selection tree
|
|
278
|
-
// further and further out. Nevertheless, this safeguard is needed to avoid infinite
|
|
279
|
-
// looping if for example the server would return the same data over and over.
|
|
280
|
-
return recurseOrStopIfNoChange;
|
|
281
|
-
}
|
|
282
|
-
const optionCode = option.code;
|
|
283
|
-
if (!(featureDidJustComeIntoScope ||
|
|
284
|
-
transaction.isSyncGroupAffectedForSelectMany(syncCode, optionCode))) {
|
|
285
|
-
return "recurseDown";
|
|
286
|
-
}
|
|
287
|
-
const syncGroupValueForOption = transaction.syncState.getForSelectMany(syncCode, optionCode);
|
|
288
|
-
if (syncGroupValueForOption === undefined) {
|
|
289
|
-
// The sync group has no opinion on this. If it is selected, just continue down.
|
|
290
|
-
return recurseOrStopIfNoChange;
|
|
291
|
-
}
|
|
292
|
-
if (syncGroupValueForOption === optionSelected) {
|
|
293
|
-
// We are in sync for this option
|
|
294
|
-
return recurseOrStopIfNoChange;
|
|
295
|
-
}
|
|
296
|
-
const feature = option.parent;
|
|
297
|
-
// Update the value. Validations are collected so that we do not
|
|
298
|
-
// send more than necessary. Do not recurse further as we will change
|
|
299
|
-
// the state and so what is selected now won't be selected then.
|
|
300
|
-
yield feature.selectOption(option, syncGroupValueForOption, ProductConfigurationBubbleMode.ToRoot);
|
|
301
|
-
transaction.addSelectManyOptionAffected(option);
|
|
302
|
-
productsToValidate.add(feature.parentProduct);
|
|
303
|
-
return "stop";
|
|
304
|
-
});
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
class OntoSyncState {
|
|
308
|
-
/**
|
|
309
|
-
* @returns true if at least one Feature changed it state. This is a bit counter intuitive,
|
|
310
|
-
* but as this method will hand over to productOntoSyncState if it updates the SyncState it
|
|
311
|
-
* can cause the Features to change. And we need to pass that information back to know when
|
|
312
|
-
* to stop
|
|
313
|
-
*/
|
|
314
|
-
static rootProduct(transaction) {
|
|
315
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
316
|
-
if (!(yield OntoSyncState.product(transaction, transaction))) {
|
|
317
|
-
// All done!
|
|
318
|
-
return false;
|
|
319
|
-
}
|
|
320
|
-
return yield SyncStateOnto.rootProduct(transaction, undefined);
|
|
321
|
-
});
|
|
322
|
-
}
|
|
323
|
-
static product(transaction, product) {
|
|
324
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
325
|
-
let change = false;
|
|
326
|
-
if (yield OntoSyncState.features(transaction, getFeaturesFromProduct(product))) {
|
|
327
|
-
if (transaction.updateMode === SyncGroupsApplyMode.Strict) {
|
|
328
|
-
return true;
|
|
329
|
-
}
|
|
330
|
-
change = true;
|
|
331
|
-
}
|
|
332
|
-
for (const additionalProduct of getAdditionalProducts(product)) {
|
|
333
|
-
if (yield OntoSyncState.product(transaction, additionalProduct)) {
|
|
334
|
-
if (transaction.updateMode === SyncGroupsApplyMode.Strict) {
|
|
335
|
-
return true;
|
|
336
|
-
}
|
|
337
|
-
change = true;
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
return change;
|
|
341
|
-
});
|
|
342
|
-
}
|
|
343
|
-
static features(transaction, featureWithInitials) {
|
|
344
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
345
|
-
let change = false;
|
|
346
|
-
for (const featureWithInitial of featureWithInitials) {
|
|
347
|
-
const feature = featureWithInitial.target;
|
|
348
|
-
switch (feature.selectionType) {
|
|
349
|
-
case SelectionType.SelectOne:
|
|
350
|
-
if (OntoSyncState.selectOneFeature(transaction, feature, false, featureWithInitial.initial === undefined)) {
|
|
351
|
-
change = true;
|
|
352
|
-
}
|
|
353
|
-
break;
|
|
354
|
-
case SelectionType.SelectMany:
|
|
355
|
-
if (OntoSyncState.selectManyFeature(transaction, featureWithInitial)) {
|
|
356
|
-
change = true;
|
|
357
|
-
}
|
|
358
|
-
break;
|
|
359
|
-
}
|
|
360
|
-
if (change && transaction.updateMode === SyncGroupsApplyMode.Strict) {
|
|
361
|
-
return true;
|
|
362
|
-
}
|
|
363
|
-
if (yield OntoSyncState.options(transaction, getSelectedOptions(featureWithInitial))) {
|
|
364
|
-
if (transaction.updateMode === SyncGroupsApplyMode.Strict) {
|
|
365
|
-
return true;
|
|
366
|
-
}
|
|
367
|
-
change = true;
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
return change;
|
|
371
|
-
});
|
|
372
|
-
}
|
|
373
|
-
static options(transaction, options) {
|
|
374
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
375
|
-
let change = false;
|
|
376
|
-
for (const option of options) {
|
|
377
|
-
if (yield OntoSyncState.features(transaction, getFeaturesFromOption(option))) {
|
|
378
|
-
if (transaction.updateMode === SyncGroupsApplyMode.Strict) {
|
|
379
|
-
return true;
|
|
380
|
-
}
|
|
381
|
-
change = true;
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
return change;
|
|
385
|
-
});
|
|
386
|
-
}
|
|
387
|
-
static selectOneFeature(transaction, feature, activeSelectionForce, featureDidJustComeIntoScope) {
|
|
388
|
-
const selectionType = feature.selectionType;
|
|
389
|
-
if (selectionType !== SelectionType.SelectOne) {
|
|
390
|
-
throw new Error("can only be used for selectOne");
|
|
391
|
-
}
|
|
392
|
-
const syncCode = SyncGroupsApplier.getSyncCode(feature.syncGroup, "push");
|
|
393
|
-
if (syncCode === undefined || syncCode === false) {
|
|
394
|
-
return false;
|
|
395
|
-
}
|
|
396
|
-
if (transaction.isSyncGroupAffectedForSelectOne(syncCode)) {
|
|
397
|
-
return false;
|
|
398
|
-
}
|
|
399
|
-
const syncState = transaction.syncState;
|
|
400
|
-
const currentSyncGroupOptionCode = syncState.getForSelectOne(syncCode);
|
|
401
|
-
const option = feature.selectedOptions[0];
|
|
402
|
-
if (option === undefined) {
|
|
403
|
-
// Options with no default are never written
|
|
404
|
-
return false;
|
|
405
|
-
}
|
|
406
|
-
if (activeSelectionForce) {
|
|
407
|
-
// To make re-apply happen, even if it actually does not update the sync group
|
|
408
|
-
transaction.addSyncGroupAffectedForSelectOne(syncCode);
|
|
409
|
-
}
|
|
410
|
-
const optionCode = option.code;
|
|
411
|
-
if (optionCode === currentSyncGroupOptionCode) {
|
|
412
|
-
return false;
|
|
413
|
-
}
|
|
414
|
-
// featureDidJustComeIntoScope, in CET there is a feature that if a feature appears which can not be set
|
|
415
|
-
// to the current sync group value, then it will set in the opposite direction. Like if the sync group was
|
|
416
|
-
// empty. To avoid bouncing back and forth we will need to enforce that a sync group can only be updated
|
|
417
|
-
// once per transaction
|
|
418
|
-
if (!(activeSelectionForce ||
|
|
419
|
-
currentSyncGroupOptionCode === undefined ||
|
|
420
|
-
(featureDidJustComeIntoScope &&
|
|
421
|
-
feature.options.every((o) => currentSyncGroupOptionCode !== o.code)))) {
|
|
422
|
-
return false;
|
|
423
|
-
}
|
|
424
|
-
syncState.logDebug();
|
|
425
|
-
transaction.addSyncGroupAffectedForSelectOne(syncCode);
|
|
426
|
-
syncState.setForSelectOne(syncCode, optionCode);
|
|
427
|
-
return true;
|
|
428
|
-
}
|
|
429
|
-
static selectManyFeature(transaction, featureWithInitial) {
|
|
430
|
-
let change = false;
|
|
431
|
-
for (const optionWithInitial of getOptions(featureWithInitial)) {
|
|
432
|
-
if (OntoSyncState.selectManyOption(transaction, optionWithInitial.target, false)) {
|
|
433
|
-
if (transaction.updateMode === SyncGroupsApplyMode.Strict) {
|
|
434
|
-
return true;
|
|
435
|
-
}
|
|
436
|
-
change = true;
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
return change;
|
|
440
|
-
}
|
|
441
|
-
static selectManyOption(transaction, option, activeSelectionForce) {
|
|
442
|
-
const feature = option.parent;
|
|
443
|
-
if (feature.selectionType !== SelectionType.SelectMany) {
|
|
444
|
-
throw new Error("can only be used for selectMany");
|
|
445
|
-
}
|
|
446
|
-
const syncCode = SyncGroupsApplier.getSyncCode(feature.syncGroup, "push");
|
|
447
|
-
if (syncCode === undefined || syncCode === false) {
|
|
448
|
-
return false;
|
|
449
|
-
}
|
|
450
|
-
const optionCode = option.code;
|
|
451
|
-
if (transaction.isSyncGroupAffectedForSelectMany(syncCode, optionCode)) {
|
|
452
|
-
return false;
|
|
453
|
-
}
|
|
454
|
-
const syncState = transaction.syncState;
|
|
455
|
-
const optionSelected = option.selected;
|
|
456
|
-
const currentSyncGroupValue = syncState.getForSelectMany(syncCode, optionCode);
|
|
457
|
-
if (activeSelectionForce) {
|
|
458
|
-
// To make re-apply happen, even if it actually does not update the sync group
|
|
459
|
-
transaction.addSyncGroupAffectedForSelectMany(syncCode, optionCode);
|
|
460
|
-
}
|
|
461
|
-
// We only initialize if the option is selected or we force.
|
|
462
|
-
// activeSelectionForce = active selection by the user.
|
|
463
|
-
if (!(currentSyncGroupValue === undefined && optionSelected) &&
|
|
464
|
-
!(activeSelectionForce && currentSyncGroupValue !== optionSelected)) {
|
|
465
|
-
return false;
|
|
466
|
-
}
|
|
467
|
-
transaction.addSyncGroupAffectedForSelectMany(syncCode, optionCode);
|
|
468
|
-
syncState.setForSelectMany(syncCode, optionCode, optionSelected);
|
|
469
|
-
return true;
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
function getAdditionalProducts(product) {
|
|
473
|
-
const initial = product.initial;
|
|
474
|
-
return product.target.additionalProducts.map((childTarget) => {
|
|
475
|
-
const refKey = childTarget.refKey;
|
|
476
|
-
const childInitial = initial === null || initial === void 0 ? void 0 : initial.additionalProducts.find((p) => refKey === p.refKey);
|
|
477
|
-
return {
|
|
478
|
-
target: childTarget._internal,
|
|
479
|
-
initial: childInitial === null || childInitial === void 0 ? void 0 : childInitial._internal,
|
|
480
|
-
};
|
|
481
|
-
});
|
|
482
|
-
}
|
|
483
|
-
function pairOptions(targets, initials) {
|
|
484
|
-
return targets.map((childTarget) => {
|
|
485
|
-
const key = childTarget.key;
|
|
486
|
-
const childInitial = initials === null || initials === void 0 ? void 0 : initials.find((o) => key === o.key);
|
|
487
|
-
return {
|
|
488
|
-
target: childTarget._internal,
|
|
489
|
-
initial: childInitial === null || childInitial === void 0 ? void 0 : childInitial._internal,
|
|
490
|
-
};
|
|
491
|
-
});
|
|
492
|
-
}
|
|
493
|
-
function getSelectedOptions(feature) {
|
|
494
|
-
var _a;
|
|
495
|
-
return pairOptions(feature.target.selectedOptions, (_a = feature.initial) === null || _a === void 0 ? void 0 : _a.selectedOptions);
|
|
496
|
-
}
|
|
497
|
-
function getOptions(feature) {
|
|
498
|
-
var _a;
|
|
499
|
-
return pairOptions(feature.target.options, (_a = feature.initial) === null || _a === void 0 ? void 0 : _a.options);
|
|
500
|
-
}
|
|
501
|
-
function pairFeatures(targets, initials) {
|
|
502
|
-
return targets.map((childTarget) => {
|
|
503
|
-
const key = childTarget.key;
|
|
504
|
-
const childInitial = initials === null || initials === void 0 ? void 0 : initials.find((f) => key === f.key);
|
|
505
|
-
return {
|
|
506
|
-
target: childTarget._internal,
|
|
507
|
-
initial: childInitial === null || childInitial === void 0 ? void 0 : childInitial._internal,
|
|
508
|
-
};
|
|
509
|
-
});
|
|
510
|
-
}
|
|
511
|
-
function getFeaturesFromProduct(product) {
|
|
512
|
-
var _a;
|
|
513
|
-
return pairFeatures(product.target.configuration.features, (_a = product.initial) === null || _a === void 0 ? void 0 : _a.configuration.features);
|
|
514
|
-
}
|
|
515
|
-
function getFeaturesFromOption(option) {
|
|
516
|
-
var _a;
|
|
517
|
-
return pairFeatures(option.target.features, (_a = option.initial) === null || _a === void 0 ? void 0 : _a.features);
|
|
518
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The SyncGroupsApplyMode controls how many SyncGroups can be updated in the SyncState for one
|
|
3
|
-
* run of rootProductOntoSyncState (C.). "Fast" is default and will make any SyncGroup that
|
|
4
|
-
* should be updated update before running syncStateOntoRootProduct (B.) This way several
|
|
5
|
-
* SyncGroups can be applied in one go before sending validation calls to the server. The
|
|
6
|
-
* downside of this is that is not exactly how CET (the desktop software) works. CET will apply
|
|
7
|
-
* Features to the SyncState as soon as it gets the chance. This is the same as running with
|
|
8
|
-
* "Strict" here. This will potentially generate a lot more validate calls, increasing delay
|
|
9
|
-
* and cost. So if you don't have to, stick with "Fast".
|
|
10
|
-
*/
|
|
11
|
-
export declare enum SyncGroupsApplyMode {
|
|
12
|
-
Fast = "Fast",
|
|
13
|
-
Strict = "Strict"
|
|
14
|
-
}
|
|
15
|
-
//# sourceMappingURL=SyncGroupsApplyMode.d.ts.map
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The SyncGroupsApplyMode controls how many SyncGroups can be updated in the SyncState for one
|
|
3
|
-
* run of rootProductOntoSyncState (C.). "Fast" is default and will make any SyncGroup that
|
|
4
|
-
* should be updated update before running syncStateOntoRootProduct (B.) This way several
|
|
5
|
-
* SyncGroups can be applied in one go before sending validation calls to the server. The
|
|
6
|
-
* downside of this is that is not exactly how CET (the desktop software) works. CET will apply
|
|
7
|
-
* Features to the SyncState as soon as it gets the chance. This is the same as running with
|
|
8
|
-
* "Strict" here. This will potentially generate a lot more validate calls, increasing delay
|
|
9
|
-
* and cost. So if you don't have to, stick with "Fast".
|
|
10
|
-
*/
|
|
11
|
-
export var SyncGroupsApplyMode;
|
|
12
|
-
(function (SyncGroupsApplyMode) {
|
|
13
|
-
SyncGroupsApplyMode["Fast"] = "Fast";
|
|
14
|
-
SyncGroupsApplyMode["Strict"] = "Strict";
|
|
15
|
-
})(SyncGroupsApplyMode || (SyncGroupsApplyMode = {}));
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { CfgPath, _CfgProductInternal } from "../CfgProduct.js";
|
|
2
|
-
import { ProductLoader } from "../productLoader.js";
|
|
3
|
-
import { SyncGroupsApplyMode } from "./SyncGroupsApplyMode.js";
|
|
4
|
-
import { SyncGroupsTransaction } from "./SyncGroupsTransaction.js";
|
|
5
|
-
export declare type SyncCode = string;
|
|
6
|
-
export declare type OptionCode = string;
|
|
7
|
-
/**
|
|
8
|
-
* Is used to apply the SyncGroups functionality on the Configuration and the other
|
|
9
|
-
* way around. It also keeps the SyncState.
|
|
10
|
-
*/
|
|
11
|
-
export declare class SyncGroupsHandler {
|
|
12
|
-
private _syncState;
|
|
13
|
-
readonly updateMode: SyncGroupsApplyMode;
|
|
14
|
-
private _currentTransaction;
|
|
15
|
-
static make(updateMode?: SyncGroupsApplyMode): SyncGroupsHandler;
|
|
16
|
-
private constructor();
|
|
17
|
-
clone(): SyncGroupsHandler;
|
|
18
|
-
/**
|
|
19
|
-
* Used to initially apply the sync state onto a new product so that it is "in sync"
|
|
20
|
-
*/
|
|
21
|
-
init(product: _CfgProductInternal, productLoader: ProductLoader): Promise<void>;
|
|
22
|
-
/**
|
|
23
|
-
* Used when an Option is selected or deselected to apply all consequences of the sync groups.
|
|
24
|
-
* Can cause multiple extra validation calls to the server.
|
|
25
|
-
*/
|
|
26
|
-
selectOption(product: _CfgProductInternal, optionPath: CfgPath, on: boolean, productLoader: ProductLoader): Promise<boolean>;
|
|
27
|
-
newTransaction(product: _CfgProductInternal, productLoader: ProductLoader, assumeNoStartProductState: boolean): Promise<SyncGroupsTransaction>;
|
|
28
|
-
applyTransaction(transaction: SyncGroupsTransaction): Promise<void>;
|
|
29
|
-
}
|
|
30
|
-
//# sourceMappingURL=SyncGroupsHandler.d.ts.map
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
|
-
import { SyncGroupsApplyMode } from "./SyncGroupsApplyMode.js";
|
|
11
|
-
import { SyncGroupsState } from "./SyncGroupsState.js";
|
|
12
|
-
import { SyncGroupsTransaction } from "./SyncGroupsTransaction.js";
|
|
13
|
-
/**
|
|
14
|
-
* Is used to apply the SyncGroups functionality on the Configuration and the other
|
|
15
|
-
* way around. It also keeps the SyncState.
|
|
16
|
-
*/
|
|
17
|
-
export class SyncGroupsHandler {
|
|
18
|
-
constructor(_syncState, updateMode) {
|
|
19
|
-
this._syncState = _syncState;
|
|
20
|
-
this.updateMode = updateMode;
|
|
21
|
-
}
|
|
22
|
-
static make(updateMode = SyncGroupsApplyMode.Fast) {
|
|
23
|
-
return new SyncGroupsHandler(new SyncGroupsState(), updateMode);
|
|
24
|
-
}
|
|
25
|
-
clone() {
|
|
26
|
-
return new SyncGroupsHandler(this._syncState.clone(), this.updateMode);
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Used to initially apply the sync state onto a new product so that it is "in sync"
|
|
30
|
-
*/
|
|
31
|
-
init(product, productLoader) {
|
|
32
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
33
|
-
const transaction = yield this.newTransaction(product, productLoader, true);
|
|
34
|
-
yield transaction.init();
|
|
35
|
-
yield this.applyTransaction(transaction);
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Used when an Option is selected or deselected to apply all consequences of the sync groups.
|
|
40
|
-
* Can cause multiple extra validation calls to the server.
|
|
41
|
-
*/
|
|
42
|
-
selectOption(product, optionPath, on, productLoader) {
|
|
43
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
44
|
-
//todo: should we guarantee that it will use root? Tricky...
|
|
45
|
-
const transaction = yield this.newTransaction(product, productLoader, false);
|
|
46
|
-
const change = yield transaction.selectOption(optionPath, on);
|
|
47
|
-
// We always apply. The change-result above only tells if the configuration
|
|
48
|
-
// has changed. The SyncState may also have changed.
|
|
49
|
-
yield this.applyTransaction(transaction);
|
|
50
|
-
return change;
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
newTransaction(product, productLoader, assumeNoStartProductState) {
|
|
54
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
55
|
-
if (this._currentTransaction !== undefined) {
|
|
56
|
-
this._currentTransaction.abort();
|
|
57
|
-
}
|
|
58
|
-
this._currentTransaction = yield SyncGroupsTransaction.make(this._syncState, this.updateMode, product, productLoader, assumeNoStartProductState);
|
|
59
|
-
return this._currentTransaction;
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
applyTransaction(transaction) {
|
|
63
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
64
|
-
if (transaction.isAborted) {
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
this._syncState.setFrom(transaction.syncState);
|
|
68
|
-
yield transaction.original.copyFrom(transaction.target, false, transaction.productLoader);
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { OptionCode, SyncCode } from "./SyncGroupsHandler.js";
|
|
2
|
-
/**
|
|
3
|
-
* Is used to keep track of the current value of the SyncGroups. Is fully separated between
|
|
4
|
-
* SelectOne and SelectMany as Features of the two types are synced separately.
|
|
5
|
-
*/
|
|
6
|
-
export declare class SyncGroupsState {
|
|
7
|
-
readonly _selectOne: Map<SyncCode, OptionCode>;
|
|
8
|
-
readonly _selectMany: Map<SyncCode, Map<OptionCode, boolean>>;
|
|
9
|
-
clone(): SyncGroupsState;
|
|
10
|
-
/**
|
|
11
|
-
* Replaces the current state
|
|
12
|
-
*/
|
|
13
|
-
setFrom(other: SyncGroupsState): void;
|
|
14
|
-
setForSelectOne(syncCode: SyncCode, optionCode: OptionCode): void;
|
|
15
|
-
setForSelectMany(syncCode: SyncCode, optionCode: OptionCode, selected: boolean): void;
|
|
16
|
-
getForSelectOne(syncCode: SyncCode): OptionCode | undefined;
|
|
17
|
-
getForSelectMany(syncCode: SyncCode, optionCode: OptionCode): boolean | undefined;
|
|
18
|
-
logDebug(): void;
|
|
19
|
-
}
|
|
20
|
-
//# sourceMappingURL=SyncGroupsState.d.ts.map
|