@configura/web-api 2.0.0-alpha.9 → 2.1.0-alpha.0

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 (58) hide show
  1. package/.eslintrc.json +1 -14
  2. package/dist/CatalogueAPI.d.ts +103 -32
  3. package/dist/CatalogueAPI.js +62 -6
  4. package/dist/CfgProduct.d.ts +90 -14
  5. package/dist/CfgProduct.js +266 -56
  6. package/dist/CfgReferencePathHelper.d.ts +3 -3
  7. package/dist/index.d.ts +1 -1
  8. package/dist/index.js +1 -1
  9. package/dist/io/CfgHistoryManager.d.ts +33 -1
  10. package/dist/io/CfgHistoryManager.js +68 -6
  11. package/dist/io/CfgHistoryToProdConfConnector.d.ts +11 -10
  12. package/dist/io/CfgHistoryToProdConfConnector.js +32 -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 +17 -18
  16. package/dist/io/CfgIOProdConfConnector.js +52 -58
  17. package/dist/io/CfgIOWarningSupplier.d.ts +4 -0
  18. package/dist/io/CfgIOWarningSupplier.js +1 -0
  19. package/dist/io/CfgObservableStateToProdConfConnector.d.ts +4 -4
  20. package/dist/io/CfgObservableStateToProdConfConnector.js +3 -3
  21. package/dist/io/CfgWindowMessageManager.js +4 -0
  22. package/dist/io/CfgWindowMessageToProdConfConnector.d.ts +4 -4
  23. package/dist/io/CfgWindowMessageToProdConfConnector.js +3 -3
  24. package/dist/productConfiguration/CfgFeature.d.ts +12 -7
  25. package/dist/productConfiguration/CfgFeature.js +33 -14
  26. package/dist/productConfiguration/CfgOption.d.ts +16 -10
  27. package/dist/productConfiguration/CfgOption.js +46 -18
  28. package/dist/productConfiguration/CfgProductConfiguration.d.ts +27 -16
  29. package/dist/productConfiguration/CfgProductConfiguration.js +53 -29
  30. package/dist/productConfiguration/filters.d.ts +6 -4
  31. package/dist/productConfiguration/filters.js +94 -23
  32. package/dist/productConfiguration/productParamsGenerator.d.ts +3 -3
  33. package/dist/productConfiguration/utilitiesProductConfiguration.d.ts +1 -1
  34. package/dist/productConfiguration/utilitiesProductConfiguration.js +11 -4
  35. package/dist/productLoader.d.ts +3 -3
  36. package/dist/productLoader.js +1 -1
  37. package/dist/syncGroups/SyncGroupsHandler.d.ts +9 -2
  38. package/dist/syncGroups/SyncGroupsHandler.js +15 -4
  39. package/dist/syncGroups/SyncGroupsState.d.ts +5 -1
  40. package/dist/syncGroups/SyncGroupsState.js +44 -2
  41. package/dist/syncGroups/SyncGroupsTransaction.js +34 -21
  42. package/dist/tasks/TaskHandler.d.ts +2 -2
  43. package/dist/tasks/TaskHandler.js +2 -1
  44. package/dist/tests/testData/dummyProductForTest.d.ts +2 -2
  45. package/dist/tests/testData/testDataAdditionalProductInAdditionalProductInProductForTest.js +14 -9
  46. package/dist/tests/testData/testDataCachedGetProduct.js +2 -0
  47. package/dist/tests/testData/testDataCachedPostValidate.js +2 -0
  48. package/dist/tests/testData/testDataProductAggregatedPrice.js +3 -1
  49. package/dist/tests/testData/testDataUpcharge.js +2 -0
  50. package/dist/utilitiesCatalogueData.d.ts +14 -9
  51. package/dist/utilitiesCatalogueData.js +7 -0
  52. package/dist/utilitiesCataloguePermission.d.ts +4 -4
  53. package/dist/utilitiesConfiguration.d.ts +29 -0
  54. package/dist/utilitiesConfiguration.js +200 -0
  55. package/dist/utilitiesNumericValues.js +13 -8
  56. package/package.json +3 -3
  57. package/dist/ConfigurationConverter.d.ts +0 -5
  58. package/dist/ConfigurationConverter.js +0 -72
@@ -13,6 +13,12 @@ import { SelectionType, } from "../productConfiguration/CfgFeature.js";
13
13
  import { ProductConfigurationBubbleMode, } from "../productConfiguration/CfgOption.js";
14
14
  import { SyncGroupsApplyMode } from "./SyncGroupsApplyMode.js";
15
15
  import { SyncGroupsPathHelper } from "./SyncGroupsPathHelper.js";
