@configura/web-api 2.0.0-alpha.2 → 2.0.0-alpha.20

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.
Files changed (52) hide show
  1. package/dist/CatalogueAPI.d.ts +73 -43
  2. package/dist/CatalogueAPI.js +37 -2
  3. package/dist/CfgProduct.d.ts +73 -11
  4. package/dist/CfgProduct.js +130 -29
  5. package/dist/CfgReferencePathHelper.d.ts +16 -3
  6. package/dist/CfgReferencePathHelper.js +14 -1
  7. package/dist/ConfigurationConverter.d.ts +13 -4
  8. package/dist/ConfigurationConverter.js +106 -12
  9. package/dist/io/CfgHistoryManager.d.ts +37 -4
  10. package/dist/io/CfgHistoryManager.js +76 -8
  11. package/dist/io/CfgHistoryToProdConfConnector.d.ts +7 -10
  12. package/dist/io/CfgHistoryToProdConfConnector.js +29 -38
  13. package/dist/io/CfgIOManager.d.ts +5 -0
  14. package/dist/io/CfgIOManager.js +20 -1
  15. package/dist/io/CfgIOProdConfConnector.d.ts +21 -17
  16. package/dist/io/CfgIOProdConfConnector.js +54 -37
  17. package/dist/io/CfgIOWarningSupplier.d.ts +4 -0
  18. package/dist/io/CfgIOWarningSupplier.js +1 -0
  19. package/dist/io/CfgObservableStateManager.d.ts +4 -0
  20. package/dist/io/CfgObservableStateManager.js +4 -0
  21. package/dist/io/CfgObservableStateToProdConfConnector.d.ts +4 -4
  22. package/dist/io/CfgObservableStateToProdConfConnector.js +4 -4
  23. package/dist/io/CfgWindowMessageManager.d.ts +2 -2
  24. package/dist/io/CfgWindowMessageManager.js +9 -2
  25. package/dist/io/CfgWindowMessageToProdConfConnector.d.ts +4 -4
  26. package/dist/io/CfgWindowMessageToProdConfConnector.js +4 -4
  27. package/dist/productConfiguration/CfgFeature.d.ts +8 -6
  28. package/dist/productConfiguration/CfgFeature.js +19 -6
  29. package/dist/productConfiguration/CfgOption.d.ts +5 -5
  30. package/dist/productConfiguration/CfgOption.js +11 -5
  31. package/dist/productConfiguration/CfgProductConfiguration.d.ts +27 -15
  32. package/dist/productConfiguration/CfgProductConfiguration.js +54 -21
  33. package/dist/productConfiguration/filters.d.ts +2 -2
  34. package/dist/productConfiguration/productParamsGenerator.d.ts +3 -3
  35. package/dist/productConfiguration/utilitiesProductConfiguration.d.ts +1 -1
  36. package/dist/productConfiguration/utilitiesProductConfiguration.js +11 -4
  37. package/dist/productLoader.d.ts +3 -3
  38. package/dist/syncGroups/SyncGroupsHandler.d.ts +4 -1
  39. package/dist/syncGroups/SyncGroupsHandler.js +6 -2
  40. package/dist/syncGroups/SyncGroupsTransaction.js +34 -21
  41. package/dist/tasks/TaskHandler.d.ts +2 -2
  42. package/dist/tasks/TaskHandler.js +2 -1
  43. package/dist/tests/testData/dummyProductForTest.d.ts +2 -2
  44. package/dist/tests/testData/testDataAdditionalProductInAdditionalProductInProductForTest.js +1 -0
  45. package/dist/tests/testData/testDataCachedGetProduct.js +1 -0
  46. package/dist/tests/testData/testDataCachedPostValidate.js +1 -0
  47. package/dist/tests/testData/testDataProductAggregatedPrice.js +1 -0
  48. package/dist/tests/testData/testDataUpcharge.js +1 -0
  49. package/dist/utilitiesCatalogueData.d.ts +14 -9
  50. package/dist/utilitiesCatalogueData.js +7 -0
  51. package/dist/utilitiesCataloguePermission.d.ts +4 -4
  52. package/package.json +3 -3
