@kosdev-code/kos-dispense-sdk 3.0.26 → 3.0.27

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 (65) hide show
  1. package/dispense-registration-manager-Da9CW_cN.js.map +1 -1
  2. package/dispense-registration-manager-Dtb31fcI.cjs.map +1 -1
  3. package/{extension-utils-CwctwFhK.cjs → extension-utils-Cfhe358W.cjs} +39 -166
  4. package/extension-utils-Cfhe358W.cjs.map +1 -0
  5. package/{extension-utils-C_pwmFbZ.js → extension-utils-D_dnBLH6.js} +39 -166
  6. package/extension-utils-D_dnBLH6.js.map +1 -0
  7. package/index.cjs +2 -2
  8. package/index.js +2 -2
  9. package/models/constants/constants.d.ts +14 -178
  10. package/models/constants/constants.d.ts.map +1 -1
  11. package/models/models/assembly/assembly-registration.d.ts +9 -69
  12. package/models/models/assembly/assembly-registration.d.ts.map +1 -1
  13. package/models/models/availability/availability-model.d.ts +10 -76
  14. package/models/models/availability/availability-model.d.ts.map +1 -1
  15. package/models/models/availability/types/index.d.ts +3 -12
  16. package/models/models/board/board-container-registration.d.ts +9 -74
  17. package/models/models/board/board-container-registration.d.ts.map +1 -1
  18. package/models/models/board/board-registration.d.ts +9 -72
  19. package/models/models/board/board-registration.d.ts.map +1 -1
  20. package/models/models/device-assembly/device-assembly-registration.d.ts +10 -76
  21. package/models/models/device-assembly/device-assembly-registration.d.ts.map +1 -1
  22. package/models/models/generic-pour/generic-pour-registration.d.ts +9 -72
  23. package/models/models/generic-pour/generic-pour-registration.d.ts.map +1 -1
  24. package/models/models/holder/holder-model.d.ts +9 -73
  25. package/models/models/holder/holder-model.d.ts.map +1 -1
  26. package/models/models/holder-container/holder-container-model.d.ts +9 -68
  27. package/models/models/holder-container/holder-container-model.d.ts.map +1 -1
  28. package/models/models/ingredient/ingredient-model.d.ts +9 -74
  29. package/models/models/ingredient/ingredient-model.d.ts.map +1 -1
  30. package/models/models/ingredient/types/index.d.ts +3 -10
  31. package/models/models/ingredient-container/ingredient-container-model.d.ts +9 -68
  32. package/models/models/ingredient-container/ingredient-container-model.d.ts.map +1 -1
  33. package/models/models/nozzle/nozzle-model.d.ts +10 -72
  34. package/models/models/nozzle/nozzle-model.d.ts.map +1 -1
  35. package/models/models/nozzle/services/nozzle-services.d.ts +11 -65
  36. package/models/models/nozzle/services/nozzle-services.d.ts.map +1 -1
  37. package/models/models/pump/pump-model.d.ts +9 -79
  38. package/models/models/pump/pump-model.d.ts.map +1 -1
  39. package/models/models/pump-container/pump-container-model.d.ts +9 -68
  40. package/models/models/pump-container/pump-container-model.d.ts.map +1 -1
  41. package/models/models/types/intent.d.ts +11 -78
  42. package/models/models/types/intent.d.ts.map +1 -1
  43. package/models/utils/extension-utils.d.ts +38 -165
  44. package/models/utils/extension-utils.d.ts.map +1 -1
  45. package/models.cjs +1 -1
  46. package/models.js +1 -1
  47. package/package.json +2 -2
  48. package/{pump-provider-CAKW652V.js → pump-provider-BQmCKz7S.js} +3 -5
  49. package/pump-provider-BQmCKz7S.js.map +1 -0
  50. package/{pump-provider-SXrqGmxO.cjs → pump-provider-uNNMh9uh.cjs} +3 -5
  51. package/pump-provider-uNNMh9uh.cjs.map +1 -0
  52. package/ui/hooks/cui-kit/use-default-cui-kit-lifecycle.d.ts +16 -43
  53. package/ui/hooks/cui-kit/use-default-cui-kit-lifecycle.d.ts.map +1 -1
  54. package/ui/hooks/ingredient/use-ingredient-pour.d.ts +7 -18
  55. package/ui/hooks/ingredient/use-ingredient-pour.d.ts.map +1 -1
  56. package/ui/hooks/nozzle-pour/use-nozzle-pour.d.ts +6 -17
  57. package/ui/hooks/nozzle-pour/use-nozzle-pour.d.ts.map +1 -1
  58. package/ui/hooks/pour/use-pour.d.ts +7 -18
  59. package/ui/hooks/pour/use-pour.d.ts.map +1 -1
  60. package/ui.cjs +1 -1
  61. package/ui.js +1 -1
  62. package/extension-utils-C_pwmFbZ.js.map +0 -1
  63. package/extension-utils-CwctwFhK.cjs.map +0 -1
  64. package/pump-provider-CAKW652V.js.map +0 -1
  65. package/pump-provider-SXrqGmxO.cjs.map +0 -1