16
+ var AffectedLevel;
17
+ (function (AffectedLevel) {
18
+ AffectedLevel[AffectedLevel["None"] = 0] = "None";
19
+ AffectedLevel[AffectedLevel["Initialized"] = 1] = "Initialized";
20
+ AffectedLevel[AffectedLevel["Set"] = 2] = "Set";
21
+ })(AffectedLevel || (AffectedLevel = {}));
16
22
  /**
17
23
  * The Transaction is a transient object used to track all the changes made to the supplied
18
24
  * SyncGroupState as a result of a (normally) single initial event, like when opening a product
@@ -39,7 +45,7 @@ import { SyncGroupsPathHelper } from "./SyncGroupsPathHelper.js";
39
45
  export class SyncGroupsTransaction {
40
46
  constructor(syncState, updateMode, productLoader, original, target, initial) {
41
47
  this._closed = false;
42
- this.affectedSelectOneFeatures = new Set();
48
+ this.affectedSelectOneFeatures = new Map();
43
49
  this.affectedSelectManyOptions = new Set();
44
50
  this.affectedSelectOneSyncGroups = new Set();
45
51
  this.affectedSelectManySyncGroupsAndOptions = new Map();
@@ -104,7 +110,7 @@ export class SyncGroupsTransaction {
104
110
  change = true;
105
111
  switch (feature.selectionType) {
106
112
  case SelectionType.SelectOne:
107
- this.affectedSelectOneFeatures.add(feature);
113
+ this.affectedSelectOneFeatures.set(feature, AffectedLevel.Set);
108
114
  break;
109
115
  case SelectionType.SelectMany:
110
116
  this.affectedSelectManyOptions.add(option);
@@ -266,14 +272,19 @@ export class SyncGroupsTransaction {
266
272
  return __awaiter(this, void 0, void 0, function* () {
267
273
  const feature = featureWithInitial.target;
268
274
  const featureDidJustComeIntoScope = featureWithInitial.initial === undefined;
269
- if (this.affectedSelectOneFeatures.has(feature)) {
270
- // This feature has already changed selection once for this transaction. We expect
271
- // this to happen very rarely, as the algorithm should settle the selection tree
272
- // further and further out. Nevertheless, this safeguard is needed to avoid infinite
273
- // looping if for example the server would return the same data over and over.
275
+ const hasBeenAffectedLevel = this.affectedSelectOneFeatures.get(feature);
276
+ const syncGroupHasBeenUpdated = this.affectedSelectOneSyncGroups.has(syncCode);
277
+ if (hasBeenAffectedLevel === AffectedLevel.Set ||
278
+ (!syncGroupHasBeenUpdated && hasBeenAffectedLevel === AffectedLevel.Initialized)) {
279
+ // A feature can change value for two reasons:
280
+ // 1. The feature did just come into scope and loads from the sync group to set its "defaults"
281
+ // 2. The sync group has updated with a new value
282
+ // The rule is that in one sync group transaction the feature value is allowed to be updated
283
+ // once or twice. Once for initialization and once for new sync group value. But they have to
284
+ // happen in the right order.
274
285
  return "recurseDown";
275
286
  }
276
- if (!featureDidJustComeIntoScope && !this.affectedSelectOneSyncGroups.has(syncCode)) {
287
+ if (!featureDidJustComeIntoScope && !syncGroupHasBeenUpdated) {
277
288
  return "recurseDown";
278
289
  }
279
290
  const currentSyncGroupValue = this.syncState.getForSelectOne(syncCode);
@@ -295,7 +306,7 @@ export class SyncGroupsTransaction {
295
306
  // Do not recurse further as we will change the state and so what is selected now won't be
296
307
  // selected then.
297
308
  yield feature.selectOption(optionToSelect._internal, true, ProductConfigurationBubbleMode.ToRoot);
298
- this.affectedSelectOneFeatures.add(feature);
309
+ this.affectedSelectOneFeatures.set(feature, syncGroupHasBeenUpdated ? AffectedLevel.Set : AffectedLevel.Initialized);
299
310
  productsToValidate.add(feature.parentProduct);
300
311
  return "stop";
301
312
  });
@@ -435,7 +446,7 @@ export class SyncGroupsTransaction {
435
446
  return change;
436
447
  });
437
448
  }
438
- applySelectOneFeature(feature, activeSelectionForce, featureDidJustComeIntoScope) {
449
+ applySelectOneFeature(feature, userInitiated, featureDidJustComeIntoScope) {
439
450
  const selectionType = feature.selectionType;
440
451
  if (selectionType !== SelectionType.SelectOne) {
441
452
  throw new Error("can only be used for selectOne");
@@ -453,7 +464,7 @@ export class SyncGroupsTransaction {
453
464
  // Options with no default are never written
454
465
  return false;
455
466
  }
456
- if (activeSelectionForce) {
467
+ if (userInitiated) {
457
468
  // To make re-apply happen, even if it actually does not update the sync group
458
469
  this.affectedSelectOneSyncGroups.add(syncCode);
459
470
  }
@@ -464,7 +475,7 @@ export class SyncGroupsTransaction {
464
475
  // can not be set to the current sync group value, then it will set in the opposite
465
476
  // direction. Like if the sync group was empty. To avoid bouncing back and forth we will
466
477
  // need to enforce that a sync group can only be updated once per transaction
467
- if (!(activeSelectionForce ||
478
+ if (!(userInitiated ||
468
479
  currentSyncGroupOptionCode === undefined ||
469
480
  (featureDidJustComeIntoScope &&
470
481
  feature.options.every((o) => currentSyncGroupOptionCode !== o.code)))) {
@@ -486,7 +497,7 @@ export class SyncGroupsTransaction {
486
497
  }
487
498
  return change;
488
499
  }
489
- applySelectManyOption(option, activeSelectionForce) {
500
+ applySelectManyOption(option, userInitiated) {
490
501
  const feature = option.parent;
491
502
  if (feature.selectionType !== SelectionType.SelectMany) {
492
503
  throw new Error("can only be used for selectMany");
@@ -500,14 +511,14 @@ export class SyncGroupsTransaction {
500
511
  }
501
512
  const optionSelected = option.selected;
502
513
  const currentSyncGroupValue = this.syncState.getForSelectMany(syncCode, option.code);
503
- if (activeSelectionForce) {
514
+ if (userInitiated) {
504
515
  // To make re-apply happen, even if it actually does not update the sync group
505
516
  this.addSyncGroupAffectedForSelectMany(syncCode, option);
506
517
  }
507
- // We only initialize if the option is selected or we force.
508
- // activeSelectionForce = active selection by the user.
509
- if (!(currentSyncGroupValue === undefined && optionSelected) &&
510
- !(activeSelectionForce && currentSyncGroupValue !== optionSelected)) {
518
+ // We only initialize if the option has not been initiated or if it is userInitiated.
519
+ // userInitiated = active selection by the user.
520
+ if (currentSyncGroupValue !== undefined &&
521
+ !(userInitiated && currentSyncGroupValue !== optionSelected)) {
511
522
  return false;
512
523
  }
513
524
  this.addSyncGroupAffectedForSelectMany(syncCode, option);
@@ -529,7 +540,9 @@ export class SyncGroupsTransaction {
529
540
  }
530
541
  function getAdditionalProducts(product) {
531
542
  const initial = product.initial;
532
- return product.target.additionalProducts.map((childTarget) => {
543
+ return product.target.additionalProducts
544
+ .filter((p) => p.selected)
545
+ .map((childTarget) => {
533
546
  const refKey = childTarget.refKey;
534
547
  const childInitial = initial === null || initial === void 0 ? void 0 : initial.additionalProducts.find((p) => refKey === p.refKey);
535
548
  return {
@@ -558,8 +571,8 @@ function getOptions(feature) {
558
571
  }
559
572
  function pairFeatures(targets, initials) {
560
573
  return targets.map((childTarget) => {
561
- const key = childTarget.key;
562
- const childInitial = initials === null || initials === void 0 ? void 0 : initials.find((f) => key === f.key);
574
+ const code = childTarget.code;
575
+ const childInitial = initials === null || initials === void 0 ? void 0 : initials.find((f) => code === f.code);
563
576
  return {
564
577
  target: childTarget._internal,
565
578
  initial: childInitial === null || childInitial === void 0 ? void 0 : childInitial._internal,
@@ -1,5 +1,5 @@
1
1
  import { Observable, SingleArgCallback } from "@configura/web-utilities";
2
- import { CatalogueAPI, DtoAdditionalProductConfiguration, DtoExportStatus, DtoExportStatusStatus, DtoProductParamsWithLang, DtoRenderStatus, DtoRenderStatusStatus, DtoTargetCameraArgs } from "../CatalogueAPI.js";
2
+ import { CatalogueAPI, DtoAdditionalProductConfiguration, DtoExportStatus, DtoExportStatusStatus, DtoProductParamsWithCidAndLang, DtoRenderStatus, DtoRenderStatusStatus, DtoTargetCameraArgs } from "../CatalogueAPI.js";
3
3
  import { CfgProduct } from "../CfgProduct.js";
4
4
  import { RenderOrExportFormat } from "./formats.js";
5
5
  export declare type TasksChangeNotification = {
@@ -51,7 +51,7 @@ export declare abstract class Task<F extends RenderOrExportFormat> {
51
51
  protected constructor(taskHandler: _TaskHandlerInternal, format: F, product: CfgProduct, getPreviewUrl: (() => Promise<string>) | undefined);
52
52
  protected abstract postInit(): Promise<DtoRenderStatus | DtoExportStatus>;
53
53
  protected abstract pollStatus(): Promise<DtoRenderStatus | DtoExportStatus>;
54
- protected _productParams: DtoProductParamsWithLang;
54
+ protected _productParams: DtoProductParamsWithCidAndLang;
55
55
  protected _apiSelection: DtoAdditionalProductConfiguration;
56
56
  private _status;
57
57
  private _uuid;
@@ -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 "../utilitiesConfiguration.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;
@@ -1,5 +1,5 @@
1
- import { DtoCatalogueParamsWithLang } from "../../CatalogueAPI.js";
1
+ import { DtoCatalogueParamsWithCidAndLang } from "../../CatalogueAPI.js";
2
2
  import { CfgProduct } from "../../CfgProduct.js";
3
- export declare const dummyCatId: DtoCatalogueParamsWithLang;
3
+ export declare const dummyCatId: DtoCatalogueParamsWithCidAndLang;
4
4
  export declare const getDummyCfgProduct: () => Promise<CfgProduct>;
5
5
  //# sourceMappingURL=dummyProductForTest.d.ts.map
@@ -222,17 +222,20 @@ export const cfgProductTest = (testFunc, prepFunc) => __awaiter(void 0, void 0,
222
222
  getProduct: getTestProduct,
223
223
  postValidate: (params, _body) => __awaiter(void 0, void 0, void 0, function* () {
224
224
  const productData = (yield getTestProduct(params)).productData;
225
- productData.partsData.selOptions = [
226
- {
227
- code: "!~!",
228
- next: {
229
- [letterOptionCodeC]: {
230
- code: letterOptionCodeC,
225
+ const partNumber = params.partNumber;
226
+ if (partNumber !== "D") {
227
+ productData.partsData.selOptions = [
228
+ {
229
+ code: "!~!",
230
+ next: {
231
+ [letterOptionCodeC]: {
232
+ code: letterOptionCodeC,
233
+ },
231
234
  },
232
235
  },
233
- },
234
- ];
235
- if (params.partNumber === "A") {
236
+ ];
237
+ }
238
+ if (partNumber === "A") {
236
239
  productData.partsData.selOptions.push({
237
240
  code: "!~!",
238
241
  next: {
@@ -252,8 +255,10 @@ export const cfgProductTest = (testFunc, prepFunc) => __awaiter(void 0, void 0,
252
255
  }
253
256
  const validateResponse = {
254
257
  uuid: "",
258
+ unit: "m",
255
259
  validated: true,
256
260
  productData,
261
+ features: [],
257
262
  };
258
263
  collect.pushNotification(`Validate ${params.enterprise} ${params.prdCat} ${params.prdCatVersion} ${params.priceList} ${params.vendor} ${params.partNumber}`);
259
264
  return validateResponse;
@@ -171,8 +171,10 @@ export const cachedProductLoaderTest = () => __awaiter(void 0, void 0, void 0, f
171
171
  ];
172
172
  const validateResponse = {
173
173
  uuid: "",
174
+ unit: "m",
174
175
  validated: true,
175
176
  productData,
177
+ features: [],
176
178
  };
177
179
  return validateResponse;
178
180
  }),
@@ -171,8 +171,10 @@ export const cachedProductLoaderTest = () => __awaiter(void 0, void 0, void 0, f
171
171
  const productData = (yield getProduct(params)).productData;
172
172
  const validateResponse = {
173
173
  uuid: "",
174
+ unit: "m",
174
175
  validated: true,
175
176
  productData,
177
+ features: [],
176
178
  };
177
179
  validateCounter.count++;
178
180
  return validateResponse;
@@ -169,13 +169,15 @@ export const cfgProductPriceTest = (testFunc, featureOption) => __awaiter(void 0
169
169
  getProduct: getTestProduct,
170
170
  postValidate: (params, _body) => __awaiter(void 0, void 0, void 0, function* () {
171
171
  const productData = (yield getTestProduct(params)).productData;
172
- if (featureOption !== undefined) {
172
+ if (featureOption !== undefined && params.partNumber === "A") {
173
173
  productData.partsData.selOptions = getSelOptions(featureOption);
174
174
  }
175
175
  const validateResponse = {
176
176
  uuid: "",
177
+ unit: "m",
177
178
  validated: true,
178
179
  productData,
180
+ features: [],
179
181
  };
180
182
  return validateResponse;
181
183
  }),
@@ -97,8 +97,10 @@ export const getUpchargeProduct = (testFunc) => __awaiter(void 0, void 0, void 0
97
97
  const productData = (yield getProduct(params)).productData;
98
98
  const validateResponse = {
99
99
  uuid: "",
100
+ unit: "m",
100
101
  validated: true,
101
102
  productData,
103
+ features: [],
102
104
  };
103
105
  return validateResponse;
104
106
  }),
@@ -1,12 +1,12 @@
1
- import { DtoAdditionalProductRef, DtoCatalogueParams, DtoCatalogueParamsWithLang, DtoCatalogueParamsWithoutCid, DtoMeasureParam, DtoModel, DtoOrientation, DtoPartsData, DtoPrices, DtoProductData, DtoProductParams, DtoProductParamsWithLang, DtoProductResponse, DtoSelectedOption, DtoTransform, DtoValidateResponse, DtoVector } from "./CatalogueAPI.js";
1
+ import { DtoAdditionalProductRef, DtoCatalogueParams, DtoCatalogueParamsWithCid, DtoCatalogueParamsWithCidAndLang, DtoMeasureParam, DtoModel, DtoOrientation, DtoPartsData, DtoPrices, DtoProductData, DtoProductParamsWithCid, DtoProductParamsWithCidAndLang, DtoProductResponse, DtoSelectedOption, DtoTransform, DtoValidateResponse, DtoVector } from "./CatalogueAPI.js";
2
2
  /**
3
3
  * Makes a string from the params which can be used as a key in for example React. Language is not respected.
4
4
  */