@@ -1,13 +1,31 @@
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
4
  /**
5
- * This class does nothing on it's own. It is used to coordinate writing to the history, that
6
- * is, updating the browsing history.
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 = {}));
20
+ /**
21
+ * This class is used to coordinate writing and reading to the browser history.
22
+ * It handles messages sent from the connectors.
7
23
  */
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,62 @@ 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
+ const warnings = this.getWarnings();
63
+ if (warnings.length !== 0) {
64
+ console.warn("History updating blocked by warnings");
65
+ warnings.forEach((w) => console.warn(w));
66
+ return;
67
+ }
68
+ for (const keyValue of qsKeyValues) {
69
+ this._aggregatedQsKeyValues.set(keyValue[0], keyValue[1]);
70
+ }
71
+ this._urlUpdateObservable.notifyAll(this.getUrl());
72
+ if (mode === HistoryMode.DoNotWrite) {
73
+ return;
74
+ }
24
75
  // Initial data is before user interaction has happened
25
76
  const initial = message.initial;
77
+ const url = CfgHistoryManager._makeUpdatedUrl(qsKeyValues);
26
78
  // At initial we do not replace the URL as we presumable have the defaults
27
- const newUrl = initial ? null : CfgHistoryManager._makeUpdatedUrl(qsKeyValues);
79
+ const writeUrl = initial ||
80
+ !(mode === HistoryMode.PushAndUpdateUrl || mode === HistoryMode.ReplaceAndUpdateUrl)
81
+ ? null
82
+ : url;
28
83
  // ...but we do replace the state so that we can in the future browse back to here
29
84
  const newState = CfgHistoryManager._makeUpdatedState(window.history.state, message, messageKey);
30
- if (initial || !useHistoryPush || this.receiveInProgress) {
31
- window.history.replaceState(newState, "", newUrl);
85
+ if (initial ||
86
+ mode === HistoryMode.Replace ||
87
+ mode === HistoryMode.ReplaceAndUpdateUrl ||
88
+ this.receiveInProgress) {
89
+ window.history.replaceState(newState, "", writeUrl);
32
90
  }
33
91
  else {
34
- window.history.pushState(newState, "", newUrl);
92
+ window.history.pushState(newState, "", writeUrl);
35
93
  }
36
94
  }
37
95
  /**
@@ -79,4 +137,14 @@ export class CfgHistoryManager extends CfgWindowEventManager {
79
137
  getDataFromEvent(event) {
80
138
  return event.state;
81
139
  }
140
+ static getMessageFromCurrentHistoryState(messageKey) {
141
+ const state = window.history.state;
142
+ if (!CfgIOManager.isIOContainer(state)) {
143
+ return undefined;
144
+ }
145
+ if (!CfgIOManager.hasIOContainerMessageKey(state, messageKey)) {
146
+ return undefined;
147
+ }
148
+ return CfgIOManager.getMessageFromIOContainer(state, messageKey);
149
+ }
82
150
  }
@@ -1,21 +1,18 @@
1
- import { DtoConfProd } 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
- export declare function dtoConfToString(conf: DtoConfProd): string;
5
- export declare function stringToDtoConf(conf: string): DtoConfProd;
6
4
  /**
7
5
  * Instantiating this will make the browser history (and URL) update with the product configuration.
8
6
  */
