import { extractTemplateCollection } from './templateEnvelopes' import { isTemplateEnvelope, resolveComponentTemplateIds, } from './componentTargetResolvers' import { cloneBinding, cloneBindingMap, cloneBindings, toVueSfc, uniquePropsName, } from './componentBindingHelpers' import { templateComponentBindings } from './componentBindingCatalog' import { propsForTemplate } from './componentTemplateProps' import type { BioTemplateEnvelope, TemplateCollectionEnvelope, TemplateId, TemplatePackId, TemplatePresetId, } from './types' export type BioTemplateComponentTarget = | TemplateId | TemplatePackId | TemplatePresetId | string | BioTemplateEnvelope | TemplateCollectionEnvelope export interface BioTemplateComponentBinding { id: string template_id: TemplateId component: string adapters: readonly string[] props: readonly string[] description: string importPath: '@morscherlab/mint-sdk' } export interface BioTemplateComponentPropsBinding extends BioTemplateComponentBinding { propsObject: Record } export interface BioTemplateResolvedComponentBinding extends Omit { /** Prop names advertised by the static template/component compatibility catalog. */ propNames: readonly string[] /** Concrete props ready for direct `v-bind="componentBindingsById[id].props"` use. */ props: Record /** Backward-compatible alias for callers that already consume componentProps entries. */ propsObject: Record } export type BioTemplateComponentBindingsById = Record export type BioTemplateComponentPropsById = Record> export type BioTemplateComponentPropsByComponent = Record[]> export interface BioTemplateComponentPropsLookupOptions { templateId?: TemplateId id?: string } export interface BioTemplateComponentImport { importPath: BioTemplateComponentBinding['importPath'] components: string[] statement: string } export interface BioTemplateComponentSnippet extends BioTemplateComponentBinding { propsName: string propsExpression: string template: string } export interface BioTemplateComponentSnippetOptions { propsVariable?: string } export interface BioTemplateComponentUsageOptions extends BioTemplateComponentSnippetOptions { targetExpression?: string targetPropName?: string } export interface BioTemplateComponentUsage { imports: BioTemplateComponentImport[] componentProps: BioTemplateComponentPropsBinding[] snippets: BioTemplateComponentSnippet[] propsDeclarations: string[] scriptSetup: string template: string sfc: string } /** @deprecated Scheduled for removal from the core SDK in MINT 1.4; the biology templates move to a dedicated package or the owning plugins. */ export function listBioTemplateComponentBindings(): Record { return cloneBindingMap(templateComponentBindings) } /** @deprecated Scheduled for removal from the core SDK in MINT 1.4; the biology templates move to a dedicated package or the owning plugins. */ export function getBioTemplateComponentBindings( target: BioTemplateComponentTarget ): BioTemplateComponentBinding[] { const templateIds = resolveComponentTemplateIds(target) return templateIds.flatMap(templateId => cloneBindings(templateComponentBindings[templateId])) } /** @deprecated Scheduled for removal from the core SDK in MINT 1.4; the biology templates move to a dedicated package or the owning plugins. */ export function toBioTemplateComponentProps( target: BioTemplateEnvelope | TemplateCollectionEnvelope ): BioTemplateComponentPropsBinding[] { if (isTemplateEnvelope(target)) { return propsForTemplate(target) } const collection = extractTemplateCollection(target) return Object.values(collection).flatMap(template => propsForTemplate(template)) } /** * Return resolved component bindings with concrete props for direct slot rendering. * * @deprecated Scheduled for removal from the core SDK in MINT 1.4; the biology templates move to a dedicated package or the owning plugins. */ export function toBioTemplateComponentBindings( target: BioTemplateEnvelope | TemplateCollectionEnvelope, ): BioTemplateResolvedComponentBinding[] { return toBioTemplateComponentProps(target).map(toResolvedComponentBinding) } /** * Return resolved component bindings keyed by stable template component id. * * @deprecated Scheduled for removal from the core SDK in MINT 1.4; the biology templates move to a dedicated package or the owning plugins. */ export function toBioTemplateComponentBindingsById( target: BioTemplateEnvelope | TemplateCollectionEnvelope, ): BioTemplateComponentBindingsById { return Object.fromEntries( toBioTemplateComponentBindings(target).map(binding => [binding.id, binding]), ) } /** * Return component props keyed by stable binding id for direct `v-bind="componentPropsById[id]"` use. * * @deprecated Scheduled for removal from the core SDK in MINT 1.4; the biology templates move to a dedicated package or the owning plugins. */ export function toBioTemplateComponentPropsById( target: BioTemplateEnvelope | TemplateCollectionEnvelope, ): BioTemplateComponentPropsById { return Object.fromEntries( toBioTemplateComponentProps(target).map(binding => [binding.id, binding.propsObject]), ) } /** * Return component props grouped by SDK component name for direct WellPlate/DoseCalculator binding. * * @deprecated Scheduled for removal from the core SDK in MINT 1.4; the biology templates move to a dedicated package or the owning plugins. */ export function toBioTemplateComponentPropsByComponent( target: BioTemplateEnvelope | TemplateCollectionEnvelope, ): BioTemplateComponentPropsByComponent { const grouped: BioTemplateComponentPropsByComponent = {} for (const binding of toBioTemplateComponentProps(target)) { const props = grouped[binding.component] ?? [] props.push(binding.propsObject) grouped[binding.component] = props } return grouped } /** * Return the first props object for an SDK component, optionally restricted by template id or binding id. * * @deprecated Scheduled for removal from the core SDK in MINT 1.4; the biology templates move to a dedicated package or the owning plugins. */ export function getBioTemplateComponentProps( target: BioTemplateEnvelope | TemplateCollectionEnvelope, component: string, options: BioTemplateComponentPropsLookupOptions = {}, ): Record | undefined { return toBioTemplateComponentProps(target).find((binding) => { if (binding.component !== component) return false if (options.id !== undefined && binding.id !== options.id) return false if (options.templateId !== undefined && binding.template_id !== options.templateId) return false return true })?.propsObject } function toResolvedComponentBinding( binding: BioTemplateComponentPropsBinding, ): BioTemplateResolvedComponentBinding { const { props: propNames, propsObject, ...rest } = binding return { ...rest, propNames, props: propsObject, propsObject, } } /** @deprecated Scheduled for removal from the core SDK in MINT 1.4; the biology templates move to a dedicated package or the owning plugins. */ export function toBioTemplateComponentImports( target: BioTemplateComponentTarget ): BioTemplateComponentImport[] { const groups = new Map() for (const binding of getBioTemplateComponentBindings(target)) { const components = groups.get(binding.importPath) ?? [] if (!components.includes(binding.component)) components.push(binding.component) groups.set(binding.importPath, components) } return Array.from(groups.entries()).map(([importPath, components]) => ({ importPath, components, statement: `import { ${components.join(', ')} } from '${importPath}'`, })) } /** @deprecated Scheduled for removal from the core SDK in MINT 1.4; the biology templates move to a dedicated package or the owning plugins. */ export function toBioTemplateComponentSnippets( target: BioTemplateEnvelope | TemplateCollectionEnvelope, options: BioTemplateComponentSnippetOptions = {} ): BioTemplateComponentSnippet[] { const propsVariable = options.propsVariable ?? 'componentProps' const usedNames = new Map() return toBioTemplateComponentProps(target).map((binding, index) => { const propsName = uniquePropsName(binding, usedNames) const propsExpression = `${propsVariable}[${index}].propsObject` return { ...cloneBinding(binding), propsName, propsExpression, template: `<${binding.component} v-bind="${propsExpression}" />`, } }) } /** @deprecated Scheduled for removal from the core SDK in MINT 1.4; the biology templates move to a dedicated package or the owning plugins. */ export function toBioTemplateComponentUsage( target: BioTemplateEnvelope | TemplateCollectionEnvelope, options: BioTemplateComponentUsageOptions = {} ): BioTemplateComponentUsage { const propsVariable = options.propsVariable ?? 'componentProps' const usesGeneratedTargetProp = options.targetExpression === undefined const targetPropName = options.targetPropName ?? 'templateCollection' const targetExpression = options.targetExpression ?? `props.${targetPropName}` const componentProps = toBioTemplateComponentProps(target) const snippets = toBioTemplateComponentSnippets(target, { propsVariable }).map(snippet => ({ ...snippet, propsExpression: snippet.propsName, template: `<${snippet.component} v-bind="${snippet.propsName}" />`, })) const propsDeclarations = snippets.map( (snippet, index) => `const ${snippet.propsName} = ${propsVariable}[${index}].propsObject` ) const setupLines = [ ...(usesGeneratedTargetProp ? [`const props = defineProps<{ ${targetPropName}: BioTemplateEnvelope | TemplateCollectionEnvelope }>()`] : []), `const ${propsVariable} = toBioTemplateComponentProps(${targetExpression})`, ...propsDeclarations, ] const imports = toBioTemplateComponentImports(target) const template = snippets.map(snippet => snippet.template).join('\n') return { imports, componentProps, snippets, propsDeclarations, scriptSetup: setupLines.join('\n'), template, sfc: toVueSfc(imports, setupLines, template, usesGeneratedTargetProp), } }