5
- export declare const makeCatalogueKey: (cat: DtoCatalogueParams) => string;
5
+ export declare const makeCatalogueKey: (cat: DtoCatalogueParamsWithCid) => string;
6
6
  /**
7
7
  * Makes a string from the params which can be used as a key in for example React. Language is not respected.
8
8
  */
9
- export declare const makeProductKey: (prod: DtoProductParams) => string;
9
+ export declare const makeProductKey: (prod: DtoProductParamsWithCid) => string;
10
10
  /**
11
11
  * Makes a string from selected options, can be used as a key for a selection.
12
12
  */
@@ -18,6 +18,11 @@ export declare type CfgProductData = Omit<Omit<DtoProductData, "models">, "parts
18
18
  selOptions: DtoSelectedOption[];
19
19
  };
20
20
  };
21
+ /**
22
+ * Deep compare. Uses the JSON.stringify method for comparison
23
+ * @returns true if equal. Key and array order is respected.
24
+ */
25
+ export declare function compareCfgProductData(pd1: CfgProductData, pd2: CfgProductData): boolean;
21
26
  export declare type CfgProductResponse = Omit<DtoProductResponse, "productData"> & {
22
27
  productData: CfgProductData;
23
28
  };
@@ -27,17 +32,17 @@ export declare type CfgValidateResponse = Omit<DtoValidateResponse, "productData
27
32
  };
