@kosdev-code/kos-dispense-sdk 2.0.41 → 2.1.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 (39) hide show
  1. package/control-pour-extension-Byiwjyzw.js +1547 -0
  2. package/control-pour-extension-Byiwjyzw.js.map +1 -0
  3. package/control-pour-extension-DGztqLxi.cjs +2 -0
  4. package/control-pour-extension-DGztqLxi.cjs.map +1 -0
  5. package/dispense-registration-manager-DauhdXxX.cjs +2 -0
  6. package/dispense-registration-manager-DauhdXxX.cjs.map +1 -0
  7. package/{dispense-registration-manager-DZWwSdsc.js → dispense-registration-manager-pB5e_YT1.js} +560 -591
  8. package/dispense-registration-manager-pB5e_YT1.js.map +1 -0
  9. package/{extension-utils-CKGiF5Qr.cjs → extension-utils-BcdtSKJM.cjs} +2 -2
  10. package/{extension-utils-CKGiF5Qr.cjs.map → extension-utils-BcdtSKJM.cjs.map} +1 -1
  11. package/{extension-utils-C-QjbNHU.js → extension-utils-siWT4ZuD.js} +2 -2
  12. package/{extension-utils-C-QjbNHU.js.map → extension-utils-siWT4ZuD.js.map} +1 -1
  13. package/extensions/control-pour-extension.d.ts +80 -0
  14. package/extensions/control-pour-extension.d.ts.map +1 -0
  15. package/extensions/index.d.ts +2 -0
  16. package/extensions/index.d.ts.map +1 -0
  17. package/index.cjs +1 -1
  18. package/index.d.ts +1 -0
  19. package/index.d.ts.map +1 -1
  20. package/index.js +97 -94
  21. package/index.js.map +1 -1
  22. package/models/models/holder/holder-model.d.ts.map +1 -1
  23. package/models/models/pump/pump-model.d.ts.map +1 -1
  24. package/models/models/pump/types/index.d.ts +3 -2
  25. package/models/utils/dispense-registration-manager.d.ts +2 -2
  26. package/models/utils/service.d.ts +8 -8
  27. package/models.cjs +1 -1
  28. package/models.js +2 -2
  29. package/package.json +3 -3
  30. package/ui.cjs +1 -1
  31. package/ui.js +67 -66
  32. package/ui.js.map +1 -1
  33. package/dispense-registration-manager-DFEU9oXa.cjs +0 -2
  34. package/dispense-registration-manager-DFEU9oXa.cjs.map +0 -1
  35. package/dispense-registration-manager-DZWwSdsc.js.map +0 -1
  36. package/pump-provider-B7qOq1di.cjs +0 -2
  37. package/pump-provider-B7qOq1di.cjs.map +0 -1
  38. package/pump-provider-BO5BamvM.js +0 -1238
  39. package/pump-provider-BO5BamvM.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispense-registration-manager-pB5e_YT1.js","sources":["../../../../packages/sdk/kos-dispense-sdk/src/models/constants/constants.ts","../../../../packages/sdk/kos-dispense-sdk/src/models/models/ingredient/ingredient-model.ts","../../../../packages/sdk/kos-dispense-sdk/src/models/models/ingredient/services/ingredient-services.ts","../../../../packages/sdk/kos-dispense-sdk/src/models/models/ingredient-container/ingredient-container-model.ts","../../../../packages/sdk/kos-dispense-sdk/src/models/models/holder/services/holder-services.ts","../../../../packages/sdk/kos-dispense-sdk/src/models/models/holder/services/assignment-services.ts","../../../../packages/sdk/kos-dispense-sdk/src/models/models/holder/holder-model.ts","../../../../packages/sdk/kos-dispense-sdk/src/models/models/assembly/holder-utils.ts","../../../../packages/sdk/kos-dispense-sdk/src/models/models/assembly/services/assembly-services.ts","../../../../packages/sdk/kos-dispense-sdk/src/models/models/board/board-container-model.ts","../../../../packages/sdk/kos-dispense-sdk/src/models/models/board/utils/board-trouble-data-mapper.ts","../../../../packages/sdk/kos-dispense-sdk/src/models/models/pump-container/pump-container-model.ts","../../../../packages/sdk/kos-dispense-sdk/src/models/models/pump/utils/pump-trouble-resolver.ts","../../../../packages/sdk/kos-dispense-sdk/src/models/models/board/utils/board-trouble-resolver.ts","../../../../packages/sdk/kos-dispense-sdk/src/models/models/board/board-model.ts","../../../../packages/sdk/kos-dispense-sdk/src/models/models/board/board-registration.ts","../../../../packages/sdk/kos-dispense-sdk/src/models/models/board/board-container-registration.ts","../../../../packages/sdk/kos-dispense-sdk/src/models/models/holder-container/holder-container-model.ts","../../../../packages/sdk/kos-dispense-sdk/src/models/models/assembly/board-utils.ts","../../../../packages/sdk/kos-dispense-sdk/src/models/models/types/pouring.ts","../../../../packages/sdk/kos-dispense-sdk/src/models/models/pump/services/pump-services.ts","../../../../packages/sdk/kos-dispense-sdk/src/models/models/pump/pump-model.ts","../../../../packages/sdk/kos-dispense-sdk/src/models/models/assembly/pump-utils.ts","../../../../packages/sdk/kos-dispense-sdk/src/models/models/assembly/assembly-model.ts","../../../../packages/sdk/kos-dispense-sdk/src/models/models/assembly/assembly-registration.ts","../../../../packages/sdk/kos-dispense-sdk/src/models/models/availability/availability-model.ts","../../../../packages/sdk/kos-dispense-sdk/src/models/models/nozzle/services/nozzle-services.ts","../../../../packages/sdk/kos-dispense-sdk/src/models/models/nozzle/nozzle-model.ts","../../../../packages/sdk/kos-dispense-sdk/src/models/models/device-assembly/device-assembly-model.ts","../../../../packages/sdk/kos-dispense-sdk/src/models/models/device-assembly/device-assembly-registration.ts","../../../../packages/sdk/kos-dispense-sdk/src/models/models/generic-pour/services/generic-pour-services.ts","../../../../packages/sdk/kos-dispense-sdk/src/models/models/generic-pour/generic-pour-model.ts","../../../../packages/sdk/kos-dispense-sdk/src/models/models/generic-pour/generic-pour-registration.ts","../../../../packages/sdk/kos-dispense-sdk/src/models/utils/registration.ts","../../../../packages/sdk/kos-dispense-sdk/src/models/utils/dispense-registration-manager.ts"],"sourcesContent":["/**\n * Extension point exposed by the KOS Dispense SDK models\n * */\nexport enum ExtensionType {\n /**\n * Loads data that will be provided as context into the {@link IngredientMapper}\n *\n * @example\n * The following example shows how to load the brandset data, normalize it into a map and then provide it back to the framework\n * where it can be used by the other extension points.\n *\n * In the ingredient container model, the data is provided to the {@link IngredientMapper} extension point in order to augment ingredient data\n * and also loaded into the ingredient container model context in order to make the data available throughout the code.\n *\n * ```typescript\n * export const ingredientContextLoader = async (): Promise<BeverageContext> => {\n * const response = await kosFetch('kos:/system/some/ingredient/endpoint.json');\n *\n * if (response.status !== 200) {\n * KosLog.error('Failed to load ingredient data');\n * return {};\n * }\n * const json = await response.json();\n * return json;\n * };\n * ```\n * */\n IngredientLoader = \"kos.ingredient.loader\",\n\n /**\n * Maps data into the {@link IngredientModel}\n *\n * It is common for the ingredient data provided by the ingredient service to be augmented with additional properties that are\n * not provided by the base KOS Ingredient model. The {@link IngredientMapper} extension point allows for the data to be mapped\n * into the {@link IngredientModel} and the {@link IngredientModel.data} property to be augmented with additional properties.\n *\n * @example\n * The following example shows how to map the data from the service response into the {@link IngredientModel}.\n * The context is provided by the {@link IngredientLoader} extension point with its data being used to optionally augment the\n * ingredient data.\n *\n * The result of the mapping will be available in the `data` property of the {@link IngredientModel}.\n *\n * In this case the `IngedientReponseData` interface represents the data being returned by the ingredient service and the\n * `IngredientData` interface represents the data that will be available in the {@link IngredientModel.data} property. The `ingredientDataMapper`\n * is responsible for mapping from one format to the other.\n *\n * ```typescript\n *\n * interface IngredientResponseData extends NozzleServices.IngredientResponse {\n * chilled: boolean;\n * carbonated: boolean;\n * highYield: boolean;\n * }\n *\n * interface IngredientData {\n * chilled: boolean;\n * carbonated: boolean;\n * highYield: boolean;\n * }\n *\n * export const ingredientDataMapper = async (\n * data: IngredientResponseData,\n * context: IngredientContext\n * ): Promise<IngredientData> => {\n * return {\n * chilled: data.chilled,\n * carbonated: data.carbonated,\n * highYield: data.highYield,\n * }\n * }\n * ```\n * */\n IngredientMapper = \"kos.ingredient.mapper\",\n\n IngredientIndex = \"kos.ingredient.index\",\n /**\n * Maps the type property of the ingredient into the {@link IngredientModel}\n * */\n IngredientTypeMapper = \"kos.ingredient.type.mapper\",\n\n /**\n * Maps the type property of the holder into the {@link HolderModel}\n * */\n HolderTypeMapper = \"kos.holder.type.mapper\",\n\n HolderMapper = \"kos.holder.mapper\",\n\n HolderIndex = \"kos.holder.index\",\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 HolderIngredientMapper = \"kos.holder.ingredient.mapper\",\n\n /**\n * Maps data into the {@link AvailabilityModel}\n *\n * @example\n * The following example shows how to map the data from the service response into the {@link AvailabilityModel}.\n * The context is provided by the {@link AvailabilityLoader} extension point with its data being used to augment the\n * availability data.\n *\n * The result of the mapping will be available in the `data` property of the {@link AvailabilityModel}.\n *\n * ```typescript\n * export const beverageDataMapper = async (\n * data: NozzleServices.BeverageResponse,\n * context: BeverageContext\n * ): Promise<BeverageData> => {\n * const id = data.altId;\n * const iconUrl = encodeURI(\n * `http://localhost:8081/system/brandset/${context?.[id]?.icon}`\n * );\n * const cuiColorCode = context?.[id]?.cuiColorCode\n * ? context?.[id]?.cuiColorCode\n * : '';\n * return { iconUrl, cuiColorCode };\n * };\n * ```\n * */\n AvailabilityMapper = \"kos.availability.mapper\",\n\n /**\n * Loads data that will be provided as context into the {@link AvailabilityMapper}\n *\n * @example\n * A common use case is to load brandset data that is UI specific and not provided directly by the Java service.\n *\n * The following example shows how to load the brandset data, normalize it into a map and then provide it back to the framework\n * where it can be used by the other extension points.\n *\n * In the nozzle model, the data is provided to the {@link AvailabilityMapper} extension point in order to augment availability data\n * and also loaded into the nozzle model context in order to make the data available throughout the code.\n *\n * ```typescript\n * export const beverageContextLoader = async (): Promise<BeverageContext> => {\n * const response = await kosFetch('kos:/system/brandset/brandset.json');\n *\n * if (response.status !== 200) {\n * KosLog.error('Failed to load beverage data');\n * return {};\n * }\n * const json: BrandsetResponse | null = await response.json();\n * const initialBeverages: Record<string, BrandsetIngredient> = {};\n * const beverages = json?.ingredients?.reduce((acc, beverage) => {\n * acc[beverage.ingredientId] = beverage;\n * return acc;\n * }, initialBeverages);\n * return beverages;\n * };\n * ```\n * */\n AvailabilityLoader = \"kos.availability.loader\",\n\n /**\n * Maps the abstract {@link SelectedPourable} data into a format that is specific to the nozzle.\n * */\n SelectedPourableMapper = \"kos.selected.pourable.mapper\",\n\n /**\n * Maps data into the {@link AssemblyModel} data.\n * Used in cases where the base assembly has been extended with additional properties in the backend. This extension\n * point allows for the data to be mapped into the {@link AssemblyModel} and augmented with additional properties.\n *\n * @example\n *\n * In this example of an implementation of a {@link AssemblyMapper}, the {@link AssemblyResponse} data is mapped into\n * a {@link FreestyleAssembly} object.\n *\n * The {@link FreestyleAssemblyResponse} interface represents the additional data being returned by the assembly service and is\n * merged into the {@link AssemblyResponse} interface.\n *\n * The {@link FreestyleAssembly} interface represents the additional data, beyond the base data set, that will be merged into the {@link AssemblyModel}.\n *\n * The mapper is responsible for mapping from the {@link FreestyleAssemblyResponse} format to the {@link FreestyleAssembly} format.\n * ```typescript\n * import { AssemblyTypes } from \"@kosdev-code/kos-dispense-sdk\";\n * import { DataMapper } from \"@kosdev-code/kos-ui-sdk\";\n *\n * // define the additional data being returned by the assembly service\n * export interface FreestyleAssemblyResponse {\n * iceAgitator?: {\n * name: \"iceAgitator\";\n * path: string;\n * };\n * }\n *\n * // define the additional data structure that will be merged into the assembly model\n * export interface FreestyleAssembly {\n * iceAgitator: {\n * path: string;\n * };\n * carbAgitator: {\n * path: string;\n * };\n * }\n *\n *\n * // define the mapper that will map the data from the service response into the additional data structure\n * // that will be merged into the assembly model.\n * // In this case the mapper is responsible for mapping from the {@link FreestyleAssemblyResponse} format to the {@link FreestyleAssembly} format.\n * export const assemblyDataMapper: DataMapper<\n * AssemblyTypes.AssemblyResponse<FreestyleAssemblyResponse>,\n * FreestyleAssembly\n * > = async (data) => {\n * const response = data.assemblies.reduce((acc, assembly) => {\n * const agitatorKeys = [\"iceAgitator\", \"carbAgitator\"];\n * agitatorKeys.forEach((key) => {\n * const agitator = assembly[key];\n * if (agitator) {\n * acc[key] = agitator;\n * }\n * });\n *\n * return acc;\n * }, {} as FreestyleAssembly);\n * return response;\n * };\n *```\n */\n AssemblyMapper = \"kos.assembly.mapper\",\n BoardMapper = \"kos.board.mapper\",\n BoardIndex = \"kos.board.index\",\n PumpIndex = \"kos.pump.index\",\n AssemblyFeatureFlags = \"kos.assembly.feature.flags\",\n}\n\nexport enum DispenseModelType {\n Nozzle = \"nozzle-model\",\n Availability = \"availability-model\",\n Holder = \"holder-model\",\n HolderContainer = \"holder-container-model\",\n IngredientContainer = \"ingredient-container-model\",\n Ingredient = \"ingredient-model\",\n Pump = \"pump-model\",\n PumpContainer = \"pump-container-model\",\n}\n","import {\n Kos,\n KosModelRegistrationBean,\n isKosModel,\n kosModel,\n} from \"@kosdev-code/kos-ui-sdk\";\nimport type { IngredientModel, IngredientOptions } from \"./types\";\n\nconst MODEL_TYPE = \"ingredient-model\";\n\n@kosModel(MODEL_TYPE)\nclass IngredientModelImpl<AdditionalData extends object = any>\n implements IngredientModel\n{\n id: string;\n ingredientId: string;\n name: string;\n type: string;\n data: AdditionalData;\n\n constructor(\n modelId: string,\n {\n name,\n type,\n data,\n ingredientId,\n ...rest\n }: IngredientOptions<AdditionalData>\n ) {\n this.id = modelId;\n this.ingredientId = ingredientId;\n this.name = name;\n this.type = type;\n this.data = data;\n Object.assign(this, rest);\n }\n\n updateModel({\n name,\n type,\n data,\n ingredientId,\n ...rest\n }: IngredientOptions<AdditionalData>): void {\n this.name = name;\n this.type = type;\n this.ingredientId = ingredientId;\n this.data = data;\n Object.assign(this, rest);\n }\n\n // -------------------LIFECYCLE----------------------------\n\n // -------------------ENTITY----------------------------\n}\n\n/**\n * # Ingredient\n *\n * The registration bean includes convenience methods for creating and working with IngredientModel instances.\n *\n * ## type\n * The type property is a string that identifies the model type.\n * The type is used to identify the model type in the model registry and to narrow down the model type in type predicates. It's most frequently\n * used when declaring dependencies on models.\n *\n * @example\n * ```typescript\n *\n * @kosDependency({modelType: Ingredient.type, id: \"ingredientId\"})\n * private ingredientModel: IngredientModel;\n * ```\n *\n *\n * ## factory\n *\n * The factory method creates a factory function that can be used to create new IngredientModel instances.\n *\n * The factory function is a curried function that takes the model id as the first argument and the options as the second argument.\n *\n * If a model with the specified id already exists, the factory function will return the existing model. The options will be ignored\n * in this case and the existing model will be returned in its current state.\n *\n * @example\n *\n * ```typescript\n * const model = Ingredient.factory(\"S1\")({\n * name: \"S1\",\n * ingredientId: \"1234532\",\n * type: \"syrup\",\n * data: {\n * // mapped from an extension point\n * }\n * });\n * ```\n *\n * ## predicate\n *\n * [Typescript type predicate](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates) function that will identify and narrow down a model to a IngredientModel.\n *\n * @example\n * ```typescript\n *\n * const model: IKosDataModel = ...; // some model\n *\n * if (Ingredient.predicate(model)) {\n * // if the function evaluates to true, the model is narrowed down to IngredientModel\n * // and the compiler will know that the model has the IngredientModel interface\n * model.updateAvailability(false);\n * }\n * ```\n *\n * ## registration\n *\n * The registration property is an object that can be used to simplify registration of the model with the model registry. The registration object\n * can be spread into the model registration and provides all of the required information to register the model implementation class against the model type.\n *\n *\n * @example\n *\n * In an application registration file you can declare the model registration as follows:\n *\n * **registration.ts**\n * ```typescript\n * import { Ingredient } from \"@kosdev-code/kos-dispense-sdk\";\n * ...\n * import { IKosRegistry } from \"@kosdev-code/kos-ui-sdk\";\n * export const kosModels: IKosRegistry[\"models\"] = {\n * ...Ingredient.registration,\n * };\n * ```\n *\n * ## registration.singleton\n *\n * The ingredient model is not a singleton model. This means that each time the factory function is called with a unique ID, a new model instance will be created.\n * If the factory function is called with an ID that already exists, the existing model will be returned.\n * */\nexport const Ingredient: Readonly<\n KosModelRegistrationBean<IngredientModel, IngredientOptions>\n> = {\n registration: {\n [MODEL_TYPE]: {\n class: IngredientModelImpl,\n singleton: false,\n },\n },\n type: MODEL_TYPE,\n predicate: isKosModel(MODEL_TYPE),\n factory: Kos.Factory.create<IngredientModel, IngredientOptions>(MODEL_TYPE),\n};\n","import { ServiceFactory, resolveServiceUrl } from \"@kosdev-code/kos-ui-sdk\";\nconst { URL } = resolveServiceUrl(\"INGREDIENT_SERVICE\");\nconst { getOne } = ServiceFactory.build({\n basePath: `${URL}/api/ext/dispense/ingredients`,\n});\n\nexport interface BrandsetResponse {\n brandSet: IngredientResponse[];\n}\n/**\n * Base ingredient response returned by the service. Most likely this will be augmented by the {@link IngredientMapper} extension point\n * to allow for additional properties to be added to the ingredient data.\n * */\nexport interface IngredientResponse {\n /** The ingredient id */\n id: string;\n\n /**\n * The raw ingredient without considering the source. This will only be different in cases where there are asymetrical nozzles with\n * discrete ingredient sources.\n */\n ingredientId: string;\n\n /** The ingredient name */\n name: string;\n\n /**\n * The ingredient type as defined by the java application. This can be any value and is generally used\n * to classify ingredients into groups. For example, the ingredient type may be used to identify ingredients that are\n * used for flavor shots.\n */\n type: string;\n}\n/**\n * @category Service\n * Retrieves the initial Ingredient data.\n */\nexport const getIngredients = async () => {\n const response = await getOne<BrandsetResponse>({\n urlOverride: `${URL}/api/ext/dispense/ingredients`,\n });\n return response;\n};\n","import type {\n IKosModelContainer,\n KosContext,\n SingletonKosModelRegistrationBean,\n} from \"@kosdev-code/kos-ui-sdk\";\nimport {\n Kos,\n KosExtensionUtils,\n KosLog,\n KosModelContainer,\n isKosModel,\n kosChild,\n kosModel,\n} from \"@kosdev-code/kos-ui-sdk\";\nimport { ExtensionType } from \"../../constants\";\nimport { Ingredient, IngredientModel, IngredientOptions } from \"../ingredient\";\nimport { getIngredients } from \"../ingredient/services\";\nimport type {\n IngredientContainerModel,\n IngredientContainerOptions,\n} from \"./types\";\n\nconst MODEL_TYPE = \"ingredient-container-model\";\n\nconst log = KosLog.createLogger({ name: \"ingredient-container-model\" });\n\n@kosModel(MODEL_TYPE)\nclass IngredientContainerModelImpl<AdditionalData extends object = any>\n implements IngredientContainerModel<AdditionalData>\n{\n id: string;\n @kosChild ingredients: IKosModelContainer<IngredientModel<AdditionalData>>;\n constructor(modelId: string, options: IngredientContainerOptions) {\n this.id = modelId;\n\n // Extension Point: kos.ingredient.index\n this.ingredients = new KosModelContainer<IngredientModel<AdditionalData>>({\n indexMap: {\n ingredientType: \"type\",\n },\n extensionId: ExtensionType.IngredientIndex,\n parentId: modelId,\n });\n if (options) {\n // Assign options properties here.\n }\n }\n\n updateModel(): void {\n // Update model properties here.\n }\n\n // -------------------LIFECYCLE----------------------------\n\n getIngredientsByType(type: string): IngredientModel[] {\n return this.ingredients.getIndexByKey(\"ingredientType\", type);\n }\n\n async load(context?: KosContext): Promise<void> {\n log.debug(`loading ingredient container ${this.id}`);\n const allIngredients = await getIngredients();\n if (allIngredients?.status !== 200) {\n throw new Error(\"Failed to load ingredients\");\n }\n\n const ingredientContext = await KosExtensionUtils.executeLoaderExtension({\n context,\n extension: ExtensionType.IngredientLoader,\n });\n\n const ingredientData = allIngredients?.data ?? {};\n for (const key of Object.keys(ingredientData)) {\n for (const ingredientData of allIngredients?.data?.[key] || []) {\n const data: AdditionalData =\n await KosExtensionUtils.executeDataMapperExtension({\n extension: ExtensionType.IngredientMapper,\n data: ingredientData,\n contextData: ingredientContext,\n });\n\n const type = await KosExtensionUtils.executePropertyMapperExtension({\n extension: ExtensionType.IngredientTypeMapper,\n data: ingredientData,\n contextData: ingredientContext,\n });\n\n const ingredientOptions: IngredientOptions = {\n ...ingredientData,\n type: type || ingredientData.type,\n ...data,\n data,\n };\n const ingredient = Ingredient.factory(ingredientData.id)(\n ingredientOptions\n );\n this.ingredients.addModel(ingredient);\n }\n }\n //load all the ingredient models\n }\n\n // -------------------ENTITY----------------------------\n}\n\n/**\n * # IngredientContainer\n *\n * The registration bean includes convenience methods for creating and working with IngredientContainerModel instances.\n *\n * ## type\n * The type property is a string that identifies the model type.\n * The type is used to identify the model type in the model registry and to narrow down the model type in type predicates. It's most frequently\n * used when declaring dependencies on models.\n *\n * @example\n * ```typescript\n *\n * @kosDependency({modelType: IngredientContainer.type})\n * private holderContainerModel: IngredientContainerModel;\n * ```\n *\n *\n * ## factory\n *\n * The factory function that can be used to create new IngredientContainerModel instances.\n *\n * As this is a singleton model, the factory function accepts the model options as its argument.\n *\n * If a model with the same model type already exists, the factory function will return the existing model. The options will be ignored\n * in this case and the existing model will be returned in its current state.\n *\n *\n * @example\n *\n * ```typescript\n * const model = IngredientContainer.factory({ });\n * ```\n *\n * ## predicate\n *\n * [Typescript type predicate](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates) function that will identify and narrow down a model to a IngredientContainerModel.\n *\n * @example\n * ```typescript\n *\n * const model: IKosDataModel = ...; // some model\n *\n * if (IngredientContainer.predicate(model)) {\n * // if the function evaluates to true, the model is narrowed down to IngredientContainerModel\n * // and the compiler will know that the model has the IngredientContainerModel interface\n * model.updateAvailability(false);\n * }\n * ```\n *\n * ## registration\n *\n * The registration property is an object that can be used to simplify registration of the model with the model registry. The registration object\n * can be spread into the model registration and provides all of the required information to register the model implementation class against the model type.\n *\n *\n * @example\n *\n * In an application registration file you can declare the model registration as follows:\n *\n * **registration.ts**\n * ```typescript\n * import { IngredientContainer } from \"@kosdev-code/kos-dispense-sdk\";\n * ...\n * import { IKosRegistry } from \"@kosdev-code/kos-ui-sdk\";\n * export const kosModels: IKosRegistry[\"models\"] = {\n * ...IngredientContainer.registration,\n * };\n * ```\n *\n * ## registration.singleton\n * The IngredientContainer model is a singleton. This means that each time the factory function is called , the same instance will be returned.\n * If the model does not yet exist, it will be created passing in the provided options to initialize it.\n *\n * * */\nexport const IngredientContainer: SingletonKosModelRegistrationBean<\n IngredientContainerModel,\n IngredientContainerOptions\n> = {\n registration: {\n [MODEL_TYPE]: {\n class: IngredientContainerModelImpl,\n singleton: true,\n },\n },\n type: MODEL_TYPE,\n predicate: isKosModel(MODEL_TYPE),\n factory: Kos.Singleton.create<\n IngredientContainerModel,\n IngredientContainerOptions\n >(MODEL_TYPE),\n};\n","import {\n KosLog,\n ServiceFactory,\n resolveServiceUrl,\n} from \"@kosdev-code/kos-ui-sdk\";\nconst { URL } = resolveServiceUrl(\"HOLDER_SERVICE\");\nconst { getAll, postModel, deleteModel } = ServiceFactory.build({\n basePath: `${URL}/api/kos/holders`,\n});\n\nconst log = KosLog.createLogger({\n name: \"holder-service\",\n group: \"Services\",\n});\n\nexport interface Pump {\n inserted: boolean;\n beveragePour: boolean;\n ingredientPour: boolean;\n type: string;\n category: string;\n ingredientId: string;\n holderPath: string;\n boardPath: string;\n nozzlePath: string;\n name: string;\n path: string;\n}\nexport interface HolderResponse {\n path: string;\n name: string;\n ingType: string;\n ingSource: string;\n}\n/**\n * @category Service\n * Retrieves the initial Holder data.\n */\nexport const getHolders = async () => {\n const response = await getAll<HolderResponse>({});\n return response;\n};\n\nexport const assignHolderIngredient = async (\n holderPath: string,\n ingredientId: string\n) => {\n if (!holderPath || !ingredientId) {\n throw new Error(\"Missing holderPath or ingredientId\");\n }\n\n const response = await postModel({\n model: { holderPath, ingredientId },\n urlOverride: `${URL}/api/ext/dispense/assignments`,\n });\n\n return response;\n};\n\nexport const unassignHolderIngredient = async (holderPath: string) => {\n if (!holderPath) {\n throw new Error(\"Missing holderPath\");\n }\n\n const response = await deleteModel({\n id: holderPath,\n urlOverride: `${URL}/api/ext/dispense/assignments/${holderPath}`,\n });\n\n return response;\n};\n\nexport const replaceLine = async (holderPath: string) => {\n if (!holderPath) throw new Error(\"Missing holderPath\");\n\n log.debug(\n `sending POST request to /api/ext/dispense/pumpEvents/replaceLine/${holderPath}`\n );\n\n const response = await postModel({\n model: {},\n urlOverride: `${URL}/api/ext/dispense/pumpEvents/replaceLine/${holderPath}`,\n });\n\n return response;\n};\n","import {\n FetchError,\n ServiceFactory,\n resolveServiceUrl,\n} from \"@kosdev-code/kos-ui-sdk\";\nconst { URL } = resolveServiceUrl(\"ASSIGNMENT_SERVICE\");\nconst { getAll, postModel, deleteModel } = ServiceFactory.build({\n destinationAddress: \"\",\n basePath: `${URL}/api/ext/dispense/assignments`,\n});\n// test\nconst useFos = window.kosUseFos;\n\nexport interface Assignment {\n ingredientId: string;\n holderPath: string;\n containerId?: string;\n fuelGauge?: number;\n}\n\nexport interface AssignmentFactoryJson {\n stickerId: string;\n stickerCode: string;\n}\n/**\n * @category Service\n * Retrieves the initial dispenser data.\n */\nexport const getAssignments = async () => {\n const response = await getAll<Assignment>({ fos: useFos });\n return response;\n};\nexport type AssignmentErrorType =\n | \"errIdLen\"\n | \"errCodeLen\"\n | \"errIdFormat\"\n | \"errCodeFormat\"\n | \"errVerify\"\n | \"errBadJson\"\n | \"unknownError\";\ntype AssignmentResponse = [\n AssignmentErrorType | undefined,\n Assignment | undefined\n];\nexport const sendRfidOverride = async (\n holderPath: string,\n overrides: any\n): Promise<AssignmentResponse> => {\n const factoryJson = JSON.stringify(overrides);\n const url = `${URL}/api/ext/dispense/assignments`;\n try {\n const response = await postModel({\n model: { holderPath, factoryJson },\n urlOverride: url,\n });\n if (response?.status === 200 && response?.data?.error) {\n return [response.data.error || \"unknownError\", response.data];\n }\n\n return [undefined, response?.data];\n } catch (error) {\n if (error instanceof FetchError) {\n return [\n error.payload?.data?.error || \"unknownError\",\n error.payload?.data,\n ];\n }\n }\n return [\"unknownError\", undefined];\n};\n\nexport const addAssignment = async (assignment: Assignment) => {\n const url = useFos\n ? `${URL}/api/ingredients/assignments/${assignment.holderPath}`\n : `${URL}/api/ext/dispense/assignments`;\n const response = await postModel({\n model: { ...assignment, fuelGauge: 680 },\n fos: useFos,\n urlOverride: url,\n });\n return response;\n};\n\nexport const deleteAssignment = async (id: string) => {\n const response = await deleteModel({ id, fos: useFos });\n return response;\n};\n","/* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */\nimport type {\n IKosModelContainer,\n KosContextLogger,\n KosCreationContext,\n KosModelRegistrationBean,\n TroubleAware,\n TroubleModel,\n} from \"@kosdev-code/kos-ui-sdk\";\nimport {\n EXTENSION_TROUBLE_DATA_MAPPER,\n EXTENSION_TROUBLE_MAPPER,\n ExtensionManager,\n Kos,\n KosLog,\n KosModelContainer,\n getKosModelSync,\n isKosModel,\n kosAction,\n kosChild,\n kosDependency,\n kosModel,\n kosTroubleAware,\n} from \"@kosdev-code/kos-ui-sdk\";\nimport { DispenseModelType } from \"../../constants\";\nimport { type IngredientModel } from \"../ingredient\";\nimport {\n IngredientContainer,\n type IngredientContainerModel,\n} from \"../ingredient-container\";\nimport { type PumpModel } from \"../pump\";\nimport type { PumpTroubleData } from \"../pump/utils/pump-trouble-resolver\";\nimport type { IntentAwareProps } from \"../types\";\nimport type { HolderSlice } from \"../types/assembly\";\nimport {\n assignHolderIngredient,\n replaceLine,\n sendRfidOverride,\n unassignHolderIngredient,\n type AssignmentErrorType,\n} from \"./services\";\nimport type { HolderModel, HolderOptions } from \"./types\";\n\nconst MODEL_TYPE = DispenseModelType.Holder;\n\nconst log = KosLog.createLogger({ name: \"holder-model\" });\n\nexport interface HolderTroubleData {\n holderPaths: string[];\n holderNames: string[];\n}\n\nexport interface ContainerTroubleData {\n ingredients: string[];\n unknonwnIngredientId?: string;\n}\nExtensionManager[EXTENSION_TROUBLE_MAPPER].register(\n \"holder\",\n async (trouble: TroubleModel<HolderTroubleData>) => {\n const result: string[] = [];\n result.push(...trouble.data.holderPaths);\n return result;\n }\n);\n\nExtensionManager[EXTENSION_TROUBLE_DATA_MAPPER].register(\n \"pump\",\n async (trouble: TroubleModel<PumpTroubleData>) => {\n // If the trouble is related to a container, we don't need to map the data\n\n if (trouble.data.pumpPath) {\n const { model: pumpModel } = getKosModelSync<PumpModel>(\n trouble.data.pumpPath\n );\n\n if (pumpModel) {\n const ingredientModel = pumpModel.ingredientId\n ? getKosModelSync<IngredientModel>(pumpModel.ingredientId).model\n : undefined;\n return {\n ingredientId: pumpModel.ingredientId,\n ingredientName:\n ingredientModel?.displayName ?? (ingredientModel?.name || \"\"),\n childPumpName: pumpModel.name,\n };\n }\n }\n return {};\n }\n);\n\nExtensionManager[EXTENSION_TROUBLE_DATA_MAPPER].register(\n \"holder\",\n async (trouble: TroubleModel<HolderTroubleData>) => {\n if (trouble.data.holderNames.length > 0) {\n const holderName = trouble.data.holderNames[0];\n return {\n holderName: holderName || \"\",\n };\n }\n return {};\n }\n);\n\nExtensionManager[EXTENSION_TROUBLE_DATA_MAPPER].register(\n \"container\",\n async (trouble: TroubleModel<ContainerTroubleData>) => {\n if (trouble.data.ingredients.length > 0) {\n const ingredientId = trouble.data.ingredients[0];\n const { model } = getKosModelSync<IngredientModel>(ingredientId);\n return {\n ingredientName: model?.displayName ?? (model?.name || \"\"),\n ingredients: trouble.data.ingredients ? trouble.data.ingredients : [],\n unknonwnIngredientId: trouble.data.unknonwnIngredientId ?? \"\",\n };\n }\n return {};\n }\n);\n\nclass AssignmentError extends Error {\n type: AssignmentErrorType;\n constructor(type: AssignmentErrorType, message: string) {\n super(message);\n this.name = \"AssignmentError\";\n this.type = type;\n }\n}\n\n// eslint-disable-next-line @typescript-eslint/no-empty-interface\ninterface HolderModelImpl<AdditionalData extends object = any>\n extends TroubleAware {}\n@kosModel(MODEL_TYPE)\n@kosTroubleAware()\nclass HolderModelImpl<AdditionalData extends object = any>\n implements HolderModel<AdditionalData>\n{\n id: string;\n path: string;\n name: string;\n ingredientId?: string;\n ingredientType?: string;\n ingredientSource?: string;\n group: string;\n slice: HolderSlice;\n logger: KosContextLogger;\n data: AdditionalData;\n enjoyByDate?: Date;\n\n @kosChild pumps: IKosModelContainer<PumpModel>;\n @kosDependency({ modelType: IngredientContainer.type })\n ingredientContainer!: IngredientContainerModel;\n\n constructor(\n modelId: string,\n {\n path,\n name,\n ingredientSource,\n ingredientId,\n ingredientType,\n slice,\n group,\n data,\n enjoyByDate,\n }: HolderOptions,\n context: KosCreationContext\n ) {\n this.id = modelId;\n this.path = path;\n this.name = name;\n this.ingredientType = ingredientType;\n this.ingredientSource = ingredientSource;\n this.ingredientId = ingredientId;\n this.group = group;\n this.slice = slice;\n this.enjoyByDate = enjoyByDate;\n this.data = data;\n this.pumps = new KosModelContainer<PumpModel>({\n parentId: modelId,\n sortKey: \"path\",\n });\n this.logger = context.logger;\n }\n\n updateModel({\n path,\n name,\n ingredientSource,\n ingredientId,\n ingredientType,\n group,\n slice,\n enjoyByDate,\n data,\n }: HolderOptions<AdditionalData>): void {\n // Update model properties here.\n\n this.path = path;\n this.name = name;\n this.ingredientId = ingredientId;\n this.ingredientType = ingredientType;\n this.ingredientSource = ingredientSource;\n this.enjoyByDate = enjoyByDate;\n this.slice = slice;\n this.group = group;\n this.data = data;\n }\n\n get hasEnjoyByDate() {\n return !!this.enjoyByDate && !this.unassigned;\n }\n get hasEnjoyByWarning() {\n return this.troublesByType[\"EnjoyByTrouble\"]?.length > 0;\n }\n\n get nozzlePaths() {\n return this.pumps.data.map((pump) => pump.nozzlePath);\n }\n\n async cancelPour() {\n await Promise.all(\n this.pumps.data\n .filter((pump) => pump.isPouring)\n .map((pump) => pump.cancelPour())\n );\n }\n\n get canPour() {\n return !this.shouldDefer && this.pumps.data.every((pump) => pump.canPour);\n }\n\n get isPouring() {\n const _isPouring = this.pumps.data.some((pump) => pump.isPouring);\n this.logger.debug(`isPouring: ${!!_isPouring}`);\n return _isPouring;\n }\n\n async performIntent(props: IntentAwareProps) {\n const intent = typeof props === \"string\" ? props : props.intent;\n const pumpPath = typeof props === \"string\" ? undefined : props.pumpPath;\n const pump = pumpPath ? this.pumps.getModel(pumpPath) : this.pumps.data[0];\n return pump?.performIntent({ intent });\n }\n\n get pourState() {\n const state = this.pumps.data.reduce((resolvedState, pump) => {\n if (pump.pouringState) {\n return pump.pouringState;\n }\n return resolvedState;\n }, \"\");\n return state;\n }\n get nozzlePath() {\n return this.pumps.data[0]?.nozzlePath;\n }\n\n get pumpPaths() {\n return this.pumps.data.map((pump) => pump.id);\n }\n\n get sortedPumps() {\n return this.pumps.data.sort((a, b) => {\n if (a.virtual && !b.virtual) {\n return -1;\n }\n\n if (!a.virtual && b.virtual) {\n return 1;\n }\n\n return a.name.localeCompare(b.name);\n });\n }\n\n get ingredient(): IngredientModel | undefined {\n if (!this.ingredientId) {\n return undefined;\n }\n const ingredient = this.ingredientContainer?.ingredients.getModel(\n this.ingredientId\n );\n return ingredient;\n }\n get ingredientName(): string {\n if (this.ingredient) {\n return this.ingredient.displayName ?? this.ingredient.name;\n } else if (this.ingredientId) {\n // If the ingredient is not found in the container, it is likely that the ingredient\n return \"unknown\";\n } else {\n return \"\";\n }\n }\n\n get previousIngredient(): IngredientModel | undefined {\n if (!this.prevIngredientId) {\n return undefined;\n }\n const ingredient = this.ingredientContainer?.ingredients.getModel(\n this.prevIngredientId\n );\n return ingredient;\n }\n\n get previousIngredientName(): string {\n if (this.previousIngredient) {\n return (\n this.previousIngredient.displayName ?? this.previousIngredient.name\n );\n } else if (this.prevIngredientId) {\n // If the ingredient is not found in the container, it is likely that the ingredient\n return \"unknown\";\n } else {\n return \"\";\n }\n }\n\n get prevIngredientId() {\n return this.pumps.data?.[0]?.prevIngredientId;\n }\n\n get unassigned() {\n return (\n (!this.ingredientId || this.ingredientId === \"0\") &&\n (!this.prevIngredientId || this.prevIngredientId === \"0\")\n );\n }\n\n get removed() {\n return (\n (!this.ingredientId || this.ingredientId === \"0\") &&\n this.prevIngredientId !== undefined &&\n this.prevIngredientId !== \"0\"\n );\n }\n\n get maxVolume() {\n return this.slice.maxVolMl ?? 0;\n }\n\n get remainingVolume() {\n return this.slice.currentVolMl ?? 0;\n }\n\n get hasMaxVolume() {\n return this.slice.maxVolMl !== undefined;\n }\n\n get hasRemainingVolume() {\n return this.slice.currentVolMl !== undefined;\n }\n\n get fillPercent() {\n return this.remainingVolume <= 0\n ? 0\n : Math.floor(((this.remainingVolume || 1) / (this.maxVolume || 1)) * 100);\n }\n\n get hasFuelGuage() {\n return this.hasMaxVolume && this.hasRemainingVolume;\n }\n\n updateIngredient(ingredientId?: string) {\n if (this.ingredientId === ingredientId) {\n return;\n }\n kosAction(() => {\n this.ingredientId = ingredientId;\n });\n }\n\n async resolveIntentVolume(intent: string) {\n const pump = this.pumps.data[0];\n if (!pump) {\n return { volume: -1 };\n }\n return pump.resolveIntentVolume(intent);\n }\n\n async overrideRfidCode<T extends Record<string, any>>(overrides: T) {\n if (!overrides) {\n throw new Error(\"Invalid override\");\n }\n try {\n const [error, result] = await sendRfidOverride(this.path, overrides);\n if (error) {\n throw new AssignmentError(\n error,\n `Failed to perform rfid override on holder ${this.id}`\n );\n }\n\n kosAction(() => {\n this.ingredientId = result?.ingredientId;\n });\n return result;\n } catch (e) {\n log.error(`Failed to perform rfid override on holder ${this.id}`, e);\n throw e;\n }\n }\n async assignIngredient(ingredientId?: string) {\n try {\n if (ingredientId) {\n await assignHolderIngredient(this.path, ingredientId);\n } else {\n await unassignHolderIngredient(this.path);\n }\n kosAction(() => {\n this.ingredientId = ingredientId;\n });\n } catch (e) {\n log.error(`Failed to perform assign ingredient to holder ${this.id}`, e);\n throw e;\n }\n }\n\n get shouldDefer() {\n return this.troubles.some((trouble) => trouble.shouldDefer);\n }\n async replaceLine() {\n await replaceLine(this.path);\n\n return;\n }\n\n // -------------------LIFECYCLE----------------------------\n\n // ----------------------------------\n // UNCOMMENT FOR TESTING FUEL GAUGE\n // ----------------------------------\n\n // async load() {\n // const random = Math.max(1000, Math.floor(Math.random() * 5000));\n // this.slice.maxVolMl = 1000;\n // setInterval(() => {\n // kosAction(() => {\n // if (this.remainingVolume < -100) {\n // this.slice.maxVolMl = 1000;\n // this.slice.currentVolMl = this.maxVolume;\n // } else {\n // this.slice.currentVolMl = this.remainingVolume - 50;\n // }\n // });\n // }, random);\n // }\n\n // -------------------ENTITY----------------------------\n}\n\n/**\n * # Holder\n *\n * The registration bean includes convenience methods for creating and working with HolderModel instances.\n *\n * ## type\n * The type property is a string that identifies the model type.\n * The type is used to identify the model type in the model registry and to narrow down the model type in type predicates. It's most frequently\n * used when declaring dependencies on models.\n *\n * @example\n * ```typescript\n *\n * @kosDependency({modelType: Holder.type, id: \"holderId\"})\n * private holderModel: HolderModel;\n * ```\n *\n *\n * ## factory\n *\n * The factory method creates a factory function that can be used to create new HolderModel instances.\n *\n * The factory function is a curried function that takes the model id as the first argument and the options as the second argument.\n *\n * If a model with the specified id already exists, the factory function will return the existing model. The options will be ignored\n * in this case and the existing model will be returned in its current state.\n *\n * @example\n *\n * ```typescript\n * const model = Holder.factory(\"S1\")({\n * path: \"core.dispenser.holder.s1\",\n * name: \"S1\",\n * ingredientId: \"1234532\",\n * assemblyName: \"\",\n * type: \"syrup\",\n * });\n * ```\n *\n * ## predicate\n *\n * [Typescript type predicate](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates) function that will identify and narrow down a model to a HolderModel.\n *\n * @example\n * ```typescript\n *\n * const model: IKosDataModel = ...; // some model\n *\n * if (Holder.predicate(model)) {\n * // if the function evaluates to true, the model is narrowed down to HolderModel\n * // and the compiler will know that the model has the HolderModel interface\n * model.updateAvailability(false);\n * }\n * ```\n *\n * ## registration\n *\n * The registration property is an object that can be used to simplify registration of the model with the model registry. The registration object\n * can be spread into the model registration and provides all of the required information to register the model implementation class against the model type.\n *\n *\n * @example\n *\n * In an application registration file you can declare the model registration as follows:\n *\n * **registration.ts**\n * ```typescript\n * import { Holder } from \"@kosdev-code/kos-dispense-sdk\";\n * ...\n * import { IKosRegistry } from \"@kosdev-code/kos-ui-sdk\";\n * export const kosModels: IKosRegistry[\"models\"] = {\n * ...Holder.registration,\n * };\n * ```\n *\n * ## registration.singleton\n *\n * The holder model is not a singleton model. This means that each time the factory function is called with a unique ID, a new model instance will be created.\n * If the factory function is called with an ID that already exists, the existing model will be returned.\n * */\nexport const Holder: Readonly<\n KosModelRegistrationBean<HolderModel, HolderOptions>\n> = {\n registration: {\n [MODEL_TYPE]: {\n class: HolderModelImpl,\n singleton: false,\n },\n },\n type: MODEL_TYPE,\n predicate: isKosModel(MODEL_TYPE),\n factory: Kos.Factory.create<HolderModel, HolderOptions>(MODEL_TYPE),\n};\n","import { ExtensionManager, KosExtensionUtils } from \"@kosdev-code/kos-ui-sdk\";\nimport { ExtensionType } from \"../../constants\";\nimport { Holder } from \"../holder/holder-model\";\nimport { HolderModel, HolderOptions } from \"../holder/types\";\nimport type { AssemblyHolder } from \"../types/assembly\";\n\nexport const mapAssemblyHolderToModel = async <\n AssemblyHolderResponseExt extends object = any,\n HolderExt extends object = any\n>(\n group: string,\n holderData: AssemblyHolder<AssemblyHolderResponseExt>\n) => {\n const _ingredientId = ExtensionManager.propertyMapper.executeMapper(\n ExtensionType.HolderIngredientMapper,\n holderData\n );\n const type =\n ExtensionManager.propertyMapper.executeMapper(\n ExtensionType.HolderTypeMapper,\n holderData\n ) || holderData.ingType;\n\n const holderExtData = await KosExtensionUtils.executeDataMapperExtension<\n AssemblyHolder<AssemblyHolderResponseExt>,\n HolderExt\n >({\n extension: ExtensionType.HolderMapper,\n data: holderData,\n contextData: {},\n });\n\n const { name, path, ingredientId, ingType, ingSource, slice, ...rest } =\n holderData;\n\n const extData = { ...rest, ...holderExtData };\n const sliceData = slice || { pos: 0 };\n\n const holderOptions: HolderOptions<HolderExt> = {\n name: name,\n path: path,\n ingredientId: _ingredientId || ingredientId,\n ingredientType: type || ingType,\n ingredientSource: ingSource,\n enjoyByDate: holderData.container?.enjoyByDate\n ? new Date(holderData.container.enjoyByDate)\n : undefined,\n slice: sliceData,\n group,\n data: extData,\n };\n const holder = Holder.factory(holderData.path)(holderOptions);\n\n return holder as HolderModel<HolderExt>;\n};\n","import {\n KosLog,\n ServiceFactory,\n resolveServiceUrl,\n} from \"@kosdev-code/kos-ui-sdk\";\nimport type { AssemblyResponse } from \"../../types/assembly\";\nconst { URL } = resolveServiceUrl(\"ASSEMBLY_SERVICE\");\nconst { getOne } = ServiceFactory.build({\n basePath: `${URL}/api/kos/device/assemblies`,\n});\n\nconst log = KosLog.createLogger({\n name: \"assembly-service\",\n group: \"Services\",\n});\n\n/**\n * @category Service\n * Retrieves the initial assembly data.\n */\nexport const getAssembly = async () => {\n log.debug(\"sending GET for assembly\");\n const response = await getOne<AssemblyResponse<{}>>({});\n return response;\n};\n","/* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */\nimport type {\n IKosDataModel,\n IKosModelContainer,\n KosContextLogger,\n KosCreationContext,\n} from \"@kosdev-code/kos-ui-sdk\";\nimport {\n DependencyLifecycle,\n KosModelContainer,\n kosChild,\n kosModel,\n kosTopicHandler,\n} from \"@kosdev-code/kos-ui-sdk\";\nimport { ExtensionType } from \"../../constants\";\nimport type { BoardContainerOptions, BoardModel } from \"./types\";\nimport { type BoardLinkEvent } from \"./types/services\";\n\nexport const MODEL_TYPE = \"board-container-model\";\nexport const TOPIC_BOARD_LINKED = \"/kos/hardware/board/linked\";\nexport const TOPIC_BOARD_UNLINKED = \"/kos/hardware/board/unlinked\";\n\n@kosModel(MODEL_TYPE)\nexport class BoardContainerModel implements IKosDataModel {\n id: string;\n private logger: KosContextLogger;\n @kosChild private models: IKosModelContainer<BoardModel>;\n constructor(\n modelId: string,\n options: BoardContainerOptions,\n context: KosCreationContext\n ) {\n this.id = modelId;\n this.logger = context.logger;\n this.models = new KosModelContainer<BoardModel>({\n parentId: modelId,\n extensionId: ExtensionType.BoardIndex,\n });\n if (options) {\n // Assign options properties here.\n }\n }\n\n get boardList() {\n return this.models.data;\n }\n\n updateModel(): void {\n // Update model properties here.\n }\n\n addModel(model: BoardModel) {\n this.models.addModel(model);\n }\n\n removeModel(id: string) {\n this.models.removeModel(id);\n }\n\n updateBoard(boardLinkEvent: BoardLinkEvent) {\n const boardId = boardLinkEvent.path;\n const board = this.models.getModel(boardId);\n if (!board) {\n this.logger.warn(`board ${boardId} not found`);\n return;\n }\n board.updateModel(boardLinkEvent);\n }\n\n // -------------------SUBSCRIPTIONS----------------------------\n\n @kosTopicHandler({\n lifecycle: DependencyLifecycle.INIT,\n topic: TOPIC_BOARD_LINKED,\n websocket: true,\n })\n handleBoardLinkEvent(boardLinkEvent: BoardLinkEvent) {\n this.logger.debug(`handling ${TOPIC_BOARD_LINKED} event ${boardLinkEvent}`);\n\n if (boardLinkEvent) {\n this.updateBoard(boardLinkEvent);\n } else {\n this.logger.debug(`- boardLinkEvent is undefined`);\n }\n }\n\n @kosTopicHandler({\n lifecycle: DependencyLifecycle.INIT,\n topic: TOPIC_BOARD_UNLINKED,\n websocket: true,\n })\n handleBoardUnlinkEvent(boardLinkEvent: BoardLinkEvent) {\n this.logger.debug(\n `handling ${TOPIC_BOARD_UNLINKED} event ${boardLinkEvent}`\n );\n\n if (boardLinkEvent) {\n this.updateBoard(boardLinkEvent);\n } else {\n this.logger.debug(`- boardLinkEvent is undefined`);\n }\n }\n}\n\nexport interface BoardContainerModel {}\n","import type { TroubleModel } from \"@kosdev-code/kos-ui-sdk\";\nimport { getKosModelSync } from \"@kosdev-code/kos-ui-sdk\";\nimport { BoardModel } from \"../types\";\nimport type { BoardTroubleData } from \"./board-trouble-resolver\";\n\nexport const boardTroubleDataMapper = async (\n trouble: TroubleModel<BoardTroubleData>\n) => {\n const boardPath = trouble.data.boardPath;\n const { model } = getKosModelSync<BoardModel>(boardPath);\n return {\n boardName: model?.name || \"\",\n };\n};\n","import type {\n IKosModelContainer,\n SingletonKosModelRegistrationBean,\n} from \"@kosdev-code/kos-ui-sdk\";\nimport {\n Kos,\n KosModelContainer,\n isKosModel,\n kosChild,\n kosModel,\n} from \"@kosdev-code/kos-ui-sdk\";\nimport { PumpModel } from \"../pump/types\";\nimport type { PumpContainerModel, PumpContainerOptions } from \"./types\";\n\nimport { DispenseModelType, ExtensionType } from \"../../constants\";\n\nconst MODEL_TYPE = DispenseModelType.PumpContainer;\n\n// const log = KosLog.createLogger({ name: \"holder-container-model\" });\n\nexport enum PumpIndex {\n byBoard = \"byBoard\",\n byType = \"byType\",\n byNozzle = \"byNozzle\",\n}\n@kosModel(MODEL_TYPE)\nclass PumpContainerModelImpl implements PumpContainerModel {\n id: string;\n @kosChild private pumps: IKosModelContainer<PumpModel>;\n\n constructor(modelId: string, options: PumpContainerOptions) {\n this.id = modelId;\n this.pumps = new KosModelContainer<PumpModel>({\n indexMap: {\n byNozzle: (pump) => pump.nozzlePaths,\n byBoard: (pump) => pump.boardPath,\n byType: \"type\",\n },\n parentId: modelId,\n extensionId: ExtensionType.PumpIndex,\n });\n if (options) {\n // Assign options properties here.\n }\n }\n\n /**\n * The collection of pump models.\n */\n get pumpModels() {\n return this.pumps.data;\n }\n\n /**\n * The collection of pump paths.\n */\n get pumpPaths() {\n return this.pumpModels.map((pump) => pump.path);\n }\n\n addModel(model: PumpModel) {\n this.pumps.addModel(model);\n }\n removeModel(id: string) {\n this.pumps.removeModel(id);\n }\n\n getModel(id: string) {\n return this.pumps.getModel(id);\n }\n\n get models() {\n return this.pumps;\n }\n get data() {\n return this.pumps.data;\n }\n\n updateModel(): void {\n // Update model properties here.\n }\n\n // -------------------LIFECYCLE----------------------------\n\n async load(): Promise<void> {}\n\n // -------------------ENTITY----------------------------\n}\n\n/**\n * # PumpContainer\n *\n * The registration bean includes convenience methods for creating and working with PumpContainerModel instances.\n *\n * ## type\n * The type property is a string that identifies the model type.\n * The type is used to identify the model type in the model registry and to narrow down the model type in type predicates. It's most frequently\n * used when declaring dependencies on models.\n *\n * @example\n * ```typescript\n *\n * @kosDependency({modelType: PumpContainer.type})\n * private holderContainerModel: PumpContainerModel;\n * ```\n *\n *\n * ## factory\n *\n * The factory function that can be used to create new PumpContainerModel instances.\n *\n * As this is a singleton model, the factory function accepts the model options as its argument.\n *\n * If a model with the same model type already exists, the factory function will return the existing model. The options will be ignored\n * in this case and the existing model will be returned in its current state.\n *\n *\n * @example\n *\n * ```typescript\n * const model = PumpContainer.factory({ });\n * ```\n *\n * ## predicate\n *\n * [Typescript type predicate](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates) function that will identify and narrow down a model to a PumpContainerModel.\n *\n * @example\n * ```typescript\n *\n * const model: IKosDataModel = ...; // some model\n *\n * if (PumpContainer.predicate(model)) {\n * // if the function evaluates to true, the model is narrowed down to PumpContainerModel\n * // and the compiler will know that the model has the PumpContainerModel interface\n * model.updateAvailability(false);\n * }\n * ```\n *\n * ## registration\n *\n * The registration property is an object that can be used to simplify registration of the model with the model registry. The registration object\n * can be spread into the model registration and provides all of the required information to register the model implementation class against the model type.\n *\n *\n * @example\n *\n * In an application registration file you can declare the model registration as follows:\n *\n * **registration.ts**\n * ```typescript\n * import { PumpContainer } from \"@kosdev-code/kos-dispense-sdk\";\n * ...\n * import { IKosRegistry } from \"@kosdev-code/kos-ui-sdk\";\n * export const kosModels: IKosRegistry[\"models\"] = {\n * ...PumpContainer.registration,\n * };\n * ```\n *\n * ## registration.singleton\n * The PumpContainer model is a singleton. This means that each time the factory function is called , the same instance will be returned.\n * If the model does not yet exist, it will be created passing in the provided options to initialize it.\n *\n * * */\nexport const PumpContainer: SingletonKosModelRegistrationBean<\n PumpContainerModel,\n PumpContainerOptions\n> = {\n registration: {\n [MODEL_TYPE]: {\n class: PumpContainerModelImpl,\n singleton: true,\n },\n },\n type: MODEL_TYPE,\n predicate: isKosModel(MODEL_TYPE),\n factory: Kos.Singleton.create<PumpContainerModel, PumpContainerOptions>(\n MODEL_TYPE\n ),\n};\n","import type { TroubleModel } from \"@kosdev-code/kos-ui-sdk\";\nimport { getKosModel } from \"@kosdev-code/kos-ui-sdk\";\nimport type { PumpModel } from \"../types\";\n\nexport interface PumpTroubleData {\n pumpPath: string;\n}\n\nexport const getPumpRelatedPaths = async (pumpPath: string) => {\n const result: string[] = [];\n const { model } = await getKosModel<PumpModel>(pumpPath);\n if (model) {\n result.push(model.boardPath);\n result.push(model.nozzlePath);\n result.push(model.holderPath);\n }\n return result;\n};\n\nexport const pumpTroubleResolver = async (\n trouble: TroubleModel<PumpTroubleData>\n) => {\n const result: string[] = [];\n const pumpPath = trouble.data.pumpPath;\n result.push(pumpPath);\n const relatedPaths = await getPumpRelatedPaths(pumpPath);\n return [...result, ...relatedPaths];\n};\n","import { getKosModel, type TroubleModel } from \"@kosdev-code/kos-ui-sdk\";\nimport {\n PumpContainer,\n PumpContainerModel,\n PumpIndex,\n} from \"../../pump-container\";\nimport { getPumpRelatedPaths } from \"../../pump/utils/pump-trouble-resolver\";\n\nexport interface BoardTroubleData {\n boardPath: string;\n}\n\nexport const boardTroubleResolver = async (\n trouble: TroubleModel<BoardTroubleData>\n) => {\n const result: string[] = [];\n const boardPath = trouble.data.boardPath;\n result.push(trouble.data.boardPath);\n const pumpContainer = await getKosModel<PumpContainerModel>(\n PumpContainer.type\n );\n if (pumpContainer?.model) {\n const boardPumps = pumpContainer.model.models.getIndexByKey(\n PumpIndex.byBoard,\n boardPath\n );\n // iterate over pumps and use the async pump trouble resolve to find all the pump and holder paths\n const pumpPromises = boardPumps.map((pump) =>\n getPumpRelatedPaths(pump.path)\n );\n const pumpResults = await Promise.allSettled(pumpPromises);\n pumpResults.forEach((r) => {\n if (r.status === \"fulfilled\") {\n (r.value as string[]).forEach((path) => result.push(path));\n }\n });\n }\n\n return Array.from(new Set(result));\n};\n","import type {\n IKosDataModel,\n KosContextLogger,\n KosCreationContext,\n} from \"@kosdev-code/kos-ui-sdk\";\nimport {\n EXTENSION_TROUBLE_DATA_MAPPER,\n EXTENSION_TROUBLE_MAPPER,\n ExtensionManager,\n kosModel,\n} from \"@kosdev-code/kos-ui-sdk\";\nimport type { BoardModel, BoardOptions } from \"./types\";\nimport { boardTroubleDataMapper } from \"./utils/board-trouble-data-mapper\";\nimport { boardTroubleResolver } from \"./utils/board-trouble-resolver\";\n\nexport const MODEL_TYPE = \"board-model\";\nconst mapOptionsToModel = <AdditionalData extends object = {}>(\n options: BoardOptions,\n model: BoardModel<AdditionalData>\n) => {\n const { type, name, path, linked, instanceId, link, ...rest } = options;\n model.type = type;\n model.name = name;\n model.path = path;\n model.linked = linked;\n model.link = Object.freeze(link);\n model.instanceId = instanceId;\n Object.assign(model, rest);\n};\n\nExtensionManager[EXTENSION_TROUBLE_MAPPER].register(\n \"board\",\n boardTroubleResolver\n);\n\nExtensionManager[EXTENSION_TROUBLE_DATA_MAPPER].register(\n \"board\",\n boardTroubleDataMapper\n);\n@kosModel(MODEL_TYPE)\nexport class BoardModelImpl<AdditionalData extends object = {}>\n implements IKosDataModel, BoardModel<AdditionalData>\n{\n id: string;\n type!: string;\n name!: string;\n path!: string;\n linked!: boolean;\n instanceId?: string;\n private logger: KosContextLogger;\n constructor(\n modelId: string,\n options: BoardOptions,\n context: KosCreationContext\n ) {\n this.id = modelId;\n\n this.logger = context.logger;\n mapOptionsToModel(options, this);\n }\n\n updateModel(options: BoardOptions): void {\n mapOptionsToModel(options, this);\n }\n\n // -------------------LIFECYCLE----------------------------\n\n async init(): Promise<void> {\n this.logger.debug(`initializing board ${this.id}`);\n }\n\n async load(): Promise<void> {\n this.logger.debug(`loading board ${this.id}`);\n }\n}\n","import type { KosModelRegistrationBean } from \"@kosdev-code/kos-ui-sdk\";\nimport { Kos, isKosModel } from \"@kosdev-code/kos-ui-sdk\";\nimport { BoardModelImpl, MODEL_TYPE } from \"./board-model\";\nimport type { BoardModel, BoardOptions } from \"./types\";\n\n/**\n * # Board\n *\n * The registration bean includes convenience methods for creating and working with BoardModel instances.\n *\n * ## type\n * The type property is a string that identifies the model type.\n * The type is used to identify the model type in the model registry and to narrow down the model type in type predicates. It's most frequently\n * used when declaring dependencies on models.\n *\n * @example\n * ```typescript\n *\n * @kosDependency({modelType: Board.type, id: \"boardId\"})\n * private boardModel: BoardModel;\n * ```\n *\n *\n * ## factory\n *\n * The factory method creates a factory function that can be used to create new BoardModel instances.\n *\n \n * The factory function is a curried function that takes the model id as the first argument and the options as the second argument.\n *\n * If a model with the specified id already exists, the factory function will return the existing model. The options will be ignored\n * in this case and the existing model will be returned in its current state.\n *\n * @example\n * ```typescript\n * const model = Board.factory(\"boardId\")({\n * // Add option data\n * });\n * ```\n \n\n *\n * ## predicate\n *\n * [Typescript type predicate](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates) function that will identify and narrow down a model to a BoardModel.\n *\n * @example\n * ```typescript\n *\n * const model: IKosDataModel = ...; // some model\n *\n * if (Board.predicate(model)) {\n * // if the function evaluates to true, the model is narrowed down to BoardModel\n * // and the compiler will know that the model has the BoardModel interface\n * model.updateAvailability(false);\n * }\n * ```\n *\n * ## registration\n *\n * The registration property is an object that can be used to simplify registration of the model with the model registry. The registration object\n * can be spread into the model registration and provides all of the required information to register the model implementation class against the model type.\n *\n *\n * @example\n *\n * In an application registration file you can declare the model registration as follows:\n *\n * **registration.ts**\n * ```typescript\n * import { Board } from \"@kosdev-code/kos-dispense-sdk\";\n * ...\n * import { ExtensionManager, IKosRegistry } from \"@kosdev-code/kos-ui-sdk\";\n * export const kosModels: IKosRegistry[\"models\"] = {\n * ...Board.registration,\n * };\n * ```\n *\n * ## registration.singleton\n \n * The board model is NOT a singleton model. This means that each time the factory function is called with a unique ID, a new model instance will be created.\n * If the factory function is called with an ID that already exists, the existing model will be returned.\n \n * */\nexport const Board: Readonly<\n KosModelRegistrationBean<BoardModel, BoardOptions>\n> = {\n registration: {\n [MODEL_TYPE]: {\n class: BoardModelImpl,\n singleton: false,\n },\n },\n type: MODEL_TYPE,\n predicate: isKosModel(MODEL_TYPE),\n factory: Kos.Factory.create<BoardModel, BoardOptions>(MODEL_TYPE),\n};\n","import type { SingletonKosModelRegistrationBean } from \"@kosdev-code/kos-ui-sdk\";\nimport { Kos, isKosModel } from \"@kosdev-code/kos-ui-sdk\";\nimport { BoardContainerModel, MODEL_TYPE } from \"./board-container-model\";\nimport { Board } from \"./board-registration\";\nimport type { BoardContainerOptions } from \"./types\";\n\n/**\n * # BoardContainer\n *\n * The registration bean includes convenience methods for creating and working with BoardContainerModel instances.\n *\n * ## type\n * The type property is a string that identifies the model type.\n * The type is used to identify the model type in the model registry and to narrow down the model type in type predicates. It's most frequently\n * used when declaring dependencies on models.\n *\n * @example\n * ```typescript\n *\n * @kosDependency({modelType: BoardContainer.type, id: \"boardContainerId\"})\n * private boardContainerModel: BoardContainerModel;\n * ```\n *\n *\n * ## factory\n *\n * The factory method creates a factory function that can be used to create new BoardContainerModel instances.\n *\n \n * As this is a singleton model, the factory function accepts the model options as its argument.\n *\n * If a model with the same model type already exists, the factory function will return the existing model. The options will be ignored\n * in this case and the existing model will be returned in its current state.\n *\n * @example\n * ```typescript\n * const model = BoardContainer.factory({\n * // Add option data\n * });\n * ```\n \n\n *\n * ## predicate\n *\n * [Typescript type predicate](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates) function that will identify and narrow down a model to a BoardContainerModel.\n *\n * @example\n * ```typescript\n *\n * const model: IKosDataModel = ...; // some model\n *\n * if (BoardContainer.predicate(model)) {\n * // if the function evaluates to true, the model is narrowed down to BoardContainerModel\n * // and the compiler will know that the model has the BoardContainerModel interface\n * model.updateAvailability(false);\n * }\n * ```\n *\n * ## registration\n *\n * The registration property is an object that can be used to simplify registration of the model with the model registry. The registration object\n * can be spread into the model registration and provides all of the required information to register the model implementation class against the model type.\n *\n *\n * @example\n *\n * In an application registration file you can declare the model registration as follows:\n *\n * **registration.ts**\n * ```typescript\n * import { BoardContainer } from \"@kosdev-code/kos-dispense-sdk\";\n * ...\n * import { ExtensionManager, IKosRegistry } from \"@kosdev-code/kos-ui-sdk\";\n * export const kosModels: IKosRegistry[\"models\"] = {\n * ...BoardContainer.registration,\n * };\n * ```\n *\n * ## registration.singleton\n \n * The boardContainer model is a singleton model. This means that each time the factory function is called , the same instance will be returned.\n * If the model does not yet exist, it will be created passing in the provided options to initialize it.\n *\n * Singleton models don't require an ID as they will use the model type as their ID to guarantee uniqueness throughout the system.\n \n * */\nexport const BoardContainer: Readonly<\n SingletonKosModelRegistrationBean<BoardContainerModel, BoardContainerOptions>\n> = {\n registration: {\n [MODEL_TYPE]: {\n class: BoardContainerModel,\n singleton: true,\n },\n ...Board.registration,\n },\n type: MODEL_TYPE,\n predicate: isKosModel(MODEL_TYPE),\n factory: Kos.Singleton.create<BoardContainerModel, BoardContainerOptions>(\n MODEL_TYPE\n ),\n};\n","import type {\n IKosModelContainer,\n KosContextLogger,\n KosCreationContext,\n SingletonKosModelRegistrationBean,\n} from \"@kosdev-code/kos-ui-sdk\";\nimport {\n Kos,\n KosLog,\n KosModelContainer,\n isKosModel,\n kosAction,\n kosChild,\n kosModel,\n kosTopicHandler,\n} from \"@kosdev-code/kos-ui-sdk\";\nimport type { HolderModel } from \"../holder/types\";\nimport type {\n HolderContainerModel,\n HolderContainerOptions,\n HolderPathAware,\n InsertionEvent,\n} from \"./types\";\n\nimport { DispenseModelType, ExtensionType } from \"../../constants\";\n\nconst MODEL_TYPE = DispenseModelType.HolderContainer;\nconst TOPIC_INSERT_START = \"/kos/insertion/insert/start\";\nconst TOPIC_INSERT_COMPLETE = \"/kos/insertion/insert/complete\";\nconst TOPIC_INSERT_UPDATE = \"/kos/insertion/insert/update\";\nconst TOPIC_REMOVE = \"/kos/insertion/remove\";\nconst TOPIC_REPLACE_LINE = \"/kos/pumpEvent/replaceLine\";\nconst TOPIC_HOLDER_CHANGED = \"/kos/handle/*\";\n\n// const log = KosLog.createLogger({ name: \"holder-container-model\" });\n\n@kosModel(MODEL_TYPE)\nclass HolderContainerModelImpl implements HolderContainerModel {\n id: string;\n @kosChild holders: IKosModelContainer<HolderModel>;\n\n private logger: KosContextLogger;\n constructor(\n modelId: string,\n _options: HolderContainerOptions,\n context: KosCreationContext\n ) {\n this.id = modelId;\n this.holders = new KosModelContainer<HolderModel>({\n indexMap: {\n nozzle: (holder) => holder.nozzlePaths,\n group: \"group\",\n },\n parentId: modelId,\n extensionId: ExtensionType.HolderIndex,\n });\n this.logger = context.logger;\n }\n\n updateModel(): void {\n // Update model properties here.\n }\n\n // -------------------LIFECYCLE----------------------------\n\n @kosTopicHandler({\n topic: TOPIC_HOLDER_CHANGED,\n websocket: true,\n condition: (event: HolderPathAware, model: HolderContainerModel) =>\n model.holders.getModel(event.path) !== undefined,\n })\n handleHolderEvents(event: HolderPathAware) {\n KosLog.ifDebug(() =>\n this.logger.debug(\"Received holder change event\", JSON.stringify(event))\n );\n const holder = this.holders.getModel(event.path);\n\n if (holder) {\n this.logger.info(\n `Received change event for holder ${holder.path}. Updating fuel gauge data.`\n );\n holder.slice.currentVolMl = event.slice?.currentVolMl;\n holder.slice.maxVolMl = event.slice?.maxVolMl;\n if (event?.container?.enjoyByDate) {\n holder.enjoyByDate = new Date(event.container.enjoyByDate);\n } else {\n holder.enjoyByDate = undefined;\n }\n }\n }\n @kosTopicHandler({\n topic: [\n TOPIC_INSERT_START,\n TOPIC_INSERT_COMPLETE,\n TOPIC_INSERT_UPDATE,\n TOPIC_REMOVE,\n TOPIC_REPLACE_LINE,\n ],\n websocket: true,\n })\n handleInsertion(data: InsertionEvent[]) {\n KosLog.ifDebug(() =>\n this.logger.debug(\"Received insertion event\", JSON.stringify(data))\n );\n const wrappedData = Array.isArray(data) ? data : [data];\n wrappedData.forEach((event) => {\n kosAction(() => {\n const ingredientId = event.ingredientId;\n const holder = this.holders.getModel(event.path);\n if (holder) {\n this.logger.info(\n `Received insertion event for holder ${holder.path}`\n );\n holder.updateIngredient(ingredientId);\n\n // update fuel gauge data\n holder.slice.currentVolMl = event.slice?.currentVolMl;\n holder.slice.maxVolMl = event.slice?.maxVolMl;\n if (event?.container?.enjoyByDate) {\n holder.enjoyByDate = new Date(event.container.enjoyByDate);\n } else {\n holder.enjoyByDate = undefined;\n }\n\n event.pumps.forEach((pump) => {\n kosAction(() => {\n const pumpModel = holder.pumps.getModel(pump.path);\n if (pumpModel) {\n pumpModel.ingredientId = pump.ingredientId;\n pumpModel.inserted = pump.inserted;\n pumpModel.prevIngredientId = pump.prevIngredientId;\n }\n });\n });\n }\n });\n });\n }\n\n // -------------------ENTITY----------------------------\n}\n\n/**\n * # HolderContainer\n *\n * The registration bean includes convenience methods for creating and working with HolderContainerModel instances.\n *\n * ## type\n * The type property is a string that identifies the model type.\n * The type is used to identify the model type in the model registry and to narrow down the model type in type predicates. It's most frequently\n * used when declaring dependencies on models.\n *\n * @example\n * ```typescript\n *\n * @kosDependency({modelType: HolderContainer.type})\n * private holderContainerModel: HolderContainerModel;\n * ```\n *\n *\n * ## factory\n *\n * The factory function that can be used to create new HolderContainerModel instances.\n *\n * As this is a singleton model, the factory function accepts the model options as its argument.\n *\n * If a model with the same model type already exists, the factory function will return the existing model. The options will be ignored\n * in this case and the existing model will be returned in its current state.\n *\n *\n * @example\n *\n * ```typescript\n * const model = HolderContainer.factory({ });\n * ```\n *\n * ## predicate\n *\n * [Typescript type predicate](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates) function that will identify and narrow down a model to a HolderContainerModel.\n *\n * @example\n * ```typescript\n *\n * const model: IKosDataModel = ...; // some model\n *\n * if (HolderContainer.predicate(model)) {\n * // if the function evaluates to true, the model is narrowed down to HolderContainerModel\n * // and the compiler will know that the model has the HolderContainerModel interface\n * model.updateAvailability(false);\n * }\n * ```\n *\n * ## registration\n *\n * The registration property is an object that can be used to simplify registration of the model with the model registry. The registration object\n * can be spread into the model registration and provides all of the required information to register the model implementation class against the model type.\n *\n *\n * @example\n *\n * In an application registration file you can declare the model registration as follows:\n *\n * **registration.ts**\n * ```typescript\n * import { HolderContainer } from \"@kosdev-code/kos-dispense-sdk\";\n * ...\n * import { IKosRegistry } from \"@kosdev-code/kos-ui-sdk\";\n * export const kosModels: IKosRegistry[\"models\"] = {\n * ...HolderContainer.registration,\n * };\n * ```\n *\n * ## registration.singleton\n * The HolderContainer model is a singleton. This means that each time the factory function is called , the same instance will be returned.\n * If the model does not yet exist, it will be created passing in the provided options to initialize it.\n *\n * * */\nexport const HolderContainer: SingletonKosModelRegistrationBean<\n HolderContainerModel,\n HolderContainerOptions\n> = {\n registration: {\n [MODEL_TYPE]: {\n class: HolderContainerModelImpl,\n singleton: true,\n },\n },\n type: MODEL_TYPE,\n predicate: isKosModel(MODEL_TYPE),\n factory: Kos.Singleton.create<HolderContainerModel, HolderContainerOptions>(\n MODEL_TYPE\n ),\n};\n","import { KosExtensionUtils, KosLog } from \"@kosdev-code/kos-ui-sdk\";\nimport { ExtensionType } from \"../../constants\";\nimport { Board, type BoardContainerModel, type BoardOptions } from \"../board\";\nimport type { AssemblyBoard } from \"../types/assembly\";\n\nconst Logger = KosLog.createLogger({ name: \"board-utils\" });\nexport const mapAssemblyBoardToModel = async <\n AssemblyBoardResponseExt extends object = any,\n BoardExt extends object = any\n>(\n board: AssemblyBoard<AssemblyBoardResponseExt>\n) => {\n const boardExtData = await KosExtensionUtils.executeDataMapperExtension<\n AssemblyBoard<AssemblyBoardResponseExt>,\n BoardExt\n >({\n extension: ExtensionType.BoardMapper,\n data: board,\n contextData: {},\n });\n const { type, name, path, linked, instanceId, ...rest } = board;\n const extData = { ...rest, ...boardExtData };\n const options: BoardOptions<BoardExt> = {\n type: type,\n name: name,\n path: path,\n linked: linked,\n instanceId: instanceId,\n ...extData,\n };\n\n const boardModel = Board.factory(board.path)(options);\n\n boardModel.updateModel(options);\n\n return boardModel;\n};\n\nexport const assemblyBoardMap =\n (boardContainer: BoardContainerModel) => async (board: AssemblyBoard) => {\n Logger.debug(`adding board ${board.name}`);\n const boardModel = await mapAssemblyBoardToModel(board);\n boardContainer.addModel(boardModel);\n };\n","export enum PourState {\n IDLE = \"IDLE\",\n POURING = \"POURING\",\n POUR_STARTING = \"POUR_STARTING\",\n POUR_CANCELING = \"POUR_CANCELING\",\n POUR_CANCELED = \"POUR_CANCELED\",\n POUR_COMPLETE = \"POUR_COMPLETE\",\n}\n","import {\n FutureManager,\n FutureResponse,\n KosLog,\n KosServiceResponse,\n ServiceFactory,\n resolveServiceUrl,\n} from \"@kosdev-code/kos-ui-sdk\";\nconst { URL } = resolveServiceUrl(\"PUMP_SERVICE\");\nconst { postModel, getOne } = ServiceFactory.build({\n basePath: `${URL}/api/kos/holders`,\n});\n\nconst log = KosLog.createLogger({\n name: \"pump-service\",\n group: \"Services\",\n});\n\nexport interface PumpResponse {\n inserted: boolean;\n beveragePour: boolean;\n ingredientPour: boolean;\n type: string;\n ingredientId: string;\n holderPath: string;\n boardPath: string;\n nozzlePath: string;\n name: string;\n path: string;\n category: string;\n}\n\ninterface IntentRequest {\n intent: string;\n pumpId: string;\n tracker: string;\n}\n\ninterface IntentVolumeResponse {\n volume: number;\n}\n\nexport const sendIntent = async ({\n intent,\n pumpId,\n tracker,\n}: IntentRequest) => {\n const url = `${URL}/api/ext/dispense/nozzle/nozzle/pipeline/ingredient/pour/${pumpId}/${intent}`;\n const response: KosServiceResponse<FutureResponse> | undefined =\n await postModel({ model: {}, urlOverride: url, tracker });\n if (response?.data) {\n FutureManager.initiateFuture(response.data);\n }\n return response;\n};\n\nexport const getIntentVolume = async (pumpId: string, intent: string) => {\n const url = `${URL}/api/ext/dispense/nozzle/nozzle/pipeline/ingredient/intent/${pumpId}/${intent}/volume`;\n const response: KosServiceResponse<IntentVolumeResponse> | undefined =\n await getOne({ urlOverride: url });\n if (!response?.data) {\n return { volume: -1 };\n }\n return response.data;\n};\n","/* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */\nimport type {\n FutureAwareContainer,\n FutureContainer,\n IFutureModel,\n KosModelRegistrationBean,\n TroubleAware,\n} from \"@kosdev-code/kos-ui-sdk\";\nimport {\n EXTENSION_TROUBLE_MAPPER,\n ExtensionManager,\n FutureHandler,\n Kos,\n KosLog,\n isKosModel,\n kosAction,\n kosFuture,\n kosModel,\n} from \"@kosdev-code/kos-ui-sdk\";\nimport type { PumpModel, PumpOptions } from \"./types\";\n\nimport { DispenseModelType } from \"../../constants\";\n\nimport type { IntentAwareProps } from \"../types/intent\";\nimport { PourState } from \"../types/pouring\";\nimport { getIntentVolume, sendIntent } from \"./services/pump-services\";\nimport { pumpTroubleResolver } from \"./utils/pump-trouble-resolver\";\n\nconst MODEL_TYPE = DispenseModelType.Pump;\n\nExtensionManager[EXTENSION_TROUBLE_MAPPER].register(\n \"pump\",\n pumpTroubleResolver\n);\n\n// eslint-disable-next-line @typescript-eslint/no-empty-interface\ninterface PumpModelImpl<AdditionalData extends object = any>\n extends TroubleAware {}\n@kosModel(MODEL_TYPE)\nclass PumpModelImpl<AdditionalData extends object = any>\n implements PumpModel<AdditionalData>, FutureContainer\n{\n id: string;\n inserted: boolean;\n type: string;\n virtual?: boolean;\n ingredientId?: string;\n holderPath: string;\n boardPath: string;\n nozzlePath: string;\n childPump: boolean;\n name: string;\n path: string;\n prevIngredientId?: string;\n\n futureHandler: FutureAwareContainer;\n currentState: PourState = PourState.IDLE;\n constructor(modelId: string, options: PumpOptions<AdditionalData>) {\n this.id = modelId;\n const {\n inserted,\n holderPath,\n boardPath,\n nozzlePath,\n name,\n path,\n childPump,\n virtual,\n prevIngredientId,\n ...rest\n } = options;\n this.inserted = inserted;\n\n this.type = options.type;\n this.ingredientId = options.ingredientId;\n this.holderPath = holderPath;\n this.boardPath = boardPath;\n this.nozzlePath = nozzlePath;\n this.name = name;\n this.path = path;\n this.childPump = !!childPump;\n this.virtual = !!virtual;\n this.prevIngredientId = prevIngredientId;\n Object.assign(this, rest);\n this.futureHandler = new FutureHandler(this);\n }\n\n updateModel(options: PumpOptions<AdditionalData>): void {\n const {\n inserted,\n holderPath,\n boardPath,\n nozzlePath,\n childPump,\n name,\n path,\n ...rest\n } = options;\n this.inserted = inserted;\n this.type = options.type;\n this.ingredientId = options.ingredientId;\n this.holderPath = holderPath;\n this.boardPath = boardPath;\n this.nozzlePath = nozzlePath;\n\n // once set to true, childPump cannot be set to false\n this.childPump = this.childPump ? this.childPump : !!childPump;\n this.name = name;\n this.path = path;\n this.prevIngredientId = options.prevIngredientId;\n Object.assign(this, rest);\n }\n\n // -------------------LIFECYCLE----------------------------\n\n get pouringState() {\n return this.future?.endState || \"\";\n }\n get isPouring() {\n return (\n !!(this.future && !this.future?.endState) ||\n this.currentState === PourState.POUR_STARTING ||\n this.currentState === PourState.POURING\n );\n }\n\n get canPour() {\n return !!this.ingredientId && !this.isPouring;\n }\n\n onFutureUpdate(future: IFutureModel) {\n if (future.endState) {\n kosAction(() => {\n this.currentState = PourState.IDLE;\n });\n }\n }\n\n async cancelPour() {\n if (\n this.currentState === PourState.POURING ||\n this.currentState === PourState.POUR_STARTING\n ) {\n this.currentState = PourState.POUR_CANCELING;\n await this.future?.cancelFuture();\n kosAction(() => {\n this.currentState = PourState.IDLE;\n });\n } else {\n KosLog.warn(`Cannot cancel pour in state ${this.currentState}`);\n }\n }\n\n get future() {\n return this.futureHandler.future;\n }\n\n async resolveIntentVolume(intent: string) {\n return await getIntentVolume(this.path, intent);\n }\n\n @kosFuture()\n async performIntent(props: IntentAwareProps, tracker?: string) {\n const intent = typeof props === \"string\" ? props : props.intent;\n if (!intent) {\n throw new Error(\"No intent provided\");\n }\n\n try {\n if (this.currentState === PourState.IDLE) {\n this.currentState = PourState.POUR_STARTING;\n if (!tracker) {\n throw new Error(\"No tracker provided\");\n }\n\n const result = await sendIntent({\n tracker,\n intent,\n pumpId: this.path,\n });\n if (this.currentState === PourState.POUR_STARTING) {\n kosAction(() => {\n this.currentState = PourState.POURING;\n });\n }\n return result?.data;\n } else {\n throw new Error(`Cannot pour in state ${this.currentState}`);\n }\n } catch (e) {\n KosLog.error(e);\n this.currentState = PourState.IDLE;\n throw e;\n }\n }\n\n // -------------------ENTITY----------------------------\n}\n\n/**\n * # Pump\n *\n * The registration bean includes convenience methods for creating and working with PumpModel instances.\n *\n * ## type\n * The type property is a string that identifies the model type.\n * The type is used to identify the model type in the model registry and to narrow down the model type in type predicates. It's most frequently\n * used when declaring dependencies on models.\n *\n * @example\n * ```typescript\n *\n * @kosDependency({modelType: Pump.type, id: \"pumpId\"})\n * private pumpModel: PumpModel;\n * ```\n *\n *\n * ## factory\n *\n * The factory method creates a factory function that can be used to create new PumpModel instances.\n *\n * The factory function is a curried function that takes the model id as the first argument and the options as the second argument.\n *\n * If a model with the specified id already exists, the factory function will return the existing model. The options will be ignored\n * in this case and the existing model will be returned in its current state.\n *\n * @example\n *\n * ```typescript\n * const model = Pump.factory(\"S1\")({\n * name: \"S1\",\n * path: \"core.assembly.pump.S1\",\n * beveragePour: true,\n * type: \"syrup\",\n * ingredientId: \"1234532\",\n * holderPath: \"core.dispenser.holder.s1\",\n * boardPath: \"core.dispenser.board.s1\",\n * nozzlePath: \"core.dispenser.nozzle.s1\",\n * inserted: true,\n * category: \"flavor\",\n * prevIngredientId: \"1234567\",\n * });\n * ```\n *\n * ## predicate\n *\n * [Typescript type predicate](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates) function that will identify and narrow down a model to a PumpModel.\n *\n * @example\n * ```typescript\n *\n * const model: IKosDataModel = ...; // some model\n *\n * if (Pump.predicate(model)) {\n * // if the function evaluates to true, the model is narrowed down to PumpModel\n * // and the compiler will know that the model has the PumpModel interface\n * model.updateAvailability(false);\n * }\n * ```\n *\n * ## registration\n *\n * The registration property is an object that can be used to simplify registration of the model with the model registry. The registration object\n * can be spread into the model registration and provides all of the required information to register the model implementation class against the model type.\n *\n *\n * @example\n *\n * In an application registration file you can declare the model registration as follows:\n *\n * **registration.ts**\n * ```typescript\n * import { Pump } from \"@kosdev-code/kos-dispense-sdk\";\n * ...\n * import { IKosRegistry } from \"@kosdev-code/kos-ui-sdk\";\n * export const kosModels: IKosRegistry[\"models\"] = {\n * ...Pump.registration,\n * };\n * ```\n *\n * ## registration.singleton\n *\n * The pump model is not a singleton model. This means that each time the factory function is called with a unique ID, a new model instance will be created.\n * If the factory function is called with an ID that already exists, the existing model will be returned.\n * */\nexport const Pump: Readonly<KosModelRegistrationBean<PumpModel, PumpOptions>> =\n {\n registration: {\n [MODEL_TYPE]: {\n class: PumpModelImpl,\n singleton: false,\n },\n },\n type: MODEL_TYPE,\n predicate: isKosModel(MODEL_TYPE),\n factory: Kos.Factory.create<PumpModel, PumpOptions>(MODEL_TYPE),\n };\n","import { KosLog } from \"@kosdev-code/kos-ui-sdk\";\nimport type { HolderContainerModel } from \"../holder-container\";\nimport { Pump, type PumpOptions } from \"../pump\";\nimport type { PumpContainerModel } from \"../pump-container\";\nimport type { AssemblyNozzle, AssemblyPump } from \"../types/assembly\";\nconst Logger = KosLog.createLogger({ name: \"pump-utils\" });\nexport const mapAssemblyPumpToModel = (\n nozzlePath: string,\n pump: AssemblyPump\n) => {\n const virtual = (pump.pumps ?? []).length > 1;\n const options: PumpOptions = {\n boardPath: pump.boardPath,\n holderPath: pump.holderPath,\n ingredientId: pump.ingredientId,\n childPump: !!pump.childPump,\n virtual,\n inserted: pump.inserted,\n name: pump.name,\n path: pump.path,\n type: pump.type,\n nozzlePath,\n prevIngredientId: pump.prevIngredientId,\n };\n const pumpModel = Pump.factory(pump.path)(options);\n\n pumpModel.updateModel(options);\n\n return pumpModel;\n};\n\nexport const assemblyPumpMap =\n (pumpContainer: PumpContainerModel) =>\n (holderContainer: HolderContainerModel) =>\n (nozzle: AssemblyNozzle) =>\n (assemblyPump: AssemblyPump) => {\n Logger.debug(`adding pump ${assemblyPump.name}`);\n const pump = mapAssemblyPumpToModel(nozzle.path, assemblyPump);\n pumpContainer.addModel(pump);\n const holderPath = pump.holderPath;\n const holder = holderContainer.holders.getModel(holderPath);\n holder?.pumps.addModel(pump);\n if (!holder?.nozzlePaths.includes(nozzle.path)) {\n holder?.nozzlePaths.push(nozzle.path);\n }\n\n assemblyPump?.pumps?.forEach((subPump) => {\n const subHolderPath = pump.holderPath;\n const subPumpData = {\n ...subPump,\n childPump: true,\n holderPath: subHolderPath,\n ingredientId: pump.ingredientId,\n };\n assemblyPumpMap(pumpContainer)(holderContainer)(nozzle)(subPumpData);\n });\n };\n","import type {\n IKosModelLogger,\n KosContext,\n KosContextLogger,\n KosCreationContext,\n TroubleContainerModel,\n} from \"@kosdev-code/kos-ui-sdk\";\nimport {\n ChildModels,\n EXTENSION_FEATURE_FLAG_RESOLVER,\n ExtensionManager,\n KosExtensionUtils,\n KosFeatureFlags,\n isKosDataModel,\n kosChild,\n kosDependency,\n kosModel,\n} from \"@kosdev-code/kos-ui-sdk\";\nimport { mapAssemblyHolderToModel } from \"./holder-utils\";\nimport { getAssembly } from \"./services\";\nimport type { AssemblyModel, AssemblyOptions } from \"./types\";\n\nimport { ExtensionType } from \"../../constants\";\nimport {\n BoardContainer,\n type BoardContainerModel,\n type BoardModel,\n} from \"../board\";\nimport { type HolderModel } from \"../holder\";\nimport {\n HolderContainer,\n type HolderContainerModel,\n} from \"../holder-container\";\nimport type { PumpModel } from \"../pump\";\nimport { PumpContainer, type PumpContainerModel } from \"../pump-container\";\nimport type { AssemblyResponse } from \"../types/assembly\";\nimport { assemblyBoardMap } from \"./board-utils\";\nimport { assemblyPumpMap } from \"./pump-utils\";\n\nexport const MODEL_TYPE = \"assembly-model\";\nexport const CONTEXT_ASSEMBLY_DATA = \"assembly-data\";\nexport const CONTEXT_ASSEMBLY_RAW_DATA = \"assembly-raw-data\";\n@kosModel(MODEL_TYPE)\nexport class AssemblyModelImpl<\n AssemblyExt extends object = any,\n HolderExt extends object = any\n> implements AssemblyModel<AssemblyExt>, IKosModelLogger\n{\n id: string;\n private _nozzlePaths = new Set<string>();\n @kosDependency({\n modelType: \"trouble-container-model\",\n })\n private troubleContainer!: TroubleContainerModel;\n\n @kosChild private holderContainer: HolderContainerModel;\n @kosChild private boardContainer: BoardContainerModel;\n @kosChild private pumpContainer: PumpContainerModel;\n logger: KosContextLogger;\n constructor(\n modelId: string,\n _options: AssemblyOptions,\n context: KosCreationContext\n ) {\n this.id = modelId;\n this.holderContainer = HolderContainer.factory({});\n this.boardContainer = BoardContainer.factory({});\n this.pumpContainer = PumpContainer.factory({});\n this.logger = context.logger;\n }\n\n updateModel(_options: AssemblyOptions): void {\n // Update model properties here.\n }\n\n get allHolders(): HolderModel<HolderExt>[] {\n return this.holderContainer.holders.data;\n }\n\n get holderGroups(): string[] {\n return this.holderContainer.holders.getIndexKeys(\"group\");\n }\n\n get nozzlePaths(): string[] {\n return Array.from(this._nozzlePaths);\n }\n getHoldersByGroup(group: string): HolderModel<HolderExt>[] {\n return this.holderContainer.holders.getIndexByKey(\"group\", group);\n }\n\n getHoldersByNozzle(nozzlePath: string): HolderModel<HolderExt>[] {\n return this.holderContainer.holders.getIndexByKey(\"nozzle\", nozzlePath);\n }\n\n /**\n * Returns a map of the pumps associated with each nozzle\n *\n * Can be used in conjunction with the nozzlePaths to get the pumps associated with each nozzle\n * @returns Record<string, PumpModel[]>\n */\n get pumpsByNozzle(): Record<string, PumpModel<any>[]> {\n return this.pumpContainer.models.idx.byNozzle;\n }\n\n /**\n * Returns a list of all fo the pumps paths across the entire assembly.\n */\n get pumpPaths(): string[] {\n return this.pumpContainer.models.data.map((pump) => pump.path);\n }\n\n get boards(): BoardModel<any>[] {\n return this.boardContainer.boardList;\n }\n\n // -------------------LIFECYCLE----------------------------\n\n async init(): Promise<void> {\n this.logger.debug(`initializing assembly ${this.id}`);\n }\n\n async ready() {\n this.troubleContainer?.troubles.increment();\n ExtensionManager[EXTENSION_FEATURE_FLAG_RESOLVER].execute(\n ExtensionType.AssemblyFeatureFlags,\n this\n );\n }\n\n async load(context: KosContext): Promise<void> {\n this.logger.debug(`loading assembly ${this.id}`);\n\n const result = await getAssembly();\n if (result?.status === 200) {\n const data = await KosExtensionUtils.executeDataMapperExtension<\n AssemblyResponse<{}>,\n AssemblyExt\n >({\n extension: ExtensionType.AssemblyMapper,\n data: result.data,\n contextData: {},\n });\n\n context.set(CONTEXT_ASSEMBLY_DATA, data);\n // assign any additional data to the model\n // data is the result of the extension mapper\n Object.assign(this, data);\n\n // add any child models to the model\n // register them as child models so that they participate in the Assembly model lifecycle\n Object.entries(data).forEach(([key, value]) => {\n if (isKosDataModel(value)) {\n this.logger.debug(`adding child model ${key} from extension data`);\n this[ChildModels][key] = true;\n }\n });\n\n context.set(CONTEXT_ASSEMBLY_RAW_DATA, result.data);\n // iterate through all of the assemblies and add the boards, holders, pumps and nozzles\n for await (const assembly of result.data.assemblies) {\n const {\n boards = [],\n holders: assemblyHolders = {},\n nozzles = [],\n core: _core,\n name,\n path: _path,\n ...rest\n } = assembly;\n\n this.logger.debug(`adding assembly ${name}`);\n\n Object.keys(rest).forEach((key) => {\n KosFeatureFlags.enableFeature(key);\n });\n // add the boards to the assembly model in the board container\n\n for await (const board of boards) {\n this.logger.debug(`adding board ${board.name}`);\n const mapper = assemblyBoardMap(this.boardContainer);\n await mapper(board);\n }\n\n // add the holders to the assembly model in the holder container\n for await (const [group, holders] of Object.entries(\n assemblyHolders ?? {}\n )) {\n for await (const holder of holders) {\n this.logger.debug(`adding holder ${holder.name}`);\n const holderModel = await mapAssemblyHolderToModel(group, holder);\n this.holderContainer.holders.addModel(holderModel);\n }\n }\n\n // add the pumps to the assembly model\n const nozzlePumpMap = assemblyPumpMap(this.pumpContainer)(\n this.holderContainer\n );\n nozzles.forEach((nozzle) => {\n this._nozzlePaths.add(nozzle.path);\n const pumpMap = nozzlePumpMap(nozzle);\n nozzle.pumps.forEach(pumpMap);\n });\n }\n }\n }\n}\n","import type { SingletonKosModelRegistrationBean } from \"@kosdev-code/kos-ui-sdk\";\nimport { Kos, isKosModel } from \"@kosdev-code/kos-ui-sdk\";\nimport { AssemblyModelImpl, MODEL_TYPE } from \"./assembly-model\";\nimport type { AssemblyModel, AssemblyOptions } from \"./types\";\n\n/**\n * # Assembly\n *\n * The registration bean includes convenience methods for creating and working with AssemblyModel instances.\n *\n * ## type\n * The type property is a string that identifies the model type.\n * The type is used to identify the model type in the model registry and to narrow down the model type in type predicates. It's most frequently\n * used when declaring dependencies on models.\n *\n * @example\n * ```typescript\n *\n * @kosDependency({modelType: Assembly.type, id: \"assemblyId\"})\n * private assemblyModel: AssemblyModel;\n * ```\n *\n *\n * ## factory\n *\n * The factory method creates a factory function that can be used to create new AssemblyModel instances.\n *\n \n * The factory function is a curried function that takes the model id as the first argument and the options as the second argument.\n *\n * If a model with the specified id already exists, the factory function will return the existing model. The options will be ignored\n * in this case and the existing model will be returned in its current state.\n *\n * @example\n * ```typescript\n * const model = Assembly.factory(\"assemblyId\")({\n * // Add option data\n * });\n * ```\n \n\n *\n * ## predicate\n *\n * [Typescript type predicate](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates) function that will identify and narrow down a model to a AssemblyModel.\n *\n * @example\n * ```typescript\n *\n * const model: IKosDataModel = ...; // some model\n *\n * if (Assembly.predicate(model)) {\n * // if the function evaluates to true, the model is narrowed down to AssemblyModel\n * // and the compiler will know that the model has the AssemblyModel interface\n * model.updateAvailability(false);\n * }\n * ```\n *\n * ## registration\n *\n * The registration property is an object that can be used to simplify registration of the model with the model registry. The registration object\n * can be spread into the model registration and provides all of the required information to register the model implementation class against the model type.\n *\n *\n * @example\n *\n * In an application registration file you can declare the model registration as follows:\n *\n * **registration.ts**\n * ```typescript\n * import { Assembly } from \"@kosdev-code/kos-dispense-sdk\";\n * ...\n * import { ExtensionManager, IKosRegistry } from \"@kosdev-code/kos-ui-sdk\";\n * export const kosModels: IKosRegistry[\"models\"] = {\n * ...Assembly.registration,\n * };\n * ```\n *\n * ## registration.singleton\n * The assembly model is a singleton model. This means that each time the factory function the same instance of the model will be returned.\n * */\nexport const Assembly: Readonly<\n SingletonKosModelRegistrationBean<AssemblyModel, AssemblyOptions>\n> = {\n registration: {\n [MODEL_TYPE]: {\n class: AssemblyModelImpl,\n singleton: true,\n },\n },\n type: MODEL_TYPE,\n predicate: isKosModel(MODEL_TYPE),\n factory: Kos.Singleton.create<AssemblyModel, AssemblyOptions>(MODEL_TYPE),\n};\n","import {\n Kos,\n isKosModel,\n kosModel,\n kosParentAware,\n type KosContextLogger,\n type KosCreationContext,\n type KosModelRegistrationBean,\n} from \"@kosdev-code/kos-ui-sdk\";\nimport { DispenseModelType } from \"../../constants\";\nimport type { AvailabilityModel, AvailabilityOptions } from \"./types\";\n\nconst MODEL_TYPE = DispenseModelType.Availability;\n@kosParentAware()\n@kosModel(MODEL_TYPE)\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nclass AvailabilityModelImpl<\n T extends object = any,\n P extends Record<string, any> = Record<string, any>\n> implements AvailabilityModel\n{\n id: string;\n data!: T;\n properties!: P;\n available!: boolean;\n visible!: boolean;\n groupId!: string;\n rawId!: string;\n altId!: string;\n type!: string;\n note?: string;\n taggedIds: string[];\n parentId?: string;\n logger: KosContextLogger;\n constructor(\n modelId: string,\n options: AvailabilityOptions<T, P>,\n context: KosCreationContext\n ) {\n this.id = modelId;\n this.taggedIds = options.taggedIds || [];\n this.logger = context.logger;\n this.available = options.available;\n this.visible = options.visible;\n this.groupId = options.groupId;\n this.rawId = options.rawId;\n this.altId = options.altId;\n this.type = options.type;\n this.parentId = options.kosParentId;\n this.data = options.data;\n this.note = options.note;\n this.properties = options.properties || ({} as P);\n }\n\n updateModel(options: AvailabilityOptions): void {\n this.taggedIds = options.taggedIds || [];\n this.available = options.available;\n this.visible = options.visible;\n this.groupId = options.groupId;\n this.rawId = options.rawId;\n this.altId = options.altId;\n this.type = options.type;\n this.data = options.data;\n }\n\n updateAvailability(available: boolean): void {\n this.available = available;\n }\n\n // -------------------LIFECYCLE----------------------------\n\n // -------------------ENTITY----------------------------\n}\n\n/**\n * # Availability\n *\n * The registration bean includes convenience methods for creating and working with AvailabilityModel instances.\n *\n * ## type\n * The type property is a string that identifies the model type.\n * The type is used to identify the model type in the model registry and to narrow down the model type in type predicates. It's most frequently\n * used when declaring dependencies on models.\n *\n * @example\n * ```typescript\n *\n * @kosDependency({modelType: Availability.type, id: \"beverageId\"})\n * private beverageModel: AvailabilityModel;\n * ```\n *\n * ## factory\n *\n * The factory method creates a factory function that can be used to create new AvailabilityModel instances.\n *\n * The factory function is a curried function that takes the model id as the first argument and the options as the second argument.\n *\n * If a model with the specified id already exists, the factory function will return the existing model. The options will be ignored\n * in this case and the existing model will be returned in its current state.\n *\n * @example\n *\n * ```typescript\n * const cherryFlavor = Availability.factory(\"beverageId\")({\n * groupId: \"flavor\",\n * rawId: \"cherry\",\n * altId: \"cherry\",\n * available: true,\n * visible: true,\n * // this data is added via extension point\n * data: {\n * name: \"Cherry\",\n * description: \"Cherry flavor\",\n * },\n * });\n * ```\n *\n * @param predicate\n *\n * [Typescript type predicate](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates) function that will identify and narrow down a model to a AvailabilityModel.\n *\n * @example\n * ```typescript\n *\n * const model: IKosDataModel = ...; // some model\n *\n * if (Availability.predicate(model)) {\n * // if the function evaluates to true, the model is narrowed down to AvailabilityModel\n * // and the compiler will know that the model has the AvailabilityModel interface\n * model.updateAvailability(false);\n * }\n * ```\n *\n * ## registration\n *\n * The registration property is an object that can be used to simplify registration of the model with the model registry. The registration object\n * can be spread into the model registration and provides all of the required information to register the model implementation class against the model type.\n *\n *\n * @example\n *\n * In an application registration file you can declare the model registration as follows:\n *\n * **registration.ts**\n * ```typescript\n * import { Availability } from \"@kosdev-code/kos-dispense-sdk\";\n * ...\n * import { ExtensionManager, IKosRegistry } from \"@kosdev-code/kos-ui-sdk\";\n * export const kosModels: IKosRegistry[\"models\"] = {\n * ...Availability.registration,\n * };\n * ```\n *\n * ## registration.singleton\n *\n * The beverage model is not a singleton model. This means that each time the factory function is called with a unique ID, a new model instance will be created.\n * If the factory function is called with an ID that already exists, the existing model will be returned.\n * */\nexport const Availability: Readonly<\n KosModelRegistrationBean<AvailabilityModel, AvailabilityOptions>\n> = {\n registration: {\n [MODEL_TYPE]: {\n class: AvailabilityModelImpl,\n\n singleton: false,\n },\n },\n\n type: MODEL_TYPE,\n predicate: isKosModel(MODEL_TYPE),\n\n factory: Kos.Factory.create<AvailabilityModel, AvailabilityOptions>(\n MODEL_TYPE\n ),\n};\n","import {\n FutureManager,\n ServiceFactory,\n resolveServiceUrl,\n} from \"@kosdev-code/kos-ui-sdk\";\nconst { URL } = resolveServiceUrl(\"NOZZLE_SERVICE\");\nconst { postModel, deleteModel, getOne } = ServiceFactory.build({\n basePath: `${URL}/api/nozzle`,\n});\n\n/**\n * An individual availability node for a nozzle.\n * */\nexport interface BeverageResponse<\n Properties extends Record<string, any> = Record<string, any>\n> {\n /**\n * Is the node available for based on the beverage graph.\n * */\n available: boolean;\n /**\n * an alternate id for the node. Typically used in cases where there are multiple nozzles where\n * the same beverage could be available. This id will represent the common id for the beverage without\n * the nozzle specific id.\n * */\n altId: string;\n /**\n * Is the item visible. This is typically used to hide items that are not available.\n * */\n visible: boolean;\n\n /**\n * The id of the availability node.\n * */\n id: string;\n\n type: string;\n taggedIds?: string[];\n note?: string;\n properties?: Properties;\n}\n\n/**\n * The response from the availability endpoint.\n * */\nexport interface AvailabilityResponse {\n /**\n * Indicates if the availability requires a full calculation of the availability nodes or just a\n * delta calculation.\n * */\n rebuild: boolean;\n\n /**\n * The availability groups for the nozzle.\n * */\n groups: {\n /**\n * the built-in beverages group\n * */\n beverages: BeverageResponse[];\n /**\n * the built-in flavors group\n * */\n flavors: BeverageResponse[];\n\n /**\n * the built-in brands group\n * */\n brands: BeverageResponse[];\n\n /**\n * Additional named groups that are defined by the dispenser.\n * */\n [k: string]: BeverageResponse[];\n };\n}\n\n/**\n *\n * Initiates a pour for the specified nozzle.\n *\n * Uses the KOS endpoint [POST] `${URL}/api/ext/dispense/nozzle/${nozzleId}/pipeline/beverage/pour`\n *\n * @param nozzleId - the nozzle id to pour from.\n * @param tracker - the tracker to use for the pour. It will be returned in the future to allow consumers\n * to track the pour.\n * @category Service\n *\n * @example\n * ```typescript\n * import { NozzleServices } from \"@kosdev-code/kos-dispense-sdk\";\n * ...\n *\n * await NozzleServices.pourPourable(\"nozzle-1\", \"my-tracker\");\n * ```\n * @see {@link FutureManager.initiateFuture}\n * @returns - a Future that encapsulates the pour including its status and progress.\n **/\nexport const pourPourable = async (nozzleId: string, tracker: string) => {\n const response = await postModel<any>({\n model: {},\n urlOverride: `${URL}/api/ext/dispense/nozzle/${nozzleId}/pipeline/beverage/pour`,\n ordered: true,\n tracker,\n });\n if (response?.data) {\n FutureManager.initiateFuture(response.data);\n }\n return response;\n};\n\n/**\n *\n * Initiates a fixed named pour for the specified nozzle.\n *\n * Typically used for cases where a named cup size is to be poured where the volume of the pour is\n * dictated by the name.\n *\n *\n * Uses the KOS endpoint [POST] `${URL}/api/ext/dispense/nozzle/${nozzleId}/pipeline/beverage/fixed/${name}`\n *\n * @param name - name of the fixed pour volume.\n * @param nozzleId - the nozzle id to pour from.\n * @param tracker - the tracker to use for the pour. It will be returned in the future to allow consumers\n * to track the pour.\n * @category Service\n *\n * @example\n * ```typescript\n * import { NozzleServices } from \"@kosdev-code/kos-dispense-sdk\";\n * ...\n *\n * await NozzleServices.pourPourable(\"nozzle-1\", \"my-tracker\");\n * ```\n * @see {@link FutureManager.initiateFuture}\n * @returns - a Future that encapsulates the pour including its status and progress.\n **/\nexport const pourNamedPourable = async (\n name: string,\n nozzleId: string,\n tracker: string\n) => {\n const response = await postModel<any>({\n model: {},\n urlOverride: `${URL}/api/ext/dispense/nozzle/${nozzleId}/pipeline/beverage/fixed/${name}`,\n ordered: true,\n tracker,\n });\n if (response?.data) {\n FutureManager.initiateFuture(response.data);\n }\n return response;\n};\n\n/**\n * Retrieves the availability nodes for a specified nozzle.\n *\n * Uses the KOS endpoint [GET] `${URL}/api/ext/dispense/nozzle/${nozzleId}/pipeline/beverage/availability`\n *\n * @param nozzleId - the nozzle id to retrieve availability for.\n * @returns - the availability nodes for the specified nozzle.\n * @category Service\n *\n * @example\n * ```typescript\n * import { NozzleServices } from \"@kosdev-code/kos-dispense-sdk\";\n * ...\n *\n * const availability = await NozzleServices.getAvailability(\"nozzle-1\");\n * if (availability?.status !== 200) {\n * throw new Error(\"Failed to load nozzle availability\");\n * }\n * ```\n */\nexport const getAvailability = async (urlPrefix: string) => {\n const response = await getOne<AvailabilityResponse>({\n urlOverride: `${URL}${urlPrefix}/pipeline/beverage/availability`,\n });\n return response;\n};\n\n/**\n * Invokes the endpoint to select a pourable for the specified nozzle.\n *\n * Uses the KOS endpoint [POST] `${URL}/api/ext/dispense/nozzle/${nozzleId}/pipeline/beverage/select`\n *\n *\n * @param nozzleId - the nozzle id to select a pourable for.\n * @param payload - the payload to send to the endpoint. The shape of the payload is determined by the\n * {@link ExtensionType.SelectedPourableMapper} extension.\n * @category Service\n * @see {@link ExtensionType.SelectedPourableMapper}\n * @returns - an emtpy response.\n *\n * @example\n * ```typescript\n * import { NozzleServices } from \"@kosdev-code/kos-dispense-sdk\";\n * ...\n * try {\n * const response = await NozzleServices.selectPourable(\"nozzle-1\", {\n * beverage: \"beverage-1\",\n * additional: [\"flavor-1\"],\n * });\n * if (response?.status !== 200) {\n * throw new Error(\"Failed to select pourable\");\n * }\n * } catch (e) {\n * console.error(e);\n * }\n * ```\n * */\nexport const selectPourable = async (nozzleId: string, payload: object) => {\n const response = await postModel({\n model: payload,\n urlOverride: `${URL}/api/ext/dispense/nozzle/${nozzleId}/pipeline/beverage/select`,\n });\n return response;\n};\n\n/**\n * Invokes the endpoint to clear the selected pourable for the specified nozzle.\n * Uses the KOS endpoint [DELETE] `${URL}/api/ext/dispense/nozzle/${nozzleId}/pipeline/beverage/select`\n *\n * @param nozzleId - the nozzle id to clear the selected pourable for.\n * @category Service\n * @returns - an emtpy response.\n * @example\n * ```typescript\n * import { NozzleServices } from \"@kosdev-code/kos-dispense-sdk\";\n * ...\n * try {\n * const response = await NozzleServices.clearPourable(\"nozzle-1\");\n * if (response?.status !== 200) {\n * throw new Error(\"Failed to clear pourable\");\n * }\n * } catch (e) {\n * console.error(e);\n * }\n * ```\n * */\nexport const clearPourable = async (nozzleId: string) => {\n const response = await deleteModel({\n id: nozzleId,\n urlOverride: `${URL}/api/ext/dispense/nozzle/${nozzleId}/pipeline/beverage/select`,\n });\n\n return response;\n};\n","import {\n EventBus,\n ExtensionManager,\n Kos,\n KosContextManager,\n KosModelContainer,\n MultipleFutureHandler,\n arraysEqual,\n createPropKey,\n destroyKosModel,\n getAllKosCompanionModels,\n isKosModel,\n kosAction,\n kosChild,\n kosFuture,\n kosModel,\n kosTopicHandler,\n type FutureAwareContainer,\n type FutureContainer,\n type IFutureModel,\n type IKosDataModel,\n type IKosModelContainer,\n type IKosModelLogger,\n type KosContext,\n type KosContextLogger,\n type KosCreationContext,\n type KosModelRegistrationBean,\n type PublicModelInterface,\n} from \"@kosdev-code/kos-ui-sdk\";\nimport { DispenseModelType, ExtensionType } from \"../../constants\";\nimport {\n Availability,\n type AvailabilityModel,\n type AvailabilityOptions,\n} from \"../availability\";\n\nimport { PourState } from \"../types/pouring\";\nimport {\n clearPourable,\n getAvailability,\n pourNamedPourable,\n pourPourable,\n selectPourable,\n type AvailabilityResponse,\n} from \"./services\";\nimport type {\n NozzleOptions,\n PourAware,\n PourCancelEvent,\n PourProgressEvent,\n PourStartEvent,\n SelectedPourable,\n} from \"./types\";\n\nconst MODEL_TYPE = DispenseModelType.Nozzle;\n\nconst PROP_BEVERAGE_TOPIC_PREFIX = createPropKey<NozzleModel>(\n \"beverageTopicPrefix\"\n);\n\nconst isPourAware = (model: any): model is PourAware =>\n model.onPourStart !== undefined &&\n model.onPourCancel !== undefined &&\n model.onPourProgress !== undefined;\n\nexport const TOPIC_NOZZLE_POUR_STARTED = \"/kos/nozzle/pour/started\";\nexport const TOPIC_NOZZLE_POUR_PROGRESS = \"/kos/nozzle/pour/progress\";\nexport const TOPIC_NOZZLE_POUR_CANCEL = \"/kos/nozzle/pour/cancel\";\n/**\n *\n */\n@kosModel(MODEL_TYPE)\nclass NozzleModelImpl\n implements IKosModelLogger, IKosDataModel, FutureContainer\n{\n /** the unique identifier for this nozzle.*/\n id: string;\n path: string;\n logger: KosContextLogger;\n name: string;\n private _selectedBeverage?: AvailabilityModel;\n private _selectedBrand?: AvailabilityModel;\n private _additionalItems?: AvailabilityModel[];\n @kosChild private _availabilityItems: IKosModelContainer<AvailabilityModel>;\n futureHandler: FutureAwareContainer;\n currentState: PourState = PourState.IDLE;\n\n beverageTopicPrefix: string;\n topicPrefix: string;\n urlPrefix: string;\n\n /**\n * The availability nodes that can be dispensed from this nozzle.\n * This is a subset of the availability for the entire dispenser\n * and is determined by the nodes associated with a nozzle.\n */\n get beverages() {\n return this._availabilityItems.getIndexByKey(\"byGroup\", \"beverages\");\n }\n\n /**\n * The availability nodes that have been grouped into the \"brands\" group.\n *\n */\n get brands() {\n return this._availabilityItems.getIndexByKey(\"byGroup\", \"brands\");\n }\n\n get visibleBrands() {\n return this.brands.filter((brand) => brand.visible);\n }\n\n get visibleBeverages() {\n return this.beverages.filter((beverage) => beverage.visible);\n }\n\n /**\n * A derived value that indicates if the nozzle is currently pouring a beverage.\n * @readonly\n */\n get isPouring() {\n return (\n !!(\n this.futureHandler.getFuture() &&\n !this.futureHandler.getFuture()?.endState\n ) ||\n this.currentState === PourState.POUR_STARTING ||\n this.currentState === PourState.POURING ||\n this.currentState === PourState.POUR_CANCELING\n );\n }\n\n /**\n * A derived value that indicates if the nozzle is currently available to pour a beverage.\n *\n * This will generally be determined by whether there is a currently selected pourable AND\n * the nozzle is not currently pouring.\n *\n * The value is observable and will change when the selected pourable changes or the nozzle\n * starts or stops pouring.\n * @readonly\n * */\n get canPour() {\n return (\n !!this._selectedBeverage &&\n this._selectedBeverage.available &&\n this.currentState === PourState.IDLE\n );\n }\n\n /**\n * The selected pourable for this nozzle. Its shape is determined by the results of the\n * {@link ExtensionType.SelectedPourableMapper} extension.\n * @readonly\n *\n * */\n get selectedPourable() {\n return {\n beverage: this._selectedBeverage,\n additional: this._additionalItems,\n };\n }\n\n get future() {\n return this.futureHandler.getFuture();\n }\n\n get pourProgress() {\n return this.future?.progress ?? 0;\n }\n\n constructor(\n modelId: string,\n options: NozzleOptions,\n context: KosCreationContext\n ) {\n this.id = modelId;\n this.path = options.path;\n this.name = options.name;\n this.beverageTopicPrefix = options.beverageTopicPrefix;\n this.topicPrefix = options.topicPrefix;\n this.urlPrefix = options.urlPrefix;\n this._selectedBeverage = undefined;\n this._selectedBrand = undefined;\n this._additionalItems = [];\n this.futureHandler = new MultipleFutureHandler(this);\n this._availabilityItems = new KosModelContainer<AvailabilityModel>({\n indexMap: {\n byGroup: \"groupId\",\n byParent: \"parentId\",\n },\n parentId: modelId,\n });\n\n this.logger = context.logger;\n }\n\n updateModel(): void {\n // Update model properties here.\n }\n\n // -------------------LIFECYCLE----------------------------\n\n setSelectedBrand(brand?: AvailabilityModel) {\n this._selectedBrand = brand;\n this._selectedBeverage = undefined;\n }\n\n get selectedBrand() {\n return this._selectedBrand;\n }\n /**\n * Set the values used to determine the selected pourable for this nozzle.\n *\n * @param pourable The pourable to set.\n * @param pourable.beverage The beverage selected.\n * @param pourable.additional The additional items such as flavors or other items that could be incorporated\n * into the pourable.\n * */\n async setSelectedPourable({\n beverage,\n additional,\n context,\n }: SelectedPourable) {\n if (!beverage) {\n const response = await clearPourable(this.name);\n if (response?.status !== 200) {\n throw new Error(\"Failed to clear pourable\");\n }\n this._selectedBeverage = undefined;\n return;\n }\n if (\n beverage === this._selectedBeverage &&\n arraysEqual(this._additionalItems, additional)\n ) {\n this.logger.info(\"No change in selected pourable\");\n return;\n }\n this._selectedBeverage = beverage;\n this._additionalItems = additional;\n let selectedPayload = await ExtensionManager.dataMapper.executeMapper(\n ExtensionType.SelectedPourableMapper,\n {\n beverage,\n additional,\n context,\n }\n );\n\n const defaultPayload = {\n bevId: beverage.rawId,\n };\n if (!selectedPayload || Object.keys(selectedPayload).length === 0) {\n this.logger.info(\n `No selected pourable mapper defined, using the default payload ${defaultPayload}`\n );\n selectedPayload = defaultPayload;\n }\n const payload = selectedPayload ?? defaultPayload;\n\n const response = await selectPourable(this.name, payload);\n if (response?.status !== 200) {\n throw new Error(\"Failed to select pourable\");\n }\n }\n\n /**\n * Utility method that will return the availability nodes that belong to the specified\n * group as defined in the dispenser beverage graph. For example, a dispenser\n * implementation may group availability nodes by Brand, Beverage, or Flavors\n *\n * @param groupId The group to filter by.\n * @returns The availability nodes that are available to be dispensed from this nozzle\n * and are in the specified group.\n * */\n getGroupAvailabilityItems<D extends object = any>(groupId: string) {\n return this._availabilityItems.getIndexByKey(\n \"byGroup\",\n groupId\n ) as AvailabilityModel<D>[];\n }\n\n /**\n * Utility method that will return the availability nodes that are tagged with the specified parent id.\n *\n * This is useful when brandsets use the taggedIds property to associate nodes with a parent node. For example,\n * when organizing a brandset into brands and beverages, the brand nodes will be tagged with the beverage nodes.\n *\n * @param parentId - The parent id to filter by.\n * @returns the availability nodes that are tagged with the specified parent id.\n */\n getAvailabilityByParent<D extends object = any>(parentId: string) {\n return this._availabilityItems.getIndexByKey(\n \"byParent\",\n parentId\n ) as AvailabilityModel<D>[];\n }\n\n private updateIfCurrent(currentState: PourState, nextState: PourState) {\n if (this.currentState === currentState) {\n kosAction(() => {\n this.currentState = nextState;\n });\n }\n }\n\n onFutureUpdate(future: IFutureModel<any>) {\n const companions = getAllKosCompanionModels(this);\n companions.forEach((model) => {\n if (isPourAware(model)) {\n model.onPourProgress(future);\n }\n });\n\n const evt: PourProgressEvent = {\n nozzleId: this.id,\n progress: future.progress,\n status: future.status,\n clientData: future.clientData,\n futureId: future.futureId,\n remainingTimeMs: future.remainingTimeMs,\n endState: future.endState,\n reason: future.reason,\n timeRemaining: future.timeRemaining,\n };\n EventBus.publish(TOPIC_NOZZLE_POUR_PROGRESS, evt);\n if (future.endState) {\n kosAction(() => {\n this.currentState = PourState.IDLE;\n });\n }\n }\n\n /**\n * An action that will initiate a pour for this nozzle.\n *\n * The invocation of this action will result in a Future being returned that will\n * provide the status of the pour and return any errors that may occur.\n *\n * @see {@link kosFuture}\n * */\n @kosFuture()\n public async pour(tracker?: string) {\n try {\n if (this.currentState === PourState.IDLE) {\n this.updateIfCurrent(PourState.IDLE, PourState.POUR_STARTING);\n if (!tracker) {\n throw new Error(\"No tracker provided\");\n }\n\n const result = await pourPourable(this.name, tracker);\n this.updateIfCurrent(PourState.POUR_STARTING, PourState.POURING);\n getAllKosCompanionModels(this).forEach((model) => {\n if (isPourAware(model)) {\n model.onPourStart?.();\n }\n });\n\n const evt: PourStartEvent = {\n nozzleId: this.id,\n type: \"free\",\n };\n EventBus.publish(TOPIC_NOZZLE_POUR_STARTED, evt);\n if (result?.data?.endState) {\n this.updateIfCurrent(PourState.POURING, PourState.IDLE);\n const evt: PourCancelEvent = {\n nozzleId: this.id,\n };\n EventBus.publish(TOPIC_NOZZLE_POUR_CANCEL, evt);\n }\n return result as unknown as Promise<void>;\n } else {\n throw new Error(`Cannot pour in state ${this.currentState}`);\n }\n } catch (e) {\n this.logger.error(e);\n this.currentState = PourState.IDLE;\n throw e;\n }\n }\n\n /**\n * An action that will initiate a fixed volume pour for this nozzle using the\n * specified pourable volume name.\n *\n * The invocation of this action will result in a Future being returned that will\n * provide the status of the pour and return any errors that may occur.\n *\n * @see {@link kosFuture}\n * */\n @kosFuture()\n public async fixedPour(name: string, tracker?: string) {\n try {\n if (this.currentState === PourState.IDLE) {\n this.currentState = PourState.POUR_STARTING;\n if (!tracker) {\n throw new Error(\"No tracker provided\");\n }\n\n const result = await pourNamedPourable(name, this.name, tracker);\n if (this.currentState === PourState.POUR_STARTING) {\n kosAction(() => {\n this.currentState = PourState.POURING;\n });\n }\n\n getAllKosCompanionModels(this).forEach((model) => {\n if (isPourAware(model)) {\n model.onPourStart?.();\n }\n });\n const evt: PourStartEvent = {\n nozzleId: this.id,\n type: \"fixed\",\n };\n EventBus.publish(TOPIC_NOZZLE_POUR_STARTED, evt);\n if (result?.data?.endState) {\n this.updateIfCurrent(PourState.POURING, PourState.IDLE);\n const evt: PourCancelEvent = {\n nozzleId: this.id,\n };\n EventBus.publish(TOPIC_NOZZLE_POUR_CANCEL, evt);\n }\n return result as unknown as Promise<void>;\n } else {\n throw new Error(`Cannot pour in state ${this.currentState}`);\n }\n } catch (e) {\n this.logger.error(e);\n this.currentState = PourState.IDLE;\n throw e;\n }\n }\n\n /**\n * An action that will cancel a pour for this nozzle.\n * */\n public async cancelPour() {\n if (\n this.currentState === PourState.POURING ||\n this.currentState === PourState.POUR_STARTING\n ) {\n this.currentState = PourState.POUR_CANCELING;\n await this.futureHandler.getFuture()?.cancelFuture();\n kosAction(() => {\n this.currentState = PourState.IDLE;\n });\n getAllKosCompanionModels(this).forEach((model) => {\n if (isPourAware(model)) {\n model.onPourCancel?.();\n }\n });\n const evt: PourCancelEvent = {\n nozzleId: this.id,\n };\n EventBus.publish(TOPIC_NOZZLE_POUR_CANCEL, evt);\n } else {\n this.logger.warn(`Cannot cancel pour in state ${this.currentState}`);\n }\n }\n\n private updateGroupMembers() {\n this._availabilityItems.data.forEach((item) => {\n const taggedIds = item.taggedIds || [];\n taggedIds.forEach((taggedId) => {\n const childItem = this._availabilityItems.data.find(\n (beverage) => beverage.rawId === taggedId\n );\n if (childItem && childItem.parentId !== item.id) {\n childItem.parentId = item.id;\n this._availabilityItems.updateModel(childItem);\n }\n });\n });\n }\n\n /** @internal */\n async load(context?: KosContext): Promise<void> {\n this.logger.debug(`loading nozzle ${this.id}`);\n\n const availability = await getAvailability(this.urlPrefix);\n if (availability?.status !== 200) {\n throw new Error(\"Failed to load nozzle availability\");\n }\n\n const beverageContext = await ExtensionManager.loader.executeLoader(\n ExtensionType.AvailabilityLoader,\n {}\n );\n\n context?.set(ExtensionType.AvailabilityLoader, beverageContext);\n context?.set(Nozzle.type, this);\n for (const group of Object.keys(availability.data?.groups) || []) {\n for (const beverageData of availability.data?.groups[group] || []) {\n const extensionData = await ExtensionManager.dataMapper.executeMapper(\n ExtensionType.AvailabilityMapper,\n { ...beverageData, groupId: group },\n beverageContext\n );\n const beverageOptions: AvailabilityOptions = {\n ...beverageData,\n note: beverageData.note ?? undefined,\n kosParentId: this.id,\n rawId: beverageData.id,\n groupId: group,\n data: extensionData,\n properties: beverageData.properties || {},\n };\n const beverage = Availability.factory(\n `${this.id}-${group}-${beverageData.id}`\n )(beverageOptions);\n this._availabilityItems.addModel(beverage);\n }\n }\n\n this.updateGroupMembers();\n }\n\n @kosTopicHandler({\n topic: `${PROP_BEVERAGE_TOPIC_PREFIX}/availability`,\n websocket: true,\n })\n async updateAvailability(update: AvailabilityResponse) {\n const context = KosContextManager.getContext(this.id);\n const beverageContext =\n context?.get(ExtensionType.AvailabilityLoader) || {};\n if (update.rebuild) {\n for (const group of Object.keys(update?.groups) || []) {\n const deletedBeverages = this._availabilityItems\n .getIndexByKey(\"group\", group)\n .filter(\n (beverage) =>\n !update.groups[group].find(\n (b) => `${this.id}-${group}-${b.id}` === beverage.id\n )\n );\n\n deletedBeverages.forEach((beverage) => {\n this._availabilityItems.removeModel(beverage.id);\n destroyKosModel(beverage);\n });\n\n // add any new beverages\n for (const beverageData of update?.groups[group] || []) {\n const extensionData = await ExtensionManager.dataMapper.executeMapper(\n ExtensionType.AvailabilityMapper,\n { ...beverageData, groupId: group },\n beverageContext\n );\n const beverageOptions: AvailabilityOptions = {\n ...beverageData,\n note: beverageData.note ?? undefined,\n kosParentId: this.id,\n groupId: group,\n rawId: beverageData.id,\n data: extensionData,\n taggedIds: beverageData.taggedIds,\n properties: beverageData.properties || {},\n };\n const existing = this._availabilityItems.getModel(\n `${this.id}-${group}-${beverageData.id}`\n );\n if (existing) {\n existing.updateModel(beverageOptions);\n } else {\n const beverage = Availability.factory(\n `${this.id}-${group}-${beverageData.id}`\n )(beverageOptions);\n this._availabilityItems.addModel(beverage);\n }\n }\n }\n } else {\n for (const group of Object.keys(update?.groups) || []) {\n for (const beverageData of update?.groups[group] || []) {\n const extensionData = await ExtensionManager.dataMapper.executeMapper(\n ExtensionType.AvailabilityMapper,\n { ...beverageData, groupId: group },\n beverageContext\n );\n const beverageOptions: AvailabilityOptions = {\n ...beverageData,\n note: beverageData.note ?? undefined,\n kosParentId: this.id,\n groupId: group,\n rawId: beverageData.id,\n data: extensionData,\n type: beverageData.type,\n taggedIds: beverageData.taggedIds,\n properties: beverageData.properties || {},\n };\n const existing = this._availabilityItems.getModel(\n `${this.id}-${group}-${beverageData.id}`\n );\n if (existing) {\n existing.updateModel(beverageOptions);\n }\n }\n }\n }\n this.updateGroupMembers();\n }\n\n // -------------------ENTITY----------------------------\n}\n\n/**\n *\n * The NozzleModel provides the availability of pourables that are\n * associated with the nozzle.\n *\n * Its primary purpose is to provide a mechanism for selecting from available pourables and initiating a pour.\n *\n * It is possible for a dispenser to have multiple asymmetrical nozzles. For example, a dispenser may have\n * a nozzle that is used for dispensing a syrups and flavors and another that is just dispensing water.\n *\n * The NozzleModel is a {@link IKosDataModel} and is registered with the model registry using the {@link Nozzle} type.\n *\n *\n * @see {@link NozzleServices.getAvailability} - The availability service will retrieve the availability for the nozzle.\n *\n * ## Lifecycle\n *\n * ### Load\n *\n * During the `load` phase of the model lifecycle, the set of Availability nodes will be retrieved for the nozzle. The nodes will be indexed based on\n * the defined `groupId` for the node. The `groupId` is defined in the dispenser beverage graph and is used to group availability nodes.\n *\n * #### Extension Points\n *\n * The `load` lifecycle hook will first call into the {@link ExtensionType.AvailabilityLoader} extension point in order to establish the context\n * that will be used to populate the availability nodes.\n *\n * The `load` lifecycle hook will then call into the {@link ExtensionType.AvailabilityMapper} for each Availability node that is retrieved.\n * The extension point will be called the the Availability context data and the {@link NozzleServices.BeverageResponse} for the availability node.\n *\n *\n *\n * @see {@link Nozzle}\n *\n *\n *\n *\n * @category Model\n * @interface\n *\n\n */\nexport type NozzleModel = PublicModelInterface<NozzleModelImpl>;\n\n/**\n *\n *\n * # Nozzle\n *\n * The registration bean includes convenience methods for creating and working with NozzleModel instances.\n *\n * ## type\n * The type property is a string that identifies the model type.\n * The type is used to identify the model type in the model registry and to narrow down the model type in type predicates. It's most frequently\n * used when declaring dependencies on models.\n *\n * @example\n * ```typescript\n *\n * @kosDependency({modelType: Nozzle.type, id: \"nozzleId\"})\n * private nozzleModel: NozzleModel;\n * ```\n *\n *\n * ## factory\n *\n * The factory method creates a factory function that can be used to create new NozzleModel instances.\n *\n * The factory function is a curried function that takes the model id as the first argument and the options as the second argument.\n *\n * If a model with the specified id already exists, the factory function will return the existing model. The options will be ignored\n * in this case and the existing model will be returned in its current state.\n *\n * @example\n *\n * ```typescript\n * const model = Nozzle.factory(\"S1\")({\n * path: \"core.assemby.nozzle.nozzle1\",\n * });\n * ```\n *\n * ## predicate\n *\n * [Typescript type predicate](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates) function that will identify and narrow down a model to a NozzleModel.\n *\n * @example\n * ```typescript\n *\n * const model: IKosDataModel = ...; // some model\n *\n * if (Nozzle.predicate(model)) {\n * // if the function evaluates to true, the model is narrowed down to NozzleModel\n * // and the compiler will know that the model has the NozzleModel interface\n * model.pour();\n * }\n * ```\n *\n * ## registration\n *\n * The registration property is an object that can be used to simplify registration of the model with the model registry. The registration object\n * can be spread into the model registration and provides all of the required information to register the model implementation class against the model type.\n *\n *\n * @example\n *\n * In an application registration file you can declare the model registration as follows:\n *\n * **registration.ts**\n * ```typescript\n * import { Nozzle } from \"@kosdev-code/kos-dispense-sdk\";\n * ...\n * import { IKosRegistry } from \"@kosdev-code/kos-ui-sdk\";\n * export const kosModels: IKosRegistry[\"models\"] = {\n * ...Nozzle.registration,\n * };\n * ```\n *\n * ## registration.singleton\n *\n * The nozzle model is not a singleton model. This means that each time the factory function is called with a unique ID, a new model instance will be created.\n * If the factory function is called with an ID that already exists, the existing model will be returned.\n *\n * @category KOS Model Registration\n * */\nexport const Nozzle: Readonly<\n KosModelRegistrationBean<NozzleModel, NozzleOptions>\n> = {\n registration: {\n [MODEL_TYPE]: {\n class: NozzleModelImpl,\n singleton: false,\n },\n },\n type: MODEL_TYPE,\n predicate: isKosModel(MODEL_TYPE),\n factory: Kos.Factory.create<NozzleModel, NozzleOptions>(MODEL_TYPE),\n};\n","import type {\n IKosDataModel,\n IKosIdentifiable,\n IKosModelContainer,\n KosContextLogger,\n KosCreationContext,\n PublicModelInterface,\n} from \"@kosdev-code/kos-ui-sdk\";\nimport { KosModelContainer, kosChild, kosModel } from \"@kosdev-code/kos-ui-sdk\";\nimport { getAssembly } from \"../assembly/services\";\nimport { Nozzle, type NozzleModel } from \"../nozzle\";\nimport type { DeviceAssemblyOptions } from \"./types\";\n\nexport const MODEL_TYPE = \"device-assembly-model\";\n\nexport type DeviceAssemblyModel = PublicModelInterface<DeviceAssemblyModelImpl>;\n\n@kosModel(MODEL_TYPE)\nexport class DeviceAssemblyModelImpl\n implements IKosDataModel, IKosIdentifiable\n{\n id: string;\n @kosChild private deviceNozzles: IKosModelContainer<NozzleModel>;\n private logger: KosContextLogger;\n constructor(\n modelId: string,\n _options: DeviceAssemblyOptions,\n context: KosCreationContext\n ) {\n this.id = modelId;\n this.logger = context.logger;\n this.deviceNozzles = new KosModelContainer();\n }\n\n // -------------------LIFECYCLE----------------------------\n\n async init(): Promise<void> {\n this.logger.debug(`initializing device-assembly ${this.id}`);\n }\n\n getNozzle(path: string): NozzleModel | undefined {\n return this.deviceNozzles.getModel(path);\n }\n\n get nozzlePaths(): string[] {\n return this.deviceNozzles.data.map((nozzle) => nozzle.path);\n }\n\n async load(): Promise<void> {\n this.logger.debug(`loading device-assembly ${this.id}`);\n const result = await getAssembly();\n if (result?.status === 200) {\n const nozzles = result.data.assemblies\n .map((assembly) => assembly.nozzles ?? [])\n .flat();\n nozzles.forEach((nozzleData) => {\n const nozzleId = nozzleData.path;\n const beverageTopicPrefix =\n nozzleData.pipelines.find((pipeline) => pipeline.name === \"beverage\")\n ?.topicPrefix || \"\";\n\n const nozzle = Nozzle.factory(nozzleId)({\n path: nozzleData.path,\n name: nozzleData.name,\n urlPrefix: nozzleData.urlPrefix,\n topicPrefix: nozzleData.topicPrefix,\n beverageTopicPrefix: beverageTopicPrefix,\n });\n this.deviceNozzles.addModel(nozzle);\n });\n }\n }\n}\n","import { SingletonKosModelRegistrationFactory } from \"@kosdev-code/kos-ui-sdk\";\nimport type { DeviceAssemblyModel } from \"./device-assembly-model\";\nimport { DeviceAssemblyModelImpl, MODEL_TYPE } from \"./device-assembly-model\";\nimport type { DeviceAssemblyOptions } from \"./types\";\n\n/**\n * # DeviceAssembly\n *\n * The registration bean includes convenience methods for creating and working with DeviceAssemblyModel instances.\n *\n * ## type\n * The type property is a string that identifies the model type.\n * The type is used to identify the model type in the model registry and to narrow down the model type in type predicates. It's most frequently\n * used when declaring dependencies on models.\n *\n * @example\n * ```typescript\n *\n * @kosDependency({modelType: DeviceAssembly.type, id: \"deviceAssemblyId\"})\n * private deviceAssemblyModel: DeviceAssemblyModel;\n * ```\n *\n *\n * ## factory\n *\n * The factory method creates a factory function that can be used to create new DeviceAssemblyModel instances.\n *\n \n * As this is a singleton model, the factory function accepts the model options as its argument.\n *\n * If a model with the same model type already exists, the factory function will return the existing model. The options will be ignored\n * in this case and the existing model will be returned in its current state.\n *\n * @example\n * ```typescript\n * const model = DeviceAssembly.factory({\n * // Add option data\n * });\n * ```\n \n\n *\n * ## predicate\n *\n * [Typescript type predicate](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates) function that will identify and narrow down a model to a DeviceAssemblyModel.\n *\n * @example\n * ```typescript\n *\n * const model: IKosDataModel = ...; // some model\n *\n * if (DeviceAssembly.predicate(model)) {\n * // if the function evaluates to true, the model is narrowed down to DeviceAssemblyModel\n * // and the compiler will know that the model has the DeviceAssemblyModel interface\n * model.updateAvailability(false);\n * }\n * ```\n *\n * ## registration\n *\n * The registration property is an object that can be used to simplify registration of the model with the model registry. The registration object\n * can be spread into the model registration and provides all of the required information to register the model implementation class against the model type.\n *\n *\n * @example\n *\n * In an application registration file you can declare the model registration as follows:\n *\n * **registration.ts**\n * ```typescript\n * import { DeviceAssembly } from \"@kos-ui/project-models\";\n * import { KosModelRegistry } from \"@kosdev-code/kos-dispense-sdk\";\n *\n * import { initKosProvider } from \"@kosdev-code/kos-ui-sdk\";\n *\n * KosModelRegistry.dispense\n * .models()\n * .model(DeviceAssembly);\n * ```\n *\n * ## registration.singleton\n \n * The deviceAssembly model is a singleton model. This means that each time the factory function is called , the same instance will be returned.\n * If the model does not yet exist, it will be created passing in the provided options to initialize it.\n *\n * Singleton models don't require an ID as they will use the model type as their ID to guarantee uniqueness throughout the system.\n \n * */\nexport const DeviceAssembly = new SingletonKosModelRegistrationFactory<\n DeviceAssemblyModel,\n DeviceAssemblyOptions\n>({\n class: DeviceAssemblyModelImpl,\n type: MODEL_TYPE,\n});\n","import {\n FutureManager,\n ServiceFactory,\n resolveServiceUrl,\n} from \"@kosdev-code/kos-ui-sdk\";\nconst { URL } = resolveServiceUrl(\"GENERIC_POUR_SERVICE\");\nconst { postModel } = ServiceFactory.build({\n basePath: `${URL}/api/nozzle`,\n});\n\n/**\n *\n * Initiates a pour for a pour target on a given path.\n *\n\n *\n * @param path - the API path to pour from, this will be passed in from the model\n * @param tracker - the tracker to use for the pour. It will be returned in the future to allow consumers\n * to track the pour\n * @category Service\n *\n * @see {@link FutureManager.initiateFuture}\n * @returns - a Future that encapsulates the pour including its status and progress.\n **/\nexport const pourOnTarget = async (path: string, tracker: string) => {\n const response = await postModel<any>({\n model: {},\n urlOverride: `${URL}${path}`,\n ordered: true,\n tracker,\n });\n if (response?.data) {\n FutureManager.initiateFuture(response.data);\n }\n return response;\n};\n","import {\n EventBus,\n FutureAwareContainer,\n FutureContainer,\n FutureEndState,\n FutureHandler,\n IFutureModel,\n IKosDataModel,\n KosContextLogger,\n KosCreationContext,\n PublicModelInterface,\n getAllKosCompanionModels,\n kosAction,\n kosFuture,\n kosModel,\n} from \"@kosdev-code/kos-ui-sdk\";\n\nimport type { PourStrategyAware } from \"../../../ui/hooks/utils/pour-strategy\";\nimport type { PourAware } from \"../nozzle/types\";\nimport { PourState } from \"../types\";\nimport { pourOnTarget } from \"./services\";\nimport type { GenericPourOptions } from \"./types\";\n\nexport const MODEL_TYPE = \"generic-pour-model\";\n\nexport type GenericPourModel = PublicModelInterface<GenericPourModelImpl>;\n\nexport const TOPIC_GENERIC_POUR_STARTED = \"/kos/generic/pour/started\";\nexport const TOPIC_GENERIC_POUR_PROGRESS = \"/kos/generic/pour/progress\";\nexport const TOPIC_GENERIC_POUR_CANCEL = \"/kos/generic/pour/cancel\";\n\ninterface BasePourEvent {\n pourTarget: string;\n}\n\ninterface PourStartEvent extends BasePourEvent {\n type: string;\n}\n\ntype PourCancelEvent = BasePourEvent;\n\ninterface PourProgressEvent<T extends Record<string, any> = Record<string, any>>\n extends BasePourEvent {\n remainingTimeMs: number;\n endState?: FutureEndState;\n reason?: string;\n clientData?: T;\n futureId: string;\n status: string;\n timeRemaining: string;\n progress: number;\n}\nconst isPourAware = (model: any): model is PourAware =>\n model.onPourStart !== undefined &&\n model.onPourCancel !== undefined &&\n model.onPourProgress !== undefined;\n@kosModel(MODEL_TYPE)\nexport class GenericPourModelImpl\n implements IKosDataModel, PourStrategyAware, FutureContainer\n{\n id: string;\n currentState: PourState = PourState.IDLE;\n servicePathFactory: (selectedId: string) => string;\n pourType: string;\n private logger: KosContextLogger;\n futureHandler: FutureAwareContainer;\n selectedId?: string;\n\n constructor(\n modelId: string,\n options: GenericPourOptions,\n context: KosCreationContext\n ) {\n this.id = modelId;\n this.logger = context.logger;\n this.futureHandler = new FutureHandler(this);\n this.servicePathFactory = options.servicePathFactory;\n this.pourType = options.pourType || \"free\"; // Default to 'free' pour type if not specified\n this.selectedId = options.selectedId;\n }\n\n get servicePath() {\n if (!this.selectedId) {\n return \"\";\n }\n return this.servicePathFactory(this.selectedId);\n }\n /**\n * An action that will initiate a pour for this nozzle.\n *\n * The invocation of this action will result in a Future being returned that will\n * provide the status of the pour and return any errors that may occur.\n *\n * @see {@link kosFuture}\n * */\n @kosFuture()\n public async pour(tracker?: string) {\n try {\n if (this.currentState === PourState.IDLE) {\n this.updateIfCurrent(PourState.IDLE, PourState.POUR_STARTING);\n if (!tracker) {\n throw new Error(\"No tracker provided\");\n }\n\n const result = await pourOnTarget(this.servicePath, tracker);\n this.updateIfCurrent(PourState.POUR_STARTING, PourState.POURING);\n getAllKosCompanionModels(this).forEach((model) => {\n if (isPourAware(model)) {\n model.onPourStart?.();\n }\n });\n\n const evt: PourStartEvent = {\n pourTarget: this.id,\n type: this.pourType,\n };\n EventBus.publish(TOPIC_GENERIC_POUR_STARTED, evt);\n\n // if the pour was successful or immediately ended, update the state\n if (result?.data?.endState) {\n this.updateIfCurrent(PourState.POURING, PourState.IDLE);\n const evt: PourCancelEvent = {\n pourTarget: this.id,\n };\n EventBus.publish(TOPIC_GENERIC_POUR_CANCEL, evt);\n }\n return result as unknown as Promise<void>;\n } else {\n throw new Error(`Cannot pour in state ${this.currentState}`);\n }\n } catch (e) {\n this.logger.error(e);\n this.currentState = PourState.IDLE;\n throw e;\n }\n }\n\n public async cancelPour() {\n if (\n this.currentState === PourState.POURING ||\n this.currentState === PourState.POUR_STARTING\n ) {\n this.currentState = PourState.POUR_CANCELING;\n await this.futureHandler.getFuture()?.cancelFuture();\n kosAction(() => {\n this.currentState = PourState.IDLE;\n });\n getAllKosCompanionModels(this).forEach((model) => {\n if (isPourAware(model)) {\n model.onPourCancel?.();\n }\n });\n const evt: PourCancelEvent = {\n pourTarget: this.id,\n };\n EventBus.publish(TOPIC_GENERIC_POUR_CANCEL, evt);\n }\n if (this.currentState === PourState.IDLE) {\n this.logger.info(\"Pour already idle, nothing to cancel.\");\n } else {\n this.logger.warn(`Cannot cancel pour in state ${this.currentState}`);\n }\n }\n\n private updateIfCurrent(currentState: PourState, nextState: PourState) {\n if (this.currentState === currentState) {\n kosAction(() => {\n this.currentState = nextState;\n });\n }\n }\n\n /**\n * A derived value that indicates if the nozzle is currently pouring a beverage.\n * @readonly\n */\n get isPouring() {\n return (\n !!(\n this.futureHandler.getFuture() &&\n !this.futureHandler.getFuture()?.endState\n ) ||\n this.currentState === PourState.POUR_STARTING ||\n this.currentState === PourState.POURING ||\n this.currentState === PourState.POUR_CANCELING\n );\n }\n\n /**\n * A derived value that indicates if the pour target is currently available to pour a beverage.\n *\n * Generally this means that the pour target is currently idle and not in the process of pouring, initiating a pour, or canceling a pour.\n * The value is observable and will change when the selected pourable changes or the pour target\n * starts or stops pouring.\n * @readonly\n * */\n get canPour() {\n return this.currentState === PourState.IDLE;\n }\n\n get future() {\n return this.futureHandler.getFuture();\n }\n\n get pourProgress() {\n return this.future?.progress ?? 0;\n }\n\n onFutureUpdate(future: IFutureModel<any>) {\n getAllKosCompanionModels(this).forEach((model) => {\n if (isPourAware(model)) {\n model.onPourProgress(future);\n }\n });\n\n const evt: PourProgressEvent = {\n pourTarget: this.id,\n progress: future.progress,\n status: future.status,\n clientData: future.clientData,\n futureId: future.futureId,\n remainingTimeMs: future.remainingTimeMs,\n endState: future.endState,\n reason: future.reason,\n timeRemaining: future.timeRemaining,\n };\n EventBus.publish(TOPIC_GENERIC_POUR_PROGRESS, evt);\n\n if (future.endState) {\n kosAction(() => {\n this.currentState = PourState.IDLE;\n });\n }\n }\n\n // -------------------LIFECYCLE----------------------------\n\n async init(): Promise<void> {\n this.logger.debug(`initializing generic-pour ${this.id}`);\n }\n\n async load(): Promise<void> {\n this.logger.debug(`loading generic-pour ${this.id}`);\n }\n}\n","import { KosModelRegistrationFactory } from \"@kosdev-code/kos-ui-sdk\";\nimport type { GenericPourOptions } from \"./types\";\nimport { GenericPourModelImpl, MODEL_TYPE } from \"./generic-pour-model\";\nimport type { GenericPourModel } from \"./generic-pour-model\";\n\n/**\n * # GenericPour\n *\n * The registration bean includes convenience methods for creating and working with GenericPourModel instances.\n *\n * ## type\n * The type property is a string that identifies the model type.\n * The type is used to identify the model type in the model registry and to narrow down the model type in type predicates. It's most frequently\n * used when declaring dependencies on models.\n *\n * @example\n * ```typescript\n *\n * @kosDependency({modelType: GenericPour.type, id: \"genericPourId\"})\n * private genericPourModel: GenericPourModel;\n * ```\n *\n *\n * ## factory\n *\n * The factory method creates a factory function that can be used to create new GenericPourModel instances.\n *\n \n * The factory function is a curried function that takes the model id as the first argument and the options as the second argument.\n *\n * If a model with the specified id already exists, the factory function will return the existing model. The options will be ignored\n * in this case and the existing model will be returned in its current state.\n *\n * @example\n * ```typescript\n * const model = GenericPour.factory(\"genericPourId\")({\n * // Add option data\n * });\n * ```\n \n\n *\n * ## predicate\n *\n * [Typescript type predicate](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates) function that will identify and narrow down a model to a GenericPourModel.\n *\n * @example\n * ```typescript\n *\n * const model: IKosDataModel = ...; // some model\n *\n * if (GenericPour.predicate(model)) {\n * // if the function evaluates to true, the model is narrowed down to GenericPourModel\n * // and the compiler will know that the model has the GenericPourModel interface\n * model.updateAvailability(false);\n * }\n * ```\n *\n * ## registration\n *\n * The registration property is an object that can be used to simplify registration of the model with the model registry. The registration object\n * can be spread into the model registration and provides all of the required information to register the model implementation class against the model type.\n *\n *\n * @example\n *\n * In an application registration file you can declare the model registration as follows:\n *\n * **registration.ts**\n * ```typescript\n * import { GenericPour } from \"@kos-ui/project-models\";\n * import { KosModelRegistry } from \"@kosdev-code/kos-dispense-sdk\";\n *\n * import { initKosProvider } from \"@kosdev-code/kos-ui-sdk\";\n *\n * KosModelRegistry.dispense\n * .models()\n * .model(GenericPour);\n * ```\n *\n * ## registration.singleton\n \n * The genericPour model is NOT a singleton model. This means that each time the factory function is called with a unique ID, a new model instance will be created.\n * If the factory function is called with an ID that already exists, the existing model will be returned.\n \n * */\nexport const GenericPour = new KosModelRegistrationFactory<\n GenericPourModel,\n GenericPourOptions\n>({\n class: GenericPourModelImpl,\n type: MODEL_TYPE,\n});\n","import type { IKosRegistry } from \"@kosdev-code/kos-ui-sdk\";\nimport { Assembly } from \"../models/assembly\";\nimport { Availability } from \"../models/availability\";\nimport { BoardContainer } from \"../models/board\";\nimport { Holder } from \"../models/holder\";\nimport { HolderContainer } from \"../models/holder-container\";\nimport { Ingredient } from \"../models/ingredient\";\nimport { IngredientContainer } from \"../models/ingredient-container\";\nimport { Nozzle } from \"../models/nozzle\";\nimport { Pump } from \"../models/pump\";\nimport { PumpContainer } from \"../models/pump-container\";\n\nexport const kosModels: IKosRegistry[\"models\"] = {\n ...IngredientContainer.registration,\n ...Ingredient.registration,\n ...HolderContainer.registration,\n ...Holder.registration,\n ...Nozzle.registration,\n ...Pump.registration,\n ...PumpContainer.registration,\n ...Availability.registration,\n ...Assembly.registration,\n ...BoardContainer.registration,\n} as IKosRegistry[\"models\"];\n","import {\n KosModelRegistry as CoreKosModelRegistration,\n EXTENSION_TROUBLE_DATA_MAPPER,\n ExtensionManager,\n RegistrationManager,\n getKosModelSync,\n registerCoreModels,\n registerLegacyModel,\n type RegistrationResult,\n type TroubleModel,\n} from \"@kosdev-code/kos-ui-sdk\";\nimport { Assembly } from \"../models/assembly/assembly-registration\";\nimport type { AssemblyModel } from \"../models/assembly/types\";\nimport type { BoardModel } from \"../models/board/types\";\nimport { DeviceAssembly } from \"../models/device-assembly\";\nimport { kosModels } from \"./registration\";\n\nexport const registerDispenseModels =\n <R>(root: R) =>\n () => {\n registerCoreModels(root)();\n DeviceAssembly.register();\n Object.keys(kosModels).forEach((key) => {\n const model = kosModels[key];\n registerLegacyModel(root)(key, model);\n });\n\n ExtensionManager[EXTENSION_TROUBLE_DATA_MAPPER].register(\n \"FirmwareUpdateInProgressTrouble\",\n async (trouble: TroubleModel) => {\n // If the trouble is related to a container, we don't need to map the data\n\n if (trouble.data?.deviceId) {\n const { model: assemblyModel } = getKosModelSync<AssemblyModel>(\n Assembly.type\n );\n\n if (assemblyModel) {\n const boardModel = assemblyModel.boards.find(\n (b) => b.id === trouble.data.deviceId\n )\n ? getKosModelSync<BoardModel>(trouble.data.deviceId).model\n : undefined;\n return {\n devices: boardModel ? boardModel.name : \"\",\n };\n }\n }\n return {};\n }\n );\n return {\n preload: RegistrationManager.model.preloadModel(root),\n model: RegistrationManager.model.register(root),\n companion: RegistrationManager.companion.register(root),\n legacy: RegistrationManager.model.registerLegacyModel(root),\n };\n };\n\nexport type DispenseKosModelRegistration<R> =\n typeof CoreKosModelRegistration & {\n dispense: { models: () => RegistrationResult<R> };\n preload: ReturnType<typeof RegistrationManager.model.preloadModel>;\n model: ReturnType<typeof RegistrationManager.model.register>;\n companion: ReturnType<typeof RegistrationManager.companion.register>;\n };\n\nconst _KosModelRegistry = {\n ...CoreKosModelRegistration,\n};\n\n(_KosModelRegistry as any).dispense = {\n models: registerDispenseModels(_KosModelRegistry),\n};\n(_KosModelRegistry as any).preload =\n RegistrationManager.model.preloadModel(_KosModelRegistry);\n(_KosModelRegistry as any).model =\n RegistrationManager.model.register(_KosModelRegistry);\n(_KosModelRegistry as any).companion =\n RegistrationManager.companion.register(_KosModelRegistry);\n(_KosModelRegistry as any).legacy =\n RegistrationManager.model.registerLegacyModel(_KosModelRegistry);\n\ntype KosModelRegistryType = DispenseKosModelRegistration<\n typeof _KosModelRegistry\n>;\n\nconst KosModelRegistry: KosModelRegistryType = _KosModelRegistry as any;\n\nexport { KosModelRegistry };\n"],"names":["ExtensionType","DispenseModelType","MODEL_TYPE","IngredientModelImpl","modelId","name","type","data","ingredientId","rest","__publicField","__decorateClass","kosModel","Ingredient","isKosModel","Kos","URL","resolveServiceUrl","getOne","ServiceFactory","getIngredients","log","KosLog","IngredientContainerModelImpl","options","KosModelContainer","context","allIngredients","ingredientContext","KosExtensionUtils","ingredientData","key","_a","ingredientOptions","ingredient","kosChild","IngredientContainer","getAll","postModel","deleteModel","getHolders","assignHolderIngredient","holderPath","unassignHolderIngredient","replaceLine","useFos","getAssignments","sendRfidOverride","overrides","factoryJson","url","response","error","FetchError","_c","_b","_d","addAssignment","assignment","deleteAssignment","id","ExtensionManager","EXTENSION_TROUBLE_MAPPER","trouble","result","EXTENSION_TROUBLE_DATA_MAPPER","pumpModel","getKosModelSync","ingredientModel","model","AssignmentError","message","HolderModelImpl","path","ingredientSource","ingredientType","slice","group","enjoyByDate","pump","_isPouring","props","intent","pumpPath","resolvedState","a","b","kosAction","e","kosDependency","kosTroubleAware","Holder","mapAssemblyHolderToModel","holderData","_ingredientId","holderExtData","ingType","ingSource","extData","sliceData","holderOptions","getAssembly","TOPIC_BOARD_LINKED","TOPIC_BOARD_UNLINKED","BoardContainerModel","boardLinkEvent","boardId","board","kosTopicHandler","DependencyLifecycle","boardTroubleDataMapper","boardPath","PumpIndex","PumpContainerModelImpl","PumpContainer","getPumpRelatedPaths","getKosModel","pumpTroubleResolver","relatedPaths","boardTroubleResolver","pumpContainer","pumpPromises","r","mapOptionsToModel","linked","instanceId","link","BoardModelImpl","Board","BoardContainer","TOPIC_INSERT_START","TOPIC_INSERT_COMPLETE","TOPIC_INSERT_UPDATE","TOPIC_REMOVE","TOPIC_REPLACE_LINE","TOPIC_HOLDER_CHANGED","HolderContainerModelImpl","_options","holder","event","HolderContainer","Logger","mapAssemblyBoardToModel","boardExtData","boardModel","assemblyBoardMap","boardContainer","PourState","sendIntent","pumpId","tracker","FutureManager","getIntentVolume","PumpModelImpl","inserted","nozzlePath","childPump","virtual","prevIngredientId","FutureHandler","future","kosFuture","Pump","mapAssemblyPumpToModel","assemblyPumpMap","holderContainer","nozzle","assemblyPump","subPump","subHolderPath","subPumpData","CONTEXT_ASSEMBLY_DATA","CONTEXT_ASSEMBLY_RAW_DATA","AssemblyModelImpl","EXTENSION_FEATURE_FLAG_RESOLVER","value","isKosDataModel","ChildModels","assembly","boards","assemblyHolders","nozzles","_core","_path","KosFeatureFlags","holders","holderModel","nozzlePumpMap","pumpMap","Assembly","AvailabilityModelImpl","available","kosParentAware","Availability","pourPourable","nozzleId","pourNamedPourable","getAvailability","urlPrefix","selectPourable","payload","clearPourable","PROP_BEVERAGE_TOPIC_PREFIX","createPropKey","isPourAware","TOPIC_NOZZLE_POUR_STARTED","TOPIC_NOZZLE_POUR_PROGRESS","TOPIC_NOZZLE_POUR_CANCEL","NozzleModelImpl","MultipleFutureHandler","brand","beverage","additional","arraysEqual","selectedPayload","defaultPayload","groupId","parentId","currentState","nextState","getAllKosCompanionModels","evt","EventBus","item","taggedId","childItem","availability","beverageContext","Nozzle","beverageData","extensionData","beverageOptions","update","KosContextManager","destroyKosModel","existing","DeviceAssemblyModelImpl","nozzleData","beverageTopicPrefix","pipeline","DeviceAssembly","SingletonKosModelRegistrationFactory","pourOnTarget","TOPIC_GENERIC_POUR_STARTED","TOPIC_GENERIC_POUR_PROGRESS","TOPIC_GENERIC_POUR_CANCEL","GenericPourModelImpl","GenericPour","KosModelRegistrationFactory","kosModels","registerDispenseModels","root","registerCoreModels","registerLegacyModel","assemblyModel","RegistrationManager","_KosModelRegistry","CoreKosModelRegistration","KosModelRegistry"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";var V=Object.defineProperty;var v=(t,e,a)=>e in t?V(t,e,{enumerable:!0,configurable:!0,writable:!0,value:a}):t[e]=a;var o=(t,e,a)=>(v(t,typeof e!="symbol"?e+"":e,a),a);const n=require("./dispense-registration-manager-DFEU9oXa.cjs"),r=require("@kosdev-code/kos-ui-sdk"),s=require("react"),O=Object.freeze(Object.defineProperty({__proto__:null,getIngredients:n.getIngredients},Symbol.toStringTag,{value:"Module"})),H=Object.freeze(Object.defineProperty({__proto__:null,addAssignment:n.addAssignment,assignHolderIngredient:n.assignHolderIngredient,deleteAssignment:n.deleteAssignment,getAssignments:n.getAssignments,getHolders:n.getHolders,replaceLine:n.replaceLine,sendRfidOverride:n.sendRfidOverride,unassignHolderIngredient:n.unassignHolderIngredient},Symbol.toStringTag,{value:"Module"})),j=Object.freeze(Object.defineProperty({__proto__:null,getAssembly:n.getAssembly},Symbol.toStringTag,{value:"Module"})),D=Object.freeze(Object.defineProperty({__proto__:null,getIntentVolume:n.getIntentVolume,sendIntent:n.sendIntent},Symbol.toStringTag,{value:"Module"})),F=Object.freeze(Object.defineProperty({__proto__:null,clearPourable:n.clearPourable,getAvailability:n.getAvailability,pourNamedPourable:n.pourNamedPourable,pourPourable:n.pourPourable,selectPourable:n.selectPourable},Symbol.toStringTag,{value:"Module"})),R=Object.freeze(Object.defineProperty({__proto__:null},Symbol.toStringTag,{value:"Module"})),L=Object.freeze(Object.defineProperty({__proto__:null,pourOnTarget:n.pourOnTarget},Symbol.toStringTag,{value:"Module"})),$=t=>{var l,u,M,x;const[e,a]=s.useState(((l=t==null?void 0:t.slice)==null?void 0:l.maxVolMl)??0),[i,m]=s.useState(((u=t==null?void 0:t.slice)==null?void 0:u.currentVolMl)??0),[p,T]=s.useState(((M=t==null?void 0:t.slice)==null?void 0:M.maxVolMl)!==void 0),[g,_]=s.useState(((x=t==null?void 0:t.slice)==null?void 0:x.currentVolMl)!==void 0),[I,S]=s.useState(i<=0?0:Math.floor((i||1)/(e||1)*100)),[f,P]=s.useState(p&&g);return s.useEffect(()=>{const A=r.kosAutoEffect(()=>{var d,c,y,E;a(((d=t==null?void 0:t.slice)==null?void 0:d.maxVolMl)??0),m(((c=t==null?void 0:t.slice)==null?void 0:c.currentVolMl)??0),T(((y=t==null?void 0:t.slice)==null?void 0:y.maxVolMl)!==void 0),_(((E=t==null?void 0:t.slice)==null?void 0:E.currentVolMl)!==void 0),S(i<=0?0:Math.floor((i||1)/(e||1)*100)),P(p&&g)});return()=>{A()}},[t]),{maxVolume:e,remainingVolume:i,fillPercent:I,hasFuelGuage:f}};class b{constructor(){o(this,"core",new r.CoreExtensionManager)}registerIngredientDataMapper(e){return r.ExtensionManager.dataMapper.registerDataMapper(n.ExtensionType.IngredientMapper,e),this}registerIngredientLoader(e){return r.ExtensionManager.loader.registerLoader(n.ExtensionType.IngredientLoader,e),this}registerIngredientIndex(e){return r.ExtensionManager.indexExtension.registerIndexExtension(n.ExtensionType.IngredientIndex,e),this}registerIngredientTypeMapper(e){return r.ExtensionManager.propertyMapper.registerPropertyMapper(n.ExtensionType.IngredientTypeMapper,e),this}registerHolderDataMapper(e){return r.ExtensionManager.dataMapper.registerDataMapper(n.ExtensionType.HolderMapper,e),this}registerHolderTypeMapper(e){return r.ExtensionManager.propertyMapper.registerPropertyMapper(n.ExtensionType.HolderTypeMapper,e),this}registerHolderIngredientMapper(e){return r.ExtensionManager.propertyMapper.registerPropertyMapper(n.ExtensionType.HolderTypeMapper,e),this}registerHolderIndex(e){return r.ExtensionManager.indexExtension.registerIndexExtension(n.ExtensionType.HolderIndex,e),this}registerAvailabilityDataMapper(e){return r.ExtensionManager.dataMapper.registerDataMapper(n.ExtensionType.AvailabilityMapper,e),this}registerAvailabilityLoader(e){return r.ExtensionManager.loader.registerLoader(n.ExtensionType.AvailabilityLoader,e),this}registerSelectedPourableDataMapper(e){return r.ExtensionManager.dataMapper.registerDataMapper(n.ExtensionType.SelectedPourableMapper,e),this}registerAssemblyDataMapper(e){return r.ExtensionManager.dataMapper.registerDataMapper(n.ExtensionType.AssemblyMapper,e),this}registerBoardIndex(e){return r.ExtensionManager.indexExtension.registerIndexExtension(n.ExtensionType.BoardIndex,e),this}registerBoardDataMapper(e){return r.ExtensionManager.dataMapper.registerDataMapper(n.ExtensionType.BoardMapper,e),this}registerAssemblyFeatureFlagResolver(e){var a;return(a=r.ExtensionManager[r.EXTENSION_FEATURE_FLAG_RESOLVER])==null||a.register(n.ExtensionType.AssemblyFeatureFlags,e),this}}class z{constructor(){o(this,"dispense");o(this,"core");this.dispense=new b,this.core=new r.CoreExtensionManager}}exports.DispenseExtensionManager=b;exports.KosExtensionManager=z;exports.assembly=R;exports.getFuelGaugeValue=$;exports.index=j;exports.index$1=L;exports.index$2=H;exports.index$3=O;exports.index$4=F;exports.index$5=D;
2
- //# sourceMappingURL=extension-utils-CKGiF5Qr.cjs.map
1
+ "use strict";var V=Object.defineProperty;var v=(t,e,a)=>e in t?V(t,e,{enumerable:!0,configurable:!0,writable:!0,value:a}):t[e]=a;var o=(t,e,a)=>(v(t,typeof e!="symbol"?e+"":e,a),a);const n=require("./dispense-registration-manager-DauhdXxX.cjs"),r=require("@kosdev-code/kos-ui-sdk"),s=require("react"),O=Object.freeze(Object.defineProperty({__proto__:null,getIngredients:n.getIngredients},Symbol.toStringTag,{value:"Module"})),H=Object.freeze(Object.defineProperty({__proto__:null,addAssignment:n.addAssignment,assignHolderIngredient:n.assignHolderIngredient,deleteAssignment:n.deleteAssignment,getAssignments:n.getAssignments,getHolders:n.getHolders,replaceLine:n.replaceLine,sendRfidOverride:n.sendRfidOverride,unassignHolderIngredient:n.unassignHolderIngredient},Symbol.toStringTag,{value:"Module"})),j=Object.freeze(Object.defineProperty({__proto__:null,getAssembly:n.getAssembly},Symbol.toStringTag,{value:"Module"})),D=Object.freeze(Object.defineProperty({__proto__:null,getIntentVolume:n.getIntentVolume,sendIntent:n.sendIntent},Symbol.toStringTag,{value:"Module"})),F=Object.freeze(Object.defineProperty({__proto__:null,clearPourable:n.clearPourable,getAvailability:n.getAvailability,pourNamedPourable:n.pourNamedPourable,pourPourable:n.pourPourable,selectPourable:n.selectPourable},Symbol.toStringTag,{value:"Module"})),R=Object.freeze(Object.defineProperty({__proto__:null},Symbol.toStringTag,{value:"Module"})),L=Object.freeze(Object.defineProperty({__proto__:null,pourOnTarget:n.pourOnTarget},Symbol.toStringTag,{value:"Module"})),$=t=>{var l,u,M,x;const[e,a]=s.useState(((l=t==null?void 0:t.slice)==null?void 0:l.maxVolMl)??0),[i,m]=s.useState(((u=t==null?void 0:t.slice)==null?void 0:u.currentVolMl)??0),[p,T]=s.useState(((M=t==null?void 0:t.slice)==null?void 0:M.maxVolMl)!==void 0),[g,_]=s.useState(((x=t==null?void 0:t.slice)==null?void 0:x.currentVolMl)!==void 0),[I,S]=s.useState(i<=0?0:Math.floor((i||1)/(e||1)*100)),[f,P]=s.useState(p&&g);return s.useEffect(()=>{const A=r.kosAutoEffect(()=>{var d,c,y,E;a(((d=t==null?void 0:t.slice)==null?void 0:d.maxVolMl)??0),m(((c=t==null?void 0:t.slice)==null?void 0:c.currentVolMl)??0),T(((y=t==null?void 0:t.slice)==null?void 0:y.maxVolMl)!==void 0),_(((E=t==null?void 0:t.slice)==null?void 0:E.currentVolMl)!==void 0),S(i<=0?0:Math.floor((i||1)/(e||1)*100)),P(p&&g)});return()=>{A()}},[t]),{maxVolume:e,remainingVolume:i,fillPercent:I,hasFuelGuage:f}};class b{constructor(){o(this,"core",new r.CoreExtensionManager)}registerIngredientDataMapper(e){return r.ExtensionManager.dataMapper.registerDataMapper(n.ExtensionType.IngredientMapper,e),this}registerIngredientLoader(e){return r.ExtensionManager.loader.registerLoader(n.ExtensionType.IngredientLoader,e),this}registerIngredientIndex(e){return r.ExtensionManager.indexExtension.registerIndexExtension(n.ExtensionType.IngredientIndex,e),this}registerIngredientTypeMapper(e){return r.ExtensionManager.propertyMapper.registerPropertyMapper(n.ExtensionType.IngredientTypeMapper,e),this}registerHolderDataMapper(e){return r.ExtensionManager.dataMapper.registerDataMapper(n.ExtensionType.HolderMapper,e),this}registerHolderTypeMapper(e){return r.ExtensionManager.propertyMapper.registerPropertyMapper(n.ExtensionType.HolderTypeMapper,e),this}registerHolderIngredientMapper(e){return r.ExtensionManager.propertyMapper.registerPropertyMapper(n.ExtensionType.HolderTypeMapper,e),this}registerHolderIndex(e){return r.ExtensionManager.indexExtension.registerIndexExtension(n.ExtensionType.HolderIndex,e),this}registerAvailabilityDataMapper(e){return r.ExtensionManager.dataMapper.registerDataMapper(n.ExtensionType.AvailabilityMapper,e),this}registerAvailabilityLoader(e){return r.ExtensionManager.loader.registerLoader(n.ExtensionType.AvailabilityLoader,e),this}registerSelectedPourableDataMapper(e){return r.ExtensionManager.dataMapper.registerDataMapper(n.ExtensionType.SelectedPourableMapper,e),this}registerAssemblyDataMapper(e){return r.ExtensionManager.dataMapper.registerDataMapper(n.ExtensionType.AssemblyMapper,e),this}registerBoardIndex(e){return r.ExtensionManager.indexExtension.registerIndexExtension(n.ExtensionType.BoardIndex,e),this}registerBoardDataMapper(e){return r.ExtensionManager.dataMapper.registerDataMapper(n.ExtensionType.BoardMapper,e),this}registerAssemblyFeatureFlagResolver(e){var a;return(a=r.ExtensionManager[r.EXTENSION_FEATURE_FLAG_RESOLVER])==null||a.register(n.ExtensionType.AssemblyFeatureFlags,e),this}}class z{constructor(){o(this,"dispense");o(this,"core");this.dispense=new b,this.core=new r.CoreExtensionManager}}exports.DispenseExtensionManager=b;exports.KosExtensionManager=z;exports.assembly=R;exports.getFuelGaugeValue=$;exports.index=j;exports.index$1=L;exports.index$2=H;exports.index$3=O;exports.index$4=F;exports.index$5=D;
2
+ //# sourceMappingURL=extension-utils-BcdtSKJM.cjs.map