@@ -80,55 +80,18 @@ const getFuelGaugeValue = (holder) => {
80
80
  class DispenseExtensionManager {
81
81
  core = new kosUiSdk.CoreExtensionManager();
82
82
  /**
83
- * Maps data into the {@link IngredientModel}
83
+ * Registers a data mapper for the {@link IngredientModel}.
84
84
  *
85
- * It is common for the ingredient data provided by the ingredient service to be augmented with additional properties that are
86
- * not provided by the base KOS Ingredient model. The {@link IngredientMapper} extension point allows for the data to be mapped
87
- * into the {@link IngredientModel} and the {@link IngredientModel.data} property to be augmented with additional properties.
85
+ * Ingredient service data often needs properties the base model does not carry. The mapper receives each
86
+ * {@link IngredientResponse} and the data returned by the ingredient loader as context, and its result
87
+ * becomes the model's `data` property.
88
88
  *
89
89
  * @param ingredientDataMapper - Mapping function that maps an {@link IngredientResponse} into additional model data
90
90
  * @param options - Optional {@link ExtensionOptions} to control failure behavior.
91
91
  * Defaults to `failurePolicy: "throw"`, which throws an {@link ExtensionException} on mapper failure.
92
92
  * Set to `"continue"` to log the error and continue processing remaining mappers.
93
93
  * @returns this instance for chaining
94
- *
95
- * @example
96
- * The following example shows how to map the data from the service response into the {@link IngredientModel}.
97
- * The context is provided by the {@link IngredientLoader} extension point with its data being used to optionally augment the
98
- * ingredient data.
99
- *
100
- * The result of the mapping will be available in the `data` property of the {@link IngredientModel}.
101
- *
102
- * In this case the `IngedientReponseData` interface represents the data being returned by the ingredient service and the
103
- * `IngredientData` interface represents the data that will be available in the {@link IngredientModel.data} property. The `ingredientDataMapper`
104
- * is responsible for mapping from one format to the other.
105
- *
106
- * ```typescript
107
- *
108
- * interface IngredientResponseData extends NozzleServices.IngredientResponse {
109
- * chilled: boolean;
110
- * carbonated: boolean;
111
- * highYield: boolean;
112
- * }
113
- *
114
- * interface IngredientData {
115
- * chilled: boolean;
116
- * carbonated: boolean;
117
- * highYield: boolean;
118
- * }
119
- *
120
- * export const ingredientDataMapper = async (
121
- * data: IngredientResponseData,
122
- * context: IngredientContext
123
- * ): Promise<IngredientData> => {
124
- * return {
125
- * chilled: data.chilled,
126
- * carbonated: data.carbonated,
127
- * highYield: data.highYield,
128
- * }
129
- * }
130
- * ```
131
- * */
94
+ */
132
95
  registerIngredientDataMapper(ingredientDataMapper, options) {
133
96
  kosUiSdk.ExtensionManager.dataMapper.registerDataMapper(
134
97
  dispenseRegistrationManager.ExtensionType.IngredientMapper,
@@ -138,34 +101,14 @@ class DispenseExtensionManager {
138
101
  return this;
139
102
  }
140
103
  /**
141
- * Loads data that will be provided as context into the {@link IngredientMapper}.
104
+ * Registers a loader whose result is passed as context to the ingredient data and type mappers.
142
105
  *
143
106
  * @param ingredientLoader - Async function that loads and returns ingredient context data
144
107
  * @param options - Optional {@link ExtensionOptions} to control failure behavior.
145
108
  * Defaults to `failurePolicy: "throw"`, which throws an {@link ExtensionException} on loader failure.
146
109
  * Set to `"continue"` to log the error and return `undefined` instead.
147
110
  * @returns this instance for chaining
148
- *
149
- * @example
150
- * The following example shows how to load the brandset data, normalize it into a map and then provide it back to the framework
151
- * where it can be used by the other extension points.
152
- *
153
- * In the ingredient container model, the data is provided to the {@link IngredientMapper} extension point in order to augment ingredient data
154
- * and also loaded into the ingredient container model context in order to make the data available throughout the code.
155
- *
156
- * ```typescript
157
- * export const ingredientContextLoader = async (): Promise<BeverageContext> => {
158
- * const response = await kosFetch('kos:/system/some/ingredient/endpoint.json');
159
- *
160
- * if (response.status !== 200) {
161
- * KosLog.error('Failed to load ingredient data');
162
- * return {};
163
- * }
164
- * const json = await response.json();
165
- * return json;
166
- * };
167
- * ```
168
- * */
111
+ */
169
112
  registerIngredientLoader(ingredientLoader, options) {
170
113
  kosUiSdk.ExtensionManager.loader.registerLoader(
171
114
  dispenseRegistrationManager.ExtensionType.IngredientLoader,
@@ -261,7 +204,10 @@ class DispenseExtensionManager {
261
204
  return this;
262
205
  }
263
206
  /**
264
- * Maps data into the {@link AvailabilityModel}.
207
+ * Registers a data mapper for the {@link AvailabilityModel}.
208
+ *
209
+ * The mapper receives each availability node, with its `groupId`, and the data returned by the
210
+ * availability loader as context. Its result becomes the model's `data` property.
265
211
  *
266
212
  * @param availabilityMapper - Mapping function that maps a {@link GroupBeverageResponse} into additional availability data
267
213
  * @param options - Optional {@link ExtensionOptions} to control failure behavior.
@@ -270,28 +216,15 @@ class DispenseExtensionManager {
270
216
  * @returns this instance for chaining
271
217
  *
272
218
  * @example
273
- * The following example shows how to map the data from the service response into the {@link AvailabilityModel}.
274
- * The context is provided by the {@link AvailabilityLoader} extension point with its data being used to augment the
275
- * availability data.
276
- *
277
- * The result of the mapping will be available in the `data` property of the {@link AvailabilityModel}.
278
- *
279
219
  * ```typescript
280
- * export const beverageDataMapper = async (
281
- * data: NozzleServices.BeverageResponse,
282
- * context: BeverageContext
283
- * ): Promise<BeverageData> => {
284
- * const id = data.altId;
285
- * const iconUrl = encodeURI(
286
- * `http://localhost:8081/system/brandset/${context?.[id]?.icon}`
287
- * );
288
- * const cuiColorCode = context?.[id]?.cuiColorCode
289
- * ? context?.[id]?.cuiColorCode
290
- * : '';
291
- * return { iconUrl, cuiColorCode };
292
- * };
220
+ * const beverageDataMapper: AvailabilityDataMapper<BeverageData> = async (
221
+ * data,
222
+ * context?: Record<string, BrandsetIngredient>
223
+ * ) => ({
224
+ * iconUrl: context?.[data.altId]?.icon ?? "",
225
+ * });
293
226
  * ```
294
- * */
227
+ */
295
228
  registerAvailabilityDataMapper(availabilityMapper, options) {
296
229
  kosUiSdk.ExtensionManager.dataMapper.registerDataMapper(
297
230
  dispenseRegistrationManager.ExtensionType.AvailabilityMapper,
@@ -301,7 +234,8 @@ class DispenseExtensionManager {
301
234
  return this;
302
235
  }
303
236
  /**
304
- * Loads data that will be provided as context into the {@link AvailabilityMapper}.
237
+ * Registers a loader whose result is passed as context to the availability data mapper. A common use is
238
+ * loading UI-specific brandset data that the backend service does not provide.
305
239
  *
306
240
  * @param availabilityLoader - Async function that loads and returns availability context data
307
241
  * @param options - Optional {@link ExtensionOptions} to control failure behavior.
@@ -310,32 +244,14 @@ class DispenseExtensionManager {
310
244
  * @returns this instance for chaining
311
245
  *
312
246
  * @example
313
- * A common use case is to load brandset data that is UI specific and not provided directly by the Java service.
314
- *
315
- * The following example shows how to load the brandset data, normalize it into a map and then provide it back to the framework
316
- * where it can be used by the other extension points.
317
- *
318
- * In the nozzle model, the data is provided to the {@link AvailabilityMapper} extension point in order to augment availability data
319
- * and also loaded into the nozzle model context in order to make the data available throughout the code.
320
- *
321
247
  * ```typescript
322
- * export const beverageContextLoader = async (): Promise<BeverageContext> => {
323
- * const response = await kosFetch('kos:/system/brandset/brandset.json');
324
- *
325
- * if (response.status !== 200) {
326
- * KosLog.error('Failed to load beverage data');
327
- * return {};
328
- * }
329
- * const json: BrandsetResponse | null = await response.json();
330
- * const initialBeverages: Record<string, BrandsetIngredient> = {};
331
- * const beverages = json?.ingredients?.reduce((acc, beverage) => {
332
- * acc[beverage.ingredientId] = beverage;
333
- * return acc;
334
- * }, initialBeverages);
335
- * return beverages;
336
- * };
248
+ * const beverageContextLoader = async () => {
249
+ * const response = await kosFetch("kos:/system/brandset/brandset.json");
250
+ * const json: BrandsetResponse = await response.json();
251
+ * return Object.fromEntries(json.ingredients.map((i) => [i.ingredientId, i]));
252
+ * };
337
253
  * ```
338
- * */
254
+ */
339
255
  registerAvailabilityLoader(availabilityLoader, options) {
340
256
  kosUiSdk.ExtensionManager.loader.registerLoader(
341
257
  dispenseRegistrationManager.ExtensionType.AvailabilityLoader,
@@ -362,9 +278,8 @@ class DispenseExtensionManager {
362
278
  return this;
363
279
  }
364
280
  /**
365
- * Maps data into the {@link AssemblyModel} data.
366
- * Used in cases where the base assembly has been extended with additional properties in the backend. This extension
367
- * point allows for the data to be mapped into the {@link AssemblyModel} and augmented with additional properties.
281
+ * Registers a data mapper for the {@link AssemblyModel}, for backends that extend the assembly response
282
+ * with additional properties. The mapper's result is merged into the assembly model.
368
283
  *
369
284
  * @param assemblyDataMapper - Mapping function that maps an {@link AssemblyTypes.AssemblyResponse} into additional assembly data
370
285
  * @param options - Optional {@link ExtensionOptions} to control failure behavior.
@@ -373,60 +288,18 @@ class DispenseExtensionManager {
373
288
  * @returns this instance for chaining
374
289
  *
375
290
  * @example
376
- *
377
- * In this example of an implementation of a {@link AssemblyMapper}, the {@link AssemblyResponse} data is mapped into
378
- * a {@link FreestyleAssembly} object.
379
- *
380
- * The {@link FreestyleAssemblyResponse} interface represents the additional data being returned by the assembly service and is
381
- * merged into the {@link AssemblyResponse} interface.
382
- *
383
- * The {@link FreestyleAssembly} interface represents the additional data, beyond the base data set, that will be merged into the {@link AssemblyModel}.
384
- *
385
- * The mapper is responsible for mapping from the {@link FreestyleAssemblyResponse} format to the {@link FreestyleAssembly} format.
386
291
  * ```typescript
387
- * import { AssemblyTypes } from "@kosdev-code/kos-dispense-sdk";
388
- * import { DataMapper } from "@kosdev-code/kos-ui-sdk";
389
- *
390
- * // define the additional data being returned by the assembly service
391
- * export interface FreestyleAssemblyResponse {
392
- * iceAgitator?: {
393
- * name: "iceAgitator";
394
- * path: string;
395
- * };
396
- * }
397
- *
398
- * // define the additional data structure that will be merged into the assembly model
399
- * export interface FreestyleAssembly {
400
- * iceAgitator: {
401
- * path: string;
402
- * };
403
- * carbAgitator: {
404
- * path: string;
405
- * };
406
- * }
407
- *
408
- *
409
- * // define the mapper that will map the data from the service response into the additional data structure
410
- * // that will be merged into the assembly model.
411
- * // In this case the mapper is responsible for mapping from the {@link FreestyleAssemblyResponse} format to the {@link FreestyleAssembly} format.
412
- * export const assemblyDataMapper: DataMapper<
413
- * AssemblyTypes.AssemblyResponse<FreestyleAssemblyResponse>,
414
- * FreestyleAssembly
415
- * > = async (data) => {
416
- * const response = data.assemblies.reduce((acc, assembly) => {
417
- * const agitatorKeys = ["iceAgitator", "carbAgitator"];
418
- * agitatorKeys.forEach((key) => {
419
- * const agitator = assembly[key];
420
- * if (agitator) {
421
- * acc[key] = agitator;
422
- * }
423
- * });
292
+ * interface IceAgitatorExt {
293
+ * iceAgitator?: { name: string; path: string };
294
+ * }
424
295
  *
425
- * return acc;
426
- * }, {} as FreestyleAssembly);
427
- * return response;
428
- * };
429
- *```
296
+ * const assemblyDataMapper: AssemblyMapper<
297
+ * { iceAgitatorPath?: string },
298
+ * AssemblyTypes.AssemblyResponse<{ AssemblyExt: IceAgitatorExt }>
299
+ * > = async (data) => ({
300
+ * iceAgitatorPath: data.assemblies.find((a) => a.iceAgitator)?.iceAgitator?.path,
301
+ * });
302
+ * ```
430
303
  */
431
304
  registerAssemblyDataMapper(assemblyDataMapper, options) {
432
305
  kosUiSdk.ExtensionManager.dataMapper.registerDataMapper(
@@ -486,4 +359,4 @@ exports.index$2 = index$4;
486
359
  exports.index$3 = index$5;
487
360
  exports.index$4 = index$1;
488
361
  exports.index$5 = index$2;
489
- //# sourceMappingURL=extension-utils-CwctwFhK.cjs.map
362
+ //# sourceMappingURL=extension-utils-Cfhe358W.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension-utils-Cfhe358W.cjs","sources":["../../../packages/kos-dispense-sdk/src/models/models/holder/utils/holder-utils.ts","../../../packages/kos-dispense-sdk/src/models/utils/extension-utils.ts"],"sourcesContent":["import { kosAutoEffect } from \"@kosdev-code/kos-ui-sdk\";\nimport { useEffect, useState } from \"react\";\nimport type { HolderModel } from \"../types\";\n\nexport const getFuelGaugeValue = (holder: HolderModel) => {\n const [maxVolume, setMaxVolume] = useState<number>(\n holder?.slice?.maxVolMl ?? 0\n );\n const [remainingVolume, setRemainingVolume] = useState<number>(\n holder?.slice?.currentVolMl ?? 0\n );\n\n const [hasMaxVolume, setHasMaxVolume] = useState<boolean>(\n holder?.slice?.maxVolMl !== undefined\n );\n\n const [hasRemainingVolume, setHasRemainingVolume] = useState<boolean>(\n holder?.slice?.currentVolMl !== undefined\n );\n\n const [fillPercent, setFillPercent] = useState<number>(\n remainingVolume <= 0\n ? 0\n : Math.floor(((remainingVolume || 1) / (maxVolume || 1)) * 100)\n );\n\n const [hasFuelGuage, setHasFuelGuage] = useState<boolean>(\n hasMaxVolume && hasRemainingVolume\n );\n\n useEffect(() => {\n const disposer = kosAutoEffect(() => {\n setMaxVolume(holder?.slice?.maxVolMl ?? 0);\n setRemainingVolume(holder?.slice?.currentVolMl ?? 0);\n setHasMaxVolume(holder?.slice?.maxVolMl !== undefined);\n setHasRemainingVolume(holder?.slice?.currentVolMl !== undefined);\n setFillPercent(\n remainingVolume <= 0\n ? 0\n : Math.floor(((remainingVolume || 1) / (maxVolume || 1)) * 100)\n );\n setHasFuelGuage(hasMaxVolume && hasRemainingVolume);\n });\n\n return () => {\n disposer();\n };\n }, [holder]);\n\n return { maxVolume, remainingVolume, fillPercent, hasFuelGuage };\n};\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {\n CoreExtensionManager,\n DataLoader,\n DataMapper,\n EXTENSION_FEATURE_FLAG_RESOLVER,\n ExtensionManager,\n ExtensionOptions,\n IndexExtension,\n PropertyMapper,\n type FlagResolver,\n} from \"@kosdev-code/kos-ui-sdk\";\nimport { ExtensionType } from \"../constants\";\nimport { AssemblyTypes, type AssemblyModel } from \"../models\";\nimport type { HolderResponse } from \"../models/holder/services\";\nimport type { HolderModel } from \"../models/holder/types\";\nimport type { IngredientResponse } from \"../models/ingredient/services\";\nimport type { BeverageResponse } from \"../models/nozzle/services\";\nimport type { SelectedPourable } from \"../models/nozzle/types\";\n\nexport type IngredientDataMapper<\n AdditionalData extends object = Record<string, any>\n> = DataMapper<IngredientResponse, AdditionalData, any>;\n\n/**\n * Mapping function that maps an ingredient response into the type property of\n * the {@link IngredientModel}.\n */\nexport type IngredientTypeMapper<\n T extends IngredientResponse = IngredientResponse\n> = PropertyMapper<T, string>;\n\n/**\n * Mapping function that maps additional data from holder service response\n * into the {@link HolderModel} data.\n */\nexport type HolderTypeMapper<T extends HolderResponse = HolderResponse> =\n PropertyMapper<T, string>;\n\n/**\n * Mapping function that maps additional data from holder service response\n * into the {@link HolderModel} data.\n */\nexport type HolderDataMapper<\n AdditionalData extends object = Record<string, any>,\n HolderData extends HolderResponse = HolderResponse\n> = DataMapper<HolderData, AdditionalData, any>;\n\nexport type GroupBeverageResponse = BeverageResponse & { groupId: string };\nexport type AvailabilityDataMapper<\n AdditionalData extends object = Record<string, any>,\n AvailabilityData extends GroupBeverageResponse = GroupBeverageResponse\n> = DataMapper<AvailabilityData, AdditionalData, any>;\n\nexport type SelectedPourableMapper = DataMapper<SelectedPourable, any>;\n\nexport type BoardDataMapper<\n AdditionalData extends object = Record<string, any>,\n BoardData extends AssemblyTypes.AssemblyBoard<any> = AssemblyTypes.AssemblyBoard<any>\n> = DataMapper<BoardData, AdditionalData, any>;\n\nexport type AssemblyMapper<\n AdditionalData extends object = Record<string, any>,\n AssemblyResponseData extends AssemblyTypes.AssemblyResponse<any> = AssemblyTypes.AssemblyResponse<any>\n> = DataMapper<AssemblyResponseData, AdditionalData, any>;\n/**\n * The DispenseExtensionManager is responsible for managing the extension points that are specific to the Dispense application.\n */\nexport class DispenseExtensionManager {\n core: CoreExtensionManager = new CoreExtensionManager();\n /**\n * Registers a data mapper for the {@link IngredientModel}.\n *\n * Ingredient service data often needs properties the base model does not carry. The mapper receives each\n * {@link IngredientResponse} and the data returned by the ingredient loader as context, and its result\n * becomes the model's `data` property.\n *\n * @param ingredientDataMapper - Mapping function that maps an {@link IngredientResponse} into additional model data\n * @param options - Optional {@link ExtensionOptions} to control failure behavior.\n * Defaults to `failurePolicy: \"throw\"`, which throws an {@link ExtensionException} on mapper failure.\n * Set to `\"continue\"` to log the error and continue processing remaining mappers.\n * @returns this instance for chaining\n */\n registerIngredientDataMapper(\n ingredientDataMapper: IngredientDataMapper,\n options?: ExtensionOptions\n ) {\n ExtensionManager.dataMapper.registerDataMapper(\n ExtensionType.IngredientMapper,\n ingredientDataMapper,\n options\n );\n\n return this;\n }\n\n /**\n * Registers a loader whose result is passed as context to the ingredient data and type mappers.\n *\n * @param ingredientLoader - Async function that loads and returns ingredient context data\n * @param options - Optional {@link ExtensionOptions} to control failure behavior.\n * Defaults to `failurePolicy: \"throw\"`, which throws an {@link ExtensionException} on loader failure.\n * Set to `\"continue\"` to log the error and return `undefined` instead.\n * @returns this instance for chaining\n */\n registerIngredientLoader(\n ingredientLoader: DataLoader,\n options?: ExtensionOptions\n ) {\n ExtensionManager.loader.registerLoader(\n ExtensionType.IngredientLoader,\n ingredientLoader,\n options\n );\n return this;\n }\n\n registerIngredientIndex(ingredientIndex: IndexExtension) {\n ExtensionManager.indexExtension.registerIndexExtension(\n ExtensionType.IngredientIndex,\n ingredientIndex\n );\n return this;\n }\n\n /**\n * Registers a property mapper that derives the `type` property of the {@link IngredientModel}\n * from an {@link IngredientResponse}.\n *\n * @param ingredientTypeMapper - Mapping function that extracts a type string from an {@link IngredientResponse}\n * @param options - Optional {@link ExtensionOptions} to control failure behavior.\n * Defaults to `failurePolicy: \"throw\"`, which throws an {@link ExtensionException} on mapper failure.\n * Set to `\"continue\"` to log the error and return a fallback value instead.\n * @returns this instance for chaining\n * */\n registerIngredientTypeMapper(\n ingredientTypeMapper: IngredientTypeMapper,\n options?: ExtensionOptions\n ) {\n ExtensionManager.propertyMapper.registerPropertyMapper(\n ExtensionType.IngredientTypeMapper,\n ingredientTypeMapper,\n options\n );\n return this;\n }\n\n /**\n * Registers a data mapper for the {@link HolderModel} model.\n *\n * @param holderDataMapper - Mapping function that maps additional data from a {@link HolderResponse}\n * @param options - Optional {@link ExtensionOptions} to control failure behavior.\n * Defaults to `failurePolicy: \"throw\"`, which throws an {@link ExtensionException} on mapper failure.\n * Set to `\"continue\"` to log the error and continue processing remaining mappers.\n * @returns this instance for chaining\n */\n registerHolderDataMapper(\n holderDataMapper: HolderDataMapper,\n options?: ExtensionOptions\n ) {\n ExtensionManager.dataMapper.registerDataMapper(\n ExtensionType.HolderMapper,\n holderDataMapper,\n options\n );\n return this;\n }\n\n /**\n * Registers a property mapper that derives the `type` property of the {@link HolderModel}\n * from a {@link HolderResponse}.\n *\n * @param holderTypeMapper - Mapping function that extracts a type string from a {@link HolderResponse}\n * @param options - Optional {@link ExtensionOptions} to control failure behavior.\n * Defaults to `failurePolicy: \"throw\"`, which throws an {@link ExtensionException} on mapper failure.\n * Set to `\"continue\"` to log the error and return a fallback value instead.\n * @returns this instance for chaining\n */\n registerHolderTypeMapper(\n holderTypeMapper: HolderTypeMapper,\n options?: ExtensionOptions\n ) {\n ExtensionManager.propertyMapper.registerPropertyMapper(\n ExtensionType.HolderTypeMapper,\n holderTypeMapper,\n options\n );\n return this;\n }\n\n /**\n * Maps the ingredientId property of the holder into the {@link HolderModel}.\n * If not provided, the ingredientId will assume that the value is mapped from the\n * ingredientId property of the service response.\n *\n * @param holderTypeMapper - Mapping function that extracts the ingredientId from a {@link HolderResponse}\n * @param options - Optional {@link ExtensionOptions} to control failure behavior.\n * Defaults to `failurePolicy: \"throw\"`, which throws an {@link ExtensionException} on mapper failure.\n * Set to `\"continue\"` to log the error and return a fallback value instead.\n * @returns this instance for chaining\n * */\n registerHolderIngredientMapper(\n holderTypeMapper: HolderTypeMapper,\n options?: ExtensionOptions\n ) {\n ExtensionManager.propertyMapper.registerPropertyMapper(\n ExtensionType.HolderTypeMapper,\n holderTypeMapper,\n options\n );\n return this;\n }\n\n registerHolderIndex<T extends HolderModel = HolderModel>(\n holderIndex: IndexExtension<T>\n ) {\n ExtensionManager.indexExtension.registerIndexExtension(\n ExtensionType.HolderIndex,\n holderIndex\n );\n return this;\n }\n\n /**\n * Registers a data mapper for the {@link AvailabilityModel}.\n *\n * The mapper receives each availability node, with its `groupId`, and the data returned by the\n * availability loader as context. Its result becomes the model's `data` property.\n *\n * @param availabilityMapper - Mapping function that maps a {@link GroupBeverageResponse} into additional availability data\n * @param options - Optional {@link ExtensionOptions} to control failure behavior.\n * Defaults to `failurePolicy: \"throw\"`, which throws an {@link ExtensionException} on mapper failure.\n * Set to `\"continue\"` to log the error and continue processing remaining mappers.\n * @returns this instance for chaining\n *\n * @example\n * ```typescript\n * const beverageDataMapper: AvailabilityDataMapper<BeverageData> = async (\n * data,\n * context?: Record<string, BrandsetIngredient>\n * ) => ({\n * iconUrl: context?.[data.altId]?.icon ?? \"\",\n * });\n * ```\n */\n registerAvailabilityDataMapper(\n availabilityMapper: AvailabilityDataMapper,\n options?: ExtensionOptions\n ) {\n ExtensionManager.dataMapper.registerDataMapper(\n ExtensionType.AvailabilityMapper,\n availabilityMapper,\n options\n );\n return this;\n }\n\n /**\n * Registers a loader whose result is passed as context to the availability data mapper. A common use is\n * loading UI-specific brandset data that the backend service does not provide.\n *\n * @param availabilityLoader - Async function that loads and returns availability context data\n * @param options - Optional {@link ExtensionOptions} to control failure behavior.\n * Defaults to `failurePolicy: \"throw\"`, which throws an {@link ExtensionException} on loader failure.\n * Set to `\"continue\"` to log the error and return `undefined` instead.\n * @returns this instance for chaining\n *\n * @example\n * ```typescript\n * const beverageContextLoader = async () => {\n * const response = await kosFetch(\"kos:/system/brandset/brandset.json\");\n * const json: BrandsetResponse = await response.json();\n * return Object.fromEntries(json.ingredients.map((i) => [i.ingredientId, i]));\n * };\n * ```\n */\n registerAvailabilityLoader(\n availabilityLoader: DataLoader,\n options?: ExtensionOptions\n ) {\n ExtensionManager.loader.registerLoader(\n ExtensionType.AvailabilityLoader,\n availabilityLoader,\n options\n );\n return this;\n }\n\n /**\n * Maps the abstract {@link SelectedPourable} data into a format that is specific to the nozzle.\n *\n * @param selectedPourableMapper - Mapping function that transforms {@link SelectedPourable} data\n * @param options - Optional {@link ExtensionOptions} to control failure behavior.\n * Defaults to `failurePolicy: \"throw\"`, which throws an {@link ExtensionException} on mapper failure.\n * Set to `\"continue\"` to log the error and continue processing remaining mappers.\n * @returns this instance for chaining\n * */\n registerSelectedPourableDataMapper(\n selectedPourableMapper: SelectedPourableMapper,\n options?: ExtensionOptions\n ) {\n ExtensionManager.dataMapper.registerDataMapper(\n ExtensionType.SelectedPourableMapper,\n selectedPourableMapper,\n options\n );\n return this;\n }\n\n /**\n * Registers a data mapper for the {@link AssemblyModel}, for backends that extend the assembly response\n * with additional properties. The mapper's result is merged into the assembly model.\n *\n * @param assemblyDataMapper - Mapping function that maps an {@link AssemblyTypes.AssemblyResponse} into additional assembly data\n * @param options - Optional {@link ExtensionOptions} to control failure behavior.\n * Defaults to `failurePolicy: \"throw\"`, which throws an {@link ExtensionException} on mapper failure.\n * Set to `\"continue\"` to log the error and continue processing remaining mappers.\n * @returns this instance for chaining\n *\n * @example\n * ```typescript\n * interface IceAgitatorExt {\n * iceAgitator?: { name: string; path: string };\n * }\n *\n * const assemblyDataMapper: AssemblyMapper<\n * { iceAgitatorPath?: string },\n * AssemblyTypes.AssemblyResponse<{ AssemblyExt: IceAgitatorExt }>\n * > = async (data) => ({\n * iceAgitatorPath: data.assemblies.find((a) => a.iceAgitator)?.iceAgitator?.path,\n * });\n * ```\n */\n registerAssemblyDataMapper(\n assemblyDataMapper: AssemblyMapper,\n options?: ExtensionOptions\n ) {\n ExtensionManager.dataMapper.registerDataMapper(\n ExtensionType.AssemblyMapper,\n assemblyDataMapper,\n options\n );\n return this;\n }\n\n registerBoardIndex(boardIndex: IndexExtension) {\n ExtensionManager.indexExtension.registerIndexExtension(\n ExtensionType.BoardIndex,\n boardIndex\n );\n return this;\n }\n\n /**\n * Registers a data mapper for the board model within an assembly.\n *\n * @param boardDataMapper - Mapping function that maps an {@link AssemblyTypes.AssemblyBoard} into additional board data\n * @param options - Optional {@link ExtensionOptions} to control failure behavior.\n * Defaults to `failurePolicy: \"throw\"`, which throws an {@link ExtensionException} on mapper failure.\n * Set to `\"continue\"` to log the error and continue processing remaining mappers.\n * @returns this instance for chaining\n */\n registerBoardDataMapper(\n boardDataMapper: BoardDataMapper<any, any>,\n options?: ExtensionOptions\n ) {\n ExtensionManager.dataMapper.registerDataMapper(\n ExtensionType.BoardMapper,\n boardDataMapper,\n options\n );\n return this;\n }\n\n registerAssemblyFeatureFlagResolver(\n assemblyFeatureFlagResolver: FlagResolver<AssemblyModel>\n ) {\n ExtensionManager[EXTENSION_FEATURE_FLAG_RESOLVER]?.register(\n ExtensionType.AssemblyFeatureFlags,\n assemblyFeatureFlagResolver\n );\n return this;\n }\n}\n\n/**\n * The KosExtensionManager provides access to the extension points that are provided in the SDK for Dispense applications.\n *\n * The extension points are divided into two categories:\n *\n * @param core - The core extension {@link CoreExtensionManager} points are used to extend the base models that are provided by the SDK.\n * @param dispense - The dispense extension {@link DispenseExtensionManager} points are used to extend the models that are specific to the Dispense SDK.\n */\nexport class KosExtensionManager {\n dispense: DispenseExtensionManager;\n core: CoreExtensionManager;\n constructor() {\n this.dispense = new DispenseExtensionManager();\n this.core = new CoreExtensionManager();\n }\n}\n"],"names":["useState","useEffect","kosAutoEffect","CoreExtensionManager","ExtensionManager","ExtensionType","EXTENSION_FEATURE_FLAG_RESOLVER"],"mappings":"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"}
@@ -79,55 +79,18 @@ const getFuelGaugeValue = (holder) => {
79
79
  class DispenseExtensionManager {
80
80
  core = new CoreExtensionManager();
81
81
  /**
82
- * Maps data into the {@link IngredientModel}
82
+ * Registers a data mapper for the {@link IngredientModel}.
83
83
  *
84
- * It is common for the ingredient data provided by the ingredient service to be augmented with additional properties that are
85
- * not provided by the base KOS Ingredient model. The {@link IngredientMapper} extension point allows for the data to be mapped
86
- * into the {@link IngredientModel} and the {@link IngredientModel.data} property to be augmented with additional properties.
84
+ * Ingredient service data often needs properties the base model does not carry. The mapper receives each
85
+ * {@link IngredientResponse} and the data returned by the ingredient loader as context, and its result
86
+ * becomes the model's `data` property.
87
87
  *
88
88
  * @param ingredientDataMapper - Mapping function that maps an {@link IngredientResponse} into additional model data
89
89
  * @param options - Optional {@link ExtensionOptions} to control failure behavior.
90
90
  * Defaults to `failurePolicy: "throw"`, which throws an {@link ExtensionException} on mapper failure.
91
91
  * Set to `"continue"` to log the error and continue processing remaining mappers.
92
92
  * @returns this instance for chaining
93
- *
94
- * @example
95
- * The following example shows how to map the data from the service response into the {@link IngredientModel}.
96
- * The context is provided by the {@link IngredientLoader} extension point with its data being used to optionally augment the
97
- * ingredient data.
98
- *
99
- * The result of the mapping will be available in the `data` property of the {@link IngredientModel}.
100
- *
101
- * In this case the `IngedientReponseData` interface represents the data being returned by the ingredient service and the
102
- * `IngredientData` interface represents the data that will be available in the {@link IngredientModel.data} property. The `ingredientDataMapper`
103
- * is responsible for mapping from one format to the other.
104
- *
105
- * ```typescript
106
- *
107
- * interface IngredientResponseData extends NozzleServices.IngredientResponse {
108
- * chilled: boolean;
109
- * carbonated: boolean;
110
- * highYield: boolean;
111
- * }
112
- *
113
- * interface IngredientData {
114
- * chilled: boolean;
115
- * carbonated: boolean;
116
- * highYield: boolean;
117
- * }
118
- *
119
- * export const ingredientDataMapper = async (
120
- * data: IngredientResponseData,
121
- * context: IngredientContext
122
- * ): Promise<IngredientData> => {
123
- * return {
124
- * chilled: data.chilled,
125
- * carbonated: data.carbonated,
126
- * highYield: data.highYield,
127
- * }
128
- * }
129
- * ```
130
- * */
93
+ */
131
94
  registerIngredientDataMapper(ingredientDataMapper, options) {
132
95
  ExtensionManager.dataMapper.registerDataMapper(
133
96
  ExtensionType.IngredientMapper,
@@ -137,34 +100,14 @@ class DispenseExtensionManager {
137
100
  return this;
138
101
  }
139
102
  /**
140
- * Loads data that will be provided as context into the {@link IngredientMapper}.
103
+ * Registers a loader whose result is passed as context to the ingredient data and type mappers.
141
104
  *
142
105
  * @param ingredientLoader - Async function that loads and returns ingredient context data
143
106
  * @param options - Optional {@link ExtensionOptions} to control failure behavior.
144
107
  * Defaults to `failurePolicy: "throw"`, which throws an {@link ExtensionException} on loader failure.
145
108
  * Set to `"continue"` to log the error and return `undefined` instead.
146
109
  * @returns this instance for chaining
147
- *
148
- * @example
149
- * The following example shows how to load the brandset data, normalize it into a map and then provide it back to the framework
150
- * where it can be used by the other extension points.
151
- *
152
- * In the ingredient container model, the data is provided to the {@link IngredientMapper} extension point in order to augment ingredient data
153
- * and also loaded into the ingredient container model context in order to make the data available throughout the code.
154
- *
155
- * ```typescript
156
- * export const ingredientContextLoader = async (): Promise<BeverageContext> => {
157
- * const response = await kosFetch('kos:/system/some/ingredient/endpoint.json');
158
- *
159
- * if (response.status !== 200) {
160
- * KosLog.error('Failed to load ingredient data');
161
- * return {};
162
- * }
163
- * const json = await response.json();
164
- * return json;
165
- * };
166
- * ```
167
- * */
110
+ */
168
111
  registerIngredientLoader(ingredientLoader, options) {
169
112
  ExtensionManager.loader.registerLoader(
170
113
  ExtensionType.IngredientLoader,
@@ -260,7 +203,10 @@ class DispenseExtensionManager {
260
203
  return this;
261
204
  }
262
205
  /**
263
- * Maps data into the {@link AvailabilityModel}.
206
+ * Registers a data mapper for the {@link AvailabilityModel}.
207
+ *
208
+ * The mapper receives each availability node, with its `groupId`, and the data returned by the
209
+ * availability loader as context. Its result becomes the model's `data` property.
264
210
  *
265
211
  * @param availabilityMapper - Mapping function that maps a {@link GroupBeverageResponse} into additional availability data
266
212
  * @param options - Optional {@link ExtensionOptions} to control failure behavior.
@@ -269,28 +215,15 @@ class DispenseExtensionManager {
269
215
  * @returns this instance for chaining
270
216
  *
271
217
  * @example
272
- * The following example shows how to map the data from the service response into the {@link AvailabilityModel}.
273
- * The context is provided by the {@link AvailabilityLoader} extension point with its data being used to augment the
274
- * availability data.
275
- *
276
- * The result of the mapping will be available in the `data` property of the {@link AvailabilityModel}.
277
- *
278
218
  * ```typescript
279
- * export const beverageDataMapper = async (
280
- * data: NozzleServices.BeverageResponse,
281
- * context: BeverageContext
282
- * ): Promise<BeverageData> => {
283
- * const id = data.altId;
284
- * const iconUrl = encodeURI(
285
- * `http://localhost:8081/system/brandset/${context?.[id]?.icon}`
286
- * );
287
- * const cuiColorCode = context?.[id]?.cuiColorCode
288
- * ? context?.[id]?.cuiColorCode
289
- * : '';
290
- * return { iconUrl, cuiColorCode };
291
- * };
219
+ * const beverageDataMapper: AvailabilityDataMapper<BeverageData> = async (
220
+ * data,
221
+ * context?: Record<string, BrandsetIngredient>
222
+ * ) => ({
223
+ * iconUrl: context?.[data.altId]?.icon ?? "",
224
+ * });
292
225
  * ```
293
- * */
226
+ */
294
227
  registerAvailabilityDataMapper(availabilityMapper, options) {
295
228
  ExtensionManager.dataMapper.registerDataMapper(
296
229
  ExtensionType.AvailabilityMapper,
@@ -300,7 +233,8 @@ class DispenseExtensionManager {
300
233
  return this;
301
234
  }
302
235
  /**
303
- * Loads data that will be provided as context into the {@link AvailabilityMapper}.
236
+ * Registers a loader whose result is passed as context to the availability data mapper. A common use is
237
+ * loading UI-specific brandset data that the backend service does not provide.
304
238
  *
305
239
  * @param availabilityLoader - Async function that loads and returns availability context data
306
240
  * @param options - Optional {@link ExtensionOptions} to control failure behavior.
@@ -309,32 +243,14 @@ class DispenseExtensionManager {
309
243
  * @returns this instance for chaining
310
244
  *
311
245
  * @example
312
- * A common use case is to load brandset data that is UI specific and not provided directly by the Java service.
313
- *
314
- * The following example shows how to load the brandset data, normalize it into a map and then provide it back to the framework
315
- * where it can be used by the other extension points.
316
- *
317
- * In the nozzle model, the data is provided to the {@link AvailabilityMapper} extension point in order to augment availability data
318
- * and also loaded into the nozzle model context in order to make the data available throughout the code.
319
- *
320
246
  * ```typescript
321
- * export const beverageContextLoader = async (): Promise<BeverageContext> => {
322
- * const response = await kosFetch('kos:/system/brandset/brandset.json');
323
- *
324
- * if (response.status !== 200) {
325
- * KosLog.error('Failed to load beverage data');
326
- * return {};
327
- * }
328
- * const json: BrandsetResponse | null = await response.json();
329
- * const initialBeverages: Record<string, BrandsetIngredient> = {};
330
- * const beverages = json?.ingredients?.reduce((acc, beverage) => {
331
- * acc[beverage.ingredientId] = beverage;
332
- * return acc;
333
- * }, initialBeverages);
334
- * return beverages;
335
- * };
247
+ * const beverageContextLoader = async () => {
248
+ * const response = await kosFetch("kos:/system/brandset/brandset.json");
249
+ * const json: BrandsetResponse = await response.json();
250
+ * return Object.fromEntries(json.ingredients.map((i) => [i.ingredientId, i]));
251
+ * };
336
252
  * ```
337
- * */
253
+ */
338
254
  registerAvailabilityLoader(availabilityLoader, options) {
339
255
  ExtensionManager.loader.registerLoader(
340
256
  ExtensionType.AvailabilityLoader,
@@ -361,9 +277,8 @@ class DispenseExtensionManager {
361
277
  return this;
362
278
  }
363
279
  /**
364
- * Maps data into the {@link AssemblyModel} data.
365
- * Used in cases where the base assembly has been extended with additional properties in the backend. This extension
366
- * point allows for the data to be mapped into the {@link AssemblyModel} and augmented with additional properties.
280
+ * Registers a data mapper for the {@link AssemblyModel}, for backends that extend the assembly response
281
+ * with additional properties. The mapper's result is merged into the assembly model.
367
282
  *
368
283
  * @param assemblyDataMapper - Mapping function that maps an {@link AssemblyTypes.AssemblyResponse} into additional assembly data
369
284
  * @param options - Optional {@link ExtensionOptions} to control failure behavior.
@@ -372,60 +287,18 @@ class DispenseExtensionManager {
372
287
  * @returns this instance for chaining
373
288
  *
374
289
  * @example
375
- *
376
- * In this example of an implementation of a {@link AssemblyMapper}, the {@link AssemblyResponse} data is mapped into
377
- * a {@link FreestyleAssembly} object.
378
- *
379
- * The {@link FreestyleAssemblyResponse} interface represents the additional data being returned by the assembly service and is
380
- * merged into the {@link AssemblyResponse} interface.
381
- *
382
- * The {@link FreestyleAssembly} interface represents the additional data, beyond the base data set, that will be merged into the {@link AssemblyModel}.
383
- *
384
- * The mapper is responsible for mapping from the {@link FreestyleAssemblyResponse} format to the {@link FreestyleAssembly} format.
385
290
  * ```typescript
386
- * import { AssemblyTypes } from "@kosdev-code/kos-dispense-sdk";
387
- * import { DataMapper } from "@kosdev-code/kos-ui-sdk";
388
- *
389
- * // define the additional data being returned by the assembly service
390
- * export interface FreestyleAssemblyResponse {
391
- * iceAgitator?: {
392
- * name: "iceAgitator";
393
- * path: string;
394
- * };
395
- * }
396
- *
397
- * // define the additional data structure that will be merged into the assembly model
398
- * export interface FreestyleAssembly {
399
- * iceAgitator: {
400
- * path: string;
401
- * };
402
- * carbAgitator: {
403
- * path: string;
404
- * };
405
- * }
406
- *
407
- *
408
- * // define the mapper that will map the data from the service response into the additional data structure
409
- * // that will be merged into the assembly model.
410
- * // In this case the mapper is responsible for mapping from the {@link FreestyleAssemblyResponse} format to the {@link FreestyleAssembly} format.
411
- * export const assemblyDataMapper: DataMapper<
412
- * AssemblyTypes.AssemblyResponse<FreestyleAssemblyResponse>,
413
- * FreestyleAssembly
414
- * > = async (data) => {
415
- * const response = data.assemblies.reduce((acc, assembly) => {
416
- * const agitatorKeys = ["iceAgitator", "carbAgitator"];
417
- * agitatorKeys.forEach((key) => {
418
- * const agitator = assembly[key];
419
- * if (agitator) {
420
- * acc[key] = agitator;
421
- * }
422
- * });
291
+ * interface IceAgitatorExt {
292
+ * iceAgitator?: { name: string; path: string };
293
+ * }
423
294
  *
424
- * return acc;
425
- * }, {} as FreestyleAssembly);
426
- * return response;
427
- * };
428
- *```
295
+ * const assemblyDataMapper: AssemblyMapper<
296
+ * { iceAgitatorPath?: string },
297
+ * AssemblyTypes.AssemblyResponse<{ AssemblyExt: IceAgitatorExt }>
298
+ * > = async (data) => ({
299
+ * iceAgitatorPath: data.assemblies.find((a) => a.iceAgitator)?.iceAgitator?.path,
300
+ * });
301
+ * ```
429
302
  */
430
303
  registerAssemblyDataMapper(assemblyDataMapper, options) {
431
304
  ExtensionManager.dataMapper.registerDataMapper(
@@ -487,4 +360,4 @@ export {
487
360
  getFuelGaugeValue as g,
488
361
  index$3 as i
489
362
  };
490
- //# sourceMappingURL=extension-utils-C_pwmFbZ.js.map
363
+ //# sourceMappingURL=extension-utils-D_dnBLH6.js.map