28
33
  export declare function isModel(arg: unknown): arg is DtoModel;
29
34
  /** Replace empty strings with "-" for compatibility with the API. */
30
- export declare function correctDefaultsOnCatalogueParams<T extends DtoCatalogueParamsWithoutCid>(catId: T): T;
35
+ export declare function correctDefaultsOnCatalogueParams<T extends DtoCatalogueParams>(catId: T): T;
31
36
  export declare function recursivelyGetPriceCodeValue(priceCodes: string[], prices: DtoPrices | undefined): number | undefined;
32
37
  export declare function comparePricesObjects(prices1: DtoPrices | undefined, prices2: DtoPrices | undefined): boolean;
33
- export declare const decodeCatalogueParams: <T extends DtoCatalogueParamsWithoutCid>(params: T) => T;
34
- export declare const decodeProductParams: <T extends DtoProductParams>(params: T) => T;
35
- export declare function isSameCatalogueParams(left: DtoCatalogueParamsWithoutCid, right: DtoCatalogueParamsWithoutCid): boolean;
38
+ export declare const decodeCatalogueParams: <T extends DtoCatalogueParams>(params: T) => T;
39
+ export declare const decodeProductParams: <T extends DtoProductParamsWithCid>(params: T) => T;
40
+ export declare function isSameCatalogueParams(left: DtoCatalogueParams, right: DtoCatalogueParams): boolean;
36
41
  export declare function isSameVector(left: DtoVector, right: DtoVector): boolean;
