@configura/web-api 2.0.0-alpha.14 → 2.0.0-alpha.15

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.
@@ -1,3 +1,8 @@
1
+ /** AdditionalProductConf */
2
+ export interface DtoAdditionalProductConf extends DtoProductConf {
3
+ refKey: string;
4
+ selected: boolean;
5
+ }
1
6
  /** AdditionalProductConfiguration */
2
7
  export interface DtoAdditionalProductConfiguration {
3
8
  refKey?: string;
@@ -5,11 +10,6 @@ export interface DtoAdditionalProductConfiguration {
5
10
  selOptions: Array<DtoSelectedOption>;
6
11
  additionalProducts?: Array<DtoAdditionalProductConfiguration>;
7
12
  }
8
- /** AdditionalProductConfigurationV2 */
9
- export interface DtoAdditionalProductConfigurationV2 extends DtoProductConfiguration {
10
- refKey: string;
11
- selected: boolean;
12
- }
13
13
  /** AdditionalProductRef */
14
14
  export interface DtoAdditionalProductRef {
15
15
  refKey: string;
@@ -52,7 +52,7 @@ export interface DtoCatalogueParams extends DtoCatalogueParamsWithoutCid {
52
52
  export interface DtoCatalogueParamsWithLang extends DtoCatalogueParams {
53
53
  lang: string;
54
54
  }
55
- /** CatalogueParamsWithoutCid */
55
+ /** CatalogueParamsWithoutCid - To identify one catalogue the Portfolio ID CID is needed in addition to the parameters in this object. However as of now CID is not used in API calls and therefore this version without CID is needed. */
56
56
  export interface DtoCatalogueParamsWithoutCid {
57
57
  enterprise: string;
58
58
  prdCat: string;
@@ -127,12 +127,12 @@ export interface DtoFeature {
127
127
  syncGroup?: DtoSyncGroup;
128
128
  unit?: string;
129
129
  }
130
- /** FeatureConfiguration */
131
- export interface DtoFeatureConfiguration {
130
+ /** FeatureConf */
131
+ export interface DtoFeatureConf {
132
132
  code: string;
133
133
  groupCode?: string;
134
134
  unit?: string;
135
- options?: Array<DtoOptionConfiguration>;
135
+ options?: Array<DtoOptionConf>;
136
136
  }
137
137
  /** FeatureRef */
138
138
  export interface DtoFeatureRef {
@@ -248,12 +248,12 @@ export interface DtoOption {
248
248
  upcharge?: number;
249
249
  priceCodes?: Array<string>;
250
250
  }
251
- /** OptionConfiguration */
252
- export interface DtoOptionConfiguration {
251
+ /** OptionConf */
252
+ export interface DtoOptionConf {
253
253
  code: string;
254
254
  selected: boolean;
255
255
  numericValue?: DtoValueWithUnit;
256
- features?: Array<DtoFeatureConfiguration>;
256
+ features?: Array<DtoFeatureConf>;
257
257
  }
258
258
  /** Orientation */
259
259
  export interface DtoOrientation {
@@ -353,10 +353,10 @@ export interface DtoProductCatalogueInfo {
353
353
  exchangeRate: number;
354
354
  lastModified: string;
355
355
  }
356
- /** ProductConfiguration */
357
- export interface DtoProductConfiguration {
358
- features?: Array<DtoFeatureConfiguration>;
359
- additionalProducts?: Array<DtoAdditionalProductConfigurationV2>;
356
+ /** ProductConf - This is intended to eventually supersede AdditionalProductConfiguration as the format for sending/receiving how a Product is configured. */
357
+ export interface DtoProductConf {
358
+ features?: Array<DtoFeatureConf>;
359
+ additionalProducts?: Array<DtoAdditionalProductConf>;
360
360
  prodParams?: DtoProductParamsWithLang;
361
361
  }
362
362
  /** ProductData */
@@ -1,5 +1,5 @@
1
1
  import { AggregatedLoadingObservable, LengthUnit, Observable, SingleArgCallback } from "@configura/web-utilities";
2
- import { DtoAdditionalProductConfiguration, DtoAdditionalProductRef, DtoCatalogueParams, DtoMeasureParam, DtoMtrlApplication, DtoPrices, DtoProductConfiguration, DtoProductParamsWithLang, DtoTransform } from "./CatalogueAPI.js";
2
+ import { DtoAdditionalProductConfiguration, DtoAdditionalProductRef, DtoCatalogueParams, DtoMeasureParam, DtoMtrlApplication, DtoPrices, DtoProductConf, DtoProductParamsWithLang, DtoTransform } 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";
@@ -93,7 +93,13 @@ export declare class _CfgProductInternal {
93
93
  get selected(): boolean;
94
94
  readonly isAdditionalProduct: boolean;
95
95
  clone(parent?: _CfgProductInternal, root?: _CfgProductInternal): Promise<_CfgProductInternal>;
96
+ /** Mark this and its descendants as destroyed and remove all listeners */
96
97
  destroy: () => void;
98
+ /**
99
+ * Internal use. Used when this product is an additional product, and
100
+ * changing a parent product has made the settings for this product
101
+ * change.
102
+ */
97
103
  _updateAdditionalProdRef(p: DtoAdditionalProductRef): void;
98
104
  get description(): string | undefined;
99
105
  get rootNodeSources(): RootNodeSource[] | undefined;
@@ -136,8 +142,8 @@ export declare class _CfgProductInternal {
136
142
  _additionalProductHasChanged: (freshRef: CfgProduct, bubbleMode: CfgProductBubbleMode, committed: boolean) => Promise<void>;
137
143
  /** Called by the configuration to tell its parent that it has changed. */
138
144
  _configurationHasChanged: (freshRef: CfgProductConfiguration, bubbleMode: ProductConfigurationBubbleMode, committed: boolean) => Promise<void>;
139
- getDtoConfiguration: (includeExtendedData: boolean, includeProductParams: boolean) => DtoProductConfiguration;
140
- setDtoConfiguration: (s: DtoProductConfiguration, doValidate: boolean, productLoaderForGroupedLoad?: ProductLoader | undefined) => Promise<boolean>;
145
+ getDtoConf: (includeExtendedData: boolean, includeProductParams: boolean) => DtoProductConf;
146
+ setDtoConf: (s: DtoProductConf, doValidate: boolean, productLoaderForGroupedLoad?: ProductLoader | undefined) => Promise<boolean>;
141
147
  setApiSelection: (s: DtoAdditionalProductConfiguration, doValidate: boolean, productLoaderForGroupedLoad?: ProductLoader | undefined) => Promise<boolean>;
142
148
  copyFrom: (source: _CfgProductInternal, doValidate: boolean, productLoaderForGroupedLoad?: ProductLoader | undefined) => Promise<boolean>;
143
149
  private _setApiSelectionWithOtherProduct;
@@ -254,11 +260,43 @@ export declare class CfgProduct {
254
260
  * Gets what selections has been made on the product, recursively including product
255
261
  * configuration, optional products and additional products. Used when a full view of all
256
262
  * selections on a product is needed, such as when doing Render or Export.
263
+ * @deprecated getDtoConf provides a newer format.
264
+ * @see getDtoConf
257
265
  */
258
266
  getApiSelection: () => DtoAdditionalProductConfiguration;
259
- getDtoConfiguration: (includeExtendedData?: boolean, includeProductParams?: boolean) => DtoProductConfiguration;
260
- setDtoConfiguration: (s: DtoProductConfiguration, doValidate?: boolean) => Promise<boolean>;
261
- setApiSelection: (s: DtoAdditionalProductConfiguration, doValidate?: boolean) => Promise<boolean>;
267
+ /**
268
+ * Applies the configuration (selections) in the passed object onto the product recursively
269
+ * including product configuration, optional products and additional products.
270
+ * @param doValidate Makes a server side validation call. These are necessary to ensure that
271
+ * the right models are loaded.
272
+ * @deprecated setDtoConf uses a newer format.
273
+ */
274
+ setApiSelection: (configuration: DtoAdditionalProductConfiguration, doValidate?: boolean) => Promise<boolean>;
275
+ /**
276
+ * A newer alternative version of getApiSelection. This returns the configuration (selections)
277
+ * on the product, recursively including product configuration, optional products and additional
278
+ * products.
279
+ * This version has the following advantages over getApiSelection:
280
+ * - The format is clearer, designed to be readable
281
+ * - Makes less assumptions about the structure in the Product being unchanging over time. In
282
+ * particular, the Feature codes are included in the data, so that changes to what Features
283
+ * are used in a Product is less likely to lead to unexpected results.
284
+ * - You can request ExtendedData and/or ProductParams to be included in the result. This extra
285
+ * data is ignored when passed back into the API, but it can be very useful for external
286
+ * applications.
287
+ * The other version (getApiSelection) has the advantage of using a format directly compatible with the API:s.
288
+ * @param includeExtendedData Includes extra data which is not an actual part of the configuration,
289
+ * i.e. units and groupCodes
290
+ * @param includeProductParams Includes what Product this was generated for, and the same for any
291
+ * Additional Products.
292
+ */
293
+ getDtoConf: (includeExtendedData?: boolean, includeProductParams?: boolean) => DtoProductConf;
294
+ /**
295
+ * A newer alternative version of setApiSelection.
296
+ * @param doValidate Makes a server side validation call. These are necessary to ensure that
297
+ * the right models are loaded.
298
+ */
299
+ setDtoConf: (configuration: DtoProductConf, doValidate?: boolean) => Promise<boolean>;
262
300
  listenForChange: (l: SingleArgCallback<CfgProductChangeNotification>) => void;
263
301
  stopListenForChange: (l: SingleArgCallback<CfgProductChangeNotification>) => void;
264
302
  stopAllListenForChange: () => void;
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  };
10
10
  import { AggregatedLoadingObservable, assert, assertDefined, augmentErrorMessage, compareArrays, count, Observable, toLengthUnit, } from "@configura/web-utilities";
11
11
  import { CfgMeasureDefinition } from "./CfgMeasure.js";
12
- import { convertDtoProductConfigurationToV1 } from "./ConfigurationConverter.js";
12
+ import { convertDtoProductConfToV1 } from "./ConfigurationConverter.js";
13
13
  import { ProductConfigurationBubbleMode } from "./productConfiguration/CfgOption.js";
14
14
  import { CfgProductConfiguration } from "./productConfiguration/CfgProductConfiguration.js";
15
15
  import { collectAdditionalProductRefs } from "./productConfiguration/utilitiesProductConfiguration.js";
@@ -67,11 +67,13 @@ export class _CfgProductInternal {
67
67
  this._destroyed = false;
68
68
  this.additionalProducts = [];
69
69
  this.changeObservable = new Observable();
70
+ /** Mark this and its descendants as destroyed and remove all listeners */
70
71
  this.destroy = () => {
72
+ var _a;
71
73
  this._destroyed = true;
72
74
  this.changeObservable.stopAllListen();
73
75
  this.configuration.stopAllListenForChange();
74
- for (const additionalProduct of this.additionalProducts || []) {
76
+ for (const additionalProduct of (_a = this.additionalProducts) !== null && _a !== void 0 ? _a : []) {
75
77
  additionalProduct.destroy();
76
78
  }
77
79
  };
@@ -140,9 +142,9 @@ export class _CfgProductInternal {
140
142
  return;
141
143
  }
142
144
  });
143
- this.getDtoConfiguration = (includeExtendedData, includeProductParams) => {
145
+ this.getDtoConf = (includeExtendedData, includeProductParams) => {
144
146
  const conf = {};
145
- const features = this.configuration._internal.getDtoConfiguration(includeExtendedData);
147
+ const features = this.configuration._internal.getDtoConf(includeExtendedData);
146
148
  if (0 < features.length) {
147
149
  conf.features = features;
148
150
  }
@@ -151,7 +153,7 @@ export class _CfgProductInternal {
151
153
  }
152
154
  const additionalProducts = this.additionalProducts;
153
155
  if (0 < additionalProducts.length) {
154
- conf.additionalProducts = additionalProducts.map((p) => p._internal.getDtoConfiguration(includeExtendedData, includeProductParams));
156
+ conf.additionalProducts = additionalProducts.map((p) => p._internal.getDtoConf(includeExtendedData, includeProductParams));
155
157
  }
156
158
  if (this.isAdditionalProduct) {
157
159
  const refKey = this.refKey;
@@ -164,14 +166,14 @@ export class _CfgProductInternal {
164
166
  }
165
167
  return conf;
166
168
  };
167
- this.setDtoConfiguration = (s, doValidate, productLoaderForGroupedLoad) => __awaiter(this, void 0, void 0, function* () {
168
- return yield this.setApiSelection(convertDtoProductConfigurationToV1(s), doValidate, productLoaderForGroupedLoad);
169
+ this.setDtoConf = (s, doValidate, productLoaderForGroupedLoad) => __awaiter(this, void 0, void 0, function* () {
170
+ return yield this.setApiSelection(convertDtoProductConfToV1(s), doValidate, productLoaderForGroupedLoad);
169
171
  });
170
172
  this.setApiSelection = (s, doValidate, productLoaderForGroupedLoad) => __awaiter(this, void 0, void 0, function* () {
171
173
  return yield this._setApiSelectionWithOtherProduct(s, doValidate, productLoaderForGroupedLoad, undefined);
172
174
  });
173
175
  this.copyFrom = (source, doValidate, productLoaderForGroupedLoad) => __awaiter(this, void 0, void 0, function* () {
174
- return yield this._setApiSelectionWithOtherProduct(convertDtoProductConfigurationToV1(source.getDtoConfiguration(false, false)), doValidate, productLoaderForGroupedLoad, source);
176
+ return yield this._setApiSelectionWithOtherProduct(convertDtoProductConfToV1(source.getDtoConf(false, false)), doValidate, productLoaderForGroupedLoad, source);
175
177
  });
176
178
  this._setApiSelectionWithOtherProduct = (s, doValidate, productLoaderForGroupedLoad, sourceProduct) => __awaiter(this, void 0, void 0, function* () {
177
179
  // Wrap with cache will make getProduct for this function call use the same server call
@@ -312,7 +314,7 @@ export class _CfgProductInternal {
312
314
  const token = this.loadingObservable.startChildLoading();
313
315
  this._revalidateInProgressToken = token;
314
316
  try {
315
- const response = yield productLoader.postValidate(correctDefaultsOnCatalogueParams(this.prodParams), { selOptions: configuration.getApiSelection() });
317
+ const response = yield productLoader.postValidate(correctDefaultsOnCatalogueParams(this.prodParams), { selOptions: configuration._internal.getApiSelection() });
316
318
  // The revalidateInProgressToken is used to know if some other revalidate
317
319
  // call has happened after this call, thereby making this call obsolete.
318
320
  // This is a bit crude in that it does not actually cancel previous validate
@@ -350,7 +352,7 @@ export class _CfgProductInternal {
350
352
  return true;
351
353
  }
352
354
  catch (e) {
353
- throw augmentErrorMessage(e, "Validate product configuration request failure");
355
+ throw augmentErrorMessage(e, `Validate product configuration request (${this.prodParams.partNumber}) failure`);
354
356
  }
355
357
  finally {
356
358
  this.loadingObservable.stopChildLoading(token);
@@ -435,7 +437,7 @@ export class _CfgProductInternal {
435
437
  var _a;
436
438
  const p = new _CfgProductInternal(() => {
437
439
  initSuccess(p);
438
- }, initFail, this._productLoaderRaw, this.prodParams, 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());
440
+ }, initFail, this._productLoaderRaw, this.prodParams, this.settings, this.optional, this.selected, this._configuration.rootFeatureRefs, this._configuration.allRawFeatures, this.uuid, this._rawUnit, this._rawProductData, this.configuration._internal.getApiSelection(), new AggregatedLoadingObservable(), parent, root, this._additionalProductRef, (_a = this._syncGroupHandler) === null || _a === void 0 ? void 0 : _a.clone());
439
441
  });
440
442
  for (const additionalProduct of this.additionalProducts) {
441
443
  product.additionalProducts.push(CfgProduct._makeNewRefFrom(yield additionalProduct._internal.clone(product, root || product)));
@@ -443,6 +445,11 @@ export class _CfgProductInternal {
443
445
  return product;
444
446
  });
445
447
  }
448
+ /**
449
+ * Internal use. Used when this product is an additional product, and
450
+ * changing a parent product has made the settings for this product
451
+ * change.
452
+ */
446
453
  _updateAdditionalProdRef(p) {
447
454
  this._additionalProductRef = p;
448
455
  if (p.optional !== this.optional) {
@@ -611,7 +618,7 @@ prodParams, settings, optional, loadingObservable, parent, root, additionalProdu
611
618
  return product;
612
619
  }
613
620
  catch (e) {
614
- throw augmentErrorMessage(e, "Load product request failure");
621
+ throw augmentErrorMessage(e, `Load product request (${prodParams.partNumber}) failure`);
615
622
  }
616
623
  });
617
624
  export class CfgProduct {
@@ -650,11 +657,43 @@ export class CfgProduct {
650
657
  * Gets what selections has been made on the product, recursively including product
651
658
  * configuration, optional products and additional products. Used when a full view of all
652
659
  * selections on a product is needed, such as when doing Render or Export.
660
+ * @deprecated getDtoConf provides a newer format.
661
+ * @see getDtoConf
662
+ */
663
+ this.getApiSelection = () => convertDtoProductConfToV1(this._internal.getDtoConf(false, false), true);
664
+ /**
665
+ * Applies the configuration (selections) in the passed object onto the product recursively
666
+ * including product configuration, optional products and additional products.
667
+ * @param doValidate Makes a server side validation call. These are necessary to ensure that
668
+ * the right models are loaded.
669
+ * @deprecated setDtoConf uses a newer format.
670
+ */
671
+ this.setApiSelection = (configuration, doValidate = true) => __awaiter(this, void 0, void 0, function* () { return yield this._internal.setApiSelection(configuration, doValidate); });
672
+ /**
673
+ * A newer alternative version of getApiSelection. This returns the configuration (selections)
674
+ * on the product, recursively including product configuration, optional products and additional
675
+ * products.
676
+ * This version has the following advantages over getApiSelection:
677
+ * - The format is clearer, designed to be readable
678
+ * - Makes less assumptions about the structure in the Product being unchanging over time. In
679
+ * particular, the Feature codes are included in the data, so that changes to what Features
680
+ * are used in a Product is less likely to lead to unexpected results.
681
+ * - You can request ExtendedData and/or ProductParams to be included in the result. This extra
682
+ * data is ignored when passed back into the API, but it can be very useful for external
683
+ * applications.
684
+ * The other version (getApiSelection) has the advantage of using a format directly compatible with the API:s.
685
+ * @param includeExtendedData Includes extra data which is not an actual part of the configuration,
686
+ * i.e. units and groupCodes
687
+ * @param includeProductParams Includes what Product this was generated for, and the same for any
688
+ * Additional Products.
689
+ */
690
+ this.getDtoConf = (includeExtendedData = false, includeProductParams = false) => this._internal.getDtoConf(includeExtendedData, includeProductParams);
691
+ /**
692
+ * A newer alternative version of setApiSelection.
693
+ * @param doValidate Makes a server side validation call. These are necessary to ensure that
694
+ * the right models are loaded.
653
695
  */
654
- this.getApiSelection = () => convertDtoProductConfigurationToV1(this._internal.getDtoConfiguration(false, false), true);
655
- this.getDtoConfiguration = (includeExtendedData = false, includeProductParams = false) => this._internal.getDtoConfiguration(includeExtendedData, includeProductParams);
656
- this.setDtoConfiguration = (s, doValidate = true) => __awaiter(this, void 0, void 0, function* () { return yield this._internal.setDtoConfiguration(s, doValidate); });
657
- this.setApiSelection = (s, doValidate = true) => __awaiter(this, void 0, void 0, function* () { return yield this._internal.setApiSelection(s, doValidate); });
696
+ this.setDtoConf = (configuration, doValidate = true) => __awaiter(this, void 0, void 0, function* () { return yield this._internal.setDtoConf(configuration, doValidate); });
658
697
  this.listenForChange = (l) => this._internal.changeObservable.listen(l);
659
698
  this.stopListenForChange = (l) => this._internal.changeObservable.stopListen(l);
660
699
  this.stopAllListenForChange = () => this._internal.changeObservable.stopAllListen();
@@ -1,14 +1,14 @@
1
- import { DtoAdditionalProductConfiguration, DtoAdditionalProductConfigurationV2, DtoFeatureConfiguration, DtoProductConfiguration, DtoSelectedOption } from "./CatalogueAPI.js";
2
- export declare const isDtoProductConfigurationAdditional: (value: DtoProductConfiguration) => value is DtoAdditionalProductConfigurationV2;
3
- export declare const convertDtoProductConfigurationToV1: (conf: DtoProductConfiguration, silenceWarnings?: boolean) => DtoAdditionalProductConfiguration;
4
- export declare const convertDtoFeatureConfigurationsToSelOptions: (features: DtoFeatureConfiguration[], silenceWarnings?: boolean) => DtoSelectedOption[];
1
+ import { DtoAdditionalProductConf, DtoAdditionalProductConfiguration, DtoFeatureConf, DtoProductConf, DtoSelectedOption } from "./CatalogueAPI.js";
2
+ export declare const isDtoProductConfAdditional: (value: DtoProductConf) => value is DtoAdditionalProductConf;
3
+ export declare const convertDtoProductConfToV1: (conf: DtoProductConf, silenceWarnings?: boolean) => DtoAdditionalProductConfiguration;
4
+ export declare const convertDtoFeatureConfsToSelOptions: (features: DtoFeatureConf[], silenceWarnings?: boolean) => DtoSelectedOption[];
5
5
  /**
6
6
  * Serializes and compacts the configuration into a format especially suited for URLs
7
7
  */
8
- export declare const dtoProductConfigurationToCompactString: (conf: DtoProductConfiguration) => string;
8
+ export declare const dtoProductConfigurationToCompactString: (conf: DtoProductConf) => string;
9
9
  /**
10
10
  * Deserializes and inflates the configuration from the compacted format
11
11
  */
12
- export declare const compactStringToDtoProductConfiguration: (versionAndConf: string) => DtoProductConfiguration;
13
- export declare const stripExtendedDataFromDtoProductConfiguration: (conf: DtoProductConfiguration) => DtoProductConfiguration;
12
+ export declare const compactStringToDtoProductConf: (versionAndConf: string) => DtoProductConf;
13
+ export declare const stripExtendedDataFromDtoProductConf: (conf: DtoProductConf) => DtoProductConf;
14
14
  //# sourceMappingURL=ConfigurationConverter.d.ts.map
@@ -1,33 +1,33 @@
1
- export const isDtoProductConfigurationAdditional = (value) => "refKey" in value;
1
+ export const isDtoProductConfAdditional = (value) => "refKey" in value;
2
2
  // As this has potential to flood the terminal we only inform once
3
3
  let hasInformedAboutProdParams = false;
4
4
  let hasInformedAboutGroupCode = false;
5
5
  let hasInformedAboutUnit = false;
6
- export const convertDtoProductConfigurationToV1 = (conf, silenceWarnings = false) => {
6
+ export const convertDtoProductConfToV1 = (conf, silenceWarnings = false) => {
7
7
  var _a, _b;
8
8
  if (!silenceWarnings && conf.prodParams !== undefined && !hasInformedAboutProdParams) {
9
9
  hasInformedAboutProdParams = true;
10
- console.info("Incoming DtoProductConfiguration contains prodParams. These will be ignored.");
10
+ console.info("Incoming DtoProductConf contains prodParams. These will be ignored.");
11
11
  }
12
12
  const result = {
13
13
  selOptions: ((_a = conf.features) !== null && _a !== void 0 ? _a : []).map((f) => ({
14
14
  code: "!~!",
15
- next: convertDtoFeatureConfigurationToApiSelection(f, silenceWarnings),
15
+ next: convertDtoFeatureConfToApiSelection(f, silenceWarnings),
16
16
  })),
17
- additionalProducts: ((_b = conf.additionalProducts) !== null && _b !== void 0 ? _b : []).map((p) => convertDtoProductConfigurationToV1(p, silenceWarnings)),
17
+ additionalProducts: ((_b = conf.additionalProducts) !== null && _b !== void 0 ? _b : []).map((p) => convertDtoProductConfToV1(p, silenceWarnings)),
18
18
  selected: true,
19
19
  };
20
- if (isDtoProductConfigurationAdditional(conf)) {
20
+ if (isDtoProductConfAdditional(conf)) {
21
21
  result.refKey = conf.refKey;
22
22
  result.selected = conf.selected;
23
23
  }
24
24
  return result;
25
25
  };
26
- export const convertDtoFeatureConfigurationsToSelOptions = (features, silenceWarnings = false) => (features !== null && features !== void 0 ? features : []).map((f) => ({
26
+ export const convertDtoFeatureConfsToSelOptions = (features, silenceWarnings = false) => (features !== null && features !== void 0 ? features : []).map((f) => ({
27
27
  code: "!~!",
28
- next: convertDtoFeatureConfigurationToApiSelection(f, silenceWarnings),
28
+ next: convertDtoFeatureConfToApiSelection(f, silenceWarnings),
29
29
  }));
30
- const convertDtoFeatureConfigurationToApiSelection = (feature, silenceWarnings) => {
30
+ const convertDtoFeatureConfToApiSelection = (feature, silenceWarnings) => {
31
31
  const { groupCode, options, unit } = feature;
32
32
  if (!silenceWarnings && groupCode !== undefined && !hasInformedAboutGroupCode) {
33
33
  hasInformedAboutGroupCode = true;
@@ -39,13 +39,13 @@ const convertDtoFeatureConfigurationToApiSelection = (feature, silenceWarnings)
39
39
  }
40
40
  const result = {};
41
41
  for (const option of (options !== null && options !== void 0 ? options : []).filter((o) => o.selected)) {
42
- result[option.code] = convertDtoOptionConfigurationToSelectedOption(option, silenceWarnings);
42
+ result[option.code] = convertDtoOptionConfToSelectedOption(option, silenceWarnings);
43
43
  }
44
44
  return result;
45
45
  };
46
- const convertDtoOptionConfigurationToSelectedOption = (option, silenceWarnings) => {
46
+ const convertDtoOptionConfToSelectedOption = (option, silenceWarnings) => {
47
47
  const { features, code, numericValue } = option;
48
- const selectionTrees = (features !== null && features !== void 0 ? features : []).map((f) => convertDtoFeatureConfigurationToApiSelection(f, silenceWarnings));
48
+ const selectionTrees = (features !== null && features !== void 0 ? features : []).map((f) => convertDtoFeatureConfToApiSelection(f, silenceWarnings));
49
49
  const mergedSelectionTree = {};
50
50
  let anyItems = false;
51
51
  for (const selectionTree of selectionTrees) {
@@ -76,7 +76,7 @@ const swapForUrlAdaptedRegex = /[-~_{}"]/g;
76
76
  const shortToLong = new Map();
77
77
  const longToShort = new Map();
78
78
  // The replacement scheme here assumes this will only be used for keys
79
- // in DtoProductConfiguration and the knowledge that it contains no one
79
+ // in DtoProductConf and the knowledge that it contains no one
80
80
  // one char keys.
81
81
  for (const [long, short] of [
82
82
  ["configuration", "c"],
@@ -116,17 +116,17 @@ const jsonStringSwapCharsForUrl = (data) => data.replace(swapForUrlAdaptedRegex,
116
116
  throw new Error(`Unexpected char "${char}" in swap for URL`);
117
117
  }
118
118
  });
119
- const compactDtoProductConfigurationJsonKeys = (data) => data.replace(jsonKeyRegex, (_, key) => { var _a; return `"${(_a = longToShort.get(key)) !== null && _a !== void 0 ? _a : key}":`; });
120
- const expandDtoProductConfigurationJsonKeys = (data) => data.replace(jsonKeyRegex, (_, key) => { var _a; return `"${(_a = shortToLong.get(key)) !== null && _a !== void 0 ? _a : key}":`; });
119
+ const compactDtoProductConfJsonKeys = (data) => data.replace(jsonKeyRegex, (_, key) => { var _a; return `"${(_a = longToShort.get(key)) !== null && _a !== void 0 ? _a : key}":`; });
120
+ const expandDtoProductConfJsonKeys = (data) => data.replace(jsonKeyRegex, (_, key) => { var _a; return `"${(_a = shortToLong.get(key)) !== null && _a !== void 0 ? _a : key}":`; });
121
121
  /**
122
122
  * Serializes and compacts the configuration into a format especially suited for URLs
123
123
  */
124
124
  export const dtoProductConfigurationToCompactString = (conf) => "v1" +
125
- jsonStringSwapCharsForUrl(compactDtoProductConfigurationJsonKeys(JSON.stringify(conf, undefined, "")));
125
+ jsonStringSwapCharsForUrl(compactDtoProductConfJsonKeys(JSON.stringify(conf, undefined, "")));
126
126
  /**
127
127
  * Deserializes and inflates the configuration from the compacted format
128
128
  */
129
- export const compactStringToDtoProductConfiguration = (versionAndConf) => {
129
+ export const compactStringToDtoProductConf = (versionAndConf) => {
130
130
  const match = versionedRegex.exec(versionAndConf);
131
131
  if (match === null) {
132
132
  throw new Error("Could not match version string");
@@ -138,29 +138,29 @@ export const compactStringToDtoProductConfiguration = (versionAndConf) => {
138
138
  if (conf === "") {
139
139
  throw new Error("No conf found");
140
140
  }
141
- return JSON.parse(expandDtoProductConfigurationJsonKeys(jsonStringSwapCharsForUrl(conf)));
141
+ return JSON.parse(expandDtoProductConfJsonKeys(jsonStringSwapCharsForUrl(conf)));
142
142
  };
143
- export const stripExtendedDataFromDtoProductConfiguration = (conf) => {
143
+ export const stripExtendedDataFromDtoProductConf = (conf) => {
144
144
  var _a, _b;
145
145
  return ({
146
- features: (_a = conf.features) === null || _a === void 0 ? void 0 : _a.map(stripExtendedDataFromDtoFeatureConfiguration),
146
+ features: (_a = conf.features) === null || _a === void 0 ? void 0 : _a.map(stripExtendedDataFromDtoFeatureConf),
147
147
  additionalProducts: (_b = conf.additionalProducts) === null || _b === void 0 ? void 0 : _b.map(stripExtendedDataFromDtoAdditionalProductConfiguration),
148
148
  });
149
149
  };
150
- const stripExtendedDataFromDtoAdditionalProductConfiguration = (conf) => (Object.assign(Object.assign({}, stripExtendedDataFromDtoProductConfiguration(conf)), { refKey: conf.refKey, selected: conf.selected }));
151
- const stripExtendedDataFromDtoFeatureConfiguration = (conf) => {
150
+ const stripExtendedDataFromDtoAdditionalProductConfiguration = (conf) => (Object.assign(Object.assign({}, stripExtendedDataFromDtoProductConf(conf)), { refKey: conf.refKey, selected: conf.selected }));
151
+ const stripExtendedDataFromDtoFeatureConf = (conf) => {
152
152
  var _a;
153
153
  return ({
154
154
  code: conf.code,
155
- options: (_a = conf.options) === null || _a === void 0 ? void 0 : _a.map(stripExtendedDataFromDtoOptionConfiguration),
155
+ options: (_a = conf.options) === null || _a === void 0 ? void 0 : _a.map(stripExtendedDataFromDtoOptionConf),
156
156
  });
157
157
  };
158
- const stripExtendedDataFromDtoOptionConfiguration = (conf) => {
158
+ const stripExtendedDataFromDtoOptionConf = (conf) => {
159
159
  var _a;
160
160
  return ({
161
161
  code: conf.code,
162
162
  selected: conf.selected,
163
163
  numericValue: conf.numericValue,
164
- features: (_a = conf.features) === null || _a === void 0 ? void 0 : _a.map(stripExtendedDataFromDtoFeatureConfiguration),
164
+ features: (_a = conf.features) === null || _a === void 0 ? void 0 : _a.map(stripExtendedDataFromDtoFeatureConf),
165
165
  });
166
166
  };
@@ -2,6 +2,21 @@ import { CfgWindowEventManager } from "./CfgWindowEventManager.js";
2
2
  declare type CfgHistoryManagerMessageData = {
3
3
  initial: boolean;
4
4
  };
5
+ /**
6
+ * How the history is updated.
7
+ * @param DoNotWrite Only listens to initial URL-values.
8
+ * @param Replace Replaces the current history frame at updates.
9
+ * @param Push Adds history frames at updates.
10
+ * @param ReplaceAndUpdateUrl Replaces the current history frame at updates and updates the browser URL
11
+ * @param PushAndUpdateUrl Adds history frames at updates and updates the browser URL
12
+ */
13
+ export declare enum HistoryMode {
14
+ DoNotWrite = 0,
15
+ Replace = 1,
16
+ Push = 2,
17
+ ReplaceAndUpdateUrl = 3,
18
+ PushAndUpdateUrl = 4
19
+ }
5
20
  /**
6
21
  * The collected data used when sending. For history this both contains the message, which is
7
22
  * used as the "state" in the history-frame, and the qsKeyValues, which are query string
@@ -11,7 +26,7 @@ declare type CfgHistoryManagerMessageData = {
11
26
  */
12
27
  export declare type CfgHistoryManagerSendData<D> = {
13
28
  message: D;
14
- useHistoryPush: boolean;
29
+ mode: HistoryMode;
15
30
  qsKeyValues: Map<string, string | undefined>;
16
31
  };
17
32
  /**
@@ -22,6 +37,22 @@ export declare class CfgHistoryManager extends CfgWindowEventManager<"popstate",
22
37
  private static _instance;
23
38
  static get instance(): CfgHistoryManager;
24
39
  private constructor();
40
+ private _aggregatedQsKeyValues;
41
+ private _urlUpdateObservable;
42
+ /**
43
+ * @returns The current browser URL updated with the latest updates from
44
+ * the Connectors.
45
+ */
46
+ getUrl(): string;
47
+ /**
48
+ * Listen for updated URL:s. This doesn't have to mean the URL in the
49
+ * browser has been updated.
50
+ */
51
+ listenForUrl(listener: (url: string) => void): void;
52
+ /**
53
+ * Stop listen.
54
+ */
55
+ stopListenForUrl(listener: (url: string) => void): void;
25
56
  /**
26
57
  * Write to the history
27
58
  */
@@ -47,6 +78,7 @@ export declare class CfgHistoryManager extends CfgWindowEventManager<"popstate",
47
78
  private static _makeUpdatedState;
48
79
  protected readonly eventType = "popstate";
49
80
  protected getDataFromEvent(event: PopStateEvent): unknown;
81
+ static getMessageFromCurrentHistoryState(messageKey: string): unknown | undefined;
50
82
  }
51
83
  export {};
52
84
  //# sourceMappingURL=CfgHistoryManager.d.ts.map
@@ -1,6 +1,22 @@
1
- import { mapQueryString, unmapQueryString } from "@configura/web-utilities";
1
+ import { mapQueryString, Observable, unmapQueryString } from "@configura/web-utilities";
2
2
  import { CfgIOManager } from "./CfgIOManager.js";
3
3
  import { CfgWindowEventManager } from "./CfgWindowEventManager.js";
4
+ /**
5
+ * How the history is updated.
6
+ * @param DoNotWrite Only listens to initial URL-values.
7
+ * @param Replace Replaces the current history frame at updates.
8
+ * @param Push Adds history frames at updates.
9
+ * @param ReplaceAndUpdateUrl Replaces the current history frame at updates and updates the browser URL
10
+ * @param PushAndUpdateUrl Adds history frames at updates and updates the browser URL
11
+ */
12
+ export var HistoryMode;
13
+ (function (HistoryMode) {
14
+ HistoryMode[HistoryMode["DoNotWrite"] = 0] = "DoNotWrite";
15
+ HistoryMode[HistoryMode["Replace"] = 1] = "Replace";
16
+ HistoryMode[HistoryMode["Push"] = 2] = "Push";
17
+ HistoryMode[HistoryMode["ReplaceAndUpdateUrl"] = 3] = "ReplaceAndUpdateUrl";
18
+ HistoryMode[HistoryMode["PushAndUpdateUrl"] = 4] = "PushAndUpdateUrl";
19
+ })(HistoryMode || (HistoryMode = {}));
4
20
  /**
5
21
  * This class is used to coordinate writing and reading to the browser history.
6
22
  * It handles messages sent from the connectors.
@@ -8,6 +24,8 @@ import { CfgWindowEventManager } from "./CfgWindowEventManager.js";
8
24
  export class CfgHistoryManager extends CfgWindowEventManager {
9
25
  constructor() {
10
26
  super();
27
+ this._aggregatedQsKeyValues = new Map();
28
+ this._urlUpdateObservable = new Observable();
11
29
  this.eventType = "popstate";
12
30
  }
13
31
  static get instance() {
@@ -16,22 +34,56 @@ export class CfgHistoryManager extends CfgWindowEventManager {
16
34
  }
17
35
  return this._instance;
18
36
  }
37
+ /**
38
+ * @returns The current browser URL updated with the latest updates from
39
+ * the Connectors.
40
+ */
41
+ getUrl() {
42
+ return CfgHistoryManager._makeUpdatedUrl(this._aggregatedQsKeyValues);
43
+ }
44
+ /**
45
+ * Listen for updated URL:s. This doesn't have to mean the URL in the
46
+ * browser has been updated.
47
+ */
48
+ listenForUrl(listener) {
49
+ this._urlUpdateObservable.listen(listener);
50
+ }
51
+ /**
52
+ * Stop listen.
53
+ */
54
+ stopListenForUrl(listener) {
55
+ this._urlUpdateObservable.stopListen(listener);
56
+ }
19
57
  /**
20
58
  * Write to the history
21
59
  */
22
60
  send(messageKey, data) {
23
- const { qsKeyValues, message, useHistoryPush } = data;
61
+ const { qsKeyValues, message, mode } = data;
62
+ for (const keyValue of qsKeyValues) {
63
+ this._aggregatedQsKeyValues.set(keyValue[0], keyValue[1]);
64
+ }
65
+ this._urlUpdateObservable.notifyAll(this.getUrl());
66
+ if (mode === HistoryMode.DoNotWrite) {
67
+ return;
68
+ }
24
69
  // Initial data is before user interaction has happened
25
70
  const initial = message.initial;
71
+ const url = CfgHistoryManager._makeUpdatedUrl(qsKeyValues);
26
72
  // At initial we do not replace the URL as we presumable have the defaults
27
- const newUrl = initial ? null : CfgHistoryManager._makeUpdatedUrl(qsKeyValues);
73
+ const writeUrl = initial ||
74
+ !(mode === HistoryMode.PushAndUpdateUrl || mode === HistoryMode.ReplaceAndUpdateUrl)
75
+ ? null
76
+ : url;
28
77
  // ...but we do replace the state so that we can in the future browse back to here
29
78
  const newState = CfgHistoryManager._makeUpdatedState(window.history.state, message, messageKey);
30
- if (initial || !useHistoryPush || this.receiveInProgress) {
31
- window.history.replaceState(newState, "", newUrl);
79
+ if (initial ||
80
+ mode === HistoryMode.Replace ||
81
+ mode === HistoryMode.ReplaceAndUpdateUrl ||
82
+ this.receiveInProgress) {
83
+ window.history.replaceState(newState, "", writeUrl);
32
84
  }
33
85
  else {
34
- window.history.pushState(newState, "", newUrl);
86
+ window.history.pushState(newState, "", writeUrl);
35
87
  }
36
88
  }
37
89
  /**
@@ -79,4 +131,14 @@ export class CfgHistoryManager extends CfgWindowEventManager {
79
131
  getDataFromEvent(event) {
80
132
  return event.state;
81
133
  }
134
+ static getMessageFromCurrentHistoryState(messageKey) {
135
+ const state = window.history.state;
136
+ if (!CfgIOManager.isIOContainer(state)) {
137
+ return undefined;
138
+ }
139
+ if (!CfgIOManager.hasIOContainerMessageKey(state, messageKey)) {
140
+ return undefined;
141
+ }
142
+ return CfgIOManager.getMessageFromIOContainer(state, messageKey);
143
+ }
82
144
  }
@@ -1,19 +1,18 @@
1
- import { DtoProductConfiguration } from "../CatalogueAPI.js";
2
- import { CfgHistoryManager, CfgHistoryManagerSendData } from "./CfgHistoryManager.js";
1
+ import { DtoProductConf } from "../CatalogueAPI.js";
2
+ import { CfgHistoryManager, CfgHistoryManagerSendData, HistoryMode } from "./CfgHistoryManager.js";
3
3
  import { CfgIOProdConfConnector, CfgProdConfMessage } from "./CfgIOProdConfConnector.js";
4
4
  /**
5
5
  * Instantiating this will make the browser history (and URL) update with the product configuration.
6
6
  */
7
7
  export declare class CfgHistoryToProdConfConnector extends CfgIOProdConfConnector<CfgHistoryManagerSendData<CfgProdConfMessage>> {
8
- private readonly _useHistoryPush;
8
+ private readonly _mode;
9
9
  private readonly _qsKey;
10
10
  /**
11
- * @param _useHistoryPush As opposed to replace. Push makes the web browser navigation buttons navigate configuration changes. Replace just updates the URL.
11
+ * @param _mode
12
12
  * @param _qsKey The Query String key for product configuration.
13
- * @param doValidate When popping from the history stack (navigating in the browser), should a navigate call be sent to the server to verify that the product configuration is still valid?
14
13
  */
15
- constructor(manager: CfgHistoryManager, _useHistoryPush: boolean, _qsKey?: string, doValidate?: boolean);
16
- protected getInitialProdConf(): DtoProductConfiguration | undefined;
17
- protected makeSendData(conf: DtoProductConfiguration, initial: boolean): CfgHistoryManagerSendData<CfgProdConfMessage>;
14
+ constructor(manager: CfgHistoryManager, _mode: HistoryMode, _qsKey?: string);
15
+ protected getInitialProdConf(): DtoProductConf | undefined;
16
+ protected makeSendData(conf: DtoProductConf, initial: boolean): CfgHistoryManagerSendData<CfgProdConfMessage>;
18
17
  }
19
18
  //# sourceMappingURL=CfgHistoryToProdConfConnector.d.ts.map
@@ -1,26 +1,39 @@
1
- import { compactStringToDtoProductConfiguration, dtoProductConfigurationToCompactString, } from "../ConfigurationConverter.js";
1
+ import { augmentErrorMessage } from "@configura/web-utilities";
2
+ import { compactStringToDtoProductConf, dtoProductConfigurationToCompactString, } from "../ConfigurationConverter.js";
2
3
  import { CfgHistoryManager } from "./CfgHistoryManager.js";
3
- import { CfgIOProdConfConnector, CfgProdConfMessageVersions, STAGE_PROD_CONF_MESSAGE_KEY, } from "./CfgIOProdConfConnector.js";
4
+ import { CfgIOProdConfConnector, CfgProdConfMessageVersions, getHighestVersionProdConfMessage, isCfgProdConfMessageV2, STAGE_PROD_CONF_MESSAGE_KEY, } from "./CfgIOProdConfConnector.js";
4
5
  /**
5
6
  * Instantiating this will make the browser history (and URL) update with the product configuration.
6
7
  */
7
8
  export class CfgHistoryToProdConfConnector extends CfgIOProdConfConnector {
8
9
  /**
9
- * @param _useHistoryPush As opposed to replace. Push makes the web browser navigation buttons navigate configuration changes. Replace just updates the URL.
10
+ * @param _mode
10
11
  * @param _qsKey The Query String key for product configuration.
11
- * @param doValidate When popping from the history stack (navigating in the browser), should a navigate call be sent to the server to verify that the product configuration is still valid?
12
12
  */
13
- constructor(manager, _useHistoryPush, _qsKey = STAGE_PROD_CONF_MESSAGE_KEY, doValidate = true) {
14
- super(manager, doValidate, false, false);
15
- this._useHistoryPush = _useHistoryPush;
13
+ constructor(manager, _mode, _qsKey = STAGE_PROD_CONF_MESSAGE_KEY) {
14
+ super(manager, false, false);
15
+ this._mode = _mode;
16
16
  this._qsKey = _qsKey;
17
17
  }
18
18
  getInitialProdConf() {
19
- const s = CfgHistoryManager.currentQsKeyValues().get(this._qsKey);
20
- if (s === undefined) {
21
- return undefined;
19
+ // First try to use the state, if that doesn't work use the query string
20
+ const initialMessage = CfgHistoryManager.getMessageFromCurrentHistoryState(STAGE_PROD_CONF_MESSAGE_KEY);
21
+ if (initialMessage !== undefined) {
22
+ const highestVersionMessage = getHighestVersionProdConfMessage(initialMessage.subMessages);
23
+ if (isCfgProdConfMessageV2(highestVersionMessage)) {
24
+ return highestVersionMessage.conf;
25
+ }
26
+ }
27
+ try {
28
+ const s = CfgHistoryManager.currentQsKeyValues().get(this._qsKey);
29
+ if (s === undefined) {
30
+ return undefined;
31
+ }
32
+ return compactStringToDtoProductConf(s);
33
+ }
34
+ catch (err) {
35
+ throw augmentErrorMessage(err, "Failed read configuration from query string");
22
36
  }
23
- return compactStringToDtoProductConfiguration(s);
24
37
  }
25
38
  makeSendData(conf, initial) {
26
39
  return {
@@ -28,7 +41,7 @@ export class CfgHistoryToProdConfConnector extends CfgIOProdConfConnector {
28
41
  qsKeyValues: new Map([
29
42
  [STAGE_PROD_CONF_MESSAGE_KEY, dtoProductConfigurationToCompactString(conf)],
30
43
  ]),
31
- useHistoryPush: this._useHistoryPush,
44
+ mode: this._mode,
32
45
  };
33
46
  }
34
47
  }
@@ -81,7 +81,7 @@ export class CfgIOManager {
81
81
  if (item.messageKey !== messageKey) {
82
82
  continue;
83
83
  }
84
- // async, not waiting. Might need to change.
84
+ // async, not waiting on each other. Might need to change.
85
85
  promises.push(item.l(message));
86
86
  }
87
87
  }
@@ -1,4 +1,4 @@
1
- import { DtoAdditionalProductConfiguration, DtoProductConfiguration } from "../CatalogueAPI.js";
1
+ import { DtoAdditionalProductConfiguration, DtoProductConf } from "../CatalogueAPI.js";
2
2
  import { CfgProduct, CfgProductChangeNotification } from "../CfgProduct.js";
3
3
  import { CfgIOManager } from "./CfgIOManager.js";
4
4
  export declare const isCfgProdConfMessage: (data: unknown) => data is CfgProdConfMessageV1 | CfgProdConfMessageV2;
@@ -9,7 +9,7 @@ export declare type CfgProdConfMessageV1 = {
9
9
  export declare const isCfgProdConfMessageV1: (data: unknown) => data is CfgProdConfMessageV1;
10
10
  export declare type CfgProdConfMessageV2 = {
11
11
  version: "2.0";
12
- conf: DtoProductConfiguration;
12
+ conf: DtoProductConf;
13
13
  };
14
14
  export declare const isCfgProdConfMessageV2: (data: unknown) => data is CfgProdConfMessageV2;
15
15
  export declare type CfgProdConfMessage = {
@@ -23,26 +23,25 @@ export declare enum CfgProdConfMessageVersions {
23
23
  }
24
24
  export declare const STAGE_PROD_CONF_MESSAGE_KEY = "stageprodconf";
25
25
  declare type ProdConfMessageCallback = (message: CfgProdConfMessage) => Promise<void>;
26
- declare type ProdConfCallback = (conf: DtoProductConfiguration) => Promise<void>;
26
+ declare type ProdConfCallback = (conf: DtoProductConf) => Promise<void>;
27
27
  /**
28
28
  * Base class for connecting the product configuration to an IO channel
29
29
  */
30
30
  export declare abstract class CfgIOProdConfConnector<S> {
31
31
  private readonly _ioManager;
32
- private readonly _doValidate;
33
32
  private readonly _includeExtendedDataInSend;
34
33
  private readonly _includeProdParamsInSend;
35
34
  private _product;
36
35
  private _stopListenToMessage;
37
36
  private _stopListenToProdConf;
38
- constructor(_ioManager: CfgIOManager<S>, _doValidate: boolean, _includeExtendedDataInSend: boolean, // Only v2.0
37
+ constructor(_ioManager: CfgIOManager<S>, _includeExtendedDataInSend: boolean, // Only v2.0
39
38
  _includeProdParamsInSend: boolean);
40
39
  destroy: () => void;
41
40
  setProduct: (product: CfgProduct | undefined) => Promise<void>;
42
41
  private _send;
43
- protected getInitialProdConf(): DtoProductConfiguration | undefined;
44
- protected abstract makeSendData(conf: DtoProductConfiguration, initial: boolean): S;
45
- static makeMessage(conf: DtoProductConfiguration, initial: boolean, sendVersions: CfgProdConfMessageVersions): CfgProdConfMessage;
42
+ protected getInitialProdConf(): DtoProductConf | undefined;
43
+ protected abstract makeSendData(conf: DtoProductConf, initial: boolean): S;
44
+ static makeMessage(conf: DtoProductConf, initial: boolean, sendVersions: CfgProdConfMessageVersions): CfgProdConfMessage;
46
45
  static makeMessageListener(callback: ProdConfMessageCallback): (message: unknown) => Promise<void>;
47
46
  /**
48
47
  * Register the callback to listen for Product Configuration messages
@@ -7,7 +7,7 @@ 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 { convertDtoProductConfigurationToV1 } from "../ConfigurationConverter.js";
10
+ import { convertDtoProductConfToV1 } from "../ConfigurationConverter.js";
11
11
  export const isCfgProdConfMessage = (data) => typeof data === "object" && data !== null && "version" in data && "conf" in data;
12
12
  export const isCfgProdConfMessageV1 = (data) => isCfgProdConfMessage(data) && data.version === "1.0";
13
13
  export const isCfgProdConfMessageV2 = (data) => isCfgProdConfMessage(data) && data.version === "2.0";
@@ -24,11 +24,10 @@ export const STAGE_PROD_CONF_MESSAGE_KEY = "stageprodconf";
24
24
  * Base class for connecting the product configuration to an IO channel
25
25
  */
26
26
  export class CfgIOProdConfConnector {
27
- constructor(_ioManager, _doValidate, _includeExtendedDataInSend, // Only v2.0
27
+ constructor(_ioManager, _includeExtendedDataInSend, // Only v2.0
28
28
  _includeProdParamsInSend // Only v2.0
29
29
  ) {
30
30
  this._ioManager = _ioManager;
31
- this._doValidate = _doValidate;
32
31
  this._includeExtendedDataInSend = _includeExtendedDataInSend;
33
32
  this._includeProdParamsInSend = _includeProdParamsInSend;
34
33
  this._stopListenToMessage = undefined;
@@ -58,12 +57,17 @@ export class CfgIOProdConfConnector {
58
57
  }
59
58
  // We only try to load initial configuration at first load
60
59
  if (currentProduct === undefined) {
61
- const initialProdConf = this.getInitialProdConf();
62
- if (initialProdConf !== undefined) {
63
- yield newProduct.setDtoConfiguration(initialProdConf, this._doValidate);
60
+ try {
61
+ const initialProdConf = this.getInitialProdConf();
62
+ if (initialProdConf !== undefined) {
63
+ yield newProduct.setDtoConf(initialProdConf);
64
+ }
65
+ }
66
+ catch (err) {
67
+ console.error(err);
64
68
  }
65
69
  }
66
- this._send(this.makeSendData(newProduct.getDtoConfiguration(this._includeExtendedDataInSend, this._includeProdParamsInSend), true));
70
+ this._send(this.makeSendData(newProduct.getDtoConf(this._includeExtendedDataInSend, this._includeProdParamsInSend), true));
67
71
  this._stopListenToMessage = CfgIOProdConfConnector.listenForMessage((messages) => __awaiter(this, void 0, void 0, function* () {
68
72
  const subMessages = messages.subMessages;
69
73
  if (subMessages.length === 0) {
@@ -72,11 +76,11 @@ export class CfgIOProdConfConnector {
72
76
  }
73
77
  const highestVersionMessage = getHighestVersionProdConfMessage(subMessages);
74
78
  if (isCfgProdConfMessageV1(highestVersionMessage)) {
75
- yield newProduct.setApiSelection(highestVersionMessage.conf, this._doValidate);
79
+ yield newProduct.setApiSelection(highestVersionMessage.conf);
76
80
  return;
77
81
  }
78
82
  if (isCfgProdConfMessageV2(highestVersionMessage)) {
79
- yield newProduct.setDtoConfiguration(highestVersionMessage.conf, this._doValidate);
83
+ yield newProduct.setDtoConf(highestVersionMessage.conf);
80
84
  return;
81
85
  }
82
86
  throw new Error("Unknown message version");
@@ -94,7 +98,7 @@ export class CfgIOProdConfConnector {
94
98
  CfgProdConfMessageVersions.V1dot0) {
95
99
  const v1 = {
96
100
  version: "1.0",
97
- conf: convertDtoProductConfigurationToV1(conf, true),
101
+ conf: convertDtoProductConfToV1(conf, true),
98
102
  };
99
103
  result.push(v1);
100
104
  }
@@ -130,7 +134,7 @@ export class CfgIOProdConfConnector {
130
134
  if (!n.committed) {
131
135
  return;
132
136
  }
133
- callback(n.freshRef.getDtoConfiguration(includeExtendedDataInSend, includeProdParamsInSend));
137
+ callback(n.freshRef.getDtoConf(includeExtendedDataInSend, includeProdParamsInSend));
134
138
  };
135
139
  }
136
140
  static listenForProdConf(product, callback, includeExtendedDataInSend, includeProdParamsInSend) {
@@ -1,16 +1,15 @@
1
- import { DtoProductConfiguration } from "../CatalogueAPI.js";
1
+ import { DtoProductConf } from "../CatalogueAPI.js";
2
2
  import { CfgIOProdConfConnector, CfgProdConfMessage, CfgProdConfMessageVersions } from "./CfgIOProdConfConnector.js";
3
3
  import { CfgObservableStateManager } from "./CfgObservableStateManager.js";
4
4
  /**
5
5
  * Instantiating this will make the observable state update with the product configuration.
6
- * @param doValidate Run server side product validation for incoming
7
6
  * @param sendVersions What versions of the productConfiguration shall be sent? Multiple can be selected
8
7
  * @param includeExtendedDataInSend Only for version 2.0. Includes unit and groupCode.
9
8
  * @param includeProdParamsInSend Only for version 2.0. Includes product params, in both main and additional products.
10
9
  */
11
10
  export declare class CfgObservableStateToProdConfConnector extends CfgIOProdConfConnector<CfgProdConfMessage> {
12
11
  private _sendVersions;
13
- constructor(manager: CfgObservableStateManager, doValidate?: boolean, _sendVersions?: CfgProdConfMessageVersions, includeExtendedDataInSend?: boolean, includeProdParamsInSend?: boolean);
14
- protected makeSendData(conf: DtoProductConfiguration, initial: boolean): CfgProdConfMessage;
12
+ constructor(manager: CfgObservableStateManager, _sendVersions?: CfgProdConfMessageVersions, includeExtendedDataInSend?: boolean, includeProdParamsInSend?: boolean);
13
+ protected makeSendData(conf: DtoProductConf, initial: boolean): CfgProdConfMessage;
15
14
  }
16
15
  //# sourceMappingURL=CfgObservableStateToProdConfConnector.d.ts.map
@@ -1,14 +1,13 @@
1
1
  import { CfgIOProdConfConnector, CfgProdConfMessageVersions, } from "./CfgIOProdConfConnector.js";
2
2
  /**
3
3
  * Instantiating this will make the observable state update with the product configuration.
4
- * @param doValidate Run server side product validation for incoming
5
4
  * @param sendVersions What versions of the productConfiguration shall be sent? Multiple can be selected
6
5
  * @param includeExtendedDataInSend Only for version 2.0. Includes unit and groupCode.
7
6
  * @param includeProdParamsInSend Only for version 2.0. Includes product params, in both main and additional products.
8
7
  */
9
8
  export class CfgObservableStateToProdConfConnector extends CfgIOProdConfConnector {
10
- constructor(manager, doValidate = true, _sendVersions = CfgProdConfMessageVersions.V2dot0, includeExtendedDataInSend = false, includeProdParamsInSend = false) {
11
- super(manager, doValidate, includeExtendedDataInSend, includeProdParamsInSend);
9
+ constructor(manager, _sendVersions = CfgProdConfMessageVersions.V2dot0, includeExtendedDataInSend = false, includeProdParamsInSend = false) {
10
+ super(manager, includeExtendedDataInSend, includeProdParamsInSend);
12
11
  this._sendVersions = _sendVersions;
13
12
  }
14
13
  makeSendData(conf, initial) {
@@ -1,18 +1,17 @@
1
- import { DtoProductConfiguration } from "../CatalogueAPI.js";
1
+ import { DtoProductConf } from "../CatalogueAPI.js";
2
2
  import { CfgIOProdConfConnector, CfgProdConfMessage, CfgProdConfMessageVersions } from "./CfgIOProdConfConnector.js";
3
3
  import { CfgWindowMessageManager } from "./CfgWindowMessageManager.js";
4
4
  /**
5
5
  * Instantiating this will make Stage send product configuration changes using the post message-API.
6
6
  * It will also make Stage listen for incoming product configuration update messages.
7
7
  * This can be used to communicate in and out of an iframe for example.
8
- * @param doValidate Run server side product validation for incoming
9
8
  * @param sendVersions What versions of the productConfiguration shall be sent? Multiple can be selected
10
9
  * @param includeExtendedDataInSend Only for version 2.0. Includes unit and groupCode.
11
10
  * @param includeProdParamsInSend Only for version 2.0. Includes product params, in both main and additional products.
12
11
  */
13
12
  export declare class CfgWindowMessageToProdConfConnector extends CfgIOProdConfConnector<CfgProdConfMessage> {
14
13
  private _sendVersions;
15
- constructor(manager: CfgWindowMessageManager, doValidate?: boolean, _sendVersions?: CfgProdConfMessageVersions, includeExtendedDataInSend?: boolean, includeProdParamsInSend?: boolean);
16
- protected makeSendData(conf: DtoProductConfiguration, initial: boolean): CfgProdConfMessage;
14
+ constructor(manager: CfgWindowMessageManager, _sendVersions?: CfgProdConfMessageVersions, includeExtendedDataInSend?: boolean, includeProdParamsInSend?: boolean);
15
+ protected makeSendData(conf: DtoProductConf, initial: boolean): CfgProdConfMessage;
17
16
  }
18
17
  //# sourceMappingURL=CfgWindowMessageToProdConfConnector.d.ts.map
@@ -3,14 +3,13 @@ import { CfgIOProdConfConnector, CfgProdConfMessageVersions, } from "./CfgIOProd
3
3
  * Instantiating this will make Stage send product configuration changes using the post message-API.
4
4
  * It will also make Stage listen for incoming product configuration update messages.
5
5
  * This can be used to communicate in and out of an iframe for example.
6
- * @param doValidate Run server side product validation for incoming
7
6
  * @param sendVersions What versions of the productConfiguration shall be sent? Multiple can be selected
8
7
  * @param includeExtendedDataInSend Only for version 2.0. Includes unit and groupCode.
9
8
  * @param includeProdParamsInSend Only for version 2.0. Includes product params, in both main and additional products.
10
9
  */
11
10
  export class CfgWindowMessageToProdConfConnector extends CfgIOProdConfConnector {
12
- constructor(manager, doValidate = true, _sendVersions = CfgProdConfMessageVersions.V2dot0, includeExtendedDataInSend = false, includeProdParamsInSend = false) {
13
- super(manager, doValidate, includeExtendedDataInSend, includeProdParamsInSend);
11
+ constructor(manager, _sendVersions = CfgProdConfMessageVersions.V2dot0, includeExtendedDataInSend = false, includeProdParamsInSend = false) {
12
+ super(manager, includeExtendedDataInSend, includeProdParamsInSend);
14
13
  this._sendVersions = _sendVersions;
15
14
  }
16
15
  makeSendData(conf, initial) {
@@ -1,5 +1,5 @@
1
1
  import { LengthUnit, Observable, SingleArgCallback } from "@configura/web-utilities";
2
- import { DtoFeature, DtoFeatureConfiguration, DtoSelectedOption, DtoSyncGroup, DtoSyncGroupMethods } from "../CatalogueAPI.js";
2
+ import { DtoFeature, DtoFeatureConf, DtoSelectedOption, DtoSyncGroup, DtoSyncGroupMethods } from "../CatalogueAPI.js";
3
3
  import { CfgProduct, _CfgProductInternal } from "../CfgProduct.js";
4
4
  import { CfgMtrlApplication } from "../material/CfgMtrlApplication.js";
5
5
  import { SyncCode } from "../syncGroups/SyncGroupsHandler.js";
@@ -99,7 +99,7 @@ export declare class _CfgFeatureInternal {
99
99
  * as nonexisting children can not call their parent.
100
100
  */
101
101
  _childHasChanged: (childOption: _CfgOptionInternal, bubbleMode: ProductConfigurationBubbleMode, committed: boolean) => Promise<void>;
102
- getDtoConfiguration: (includeExtendedData: boolean) => DtoFeatureConfiguration;
102
+ getDtoConf: (includeExtendedData: boolean) => DtoFeatureConf;
103
103
  setApiSelection: (apiOptionSelectionMap: {
104
104
  [index: string]: DtoSelectedOption;
105
105
  } | undefined) => Promise<boolean>;
@@ -114,7 +114,7 @@ export class _CfgFeatureInternal {
114
114
  }
115
115
  yield this._notifyAllOfChange(bubbleMode, committed);
116
116
  });
117
- this.getDtoConfiguration = (includeExtendedData) => {
117
+ this.getDtoConf = (includeExtendedData) => {
118
118
  const result = {
119
119
  code: this.code,
120
120
  };
@@ -124,10 +124,16 @@ export class _CfgFeatureInternal {
124
124
  }
125
125
  const selectedOptions = this._selectedOptions;
126
126
  if (0 < selectedOptions.length) {
127
- result.options = selectedOptions.map((o) => o._internal.getDtoConfiguration(includeExtendedData));
127
+ result.options = selectedOptions.map((o) => o._internal.getDtoConf(includeExtendedData));
128
128
  }
129
129
  return result;
130
130
  };
131
+ // DtoFeatureConf is the newer more easily readable format for configuration. As
132
+ // the API:s are still using the older format (and will for the forseeable future) we need
133
+ // to support both formats. The new format can be converted to the old, but not the other
134
+ // way around. For that reason the get-method above uses the new format, and the set-method
135
+ // below the old format. As these functions are meant to only be used internally this should't
136
+ // cause too much confusion.
131
137
  this.setApiSelection = (apiOptionSelectionMap) => __awaiter(this, void 0, void 0, function* () {
132
138
  const selectionType = this.selectionType;
133
139
  const isGroup = selectionType === SelectionType.Group;
@@ -1,5 +1,5 @@
1
1
  import { LengthUnit, Observable, SingleArgCallback } from "@configura/web-utilities";
2
- import { DtoFeature, DtoOption, DtoOptionConfiguration, DtoSelectedOption } from "../CatalogueAPI.js";
2
+ import { DtoFeature, DtoOption, DtoOptionConf, DtoSelectedOption } from "../CatalogueAPI.js";
3
3
  import { CfgProduct, _CfgProductInternal } from "../CfgProduct.js";
4
4
  import { CfgMtrlApplication } from "../material/CfgMtrlApplication.js";
5
5
  import { NumericValuesSelection } from "../utilitiesNumericValues.js";
@@ -89,7 +89,7 @@ export declare class _CfgOptionInternal {
89
89
  get features(): CfgFeature[];
90
90
  /** Called by child to tell its parent that it has changed. */
91
91
  _childHasChanged: (freshRef: CfgFeature, bubbleMode: ProductConfigurationBubbleMode, committed: boolean) => Promise<void>;
92
- getDtoConfiguration: (includeExtendedData: boolean) => DtoOptionConfiguration;
92
+ getDtoConf: (includeExtendedData: boolean) => DtoOptionConf;
93
93
  setApiSelection: (apiOptionSelection: DtoSelectedOption | undefined) => Promise<boolean>;
94
94
  structureCompare: (other: _CfgOptionInternal, strictOrder?: boolean, descriptionMatch?: boolean) => boolean;
95
95
  tryMatchSelection: (other: CfgOption, descriptionMatch?: boolean) => Promise<boolean>;
@@ -110,7 +110,7 @@ export class _CfgOptionInternal {
110
110
  yield this.parent._childHasChanged(this, bubbleMode, committed);
111
111
  }
112
112
  });
113
- this.getDtoConfiguration = (includeExtendedData) => {
113
+ this.getDtoConf = (includeExtendedData) => {
114
114
  const { features, isUseNumericValue, code, selected, numericValue } = this;
115
115
  if (!selected) {
116
116
  throw new Error("Currently only useable on selected options. Selected in the result is for future use.");
@@ -128,10 +128,16 @@ export class _CfgOptionInternal {
128
128
  }
129
129
  }
130
130
  if (0 < features.length) {
131
- result.features = features.map((f) => f._internal.getDtoConfiguration(includeExtendedData));
131
+ result.features = features.map((f) => f._internal.getDtoConf(includeExtendedData));
132
132
  }
133
133
  return result;
134
134
  };
135
+ // DtoOptionConf is the newer more easily readable format for configuration. As
136
+ // the API:s are still using the older format (and will for the forseeable future) we need
137
+ // to support both formats. The new format can be converted to the old, but not the other
138
+ // way around. For that reason the get-method above uses the new format, and the set-method
139
+ // below the old format. As these functions are meant to only be used internally this should't
140
+ // cause too much confusion.
135
141
  this.setApiSelection = (apiOptionSelection) => __awaiter(this, void 0, void 0, function* () {
136
142
  let features;
137
143
  if (apiOptionSelection === undefined) {
@@ -1,5 +1,5 @@
1
1
  import { LengthUnit, LengthValue, Observable, SingleArgCallback } from "@configura/web-utilities";
2
- import { DtoFeature, DtoFeatureConfiguration, DtoFeatureRef, DtoSelectedOption } from "../CatalogueAPI.js";
2
+ import { DtoFeature, DtoFeatureConf, DtoFeatureRef, DtoSelectedOption } from "../CatalogueAPI.js";
3
3
  import { CfgProduct, _CfgProductInternal } from "../CfgProduct.js";
4
4
  import { CfgFeature, _CfgFeatureInternal } from "./CfgFeature.js";
5
5
  import { ProductConfigurationBubbleMode } from "./CfgOption.js";
@@ -34,10 +34,12 @@ export declare class _CfgProductConfigurationInternal {
34
34
  _freshRefDescendants(): void;
35
35
  /** Called by child to tell its parent that it has changed. */
36
36
  _childHasChanged: (freshRef: CfgFeature, bubbleMode: ProductConfigurationBubbleMode, committed: boolean) => Promise<void>;
37
- getDtoConfiguration: (includeExtendedData: boolean) => DtoFeatureConfiguration[];
37
+ getDtoConf: (includeExtendedData: boolean) => DtoFeatureConf[];
38
+ getApiSelection: () => DtoSelectedOption[];
38
39
  /**
39
40
  * When used internally the notifications are taken care off by the caller, but if set from
40
41
  * outside we want notifications to bubble all the way to the root.
42
+ * This method will not cause validation calls. Data is assumed to already be validated.
41
43
  */
42
44
  setApiSelection: (selectedOptions: DtoSelectedOption[], bubbleToRoot: boolean) => Promise<boolean>;
43
45
  structureCompare: (other: _CfgProductConfigurationInternal, strictOrder: boolean, descriptionMatch: boolean) => boolean;
@@ -94,12 +96,6 @@ export declare class CfgProductConfiguration {
94
96
  * This method will cause validation calls.
95
97
  */
96
98
  tryMatchSelection: (other: CfgProductConfiguration, descriptionMatch?: boolean) => Promise<boolean>;
97
- getApiSelection: () => DtoSelectedOption[];
98
- /**
99
- * This method does not propagate its selections.
100
- * This method will not cause validation calls. Data is assumed to already be validated.
101
- */
102
- setApiSelection: (selectedOptions: DtoSelectedOption[]) => Promise<boolean>;
103
99
  /**
104
100
  * Set how stretched a certain measure should be measureParamCode is the measure to be
105
101
  * stretched referenceLength is a value relative to the initial length of the measure. If the
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  };
10
10
  import { compareArrays, count, isEqualLength, isLengthUnit, Observable, toError, toLengthUnit, } from "@configura/web-utilities";
11
11
  import { CfgProduct } from "../CfgProduct.js";
12
- import { convertDtoFeatureConfigurationsToSelOptions } from "../ConfigurationConverter.js";
12
+ import { convertDtoFeatureConfsToSelOptions } from "../ConfigurationConverter.js";
13
13
  import { CfgFeature } from "./CfgFeature.js";
14
14
  import { ProductConfigurationBubbleMode } from "./CfgOption.js";
15
15
  import { syncCfgFeatures } from "./utilitiesProductConfiguration.js";
@@ -55,10 +55,12 @@ export class _CfgProductConfigurationInternal {
55
55
  features[i] = freshRef;
56
56
  yield this._notifyAllOfChange(bubbleMode, committed);
57
57
  });
58
- this.getDtoConfiguration = (includeExtendedData) => this._features.map((f) => f._internal.getDtoConfiguration(includeExtendedData));
58
+ this.getDtoConf = (includeExtendedData) => this._features.map((f) => f._internal.getDtoConf(includeExtendedData));
59
+ this.getApiSelection = () => convertDtoFeatureConfsToSelOptions(this.getDtoConf(false), true);
59
60
  /**
60
61
  * When used internally the notifications are taken care off by the caller, but if set from
61
62
  * outside we want notifications to bubble all the way to the root.
63
+ * This method will not cause validation calls. Data is assumed to already be validated.
62
64
  */
63
65
  this.setApiSelection = (selectedOptions, bubbleToRoot) => __awaiter(this, void 0, void 0, function* () {
64
66
  const featuresLength = this._features.length;
@@ -233,12 +235,6 @@ export class CfgProductConfiguration {
233
235
  */
234
236
  this.tryMatchSelection = (other, descriptionMatch = false // Match on case insensitive description, not code
235
237
  ) => __awaiter(this, void 0, void 0, function* () { return yield this._internal.tryMatchSelection(other._internal, descriptionMatch, true); });
236
- this.getApiSelection = () => convertDtoFeatureConfigurationsToSelOptions(this._internal.getDtoConfiguration(false), true);
237
- /**
238
- * This method does not propagate its selections.
239
- * This method will not cause validation calls. Data is assumed to already be validated.
240
- */
241
- this.setApiSelection = (selectedOptions) => __awaiter(this, void 0, void 0, function* () { return yield this._internal.setApiSelection(selectedOptions, true); });
242
238
  /**
243
239
  * Set how stretched a certain measure should be measureParamCode is the measure to be
244
240
  * stretched referenceLength is a value relative to the initial length of the measure. If the
@@ -9,6 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  };
10
10
  import { augmentErrorMessage, Observable } from "@configura/web-utilities";
11
11
  import { dtoExportFormatNames, dtoRenderFormatNames, } from "../CatalogueAPI.js";
12
+ import { convertDtoProductConfToV1 } from "../ConfigurationConverter.js";
12
13
  import { isExportFormat, isRenderFormat } from "./formats.js";
13
14
  export class _TaskHandlerInternal {
14
15
  constructor(api) {
@@ -175,7 +176,7 @@ export class Task {
175
176
  this.taskHandler.removeTask(this);
176
177
  };
177
178
  this._productParams = product.prodParams;
178
- this._apiSelection = product.getApiSelection();
179
+ this._apiSelection = convertDtoProductConfToV1(product.getDtoConf());
179
180
  if (getPreviewUrl !== undefined) {
180
181
  void getPreviewUrl().then((dataUrl) => {
181
182
  this._previewUrl = dataUrl;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@configura/web-api",
3
- "version": "2.0.0-alpha.14",
3
+ "version": "2.0.0-alpha.15",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -23,7 +23,7 @@
23
23
  "access": "public"
24
24
  },
25
25
  "dependencies": {
26
- "@configura/web-utilities": "2.0.0-alpha.14"
26
+ "@configura/web-utilities": "2.0.0-alpha.15"
27
27
  },
28
- "gitHead": "b3d0439069dc8cca134143d00fcd2f964525ceca"
28
+ "gitHead": "9f9facc3e6b6c16c02ff6950a1f6c86e44671957"
29
29
  }