@morscherlab/mint-sdk 1.2.0-beta.8 → 1.2.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.
- package/README.md +60 -0
- package/dist/{ExperimentPopover-CfOdh5Rm.js → ExperimentPopover-CJdNlCZb.js} +24 -15
- package/dist/ExperimentPopover-CJdNlCZb.js.map +1 -0
- package/dist/{ExperimentSelectorModal-DvIagrxY.js → ExperimentSelectorModal-DCXmwKNS.js} +5 -5
- package/dist/ExperimentSelectorModal-DCXmwKNS.js.map +1 -0
- package/dist/{SettingsModal-W3TYfnP9.js → SettingsModal-BYR20I4c.js} +5 -5
- package/dist/SettingsModal-BYR20I4c.js.map +1 -0
- package/dist/{EmptyState-NBqf2_8z.js → Skeleton-BAF3CKY7.js} +111 -93
- package/dist/Skeleton-BAF3CKY7.js.map +1 -0
- package/dist/__tests__/components/DataStates.test.d.ts +1 -0
- package/dist/__tests__/components/ExperimentTimeline.test.d.ts +1 -0
- package/dist/__tests__/components/FileBrowserModal.test.d.ts +1 -0
- package/dist/__tests__/components/FilePicker.state.test.d.ts +1 -0
- package/dist/__tests__/components/FilePicker.test.d.ts +1 -0
- package/dist/__tests__/components/PlotlyChart.test.d.ts +1 -0
- package/dist/__tests__/components/iconButtonIconSizing.test.d.ts +1 -0
- package/dist/__tests__/composables/useFileBrowser.test.d.ts +1 -0
- package/dist/__tests__/composables/useListReorder.test.d.ts +1 -0
- package/dist/__tests__/composables/usePlatformFilePickerAdapter.test.d.ts +1 -0
- package/dist/__tests__/styles/cssTokens.test.d.ts +1 -0
- package/dist/apiErrors.d.ts +26 -0
- package/dist/components/ActionMenu.vue.d.ts +1 -1
- package/dist/components/AppPluginSwitcher.vue.d.ts +2 -0
- package/dist/components/AuditTrail.vue.d.ts +13 -0
- package/dist/components/BaseInput.vue.d.ts +1 -1
- package/dist/components/BaseSelect.vue.d.ts +1 -1
- package/dist/components/BaseTextarea.vue.d.ts +1 -1
- package/dist/components/BatchProgressList.vue.d.ts +17 -0
- package/dist/components/BioTemplateExperimentWorkspaceView.vue.d.ts +2 -2
- package/dist/components/BioTemplatePackWorkspaceView.vue.d.ts +2 -2
- package/dist/components/ConcentrationInput.vue.d.ts +1 -1
- package/dist/components/DataFrame.vue.d.ts +14 -2
- package/dist/components/DatePicker.vue.d.ts +2 -2
- package/dist/components/DateTimePicker.vue.d.ts +3 -1
- package/dist/components/ExperimentDataViewer.vue.d.ts +26 -1
- package/dist/components/ExperimentPopover.vue.d.ts +1 -0
- package/dist/components/ExperimentTimeline.vue.d.ts +29 -1
- package/dist/components/FileBrowserModal.vue.d.ts +99 -0
- package/dist/components/FilePicker.vue.d.ts +32 -0
- package/dist/components/FileUploader.vue.d.ts +5 -2
- package/dist/components/FormulaInput.vue.d.ts +1 -1
- package/dist/components/GeneratedPlotlyResult.vue.d.ts +1 -3
- package/dist/components/LcmsSequenceTable.vue.d.ts +29 -1
- package/dist/components/MobileSupportGate.vue.d.ts +1 -1
- package/dist/components/MoleculeInput.vue.d.ts +1 -1
- package/dist/components/NumberInput.vue.d.ts +1 -1
- package/dist/components/PlotlyChart.vue.d.ts +59 -0
- package/dist/components/ProgressBar.vue.d.ts +1 -1
- package/dist/components/ProtocolStepEditor.vue.d.ts +1 -0
- package/dist/components/ReagentList.vue.d.ts +29 -1
- package/dist/components/ResourceCard.vue.d.ts +1 -1
- package/dist/components/SampleHierarchyTree.vue.d.ts +29 -1
- package/dist/components/SampleSelector.drag.d.ts +13 -0
- package/dist/components/SampleSelector.tree.d.ts +2 -0
- package/dist/components/SampleSelector.vue.d.ts +34 -1
- package/dist/components/ScheduleCalendar.vue.d.ts +20 -0
- package/dist/components/SecretInput.vue.d.ts +1 -1
- package/dist/components/SequenceInput.vue.d.ts +1 -1
- package/dist/components/SmartGroupFieldRecipe.vue.d.ts +1 -0
- package/dist/components/StatusIndicator.vue.d.ts +1 -1
- package/dist/components/TagsInput.vue.d.ts +1 -1
- package/dist/components/TimePicker.vue.d.ts +2 -1
- package/dist/components/TimeRangeInput.vue.d.ts +1 -1
- package/dist/components/UnitInput.vue.d.ts +1 -1
- package/dist/components/WellPlate.geometry.d.ts +15 -0
- package/dist/components/WellPlate.interaction.d.ts +13 -0
- package/dist/components/WellPlate.vue.d.ts +30 -1
- package/dist/components/fileBrowserPresentation.d.ts +10 -0
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.js +8 -8
- package/dist/components/internal/AppTopBarPageSelectorInternal.vue.d.ts +2 -0
- package/dist/components/internal/DataStateInternal.vue.d.ts +43 -0
- package/dist/components/internal/FileBrowserDialogInternal.vue.d.ts +34 -0
- package/dist/components/internal/FileBrowserListingInternal.vue.d.ts +25 -0
- package/dist/components/internal/FileBrowserToolbarInternal.vue.d.ts +26 -0
- package/dist/components/internal/FilePickerPreviewInternal.vue.d.ts +18 -0
- package/dist/components/internal/FilePickerTreeInternal.vue.d.ts +31 -0
- package/dist/{components-B80gV0P6.js → components-DIum5hkx.js} +5415 -2753
- package/dist/components-DIum5hkx.js.map +1 -0
- package/dist/composables/controlSchemaTypes.d.ts +34 -0
- package/dist/composables/filePicker/localFiles.d.ts +3 -0
- package/dist/composables/filePicker/usePickerNavigation.d.ts +96 -0
- package/dist/composables/filePicker/usePickerSelection.d.ts +31 -0
- package/dist/composables/filePicker/validation.d.ts +5 -0
- package/dist/composables/index.d.ts +3 -0
- package/dist/composables/index.js +10 -10
- package/dist/composables/useApi.d.ts +14 -7
- package/dist/composables/useDropdownState.d.ts +18 -2
- package/dist/composables/useEventStream.d.ts +9 -0
- package/dist/composables/useFileBrowser.d.ts +55 -0
- package/dist/composables/useFilePicker.d.ts +189 -0
- package/dist/composables/useListReorder.d.ts +90 -0
- package/dist/composables/useMenuKeyboard.d.ts +2 -2
- package/dist/composables/usePlatformFilePickerAdapter.d.ts +11 -0
- package/dist/composables/usePluginConfig.d.ts +3 -1
- package/dist/composables/useRequestSyncState.d.ts +42 -2
- package/dist/composables/useScheduleDrag.d.ts +1 -0
- package/dist/{composables-C8mmD5ta.js → composables-mFXsTA4g.js} +307 -74
- package/dist/composables-mFXsTA4g.js.map +1 -0
- package/dist/{useApi-CDBq6z23.js → errors-BLuqMee5.js} +178 -16
- package/dist/errors-BLuqMee5.js.map +1 -0
- package/dist/{experiment-Y9Iz7KYi.js → experiment-CVDRAnqp.js} +3 -8
- package/dist/experiment-CVDRAnqp.js.map +1 -0
- package/dist/{experiment-utils-DV3DrvE_.js → experiment-utils-CV2Wza3z.js} +1 -1
- package/dist/experiment-utils-CV2Wza3z.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +15 -15
- package/dist/install.js +2 -7
- package/dist/install.js.map +1 -1
- package/dist/permissions.d.ts +42 -1
- package/dist/permissions.js +20 -10
- package/dist/permissions.js.map +1 -1
- package/dist/stores/index.d.ts +1 -1
- package/dist/stores/index.js +3 -3
- package/dist/stores/settings.d.ts +31 -1
- package/dist/styles.css +15162 -32475
- package/dist/templates/index.js +2 -4
- package/dist/{templates-CK72aKO1.js → templates-CmGfmBRA.js} +291 -85
- package/dist/templates-CmGfmBRA.js.map +1 -0
- package/dist/types/fileBrowserTypes.d.ts +77 -0
- package/dist/types/filePicker.d.ts +77 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/{useControlSchema-_OVhavKq.js → useControlSchema-DldpxNOP.js} +234 -1121
- package/dist/useControlSchema-DldpxNOP.js.map +1 -0
- package/dist/{useDropdownState-D5G4UvWd.js → useDropdownState-C7hRiVQf.js} +22 -6
- package/dist/useDropdownState-C7hRiVQf.js.map +1 -0
- package/dist/{useExperimentSelector-DSEckf_g.js → useExperimentSelector-CEcIaueJ.js} +4 -4
- package/dist/{useExperimentSelector-DSEckf_g.js.map → useExperimentSelector-CEcIaueJ.js.map} +1 -1
- package/dist/{useFormBuilder-Bd714C7y.js → useFormBuilder-z5L_dUIy.js} +2 -2
- package/dist/{useFormBuilder-Bd714C7y.js.map → useFormBuilder-z5L_dUIy.js.map} +1 -1
- package/dist/utils/color.d.ts +13 -0
- package/dist/utils/errors.d.ts +9 -0
- package/dist/{useProtocolTemplates-Dq5Pzwyd.js → validation-uwoJGEb6.js} +231 -158
- package/dist/validation-uwoJGEb6.js.map +1 -0
- package/package.json +1 -1
- package/src/__tests__/apiErrors.test.ts +81 -0
- package/src/__tests__/components/ActionMenu.test.ts +94 -0
- package/src/__tests__/components/DataFrame.test.ts +183 -11
- package/src/__tests__/components/DataStates.test.ts +176 -0
- package/src/__tests__/components/DatePicker.test.ts +76 -0
- package/src/__tests__/components/DateTimePicker.test.ts +36 -0
- package/src/__tests__/components/ExperimentPopover.test.ts +30 -0
- package/src/__tests__/components/ExperimentTimeline.test.ts +63 -0
- package/src/__tests__/components/FileBrowserModal.test.ts +460 -0
- package/src/__tests__/components/FilePicker.state.test.ts +287 -0
- package/src/__tests__/components/FilePicker.test.ts +487 -0
- package/src/__tests__/components/GeneratedPlotlyResult.test.ts +52 -5
- package/src/__tests__/components/GroupAssigner.test.ts +53 -0
- package/src/__tests__/components/LcmsSequenceTable.test.ts +22 -0
- package/src/__tests__/components/PlotlyChart.test.ts +305 -0
- package/src/__tests__/components/RackEditor.test.ts +35 -0
- package/src/__tests__/components/ReagentList.test.ts +64 -2
- package/src/__tests__/components/RetiredStyles.test.ts +31 -0
- package/src/__tests__/components/SampleSelector.drag.test.ts +51 -1
- package/src/__tests__/components/ScheduleCalendar.test.ts +63 -0
- package/src/__tests__/components/SegmentedControl.test.ts +107 -0
- package/src/__tests__/components/TimePicker.test.ts +61 -0
- package/src/__tests__/components/WellPlate.interaction.test.ts +59 -0
- package/src/__tests__/components/iconButtonIconSizing.test.ts +18 -0
- package/src/__tests__/composables/useApi.test.ts +92 -9
- package/src/__tests__/composables/useDropdownState.test.ts +58 -1
- package/src/__tests__/composables/useFileBrowser.test.ts +305 -0
- package/src/__tests__/composables/useGeneratedAnalysis.test.ts +7 -2
- package/src/__tests__/composables/useListReorder.test.ts +145 -0
- package/src/__tests__/composables/usePlatformFilePickerAdapter.test.ts +67 -0
- package/src/__tests__/composables/usePluginClient.test.ts +3 -0
- package/src/__tests__/composables/useRequestSyncState.test.ts +140 -0
- package/src/__tests__/stores/settings.test.ts +71 -1
- package/src/__tests__/styles/cssTokens.test.ts +131 -0
- package/src/__tests__/utils/permissions.test.ts +68 -0
- package/src/apiErrors.ts +85 -0
- package/src/components/ActionMenu.vue +45 -88
- package/src/components/AlertBox.vue +0 -4
- package/src/components/AppAvatarMenu.vue +2 -14
- package/src/components/AppLayout.vue +0 -4
- package/src/components/AppPluginSwitcher.story.vue +87 -0
- package/src/components/AppPluginSwitcher.vue +2 -5
- package/src/components/AppSidebar.vue +0 -4
- package/src/components/AppToastContainer.vue +6 -8
- package/src/components/AppTopBar.vue +0 -4
- package/src/components/ArtifactSaveDialog.vue +0 -4
- package/src/components/ArtifactSelectorModal.vue +0 -4
- package/src/components/AuditTrail.story.vue +18 -0
- package/src/components/AuditTrail.vue +27 -7
- package/src/components/AutoGroupModal.vue +0 -4
- package/src/components/Avatar.vue +0 -4
- package/src/components/BaseButton.vue +0 -4
- package/src/components/BaseCheckbox.vue +0 -4
- package/src/components/BaseInput.vue +0 -4
- package/src/components/BaseModal.vue +0 -4
- package/src/components/BasePill.vue +0 -4
- package/src/components/BaseRadioGroup.vue +0 -4
- package/src/components/BaseSelect.vue +0 -4
- package/src/components/BaseSlider.vue +0 -4
- package/src/components/BaseTabs.vue +0 -4
- package/src/components/BaseTextarea.vue +0 -4
- package/src/components/BaseToggle.vue +0 -4
- package/src/components/BatchProgressList.story.vue +18 -0
- package/src/components/BatchProgressList.vue +32 -4
- package/src/components/Breadcrumb.vue +0 -4
- package/src/components/Calendar.vue +0 -4
- package/src/components/ChartContainer.story.vue +1 -1
- package/src/components/ChartContainer.vue +0 -4
- package/src/components/ChemicalFormula.vue +0 -4
- package/src/components/CollapsibleCard.vue +0 -4
- package/src/components/ColorSlider.vue +0 -4
- package/src/components/ConcentrationInput.vue +0 -4
- package/src/components/ConfirmDialog.vue +0 -4
- package/src/components/DataFrame.story.vue +14 -0
- package/src/components/DataFrame.vue +97 -23
- package/src/components/DatePicker.vue +73 -27
- package/src/components/DateTimePicker.vue +45 -17
- package/src/components/Divider.vue +0 -4
- package/src/components/DoseCalculator.vue +0 -4
- package/src/components/DropdownButton.vue +2 -14
- package/src/components/EmptyState.vue +0 -4
- package/src/components/ExperimentCodeBadge.vue +0 -4
- package/src/components/ExperimentDataViewer.story.vue +3 -0
- package/src/components/ExperimentDataViewer.vue +33 -13
- package/src/components/ExperimentPopover.vue +12 -7
- package/src/components/ExperimentSelectorModal.vue +0 -4
- package/src/components/ExperimentTimeline.story.vue +18 -0
- package/src/components/ExperimentTimeline.vue +81 -75
- package/src/components/FileBrowserModal.story.vue +203 -0
- package/src/components/FileBrowserModal.vue +384 -0
- package/src/components/FilePicker.story.vue +44 -0
- package/src/components/FilePicker.vue +284 -0
- package/src/components/FileUploader.vue +32 -18
- package/src/components/FitPanel.vue +0 -4
- package/src/components/FormActions.story.vue +96 -0
- package/src/components/FormActions.vue +0 -4
- package/src/components/FormBuilder.vue +0 -4
- package/src/components/FormField.vue +0 -4
- package/src/components/FormulaInput.vue +0 -4
- package/src/components/GeneratedPathInput.story.vue +68 -0
- package/src/components/GeneratedPlotlyResult.story.vue +96 -0
- package/src/components/GeneratedPlotlyResult.vue +34 -69
- package/src/components/GeneratedPluginView.story.vue +145 -0
- package/src/components/GeneratedPluginView.vue +10 -10
- package/src/components/GeneratedResultRenderer.story.vue +117 -0
- package/src/components/GeneratedResultRenderer.vue +4 -9
- package/src/components/GroupAssigner.vue +67 -5
- package/src/components/IconButton.vue +0 -4
- package/src/components/InstrumentAlertLog.vue +0 -4
- package/src/components/InstrumentStateBadge.vue +0 -4
- package/src/components/InstrumentStatusCard.vue +0 -4
- package/src/components/JobsStatusTray.vue +0 -4
- package/src/components/LcmsSequenceTable.vue +81 -50
- package/src/components/LoadingSpinner.vue +0 -4
- package/src/components/MobileSupportGate.vue +0 -4
- package/src/components/MoleculeInput.vue +0 -4
- package/src/components/MultiSelect.vue +0 -4
- package/src/components/NumberInput.vue +0 -4
- package/src/components/PlateMapEditor.vue +3 -14
- package/src/components/PlotlyChart.story.vue +61 -0
- package/src/components/PlotlyChart.vue +233 -0
- package/src/components/PluginIcon.vue +0 -4
- package/src/components/ProgressBar.vue +0 -4
- package/src/components/ProtocolStepEditor.vue +2 -4
- package/src/components/RackEditor.vue +51 -70
- package/src/components/ReagentEditor.vue +0 -4
- package/src/components/ReagentList.story.vue +18 -0
- package/src/components/ReagentList.vue +127 -82
- package/src/components/ResourceCard.vue +0 -4
- package/src/components/RuntimeUpdateNotice.story.vue +49 -0
- package/src/components/RuntimeUpdateNotice.vue +4 -4
- package/src/components/SampleHierarchyTree.story.vue +18 -0
- package/src/components/SampleHierarchyTree.vue +32 -9
- package/src/components/SampleLegend.vue +2 -8
- package/src/components/SampleSelector.drag.ts +51 -0
- package/src/components/SampleSelector.story.vue +6 -0
- package/src/components/SampleSelector.tree.ts +2 -0
- package/src/components/SampleSelector.vue +49 -10
- package/src/components/SampleSelectorGroupNode.vue +19 -0
- package/src/components/ScheduleCalendar.story.vue +6 -0
- package/src/components/ScheduleCalendar.vue +82 -7
- package/src/components/ScientificNumber.vue +0 -4
- package/src/components/SectionCard.vue +0 -4
- package/src/components/SegmentedControl.vue +50 -7
- package/src/components/SequenceInput.vue +0 -4
- package/src/components/SequenceProgressBar.story.vue +110 -0
- package/src/components/SequenceProgressBar.vue +0 -4
- package/src/components/SettingsModal.vue +0 -4
- package/src/components/Skeleton.vue +0 -4
- package/src/components/SmartGroupFieldRecipe.vue +8 -6
- package/src/components/SmartGroupManual.vue +0 -4
- package/src/components/StatusIndicator.vue +0 -4
- package/src/components/StepWizard.vue +0 -4
- package/src/components/TagsInput.vue +4 -6
- package/src/components/ThemeToggle.vue +0 -4
- package/src/components/TimePicker.vue +36 -7
- package/src/components/TimeRangeInput.vue +0 -4
- package/src/components/Tooltip.story.vue +3 -3
- package/src/components/Tooltip.vue +0 -4
- package/src/components/UnitInput.vue +0 -4
- package/src/components/WellPlate.geometry.ts +60 -1
- package/src/components/WellPlate.interaction.ts +44 -0
- package/src/components/WellPlate.story.vue +8 -0
- package/src/components/WellPlate.vue +53 -7
- package/src/components/fileBrowserPresentation.ts +39 -0
- package/src/components/index.ts +5 -0
- package/src/components/internal/AppTopBarPageSelectorInternal.vue +2 -5
- package/src/components/internal/AppTopBarPillNavInternal.vue +0 -4
- package/src/components/internal/DataStateInternal.vue +74 -0
- package/src/components/internal/FileBrowserDialogInternal.vue +75 -0
- package/src/components/internal/FileBrowserListingInternal.vue +197 -0
- package/src/components/internal/FileBrowserToolbarInternal.vue +136 -0
- package/src/components/internal/FilePickerPreviewInternal.vue +100 -0
- package/src/components/internal/FilePickerTreeInternal.vue +238 -0
- package/src/components/internal/FormSectionRenderer.vue +0 -4
- package/src/components/internal/WellEditPopupInternal.vue +0 -4
- package/src/composables/controlSchemaTypes.ts +34 -0
- package/src/composables/filePicker/localFiles.ts +58 -0
- package/src/composables/filePicker/usePickerNavigation.ts +220 -0
- package/src/composables/filePicker/usePickerSelection.ts +259 -0
- package/src/composables/filePicker/validation.ts +41 -0
- package/src/composables/index.ts +17 -0
- package/src/composables/useApi.ts +57 -13
- package/src/composables/useDropdownState.ts +35 -5
- package/src/composables/useEventStream.ts +14 -2
- package/src/composables/useFileBrowser.ts +314 -0
- package/src/composables/useFileImport.ts +2 -7
- package/src/composables/useFilePicker.ts +366 -0
- package/src/composables/useGeneratedAnalysis.ts +18 -26
- package/src/composables/useListReorder.story.vue +143 -0
- package/src/composables/useListReorder.ts +242 -0
- package/src/composables/useMenuKeyboard.ts +2 -2
- package/src/composables/useOptimisticMutation.ts +1 -15
- package/src/composables/usePlatformFilePickerAdapter.ts +104 -0
- package/src/composables/usePluginClient.ts +3 -0
- package/src/composables/usePluginConfig.ts +3 -1
- package/src/composables/useRackEditor.ts +2 -11
- package/src/composables/useRequestSyncState.ts +98 -28
- package/src/composables/useResourceCrud.ts +1 -15
- package/src/composables/useScheduleDrag.ts +37 -0
- package/src/composables/useWellPainting.ts +5 -29
- package/src/composables/useWellPlateEditor.ts +1 -11
- package/src/index.ts +3 -0
- package/src/permissions.ts +48 -9
- package/src/stores/experiment.ts +2 -7
- package/src/stores/index.ts +9 -1
- package/src/stores/settings.ts +93 -1
- package/src/styles/components/audit-trail.css +5 -5
- package/src/styles/components/batch-progress-list.css +7 -0
- package/src/styles/components/color-slider.css +2 -2
- package/src/styles/components/data-state.css +30 -0
- package/src/styles/components/dataframe.css +29 -35
- package/src/styles/components/experiment-data-viewer.css +4 -4
- package/src/styles/components/experiment-timeline.css +3 -30
- package/src/styles/components/file-browser-modal.css +489 -0
- package/src/styles/components/file-picker.css +502 -0
- package/src/styles/components/form-builder.css +5 -5
- package/src/styles/components/icon-button.css +9 -0
- package/src/styles/components/lcms-sequence-table.css +16 -1
- package/src/styles/components/multi-select.css +1 -1
- package/src/styles/components/reagent-list.css +38 -31
- package/src/styles/components/sample-hierarchy-tree.css +5 -19
- package/src/styles/components/sample-selector.css +9 -2
- package/src/styles/components/schedule-calendar.css +8 -0
- package/src/styles/components/scientific-number.css +1 -1
- package/src/styles/components/well-plate.css +8 -0
- package/src/styles/index.css +11 -0
- package/src/styles/variables.css +29 -0
- package/src/templates/builderPresetControls.ts +1 -1
- package/src/templates/componentPlateHelpers.ts +3 -1
- package/src/templates/doseResponseAdapters.ts +2 -13
- package/src/templates/elisaAssayCollectionBuilder.ts +2 -2
- package/src/templates/plateMapBuilder.ts +2 -2
- package/src/templates/qpcrPlateBuilder.ts +1 -1
- package/src/templates/templateValidators.ts +1 -1
- package/src/templates/timeCourseBuilder.ts +2 -2
- package/src/templates/wellPlateScreenCollectionBuilder.ts +2 -2
- package/src/types/fileBrowserTypes.ts +85 -0
- package/src/types/filePicker.ts +72 -0
- package/src/types/index.ts +14 -0
- package/src/utils/color.ts +51 -0
- package/src/utils/errors.ts +29 -0
- package/dist/EmptyState-NBqf2_8z.js.map +0 -1
- package/dist/ExperimentPopover-CfOdh5Rm.js.map +0 -1
- package/dist/ExperimentSelectorModal-DvIagrxY.js.map +0 -1
- package/dist/SettingsModal-W3TYfnP9.js.map +0 -1
- package/dist/components-B80gV0P6.js.map +0 -1
- package/dist/composables/autoGroupConstants.d.ts +0 -1
- package/dist/composables/autoGroupGrouping.d.ts +0 -3
- package/dist/composables/useAutoGroupInputSources.d.ts +0 -32
- package/dist/composables-C8mmD5ta.js.map +0 -1
- package/dist/experiment-Y9Iz7KYi.js.map +0 -1
- package/dist/experiment-utils-DV3DrvE_.js.map +0 -1
- package/dist/templates/builderDefaults.d.ts +0 -1
- package/dist/templates/plateGeometry.d.ts +0 -4
- package/dist/templates-CK72aKO1.js.map +0 -1
- package/dist/useApi-CDBq6z23.js.map +0 -1
- package/dist/useControlSchema-_OVhavKq.js.map +0 -1
- package/dist/useDropdownState-D5G4UvWd.js.map +0 -1
- package/dist/useProtocolTemplates-Dq5Pzwyd.js.map +0 -1
- package/src/__tests__/composables/useAutoGroupInputSources.test.ts +0 -127
- package/src/composables/autoGroupConstants.ts +0 -4
- package/src/composables/autoGroupGrouping.ts +0 -148
- package/src/composables/useAutoGroupInputSources.ts +0 -147
- package/src/templates/builderDefaults.ts +0 -11
- package/src/templates/plateGeometry.ts +0 -62
- /package/dist/__tests__/{composables/useAutoGroupInputSources.test.d.ts → apiErrors.test.d.ts} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"composables-mFXsTA4g.js","names":[],"sources":["../src/composables/useAuth.ts","../src/composables/usePasskey.ts","../src/composables/pluginFrontendBase.ts","../src/composables/useAsync.ts","../src/composables/usePluginConfig.ts","../src/composables/useFileBrowser.ts","../src/composables/analysisArtifactTarget.ts","../src/composables/useCommandHistory.ts","../src/composables/useOptimisticMutation.ts","../src/composables/useResourceCrud.ts","../src/composables/useWellPainting.ts","../src/composables/useWellPlateAdapter.ts","../src/composables/useWellPlateValidation.ts","../src/composables/pluginEndpointBuilder.ts","../src/composables/usePluginClient.ts","../src/composables/usePlatformFilePickerAdapter.ts"],"sourcesContent":["import axios from 'axios'\nimport { ref, onMounted, onUnmounted, watch, getCurrentInstance, type Ref } from 'vue'\nimport { useAuthStore } from '../stores/auth'\nimport { useSettingsStore } from '../stores/settings'\nimport type { AuthConfig, UserInfo, LoginResponse, TokenVerifyResponse, UpdateProfileRequest } from '../types'\nimport type { RoleInfo } from '../permissions'\n\ninterface UserResponse {\n id: number\n username: string\n shortname: string | null\n email: string | null\n role: string\n role_obj?: RoleInfo | null\n is_active: boolean\n}\n\ninterface RefreshResponse {\n access_token: string\n expires_in: number\n token_type: string\n}\n\n// Token refresh configuration\nconst TOKEN_REFRESH_MARGIN_MS = 5 * 60 * 1000 // Refresh 5 minutes before expiry\nconst TOKEN_REFRESH_CHECK_INTERVAL_MS = 60 * 1000 // Check every minute\n\n/**\n * Authentication composable with automatic token refresh.\n *\n * Features:\n * - Automatic token refresh before expiration\n * - Login/logout/register functionality\n * - Token verification on startup\n * - User profile management\n *\n * @example\n * ```typescript\n * const { login, logout, isAuthenticated, user } = useAuth()\n *\n * // Login\n * const success = await login('username', 'password')\n *\n * // Automatic refresh is enabled by default\n * // Tokens are refreshed 5 minutes before expiration\n * ```\n */\nexport interface UseAuthReturn {\n login: (username: string, password: string) => Promise<boolean>\n logout: () => void\n register: (username: string, password: string, email?: string) => Promise<boolean>\n verifyToken: () => Promise<boolean>\n fetchAuthConfig: () => Promise<AuthConfig>\n initializeAuth: () => Promise<void>\n getCurrentUser: () => Promise<UserInfo | null>\n getAuthHeader: () => Record<string, string>\n updateProfile: (data: { email?: string; shortname?: string; currentPassword?: string; newPassword?: string }) => Promise<{ success: boolean; error?: string }>\n refreshToken: () => Promise<boolean>\n isRefreshing: Ref<boolean>\n}\n\n// Module-level singletons to prevent duplicate refresh requests and timers\n// across multiple useAuth() instances\nlet _refreshPromise: Promise<boolean> | null = null\nlet _refreshTimerId: number | null = null\nlet _mountedConsumerCount = 0\n\n/** @internal Reset module-level state — only for use in tests. */\nexport function _resetAuthStateForTesting(): void {\n _refreshPromise = null\n if (_refreshTimerId !== null) {\n clearTimeout(_refreshTimerId)\n _refreshTimerId = null\n }\n _mountedConsumerCount = 0\n}\n\n/** Manages authentication state with login/logout/register and automatic JWT token refresh. */\nexport function useAuth(): UseAuthReturn {\n const authStore = useAuthStore()\n const settingsStore = useSettingsStore()\n\n const isRefreshing = ref(false)\n\n function getApiBaseUrl(): string {\n return settingsStore.getApiBaseUrl()\n }\n\n async function fetchAuthConfig(): Promise<AuthConfig> {\n try {\n const response = await axios.get<{\n auth_required: boolean\n passkey_enabled: boolean\n passkey_registered?: boolean\n registration_enabled?: boolean\n database_mode?: string\n access?: {\n experiment_visibility_mode?: 'open' | 'restricted'\n experimentVisibilityMode?: 'open' | 'restricted'\n }\n }>(`${getApiBaseUrl()}/setup/config/public`)\n\n const config: AuthConfig = {\n authRequired: response.data.auth_required,\n passkeyEnabled: response.data.passkey_enabled,\n passkeyRegistered: response.data.passkey_registered ?? false,\n registrationEnabled: response.data.registration_enabled ?? false,\n databaseMode: response.data.database_mode ?? 'none',\n experimentVisibilityMode:\n response.data.access?.experiment_visibility_mode\n ?? response.data.access?.experimentVisibilityMode\n ?? 'open',\n }\n\n authStore.setAuthConfig(config)\n return config\n } catch (error) {\n console.error('Failed to fetch auth config:', error)\n return {\n authRequired: false,\n passkeyEnabled: false,\n passkeyRegistered: false,\n registrationEnabled: false,\n databaseMode: 'none',\n experimentVisibilityMode: 'open',\n }\n }\n }\n\n async function login(username: string, password: string): Promise<boolean> {\n authStore.setLoading(true)\n authStore.setError(null)\n\n try {\n const response = await axios.post<LoginResponse>(\n `${getApiBaseUrl()}/auth/login`,\n { username, password }\n )\n\n authStore.setToken(response.data.access_token, response.data.expires_in)\n authStore.setUsername(username)\n\n await getCurrentUser()\n\n // Start auto-refresh after successful login\n scheduleTokenRefresh()\n\n return true\n } catch (error) {\n if (axios.isAxiosError(error) && error.response) {\n authStore.setError(error.response.data.detail || 'Login failed')\n } else {\n authStore.setError('Network error. Please try again.')\n }\n return false\n } finally {\n authStore.setLoading(false)\n }\n }\n\n async function register(username: string, password: string, email?: string): Promise<boolean> {\n authStore.setLoading(true)\n authStore.setError(null)\n\n try {\n await axios.post<UserResponse>(\n `${getApiBaseUrl()}/users/register`,\n { username, password, email }\n )\n\n return await login(username, password)\n } catch (error) {\n if (axios.isAxiosError(error) && error.response) {\n authStore.setError(error.response.data.detail || 'Registration failed')\n } else {\n authStore.setError('Network error. Please try again.')\n }\n return false\n } finally {\n authStore.setLoading(false)\n }\n }\n\n async function getCurrentUser(): Promise<UserInfo | null> {\n if (!authStore.token) {\n return null\n }\n\n try {\n const response = await axios.get<UserResponse>(\n `${getApiBaseUrl()}/users/me`,\n { headers: getAuthHeader() }\n )\n\n const userInfo: UserInfo = {\n id: response.data.id,\n username: response.data.username,\n shortname: response.data.shortname,\n email: response.data.email,\n role: response.data.role,\n roleObj: response.data.role_obj ?? null,\n isActive: response.data.is_active,\n }\n\n authStore.setUserInfo(userInfo)\n return userInfo\n } catch {\n return null\n }\n }\n\n async function verifyToken(): Promise<boolean> {\n if (!authStore.token) {\n return false\n }\n\n try {\n const response = await axios.get<TokenVerifyResponse>(\n `${getApiBaseUrl()}/auth/verify`,\n {\n headers: {\n Authorization: `Bearer ${authStore.token}`,\n },\n }\n )\n\n if (response.data.valid && response.data.username) {\n authStore.setUsername(response.data.username)\n return true\n }\n\n authStore.clearToken()\n return false\n } catch {\n authStore.clearToken()\n return false\n }\n }\n\n /**\n * Refresh the authentication token.\n * Called automatically before token expiration.\n * Uses promise caching to prevent concurrent refresh requests.\n */\n async function refreshToken(): Promise<boolean> {\n if (!authStore.token) return false\n if (_refreshPromise) return _refreshPromise\n\n _refreshPromise = (async () => {\n isRefreshing.value = true\n\n try {\n const response = await axios.post<RefreshResponse>(\n `${getApiBaseUrl()}/auth/refresh`,\n {},\n { headers: getAuthHeader() }\n )\n\n authStore.setToken(response.data.access_token, response.data.expires_in)\n\n // Reschedule next refresh\n scheduleTokenRefresh()\n\n return true\n } catch (error) {\n // If refresh fails, the token may have been revoked\n // Clear auth state and let user re-login\n if (axios.isAxiosError(error) && error.response?.status === 401) {\n console.warn('[Auth] Token refresh failed - session expired')\n authStore.clearToken()\n stopTokenRefresh()\n }\n return false\n } finally {\n isRefreshing.value = false\n _refreshPromise = null\n }\n })()\n\n return _refreshPromise\n }\n\n /**\n * Schedule automatic token refresh before expiration.\n */\n function scheduleTokenRefresh(): void {\n // Clear any existing timer\n stopTokenRefresh()\n\n if (!authStore.tokenExpires) {\n return\n }\n\n const expiresAt = authStore.tokenExpires.getTime()\n const refreshAt = expiresAt - TOKEN_REFRESH_MARGIN_MS\n const now = Date.now()\n\n if (refreshAt <= now) {\n // Token is already close to expiring or expired, refresh now\n refreshToken()\n return\n }\n\n // Schedule refresh\n const delay = refreshAt - now\n _refreshTimerId = window.setTimeout(() => {\n refreshToken()\n }, delay)\n }\n\n /**\n * Stop automatic token refresh.\n */\n function stopTokenRefresh(): void {\n if (_refreshTimerId !== null) {\n window.clearTimeout(_refreshTimerId)\n _refreshTimerId = null\n }\n }\n\n /**\n * Check if token needs refresh and refresh if necessary.\n * Called periodically as a safety net.\n */\n function checkAndRefreshIfNeeded(): void {\n if (!authStore.token || !authStore.tokenExpires) {\n return\n }\n\n const expiresAt = authStore.tokenExpires.getTime()\n const refreshAt = expiresAt - TOKEN_REFRESH_MARGIN_MS\n const now = Date.now()\n\n if (now >= refreshAt) {\n refreshToken()\n }\n }\n\n async function initializeAuth(): Promise<void> {\n authStore.initialize()\n await fetchAuthConfig()\n\n if (authStore.token) {\n const valid = await verifyToken()\n if (valid) {\n await getCurrentUser()\n // Start auto-refresh for existing session\n scheduleTokenRefresh()\n }\n }\n }\n\n function logout(): void {\n stopTokenRefresh()\n authStore.logout()\n }\n\n function getAuthHeader(): Record<string, string> {\n if (authStore.token) {\n return { Authorization: `Bearer ${authStore.token}` }\n }\n return {}\n }\n\n async function updateProfile(data: {\n email?: string\n shortname?: string\n currentPassword?: string\n newPassword?: string\n }): Promise<{ success: boolean; error?: string }> {\n if (!authStore.token) {\n return { success: false, error: 'Not authenticated' }\n }\n\n try {\n const requestData: UpdateProfileRequest = {}\n if (data.email !== undefined) requestData.email = data.email\n if (data.shortname !== undefined) requestData.shortname = data.shortname\n if (data.currentPassword) requestData.current_password = data.currentPassword\n if (data.newPassword) requestData.new_password = data.newPassword\n\n const response = await axios.put<UserResponse>(\n `${getApiBaseUrl()}/users/me`,\n requestData,\n { headers: getAuthHeader() }\n )\n\n const userInfo: UserInfo = {\n id: response.data.id,\n username: response.data.username,\n shortname: response.data.shortname,\n email: response.data.email,\n role: response.data.role,\n roleObj: response.data.role_obj ?? null,\n isActive: response.data.is_active,\n }\n authStore.setUserInfo(userInfo)\n\n return { success: true }\n } catch (error) {\n if (axios.isAxiosError(error) && error.response) {\n return { success: false, error: error.response.data.detail || 'Update failed' }\n }\n return { success: false, error: 'Network error. Please try again.' }\n }\n }\n\n // Set up periodic check as safety net (only inside component setup)\n let checkInterval: number | null = null\n\n if (getCurrentInstance()) {\n onMounted(() => {\n _mountedConsumerCount += 1\n checkInterval = window.setInterval(checkAndRefreshIfNeeded, TOKEN_REFRESH_CHECK_INTERVAL_MS)\n })\n\n onUnmounted(() => {\n if (checkInterval !== null) {\n window.clearInterval(checkInterval)\n checkInterval = null\n }\n\n _mountedConsumerCount = Math.max(0, _mountedConsumerCount - 1)\n if (_mountedConsumerCount === 0) {\n stopTokenRefresh()\n }\n })\n\n // Watch for token changes to reschedule refresh\n watch(\n () => authStore.tokenExpires,\n (newExpires) => {\n if (newExpires) {\n scheduleTokenRefresh()\n } else {\n stopTokenRefresh()\n }\n }\n )\n }\n\n return {\n // Core auth methods\n login,\n logout,\n register,\n verifyToken,\n fetchAuthConfig,\n initializeAuth,\n getCurrentUser,\n getAuthHeader,\n updateProfile,\n\n // Token refresh\n refreshToken,\n isRefreshing,\n }\n}\n","import axios from 'axios'\nimport { useAuthStore } from '../stores/auth'\nimport { useSettingsStore } from '../stores/settings'\nimport type { CredentialInfo } from '../types'\n\n// Lazy-load @simplewebauthn/browser so plugins that never call usePasskey\n// don't need the optional peer dep installed (avoids build failures).\nasync function loadWebAuthn() {\n try {\n return await import('@simplewebauthn/browser')\n } catch {\n throw new Error(\n '@simplewebauthn/browser is required for passkey support. Install it: bun add @simplewebauthn/browser',\n )\n }\n}\n\ninterface PasskeyLoginResponse {\n access_token: string\n token_type: string\n expires_in: number\n}\n\n/** Registers and authenticates passkeys using WebAuthn, lazily loading the browser dependency. */\nexport function usePasskey() {\n const authStore = useAuthStore()\n const settingsStore = useSettingsStore()\n\n function getApiBaseUrl(): string {\n return settingsStore.getApiBaseUrl()\n }\n\n async function isSupported(): Promise<boolean> {\n try {\n const { browserSupportsWebAuthn } = await loadWebAuthn()\n return browserSupportsWebAuthn()\n } catch {\n return false\n }\n }\n\n async function registerPasskey(deviceName?: string): Promise<boolean> {\n const webauthn = await loadWebAuthn()\n if (!webauthn.browserSupportsWebAuthn()) {\n authStore.setError('WebAuthn is not supported in this browser')\n return false\n }\n\n authStore.setLoading(true)\n authStore.setError(null)\n\n try {\n const optionsResponse = await axios.get<{ options: string }>(\n `${getApiBaseUrl()}/auth/passkey/register/options`,\n {\n headers: { Authorization: `Bearer ${authStore.token}` },\n withCredentials: true,\n }\n )\n\n const options = JSON.parse(optionsResponse.data.options)\n\n const credential = await webauthn.startRegistration(options)\n\n await axios.post(\n `${getApiBaseUrl()}/auth/passkey/register/verify`,\n {\n credential: JSON.stringify(credential),\n device_name: deviceName,\n },\n {\n headers: { Authorization: `Bearer ${authStore.token}` },\n withCredentials: true,\n }\n )\n\n authStore.setAuthConfig({\n ...authStore.authConfig,\n passkeyRegistered: true,\n })\n\n return true\n } catch (error) {\n if (axios.isAxiosError(error) && error.response) {\n authStore.setError(error.response.data.detail || 'Passkey registration failed')\n } else if (error instanceof Error) {\n if (error.name === 'NotAllowedError') {\n authStore.setError('Registration was cancelled or timed out')\n } else if (error.name === 'InvalidStateError') {\n authStore.setError('This authenticator is already registered')\n } else {\n authStore.setError(error.message)\n }\n } else {\n authStore.setError('Passkey registration failed')\n }\n return false\n } finally {\n authStore.setLoading(false)\n }\n }\n\n async function loginWithPasskey(): Promise<boolean> {\n const webauthn = await loadWebAuthn()\n if (!webauthn.browserSupportsWebAuthn()) {\n authStore.setError('WebAuthn is not supported in this browser')\n return false\n }\n\n authStore.setLoading(true)\n authStore.setError(null)\n\n try {\n const optionsResponse = await axios.get<{ options: string }>(\n `${getApiBaseUrl()}/auth/passkey/login/options`,\n { withCredentials: true }\n )\n\n const options = JSON.parse(optionsResponse.data.options)\n\n const credential = await webauthn.startAuthentication(options)\n\n const response = await axios.post<PasskeyLoginResponse>(\n `${getApiBaseUrl()}/auth/passkey/login/verify`,\n { credential: JSON.stringify(credential) },\n { withCredentials: true }\n )\n\n authStore.setToken(response.data.access_token, response.data.expires_in)\n\n return true\n } catch (error) {\n if (axios.isAxiosError(error) && error.response) {\n if (error.response.status === 404) {\n authStore.setError('No passkeys registered. Please login with password first.')\n } else {\n authStore.setError(error.response.data.detail || 'Passkey login failed')\n }\n } else if (error instanceof Error) {\n if (error.name === 'NotAllowedError') {\n authStore.setError('Authentication was cancelled or timed out')\n } else {\n authStore.setError(error.message)\n }\n } else {\n authStore.setError('Passkey login failed')\n }\n return false\n } finally {\n authStore.setLoading(false)\n }\n }\n\n async function listCredentials(): Promise<CredentialInfo[]> {\n try {\n const response = await axios.get<{ credentials: CredentialInfo[] }>(\n `${getApiBaseUrl()}/auth/passkey/credentials`,\n {\n headers: { Authorization: `Bearer ${authStore.token}` },\n }\n )\n return response.data.credentials\n } catch {\n return []\n }\n }\n\n async function deleteCredential(credentialId: string): Promise<boolean> {\n try {\n await axios.delete(\n `${getApiBaseUrl()}/auth/passkey/credentials/${encodeURIComponent(credentialId)}`,\n {\n headers: { Authorization: `Bearer ${authStore.token}` },\n }\n )\n\n const remaining = await listCredentials()\n if (remaining.length === 0) {\n authStore.setAuthConfig({\n ...authStore.authConfig,\n passkeyRegistered: false,\n })\n }\n\n return true\n } catch {\n return false\n }\n }\n\n async function deleteAllCredentials(): Promise<boolean> {\n try {\n await axios.delete(`${getApiBaseUrl()}/auth/passkey/credentials`, {\n headers: { Authorization: `Bearer ${authStore.token}` },\n })\n\n authStore.setAuthConfig({\n ...authStore.authConfig,\n passkeyRegistered: false,\n })\n\n return true\n } catch {\n return false\n }\n }\n\n return {\n isSupported,\n registerPasskey,\n loginWithPasskey,\n listCredentials,\n deleteCredential,\n deleteAllCredentials,\n }\n}\n","import { getInjectedPlatformContext } from './platformContextHelpers'\n\nfunction normalizePluginRoutePrefix(prefix: string | undefined): string | undefined {\n const candidate = prefix?.trim()\n if (!candidate) return undefined\n\n const path = candidate.split('/').filter(Boolean).join('/')\n return path ? `/${path}/` : '/'\n}\n\n/**\n * Resolve the Vue Router base for a plugin frontend.\n *\n * Integrated plugins use the platform-injected mount prefix. Standalone and\n * development builds retain the caller's Vite base unchanged.\n */\nexport function resolvePluginFrontendBase(fallbackBase: string = '/'): string {\n const context = getInjectedPlatformContext()\n if (!context?.isIntegrated) return fallbackBase\n\n return normalizePluginRoutePrefix(context.plugin?.route_prefix) ?? fallbackBase\n}\n","import { ref, computed, type Ref, type ComputedRef } from 'vue'\n\n/**\n * Error type for async operations.\n */\nexport interface AsyncError {\n message: string\n code?: string\n details?: Record<string, unknown>\n originalError?: unknown\n}\n\n/**\n * State of an async operation.\n */\nexport type AsyncState = 'idle' | 'loading' | 'success' | 'error'\n\n/**\n * Return type for useAsync composable.\n */\nexport interface UseAsyncReturn<T> {\n // Data\n data: Ref<T | null>\n error: Ref<AsyncError | null>\n\n // State\n state: Ref<AsyncState>\n isIdle: ComputedRef<boolean>\n isLoading: ComputedRef<boolean>\n isSuccess: ComputedRef<boolean>\n isError: ComputedRef<boolean>\n\n // Methods\n execute: (...args: unknown[]) => Promise<T | null>\n reset: () => void\n setData: (data: T | null) => void\n setError: (error: AsyncError | null) => void\n}\n\n/**\n * Options for useAsync.\n */\nexport interface UseAsyncOptions<T> {\n // Initial data value\n initialData?: T | null\n\n // Whether to run immediately on creation\n immediate?: boolean\n\n // Arguments for immediate execution\n immediateArgs?: unknown[]\n\n // Transform error into AsyncError\n transformError?: (error: unknown) => AsyncError\n\n // Called on success\n onSuccess?: (data: T) => void\n\n // Called on error\n onError?: (error: AsyncError) => void\n\n // Reset data on new execution\n resetOnExecute?: boolean\n}\n\n/**\n * Default error transformer.\n */\nfunction defaultTransformError(error: unknown): AsyncError {\n if (error instanceof Error) {\n return {\n message: error.message,\n originalError: error,\n }\n }\n\n if (typeof error === 'object' && error !== null) {\n const errorObj = error as Record<string, unknown>\n\n // Handle Axios-like errors\n if ('response' in errorObj && errorObj.response) {\n const response = errorObj.response as Record<string, unknown>\n const data = response.data as Record<string, unknown> | undefined\n\n return {\n message: (data?.detail as string) || (data?.message as string) || 'Request failed',\n code: String(response.status),\n details: data,\n originalError: error,\n }\n }\n\n // Handle generic error objects\n return {\n message: (errorObj.message as string) || 'Unknown error',\n code: errorObj.code as string | undefined,\n details: errorObj,\n originalError: error,\n }\n }\n\n return {\n message: String(error),\n originalError: error,\n }\n}\n\n/**\n * Composable for managing async operation state.\n *\n * Provides standardized loading, error, and success state management\n * for any async function.\n *\n * @param asyncFn - The async function to wrap\n * @param options - Configuration options\n *\n * @example\n * ```typescript\n * // Basic usage\n * const { data, isLoading, error, execute } = useAsync(\n * async (id: string) => {\n * const response = await api.get(`/users/${id}`)\n * return response.data\n * }\n * )\n *\n * // Execute the function\n * await execute('user-123')\n *\n * // In template\n * <div v-if=\"isLoading\">Loading...</div>\n * <div v-else-if=\"error\">{{ error.message }}</div>\n * <div v-else-if=\"data\">{{ data.name }}</div>\n * ```\n *\n * @example\n * ```typescript\n * // With options\n * const { data, execute } = useAsync(\n * fetchUser,\n * {\n * immediate: true,\n * immediateArgs: ['default-user'],\n * onSuccess: (user) => console.log('Fetched:', user.name),\n * onError: (error) => toast.error(error.message),\n * }\n * )\n * ```\n *\n * @example\n * ```typescript\n * // Form submission\n * const { isLoading, error, execute: submit } = useAsync(\n * async (formData: FormData) => {\n * await api.post('/submit', formData)\n * },\n * {\n * onSuccess: () => {\n * toast.success('Submitted!')\n * router.push('/success')\n * },\n * }\n * )\n *\n * const handleSubmit = () => submit(new FormData(formRef.value))\n * ```\n */\n/**\n * Wraps an async function with reactive loading, error, and success state plus optional auto-execute.\n *\n * @deprecated Unused by the MINT platform and scheduled for removal in MINT 1.3; use `useRequestSyncState()` instead.\n */\nexport function useAsync<T>(\n asyncFn: (...args: unknown[]) => Promise<T>,\n options: UseAsyncOptions<T> = {}\n): UseAsyncReturn<T> {\n const {\n initialData = null,\n immediate = false,\n immediateArgs = [],\n transformError = defaultTransformError,\n onSuccess,\n onError,\n resetOnExecute = false,\n } = options\n\n // State\n const data = ref<T | null>(initialData) as Ref<T | null>\n const error = ref<AsyncError | null>(null)\n const state = ref<AsyncState>('idle')\n\n // Computed state helpers\n const isIdle = computed(() => state.value === 'idle')\n const isLoading = computed(() => state.value === 'loading')\n const isSuccess = computed(() => state.value === 'success')\n const isError = computed(() => state.value === 'error')\n\n // Execute the async function\n async function execute(...args: unknown[]): Promise<T | null> {\n state.value = 'loading'\n error.value = null\n\n if (resetOnExecute) {\n data.value = null\n }\n\n try {\n const result = await asyncFn(...args)\n data.value = result\n state.value = 'success'\n onSuccess?.(result)\n return result\n } catch (e) {\n const asyncError = transformError(e)\n error.value = asyncError\n state.value = 'error'\n onError?.(asyncError)\n return null\n }\n }\n\n // Reset to initial state\n function reset(): void {\n data.value = initialData\n error.value = null\n state.value = 'idle'\n }\n\n // Manual data setter\n function setData(newData: T | null): void {\n data.value = newData\n if (newData !== null) {\n state.value = 'success'\n error.value = null\n }\n }\n\n // Manual error setter\n function setError(newError: AsyncError | null): void {\n error.value = newError\n if (newError !== null) {\n state.value = 'error'\n }\n }\n\n // Execute immediately if requested\n if (immediate) {\n execute(...immediateArgs)\n }\n\n return {\n data,\n error,\n state,\n isIdle,\n isLoading,\n isSuccess,\n isError,\n execute,\n reset,\n setData,\n setError,\n }\n}\n\n/**\n * Create a batch of async operations that can be executed in parallel.\n *\n * @example\n * ```typescript\n * const { results, isLoading, execute } = useAsyncBatch([\n * () => fetchUser(userId),\n * () => fetchPosts(userId),\n * () => fetchComments(userId),\n * ])\n *\n * await execute()\n * // results.value = [user, posts, comments]\n * ```\n */\nexport function useAsyncBatch<T extends readonly (() => Promise<unknown>)[]>(\n asyncFns: T\n): {\n results: Ref<{ [K in keyof T]: Awaited<ReturnType<T[K]>> | null }>\n errors: Ref<(AsyncError | null)[]>\n isLoading: Ref<boolean>\n execute: () => Promise<void>\n reset: () => void\n} {\n type Results = { [K in keyof T]: Awaited<ReturnType<T[K]>> | null }\n\n const results = ref<Results>(asyncFns.map(() => null) as unknown as Results) as Ref<Results>\n const errors = ref<(AsyncError | null)[]>(asyncFns.map(() => null))\n const isLoading = ref(false)\n\n async function execute(): Promise<void> {\n isLoading.value = true\n errors.value = asyncFns.map(() => null)\n\n const promises = asyncFns.map(async (fn, index) => {\n try {\n const result = await fn()\n ;(results.value as unknown[])[index] = result\n } catch (e) {\n errors.value[index] = defaultTransformError(e)\n ;(results.value as unknown[])[index] = null\n }\n })\n\n await Promise.all(promises)\n isLoading.value = false\n }\n\n function reset(): void {\n results.value = asyncFns.map(() => null) as unknown as Results\n errors.value = asyncFns.map(() => null)\n isLoading.value = false\n }\n\n return {\n results,\n errors,\n isLoading,\n execute,\n reset,\n }\n}\n","import { ref, computed, onMounted, type Ref, type ComputedRef } from 'vue'\nimport { useApi } from './useApi'\nimport { usePlatformContext } from './usePlatformContext'\nimport { getInjectedPlatformContext } from './platformContextHelpers'\nimport { useRequestSyncState } from './useRequestSyncState'\n\nconst PLATFORM_OWNED_SETTINGS_KEY = 'allowed_experiment_types'\n\nfunction cloneConfig(config: Record<string, unknown>): Record<string, unknown> {\n return JSON.parse(JSON.stringify(config)) as Record<string, unknown>\n}\n\nfunction hasOwnConfig(config: Record<string, unknown>, key: string): boolean {\n return Object.prototype.hasOwnProperty.call(config, key)\n}\n\nfunction changedTopLevelKeys(\n current: Record<string, unknown>,\n saved: Record<string, unknown>,\n): Set<string> {\n return new Set(\n [...new Set([...Object.keys(current), ...Object.keys(saved)])].filter(\n key => JSON.stringify(current[key]) !== JSON.stringify(saved[key]),\n ),\n )\n}\n\nfunction topLevelConfigPatch(\n current: Record<string, unknown>,\n keys: Iterable<string>,\n): Record<string, unknown> {\n return Object.fromEntries(\n [...keys].map(key => [\n key,\n hasOwnConfig(current, key) ? current[key] : null,\n ]),\n )\n}\n\nfunction platformOwnedConfigPatch(config: Record<string, unknown>): Record<string, unknown> {\n return {\n [PLATFORM_OWNED_SETTINGS_KEY]: hasOwnConfig(config, PLATFORM_OWNED_SETTINGS_KEY)\n ? config[PLATFORM_OWNED_SETTINGS_KEY]\n : null,\n }\n}\n\nfunction responseConfigPayload(response: {\n config?: Record<string, unknown>\n settings?: Record<string, unknown>\n}): Record<string, unknown> {\n return response.config ?? response.settings ?? {}\n}\n\nexport interface UsePluginConfigReturn {\n /** Editable plugin configuration values. */\n config: Ref<Record<string, unknown>>\n /** Whether the config is currently loading. */\n isLoading: Ref<boolean>\n /** Whether the config is currently saving. */\n isSaving: Ref<boolean>\n /** Error message from the last failed operation, or null. */\n error: Ref<string | null>\n /** Timestamp of the last successful load, or null. */\n lastLoadedAt: Ref<Date | null>\n /** Timestamp of the last successful save, or null. */\n lastSavedAt: Ref<Date | null>\n /** Whether local config differs from the last loaded or saved snapshot. */\n isDirty: ComputedRef<boolean>\n /** Load plugin configuration from the platform. */\n load: () => Promise<void>\n /** Save plugin configuration to the platform. */\n save: () => Promise<boolean>\n /** Restore the last loaded or saved configuration snapshot. */\n reset: () => void\n}\n\n/**\n * @deprecated Unused by the MINT platform and scheduled for removal in MINT 1.3; use `usePluginSettings()` for typed plugin settings.\n */\nexport function usePluginConfig(pluginName?: string): UsePluginConfigReturn {\n const injectedContext = getInjectedPlatformContext()\n const { plugin } = usePlatformContext()\n const platformApi = useApi()\n const pluginApi = useApi({\n baseUrl: injectedContext?.plugin?.api_prefix ?? plugin.value?.api_prefix,\n })\n\n const resolvedName = computed(\n () => pluginName ?? plugin.value?.name ?? injectedContext?.plugin?.name ?? '',\n )\n const usesPluginSettingsApi = computed(() => {\n const currentPlugin = injectedContext?.plugin ?? plugin.value\n return currentPlugin?.settings_api === 'plugin'\n && resolvedName.value === currentPlugin.name\n })\n\n const config = ref<Record<string, unknown>>({})\n const savedConfig = ref<Record<string, unknown>>({})\n const revision = ref<string | null>(null)\n const request = useRequestSyncState('Plugin config request failed.')\n const isLoading = ref(false)\n const isSaving = ref(false)\n const error = request.error\n const lastLoadedAt = request.lastLoadedAt\n const lastSavedAt = request.lastSavedAt\n\n const isDirty = computed(() => {\n return JSON.stringify(config.value) !== JSON.stringify(savedConfig.value)\n })\n\n async function load(): Promise<void> {\n const name = resolvedName.value\n if (!name) return\n\n isLoading.value = true\n try {\n const response = usesPluginSettingsApi.value\n ? await request.run(\n () => pluginApi.get<{\n settings: Record<string, unknown>\n mode?: string\n revision?: string\n }>('/settings'),\n { success: 'load', errorMessage: 'Failed to load plugin config' },\n )\n : await request.run(\n () => platformApi.get<{\n plugin_name: string\n config: Record<string, unknown>\n revision?: string\n }>(\n `/plugins/${encodeURIComponent(name)}/config`,\n ),\n { success: 'load', errorMessage: 'Failed to load plugin config' },\n )\n const responseConfig = responseConfigPayload(response)\n config.value = cloneConfig(responseConfig)\n savedConfig.value = cloneConfig(responseConfig)\n revision.value = response.revision ?? null\n } catch {\n // Error state is handled by request.run().\n } finally {\n isLoading.value = false\n }\n }\n\n async function save(): Promise<boolean> {\n const name = resolvedName.value\n if (!name) return false\n\n isSaving.value = true\n try {\n const payload = cloneConfig(config.value)\n let response: {\n plugin_name?: string\n config?: Record<string, unknown>\n settings?: Record<string, unknown>\n mode?: string\n revision?: string\n } | undefined\n let nextRevision = revision.value\n\n if (usesPluginSettingsApi.value) {\n response = await request.run(\n () => pluginApi.put<{\n settings: Record<string, unknown>\n mode?: string\n revision?: string\n }>(\n '/settings',\n payload,\n revision.value\n ? { headers: { 'If-Match': `\"${revision.value}\"` } }\n : undefined,\n ),\n { success: 'save', errorMessage: 'Failed to save plugin config' },\n )\n nextRevision = response.revision ?? nextRevision\n } else {\n const dirtyKeys = changedTopLevelKeys(payload, savedConfig.value)\n const platformOwnedChanged = dirtyKeys.has(PLATFORM_OWNED_SETTINGS_KEY)\n const typedKeys = [...dirtyKeys].filter(\n key => key !== PLATFORM_OWNED_SETTINGS_KEY,\n )\n\n if (typedKeys.length) {\n response = await request.run(\n () => platformApi.patch<{\n plugin_name: string\n config: Record<string, unknown>\n revision?: string\n }>(\n `/plugins/${encodeURIComponent(name)}/config`,\n { config: topLevelConfigPatch(payload, typedKeys) },\n ),\n { success: 'save', errorMessage: 'Failed to save plugin config' },\n )\n nextRevision = response.revision ?? nextRevision\n }\n\n if (platformOwnedChanged) {\n response = await request.run(\n () => platformApi.patch<{\n plugin_name: string\n config: Record<string, unknown>\n revision?: string\n }>(\n `/plugins/${encodeURIComponent(name)}/config`,\n { config: platformOwnedConfigPatch(payload) },\n ),\n { success: 'save', errorMessage: 'Failed to save plugin config' },\n )\n nextRevision = response.revision ?? nextRevision\n }\n }\n\n if (!response) return true\n const responseConfig = responseConfigPayload(response)\n config.value = cloneConfig(responseConfig)\n savedConfig.value = cloneConfig(responseConfig)\n revision.value = response.revision ?? nextRevision\n return true\n } catch {\n return false\n } finally {\n isSaving.value = false\n }\n }\n\n function reset(): void {\n config.value = cloneConfig(savedConfig.value)\n request.clearError()\n }\n\n onMounted(() => {\n load()\n })\n\n return {\n config,\n isLoading,\n isSaving,\n error,\n lastLoadedAt,\n lastSavedAt,\n isDirty,\n load,\n save,\n reset,\n }\n}\n","import {\n computed,\n getCurrentScope,\n onScopeDispose,\n ref,\n shallowRef,\n toValue,\n watch,\n type ComputedRef,\n type MaybeRefOrGetter,\n type Ref,\n} from 'vue'\n\nimport type {\n FileBrowserSortKey,\n FileDirectoryListing,\n FileEntry,\n FilePathCrumb,\n FileSelection,\n ServerMount,\n} from '../types/fileBrowserTypes'\nimport { useApi } from './useApi'\nimport { getInjectedPlatformContext } from './platformContextHelpers'\nimport { useRequestSyncState } from './useRequestSyncState'\n\nexport interface UseFileBrowserOptions {\n /** Extensions the caller cares about; entries are flagged, never removed. */\n typeRules?: MaybeRefOrGetter<string[] | undefined>\n /** Mount to open first; defaults to the first available one. */\n initialMountId?: MaybeRefOrGetter<string | undefined>\n /** Override the platform API base URL (standalone plugin dev). */\n apiBaseUrl?: string\n}\n\nexport interface UseFileBrowserReturn {\n /** Every configured mount, offline ones included. */\n mounts: Ref<ServerMount[]>\n /** Mount the current listing belongs to. */\n mountId: Ref<string>\n /** Mount-relative path of the current listing. */\n path: Ref<string>\n /** Parent path, or null at a mount root. */\n parent: Ref<string | null>\n entries: Ref<FileEntry[]>\n breadcrumbs: Ref<FilePathCrumb[]>\n /** Directory size before any search filter. */\n totalCount: Ref<number | null>\n /** How many entries satisfy the type rules. */\n matchCount: Ref<number | null>\n /** How many rows this listing carries, after search and any cap. */\n shownCount: Ref<number | null>\n /** True when the server capped the listing. */\n truncated: Ref<boolean>\n search: Ref<string>\n sort: Ref<FileBrowserSortKey>\n /** Controlled selection, ready to bind to FileBrowserModal. */\n selected: Ref<FileSelection[]>\n isLoading: ComputedRef<boolean>\n error: Ref<string | null>\n /** Load the mount list and open the first available mount. */\n init: () => Promise<void>\n /** Open a directory, or a mount root when path is empty. */\n navigate: (location: { mount_id: string; path: string }) => Promise<void>\n /** Re-read the current directory. */\n refresh: () => Promise<void>\n /** Take the directory currently being viewed as the input. */\n selectCurrentFolder: () => void\n clear: () => void\n}\n\n/**\n * Drives FileBrowserModal against the platform's `/api/filesystem` routes.\n *\n * Requires the `filesystem.browse` permission and a deployment that declares\n * mounts; with none configured the routes are absent and `mounts` stays empty.\n */\nexport function useFileBrowser(options: UseFileBrowserOptions = {}): UseFileBrowserReturn {\n const injectedContext = getInjectedPlatformContext()\n const api = useApi({ baseUrl: options.apiBaseUrl ?? injectedContext?.platformApiUrl })\n const sync = useRequestSyncState('Could not read the server mounts.')\n\n const mounts = ref<ServerMount[]>([])\n const mountId = shallowRef('')\n const path = shallowRef('')\n const parent = ref<string | null>(null)\n const entries = ref<FileEntry[]>([])\n const breadcrumbs = ref<FilePathCrumb[]>([])\n const totalCount = ref<number | null>(null)\n const matchCount = ref<number | null>(null)\n const shownCount = ref<number | null>(null)\n const truncated = ref(false)\n const search = shallowRef('')\n const sort = shallowRef<FileBrowserSortKey>('name')\n const selected = ref<FileSelection[]>([])\n\n const mountsLoading = shallowRef(false)\n const listingLoading = shallowRef(false)\n const listingReady = shallowRef(false)\n const isLoading = computed(() => mountsLoading.value || listingLoading.value)\n let listToken = 0\n let mountsToken = 0\n let disposed = false\n let listingController: AbortController | undefined\n let mountsController: AbortController | undefined\n let searchTimer: ReturnType<typeof setTimeout> | undefined\n\n function resetListing(): void {\n listingReady.value = false\n entries.value = []\n breadcrumbs.value = []\n parent.value = null\n totalCount.value = null\n matchCount.value = null\n shownCount.value = null\n truncated.value = false\n }\n\n function typeRuleParams(): string {\n const rules = toValue(options.typeRules) ?? []\n return rules.map((rule) => `&type_rules=${encodeURIComponent(rule)}`).join('')\n }\n\n /** Prefer the API's own `detail` over axios's \"Request failed with status N\". */\n function describe(cause: unknown, fallback: string): string {\n const detail = (cause as { response?: { data?: { detail?: unknown } } })?.response?.data?.detail\n return typeof detail === 'string' && detail ? detail : sync.readErrorMessage(cause, fallback)\n }\n\n function fail(cause: unknown, fallback: string): void {\n sync.setError(new Error(describe(cause, fallback)), fallback)\n }\n\n function statusOf(cause: unknown): number | undefined {\n return (cause as { response?: { status?: number } })?.response?.status\n }\n\n async function loadMounts(): Promise<boolean> {\n const token = ++mountsToken\n mountsController?.abort()\n mountsController = new AbortController()\n mountsLoading.value = true\n try {\n const data = await api.get<{ mounts: ServerMount[] }>('/filesystem/mounts', {\n signal: mountsController.signal,\n })\n if (disposed || token !== mountsToken) return false\n mounts.value = data.mounts ?? []\n sync.clearError()\n sync.markLoaded()\n return true\n } catch (cause) {\n if (disposed || token !== mountsToken) return false\n // The platform only registers these routes once mounts are configured, so\n // a 404 means \"none declared\" — an empty sidebar, not a failure.\n if (statusOf(cause) === 404) {\n mounts.value = []\n sync.clearError()\n sync.markLoaded()\n return true\n }\n mounts.value = []\n fail(cause, 'Could not read the server mounts.')\n return false\n } finally {\n if (token === mountsToken) mountsLoading.value = false\n }\n }\n\n async function navigate(location: { mount_id: string; path: string }): Promise<void> {\n if (disposed || !location.mount_id) return\n clearTimeout(searchTimer)\n const token = ++listToken\n listingController?.abort()\n listingController = new AbortController()\n listingLoading.value = true\n mountId.value = location.mount_id\n path.value = location.path\n resetListing()\n sync.clearError()\n try {\n const query =\n `mount_id=${encodeURIComponent(location.mount_id)}` +\n `&path=${encodeURIComponent(location.path)}` +\n `&sort=${sort.value}` +\n (search.value ? `&search=${encodeURIComponent(search.value)}` : '') +\n typeRuleParams()\n const listing = await api.get<FileDirectoryListing>(`/filesystem/browse?${query}`, {\n signal: listingController.signal,\n })\n if (disposed || token !== listToken) return\n mountId.value = listing.mount_id\n path.value = listing.path\n parent.value = listing.parent ?? null\n entries.value = listing.entries ?? []\n breadcrumbs.value = listing.breadcrumbs ?? []\n totalCount.value = listing.total_count ?? null\n matchCount.value = listing.match_count ?? null\n shownCount.value = listing.shown_count ?? listing.entries?.length ?? null\n truncated.value = listing.truncated ?? false\n listingReady.value = true\n sync.clearError()\n sync.markLoaded()\n } catch (cause) {\n if (disposed || token !== listToken) return\n entries.value = []\n fail(cause, 'Could not read that folder.')\n } finally {\n if (token === listToken) listingLoading.value = false\n }\n }\n\n async function init(): Promise<void> {\n if (disposed) return\n const navigationToken = listToken\n if (!(await loadMounts()) || disposed || navigationToken !== listToken) return\n const preferred = toValue(options.initialMountId)\n // An offline mount is not navigable, so a remembered preference for one\n // falls through to the first reachable mount instead of opening on an error.\n const reachable = (mount: ServerMount): boolean => mount.available !== false\n const target =\n mounts.value.find((mount) => mount.id === preferred && reachable(mount)) ??\n mounts.value.find(reachable)\n if (target) await navigate({ mount_id: target.id, path: '' })\n else {\n mountId.value = ''\n path.value = ''\n resetListing()\n }\n }\n\n async function refresh(): Promise<void> {\n if (disposed) return\n if (mountId.value) await navigate({ mount_id: mountId.value, path: path.value })\n else await init()\n }\n\n function selectCurrentFolder(): void {\n if (!mountId.value || !listingReady.value || isLoading.value || sync.error.value) return\n const crumb = breadcrumbs.value[breadcrumbs.value.length - 1]\n const key = JSON.stringify([mountId.value, path.value])\n if (selected.value.some((item) => JSON.stringify([item.mount_id, item.path]) === key)) return\n selected.value = [\n ...selected.value,\n {\n mount_id: mountId.value,\n path: path.value,\n name: crumb?.label ?? path.value,\n kind: 'directory',\n child_count: totalCount.value,\n },\n ]\n }\n\n function clear(): void {\n selected.value = []\n }\n\n // Both controls are server-side, so they only take effect on a re-fetch.\n // Without these watchers the search box and sort button look live but are\n // inert until the user happens to navigate.\n watch(search, () => {\n if (!mountId.value) return\n clearTimeout(searchTimer)\n // Debounced: search changes on every keystroke.\n searchTimer = setTimeout(() => {\n void refresh()\n }, 250)\n })\n\n watch(sort, () => {\n if (mountId.value) void refresh()\n })\n\n watch(\n () => toValue(options.typeRules),\n () => {\n if (mountId.value) void refresh()\n },\n { deep: true },\n )\n\n if (getCurrentScope())\n onScopeDispose(() => {\n disposed = true\n ++listToken\n ++mountsToken\n clearTimeout(searchTimer)\n listingController?.abort()\n mountsController?.abort()\n })\n\n return {\n mounts,\n mountId,\n path,\n parent,\n entries,\n breadcrumbs,\n totalCount,\n matchCount,\n shownCount,\n truncated,\n search,\n sort,\n selected,\n isLoading,\n error: sync.error,\n init,\n navigate,\n refresh,\n selectCurrentFolder,\n clear,\n }\n}\n","import type { AnalysisArtifactTarget } from '../types/analysisArtifactTypes'\n\nconst EXPERIMENT_ID = 'experiment_id'\nconst ARTIFACT_PLUGIN_ID = 'artifact_plugin_id'\nconst ARTIFACT_KEY = 'artifact_key'\nconst ARTIFACT_ID = 'artifact_id'\n\nfunction parsePositiveInteger(value: string | null): number | undefined {\n if (value === null || !/^\\d+$/.test(value)) return undefined\n const parsed = Number(value)\n return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : undefined\n}\n\n/** Build the canonical query used to open one analysis artifact in a plugin. */\nexport function buildAnalysisArtifactTargetQuery(\n target: AnalysisArtifactTarget,\n): URLSearchParams {\n const query = new URLSearchParams()\n query.set(EXPERIMENT_ID, String(target.experimentId))\n query.set(ARTIFACT_PLUGIN_ID, target.artifactPluginId)\n query.set(ARTIFACT_KEY, target.artifactKey)\n if (target.artifactId !== undefined) {\n query.set(ARTIFACT_ID, String(target.artifactId))\n }\n return query\n}\n\n/** Parse a complete canonical target. Incomplete or invalid input is not guessed. */\nexport function parseAnalysisArtifactTarget(\n query: URLSearchParams,\n): AnalysisArtifactTarget | null {\n const experimentId = parsePositiveInteger(query.get(EXPERIMENT_ID))\n const artifactPluginId = query.get(ARTIFACT_PLUGIN_ID)?.trim()\n const artifactKey = query.get(ARTIFACT_KEY)?.trim()\n const rawArtifactId = query.get(ARTIFACT_ID)\n const artifactId = parsePositiveInteger(rawArtifactId)\n\n if (\n experimentId === undefined\n || !artifactPluginId\n || !artifactKey\n || (rawArtifactId !== null && artifactId === undefined)\n ) {\n return null\n }\n\n return {\n experimentId,\n artifactPluginId,\n artifactKey,\n ...(artifactId === undefined ? {} : { artifactId }),\n }\n}\n","import { computed, ref, type ComputedRef, type Ref } from 'vue'\n\nexport type CommandHistoryResult = void | Promise<void>\n\nexport interface CommandHistoryCommand {\n execute: () => CommandHistoryResult\n undo: () => CommandHistoryResult\n redo?: () => CommandHistoryResult\n description?: string\n}\n\nexport interface CommandHistoryExecuteOptions {\n skipExecute?: boolean\n}\n\nexport interface UseCommandHistoryOptions {\n maxDepth?: number\n}\n\nexport interface UseCommandHistoryReturn<TCommand extends CommandHistoryCommand = CommandHistoryCommand> {\n undoStack: Ref<TCommand[]>\n redoStack: Ref<TCommand[]>\n canUndo: ComputedRef<boolean>\n canRedo: ComputedRef<boolean>\n undoDescription: ComputedRef<string>\n redoDescription: ComputedRef<string>\n execute: (command: TCommand, options?: CommandHistoryExecuteOptions) => CommandHistoryResult\n push: (command: TCommand) => void\n undo: () => CommandHistoryResult\n redo: () => CommandHistoryResult\n clear: () => void\n}\n\n/**\n * Generic command-stack state for plugin editors with undo/redo controls.\n *\n * @deprecated Unused by the MINT platform and scheduled for removal in MINT 1.3; keep command stacks plugin-local.\n */\nexport function useCommandHistory<TCommand extends CommandHistoryCommand = CommandHistoryCommand>(\n options: UseCommandHistoryOptions = {},\n): UseCommandHistoryReturn<TCommand> {\n const maxDepth = Math.max(1, options.maxDepth ?? 50)\n const undoStack = ref<TCommand[]>([]) as Ref<TCommand[]>\n const redoStack = ref<TCommand[]>([]) as Ref<TCommand[]>\n\n const canUndo = computed(() => undoStack.value.length > 0)\n const canRedo = computed(() => redoStack.value.length > 0)\n const undoDescription = computed(() => undoStack.value[undoStack.value.length - 1]?.description ?? '')\n const redoDescription = computed(() => redoStack.value[redoStack.value.length - 1]?.description ?? '')\n\n function push(command: TCommand): void {\n undoStack.value = [...undoStack.value.slice(-(maxDepth - 1)), command]\n redoStack.value = []\n }\n\n function execute(\n command: TCommand,\n executeOptions: CommandHistoryExecuteOptions = {},\n ): CommandHistoryResult {\n if (executeOptions.skipExecute) {\n push(command)\n return\n }\n\n return afterMaybePromise(command.execute(), () => push(command))\n }\n\n function undo(): CommandHistoryResult {\n const command = undoStack.value[undoStack.value.length - 1]\n if (!command) return\n\n return afterMaybePromise(command.undo(), () => {\n undoStack.value = undoStack.value.slice(0, -1)\n redoStack.value = [...redoStack.value, command]\n })\n }\n\n function redo(): CommandHistoryResult {\n const command = redoStack.value[redoStack.value.length - 1]\n if (!command) return\n\n return afterMaybePromise((command.redo ?? command.execute)(), () => {\n redoStack.value = redoStack.value.slice(0, -1)\n undoStack.value = [...undoStack.value.slice(-(maxDepth - 1)), command]\n })\n }\n\n function clear(): void {\n undoStack.value = []\n redoStack.value = []\n }\n\n return {\n undoStack,\n redoStack,\n canUndo,\n canRedo,\n undoDescription,\n redoDescription,\n execute,\n push,\n undo,\n redo,\n clear,\n }\n}\n\nfunction afterMaybePromise(result: CommandHistoryResult, callback: () => void): CommandHistoryResult {\n if (isPromiseLike(result)) {\n return result.then(callback)\n }\n callback()\n}\n\nfunction isPromiseLike(value: unknown): value is Promise<void> {\n return !!value && typeof (value as { then?: unknown }).then === 'function'\n}\n","import { computed, ref, shallowRef, type ComputedRef, type Ref, type ShallowRef } from 'vue'\nimport { readErrorMessage } from '../utils/errors'\n\nexport interface OptimisticMutationContext<TVariables, TSnapshot> {\n variables: TVariables\n snapshot: TSnapshot | undefined\n}\n\nexport interface UseOptimisticMutationOptions<TVariables, TData, TSnapshot = unknown> {\n mutation: (variables: TVariables) => Promise<TData>\n snapshot?: (variables: TVariables) => TSnapshot\n apply?: (variables: TVariables, snapshot: TSnapshot | undefined) => void\n commit?: (data: TData, context: OptimisticMutationContext<TVariables, TSnapshot>) => void\n rollback?: (\n snapshot: TSnapshot | undefined,\n variables: TVariables,\n error: unknown,\n ) => void\n onSuccess?: (data: TData, context: OptimisticMutationContext<TVariables, TSnapshot>) => void\n onError?: (error: unknown, context: OptimisticMutationContext<TVariables, TSnapshot>) => void\n onSettled?: (context: OptimisticMutationContext<TVariables, TSnapshot>) => void\n readErrorMessage?: (error: unknown) => string\n}\n\nexport interface UseOptimisticMutationReturn<TVariables, TData, TSnapshot = unknown> {\n loading: ShallowRef<boolean>\n error: Ref<string | null>\n data: Ref<TData | null>\n lastSnapshot: Ref<TSnapshot | undefined>\n isIdle: ComputedRef<boolean>\n run: (variables: TVariables) => Promise<TData>\n clearError: () => void\n reset: () => void\n}\n\n/**\n * Run async mutations with optional optimistic local updates and rollback.\n *\n * @deprecated Unused by the MINT platform and scheduled for removal in MINT 1.3; use `useRequestSyncState()` instead.\n */\nexport function useOptimisticMutation<TVariables, TData, TSnapshot = unknown>(\n options: UseOptimisticMutationOptions<TVariables, TData, TSnapshot>,\n): UseOptimisticMutationReturn<TVariables, TData, TSnapshot> {\n const loading = shallowRef(false)\n const error = ref<string | null>(null)\n const data = ref<TData | null>(null) as Ref<TData | null>\n const lastSnapshot = ref<TSnapshot | undefined>(undefined) as Ref<TSnapshot | undefined>\n const isIdle = computed(() => !loading.value && data.value === null && error.value === null)\n\n function clearError(): void {\n error.value = null\n }\n\n function reset(): void {\n loading.value = false\n error.value = null\n data.value = null\n lastSnapshot.value = undefined\n }\n\n async function run(variables: TVariables): Promise<TData> {\n const snapshot = options.snapshot?.(variables)\n const context: OptimisticMutationContext<TVariables, TSnapshot> = { variables, snapshot }\n\n loading.value = true\n error.value = null\n lastSnapshot.value = snapshot\n options.apply?.(variables, snapshot)\n\n try {\n const result = await options.mutation(variables)\n data.value = result\n options.commit?.(result, context)\n options.onSuccess?.(result, context)\n return result\n } catch (err) {\n options.rollback?.(snapshot, variables, err)\n error.value = options.readErrorMessage?.(err) ?? readErrorMessage(err)\n options.onError?.(err, context)\n throw err\n } finally {\n loading.value = false\n options.onSettled?.(context)\n }\n }\n\n return {\n loading,\n error,\n data,\n lastSnapshot,\n isIdle,\n run,\n clearError,\n reset,\n }\n}\n","import { computed, ref, shallowRef, type ComputedRef, type Ref, type ShallowRef } from 'vue'\nimport { readErrorMessage } from '../utils/errors'\n\nexport type ResourceKey = string | number\n\nexport interface ResourceCrudAdapter<TItem, TCreate = Partial<TItem>, TUpdate = Partial<TItem>, TKey extends ResourceKey = ResourceKey> {\n list: () => Promise<TItem[]>\n create?: (payload: TCreate) => Promise<TItem>\n update?: (key: TKey, payload: TUpdate) => Promise<TItem>\n remove?: (key: TKey) => Promise<void>\n}\n\nexport interface UseResourceCrudOptions<\n TItem,\n TCreate = Partial<TItem>,\n TUpdate = Partial<TItem>,\n TKey extends ResourceKey = ResourceKey,\n> {\n adapter: ResourceCrudAdapter<TItem, TCreate, TUpdate, TKey>\n initialItems?: readonly TItem[]\n getKey?: (item: TItem) => TKey\n readErrorMessage?: (error: unknown) => string\n}\n\nexport interface UseResourceCrudReturn<TItem, TCreate, TUpdate, TKey extends ResourceKey> {\n items: Ref<TItem[]>\n loading: ShallowRef<boolean>\n saving: ShallowRef<boolean>\n deleting: ShallowRef<boolean>\n error: Ref<string | null>\n isBusy: ComputedRef<boolean>\n load: () => Promise<TItem[]>\n createItem: (payload: TCreate) => Promise<TItem>\n updateItem: (key: TKey, payload: TUpdate) => Promise<TItem>\n deleteItem: (keyOrItem: TKey | TItem) => Promise<void>\n setItems: (items: readonly TItem[]) => void\n upsertLocal: (item: TItem) => void\n removeLocal: (keyOrItem: TKey | TItem) => void\n clearError: () => void\n}\n\n/**\n * Common list/create/update/delete state wrapper for generated plugin clients.\n *\n * @deprecated Unused by the MINT platform and scheduled for removal in MINT 1.3; use `useGeneratedPluginClient()` instead.\n */\nexport function useResourceCrud<\n TItem,\n TCreate = Partial<TItem>,\n TUpdate = Partial<TItem>,\n TKey extends ResourceKey = ResourceKey,\n>(\n options: UseResourceCrudOptions<TItem, TCreate, TUpdate, TKey>,\n): UseResourceCrudReturn<TItem, TCreate, TUpdate, TKey> {\n const items = ref<TItem[]>([...(options.initialItems ?? [])]) as Ref<TItem[]>\n const loading = shallowRef(false)\n const saving = shallowRef(false)\n const deleting = shallowRef(false)\n const error = ref<string | null>(null)\n const isBusy = computed(() => loading.value || saving.value || deleting.value)\n\n const readMessage = options.readErrorMessage ?? readErrorMessage\n const getKey = options.getKey ?? defaultGetKey<TKey, TItem>\n\n function clearError(): void {\n error.value = null\n }\n\n function setError(err: unknown): void {\n error.value = readMessage(err)\n }\n\n function setItems(nextItems: readonly TItem[]): void {\n items.value = [...nextItems]\n }\n\n function upsertLocal(item: TItem): void {\n const key = getKey(item)\n const index = items.value.findIndex(existing => getKey(existing) === key)\n if (index === -1) {\n items.value = [...items.value, item]\n return\n }\n items.value = [\n ...items.value.slice(0, index),\n item,\n ...items.value.slice(index + 1),\n ]\n }\n\n function removeLocal(keyOrItem: TKey | TItem): void {\n const key = resolveKey(keyOrItem, getKey)\n items.value = items.value.filter(item => getKey(item) !== key)\n }\n\n async function load(): Promise<TItem[]> {\n loading.value = true\n clearError()\n try {\n const result = await options.adapter.list()\n setItems(result)\n return result\n } catch (err) {\n setError(err)\n throw err\n } finally {\n loading.value = false\n }\n }\n\n async function createItem(payload: TCreate): Promise<TItem> {\n if (!options.adapter.create) {\n throw new Error('[MINT SDK] Resource adapter does not implement create().')\n }\n saving.value = true\n clearError()\n try {\n const result = await options.adapter.create(payload)\n upsertLocal(result)\n return result\n } catch (err) {\n setError(err)\n throw err\n } finally {\n saving.value = false\n }\n }\n\n async function updateItem(key: TKey, payload: TUpdate): Promise<TItem> {\n if (!options.adapter.update) {\n throw new Error('[MINT SDK] Resource adapter does not implement update().')\n }\n saving.value = true\n clearError()\n try {\n const result = await options.adapter.update(key, payload)\n upsertLocal(result)\n return result\n } catch (err) {\n setError(err)\n throw err\n } finally {\n saving.value = false\n }\n }\n\n async function deleteItem(keyOrItem: TKey | TItem): Promise<void> {\n if (!options.adapter.remove) {\n throw new Error('[MINT SDK] Resource adapter does not implement remove().')\n }\n const key = resolveKey(keyOrItem, getKey)\n deleting.value = true\n clearError()\n try {\n await options.adapter.remove(key)\n removeLocal(key)\n } catch (err) {\n setError(err)\n throw err\n } finally {\n deleting.value = false\n }\n }\n\n return {\n items,\n loading,\n saving,\n deleting,\n error,\n isBusy,\n load,\n createItem,\n updateItem,\n deleteItem,\n setItems,\n upsertLocal,\n removeLocal,\n clearError,\n }\n}\n\nexport interface PluginResourceClientOptions<\n TClient,\n TItem,\n TCreate = Partial<TItem>,\n TUpdate = Partial<TItem>,\n TKey extends ResourceKey = ResourceKey,\n> {\n client: TClient\n list: (client: TClient) => Promise<TItem[]>\n create?: (client: TClient, payload: TCreate) => Promise<TItem>\n update?: (client: TClient, key: TKey, payload: TUpdate) => Promise<TItem>\n remove?: (client: TClient, key: TKey) => Promise<void>\n}\n\nexport function createPluginResourceClient<\n TClient,\n TItem,\n TCreate = Partial<TItem>,\n TUpdate = Partial<TItem>,\n TKey extends ResourceKey = ResourceKey,\n>(\n options: PluginResourceClientOptions<TClient, TItem, TCreate, TUpdate, TKey>,\n): ResourceCrudAdapter<TItem, TCreate, TUpdate, TKey> {\n return {\n list: () => options.list(options.client),\n create: options.create\n ? payload => options.create!(options.client, payload)\n : undefined,\n update: options.update\n ? (key, payload) => options.update!(options.client, key, payload)\n : undefined,\n remove: options.remove\n ? key => options.remove!(options.client, key)\n : undefined,\n }\n}\n\nfunction defaultGetKey<TKey extends ResourceKey, TItem>(item: TItem): TKey {\n if (item && typeof item === 'object' && 'id' in item) {\n return (item as { id: ResourceKey }).id as TKey\n }\n throw new Error('[MINT SDK] Resource items need an id field or a getKey option.')\n}\n\nfunction resolveKey<TItem, TKey extends ResourceKey>(\n keyOrItem: TKey | TItem,\n getKey: (item: TItem) => TKey,\n): TKey {\n if (typeof keyOrItem === 'string' || typeof keyOrItem === 'number') {\n return keyOrItem as TKey\n }\n return getKey(keyOrItem as TItem)\n}\n","import { computed, ref, toValue, type ComputedRef, type Ref } from 'vue'\nimport type { WellPlateFormat } from '../types'\nimport {\n PLATE_CONFIGS as PLATE_DIMENSIONS,\n rowIndex as rowLabelToIndex,\n rowLabel as indexToRowLabel,\n} from '../components/WellPlate.geometry'\n\nexport type WellPlateSource<T> = T | Ref<T> | ComputedRef<T> | (() => T)\n\nexport interface WellCoordinate {\n row: number\n col: number\n}\n\nexport interface WellPaintResult<TMode extends string = string, TPayload = unknown> {\n wellIds: string[]\n mode: TMode\n payload?: TPayload\n}\n\nexport interface UseWellPaintingOptions<TMode extends string = string, TPayload = unknown> {\n format: WellPlateSource<WellPlateFormat>\n initialMode?: TMode\n initialPayload?: TPayload\n onComplete?: (result: WellPaintResult<TMode, TPayload>) => void\n}\n\nexport interface UseWellPaintingReturn<TMode extends string = string, TPayload = unknown> {\n activeMode: Ref<TMode>\n activePayload: Ref<TPayload | undefined>\n isDragging: Ref<boolean>\n previewWellIds: ComputedRef<string[]>\n setMode: (mode: TMode, payload?: TPayload) => void\n setPayload: (payload: TPayload | undefined) => void\n onWellMouseDown: (wellId: string) => void\n onWellMouseMove: (wellId: string) => void\n onWellMouseUp: () => void\n cancel: () => void\n}\n\n\n/**\n * Pointer painting/rectangle selection state for WellPlate-based editors.\n *\n * @deprecated Unused by the MINT platform and scheduled for removal in MINT 1.3; use `useWellPlateEditor()` instead.\n */\nexport function useWellPainting<TMode extends string = string, TPayload = unknown>(\n options: UseWellPaintingOptions<TMode, TPayload>,\n): UseWellPaintingReturn<TMode, TPayload> {\n const activeMode = ref<TMode>(options.initialMode ?? 'select' as TMode) as Ref<TMode>\n const activePayload = ref<TPayload | undefined>(options.initialPayload) as Ref<TPayload | undefined>\n const isDragging = ref(false)\n const dragStart = ref<WellCoordinate | null>(null)\n const dragEnd = ref<WellCoordinate | null>(null)\n const paintTrail = ref<Set<string>>(new Set())\n\n const previewWellIds = computed(() => {\n if (!isDragging.value) return []\n if (activeMode.value === 'select') {\n if (!dragStart.value || !dragEnd.value) return []\n return wellIdsInRectangle(dragStart.value, dragEnd.value, toValue(options.format))\n }\n return [...paintTrail.value]\n })\n\n function setMode(mode: TMode, payload?: TPayload): void {\n activeMode.value = mode\n activePayload.value = payload\n }\n\n function setPayload(payload: TPayload | undefined): void {\n activePayload.value = payload\n }\n\n function onWellMouseDown(wellId: string): void {\n const coord = wellIdToCoordinate(wellId)\n if (!coord) return\n isDragging.value = true\n dragStart.value = coord\n dragEnd.value = coord\n paintTrail.value = new Set([wellId])\n }\n\n function onWellMouseMove(wellId: string): void {\n if (!isDragging.value) return\n const coord = wellIdToCoordinate(wellId)\n if (!coord) return\n dragEnd.value = coord\n if (activeMode.value !== 'select') {\n paintTrail.value = new Set([...paintTrail.value, wellId])\n }\n }\n\n function onWellMouseUp(): void {\n if (!isDragging.value) return\n const wellIds = previewWellIds.value\n isDragging.value = false\n if (wellIds.length > 0) {\n options.onComplete?.({\n wellIds,\n mode: activeMode.value,\n payload: activePayload.value,\n })\n }\n clearDragState()\n }\n\n function cancel(): void {\n isDragging.value = false\n clearDragState()\n }\n\n function clearDragState(): void {\n dragStart.value = null\n dragEnd.value = null\n paintTrail.value = new Set()\n }\n\n return {\n activeMode,\n activePayload,\n isDragging,\n previewWellIds,\n setMode,\n setPayload,\n onWellMouseDown,\n onWellMouseMove,\n onWellMouseUp,\n cancel,\n }\n}\n\nexport function wellIdToCoordinate(wellId: string): WellCoordinate | null {\n const match = /^([A-Z]+)(\\d+)$/i.exec(wellId.trim())\n if (!match) return null\n return {\n row: rowLabelToIndex(match[1].toUpperCase()),\n col: Number(match[2]) - 1,\n }\n}\n\nexport function coordinateToWellId(coord: WellCoordinate): string {\n return `${indexToRowLabel(coord.row)}${coord.col + 1}`\n}\n\nexport function wellIdsInRectangle(\n start: WellCoordinate,\n end: WellCoordinate,\n format: WellPlateFormat,\n): string[] {\n const dimensions = PLATE_DIMENSIONS[format]\n const minRow = Math.max(0, Math.min(start.row, end.row))\n const maxRow = Math.min(dimensions.rows - 1, Math.max(start.row, end.row))\n const minCol = Math.max(0, Math.min(start.col, end.col))\n const maxCol = Math.min(dimensions.cols - 1, Math.max(start.col, end.col))\n const ids: string[] = []\n\n for (let row = minRow; row <= maxRow; row++) {\n for (let col = minCol; col <= maxCol; col++) {\n ids.push(coordinateToWellId({ row, col }))\n }\n }\n return ids\n}\n\n\n","import { computed, toValue, type ComputedRef, type Ref } from 'vue'\nimport type { ColumnCondition, RowCondition, Well } from '../types'\n\nexport type WellPlateAdapterSource<T> =\n | T\n | Ref<T>\n | ComputedRef<T>\n | (() => T)\n\nexport interface WellPlateEntry {\n wellId: string\n state?: Well['state']\n sampleType?: string\n value?: number\n metadata?: Record<string, unknown>\n}\n\nexport interface WellPlateAdapterOptions<TEntry> {\n entries: WellPlateAdapterSource<readonly TEntry[]>\n getWellId: (entry: TEntry) => string\n getState?: (entry: TEntry) => Well['state'] | undefined\n getSampleType?: (entry: TEntry) => string | undefined\n getValue?: (entry: TEntry) => number | undefined\n getMetadata?: (entry: TEntry) => Record<string, unknown> | undefined\n}\n\nexport interface UseWellPlateAdapterReturn {\n wells: ComputedRef<Record<string, Partial<Well>>>\n}\n\n/**\n * Convert domain rows into WellPlate's wells prop without hand-written adapters.\n *\n * @deprecated Unused by the MINT platform and scheduled for removal in MINT 1.3; use `useWellPlateEditor()` instead.\n */\nexport function useWellPlateAdapter<TEntry>(\n options: WellPlateAdapterOptions<TEntry>,\n): UseWellPlateAdapterReturn {\n const wells = computed(() => createWellPlateWells(toValue(options.entries), options))\n return { wells }\n}\n\nexport function createWellPlateWells<TEntry>(\n entries: readonly TEntry[],\n options: Omit<WellPlateAdapterOptions<TEntry>, 'entries'>,\n): Record<string, Partial<Well>> {\n return Object.fromEntries(entries.map((entry) => {\n const wellId = options.getWellId(entry)\n const coord = parseWellId(wellId)\n const well: Partial<Well> = {\n id: wellId,\n row: coord.row,\n col: coord.col,\n state: options.getState?.(entry) ?? 'filled',\n sampleType: options.getSampleType?.(entry),\n value: options.getValue?.(entry),\n metadata: options.getMetadata?.(entry),\n }\n return [wellId, well]\n }))\n}\n\nexport interface AxisConditionEntry {\n label: string\n color: string\n start: string | number\n concentrations: readonly { value: number; replicates?: number }[]\n unit?: string\n}\n\nexport function createColumnConditions(entries: readonly AxisConditionEntry[]): ColumnCondition[] {\n return entries.map((entry) => {\n const startCol = typeof entry.start === 'number'\n ? entry.start\n : Number.parseInt(entry.start, 10)\n const cols: number[] = []\n const concentrations: number[] = []\n\n for (const concentration of entry.concentrations) {\n const replicates = concentration.replicates ?? 1\n for (let index = 0; index < replicates; index++) {\n cols.push(startCol + cols.length)\n concentrations.push(concentration.value)\n }\n }\n\n return {\n label: entry.label,\n color: entry.color,\n unit: entry.unit,\n cols,\n concentrations,\n }\n })\n}\n\nexport function createRowConditions(entries: readonly AxisConditionEntry[]): RowCondition[] {\n return entries.map((entry) => {\n const startRow = typeof entry.start === 'number'\n ? entry.start\n : rowLabelToIndex(entry.start)\n const rows: string[] = []\n const concentrations: number[] = []\n\n for (const concentration of entry.concentrations) {\n const replicates = concentration.replicates ?? 1\n for (let index = 0; index < replicates; index++) {\n rows.push(indexToRowLabel(startRow + rows.length))\n concentrations.push(concentration.value)\n }\n }\n\n return {\n label: entry.label,\n color: entry.color,\n unit: entry.unit,\n rows,\n concentrations,\n }\n })\n}\n\nfunction parseWellId(wellId: string): { row: number; col: number } {\n const match = /^([A-Z]+)(\\d+)$/i.exec(wellId.trim())\n if (!match) {\n throw new Error(`[MINT SDK] Invalid well id \"${wellId}\".`)\n }\n return {\n row: rowLabelToIndex(match[1].toUpperCase()),\n col: Number(match[2]) - 1,\n }\n}\n\nfunction rowLabelToIndex(label: string): number {\n let result = 0\n for (const char of label.toUpperCase()) {\n result = result * 26 + (char.charCodeAt(0) - 64)\n }\n return result - 1\n}\n\nfunction indexToRowLabel(index: number): string {\n let value = index + 1\n let label = ''\n while (value > 0) {\n value--\n label = String.fromCharCode(65 + (value % 26)) + label\n value = Math.floor(value / 26)\n }\n return label\n}\n","import { computed, toValue, type ComputedRef, type Ref } from 'vue'\n\nexport type WellPlateValidationSeverity = 'error' | 'warning' | 'info'\n\nexport interface WellPlateValidationWarning<TType extends string = string> {\n type: TType\n severity: WellPlateValidationSeverity\n message: string\n affectedWells?: string[]\n}\n\nexport interface WellPlateValidationRule<TContext, TType extends string = string> {\n type: TType\n severity: WellPlateValidationSeverity\n validate: (context: TContext) => false | string | Omit<WellPlateValidationWarning<TType>, 'type' | 'severity'>\n}\n\nexport type WellPlateValidationSource<T> =\n | T\n | Ref<T>\n | ComputedRef<T>\n | (() => T)\n\nexport interface UseWellPlateValidationOptions<TContext, TType extends string = string> {\n context: WellPlateValidationSource<TContext>\n rules: WellPlateValidationSource<readonly WellPlateValidationRule<TContext, TType>[]>\n}\n\nexport interface UseWellPlateValidationReturn<TType extends string = string> {\n warnings: ComputedRef<WellPlateValidationWarning<TType>[]>\n hasBlockingIssues: ComputedRef<boolean>\n warningCount: ComputedRef<number>\n errorCount: ComputedRef<number>\n}\n\n/**\n * Rule-driven validation state for WellPlate layout/design screens.\n *\n * @deprecated Unused by the MINT platform and scheduled for removal in MINT 1.3; use `useWellPlateEditor()` instead.\n */\nexport function useWellPlateValidation<TContext, TType extends string = string>(\n options: UseWellPlateValidationOptions<TContext, TType>,\n): UseWellPlateValidationReturn<TType> {\n const warnings = computed(() => runWellPlateValidation(\n toValue(options.context),\n toValue(options.rules),\n ))\n const hasBlockingIssues = computed(() => warnings.value.some(warning => warning.severity === 'error'))\n const warningCount = computed(() => warnings.value.length)\n const errorCount = computed(() => warnings.value.filter(warning => warning.severity === 'error').length)\n\n return {\n warnings,\n hasBlockingIssues,\n warningCount,\n errorCount,\n }\n}\n\nexport function runWellPlateValidation<TContext, TType extends string = string>(\n context: TContext,\n rules: readonly WellPlateValidationRule<TContext, TType>[],\n): WellPlateValidationWarning<TType>[] {\n const warnings: WellPlateValidationWarning<TType>[] = []\n for (const rule of rules) {\n const result = rule.validate(context)\n if (!result) continue\n warnings.push(normalizeWarning(rule, result))\n }\n return warnings\n}\n\nfunction normalizeWarning<TContext, TType extends string>(\n rule: WellPlateValidationRule<TContext, TType>,\n result: string | Omit<WellPlateValidationWarning<TType>, 'type' | 'severity'>,\n): WellPlateValidationWarning<TType> {\n if (typeof result === 'string') {\n return {\n type: rule.type,\n severity: rule.severity,\n message: result,\n }\n }\n return {\n type: rule.type,\n severity: rule.severity,\n ...result,\n }\n}\n","import {\n getInjectedPlatformContext,\n resolveCurrentExperimentId,\n} from './platformContextHelpers'\nimport type {\n BuildPluginEndpointUrlOptions,\n PluginContract,\n PluginEndpointDefinition,\n PluginEndpointParamDefinition,\n} from './usePluginClient'\n\nfunction normalizeApiBaseUrl(baseUrl: string | undefined): string | undefined {\n if (!baseUrl) return undefined\n return baseUrl.length > 1 ? baseUrl.replace(/\\/+$/, '') : baseUrl\n}\n\nfunction normalizeApiPrefix(prefix: string | undefined): string | undefined {\n if (!prefix) return undefined\n if (prefix.startsWith('/api/')) return normalizeApiBaseUrl(prefix)\n if (prefix === '/api') return prefix\n if (prefix.startsWith('/')) return normalizeApiBaseUrl(`/api${prefix}`)\n return normalizeApiBaseUrl(`/api/${prefix}`)\n}\n\nfunction endpointParamName(param: PluginEndpointParamDefinition): string {\n return typeof param === 'string' ? param : param.name\n}\n\nfunction endpointParamFieldName(param: PluginEndpointParamDefinition): string {\n return typeof param === 'string' ? param : param.fieldName ?? param.name\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n\nfunction replacePathParam(path: string, name: string, encoded: string): string {\n const escapedName = escapeRegExp(name)\n return path\n .replace(new RegExp(`\\\\{${escapedName}(?::[^{}]+)?\\\\}`, 'g'), () => encoded)\n .replace(new RegExp(`:${escapedName}(?=/|$)`, 'g'), () => encoded)\n}\n\n/** Resolve the runtime plugin API base URL from env, explicit options, platform injection, or contract metadata. */\nexport function resolvePluginBaseUrl(contract: PluginContract, explicitBaseUrl?: string): string {\n const envPrefix = (import.meta.env?.VITE_API_PREFIX as string | undefined) || undefined\n if (envPrefix) return normalizeApiBaseUrl(envPrefix) ?? envPrefix\n if (explicitBaseUrl) return normalizeApiBaseUrl(explicitBaseUrl) ?? explicitBaseUrl\n\n const injected = getInjectedPlatformContext()\n const platformPrefix =\n normalizeApiBaseUrl(injected?.plugin?.api_prefix) ||\n normalizeApiPrefix(injected?.plugin?.route_prefix)\n if (platformPrefix) return platformPrefix\n\n return normalizeApiBaseUrl(contract.plugin.apiPrefix) || '/api'\n}\n\nfunction encodePath(\n path: string,\n payload: Record<string, unknown>,\n pathParams: PluginEndpointParamDefinition[],\n): string {\n let nextPath = path\n for (const param of pathParams) {\n const name = endpointParamName(param)\n const fieldName = endpointParamFieldName(param)\n const value = payload[fieldName] ?? payload[name]\n if (value === undefined || value === null) {\n throw new Error(`[MINT SDK] Missing path parameter '${fieldName}' for plugin endpoint ${path}`)\n }\n const encoded = encodeURIComponent(String(value))\n nextPath = replacePathParam(nextPath, name, encoded)\n if (fieldName !== name) {\n nextPath = replacePathParam(nextPath, fieldName, encoded)\n }\n }\n return nextPath\n}\n\nfunction withDefaultPathParams(\n payload: Record<string, unknown>,\n pathParams: PluginEndpointParamDefinition[],\n): Record<string, unknown> {\n if (!pathParams.length) return payload\n const nextPayload = { ...payload }\n for (const param of pathParams) {\n const name = endpointParamName(param)\n const fieldName = endpointParamFieldName(param)\n if (\n (nextPayload[fieldName] !== undefined && nextPayload[fieldName] !== null)\n || (nextPayload[name] !== undefined && nextPayload[name] !== null)\n ) {\n continue\n }\n if (isExperimentPathParam(fieldName) || isExperimentPathParam(name)) {\n const experimentId = resolveCurrentExperimentId()\n if (experimentId !== undefined) {\n nextPayload[fieldName] = experimentId\n }\n }\n }\n return nextPayload\n}\n\nfunction isExperimentPathParam(param: string): boolean {\n return param === 'experimentId' || param === 'experiment_id'\n}\n\nfunction withoutPathParams(payload: Record<string, unknown>, pathParams: PluginEndpointParamDefinition[]) {\n const copy = { ...payload }\n for (const param of pathParams) {\n delete copy[endpointParamFieldName(param)]\n delete copy[endpointParamName(param)]\n }\n return copy\n}\n\nfunction queryParamsFromPayload(\n payload: Record<string, unknown>,\n pathParams: PluginEndpointParamDefinition[],\n queryParams?: PluginEndpointParamDefinition[],\n endpointPath?: string,\n includeUnspecifiedParams = false,\n) {\n if (!queryParams?.length) {\n return includeUnspecifiedParams ? withoutPathParams(payload, pathParams) : {}\n }\n\n const query: Record<string, unknown> = {}\n for (const param of queryParams) {\n const name = typeof param === 'string' ? param : param.name\n const fieldName = typeof param === 'string' ? param : param.fieldName ?? param.name\n const required = typeof param !== 'string' && param.required === true\n const value = payload[fieldName]\n if (value === undefined || value === null) {\n if (required) {\n throw new Error(\n `[MINT SDK] Missing query parameter '${fieldName}' for plugin endpoint ${endpointPath ?? ''}`,\n )\n }\n continue\n }\n query[name] = value\n }\n return query\n}\n\nexport function hasKeys(value: Record<string, unknown>): boolean {\n return Object.keys(value).length > 0\n}\n\nfunction isPlainPayloadObject(value: unknown): value is Record<string, unknown> {\n return !!value && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction hasOwn(value: Record<string, unknown>, key: string): boolean {\n return Object.prototype.hasOwnProperty.call(value, key)\n}\n\nfunction normalizeStructuredEndpointPayload(payload: Record<string, unknown>): Record<string, unknown> {\n const pathParamPayload = payload.pathParams\n const queryPayload = payload.query\n const hasStructuredPathParams = hasOwn(payload, 'pathParams') && isPlainPayloadObject(pathParamPayload)\n const hasStructuredQuery = hasOwn(payload, 'query') && isPlainPayloadObject(queryPayload)\n if (!hasStructuredPathParams && !hasStructuredQuery) return payload\n\n const nextPayload = { ...payload }\n delete nextPayload.pathParams\n delete nextPayload.query\n\n if (hasStructuredPathParams) {\n Object.assign(nextPayload, pathParamPayload)\n }\n if (hasStructuredQuery) {\n Object.assign(nextPayload, queryPayload)\n }\n\n return nextPayload\n}\n\nexport function requestBodyFromPayload(\n payload: unknown,\n requestPayload: Record<string, unknown>,\n endpoint: PluginEndpointDefinition,\n): unknown {\n if (!endpoint.hasBody) return undefined\n const body = endpoint.pathParams?.length || endpoint.queryParams?.length\n ? requestPayload.body\n : payload\n if (body === undefined || body === null) {\n throw new Error(`[MINT SDK] Missing request body for plugin endpoint ${endpoint.path}`)\n }\n return body\n}\n\nexport function pluginEndpointRequestParts(\n contract: PluginContract,\n endpoint: PluginEndpointDefinition,\n payload?: unknown,\n explicitBaseUrl?: string,\n) {\n const payloadObject = isPlainPayloadObject(payload)\n ? normalizeStructuredEndpointPayload(payload)\n : {}\n const pathParams = endpoint.pathParams ?? []\n const requestPayload = withDefaultPathParams(payloadObject, pathParams)\n const path = encodePath(endpoint.path, requestPayload, pathParams)\n const query = queryParamsFromPayload(\n requestPayload,\n pathParams,\n endpoint.queryParams,\n endpoint.path,\n endpoint.method === 'get',\n )\n\n return {\n baseUrl: resolvePluginBaseUrl(contract, explicitBaseUrl),\n path,\n query,\n requestPayload,\n }\n}\n\nfunction appendQueryValue(params: URLSearchParams, key: string, value: unknown): void {\n if (value === undefined || value === null) return\n if (Array.isArray(value)) {\n for (const item of value) {\n appendQueryValue(params, key, item)\n }\n return\n }\n if (typeof value === 'object') {\n params.append(key, JSON.stringify(value))\n return\n }\n params.append(key, String(value))\n}\n\nfunction queryString(query: Record<string, unknown>): string {\n const params = new URLSearchParams()\n for (const [key, value] of Object.entries(query)) {\n appendQueryValue(params, key, value)\n }\n const serialized = params.toString()\n return serialized ? `?${serialized}` : ''\n}\n\nfunction joinBaseUrl(baseUrl: string, path: string): string {\n if (!baseUrl) return path\n const normalizedBase = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl\n const normalizedPath = path.startsWith('/') ? path : `/${path}`\n return `${normalizedBase}${normalizedPath}`\n}\n\n/** Build the concrete URL for a generated plugin endpoint without making a request. */\nexport function buildPluginEndpointUrl(\n contract: PluginContract,\n endpoint: PluginEndpointDefinition,\n payload?: unknown,\n options: BuildPluginEndpointUrlOptions = {},\n): string {\n const parts = pluginEndpointRequestParts(contract, endpoint, payload, options.baseUrl)\n const pathWithQuery = `${parts.path}${queryString(parts.query)}`\n if (options.includeBaseUrl === false) return pathWithQuery\n return joinBaseUrl(parts.baseUrl, pathWithQuery)\n}\n","import {\n computed,\n onMounted,\n ref,\n shallowRef,\n watch,\n type ComputedRef,\n type Ref,\n} from 'vue'\nimport {\n AuthenticationRequiredError,\n authenticationRequiredError,\n useApi,\n} from './useApi'\nimport { usePlatformContext } from './usePlatformContext'\nimport { useRequestSyncState } from './useRequestSyncState'\nimport { useAuthStore } from '../stores/auth'\nimport { PLUGIN_SECRET_FORMAT_KEY } from '../utils/pluginSecrets'\nimport {\n currentExperimentFromContext,\n getInjectedPlatformContext,\n resolveCurrentExperimentId,\n} from './platformContextHelpers'\nimport {\n buildPluginEndpointUrl,\n hasKeys,\n pluginEndpointRequestParts,\n requestBodyFromPayload,\n} from './pluginEndpointBuilder'\nimport {\n useEventStream,\n type EventStreamMessage,\n type EventStreamTransport,\n type UseEventStreamReturn,\n} from './useEventStream'\nimport type {\n ExperimentSummary,\n GeneratedJobDefinition,\n PageSelectorItem,\n SettingsModalSchema,\n TopBarSettingsConfig,\n} from '../types'\n\nexport {\n buildPluginEndpointUrl,\n resolvePluginBaseUrl,\n} from './pluginEndpointBuilder'\n\nexport type PluginHttpMethod = 'get' | 'post' | 'put' | 'patch' | 'delete'\n\nexport interface PluginEndpointContract {\n name: string\n operationId?: string\n method: PluginHttpMethod\n path: string\n requiresAuth?: boolean\n pathParams?: PluginEndpointParamContract[]\n queryParams?: PluginEndpointParamContract[]\n requestType?: string | null\n requestContentType?: string | null\n responseType?: string | null\n responseContentType?: string | null\n eventStream?: boolean\n}\n\nexport interface PluginEndpointParamContract {\n name: string\n fieldName: string\n type?: string\n required?: boolean\n}\n\nexport interface PluginNavItemContract {\n path: string\n label: string\n id?: string\n icon?: string\n description?: string\n requiresAuth?: boolean\n requiresAdmin?: boolean\n requiresFeature?: string\n}\n\nexport interface PluginContractSettings {\n modelName: string | null\n /** Pydantic JSON Schema used to generate typed settings values. */\n valueSchema: Record<string, unknown> | null\n /** SDK SettingsModal schema used to render the settings form. */\n formSchema: SettingsModalSchema | null\n}\n\nexport interface PluginContract {\n schemaVersion: 2\n plugin: {\n name?: string\n packageName?: string\n version?: string\n description?: string\n routesPrefix: string\n apiPrefix: string\n type: 'analysis' | 'experiment-design' | string\n analysisType?: string\n icon?: string\n color?: string\n navItems?: PluginNavItemContract[]\n analysisResultReaders?: string[]\n capabilities?: Record<string, unknown>\n }\n settings: PluginContractSettings\n endpoints: PluginEndpointContract[]\n schemas?: Record<string, Record<string, unknown>>\n jobs?: GeneratedJobDefinition[]\n hash: string\n}\n\nexport interface PluginEndpointDefinition {\n method: PluginHttpMethod\n path: string\n requiresAuth?: boolean\n pathParams?: PluginEndpointParamDefinition[]\n queryParams?: PluginEndpointParamDefinition[]\n hasBody?: boolean\n requestContentType?: string | null\n eventStream?: boolean\n responseType?: string | null\n responseContentType?: string | null\n}\n\nexport type PluginEndpointParamDefinition = string | {\n name: string\n fieldName?: string\n type?: string\n required?: boolean\n}\n\nexport interface CreatePluginClientOptions {\n endpoints: Record<string, PluginEndpointDefinition>\n baseUrl?: string\n}\n\nexport interface BuildPluginEndpointUrlOptions {\n /** Override the generated or platform-injected API base URL. */\n baseUrl?: string\n /** Return only the endpoint path and query string instead of base URL + path. */\n includeBaseUrl?: boolean\n}\n\nexport interface PluginEndpointRequestOptions {\n /** Override the generated or platform-injected API base URL. */\n baseUrl?: string\n /** Cancel the request without changing its endpoint or authentication behavior. */\n signal?: AbortSignal\n}\n\nexport interface PluginClientRequestOptions {\n /** Cancel the generated endpoint request. */\n signal?: AbortSignal\n}\n\nexport interface DownloadPluginEndpointOptions extends PluginEndpointRequestOptions {\n /** Browser download filename. When omitted, the blob is returned without triggering a download. */\n filename?: string\n /** Delay before revoking the object URL after a browser download is triggered. */\n revokeObjectUrlDelayMs?: number\n}\n\nexport interface DownloadBlobOptions {\n /** Delay before revoking the object URL after a browser download is triggered. */\n revokeObjectUrlDelayMs?: number\n}\n\nexport type PluginSettingsValues<TSettings> = Partial<TSettings> & Record<string, unknown>\n\nexport interface UsePluginSettingsOptions {\n /** Plugin name for platform persistence. Defaults to the integrated platform plugin name. */\n pluginName?: string\n /** Plugin API base URL for standalone/local settings routes. Generated clients pass pluginApiPrefix. */\n apiBaseUrl?: string\n /** Platform API base URL for /plugins/{name}/config. Defaults to the injected platform API URL. */\n platformApiBaseUrl?: string\n /** SettingsModal schema generated from the backend plugin config model. */\n schema?: SettingsModalSchema | null\n /** SettingsModal title when using settingsConfig. */\n title?: string\n /** Whether SettingsModal should include SDK appearance controls. */\n showAppearance?: boolean\n /** Load persisted values on component mount. */\n loadOnMount?: boolean\n}\n\nexport interface UsePluginSettingsReturn<TSettings = Record<string, unknown>> {\n /** Current typed settings values. */\n settings: ComputedRef<PluginSettingsValues<TSettings>>\n /** Editable settings values for SettingsModal. */\n values: Ref<PluginSettingsValues<TSettings>>\n /** Alias for values, kept for callers that think in platform config terms. */\n config: Ref<PluginSettingsValues<TSettings>>\n /** Ready-to-pass AppTopBar/PluginWorkspaceView settingsConfig. */\n settingsConfig: ComputedRef<TopBarSettingsConfig>\n isLoading: Ref<boolean>\n isSaving: Ref<boolean>\n error: Ref<string | null>\n lastLoadedAt: Ref<Date | null>\n lastSavedAt: Ref<Date | null>\n isDirty: ComputedRef<boolean>\n setValues: (values: Record<string, unknown>) => void\n load: () => Promise<void>\n save: (values?: Record<string, unknown>) => Promise<boolean>\n reset: () => void\n}\n\nexport type PluginEventStreamMessage<TData = string> = EventStreamMessage<TData>\n\nexport interface PluginEventStreamOptions<TData = string> {\n /** Override the generated or platform-injected API base URL. */\n baseUrl?: string\n /** Start the stream immediately. Defaults to true. */\n immediate?: boolean\n /** Reconnect after errors or server closes. Defaults to true. */\n reconnect?: boolean\n /** Delay before reconnecting after a stream failure or close. Defaults to 2000ms. */\n reconnectDelayMs?: number\n /** Parse `data:` as JSON. Defaults to true for typed endpoints and false otherwise. */\n parseJson?: boolean\n /** Fetch credentials mode. Defaults to same-origin. */\n credentials?: RequestCredentials\n /** Extra request headers. Authorization is injected unless already supplied. */\n headers?: Record<string, string>\n onOpen?: () => void\n onMessage?: (message: PluginEventStreamMessage<TData>) => void\n onError?: (error: unknown) => void\n}\n\nexport type UsePluginEventStreamReturn<TData = string> = UseEventStreamReturn<TData>\n\nexport type PluginFormDataValue =\n | string\n | number\n | boolean\n | Blob\n | null\n | undefined\n | Record<string, unknown>\n\nexport type PluginFormDataPayload = Record<string, PluginFormDataValue | PluginFormDataValue[]>\n\nexport interface UseCurrentExperimentOptions {\n apiBaseUrl?: string\n immediate?: boolean\n}\n\nexport interface UseCurrentExperimentReturn<TExperiment = ExperimentSummary> {\n /** Current experiment id resolved from platform injection or URL conventions. */\n experimentId: ComputedRef<number | undefined>\n /** Whether a current experiment id is available. */\n hasExperiment: ComputedRef<boolean>\n /** Current experiment payload, if injected or successfully fetched. */\n experiment: Ref<TExperiment | undefined>\n /** Whether the current experiment is currently loading. */\n isLoading: Ref<boolean>\n /** Error message from the last failed current-experiment fetch, or null. */\n error: Ref<string | null>\n /** Timestamp of the last successful current-experiment fetch, or null. */\n lastLoadedAt: Ref<Date | null>\n /** Return the current experiment id or throw a clear SDK error when absent. */\n requireExperimentId: () => number\n /** Fetch a specific experiment id, defaulting to the current experiment id. */\n fetch: (experimentId?: number) => Promise<TExperiment | undefined>\n /** Refetch the currently resolved experiment id. */\n refresh: () => Promise<TExperiment | undefined>\n}\n\nexport type PluginEndpointCaller = (\n payloadOrOptions?: unknown,\n options?: PluginClientRequestOptions,\n) => Promise<unknown>\nexport type GeneratedPluginClient = Record<string, (...args: any[]) => Promise<any>>\n\nfunction queryConfig(query: Record<string, unknown>) {\n return hasKeys(query) ? { params: query } : undefined\n}\n\nconst OCTET_STREAM = 'application/octet-stream'\nconst MULTIPART_FORM_DATA = 'multipart/form-data'\n\nfunction endpointRequestConfig(\n endpoint: PluginEndpointDefinition,\n query: Record<string, unknown>,\n options?: PluginClientRequestOptions,\n) {\n const config: Record<string, unknown> = {}\n if (hasKeys(query)) config.params = query\n if (endpoint.requestContentType === OCTET_STREAM) {\n config.headers = { 'Content-Type': OCTET_STREAM }\n }\n if (endpoint.requestContentType === MULTIPART_FORM_DATA) {\n config.headers = { 'Content-Type': undefined }\n }\n if (endpoint.responseContentType === OCTET_STREAM) {\n config.responseType = 'blob'\n }\n if (options?.signal) config.signal = options.signal\n return hasKeys(config) ? config : undefined\n}\n\nfunction isFormData(value: unknown): value is FormData {\n return typeof FormData !== 'undefined' && value instanceof FormData\n}\n\nfunction endpointRequestBody(endpoint: PluginEndpointDefinition, body: unknown): unknown {\n return endpoint.requestContentType === MULTIPART_FORM_DATA\n ? pluginFormDataFromPayload(body)\n : body\n}\n\nfunction endpointHasPayload(endpoint: PluginEndpointDefinition): boolean {\n return Boolean(\n endpoint.hasBody\n || endpoint.pathParams?.length\n || endpoint.queryParams?.length,\n )\n}\n\nfunction isBlob(value: unknown): value is Blob {\n return typeof Blob !== 'undefined' && value instanceof Blob\n}\n\nfunction appendFormDataValue(formData: FormData, key: string, value: PluginFormDataValue | PluginFormDataValue[]): void {\n if (value === undefined || value === null) return\n\n if (Array.isArray(value)) {\n for (const item of value) {\n appendFormDataValue(formData, key, item)\n }\n return\n }\n\n if (isBlob(value)) {\n formData.append(key, value)\n return\n }\n\n if (typeof value === 'object') {\n formData.append(key, JSON.stringify(value))\n return\n }\n\n formData.append(key, String(value))\n}\n\n/** Convert plain upload payloads into FormData using the same encoding across generated plugin clients. */\nexport function pluginFormDataFromPayload(payload: unknown): FormData {\n if (isFormData(payload)) return payload\n if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {\n throw new Error('[MINT SDK] Plugin upload endpoints require a FormData or plain object payload.')\n }\n\n const formData = new FormData()\n for (const [key, value] of Object.entries(payload as PluginFormDataPayload)) {\n appendFormDataValue(formData, key, value)\n }\n return formData\n}\n\n/** Trigger a browser download for an already-created Blob. */\nexport function downloadBlob(blob: Blob, filename: string, options: DownloadBlobOptions = {}): void {\n if (typeof document === 'undefined' || typeof URL === 'undefined') {\n throw new Error('[MINT SDK] Cannot trigger a file download outside a browser.')\n }\n\n const blobUrl = URL.createObjectURL(blob)\n const link = document.createElement('a')\n link.href = blobUrl\n link.download = filename\n document.body.appendChild(link)\n link.click()\n document.body.removeChild(link)\n setTimeout(() => URL.revokeObjectURL(blobUrl), options.revokeObjectUrlDelayMs ?? 100)\n}\n\nfunction normalizePluginNavPath(path: string): string {\n const raw = path.trim() || '/'\n const prefixed = raw.startsWith('/') ? raw : `/${raw}`\n return prefixed.replace(/\\/+$/, '') || '/'\n}\n\nfunction pluginPageIdFromPath(path: string, fallbackIndex: number): string {\n const normalizedPath = normalizePluginNavPath(path)\n if (normalizedPath === '/') return 'dashboard'\n return normalizedPath.replace(/^\\/+/, '').replace(/\\/+/g, '-') || `page-${fallbackIndex + 1}`\n}\n\n/** Convert resolved @mint_plugin nav_items into page selectors for the topbar and homepage PluginCards. */\nexport function getPluginPageSelectorItems(contract: PluginContract): PageSelectorItem[] {\n const pluginIcon = contract.plugin.icon ?? ''\n const navItems = contract.plugin.navItems ?? []\n return navItems.map((item, index) => ({\n id: item.id || pluginPageIdFromPath(item.path, index),\n label: item.label,\n to: normalizePluginNavPath(item.path),\n icon: item.icon || pluginIcon || undefined,\n }))\n}\n\n/** Create a typed plugin API client from a generated MINT plugin contract. */\nexport function createPluginClient<TClient extends object = GeneratedPluginClient>(\n contract: PluginContract,\n options: CreatePluginClientOptions,\n): TClient {\n const client: Record<string, PluginEndpointCaller> = {}\n\n for (const [name, endpoint] of Object.entries(options.endpoints)) {\n client[name] = async (\n payloadOrOptions?: unknown,\n explicitOptions?: PluginClientRequestOptions,\n ) => {\n const hasPayload = endpointHasPayload(endpoint)\n const payload = hasPayload ? payloadOrOptions : undefined\n const callOptions = hasPayload\n ? explicitOptions\n : (payloadOrOptions as PluginClientRequestOptions | undefined) ?? explicitOptions\n const parts = pluginEndpointRequestParts(contract, endpoint, payload, options.baseUrl)\n const api = useApi({\n baseUrl: parts.baseUrl,\n withAuth: endpoint.requiresAuth !== false,\n typedErrors: true,\n })\n const config = endpointRequestConfig(endpoint, parts.query, callOptions)\n\n if (endpoint.method === 'get') {\n return api.get(parts.path, config)\n }\n\n if (endpoint.method === 'delete') {\n const rawBody = requestBodyFromPayload(payload, parts.requestPayload, endpoint)\n const body = rawBody === undefined ? undefined : endpointRequestBody(endpoint, rawBody)\n const config = body === undefined\n ? endpointRequestConfig(endpoint, parts.query, callOptions)\n : { ...endpointRequestConfig(endpoint, parts.query, callOptions), data: body }\n return api.delete(parts.path, config)\n }\n\n const body = endpointRequestBody(\n endpoint,\n requestBodyFromPayload(payload, parts.requestPayload, endpoint),\n )\n\n if (endpoint.method === 'post') return api.post(parts.path, body, config)\n if (endpoint.method === 'put') return api.put(parts.path, body, config)\n if (endpoint.method === 'patch') return api.patch(parts.path, body, config)\n throw new Error(`[MINT SDK] Unsupported plugin endpoint method: ${endpoint.method}`)\n }\n }\n\n return client as TClient\n}\n\n/** Send multipart or raw binary data to a generated endpoint with contract URL, cancellation, and auth handling. */\nexport async function uploadPluginEndpoint<TResponse = unknown>(\n contract: PluginContract,\n endpoint: PluginEndpointDefinition,\n payload?: unknown,\n options: PluginEndpointRequestOptions = {},\n): Promise<TResponse> {\n if (!['post', 'put', 'patch'].includes(endpoint.method)) {\n throw new Error(`[MINT SDK] Plugin upload endpoints must use POST, PUT, or PATCH; got ${endpoint.method}`)\n }\n\n const parts = pluginEndpointRequestParts(contract, endpoint, payload, options.baseUrl)\n const api = useApi({\n baseUrl: parts.baseUrl,\n withAuth: endpoint.requiresAuth !== false,\n typedErrors: true,\n })\n const body = endpoint.hasBody\n ? requestBodyFromPayload(payload, parts.requestPayload, endpoint)\n : payload\n if (endpoint.requestContentType === OCTET_STREAM) {\n const config = endpointRequestConfig(endpoint, parts.query, { signal: options.signal })\n if (endpoint.method === 'post') return api.post<TResponse>(parts.path, body, config)\n if (endpoint.method === 'put') return api.put<TResponse>(parts.path, body, config)\n return api.patch<TResponse>(parts.path, body, config)\n }\n const formData = pluginFormDataFromPayload(body)\n const config = {\n ...(queryConfig(parts.query) ?? {}),\n ...(options.signal ? { signal: options.signal } : {}),\n // Let Axios/browser set multipart boundaries.\n headers: { 'Content-Type': undefined },\n }\n\n if (endpoint.method === 'post') return api.post<TResponse>(parts.path, formData, config)\n if (endpoint.method === 'put') return api.put<TResponse>(parts.path, formData, config)\n return api.patch<TResponse>(parts.path, formData, config)\n}\n\n/** Fetch a generated plugin endpoint as a Blob and optionally trigger a browser download. */\nexport async function downloadPluginEndpoint(\n contract: PluginContract,\n endpoint: PluginEndpointDefinition,\n payload?: unknown,\n options: DownloadPluginEndpointOptions = {},\n): Promise<Blob> {\n if (endpoint.requestContentType === MULTIPART_FORM_DATA) {\n throw new Error('[MINT SDK] Plugin download endpoints do not support multipart request bodies')\n }\n\n const parts = pluginEndpointRequestParts(contract, endpoint, payload, options.baseUrl)\n const api = useApi({\n baseUrl: parts.baseUrl,\n withAuth: endpoint.requiresAuth !== false,\n typedErrors: true,\n })\n const config = {\n ...(endpointRequestConfig(endpoint, parts.query, { signal: options.signal }) ?? {}),\n responseType: 'blob' as const,\n }\n const rawBody = requestBodyFromPayload(payload, parts.requestPayload, endpoint)\n const body = rawBody === undefined ? undefined : endpointRequestBody(endpoint, rawBody)\n let blob: Blob\n\n if (endpoint.method === 'get') blob = await api.get<Blob>(parts.path, config)\n else if (endpoint.method === 'post') blob = await api.post<Blob>(parts.path, body, config)\n else if (endpoint.method === 'put') blob = await api.put<Blob>(parts.path, body, config)\n else if (endpoint.method === 'patch') blob = await api.patch<Blob>(parts.path, body, config)\n else if (endpoint.method === 'delete') {\n blob = await api.delete<Blob>(parts.path, body === undefined ? config : { ...config, data: body })\n } else {\n throw new Error(`[MINT SDK] Unsupported plugin endpoint method: ${endpoint.method}`)\n }\n\n if (options.filename) {\n downloadBlob(blob, options.filename, {\n revokeObjectUrlDelayMs: options.revokeObjectUrlDelayMs,\n })\n }\n\n return blob\n}\n\nfunction normalizePluginSettingsOptions(options: UsePluginSettingsOptions | string = {}): UsePluginSettingsOptions {\n return typeof options === 'string' ? { pluginName: options } : options\n}\n\n/** @deprecated Use `useGeneratedPluginClient()` for generated clients. */\nexport function usePluginClient<TClient>(client: TClient): TClient {\n return client\n}\n\nconst PLATFORM_OWNED_SETTINGS_KEY = 'allowed_experiment_types'\n\n/**\n * Secret settings travel as `{ \"$secret\": \"<id>\" }` references, so an untouched\n * secret round-trips without ever exposing its value. Declaring the format on\n * every write keeps a `null` unambiguous: it clears the stored secret instead of\n * meaning \"unchanged\", which is what the deprecated placeholder form meant.\n */\nfunction withSecretFormat(\n payload: Record<string, unknown>,\n secretFormat: string | null,\n): Record<string, unknown> {\n if (!secretFormat) return payload\n return { ...payload, [PLUGIN_SECRET_FORMAT_KEY]: secretFormat }\n}\n\nfunction responseSecretFormat(response: unknown): string | null {\n if (!response || typeof response !== 'object') return null\n const format = (response as Record<string, unknown>)[PLUGIN_SECRET_FORMAT_KEY]\n return typeof format === 'string' && format ? format : null\n}\n\nfunction cloneRecord(value: Record<string, unknown>): Record<string, unknown> {\n return JSON.parse(JSON.stringify(value)) as Record<string, unknown>\n}\n\nfunction hasOwnSetting(settings: Record<string, unknown>, key: string): boolean {\n return Object.prototype.hasOwnProperty.call(settings, key)\n}\n\nfunction responseSettingsPayload(response: unknown): Record<string, unknown> {\n if (!response || typeof response !== 'object') return {}\n const data = response as {\n config?: unknown\n settings?: unknown\n }\n if (data.config && typeof data.config === 'object') {\n return cloneRecord(data.config as Record<string, unknown>)\n }\n if (data.settings && typeof data.settings === 'object') {\n return cloneRecord(data.settings as Record<string, unknown>)\n }\n return {}\n}\n\nfunction responseSettingsRevision(response: unknown): string | null {\n if (!response || typeof response !== 'object') return null\n const revision = (response as { revision?: unknown }).revision\n return typeof revision === 'string' && revision ? revision : null\n}\n\nfunction topLevelSettingsPatch(\n current: Record<string, unknown>,\n keys: Iterable<string>,\n): Record<string, unknown> {\n return Object.fromEntries(\n [...keys].map(key => [\n key,\n hasOwnSetting(current, key) ? current[key] : null,\n ]),\n )\n}\n\nfunction changedTopLevelSettingKeys(\n current: Record<string, unknown>,\n saved: Record<string, unknown>,\n): Set<string> {\n return new Set(\n [...new Set([...Object.keys(current), ...Object.keys(saved)])].filter(\n key => JSON.stringify(current[key]) !== JSON.stringify(saved[key]),\n ),\n )\n}\n\nfunction platformOwnedSettingsPatch(settings: Record<string, unknown>): Record<string, unknown> {\n return {\n [PLATFORM_OWNED_SETTINGS_KEY]: hasOwnSetting(settings, PLATFORM_OWNED_SETTINGS_KEY)\n ? settings[PLATFORM_OWNED_SETTINGS_KEY]\n : null,\n }\n}\n\n/** Load, edit, and persist plugin settings from platform config or the plugin-local settings router. */\nexport function usePluginSettings<TSettings = Record<string, unknown>>(\n options: UsePluginSettingsOptions | string = {},\n): UsePluginSettingsReturn<TSettings> {\n const resolvedOptions = normalizePluginSettingsOptions(options)\n const injectedContext = getInjectedPlatformContext()\n const { plugin, isIntegrated } = usePlatformContext()\n const platformApi = useApi({ baseUrl: resolvedOptions.platformApiBaseUrl ?? injectedContext?.platformApiUrl })\n const pluginApi = useApi({ baseUrl: resolvedOptions.apiBaseUrl ?? injectedContext?.plugin?.api_prefix })\n\n const values = ref({}) as Ref<PluginSettingsValues<TSettings>>\n const savedValues = shallowRef<Record<string, unknown>>({})\n const revision = ref<string | null>(null)\n const secretFormat = ref<string | null>(null)\n const request = useRequestSyncState('Plugin settings request failed.')\n const isLoading = ref(false)\n const isSaving = ref(false)\n\n const resolvedPluginName = computed(() =>\n resolvedOptions.pluginName ?? plugin.value?.name ?? injectedContext?.plugin?.name ?? '',\n )\n const usesPluginSettingsApi = computed(() => {\n const currentPlugin = injectedContext?.plugin ?? plugin.value\n return currentPlugin?.settings_api === 'plugin'\n && resolvedPluginName.value === currentPlugin.name\n })\n const usesPlatformConfig = computed(() =>\n Boolean(\n (isIntegrated.value || injectedContext?.isIntegrated)\n && resolvedPluginName.value\n && !usesPluginSettingsApi.value,\n ),\n )\n const settings = computed(() => values.value)\n const isDirty = computed(() => JSON.stringify(values.value) !== JSON.stringify(savedValues.value))\n const settingsConfig = computed<TopBarSettingsConfig>(() => ({\n title: resolvedOptions.title,\n schema: resolvedOptions.schema ?? undefined,\n showAppearance: resolvedOptions.showAppearance,\n values: values.value,\n }))\n\n function setValues(nextValues: Record<string, unknown>): void {\n values.value = cloneRecord(nextValues) as PluginSettingsValues<TSettings>\n }\n\n function applyLoaded(\n nextValues: Record<string, unknown>,\n nextRevision: string | null,\n nextSecretFormat: string | null = secretFormat.value,\n ): void {\n const cloned = cloneRecord(nextValues)\n values.value = cloned as PluginSettingsValues<TSettings>\n savedValues.value = cloneRecord(cloned)\n revision.value = nextRevision\n secretFormat.value = nextSecretFormat\n }\n\n async function load(): Promise<void> {\n isLoading.value = true\n try {\n const response = usesPlatformConfig.value\n ? await request.run(\n () => platformApi.get<{ plugin_name: string; config: Record<string, unknown> }>(\n `/plugins/${encodeURIComponent(resolvedPluginName.value)}/config`,\n ),\n { success: 'load', errorMessage: 'Failed to load plugin settings' },\n )\n : await request.run(\n () => pluginApi.get<{ settings: Record<string, unknown>; mode?: string }>('/settings'),\n { success: 'load', errorMessage: 'Failed to load plugin settings' },\n )\n applyLoaded(\n responseSettingsPayload(response),\n responseSettingsRevision(response),\n responseSecretFormat(response),\n )\n } catch {\n // Error state is handled by request.run().\n } finally {\n isLoading.value = false\n }\n }\n\n async function save(nextValues?: Record<string, unknown>): Promise<boolean> {\n if (nextValues) {\n setValues(nextValues)\n }\n\n isSaving.value = true\n try {\n const payload = cloneRecord(values.value)\n let response: unknown\n if (usesPlatformConfig.value) {\n const dirtyKeys = changedTopLevelSettingKeys(payload, savedValues.value)\n const platformOwnedChanged = dirtyKeys.has(PLATFORM_OWNED_SETTINGS_KEY)\n const typedKeys = [...dirtyKeys].filter(\n key => key !== PLATFORM_OWNED_SETTINGS_KEY,\n )\n let nextRevision = revision.value\n\n if (typedKeys.length) {\n response = await request.run(\n () => platformApi.patch<{\n plugin_name: string\n config: Record<string, unknown>\n revision?: string\n }>(\n `/plugins/${encodeURIComponent(resolvedPluginName.value)}/config`,\n {\n config: withSecretFormat(\n topLevelSettingsPatch(payload, typedKeys),\n secretFormat.value,\n ),\n },\n ),\n { success: 'save', errorMessage: 'Failed to save plugin settings' },\n )\n nextRevision = responseSettingsRevision(response) ?? nextRevision\n }\n\n if (platformOwnedChanged) {\n response = await request.run(\n () => platformApi.patch<{\n plugin_name: string\n config: Record<string, unknown>\n revision?: string\n }>(\n `/plugins/${encodeURIComponent(resolvedPluginName.value)}/config`,\n { config: platformOwnedSettingsPatch(payload) },\n ),\n { success: 'save', errorMessage: 'Failed to save plugin settings' },\n )\n nextRevision = responseSettingsRevision(response) ?? nextRevision\n }\n\n if (!response) return true\n applyLoaded(\n responseSettingsPayload(response),\n nextRevision,\n responseSecretFormat(response) ?? secretFormat.value,\n )\n return true\n } else {\n const ifMatch = revision.value\n ? { headers: { 'If-Match': `\"${revision.value}\"` } }\n : undefined\n response = await request.run(\n () => pluginApi.put<{\n settings: Record<string, unknown>\n mode?: string\n revision?: string\n }>('/settings', withSecretFormat(payload, secretFormat.value), ifMatch),\n { success: 'save', errorMessage: 'Failed to save plugin settings' },\n )\n }\n applyLoaded(\n responseSettingsPayload(response),\n responseSettingsRevision(response) ?? revision.value,\n responseSecretFormat(response) ?? secretFormat.value,\n )\n return true\n } catch {\n return false\n } finally {\n isSaving.value = false\n }\n }\n\n function reset(): void {\n values.value = cloneRecord(savedValues.value) as PluginSettingsValues<TSettings>\n request.clearError()\n }\n\n onMounted(() => {\n if (resolvedOptions.loadOnMount !== false) {\n void load()\n }\n })\n\n return {\n settings,\n values,\n config: values,\n settingsConfig,\n isLoading,\n isSaving,\n error: request.error,\n lastLoadedAt: request.lastLoadedAt,\n lastSavedAt: request.lastSavedAt,\n isDirty,\n setValues,\n load,\n save,\n reset,\n }\n}\n\nfunction streamRequestAuth(\n requestHeaders: HeadersInit | undefined,\n policy: { requiresAuth: boolean },\n): {\n headers: Headers\n token?: string\n} {\n const headers = new Headers(requestHeaders)\n const authStore = useAuthStore()\n if (!authStore.isInitialized) {\n authStore.initialize()\n }\n if (policy.requiresAuth && authStore.token && !headers.has('Authorization')) {\n headers.set('Authorization', `Bearer ${authStore.token}`)\n }\n const token = policy.requiresAuth ? authStore.token : undefined\n return {\n headers,\n token: token && headers.get('Authorization') === `Bearer ${token}` ? token : undefined,\n }\n}\n\nfunction pluginEventStreamTransport(\n endpoint: PluginEndpointDefinition,\n): EventStreamTransport {\n return async (url, init = {}) => {\n if (typeof fetch !== 'function') {\n throw new Error('[MINT SDK] fetch is required for plugin event streams.')\n }\n const requestAuth = streamRequestAuth(\n init.headers,\n { requiresAuth: endpoint.requiresAuth !== false },\n )\n const response = await fetch(url, { ...init, headers: requestAuth.headers })\n if (response.status === 401) {\n throw authenticationRequiredError(response, requestAuth.token)\n }\n return response\n }\n}\n\nfunction looksLikeEventStreamOptions(value: unknown): value is PluginEventStreamOptions {\n if (!value || typeof value !== 'object') return false\n const candidate = value as Record<string, unknown>\n return [\n 'baseUrl',\n 'immediate',\n 'reconnect',\n 'reconnectDelayMs',\n 'parseJson',\n 'credentials',\n 'headers',\n 'onOpen',\n 'onMessage',\n 'onError',\n ].some(key => key in candidate)\n}\n\n/** Consume a generated plugin SSE endpoint with auth headers, reconnect, and teardown. */\nexport function usePluginEventStream<TData = string>(\n contract: PluginContract,\n endpoint: PluginEndpointDefinition,\n options?: PluginEventStreamOptions<TData>,\n): UsePluginEventStreamReturn<TData>\nexport function usePluginEventStream<TData = string>(\n contract: PluginContract,\n endpoint: PluginEndpointDefinition,\n payload?: unknown,\n options?: PluginEventStreamOptions<TData>,\n): UsePluginEventStreamReturn<TData>\nexport function usePluginEventStream<TData = string>(\n contract: PluginContract,\n endpoint: PluginEndpointDefinition,\n payloadOrOptions?: unknown,\n maybeOptions?: PluginEventStreamOptions<TData>,\n): UsePluginEventStreamReturn<TData> {\n if (endpoint.method !== 'get') {\n throw new Error(`[MINT SDK] Plugin event streams must use GET; got ${endpoint.method}`)\n }\n const payload = maybeOptions === undefined && looksLikeEventStreamOptions(payloadOrOptions)\n ? undefined\n : payloadOrOptions\n const options = (\n maybeOptions === undefined && looksLikeEventStreamOptions(payloadOrOptions)\n ? payloadOrOptions\n : maybeOptions ?? {}\n ) as PluginEventStreamOptions<TData>\n const responseType = endpoint.responseType?.trim()\n const parseJson = options.parseJson ?? Boolean(responseType && responseType !== 'string')\n return useEventStream<TData>(\n () => buildPluginEndpointUrl(contract, endpoint, payload, { baseUrl: options.baseUrl }),\n {\n transport: pluginEventStreamTransport(endpoint),\n immediate: options.immediate,\n reconnect: options.reconnect,\n reconnectDelayMs: options.reconnectDelayMs,\n parseJson,\n credentials: options.credentials,\n headers: options.headers,\n shouldReconnect: cause => !(cause instanceof AuthenticationRequiredError),\n onOpen: options.onOpen,\n onMessage: options.onMessage,\n onError: options.onError,\n errorLabel: 'Plugin event stream',\n },\n )\n}\n\n/** Read and optionally load the current platform experiment for integrated plugin views. */\nexport function useCurrentExperiment<TExperiment = ExperimentSummary>(\n options: UseCurrentExperimentOptions = {},\n): UseCurrentExperimentReturn<TExperiment> {\n const api = useApi({ baseUrl: options.apiBaseUrl ?? getInjectedPlatformContext()?.platformApiUrl })\n const experiment = shallowRef<TExperiment | undefined>(currentExperimentFromContext<TExperiment>())\n const request = useRequestSyncState('Failed to load current experiment')\n const isLoading = request.loading\n const error = request.error\n const lastLoadedAt = request.lastLoadedAt\n\n const experimentId = computed<number | undefined>(() => {\n return resolveCurrentExperimentId()\n })\n const hasExperiment = computed(() => experimentId.value !== undefined)\n\n function requireExperimentId(): number {\n const id = experimentId.value\n if (id === undefined) {\n throw new Error('[MINT SDK] No current experiment is selected.')\n }\n return id\n }\n\n async function fetchExperiment(id = experimentId.value): Promise<TExperiment | undefined> {\n if (id === undefined) {\n experiment.value = currentExperimentFromContext<TExperiment>()\n return experiment.value\n }\n\n try {\n const result = await request.run(\n () => api.get<TExperiment>(`/experiments/${id}`),\n { success: 'load', errorMessage: 'Failed to load current experiment' },\n )\n experiment.value = result\n return result\n } catch (e) {\n experiment.value = undefined\n return undefined\n }\n }\n\n async function refresh(): Promise<TExperiment | undefined> {\n return fetchExperiment()\n }\n\n watch(\n experimentId,\n (id) => {\n if (options.immediate === false) return\n if (id === undefined) {\n experiment.value = currentExperimentFromContext<TExperiment>()\n return\n }\n void fetchExperiment(id)\n },\n { immediate: options.immediate !== false },\n )\n\n return {\n experimentId,\n hasExperiment,\n experiment,\n isLoading,\n error,\n lastLoadedAt,\n requireExperimentId,\n fetch: fetchExperiment,\n refresh,\n }\n}\n","import type { PickerAdapter, PickerNode, PickerRequest } from '../types/filePicker'\nimport type { FileDirectoryListing, ServerMount } from '../types/fileBrowserTypes'\nimport { useApi } from './useApi'\nimport { getInjectedPlatformContext } from './platformContextHelpers'\nimport { pickerFormat } from './filePicker/validation'\n\n/** Opaque picker identity; decode before passing a selection to a mount-scoped API. */\nexport function encodePlatformPickerPath(mountId: string, path = ''): string {\n return JSON.stringify([mountId, path])\n}\nexport function decodePlatformPickerPath(path: string): { mountId: string; path: string } {\n const decoded: unknown = JSON.parse(path)\n if (\n !Array.isArray(decoded) ||\n decoded.length !== 2 ||\n !decoded.every((item) => typeof item === 'string') ||\n !decoded[0]\n ) {\n throw new Error('Invalid platform picker path.')\n }\n return { mountId: decoded[0], path: decoded[1] }\n}\n\n/** Adapt the authenticated MINT mount API without exposing absolute host paths. */\nexport function usePlatformFilePickerAdapter(options: { apiBaseUrl?: string } = {}): PickerAdapter {\n const api = useApi({\n baseUrl: options.apiBaseUrl ?? getInjectedPlatformContext()?.platformApiUrl,\n })\n const mountLabels = new Map<string, string>()\n async function listRoot(request?: PickerRequest): Promise<PickerNode[]> {\n try {\n const { mounts } = await api.get<{ mounts: ServerMount[] }>('/filesystem/mounts', {\n signal: request?.signal,\n })\n return mounts.map((mount) => {\n mountLabels.set(mount.id, mount.label)\n return {\n kind: 'folder',\n path: encodePlatformPickerPath(mount.id),\n name: mount.label,\n parentPath: null,\n parentName: 'Server mounts',\n unavailableReason: mount.available === false ? 'This mount is offline.' : undefined,\n }\n })\n } catch (cause) {\n if ((cause as { response?: { status?: number } }).response?.status === 404) return []\n throw cause\n }\n }\n async function listChildren(path: string, request?: PickerRequest): Promise<PickerNode[]> {\n const location = decodePlatformPickerPath(path)\n const query = new URLSearchParams({ mount_id: location.mountId, path: location.path })\n const listing = await api.get<FileDirectoryListing>(`/filesystem/browse?${query}`, {\n signal: request?.signal,\n })\n if (listing.truncated)\n throw new Error(\n 'This directory exceeds the server listing limit. Choose a smaller data directory.',\n )\n return (listing.entries ?? []).map(\n (entry) =>\n ({\n kind: entry.kind === 'directory' ? 'folder' : 'file',\n path: encodePlatformPickerPath(location.mountId, entry.path),\n parentPath: path,\n parentName: `${mountLabels.get(location.mountId) ?? location.mountId}${location.path ? ` / ${location.path}` : ''}`,\n name: entry.name,\n bytes: entry.size_bytes,\n ...(entry.kind === 'directory'\n ? { hasChildren: entry.child_count !== 0 }\n : { format: pickerFormat(entry.name) }),\n }) as PickerNode,\n )\n }\n return {\n listRoot,\n listChildren,\n async search(query, scope, request) {\n const matches: PickerNode[] = []\n const queue = [scope.path]\n const visited = new Set<string>()\n while (queue.length) {\n request?.signal?.throwIfAborted()\n const path = queue.shift()!\n if (visited.has(path)) continue\n visited.add(path)\n if (visited.size > 500)\n throw new Error(\n 'Search reached its folder limit. Search a smaller location or turn off Subfolders.',\n )\n const nodes = path ? await listChildren(path, request) : await listRoot(request)\n for (const node of nodes) {\n if (node.name.toLowerCase().includes(query.toLowerCase())) matches.push(node)\n if (scope.recursive && node.kind === 'folder' && !node.unavailableReason)\n queue.push(node.path)\n }\n if (matches.length > 10000)\n throw new Error('Too many search results. Use a more specific search.')\n }\n return matches\n },\n }\n}\n"],"mappings":"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"}
|