37
42
  export declare function isSameOrientation(left: DtoOrientation, right: DtoOrientation): boolean;
38
43
  export declare function isSameAnchor(left: DtoMeasureParam, right: DtoMeasureParam): boolean;
39
44
  export declare function isSameTransform(left: DtoTransform, right: DtoTransform): boolean;
40
45
  export declare function isSameProductRef(left: DtoAdditionalProductRef, right: DtoAdditionalProductRef): boolean;
41
- export declare const isSameDtoCatalogueParamsWithLang: (left: DtoCatalogueParamsWithLang, right: DtoCatalogueParamsWithLang) => boolean;
42
- export declare const isSameDtoProductParamsWithLang: (left: DtoProductParamsWithLang, right: DtoProductParamsWithLang) => boolean;
46
+ export declare const isSameDtoCatalogueParamsWithLang: (left: DtoCatalogueParamsWithCidAndLang, right: DtoCatalogueParamsWithCidAndLang) => boolean;
47
+ export declare const isSameDtoProductParamsWithLang: (left: DtoProductParamsWithCidAndLang, right: DtoProductParamsWithCidAndLang) => boolean;
43
48
  //# sourceMappingURL=utilitiesCatalogueData.d.ts.map
@@ -25,6 +25,13 @@ export const makeSelOptionsKey = (options) => options.reduce((p, option) => {
25
25
  p += "_}";
26
26
  return p;
27
27
  }, "");
28
+ /**
29
+ * Deep compare. Uses the JSON.stringify method for comparison
30
+ * @returns true if equal. Key and array order is respected.
31
+ */
32
+ export function compareCfgProductData(pd1, pd2) {
33
+ return JSON.stringify(pd1) === JSON.stringify(pd2);
34
+ }
28
35
  export function isModel(arg) {
29
36
  return typeof arg === "object" && arg !== null && "cid" in arg && "uri" in arg;
30
37
  }
@@ -1,10 +1,10 @@
1
- import { DtoCatalogueParams, DtoCataloguePermission } from "./CatalogueAPI.js";
1
+ import { DtoCatalogueParamsWithCid, DtoCataloguePermission } from "./CatalogueAPI.js";
2
2
  interface CataloguePermissionByEnterpriseKey {
3
3
  [key: string]: DtoCataloguePermission[];
4
4
  }
