@configura/web-api 1.6.1-alpha.7 → 1.6.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/.eslintrc.json +18 -0
- package/dist/CatalogueAPI.d.ts +4 -9
- package/dist/CatalogueAPI.js +6 -3
- package/dist/CfgProduct.d.ts +31 -12
- package/dist/CfgProduct.js +124 -45
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/productConfiguration/CfgFeature.d.ts +13 -3
- package/dist/productConfiguration/CfgFeature.js +77 -52
- package/dist/productConfiguration/CfgOption.d.ts +30 -8
- package/dist/productConfiguration/CfgOption.js +49 -17
- package/dist/productConfiguration/CfgProductConfiguration.d.ts +1 -1
- package/dist/productConfiguration/CfgProductConfiguration.js +4 -2
- package/dist/productConfiguration/filters.js +7 -7
- package/dist/syncGroups/SyncGroupsApplyMode.d.ts +21 -0
- package/dist/syncGroups/SyncGroupsApplyMode.js +21 -0
- package/dist/syncGroups/SyncGroupsHandler.d.ts +41 -0
- package/dist/syncGroups/SyncGroupsHandler.js +358 -0
- package/dist/syncGroups/SyncGroupsPathHelper.d.ts +27 -0
- package/dist/syncGroups/SyncGroupsPathHelper.js +90 -0
- package/dist/syncGroups/SyncGroupsState.d.ts +36 -0
- package/dist/syncGroups/SyncGroupsState.js +125 -0
- package/dist/syncGroups/SyncGroupsTransaction.d.ts +155 -0
- package/dist/syncGroups/SyncGroupsTransaction.js +576 -0
- package/dist/tasks/TaskHandler.d.ts +1 -1
- package/dist/tasks/TaskHandler.js +20 -9
- package/dist/tests/testData/collectorForTest.d.ts +1 -1
- package/dist/tests/testData/collectorForTest.js +1 -2
- package/dist/tests/testData/testDataAdditionalProductInAdditionalProductInProductForTest.d.ts +3 -24
- package/dist/tests/testData/testDataAdditionalProductInAdditionalProductInProductForTest.js +30 -101
- package/dist/tests/testData/testDataCachedGetProduct.d.ts +1 -1
- package/dist/tests/testData/testDataCachedGetProduct.js +16 -27
- package/dist/tests/testData/testDataCachedPostValidate.js +5 -5
- package/dist/tests/testData/testDataOptions.d.ts +13 -0
- package/dist/tests/testData/testDataOptions.js +60 -0
- package/dist/tests/testData/testDataProductAggregatedPrice.js +19 -30
- package/dist/tests/testData/testDataUpcharge.d.ts +3 -24
- package/dist/tests/testData/testDataUpcharge.js +17 -49
- package/dist/utilitiesCatalogueData.d.ts +8 -2
- package/dist/utilitiesCatalogueData.js +105 -9
- package/dist/utilitiesCataloguePermission.d.ts +1 -3
- package/dist/utilitiesCataloguePermission.js +10 -14
- package/package.json +3 -3
package/.eslintrc.json
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"parser": "@typescript-eslint/parser",
|
|
3
|
+
"plugins": ["@typescript-eslint"],
|
|
4
|
+
"extends": [
|
|
5
|
+
"eslint:recommended",
|
|
6
|
+
"plugin:@typescript-eslint/recommended",
|
|
7
|
+
"prettier"
|
|
8
|
+
|
|
9
|
+
// TODO: Type-checking rules require a proper tsconfig-file to work,
|
|
10
|
+
// pointed at by the parserOption.project setting.
|
|
11
|
+
//
|
|
12
|
+
//"plugin:@typescript-eslint/recommended-requiring-type-checking"
|
|
13
|
+
]
|
|
14
|
+
//"rules": { "@typescript-eslint/no-floating-promises": "error" }
|
|
15
|
+
//"parserOptions": {
|
|
16
|
+
// "project": "./tsconfig.json"
|
|
17
|
+
//}
|
|
18
|
+
}
|
package/dist/CatalogueAPI.d.ts
CHANGED
|
@@ -66,14 +66,6 @@ export interface CodeRange {
|
|
|
66
66
|
maxValue: number;
|
|
67
67
|
increment?: number;
|
|
68
68
|
}
|
|
69
|
-
/** ConnectorRef */
|
|
70
|
-
export interface ConnectorRef {
|
|
71
|
-
code: string;
|
|
72
|
-
connectRule: string;
|
|
73
|
-
visible: boolean;
|
|
74
|
-
anchor?: MeasureParam;
|
|
75
|
-
transform: Transform;
|
|
76
|
-
}
|
|
77
69
|
/** ErrorResponse */
|
|
78
70
|
export interface ErrorResponse {
|
|
79
71
|
error: string;
|
|
@@ -349,7 +341,6 @@ export interface ProductData {
|
|
|
349
341
|
navImage?: string;
|
|
350
342
|
sku: string;
|
|
351
343
|
measurements?: Array<Measurement>;
|
|
352
|
-
connectorRefs?: Array<ConnectorRef>;
|
|
353
344
|
tags?: Array<{
|
|
354
345
|
[index: string]: string;
|
|
355
346
|
}>;
|
|
@@ -491,8 +482,11 @@ export declare class APIError<T> extends Error {
|
|
|
491
482
|
parsed?: T;
|
|
492
483
|
status?: number;
|
|
493
484
|
}
|
|
485
|
+
declare type FetchFunc = (input: RequestInfo, init?: RequestInit) => Promise<Response>;
|
|
494
486
|
export declare class CatalogueAPI {
|
|
487
|
+
private readonly _fetch;
|
|
495
488
|
auth: AuthorizeResponse | undefined;
|
|
489
|
+
constructor(_fetch?: FetchFunc);
|
|
496
490
|
private _alternativeReferer;
|
|
497
491
|
_saveAlternativeReferer(): void;
|
|
498
492
|
hasFeature(feature: string): boolean;
|
|
@@ -510,4 +504,5 @@ export declare class CatalogueAPI {
|
|
|
510
504
|
getRenderById(params: GetRenderByIdParams): Promise<RenderResponse>;
|
|
511
505
|
postSessionTokenRefresh(): Promise<RefreshSessionTokenResponse>;
|
|
512
506
|
}
|
|
507
|
+
export {};
|
|
513
508
|
//# sourceMappingURL=CatalogueAPI.d.ts.map
|
package/dist/CatalogueAPI.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
//
|
|
2
|
-
|
|
1
|
+
// TODO: Fix the linter issue in Tygen and regenerate this file.
|
|
2
|
+
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
|
3
3
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
4
4
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
5
5
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -35,6 +35,9 @@ export const syncGroupMethodsNames = ["pull", "push", "twoWay"];
|
|
|
35
35
|
export class APIError extends Error {
|
|
36
36
|
}
|
|
37
37
|
export class CatalogueAPI {
|
|
38
|
+
constructor(_fetch = window.fetch.bind(window)) {
|
|
39
|
+
this._fetch = _fetch;
|
|
40
|
+
}
|
|
38
41
|
// For internal use
|
|
39
42
|
_saveAlternativeReferer() {
|
|
40
43
|
if (typeof document === "undefined") {
|
|
@@ -59,7 +62,7 @@ export class CatalogueAPI {
|
|
|
59
62
|
options.headers["Content-Type"] = "application/json;charset=utf-8";
|
|
60
63
|
}
|
|
61
64
|
try {
|
|
62
|
-
response = yield
|
|
65
|
+
response = yield this._fetch(url, options);
|
|
63
66
|
body = yield response.text();
|
|
64
67
|
const parsed = JSON.parse(body);
|
|
65
68
|
if ("error" in parsed) {
|
package/dist/CfgProduct.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { AggregatedLoadingObservable, LengthUnit, Observable, SingleArgCallback } from "@configura/web-utilities";
|
|
2
|
-
import { AdditionalProductConfiguration, CatalogueParams, MeasureParam, MtrlApplication, Prices, Transform } from "./CatalogueAPI.js";
|
|
2
|
+
import { AdditionalProductConfiguration, AdditionalProductRef, CatalogueParams, MeasureParam, MtrlApplication, Prices, Transform } from "./CatalogueAPI.js";
|
|
3
3
|
import { CfgMeasureDefinition } from "./CfgMeasure.js";
|
|
4
4
|
import { _CfgFeatureInternal } from "./productConfiguration/CfgFeature.js";
|
|
5
5
|
import { ProductConfigurationBubbleMode } from "./productConfiguration/CfgOption.js";
|
|
6
6
|
import { CfgProductConfiguration } from "./productConfiguration/CfgProductConfiguration.js";
|
|
7
7
|
import { ProductLoader } from "./productLoader.js";
|
|
8
|
+
import { SyncGroupsApplyMode } from "./syncGroups/SyncGroupsApplyMode.js";
|
|
9
|
+
import { SyncGroupsHandler } from "./syncGroups/SyncGroupsHandler.js";
|
|
8
10
|
import { CfgProductData, RootNodeSource } from "./utilitiesCatalogueData.js";
|
|
9
11
|
export declare type CfgProductChangeNotification = {
|
|
10
12
|
freshRef: CfgProduct;
|
|
@@ -18,12 +20,19 @@ export declare type CfgProductSettings = {
|
|
|
18
20
|
*/
|
|
19
21
|
strictSelectOneSelectionCount: boolean;
|
|
20
22
|
/**
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
23
|
+
* Controls if SyncGroups are applied Faster or Stricter.
|
|
24
|
+
*
|
|
25
|
+
* Fast - Tries to minimize the number of validates calls to the AI lowering the response times
|
|
26
|
+
* for selecting options. Might not always give the expected result for complex products.
|
|
27
|
+
*
|
|
28
|
+
* Strict - Apply the SyncGroups rules in a stricter fashion to be as close to CET as possible,
|
|
29
|
+
* which might result in longer response times and more validation calls to the API when
|
|
30
|
+
* selecting options.
|
|
31
|
+
*
|
|
32
|
+
* The SDK will default to Strict, but we recommend that you try out Fast since cases where the
|
|
33
|
+
* results differ should be rare in most real uses cases and the speedup can be quite large.
|
|
25
34
|
*/
|
|
26
|
-
|
|
35
|
+
syncGroupsApplyMode: SyncGroupsApplyMode | undefined;
|
|
27
36
|
};
|
|
28
37
|
/**
|
|
29
38
|
* This enum is used internally in the SDK and is not expected by be used directly by integrators.
|
|
@@ -63,12 +72,10 @@ export declare class _CfgProductInternal {
|
|
|
63
72
|
private readonly _rawUnit;
|
|
64
73
|
private _rawProductData;
|
|
65
74
|
readonly loadingObservable: AggregatedLoadingObservable;
|
|
66
|
-
readonly refKey: string | undefined;
|
|
67
|
-
readonly refDescription: string | undefined;
|
|
68
75
|
readonly parent: _CfgProductInternal | undefined;
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
static make: (productLoaderRaw: ProductLoader, productLoaderForGroupedLoad: ProductLoader | undefined, lang: string, catId: CatalogueParams, partNumber: string, settings: CfgProductSettings, optional: boolean, loadingObservable: AggregatedLoadingObservable,
|
|
76
|
+
private _additionalProductRef;
|
|
77
|
+
private readonly _syncGroupHandler;
|
|
78
|
+
static make: (productLoaderRaw: ProductLoader, productLoaderForGroupedLoad: ProductLoader | undefined, lang: string, catId: CatalogueParams, partNumber: string, settings: CfgProductSettings, optional: boolean, loadingObservable: AggregatedLoadingObservable, parent: _CfgProductInternal | undefined, root: _CfgProductInternal | undefined, additionalProductRef: AdditionalProductRef | undefined) => Promise<_CfgProductInternal>;
|
|
72
79
|
private constructor();
|
|
73
80
|
readonly root: _CfgProductInternal;
|
|
74
81
|
private _destroyed;
|
|
@@ -81,6 +88,7 @@ export declare class _CfgProductInternal {
|
|
|
81
88
|
readonly isAdditionalProduct: boolean;
|
|
82
89
|
clone(parent?: _CfgProductInternal, root?: _CfgProductInternal): Promise<_CfgProductInternal>;
|
|
83
90
|
destroy: () => void;
|
|
91
|
+
_updateAdditionalProdRef(p: AdditionalProductRef): void;
|
|
84
92
|
get description(): string | undefined;
|
|
85
93
|
get rootNodeSources(): RootNodeSource[] | undefined;
|
|
86
94
|
get mtrlApplications(): MtrlApplication[] | undefined;
|
|
@@ -90,6 +98,9 @@ export declare class _CfgProductInternal {
|
|
|
90
98
|
private _measureDefinitions;
|
|
91
99
|
get measureDefinitions(): CfgMeasureDefinition[];
|
|
92
100
|
private _unit;
|
|
101
|
+
get refKey(): string | undefined;
|
|
102
|
+
get transform(): Transform | undefined;
|
|
103
|
+
get anchor(): MeasureParam | undefined;
|
|
93
104
|
/** @throws an error if the actual unit sent by the server was not a LengthUnit */
|
|
94
105
|
get unit(): LengthUnit;
|
|
95
106
|
get aggregatedPrice(): CfgPrice;
|
|
@@ -121,6 +132,14 @@ export declare class _CfgProductInternal {
|
|
|
121
132
|
_configurationHasChanged: (freshRef: CfgProductConfiguration, bubbleMode: ProductConfigurationBubbleMode) => Promise<void>;
|
|
122
133
|
getApiSelection: () => AdditionalProductConfiguration;
|
|
123
134
|
setApiSelection: (s: AdditionalProductConfiguration, doValidate: boolean, productLoaderForGroupedLoad?: ProductLoader | undefined) => Promise<boolean>;
|
|
135
|
+
copyFrom: (source: _CfgProductInternal, doValidate: boolean, productLoaderForGroupedLoad?: ProductLoader | undefined) => Promise<boolean>;
|
|
136
|
+
private _setApiSelectionWithOtherProduct;
|
|
137
|
+
get syncGroupHandler(): SyncGroupsHandler | undefined;
|
|
138
|
+
get syncGroupsVerboseLogging(): boolean;
|
|
139
|
+
/**
|
|
140
|
+
* Set to true to get verbose sync state changes logged to the console.
|
|
141
|
+
*/
|
|
142
|
+
set syncGroupsVerboseLogging(v: boolean);
|
|
124
143
|
structureCompare: (other: _CfgProductInternal, strictOrder?: boolean, descriptionMatch?: boolean) => boolean;
|
|
125
144
|
tryMatchSelection: (other: _CfgProductInternal, descriptionMatch?: boolean, productLoaderForGroupedLoad?: ProductLoader | undefined) => Promise<boolean>;
|
|
126
145
|
/** Only features in selected options and selected additional products. */
|
|
@@ -143,7 +162,7 @@ export declare class CfgProduct {
|
|
|
143
162
|
static make(productLoader: ProductLoader, lang: string, catId: CatalogueParams, partNumber: string, settings?: Partial<CfgProductSettings>): Promise<CfgProduct>;
|
|
144
163
|
/**
|
|
145
164
|
* Makes an object wrapping the passed object. This is not a clone method, it is a method to
|
|
146
|
-
* make a new outer reference. Like a shallow copy
|
|
165
|
+
* make a new outer reference. Like a shallow copy. We use this to help frameworks that are
|
|
147
166
|
* build around using equals to detect change.
|
|
148
167
|
*/
|
|
149
168
|
static _makeNewRefFrom(source: _CfgProductInternal): CfgProduct;
|
package/dist/CfgProduct.js
CHANGED
|
@@ -7,18 +7,19 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
import { AggregatedLoadingObservable, compareArrays, count, Observable, toLengthUnit, } from "@configura/web-utilities";
|
|
10
|
+
import { AggregatedLoadingObservable, assert, assertDefined, augmentErrorMessage, compareArrays, count, Observable, toLengthUnit, } from "@configura/web-utilities";
|
|
11
11
|
import { CfgMeasureDefinition } from "./CfgMeasure.js";
|
|
12
12
|
import { ProductConfigurationBubbleMode } from "./productConfiguration/CfgOption.js";
|
|
13
13
|
import { CfgProductConfiguration } from "./productConfiguration/CfgProductConfiguration.js";
|
|
14
14
|
import { collectAdditionalProductRefs } from "./productConfiguration/utilitiesProductConfiguration.js";
|
|
15
15
|
import { wrapWithCache } from "./productLoader.js";
|
|
16
|
-
import {
|
|
16
|
+
import { SyncGroupsHandler } from "./syncGroups/SyncGroupsHandler.js";
|
|
17
|
+
import { comparePricesObjects, correctDefaultsOnCatalogueParams, isSameCatalogueParams, isSameProductRef, makeProductKey, } from "./utilitiesCatalogueData.js";
|
|
17
18
|
function completeSettings(incompleteSettings) {
|
|
18
|
-
var _a
|
|
19
|
+
var _a;
|
|
19
20
|
return {
|
|
20
21
|
strictSelectOneSelectionCount: (_a = incompleteSettings === null || incompleteSettings === void 0 ? void 0 : incompleteSettings.strictSelectOneSelectionCount) !== null && _a !== void 0 ? _a : false,
|
|
21
|
-
|
|
22
|
+
syncGroupsApplyMode: incompleteSettings === null || incompleteSettings === void 0 ? void 0 : incompleteSettings.syncGroupsApplyMode,
|
|
22
23
|
};
|
|
23
24
|
}
|
|
24
25
|
/**
|
|
@@ -50,7 +51,8 @@ function isDescriptionMatch(l, r) {
|
|
|
50
51
|
* the class that should be used and interacted with.
|
|
51
52
|
*/
|
|
52
53
|
export class _CfgProductInternal {
|
|
53
|
-
constructor(initSuccess, initFail, _productLoaderRaw, lang, catId, partNumber, settings, optional, selected, rootFeatureRefs, allRawFeatures, uuid, _rawUnit, _rawProductData, apiSelection, loadingObservable,
|
|
54
|
+
constructor(initSuccess, initFail, _productLoaderRaw, lang, catId, partNumber, settings, optional, selected, rootFeatureRefs, allRawFeatures, uuid, _rawUnit, _rawProductData, apiSelection, loadingObservable, parent, root, _additionalProductRef, _syncGroupHandler) {
|
|
55
|
+
var _a;
|
|
54
56
|
this._productLoaderRaw = _productLoaderRaw;
|
|
55
57
|
this.lang = lang;
|
|
56
58
|
this.catId = catId;
|
|
@@ -60,11 +62,9 @@ export class _CfgProductInternal {
|
|
|
60
62
|
this._rawUnit = _rawUnit;
|
|
61
63
|
this._rawProductData = _rawProductData;
|
|
62
64
|
this.loadingObservable = loadingObservable;
|
|
63
|
-
this.refKey = refKey;
|
|
64
|
-
this.refDescription = refDescription;
|
|
65
65
|
this.parent = parent;
|
|
66
|
-
this.
|
|
67
|
-
this.
|
|
66
|
+
this._additionalProductRef = _additionalProductRef;
|
|
67
|
+
this._syncGroupHandler = _syncGroupHandler;
|
|
68
68
|
this._destroyed = false;
|
|
69
69
|
this.additionalProducts = [];
|
|
70
70
|
this.changeObservable = new Observable();
|
|
@@ -120,6 +120,9 @@ export class _CfgProductInternal {
|
|
|
120
120
|
// The revalidate call will continue the bubble
|
|
121
121
|
yield this._revalidate(CfgProductBubbleMode.ToRootAndBubbleSelected, this._productLoaderRaw);
|
|
122
122
|
return;
|
|
123
|
+
case ProductConfigurationBubbleMode.BubbleSelected:
|
|
124
|
+
yield this._childHasChanged(CfgProductBubbleMode.ToRootAndBubbleSelected);
|
|
125
|
+
return;
|
|
123
126
|
case ProductConfigurationBubbleMode.Validate:
|
|
124
127
|
// The revalidate call will continue the bubble
|
|
125
128
|
yield this._revalidate(CfgProductBubbleMode.ToRoot, this._productLoaderRaw);
|
|
@@ -145,13 +148,27 @@ export class _CfgProductInternal {
|
|
|
145
148
|
additionalProducts: this.additionalProducts.map((additionalProduct) => additionalProduct.getApiSelection()),
|
|
146
149
|
});
|
|
147
150
|
this.setApiSelection = (s, doValidate, productLoaderForGroupedLoad) => __awaiter(this, void 0, void 0, function* () {
|
|
151
|
+
return this._setApiSelectionWithOtherProduct(s, doValidate, productLoaderForGroupedLoad, undefined);
|
|
152
|
+
});
|
|
153
|
+
this.copyFrom = (source, doValidate, productLoaderForGroupedLoad) => __awaiter(this, void 0, void 0, function* () {
|
|
154
|
+
return yield this._setApiSelectionWithOtherProduct(source.getApiSelection(), doValidate, productLoaderForGroupedLoad, source);
|
|
155
|
+
});
|
|
156
|
+
this._setApiSelectionWithOtherProduct = (s, doValidate, productLoaderForGroupedLoad, sourceProduct) => __awaiter(this, void 0, void 0, function* () {
|
|
148
157
|
// Wrap with cache will make getProduct for this function call use the same server call
|
|
149
158
|
// for the same product with the same params. Used for getProduct (when a new additional
|
|
150
159
|
// product is loaded) and postValidate.
|
|
151
160
|
productLoaderForGroupedLoad =
|
|
152
161
|
productLoaderForGroupedLoad || wrapWithCache(this._productLoaderRaw);
|
|
162
|
+
let change = false;
|
|
163
|
+
if (sourceProduct !== undefined) {
|
|
164
|
+
this._rawProductData = sourceProduct.rawProductData;
|
|
165
|
+
this.configuration._internal.populateFeatures(sourceProduct.configuration.rootFeatureRefs);
|
|
166
|
+
change = true; // We can not know if this is an actual change, so we assume it is
|
|
167
|
+
}
|
|
153
168
|
const configurationChange = yield this.configuration._internal.setApiSelection(s.selOptions, false);
|
|
154
|
-
|
|
169
|
+
if (configurationChange) {
|
|
170
|
+
change = true;
|
|
171
|
+
}
|
|
155
172
|
if (this.optional) {
|
|
156
173
|
if (yield this.setSelected(s.selected !== false, CfgProductBubbleMode.Stop)) {
|
|
157
174
|
change = true;
|
|
@@ -165,17 +182,23 @@ export class _CfgProductInternal {
|
|
|
165
182
|
if (apiSelectionAdditionalProductsCount !== additionalProductsCount) {
|
|
166
183
|
throw new Error(`Additional products are not same length. This product: "${this.key}". This product additional products count: ${additionalProductsCount}. Passed apiSelection additional products count: ${apiSelectionAdditionalProductsCount}`);
|
|
167
184
|
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
185
|
+
const sourceProductAdditionalProducts = sourceProduct === null || sourceProduct === void 0 ? void 0 : sourceProduct.additionalProducts;
|
|
186
|
+
assert(!sourceProductAdditionalProducts ||
|
|
187
|
+
additionalProductsCount === sourceProductAdditionalProducts.length, `Passed sourceProduct does not have the same number of additional products as this.`);
|
|
188
|
+
if ((yield Promise.all(apiSelectionAdditionalProducts.map((apiSelectionAdditionalProduct, index) => {
|
|
189
|
+
var _a;
|
|
190
|
+
const refKey = apiSelectionAdditionalProduct.refKey;
|
|
191
|
+
assertDefined(refKey, "Additional product api configurations must have refKey.");
|
|
173
192
|
const i = additionalProducts.findIndex((a) => refKey === a.refKey);
|
|
174
|
-
|
|
175
|
-
|
|
193
|
+
assert(i !== -1, `Additional product not found. This product: "${this.key}". refKey of not found additional product: "${refKey}"`);
|
|
194
|
+
let sourceProductAdditionalProduct = undefined;
|
|
195
|
+
if (sourceProductAdditionalProducts !== undefined) {
|
|
196
|
+
sourceProductAdditionalProduct =
|
|
197
|
+
(_a = sourceProductAdditionalProducts.find((a) => refKey === a.refKey)) === null || _a === void 0 ? void 0 : _a._internal;
|
|
198
|
+
assertDefined(sourceProductAdditionalProduct, "Additional product not found in sourceProduct");
|
|
176
199
|
}
|
|
177
200
|
const additionalProduct = additionalProducts.splice(i, 1)[0]; // Splicing like this is okay because this is done synchronous. The setCon. is what is async.
|
|
178
|
-
return additionalProduct._internal.
|
|
201
|
+
return additionalProduct._internal._setApiSelectionWithOtherProduct(apiSelectionAdditionalProduct, doValidate, productLoaderForGroupedLoad, sourceProductAdditionalProduct);
|
|
179
202
|
}))).some((b) => b)) {
|
|
180
203
|
change = true;
|
|
181
204
|
}
|
|
@@ -307,7 +330,7 @@ export class _CfgProductInternal {
|
|
|
307
330
|
return true;
|
|
308
331
|
}
|
|
309
332
|
catch (e) {
|
|
310
|
-
throw e;
|
|
333
|
+
throw augmentErrorMessage(e, "Validate product configuration request failure");
|
|
311
334
|
}
|
|
312
335
|
finally {
|
|
313
336
|
this.loadingObservable.stopChildLoading(token);
|
|
@@ -322,7 +345,14 @@ export class _CfgProductInternal {
|
|
|
322
345
|
const additionalProductRefs = [
|
|
323
346
|
...(productData.additionalProductRefs || []),
|
|
324
347
|
...collectAdditionalProductRefs(configuration),
|
|
325
|
-
]
|
|
348
|
+
]
|
|
349
|
+
.reduce((a, c) => {
|
|
350
|
+
if (a.every((p) => !isSameProductRef(p, c))) {
|
|
351
|
+
a.push(c);
|
|
352
|
+
}
|
|
353
|
+
return a;
|
|
354
|
+
}, [])
|
|
355
|
+
.map((prodRef, originalIndex) => ({
|
|
326
356
|
prodRef,
|
|
327
357
|
originalIndex,
|
|
328
358
|
}));
|
|
@@ -330,14 +360,19 @@ export class _CfgProductInternal {
|
|
|
330
360
|
let i = currentAdditionalProducts.length;
|
|
331
361
|
while (i--) {
|
|
332
362
|
const currentAdditionalProduct = currentAdditionalProducts[i];
|
|
333
|
-
const
|
|
334
|
-
|
|
363
|
+
const j = additionalProductRefs.findIndex((p) => {
|
|
364
|
+
const prodRef = p.prodRef;
|
|
365
|
+
return (prodRef.refKey === currentAdditionalProduct.refKey &&
|
|
366
|
+
prodRef.partNumber === currentAdditionalProduct.partNumber &&
|
|
367
|
+
isSameCatalogueParams(prodRef.catId, currentAdditionalProduct.catId));
|
|
368
|
+
});
|
|
335
369
|
if (j === -1) {
|
|
336
370
|
currentAdditionalProduct.destroy();
|
|
337
371
|
currentAdditionalProducts.splice(i, 1);
|
|
338
372
|
change = true;
|
|
339
373
|
}
|
|
340
374
|
else {
|
|
375
|
+
currentAdditionalProduct._internal._updateAdditionalProdRef(additionalProductRefs[j].prodRef);
|
|
341
376
|
additionalProductRefs.splice(j, 1);
|
|
342
377
|
}
|
|
343
378
|
}
|
|
@@ -350,7 +385,7 @@ export class _CfgProductInternal {
|
|
|
350
385
|
const additionalProductRef = p.prodRef;
|
|
351
386
|
return {
|
|
352
387
|
originalIndex: p.originalIndex,
|
|
353
|
-
product: CfgProduct._makeNewRefFrom(yield _CfgProductInternal.make(productLoaderRaw, productLoaderForGroupedLoad, lang, additionalProductRef.catId, additionalProductRef.partNumber, this.settings, additionalProductRef.optional === true, this.loadingObservable,
|
|
388
|
+
product: CfgProduct._makeNewRefFrom(yield _CfgProductInternal.make(productLoaderRaw, productLoaderForGroupedLoad, lang, additionalProductRef.catId, additionalProductRef.partNumber, this.settings, additionalProductRef.optional === true, this.loadingObservable, this, this.root, additionalProductRef)),
|
|
354
389
|
};
|
|
355
390
|
}))()));
|
|
356
391
|
if (this._destroyed) {
|
|
@@ -361,15 +396,12 @@ export class _CfgProductInternal {
|
|
|
361
396
|
}
|
|
362
397
|
return change;
|
|
363
398
|
}
|
|
364
|
-
catch (e) {
|
|
365
|
-
throw e;
|
|
366
|
-
}
|
|
367
399
|
finally {
|
|
368
400
|
this.loadingObservable.stopChildLoading(token);
|
|
369
401
|
}
|
|
370
402
|
});
|
|
371
|
-
this.root = root
|
|
372
|
-
this.key = makeProductKey(catId,
|
|
403
|
+
this.root = root !== null && root !== void 0 ? root : this;
|
|
404
|
+
this.key = makeProductKey(catId, (_a = _additionalProductRef === null || _additionalProductRef === void 0 ? void 0 : _additionalProductRef.refKey) !== null && _a !== void 0 ? _a : partNumber);
|
|
373
405
|
this._selected = optional ? selected : undefined;
|
|
374
406
|
this.isAdditionalProduct = parent !== undefined;
|
|
375
407
|
this._configuration = CfgProductConfiguration.make(initSuccess, initFail, rootFeatureRefs, allRawFeatures, apiSelection, this, this.root);
|
|
@@ -380,9 +412,10 @@ export class _CfgProductInternal {
|
|
|
380
412
|
clone(parent, root) {
|
|
381
413
|
return __awaiter(this, void 0, void 0, function* () {
|
|
382
414
|
const product = yield new Promise((initSuccess, initFail) => {
|
|
415
|
+
var _a;
|
|
383
416
|
const p = new _CfgProductInternal(() => {
|
|
384
417
|
initSuccess(p);
|
|
385
|
-
}, initFail, this._productLoaderRaw, this.lang, this.catId, this.partNumber, this.settings, this.optional, this.selected, this._configuration.rootFeatureRefs, this._configuration.allRawFeatures, this.uuid, this._rawUnit, this._rawProductData, this.configuration.getApiSelection(), new AggregatedLoadingObservable(),
|
|
418
|
+
}, initFail, this._productLoaderRaw, this.lang, this.catId, this.partNumber, this.settings, this.optional, this.selected, this._configuration.rootFeatureRefs, this._configuration.allRawFeatures, this.uuid, this._rawUnit, this._rawProductData, this.configuration.getApiSelection(), new AggregatedLoadingObservable(), parent, root, this._additionalProductRef, (_a = this._syncGroupHandler) === null || _a === void 0 ? void 0 : _a.clone());
|
|
386
419
|
});
|
|
387
420
|
for (const additionalProduct of this.additionalProducts) {
|
|
388
421
|
product.additionalProducts.push(CfgProduct._makeNewRefFrom(yield additionalProduct._internal.clone(product, root || product)));
|
|
@@ -390,8 +423,15 @@ export class _CfgProductInternal {
|
|
|
390
423
|
return product;
|
|
391
424
|
});
|
|
392
425
|
}
|
|
426
|
+
_updateAdditionalProdRef(p) {
|
|
427
|
+
this._additionalProductRef = p;
|
|
428
|
+
if (p.optional !== this.optional) {
|
|
429
|
+
this._selected = p.optional ? false : undefined;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
393
432
|
get description() {
|
|
394
|
-
|
|
433
|
+
var _a, _b;
|
|
434
|
+
return (_b = (_a = this._additionalProductRef) === null || _a === void 0 ? void 0 : _a.refDescription) !== null && _b !== void 0 ? _b : this._rawProductData.description;
|
|
395
435
|
}
|
|
396
436
|
get rootNodeSources() {
|
|
397
437
|
return this._rawProductData.models;
|
|
@@ -417,6 +457,18 @@ export class _CfgProductInternal {
|
|
|
417
457
|
}
|
|
418
458
|
return this._measureDefinitions;
|
|
419
459
|
}
|
|
460
|
+
get refKey() {
|
|
461
|
+
var _a;
|
|
462
|
+
return (_a = this._additionalProductRef) === null || _a === void 0 ? void 0 : _a.refKey;
|
|
463
|
+
}
|
|
464
|
+
get transform() {
|
|
465
|
+
var _a;
|
|
466
|
+
return (_a = this._additionalProductRef) === null || _a === void 0 ? void 0 : _a.transform;
|
|
467
|
+
}
|
|
468
|
+
get anchor() {
|
|
469
|
+
var _a;
|
|
470
|
+
return (_a = this._additionalProductRef) === null || _a === void 0 ? void 0 : _a.anchor;
|
|
471
|
+
}
|
|
420
472
|
/** @throws an error if the actual unit sent by the server was not a LengthUnit */
|
|
421
473
|
get unit() {
|
|
422
474
|
if (this._unit === undefined) {
|
|
@@ -494,26 +546,53 @@ export class _CfgProductInternal {
|
|
|
494
546
|
? this.visibleIfAdditionalProduct
|
|
495
547
|
: this.visibleIfMainProduct;
|
|
496
548
|
}
|
|
549
|
+
get syncGroupHandler() {
|
|
550
|
+
return this.root._syncGroupHandler;
|
|
551
|
+
}
|
|
552
|
+
get syncGroupsVerboseLogging() {
|
|
553
|
+
var _a, _b;
|
|
554
|
+
return (_b = (_a = this.syncGroupHandler) === null || _a === void 0 ? void 0 : _a.verboseLogging) !== null && _b !== void 0 ? _b : false;
|
|
555
|
+
}
|
|
556
|
+
/**
|
|
557
|
+
* Set to true to get verbose sync state changes logged to the console.
|
|
558
|
+
*/
|
|
559
|
+
set syncGroupsVerboseLogging(v) {
|
|
560
|
+
const syncGroupHandler = this.syncGroupHandler;
|
|
561
|
+
if (syncGroupHandler === undefined) {
|
|
562
|
+
throw new Error("No syncGroupHandler, so can not change log verbosity");
|
|
563
|
+
}
|
|
564
|
+
syncGroupHandler.verboseLogging = v;
|
|
565
|
+
}
|
|
497
566
|
}
|
|
498
567
|
_CfgProductInternal.make = (productLoaderRaw, productLoaderForGroupedLoad, // Used when instantiating the current product
|
|
499
|
-
lang, catId, partNumber, settings, optional, loadingObservable,
|
|
568
|
+
lang, catId, partNumber, settings, optional, loadingObservable, parent, root, additionalProductRef) => __awaiter(void 0, void 0, void 0, function* () {
|
|
500
569
|
// Wrap with cache will make getProduct for this function call use the same server call
|
|
501
570
|
// for the same product with the same params. Not retained for future calls, only used
|
|
502
571
|
// at this initial load.
|
|
503
572
|
productLoaderForGroupedLoad =
|
|
504
573
|
productLoaderForGroupedLoad || wrapWithCache(productLoaderRaw);
|
|
505
|
-
const
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
574
|
+
const syncGroupHandler = root === undefined
|
|
575
|
+
? SyncGroupsHandler.make(settings.syncGroupsApplyMode, loadingObservable)
|
|
576
|
+
: undefined;
|
|
577
|
+
try {
|
|
578
|
+
const productResponse = yield productLoaderForGroupedLoad.getProduct(Object.assign(Object.assign({ lang }, correctDefaultsOnCatalogueParams(catId)), { partNumber }));
|
|
579
|
+
const { productData, rootFeatureRefs, features: allRawFeatures, uuid, unit, } = productResponse;
|
|
580
|
+
const product = yield new Promise((initSuccess, initFail) => {
|
|
581
|
+
const p = new _CfgProductInternal(() => {
|
|
582
|
+
// We absolutely do not want anyone to assign to this._configuration. So we want that field private.
|
|
583
|
+
// But we can not set the api selection synchronously. And the product configuration needs "this". So we use this callback.
|
|
584
|
+
// Feel free to find a nicer more readable solution :)
|
|
585
|
+
initSuccess(p);
|
|
586
|
+
}, initFail, productLoaderRaw, lang, catId, partNumber, settings, optional, !optional, rootFeatureRefs, allRawFeatures, uuid, unit, productData, productData.partsData.selOptions || [], loadingObservable, parent, root, additionalProductRef, syncGroupHandler);
|
|
587
|
+
});
|
|
588
|
+
yield product._syncAndLoadAdditionalProducts(productLoaderForGroupedLoad);
|
|
589
|
+
// Product is guaranteed to be root
|
|
590
|
+
yield (syncGroupHandler === null || syncGroupHandler === void 0 ? void 0 : syncGroupHandler.init(product, productLoaderForGroupedLoad));
|
|
591
|
+
return product;
|
|
592
|
+
}
|
|
593
|
+
catch (e) {
|
|
594
|
+
throw augmentErrorMessage(e, "Load product request failure");
|
|
595
|
+
}
|
|
517
596
|
});
|
|
518
597
|
export class CfgProduct {
|
|
519
598
|
constructor(_internal) {
|
|
@@ -563,12 +642,12 @@ export class CfgProduct {
|
|
|
563
642
|
}
|
|
564
643
|
static make(productLoader, lang, catId, partNumber, settings) {
|
|
565
644
|
return __awaiter(this, void 0, void 0, function* () {
|
|
566
|
-
return this._makeNewRefFrom(yield _CfgProductInternal.make(productLoader, undefined, lang, catId, partNumber, completeSettings(settings), false, new AggregatedLoadingObservable(), undefined, undefined, undefined
|
|
645
|
+
return this._makeNewRefFrom(yield _CfgProductInternal.make(productLoader, undefined, lang, catId, partNumber, completeSettings(settings), false, new AggregatedLoadingObservable(), undefined, undefined, undefined));
|
|
567
646
|
});
|
|
568
647
|
}
|
|
569
648
|
/**
|
|
570
649
|
* Makes an object wrapping the passed object. This is not a clone method, it is a method to
|
|
571
|
-
* make a new outer reference. Like a shallow copy
|
|
650
|
+
* make a new outer reference. Like a shallow copy. We use this to help frameworks that are
|
|
572
651
|
* build around using equals to detect change.
|
|
573
652
|
*/
|
|
574
653
|
static _makeNewRefFrom(source) {
|
package/dist/index.d.ts
CHANGED
|
@@ -11,6 +11,8 @@ export * from "./productConfiguration/CfgProductConfiguration.js";
|
|
|
11
11
|
export * from "./productConfiguration/filters.js";
|
|
12
12
|
export * from "./productConfiguration/productParamsGenerator.js";
|
|
13
13
|
export * from "./productLoader.js";
|
|
14
|
+
export * from "./syncGroups/SyncGroupsApplyMode.js";
|
|
15
|
+
export * from "./syncGroups/SyncGroupsHandler.js";
|
|
14
16
|
export * from "./tasks/formats.js";
|
|
15
17
|
export * from "./tasks/TaskHandler.js";
|
|
16
18
|
export * from "./utilitiesCatalogueData.js";
|
package/dist/index.js
CHANGED
|
@@ -11,6 +11,8 @@ export * from "./productConfiguration/CfgProductConfiguration.js";
|
|
|
11
11
|
export * from "./productConfiguration/filters.js";
|
|
12
12
|
export * from "./productConfiguration/productParamsGenerator.js";
|
|
13
13
|
export * from "./productLoader.js";
|
|
14
|
+
export * from "./syncGroups/SyncGroupsApplyMode.js";
|
|
15
|
+
export * from "./syncGroups/SyncGroupsHandler.js";
|
|
14
16
|
export * from "./tasks/formats.js";
|
|
15
17
|
export * from "./tasks/TaskHandler.js";
|
|
16
18
|
export * from "./utilitiesCatalogueData.js";
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { LengthUnit, Observable, SingleArgCallback } from "@configura/web-utilities";
|
|
2
|
-
import { Feature, SelectedOption } from "../CatalogueAPI.js";
|
|
2
|
+
import { Feature, SelectedOption, SyncGroup, SyncGroupMethods } from "../CatalogueAPI.js";
|
|
3
3
|
import { CfgProduct, _CfgProductInternal } from "../CfgProduct.js";
|
|
4
4
|
import { CfgMtrlApplication } from "../material/CfgMtrlApplication.js";
|
|
5
|
+
import { SyncCode } from "../syncGroups/SyncGroupsHandler.js";
|
|
5
6
|
import { CfgOption, ProductConfigurationBubbleMode, _CfgOptionInternal } from "./CfgOption.js";
|
|
6
7
|
import { _CfgProductConfigurationInternal } from "./CfgProductConfiguration.js";
|
|
7
8
|
export declare enum SelectionType {
|
|
@@ -50,6 +51,14 @@ export declare class _CfgFeatureInternal {
|
|
|
50
51
|
get numericValue(): number | undefined;
|
|
51
52
|
setNumericValue: (val: number) => Promise<boolean>;
|
|
52
53
|
get description(): string;
|
|
54
|
+
get syncGroup(): SyncGroup | undefined;
|
|
55
|
+
/**
|
|
56
|
+
* @return one of the following, in order:
|
|
57
|
+
* - undefined if the Feature lacks a syncGroup.
|
|
58
|
+
* - false if the syncGroup doesn't fulfill the optional mustSupport requirement.
|
|
59
|
+
* - syncCode from the syncGroup.
|
|
60
|
+
*/
|
|
61
|
+
getSyncCode(mustSupport?: SyncGroupMethods): undefined | false | SyncCode;
|
|
53
62
|
/**
|
|
54
63
|
* The MeasureParam class is re-used for different purposes. In Features it is used
|
|
55
64
|
* to indicate which stretch measures inside Models shall be affected by this state
|
|
@@ -100,8 +109,9 @@ export declare class _CfgFeatureInternal {
|
|
|
100
109
|
structureCompare: (other: _CfgFeatureInternal, strictOrder?: boolean, descriptionMatch?: boolean) => boolean;
|
|
101
110
|
tryMatchSelection: (other: _CfgFeatureInternal, descriptionMatch?: boolean) => Promise<boolean>;
|
|
102
111
|
/**
|
|
103
|
-
* Normally this is used through methods on CfgFeature and CfgOption. Use this
|
|
104
|
-
*
|
|
112
|
+
* Normally this is used through methods on CfgFeature and CfgOption. Use this internal version
|
|
113
|
+
* if you need to control the bubbleMode.
|
|
114
|
+
*
|
|
105
115
|
* Using a validate bubbleMode will cause validation calls to the server.
|
|
106
116
|
*/
|
|
107
117
|
selectOption: (optionInternal: _CfgOptionInternal, on: boolean, bubbleMode: ProductConfigurationBubbleMode) => Promise<boolean>;
|