9
7
  export declare class CfgHistoryToProdConfConnector extends CfgIOProdConfConnector<CfgHistoryManagerSendData<CfgProdConfMessage>> {
10
- private readonly _useHistoryPush;
8
+ private readonly _mode;
11
9
  private readonly _qsKey;
12
10
  /**
13
- * @param _useHistoryPush As opposed to replace. Push makes the web browser navigation buttons navigate configuration changes. Replace just updates the URL.
11
+ * @param _mode
14
12
  * @param _qsKey The Query String key for product configuration.
15
- * @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?
16
13
  */
17
- constructor(manager: CfgHistoryManager, _useHistoryPush: boolean, _qsKey?: string, doValidate?: boolean);
18
- protected getInitialProdConf(): DtoConfProd | undefined;
19
- protected makeSendData(conf: DtoConfProd, 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>;
20
17
  }
21
18
  //# sourceMappingURL=CfgHistoryToProdConfConnector.d.ts.map
@@ -1,56 +1,47 @@
1
+ import { augmentErrorMessage } from "@configura/web-utilities";
2
+ import { compactStringToDtoProductConf, dtoProductConfigurationToCompactString, } from "../ConfigurationConverter.js";
1
3
  import { CfgHistoryManager } from "./CfgHistoryManager.js";
2
- import { CfgIOProdConfConnector, CfgProdConfMessageVersions, STAGE_PROD_CONF_MESSAGE_KEY, } from "./CfgIOProdConfConnector.js";
3
- const jsonKeyRegex = /"([^"]+)":/g;
4
- const keyMap = [
5
- ["configuration", "cn"],
6
- ["additionalProducts", "as"],
7
- ["prodParams", "pp"],
8
- ["refKey", "rk"],
9
- ["selected", "se"],
10
- ["features", "fs"],
11
- ["code", "cd"],
12
- ["options", "os"],
13
- ["numericValue", "nu"],
14
- ["groupCode", "gc"],
15
- ["unit", "un"],
16
- ];
17
- // todo: Could be worth making faster
18
- const toCompact = (key) => { var _a, _b; return (_b = (_a = keyMap.find((i) => i[0] === key)) === null || _a === void 0 ? void 0 : _a[1]) !== null && _b !== void 0 ? _b : key; };
19
- const toExpanded = (key) => { var _a, _b; return (_b = (_a = keyMap.find((i) => i[1] === key)) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : key; };
20
- export function dtoConfToString(conf) {
21
- const stringified = JSON.stringify(conf, undefined, "");
22
- return stringified.replace(jsonKeyRegex, (_, key) => `"${toCompact(key)}":`);
23
- }
24
- export function stringToDtoConf(conf) {
25
- const expandedKeys = conf.replace(jsonKeyRegex, (_, key) => `"${toExpanded(key)}":`);
26
- return JSON.parse(expandedKeys);
27
- }
4
+ import { CfgIOProdConfConnector, CfgProdConfMessageVersions, getHighestVersionProdConfMessage, isCfgProdConfMessageV2, STAGE_PROD_CONF_MESSAGE_KEY, } from "./CfgIOProdConfConnector.js";
28
5
  /**
29
6
  * Instantiating this will make the browser history (and URL) update with the product configuration.
30
7
  */
31
8
  export class CfgHistoryToProdConfConnector extends CfgIOProdConfConnector {
32
9
  /**
33
- * @param _useHistoryPush As opposed to replace. Push makes the web browser navigation buttons navigate configuration changes. Replace just updates the URL.
10
+ * @param _mode
34
11
  * @param _qsKey The Query String key for product configuration.
35
- * @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?
36
12
  */
37
- constructor(manager, _useHistoryPush, _qsKey = STAGE_PROD_CONF_MESSAGE_KEY, doValidate = true) {
38
- super(manager, doValidate, CfgProdConfMessageVersions.V2dot0, false, false);
39
- this._useHistoryPush = _useHistoryPush;
13
+ constructor(manager, _mode, _qsKey = STAGE_PROD_CONF_MESSAGE_KEY) {
14
+ super(manager, false, false);
15
+ this._mode = _mode;
40
16
  this._qsKey = _qsKey;
41
17
  }
42
18
  getInitialProdConf() {
43
- const s = CfgHistoryManager.currentQsKeyValues().get(this._qsKey);
44
- if (s === undefined) {
45
- 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");
46
36
  }
47
- return stringToDtoConf(s);
48
37
  }
49
38
  makeSendData(conf, initial) {
50
39
  return {
51
- message: this.makeMessage(conf, initial),
52
- qsKeyValues: new Map([[STAGE_PROD_CONF_MESSAGE_KEY, dtoConfToString(conf)]]),
53
- useHistoryPush: this._useHistoryPush,
40
+ message: CfgIOProdConfConnector.makeMessage(conf, initial, CfgProdConfMessageVersions.V2dot0),
41
+ qsKeyValues: new Map([
42
+ [STAGE_PROD_CONF_MESSAGE_KEY, dtoProductConfigurationToCompactString(conf)],
43
+ ]),
44
+ mode: this._mode,
54
45
  };
55
46
  }
56
47
  }
@@ -1,3 +1,4 @@
1
+ import { CfgIOWarningSupplier } from "./CfgIOWarningSupplier";
1
2
  declare type ConfiguraAttribute = "C0nf1gura";
2
3
  declare type ConfiguraShebang = "arug1fn0C";
3
4
  declare const CONFIGURA_ATTRIBUTE: ConfiguraAttribute;
@@ -17,6 +18,10 @@ export declare type CfgIOContainer = {
17
18
  * Base class for classes handling input and output in globally shared environments.
18
19
  */
19
20
  export declare abstract class CfgIOManager<S> {
21
+ private _warningSuppliers;
22
+ addWarningSupplier(supplier: CfgIOWarningSupplier): void;
23
+ removeWarningSupplier(supplier: CfgIOWarningSupplier): void;
24
+ getWarnings(): string[];
20
25
  /**
21
26
  * Listen for the message messageKey being received.
22
27
  */
@@ -18,12 +18,31 @@ const hasConfiguraAttribute = (data) => {
18
18
  */
19
19
  export class CfgIOManager {
20
20
  constructor() {
21
+ this._warningSuppliers = [];
21
22
  // A lock to avoid circular write. Asynchronous conditions can make this not be enough.
22
23
  // Avoid creating pre-conditions where this can happen.
23
24
  this._receiveInProgress = false;
24
25
  this._messageListeners = [];
25
26
  this._getIndexOfMessageListener = (l) => this._messageListeners.findIndex((item) => l === item.l);
26
27
  }
28
+ addWarningSupplier(supplier) {
29
+ this._warningSuppliers.push(supplier);
30
+ }
31
+ removeWarningSupplier(supplier) {
32
+ const i = this._warningSuppliers.indexOf(supplier);
33
+ if (i === -1) {
34
+ return;
35
+ }
36
+ this._warningSuppliers.splice(i, 1);
37
+ }
38
+ getWarnings() {
39
+ return this._warningSuppliers.reduce((aggregated, supplier) => {
40
+ for (const warning of supplier.getWarnings()) {
41
+ aggregated.push(warning);
42
+ }
43
+ return aggregated;
44
+ }, []);
45
+ }
27
46
  /**
28
47
  * Listen for the message messageKey being received.
29
48
  */
@@ -81,7 +100,7 @@ export class CfgIOManager {
81
100
  if (item.messageKey !== messageKey) {
82
101
  continue;
83
102
  }
84
- // async, not waiting. Might need to change.
103
+ // async, not waiting on each other. Might need to change.
85
104
  promises.push(item.l(message));
86
105
  }
87
106
  }
@@ -1,53 +1,57 @@
1
- import { DtoAdditionalProductConfiguration, DtoConfProd } 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
+ import { CfgIOWarningSupplier } from "./CfgIOWarningSupplier.js";
5
+ export declare const isCfgProdConfMessage: (data: unknown) => data is CfgProdConfMessageV1 | CfgProdConfMessageV2;
4
6
  export declare type CfgProdConfMessageV1 = {
5
7
  version: "1.0";
6
8
  conf: DtoAdditionalProductConfiguration;
7
9
  };
10
+ export declare const isCfgProdConfMessageV1: (data: unknown) => data is CfgProdConfMessageV1;
8
11
  export declare type CfgProdConfMessageV2 = {
9
12
  version: "2.0";
10
- conf: DtoConfProd;
13
+ conf: DtoProductConf;
11
14
  };
15
+ export declare const isCfgProdConfMessageV2: (data: unknown) => data is CfgProdConfMessageV2;
12
16
  export declare type CfgProdConfMessage = {
13
17
  initial: boolean;
14
18
  subMessages: (CfgProdConfMessageV1 | CfgProdConfMessageV2)[];
15
19
  };
20
+ export declare const getHighestVersionProdConfMessage: (subMessages: (CfgProdConfMessageV1 | CfgProdConfMessageV2)[]) => CfgProdConfMessageV1 | CfgProdConfMessageV2;
16
21
  export declare enum CfgProdConfMessageVersions {
17
22
  V1dot0 = 1,
18
23
  V2dot0 = 2
19
24
  }
20
25
  export declare const STAGE_PROD_CONF_MESSAGE_KEY = "stageprodconf";
21
26
  declare type ProdConfMessageCallback = (message: CfgProdConfMessage) => Promise<void>;
22
- declare type ProdConfCallback = (conf: DtoConfProd) => Promise<void>;
27
+ declare type ProdConfCallback = (conf: DtoProductConf) => Promise<void>;
23
28
  /**
24
29
  * Base class for connecting the product configuration to an IO channel
25
30
  */
26
- export declare abstract class CfgIOProdConfConnector<S> {
27
- private readonly _ioManager;
28
- private readonly _doValidate;
29
- private readonly _sendVersions;
31
+ export declare abstract class CfgIOProdConfConnector<S> implements CfgIOWarningSupplier {
32
+ protected readonly _ioManager: CfgIOManager<S>;
30
33
  private readonly _includeExtendedDataInSend;
31
34
  private readonly _includeProdParamsInSend;
32
- private _product;
35
+ protected _product: CfgProduct | undefined;
33
36
  private _stopListenToMessage;
34
37
  private _stopListenToProdConf;
35
- constructor(_ioManager: CfgIOManager<S>, _doValidate: boolean, _sendVersions: CfgProdConfMessageVersions, _includeExtendedDataInSend: boolean, // Only v2.0
38
+ constructor(_ioManager: CfgIOManager<S>, _includeExtendedDataInSend: boolean, // Only for v2.0
36
39
  _includeProdParamsInSend: boolean);
37
- destroy: () => void;
40
+ destroy(): void;
41
+ getWarnings(): string[];
38
42
  setProduct: (product: CfgProduct | undefined) => Promise<void>;
39
43
  private _send;
40
- protected getInitialProdConf(): DtoConfProd | undefined;
41
- protected abstract makeSendData(conf: DtoConfProd, initial: boolean): S;
42
- makeMessage(conf: DtoConfProd, initial: boolean): CfgProdConfMessage;
43
- makeMessageListener(callback: ProdConfMessageCallback): (message: unknown) => Promise<void>;
44
+ protected getInitialProdConf(): DtoProductConf | undefined;
45
+ protected abstract makeSendData(conf: DtoProductConf, initial: boolean): S;
46
+ static makeMessage(conf: DtoProductConf, initial: boolean, sendVersions: CfgProdConfMessageVersions): CfgProdConfMessage;
47
+ static makeMessageListener(callback: ProdConfMessageCallback): (message: unknown) => Promise<void>;
44
48
  /**
45
49
  * Register the callback to listen for Product Configuration messages
46
50
  * @returns A function which when called will cancel listening
47
51
  */
48
- listenForMessage(callback: ProdConfMessageCallback): () => void;
49
- makeProdConfListener(callback: ProdConfCallback): (n: CfgProductChangeNotification) => void;
50
- listenForProdConf(product: CfgProduct, callback: ProdConfCallback): () => void;
52
+ static listenForMessage<S>(callback: ProdConfMessageCallback, ioManager: CfgIOManager<S>): () => void;
53
+ static makeProdConfListener(callback: ProdConfCallback, includeExtendedDataInSend: boolean, includeProdParamsInSend: boolean): (n: CfgProductChangeNotification) => void;
54
+ static listenForProdConf(product: CfgProduct, callback: ProdConfCallback, includeExtendedDataInSend: boolean, includeProdParamsInSend: boolean): () => void;
51
55
  }
52
56
  export {};
53
57
  //# sourceMappingURL=CfgIOProdConfConnector.d.ts.map
@@ -7,7 +7,13 @@ 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 { convertDtoConfProdToV1 } from "../ConfigurationConverter.js";
10
+ import { convertDtoProductConfToV1 } from "../ConfigurationConverter.js";
11
+ export const isCfgProdConfMessage = (data) => typeof data === "object" && data !== null && "version" in data && "conf" in data;
12
+ export const isCfgProdConfMessageV1 = (data) => isCfgProdConfMessage(data) && data.version === "1.0";
13
+ export const isCfgProdConfMessageV2 = (data) => isCfgProdConfMessage(data) && data.version === "2.0";
14
+ export const getHighestVersionProdConfMessage = (subMessages) => subMessages
15
+ .slice(1)
16
+ .reduce((a, c) => (a.version < c.version ? c : a), subMessages[0]);
11
17
  export var CfgProdConfMessageVersions;
12
18
  (function (CfgProdConfMessageVersions) {
13
19
  CfgProdConfMessageVersions[CfgProdConfMessageVersions["V1dot0"] = 1] = "V1dot0";
@@ -18,21 +24,14 @@ export const STAGE_PROD_CONF_MESSAGE_KEY = "stageprodconf";
18
24
  * Base class for connecting the product configuration to an IO channel
19
25
  */
20
26
  export class CfgIOProdConfConnector {
21
- constructor(_ioManager, _doValidate, _sendVersions, _includeExtendedDataInSend, // Only v2.0
22
- _includeProdParamsInSend // Only v2.0
27
+ constructor(_ioManager, _includeExtendedDataInSend, // Only for v2.0
28
+ _includeProdParamsInSend // Only for v2.0
23
29
  ) {
24
30
  this._ioManager = _ioManager;
25
- this._doValidate = _doValidate;
26
- this._sendVersions = _sendVersions;
27
31
  this._includeExtendedDataInSend = _includeExtendedDataInSend;
28
32
  this._includeProdParamsInSend = _includeProdParamsInSend;
29
33
  this._stopListenToMessage = undefined;
30
34
  this._stopListenToProdConf = undefined;
31
- this.destroy = () => {
32
- var _a, _b;
33
- (_a = this._stopListenToMessage) === null || _a === void 0 ? void 0 : _a.call(this);
34
- (_b = this._stopListenToProdConf) === null || _b === void 0 ? void 0 : _b.call(this);
35
- };
36
35
  this.setProduct = (product) => __awaiter(this, void 0, void 0, function* () {
37
36
  var _a, _b;
38
37
  const currentProduct = this._product;
@@ -53,49 +52,68 @@ export class CfgIOProdConfConnector {
53
52
  }
54
53
  // We only try to load initial configuration at first load
55
54
  if (currentProduct === undefined) {
56
- const initialProdConf = this.getInitialProdConf();
57
- if (initialProdConf !== undefined) {
58
- yield newProduct.setDtoConf(initialProdConf, this._doValidate);
55
+ try {
56
+ const initialProdConf = this.getInitialProdConf();
57
+ if (initialProdConf !== undefined) {
58
+ yield newProduct.setDtoConf(initialProdConf);
59
+ }
60
+ }
61
+ catch (err) {
62
+ console.error(err);
59
63
  }
60
64
  }
61
65
  this._send(this.makeSendData(newProduct.getDtoConf(this._includeExtendedDataInSend, this._includeProdParamsInSend), true));
62
- this._stopListenToMessage = this.listenForMessage((messages) => __awaiter(this, void 0, void 0, function* () {
66
+ this._stopListenToMessage = CfgIOProdConfConnector.listenForMessage((messages) => __awaiter(this, void 0, void 0, function* () {
63
67
  const subMessages = messages.subMessages;
64
68
  if (subMessages.length === 0) {
65
69
  console.warn(`${STAGE_PROD_CONF_MESSAGE_KEY} message without any submessages. Unexpected.`);
66
70
  return;
67
71
  }
68
- const highestVersionMessage = subMessages
69
- .slice(1)
70
- .reduce((a, c) => (a.version < c.version ? c : a), subMessages[0]);
71
- switch (highestVersionMessage.version) {
72
- case "1.0":
73
- yield newProduct.setApiSelection(highestVersionMessage.conf, this._doValidate);
74
- return;
75
- case "2.0":
76
- yield newProduct.setDtoConf(highestVersionMessage.conf, this._doValidate);
77
- return;
72
+ const highestVersionMessage = getHighestVersionProdConfMessage(subMessages);
73
+ if (isCfgProdConfMessageV1(highestVersionMessage)) {
74
+ yield newProduct.setApiSelection(highestVersionMessage.conf);
75
+ return;
76
+ }
77
+ if (isCfgProdConfMessageV2(highestVersionMessage)) {
78
+ yield newProduct.setDtoConf(highestVersionMessage.conf);
79
+ return;
78
80
  }
79
81
  throw new Error("Unknown message version");
80
- }));
81
- this._stopListenToProdConf = this.listenForProdConf(newProduct, (conf) => __awaiter(this, void 0, void 0, function* () { return this._send(this.makeSendData(conf, false)); }));
82
+ }), this._ioManager);
83
+ this._stopListenToProdConf = CfgIOProdConfConnector.listenForProdConf(newProduct, (conf) => __awaiter(this, void 0, void 0, function* () { return this._send(this.makeSendData(conf, false)); }), this._includeExtendedDataInSend, this._includeProdParamsInSend);
82
84
  });
83
85
  this._send = (data) => this._ioManager.send(STAGE_PROD_CONF_MESSAGE_KEY, data);
86
+ _ioManager.addWarningSupplier(this);
87
+ }
88
+ destroy() {
89
+ var _a, _b;
90
+ (_a = this._stopListenToMessage) === null || _a === void 0 ? void 0 : _a.call(this);
91
+ (_b = this._stopListenToProdConf) === null || _b === void 0 ? void 0 : _b.call(this);
92
+ this._ioManager.removeWarningSupplier(this);
93
+ }
94
+ getWarnings() {
95
+ const product = this._product;
96
+ if (product !== undefined && product.hasRootFeaturesChanged) {
97
+ return [
98
+ "In at least one of the Products, Functional Selection has taken place, thereby changing what root Features are used. The SDK can not yet apply a serialized configuration in these cases. Extracting this data from the SDK for external applications can work, but reinserting the data into Stage will most likely fail.",
99
+ ];
100
+ }
101
+ return [];
84
102
  }
85
103
  getInitialProdConf() {
86
104
  return undefined;
87
105
  }
88
- makeMessage(conf, initial) {
106
+ static makeMessage(conf, initial, sendVersions) {
89
107
  const result = [];
90
- if ((this._sendVersions & CfgProdConfMessageVersions.V1dot0) ===
108
+ if ((sendVersions & CfgProdConfMessageVersions.V1dot0) ===
91
109
  CfgProdConfMessageVersions.V1dot0) {
92
110
  const v1 = {
93
111
  version: "1.0",
94
- conf: convertDtoConfProdToV1(conf, true),
112
+ conf: convertDtoProductConfToV1(conf, true),
95
113
  };
96
114
  result.push(v1);
97
115
  }
98
- if ((this._sendVersions & CfgProdConfMessageVersions.V2dot0) ===
116
+ if ((sendVersions & CfgProdConfMessageVersions.V2dot0) ===
99
117
  CfgProdConfMessageVersions.V2dot0) {
100
118
  const v2 = {
101
119
  version: "2.0",
@@ -105,7 +123,7 @@ export class CfgIOProdConfConnector {
105
123
  }
106
124
  return { subMessages: result, initial };
107
125
  }
108
- makeMessageListener(callback) {
126
+ static makeMessageListener(callback) {
109
127
  return (message) => __awaiter(this, void 0, void 0, function* () {
110
128
  const prodConfMessage = message;
111
129
  yield callback(prodConfMessage);
@@ -115,24 +133,23 @@ export class CfgIOProdConfConnector {
115
133
  * Register the callback to listen for Product Configuration messages
116
134
  * @returns A function which when called will cancel listening
117
135
  */
118
- listenForMessage(callback) {
119
- const ioManager = this._ioManager;
136
+ static listenForMessage(callback, ioManager) {
120
137
  const listener = this.makeMessageListener(callback);
121
138
  ioManager.listenForMessage(listener, STAGE_PROD_CONF_MESSAGE_KEY);
122
139
  return () => {
123
140
  ioManager.stopListenForMessage(listener);
124
141
  };
125
142
  }
126
- makeProdConfListener(callback) {
143
+ static makeProdConfListener(callback, includeExtendedDataInSend, includeProdParamsInSend) {
127
144
  return (n) => {
128
145
  if (!n.committed) {
129
146
  return;
130
147
  }
131
- callback(n.freshRef.getDtoConf(this._includeExtendedDataInSend, this._includeProdParamsInSend));
148
+ callback(n.freshRef.getDtoConf(includeExtendedDataInSend, includeProdParamsInSend));
132
149
  };
133
150
  }
134
- listenForProdConf(product, callback) {
135
- const listener = this.makeProdConfListener(callback);
151
+ static listenForProdConf(product, callback, includeExtendedDataInSend, includeProdParamsInSend) {
152
+ const listener = this.makeProdConfListener(callback, includeExtendedDataInSend, includeProdParamsInSend);
136
153
  product.listenForChange(listener);
137
154
  return () => {
138
155
  product.stopListenForChange(listener);
@@ -0,0 +1,4 @@
1
+ export interface CfgIOWarningSupplier {
2
+ getWarnings(): string[];
3
+ }
4
+ //# sourceMappingURL=CfgIOWarningSupplier.d.ts.map
@@ -0,0 +1 @@
1
+ export {};
@@ -1,5 +1,9 @@
1
1
  import { Observable } from "@configura/web-utilities";
2
2
  import { CfgIOManager, IOManagerListener } from "./CfgIOManager.js";
3
+ /**
4
+ * This class is used to coordinate sending and receiving using the observable
5
+ * state in the class. It handles messages sent from the connectors.
6
+ */
3
7
  export declare class CfgObservableStateManager extends CfgIOManager<unknown> {
4
8
  private static _instance;
5
9
  static get instance(): CfgObservableStateManager;
@@ -1,5 +1,9 @@
1
1
  import { Observable } from "@configura/web-utilities";
2
2
  import { CfgIOManager } from "./CfgIOManager.js";
3
+ /**
4
+ * This class is used to coordinate sending and receiving using the observable
5
+ * state in the class. It handles messages sent from the connectors.
6
+ */
3
7
  export class CfgObservableStateManager extends CfgIOManager {
4
8
  constructor() {
5
9
  super();
@@ -1,15 +1,15 @@
1
- import { DtoConfProd } 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
- constructor(manager: CfgObservableStateManager, doValidate?: boolean, sendVersions?: CfgProdConfMessageVersions, includeExtendedDataInSend?: boolean, includeProdParamsInSend?: boolean);
13
- protected makeSendData(conf: DtoConfProd, initial: boolean): CfgProdConfMessage;
11
+ private _sendVersions;
12
+ constructor(manager: CfgObservableStateManager, _sendVersions?: CfgProdConfMessageVersions, includeExtendedDataInSend?: boolean, includeProdParamsInSend?: boolean);
13
+ protected makeSendData(conf: DtoProductConf, initial: boolean): CfgProdConfMessage;
14
14
  }
15
15
  //# sourceMappingURL=CfgObservableStateToProdConfConnector.d.ts.map
@@ -1,16 +1,16 @@
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, sendVersions, includeExtendedDataInSend, includeProdParamsInSend);
9
+ constructor(manager, _sendVersions = CfgProdConfMessageVersions.V2dot0, includeExtendedDataInSend = false, includeProdParamsInSend = false) {
10
+ super(manager, includeExtendedDataInSend, includeProdParamsInSend);
11
+ this._sendVersions = _sendVersions;
12
12
  }
13
13
  makeSendData(conf, initial) {
14
- return this.makeMessage(conf, initial);
14
+ return CfgIOProdConfConnector.makeMessage(conf, initial, this._sendVersions);
15
15
  }
16
16
  }
@@ -1,8 +1,8 @@
1
1
  import { IOManagerListener } from "./CfgIOManager.js";
2
2
  import { CfgWindowEventManager } from "./CfgWindowEventManager.js";
3
3
  /**
4
- * This class does nothing on it's own. It is used to coordinate sending and receiving
5
- * using the post message-API. See https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
4
+ * This class is used to coordinate sending and receiving using the post message-API.
5
+ * See https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
6
6
  */
7
7
  export declare class CfgWindowMessageManager extends CfgWindowEventManager<"message", unknown> {
8
8
  private static _instance;
@@ -1,8 +1,8 @@
1
1
  import { CfgIOManager } from "./CfgIOManager.js";
2
2
  import { CfgWindowEventManager } from "./CfgWindowEventManager.js";
3
3
  /**
4
- * This class does nothing on it's own. It is used to coordinate sending and receiving
5
- * using the post message-API. See https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
4
+ * This class is used to coordinate sending and receiving using the post message-API.
5
+ * See https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
6
6
  */
7
7
  export class CfgWindowMessageManager extends CfgWindowEventManager {
8
8
  /**
@@ -64,9 +64,16 @@ export class CfgWindowMessageManager extends CfgWindowEventManager {
64
64
  return super.stopListenForMessage(l);
65
65
  }
66
66
  send(messageKey, data) {
67
+ if (this.receiveInProgress) {
68
+ return;
69
+ }
67
70
  const container = CfgIOManager.makeContainer({
68
71
  [messageKey]: data,
69
72
  });
73
+ const warnings = this.getWarnings();
74
+ if (warnings.length !== 0) {
75
+ warnings.forEach((w) => console.warn(w));
76
+ }
70
77
  for (const remoteEnd of this._remoteEnds) {
71
78
  remoteEnd.postMessage(container, this._targetOrigin);
72
79
  }