5
5
  export declare const groupAndSortCataloguePermissions: (cataloguePermissions: DtoCataloguePermission[]) => CataloguePermissionByEnterpriseKey;
6
6
  export declare const isParamSet: (param: string | undefined) => boolean;
7
- export declare const createCataloguePermissionsFilter: (catParams: Partial<DtoCatalogueParams>) => (perm: DtoCataloguePermission) => boolean;
7
+ export declare const createCataloguePermissionsFilter: (catParams: Partial<DtoCatalogueParamsWithCid>) => (perm: DtoCataloguePermission) => boolean;
8
8
  /**
9
9
  * Sometimes you will want to use the latest available prdCatVersion. This method will
10
10
  * find the highest prdCatVersion version in the cataloguePermissions. If the versions are
@@ -25,7 +25,7 @@ export declare const getPrdCatVersionFromPermissions: (cataloguePermissions: Dto
25
25
  * @param auth
26
26
  * @param params
27
27
  */
28
- export declare const getPrdCatVersionOrLatestFromPermissions: (params: DtoCatalogueParams, cataloguePermissions: DtoCataloguePermission[]) => string;
28
+ export declare const getPrdCatVersionOrLatestFromPermissions: (params: DtoCatalogueParamsWithCid, cataloguePermissions: DtoCataloguePermission[]) => string;
29
29
  /**
30
30
  * Sometimes you will want a missing prdCatVersion to represent "Get the current highest version".
31
31
  * This method will, if the prdCatVersion is not set, fetch the highest available from the
@@ -34,6 +34,6 @@ export declare const getPrdCatVersionOrLatestFromPermissions: (params: DtoCatalo
34
34
  * @param auth
35
35
  * @param params
36
36
  */
37
- export declare const fillMissingPrdCatVersionFromPermissions: <T extends DtoCatalogueParams>(params: T, cataloguePermissions: DtoCataloguePermission[]) => T;
37
+ export declare const fillMissingPrdCatVersionFromPermissions: <T extends DtoCatalogueParamsWithCid>(params: T, cataloguePermissions: DtoCataloguePermission[]) => T;
38
38
  export {};
39
39
  //# sourceMappingURL=utilitiesCataloguePermission.d.ts.map
@@ -0,0 +1,29 @@
1
+ import { DtoAdditionalProductConf, DtoAdditionalProductConfiguration, DtoFeatureConf, DtoProductConf, DtoSelectedOption } from "./CatalogueAPI.js";
2
+ /**
3
+ * @param ExtendedData Extra data, i.e. units and groupCodes
4
+ * @param ProductParams What Product the conf is for, and the same for any Additional Products.
5
+ * @param SyncGroupState The current sync group state
6
+ */
7
+ export declare enum CfgProdConfParts {
8
+ NoExtra = 0,
9
+ ExtendedData = 1,
10
+ ProdParams = 2,
11
+ SyncGroupState = 4
12
+ }
13
+ /** Is the newer version of product configuration */
14
+ export declare const isProductConf: (value: DtoAdditionalProductConfiguration | DtoProductConf) => value is DtoAdditionalProductConf;
15
+ /** Is the older version of product configuration */
16
+ export declare const isAdditionalProductConfiguration: (value: DtoAdditionalProductConfiguration | DtoProductConf) => value is DtoAdditionalProductConfiguration;
17
+ export declare const isDtoProductConfAdditional: (value: DtoProductConf) => value is DtoAdditionalProductConf;
18
+ export declare const convertDtoProductConfToV1: (conf: DtoProductConf, silenceWarnings?: boolean) => DtoAdditionalProductConfiguration;
19
+ export declare const convertDtoFeatureConfsToSelOptions: (features: DtoFeatureConf[], silenceWarnings?: boolean) => DtoSelectedOption[];
20
+ /**
21
+ * Serializes and compacts the configuration into a format especially suited for URLs
22
+ */
23
+ export declare const dtoProductConfigurationToCompactString: (conf: DtoProductConf) => string;
24
+ /**
25
+ * Deserializes and inflates the configuration from the compacted format
26
+ */
27
+ export declare const compactStringToDtoProductConf: (versionAndConf: string) => DtoProductConf;
28
+ export declare const stripExtendedDataFromDtoProductConf: (conf: DtoProductConf, toStrip: CfgProdConfParts) => DtoProductConf;
29
+ //# sourceMappingURL=utilitiesConfiguration.d.ts.map
@@ -0,0 +1,200 @@
1
+ /**
2
+ * @param ExtendedData Extra data, i.e. units and groupCodes
3
+ * @param ProductParams What Product the conf is for, and the same for any Additional Products.
4
+ * @param SyncGroupState The current sync group state
5
+ */
6
+ export var CfgProdConfParts;
7
+ (function (CfgProdConfParts) {
8
+ CfgProdConfParts[CfgProdConfParts["NoExtra"] = 0] = "NoExtra";
9
+ CfgProdConfParts[CfgProdConfParts["ExtendedData"] = 1] = "ExtendedData";
10
+ CfgProdConfParts[CfgProdConfParts["ProdParams"] = 2] = "ProdParams";
11
+ CfgProdConfParts[CfgProdConfParts["SyncGroupState"] = 4] = "SyncGroupState";
12
+ })(CfgProdConfParts || (CfgProdConfParts = {}));
13
+ /** Is the newer version of product configuration */
14
+ export const isProductConf = (value) => !("selOptions" in value);
15
+ /** Is the older version of product configuration */
16
+ export const isAdditionalProductConfiguration = (value) => "selOptions" in value;
17
+ export const isDtoProductConfAdditional = (value) => "refKey" in value;
18
+ // As this has potential to flood the terminal we only inform once
19
+ let hasInformedAboutProdParams = false;
20
+ let hasInformedAboutGroupCode = false;
21
+ let hasInformedAboutUnit = false;
22
+ export const convertDtoProductConfToV1 = (conf, silenceWarnings = false) => {
23
+ var _a, _b;
24
+ if (!silenceWarnings && conf.prodParams !== undefined && !hasInformedAboutProdParams) {
25
+ hasInformedAboutProdParams = true;
26
+ console.info("Incoming DtoProductConf contains prodParams. These will be ignored.");
27
+ }
28
+ const result = {
29
+ selOptions: ((_a = conf.features) !== null && _a !== void 0 ? _a : []).map((f) => ({
30
+ code: "!~!",
31
+ next: convertDtoFeatureConfToApiSelection(f, silenceWarnings),
32
+ })),
33
+ additionalProducts: ((_b = conf.additionalProducts) !== null && _b !== void 0 ? _b : []).map((p) => convertDtoProductConfToV1(p, silenceWarnings)),
34
+ selected: true,
35
+ };
36
+ if (isDtoProductConfAdditional(conf)) {
37
+ result.refKey = conf.refKey;
38
+ result.selected = conf.selected;
39
+ }
40
+ return result;
41
+ };
42
+ export const convertDtoFeatureConfsToSelOptions = (features, silenceWarnings = false) => (features !== null && features !== void 0 ? features : []).map((f) => ({
43
+ code: "!~!",
44
+ next: convertDtoFeatureConfToApiSelection(f, silenceWarnings),
45
+ }));
46
+ const convertDtoFeatureConfToApiSelection = (feature, silenceWarnings) => {
47
+ const { groupCode, options, unit } = feature;
48
+ if (!silenceWarnings && groupCode !== undefined && !hasInformedAboutGroupCode) {
49
+ hasInformedAboutGroupCode = true;
50
+ console.info("Incoming DtoFeature contains groupCode. It will be ignored.");
51
+ }
52
+ if (!silenceWarnings && unit !== undefined && !hasInformedAboutUnit) {
53
+ hasInformedAboutUnit = true;
54
+ console.info("Incoming DtoFeature contains a unit. It will be ignored.");
55
+ }
56
+ const result = {};
57
+ for (const option of (options !== null && options !== void 0 ? options : []).filter((o) => o.selected)) {
58
+ result[option.code] = convertDtoOptionConfToSelectedOption(option, silenceWarnings);
59
+ }
60
+ return result;
61
+ };
62
+ const convertDtoOptionConfToSelectedOption = (option, silenceWarnings) => {
63
+ const { features, code, numericValue } = option;
64
+ const selectionTrees = (features !== null && features !== void 0 ? features : []).map((f) => convertDtoFeatureConfToApiSelection(f, silenceWarnings));
65
+ const mergedSelectionTree = {};
66
+ let anyItems = false;
67
+ for (const selectionTree of selectionTrees) {
68
+ if (selectionTree === undefined) {
69
+ continue;
70
+ }
71
+ for (const key of Object.keys(selectionTree)) {
72
+ if (mergedSelectionTree[key] !== undefined) {
73
+ console.warn(`The key (${key}) is already used in the selection tree. Option code: "${code}".`);
74
+ continue;
75
+ }
76
+ mergedSelectionTree[key] = selectionTree[key];
77
+ anyItems = true;
78
+ }
79
+ }
80
+ const selectedOption = {
81
+ code,
82
+ numericValue,
83
+ };
84
+ if (anyItems) {
85
+ selectedOption.next = mergedSelectionTree;
86
+ }
87
+ return selectedOption;
88
+ };
89
+ const versionedRegex = /^v(\d+)(.+)$/;
90
+ const jsonKeyRegex = /"([^"]+)":/g;
91
+ const swapForUrlAdaptedRegex = /[-~_{}"]/g;
92
+ const shortToLong = new Map();
93
+ const longToShort = new Map();
94
+ // The replacement scheme here assumes this will only be used for keys
95
+ // in DtoProductConf and the knowledge that it contains no one
96
+ // one char keys.
97
+ for (const [long, short] of [
98
+ ["configuration", "c"],
99
+ ["additionalProducts", "a"],
100
+ ["prodParams", "p"],
101
+ ["refKey", "r"],
102
+ ["selected", "s"],
103
+ ["features", "f"],
104
+ ["code", "d"],
105
+ ["options", "o"],
106
+ ["numericValue", "n"],
107
+ ["groupCode", "g"],
108
+ ["unit", "u"],
109
+ ["syncGroupState", "sgs"],
110
+ ["selectOne", "so"],
111
+ ["selectMany", "sm"],
112
+ ["syncCode", "sc"],
113
+ ["optionCode", "oc"],
114
+ ]) {
115
+ shortToLong.set(short, long);
116
+ longToShort.set(long, short);
117
+ }
118
+ /**
119
+ * As certain chars are abundant in JSON but less abundant in the actual data
120
+ * we swap these so that frequent characters do not need to be URL-encoded.
121
+ */
122
+ const jsonStringSwapCharsForUrl = (data) => data.replace(swapForUrlAdaptedRegex, (char) => {
123
+ switch (char) {
124
+ case "{":
125
+ return "~";
126
+ case "}":
127
+ return "-";
128
+ case '"':
129
+ return "_";
130
+ case "~":
131
+ return "{";
132
+ case "-":
133
+ return "}";
134
+ case "_":
135
+ return '"';
136
+ default:
137
+ throw new Error(`Unexpected char "${char}" in swap for URL`);
138
+ }
139
+ });
140
+ const compactDtoProductConfJsonKeys = (data) => data.replace(jsonKeyRegex, (_, key) => { var _a; return `"${(_a = longToShort.get(key)) !== null && _a !== void 0 ? _a : key}":`; });
141
+ const expandDtoProductConfJsonKeys = (data) => data.replace(jsonKeyRegex, (_, key) => { var _a; return `"${(_a = shortToLong.get(key)) !== null && _a !== void 0 ? _a : key}":`; });
142
+ /**
143
+ * Serializes and compacts the configuration into a format especially suited for URLs
144
+ */
145
+ export const dtoProductConfigurationToCompactString = (conf) => "v1" +
146
+ jsonStringSwapCharsForUrl(compactDtoProductConfJsonKeys(JSON.stringify(conf, undefined, "")));
147
+ /**
148
+ * Deserializes and inflates the configuration from the compacted format
149
+ */
150
+ export const compactStringToDtoProductConf = (versionAndConf) => {
151
+ const match = versionedRegex.exec(versionAndConf);
152
+ if (match === null) {
153
+ throw new Error("Could not match version string");
154
+ }
155
+ const [, version, conf] = match;
156
+ if (version !== "1") {
157
+ throw new Error("Unknown packed URL version");
158
+ }
159
+ if (conf === "") {
160
+ throw new Error("No conf found");
161
+ }
162
+ return JSON.parse(expandDtoProductConfJsonKeys(jsonStringSwapCharsForUrl(conf)));
163
+ };
164
+ export const stripExtendedDataFromDtoProductConf = (conf, toStrip) => {
165
+ var _a, _b;
166
+ const stripped = {
167
+ features: (_a = conf.features) === null || _a === void 0 ? void 0 : _a.map((f) => stripExtendedDataFromDtoFeatureConf(f, toStrip)),
168
+ additionalProducts: (_b = conf.additionalProducts) === null || _b === void 0 ? void 0 : _b.map(stripExtendedDataFromDtoAdditionalProductConfiguration),
169
+ };
170
+ if ((toStrip & CfgProdConfParts.SyncGroupState) !== CfgProdConfParts.SyncGroupState) {
171
+ stripped.syncGroupState = conf.syncGroupState;
172
+ }
173
+ if ((toStrip & CfgProdConfParts.ProdParams) !== CfgProdConfParts.ProdParams) {
174
+ stripped.prodParams = conf.prodParams;
175
+ }
176
+ return stripped;
177
+ };
178
+ const stripExtendedDataFromDtoAdditionalProductConfiguration = (conf, toStrip) => (Object.assign(Object.assign({}, stripExtendedDataFromDtoProductConf(conf, toStrip)), { refKey: conf.refKey, selected: conf.selected }));
179
+ const stripExtendedDataFromDtoFeatureConf = (conf, toStrip) => {
180
+ var _a;
181
+ const stripped = {
182
+ code: conf.code,
183
+ options: (_a = conf.options) === null || _a === void 0 ? void 0 : _a.map((o) => stripExtendedDataFromDtoOptionConf(o, toStrip)),
184
+ };
185
+ if ((toStrip & CfgProdConfParts.ExtendedData) !== CfgProdConfParts.ExtendedData) {
186
+ // Keep in sync with getDtoConf in CfgFeature
187
+ stripped.groupCode = conf.groupCode;
188
+ stripped.unit = conf.unit;
189
+ }
190
+ return stripped;
191
+ };
192
+ const stripExtendedDataFromDtoOptionConf = (conf, toStrip) => {
193
+ var _a;
194
+ return ({
195
+ code: conf.code,
196
+ selected: conf.selected,
197
+ numericValue: conf.numericValue,
198
+ features: (_a = conf.features) === null || _a === void 0 ? void 0 : _a.map((f) => stripExtendedDataFromDtoFeatureConf(f, toStrip)),
199
+ });
200
+ };