@morscherlab/mint-sdk 1.1.25 → 1.2.0-beta.10
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 +44 -12
- package/dist/{ExperimentPopover-tLwJ7XF4.js → ExperimentPopover-oL0fg_A0.js} +6 -4
- package/dist/ExperimentPopover-oL0fg_A0.js.map +1 -0
- package/dist/{ExperimentSelectorModal-B6P2msT4.js → ExperimentSelectorModal-BeEOomw_.js} +5 -5
- package/dist/ExperimentSelectorModal-BeEOomw_.js.map +1 -0
- package/dist/{SettingsModal-BW3Ar-uy.js → SettingsModal-Dphh3RrI.js} +5 -8
- package/dist/SettingsModal-Dphh3RrI.js.map +1 -0
- package/dist/{EmptyState-p90quq8Z.js → Skeleton-DxtwJ5gt.js} +111 -93
- package/dist/Skeleton-DxtwJ5gt.js.map +1 -0
- package/dist/__tests__/components/ExperimentTimeline.test.d.ts +1 -0
- package/dist/__tests__/components/PluginWorkspaceView.internal.test.d.ts +1 -0
- package/dist/__tests__/components/SecretInput.test.d.ts +1 -0
- package/dist/__tests__/components/WellEditPopupInternal.test.d.ts +1 -0
- package/dist/__tests__/composables/useEventStream.test.d.ts +1 -0
- package/dist/__tests__/composables/useListReorder.test.d.ts +1 -0
- package/dist/__tests__/styles/cssTokens.test.d.ts +1 -0
- package/dist/components/ActionMenu.vue.d.ts +1 -1
- package/dist/components/AppAvatarMenu.vue.d.ts +4 -0
- package/dist/components/AppPluginSwitcher.vue.d.ts +2 -0
- package/dist/components/AppSidebar.vue.d.ts +1 -1
- package/dist/components/AuditTrail.vue.d.ts +13 -0
- package/dist/components/BatchProgressList.vue.d.ts +17 -0
- package/dist/components/BioTemplateExperimentWorkspaceView.vue.d.ts +1 -1
- package/dist/components/DataFrame.vue.d.ts +14 -2
- package/dist/components/DatePicker.vue.d.ts +1 -1
- package/dist/components/DateTimePicker.vue.d.ts +2 -0
- package/dist/components/DropdownButton.vue.d.ts +2 -0
- 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/FitPanel.vue.d.ts +1 -1
- package/dist/components/LcmsSequenceTable.vue.d.ts +29 -1
- package/dist/components/PluginWorkspaceView.props.d.ts +29 -1
- package/dist/components/PluginWorkspaceView.vue.d.ts +5 -5
- 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/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 +28 -0
- package/dist/components/SmartGroupFieldRecipe.vue.d.ts +2 -1
- package/dist/components/TimePicker.vue.d.ts +1 -0
- 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 +29 -0
- package/dist/components/index.d.ts +9 -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/WellEditPopupInternal.vue.d.ts +3 -1
- package/dist/components/internal/WorkspaceControlsInternal.vue.d.ts +23 -0
- package/dist/components/internal/WorkspaceShellInternal.vue.d.ts +70 -0
- package/dist/components/internal/WorkspaceSidebarInternal.vue.d.ts +43 -0
- package/dist/{components-DQt0tcpY.js → components-CgAUzF8F.js} +2491 -2235
- package/dist/components-CgAUzF8F.js.map +1 -0
- package/dist/composables/controlSchemaTypes.d.ts +34 -0
- package/dist/composables/flattenWorkspaceBindings.d.ts +61 -0
- package/dist/composables/index.d.ts +8 -2
- package/dist/composables/index.js +10 -10
- package/dist/composables/pluginWorkspaceModel.d.ts +164 -0
- package/dist/composables/useAsync.d.ts +5 -1
- package/dist/composables/useBioTemplateWorkspace.d.ts +4 -20
- package/dist/composables/useCommandHistory.d.ts +5 -1
- package/dist/composables/useDropdownState.d.ts +18 -2
- package/dist/composables/useEventStream.d.ts +52 -0
- package/dist/composables/useFocusTrap.d.ts +21 -0
- package/dist/composables/useJobsStatusTray.d.ts +1 -1
- package/dist/composables/useListReorder.d.ts +90 -0
- package/dist/composables/useMenuKeyboard.d.ts +29 -0
- package/dist/composables/useOptimisticMutation.d.ts +5 -1
- package/dist/composables/usePluginClient.d.ts +4 -17
- package/dist/composables/usePluginConfig.d.ts +3 -1
- package/dist/composables/usePluginWorkspace.d.ts +51 -0
- package/dist/composables/useRequestSyncState.d.ts +42 -2
- package/dist/composables/useResourceCrud.d.ts +5 -1
- package/dist/composables/useRovingFocus.d.ts +24 -0
- package/dist/composables/useScheduleDrag.d.ts +1 -0
- package/dist/composables/useWellPainting.d.ts +5 -1
- package/dist/composables/useWellPlateAdapter.d.ts +5 -1
- package/dist/composables/useWellPlateValidation.d.ts +5 -1
- package/dist/composables/workspaceRecipes.d.ts +188 -0
- package/dist/{composables-CkXDe7nm.js → composables-B_pia3hO.js} +105 -254
- package/dist/composables-B_pia3hO.js.map +1 -0
- package/dist/{useApi-CDBq6z23.js → errors-_W0-LbA6.js} +102 -3
- package/dist/errors-_W0-LbA6.js.map +1 -0
- package/dist/{experiment-Y9Iz7KYi.js → experiment-Cwl9AYxw.js} +3 -8
- package/dist/experiment-Cwl9AYxw.js.map +1 -0
- package/dist/{experiment-utils-CLnzPPq5.js → experiment-utils-DV3DrvE_.js} +70 -51
- package/dist/experiment-utils-DV3DrvE_.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 +11247 -29501
- package/dist/templates/builderReadUtils.d.ts +1 -1
- package/dist/templates/index.js +2 -4
- package/dist/{templates-CovvRZ-9.js → templates-Qq113pyZ.js} +303 -106
- package/dist/templates-Qq113pyZ.js.map +1 -0
- package/dist/types/form-builder.d.ts +1 -1
- package/dist/{useControlSchema-BhoJzWzx.js → useControlSchema-aMZlb4Sc.js} +684 -1216
- package/dist/useControlSchema-aMZlb4Sc.js.map +1 -0
- package/dist/{useDropdownState-DSb3BC3N.js → useDropdownState-DitCtrTT.js} +22 -6
- package/dist/useDropdownState-DitCtrTT.js.map +1 -0
- package/dist/{useExperimentSelector-D0pjj9WH.js → useExperimentSelector-I8HC8hUu.js} +4 -4
- package/dist/{useExperimentSelector-D0pjj9WH.js.map → useExperimentSelector-I8HC8hUu.js.map} +1 -1
- package/dist/{useFormBuilder-DiEcDis2.js → useFormBuilder-TCxNnqeb.js} +2 -2
- package/dist/{useFormBuilder-DiEcDis2.js.map → useFormBuilder-TCxNnqeb.js.map} +1 -1
- package/dist/{useProtocolTemplates-DHwSveE6.js → useProtocolTemplates-BmX_iVBR.js} +660 -197
- package/dist/useProtocolTemplates-BmX_iVBR.js.map +1 -0
- package/dist/utils/color.d.ts +13 -0
- package/dist/utils/errors.d.ts +9 -0
- package/dist/utils/pluginSecrets.d.ts +53 -0
- package/dist/utils/records.d.ts +4 -0
- package/package.json +1 -1
- package/src/__tests__/components/ActionMenu.test.ts +94 -0
- package/src/__tests__/components/AppAvatarMenu.test.ts +123 -0
- package/src/__tests__/components/BaseTabs.test.ts +67 -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/DropdownButton.test.ts +134 -0
- package/src/__tests__/components/ExperimentTimeline.test.ts +63 -0
- package/src/__tests__/components/GeneratedPluginView.test.ts +0 -5
- package/src/__tests__/components/GroupAssigner.test.ts +53 -0
- package/src/__tests__/components/JobsStatusTray.test.ts +20 -18
- package/src/__tests__/components/LcmsSequenceTable.test.ts +22 -0
- package/src/__tests__/components/PluginWorkspaceView.internal.test.ts +230 -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/SecretInput.test.ts +87 -0
- package/src/__tests__/components/SegmentedControl.test.ts +88 -0
- package/src/__tests__/components/TimePicker.test.ts +61 -0
- package/src/__tests__/components/WellEditPopupInternal.test.ts +108 -0
- package/src/__tests__/components/WellPlate.interaction.test.ts +59 -0
- package/src/__tests__/composables/useAuth.test.ts +25 -0
- package/src/__tests__/composables/useDropdownState.test.ts +58 -1
- package/src/__tests__/composables/useEventStream.test.ts +140 -0
- package/src/__tests__/composables/useGeneratedAnalysis.test.ts +103 -0
- package/src/__tests__/composables/useJobsStatusTray.test.ts +25 -161
- package/src/__tests__/composables/useListReorder.test.ts +145 -0
- package/src/__tests__/composables/usePluginClient.test.ts +148 -13
- package/src/__tests__/composables/useRequestSyncState.test.ts +140 -0
- package/src/__tests__/docs/frontendDocsCatalog.test.ts +55 -2
- 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/components/ActionMenu.vue +45 -88
- package/src/components/AlertBox.vue +0 -4
- package/src/components/AppAvatarMenu.vue +26 -7
- 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 +8 -60
- 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 +26 -5
- 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/BioTemplateExperimentWorkspaceView.vue +10 -21
- package/src/components/BioTemplatePackWorkspaceView.vue +11 -15
- package/src/components/BioTemplatePresetWorkspaceView.vue +8 -13
- 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/ComponentBindingRenderer.vue +1 -3
- package/src/components/ConcentrationInput.vue +0 -4
- package/src/components/ConfirmDialog.vue +0 -4
- package/src/components/ControlWorkspaceView.vue +11 -22
- 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/DoseDesignWorkspaceView.vue +6 -25
- package/src/components/DropdownButton.vue +24 -6
- 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 +2 -5
- 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/FileUploader.vue +0 -4
- 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 +3 -3
- 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 -4
- 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.story.vue +6 -10
- 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/PluginIcon.vue +0 -4
- package/src/components/PluginWorkspaceView.props.ts +38 -0
- package/src/components/PluginWorkspaceView.vue +53 -224
- 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/SecretInput.story.vue +79 -0
- package/src/components/SecretInput.vue +150 -0
- package/src/components/SectionCard.vue +0 -4
- package/src/components/SegmentedControl.vue +48 -5
- 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/index.ts +9 -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/FormSectionRenderer.vue +0 -4
- package/src/components/internal/WellEditPopupInternal.vue +20 -5
- package/src/components/internal/WorkspaceControlsInternal.vue +20 -0
- package/src/components/internal/WorkspaceShellInternal.vue +125 -0
- package/src/components/internal/WorkspaceSidebarInternal.vue +82 -0
- package/src/composables/controlSchemaTypes.ts +34 -0
- package/src/composables/experimentDesignData.ts +1 -3
- package/src/composables/flattenWorkspaceBindings.ts +104 -0
- package/src/composables/formBuilderRegistry.ts +5 -0
- package/src/composables/index.ts +41 -5
- package/src/composables/pluginWorkspaceModel.ts +182 -0
- package/src/composables/useAsync.ts +5 -1
- package/src/composables/useBioTemplatePackWorkspace.ts +15 -9
- package/src/composables/useBioTemplatePresetWorkspace.ts +14 -15
- package/src/composables/useBioTemplateWorkspace.ts +18 -43
- package/src/composables/useCommandHistory.ts +5 -1
- package/src/composables/useDropdownState.ts +35 -5
- package/src/composables/useEventStream.ts +326 -0
- package/src/composables/useFileImport.ts +2 -7
- package/src/composables/useFocusTrap.ts +91 -0
- package/src/composables/useGeneratedAnalysis.ts +46 -103
- package/src/composables/useJobsStatusTray.ts +1 -1
- package/src/composables/useListReorder.story.vue +143 -0
- package/src/composables/useListReorder.ts +242 -0
- package/src/composables/useMenuKeyboard.ts +90 -0
- package/src/composables/useOptimisticMutation.ts +6 -16
- package/src/composables/usePluginClient.ts +91 -252
- package/src/composables/usePluginConfig.ts +3 -1
- package/src/composables/usePluginWorkspace.ts +208 -0
- package/src/composables/useRackEditor.ts +2 -11
- package/src/composables/useRequestSyncState.ts +98 -28
- package/src/composables/useResourceCrud.ts +6 -16
- package/src/composables/useRovingFocus.ts +66 -0
- package/src/composables/useScheduleDrag.ts +37 -0
- package/src/composables/useWellPainting.ts +10 -30
- package/src/composables/useWellPlateAdapter.ts +5 -1
- package/src/composables/useWellPlateEditor.ts +1 -11
- package/src/composables/useWellPlateValidation.ts +5 -1
- package/src/composables/workspaceRecipes.ts +267 -0
- package/src/index.ts +16 -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/form-builder.css +5 -5
- 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/secret-input.css +60 -0
- package/src/styles/components/well-plate.css +8 -0
- package/src/styles/index.css +9 -0
- package/src/styles/variables.css +29 -0
- package/src/templates/builderPresetControls.ts +1 -1
- package/src/templates/builderReadUtils.ts +1 -3
- package/src/templates/componentPlateHelpers.ts +3 -1
- package/src/templates/componentTargetResolvers.ts +1 -3
- package/src/templates/controlSchemaTargets.ts +1 -3
- 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/form-builder.ts +1 -0
- package/src/utils/color.ts +51 -0
- package/src/utils/errors.ts +29 -0
- package/src/utils/formModelSync.ts +1 -3
- package/src/utils/pluginIcon.ts +1 -3
- package/src/utils/pluginSecrets.ts +102 -0
- package/src/utils/records.ts +9 -0
- package/dist/EmptyState-p90quq8Z.js.map +0 -1
- package/dist/ExperimentPopover-tLwJ7XF4.js.map +0 -1
- package/dist/ExperimentSelectorModal-B6P2msT4.js.map +0 -1
- package/dist/SettingsModal-BW3Ar-uy.js.map +0 -1
- package/dist/components-DQt0tcpY.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-CkXDe7nm.js.map +0 -1
- package/dist/experiment-Y9Iz7KYi.js.map +0 -1
- package/dist/experiment-utils-CLnzPPq5.js.map +0 -1
- package/dist/templates/builderDefaults.d.ts +0 -1
- package/dist/templates/plateGeometry.d.ts +0 -4
- package/dist/templates-CovvRZ-9.js.map +0 -1
- package/dist/useApi-CDBq6z23.js.map +0 -1
- package/dist/useControlSchema-BhoJzWzx.js.map +0 -1
- package/dist/useDropdownState-DSb3BC3N.js.map +0 -1
- package/dist/useProtocolTemplates-DHwSveE6.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 → components/DataStates.test.d.ts} +0 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { nextTick } from 'vue'
|
|
2
|
+
|
|
3
|
+
export interface UseMenuKeyboardOptions {
|
|
4
|
+
/** Returns the currently navigable items inside the open panel, in DOM order. */
|
|
5
|
+
items: () => HTMLElement[]
|
|
6
|
+
/** True while the panel is open. */
|
|
7
|
+
isOpen: () => boolean
|
|
8
|
+
/** Opens the panel. */
|
|
9
|
+
open: () => void
|
|
10
|
+
/** Closes the panel. When `returnFocus` is true, focus should return to the trigger. */
|
|
11
|
+
close: (returnFocus?: boolean) => void
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface UseMenuKeyboardReturn {
|
|
15
|
+
/**
|
|
16
|
+
* Bind to the trigger's `@keydown`. ArrowDown/Enter/Space open the panel (when
|
|
17
|
+
* closed) and focus its first item; ArrowUp opens it focused on the last item.
|
|
18
|
+
*/
|
|
19
|
+
handleTriggerKeydown: (event: KeyboardEvent) => void
|
|
20
|
+
/**
|
|
21
|
+
* Bind to the open panel's `@keydown`. ArrowUp/ArrowDown cycle focus with
|
|
22
|
+
* wraparound, Home/End jump to the first/last item, Escape closes and returns
|
|
23
|
+
* focus to the trigger, and Tab closes without moving focus.
|
|
24
|
+
*/
|
|
25
|
+
handlePanelKeydown: (event: KeyboardEvent) => void
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Shared keyboard contract for menu- and listbox-style disclosure panels (the
|
|
30
|
+
* WAI-ARIA menu button pattern). Used by ActionMenu, AppAvatarMenu and DropdownButton,
|
|
31
|
+
* each pairing it with `useDropdownState` for the disclosure state itself.
|
|
32
|
+
*/
|
|
33
|
+
export function useMenuKeyboard(options: UseMenuKeyboardOptions): UseMenuKeyboardReturn {
|
|
34
|
+
function focusItem(position: 'first' | 'last') {
|
|
35
|
+
void nextTick(() => {
|
|
36
|
+
const items = options.items()
|
|
37
|
+
const target = position === 'first' ? items[0] : items[items.length - 1]
|
|
38
|
+
target?.focus()
|
|
39
|
+
})
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function handleTriggerKeydown(event: KeyboardEvent) {
|
|
43
|
+
if (options.isOpen()) return
|
|
44
|
+
|
|
45
|
+
if (event.key === 'ArrowDown' || event.key === 'Enter' || event.key === ' ') {
|
|
46
|
+
event.preventDefault()
|
|
47
|
+
options.open()
|
|
48
|
+
focusItem('first')
|
|
49
|
+
return
|
|
50
|
+
}
|
|
51
|
+
if (event.key === 'ArrowUp') {
|
|
52
|
+
event.preventDefault()
|
|
53
|
+
options.open()
|
|
54
|
+
focusItem('last')
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function handlePanelKeydown(event: KeyboardEvent) {
|
|
59
|
+
const items = options.items()
|
|
60
|
+
const currentIndex = items.indexOf(document.activeElement as HTMLElement)
|
|
61
|
+
|
|
62
|
+
if (event.key === 'Escape') {
|
|
63
|
+
event.preventDefault()
|
|
64
|
+
options.close(true)
|
|
65
|
+
return
|
|
66
|
+
}
|
|
67
|
+
if (event.key === 'Tab') {
|
|
68
|
+
options.close()
|
|
69
|
+
return
|
|
70
|
+
}
|
|
71
|
+
if (event.key === 'Home') {
|
|
72
|
+
event.preventDefault()
|
|
73
|
+
items[0]?.focus()
|
|
74
|
+
return
|
|
75
|
+
}
|
|
76
|
+
if (event.key === 'End') {
|
|
77
|
+
event.preventDefault()
|
|
78
|
+
items[items.length - 1]?.focus()
|
|
79
|
+
return
|
|
80
|
+
}
|
|
81
|
+
if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') return
|
|
82
|
+
|
|
83
|
+
event.preventDefault()
|
|
84
|
+
const direction = event.key === 'ArrowDown' ? 1 : -1
|
|
85
|
+
const nextIndex = (Math.max(currentIndex, 0) + direction + items.length) % items.length
|
|
86
|
+
items[nextIndex]?.focus()
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return { handleTriggerKeydown, handlePanelKeydown }
|
|
90
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { computed, ref, shallowRef, type ComputedRef, type Ref, type ShallowRef } from 'vue'
|
|
2
|
+
import { readErrorMessage } from '../utils/errors'
|
|
2
3
|
|
|
3
4
|
export interface OptimisticMutationContext<TVariables, TSnapshot> {
|
|
4
5
|
variables: TVariables
|
|
@@ -32,7 +33,11 @@ export interface UseOptimisticMutationReturn<TVariables, TData, TSnapshot = unkn
|
|
|
32
33
|
reset: () => void
|
|
33
34
|
}
|
|
34
35
|
|
|
35
|
-
/**
|
|
36
|
+
/**
|
|
37
|
+
* Run async mutations with optional optimistic local updates and rollback.
|
|
38
|
+
*
|
|
39
|
+
* @deprecated Unused by the MINT platform and scheduled for removal in MINT 1.3; use `useRequestSyncState()` instead.
|
|
40
|
+
*/
|
|
36
41
|
export function useOptimisticMutation<TVariables, TData, TSnapshot = unknown>(
|
|
37
42
|
options: UseOptimisticMutationOptions<TVariables, TData, TSnapshot>,
|
|
38
43
|
): UseOptimisticMutationReturn<TVariables, TData, TSnapshot> {
|
|
@@ -90,18 +95,3 @@ export function useOptimisticMutation<TVariables, TData, TSnapshot = unknown>(
|
|
|
90
95
|
reset,
|
|
91
96
|
}
|
|
92
97
|
}
|
|
93
|
-
|
|
94
|
-
function readErrorMessage(value: unknown): string {
|
|
95
|
-
if (value instanceof Error && value.message) return value.message
|
|
96
|
-
if (typeof value === 'string' && value.trim()) return value
|
|
97
|
-
if (
|
|
98
|
-
typeof value === 'object'
|
|
99
|
-
&& value !== null
|
|
100
|
-
&& 'message' in value
|
|
101
|
-
&& typeof (value as { message?: unknown }).message === 'string'
|
|
102
|
-
&& (value as { message: string }).message.trim()
|
|
103
|
-
) {
|
|
104
|
-
return (value as { message: string }).message
|
|
105
|
-
}
|
|
106
|
-
return 'Request failed.'
|
|
107
|
-
}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
computed,
|
|
3
|
-
getCurrentInstance,
|
|
4
3
|
onMounted,
|
|
5
|
-
onUnmounted,
|
|
6
4
|
ref,
|
|
7
5
|
shallowRef,
|
|
8
6
|
watch,
|
|
@@ -17,6 +15,7 @@ import {
|
|
|
17
15
|
import { usePlatformContext } from './usePlatformContext'
|
|
18
16
|
import { useRequestSyncState } from './useRequestSyncState'
|
|
19
17
|
import { useAuthStore } from '../stores/auth'
|
|
18
|
+
import { PLUGIN_SECRET_FORMAT_KEY } from '../utils/pluginSecrets'
|
|
20
19
|
import {
|
|
21
20
|
currentExperimentFromContext,
|
|
22
21
|
getInjectedPlatformContext,
|
|
@@ -28,6 +27,12 @@ import {
|
|
|
28
27
|
pluginEndpointRequestParts,
|
|
29
28
|
requestBodyFromPayload,
|
|
30
29
|
} from './pluginEndpointBuilder'
|
|
30
|
+
import {
|
|
31
|
+
useEventStream,
|
|
32
|
+
type EventStreamMessage,
|
|
33
|
+
type EventStreamTransport,
|
|
34
|
+
type UseEventStreamReturn,
|
|
35
|
+
} from './useEventStream'
|
|
31
36
|
import type {
|
|
32
37
|
ExperimentSummary,
|
|
33
38
|
GeneratedJobDefinition,
|
|
@@ -204,13 +209,7 @@ export interface UsePluginSettingsReturn<TSettings = Record<string, unknown>> {
|
|
|
204
209
|
reset: () => void
|
|
205
210
|
}
|
|
206
211
|
|
|
207
|
-
export
|
|
208
|
-
event: string
|
|
209
|
-
data: TData
|
|
210
|
-
id?: string
|
|
211
|
-
retry?: number
|
|
212
|
-
raw: string
|
|
213
|
-
}
|
|
212
|
+
export type PluginEventStreamMessage<TData = string> = EventStreamMessage<TData>
|
|
214
213
|
|
|
215
214
|
export interface PluginEventStreamOptions<TData = string> {
|
|
216
215
|
/** Override the generated or platform-injected API base URL. */
|
|
@@ -232,15 +231,7 @@ export interface PluginEventStreamOptions<TData = string> {
|
|
|
232
231
|
onError?: (error: unknown) => void
|
|
233
232
|
}
|
|
234
233
|
|
|
235
|
-
export
|
|
236
|
-
isConnected: Ref<boolean>
|
|
237
|
-
isConnecting: Ref<boolean>
|
|
238
|
-
error: Ref<string | null>
|
|
239
|
-
lastMessage: Ref<PluginEventStreamMessage<TData> | null>
|
|
240
|
-
lastEventId: Ref<string | null>
|
|
241
|
-
start: () => void
|
|
242
|
-
stop: () => void
|
|
243
|
-
}
|
|
234
|
+
export type UsePluginEventStreamReturn<TData = string> = UseEventStreamReturn<TData>
|
|
244
235
|
|
|
245
236
|
export type PluginFormDataValue =
|
|
246
237
|
| string
|
|
@@ -544,16 +535,36 @@ export async function downloadPluginEndpoint(
|
|
|
544
535
|
return blob
|
|
545
536
|
}
|
|
546
537
|
|
|
547
|
-
|
|
538
|
+
function normalizePluginSettingsOptions(options: UsePluginSettingsOptions | string = {}): UsePluginSettingsOptions {
|
|
539
|
+
return typeof options === 'string' ? { pluginName: options } : options
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
/** @deprecated Use `useGeneratedPluginClient()` for generated clients. */
|
|
548
543
|
export function usePluginClient<TClient>(client: TClient): TClient {
|
|
549
544
|
return client
|
|
550
545
|
}
|
|
551
546
|
|
|
552
|
-
|
|
553
|
-
|
|
547
|
+
const PLATFORM_OWNED_SETTINGS_KEY = 'allowed_experiment_types'
|
|
548
|
+
|
|
549
|
+
/**
|
|
550
|
+
* Secret settings travel as `{ "$secret": "<id>" }` references, so an untouched
|
|
551
|
+
* secret round-trips without ever exposing its value. Declaring the format on
|
|
552
|
+
* every write keeps a `null` unambiguous: it clears the stored secret instead of
|
|
553
|
+
* meaning "unchanged", which is what the deprecated placeholder form meant.
|
|
554
|
+
*/
|
|
555
|
+
function withSecretFormat(
|
|
556
|
+
payload: Record<string, unknown>,
|
|
557
|
+
secretFormat: string | null,
|
|
558
|
+
): Record<string, unknown> {
|
|
559
|
+
if (!secretFormat) return payload
|
|
560
|
+
return { ...payload, [PLUGIN_SECRET_FORMAT_KEY]: secretFormat }
|
|
554
561
|
}
|
|
555
562
|
|
|
556
|
-
|
|
563
|
+
function responseSecretFormat(response: unknown): string | null {
|
|
564
|
+
if (!response || typeof response !== 'object') return null
|
|
565
|
+
const format = (response as Record<string, unknown>)[PLUGIN_SECRET_FORMAT_KEY]
|
|
566
|
+
return typeof format === 'string' && format ? format : null
|
|
567
|
+
}
|
|
557
568
|
|
|
558
569
|
function cloneRecord(value: Record<string, unknown>): Record<string, unknown> {
|
|
559
570
|
return JSON.parse(JSON.stringify(value)) as Record<string, unknown>
|
|
@@ -628,6 +639,7 @@ export function usePluginSettings<TSettings = Record<string, unknown>>(
|
|
|
628
639
|
const values = ref({}) as Ref<PluginSettingsValues<TSettings>>
|
|
629
640
|
const savedValues = shallowRef<Record<string, unknown>>({})
|
|
630
641
|
const revision = ref<string | null>(null)
|
|
642
|
+
const secretFormat = ref<string | null>(null)
|
|
631
643
|
const request = useRequestSyncState('Plugin settings request failed.')
|
|
632
644
|
const isLoading = ref(false)
|
|
633
645
|
const isSaving = ref(false)
|
|
@@ -660,11 +672,16 @@ export function usePluginSettings<TSettings = Record<string, unknown>>(
|
|
|
660
672
|
values.value = cloneRecord(nextValues) as PluginSettingsValues<TSettings>
|
|
661
673
|
}
|
|
662
674
|
|
|
663
|
-
function applyLoaded(
|
|
675
|
+
function applyLoaded(
|
|
676
|
+
nextValues: Record<string, unknown>,
|
|
677
|
+
nextRevision: string | null,
|
|
678
|
+
nextSecretFormat: string | null = secretFormat.value,
|
|
679
|
+
): void {
|
|
664
680
|
const cloned = cloneRecord(nextValues)
|
|
665
681
|
values.value = cloned as PluginSettingsValues<TSettings>
|
|
666
682
|
savedValues.value = cloneRecord(cloned)
|
|
667
683
|
revision.value = nextRevision
|
|
684
|
+
secretFormat.value = nextSecretFormat
|
|
668
685
|
}
|
|
669
686
|
|
|
670
687
|
async function load(): Promise<void> {
|
|
@@ -684,6 +701,7 @@ export function usePluginSettings<TSettings = Record<string, unknown>>(
|
|
|
684
701
|
applyLoaded(
|
|
685
702
|
responseSettingsPayload(response),
|
|
686
703
|
responseSettingsRevision(response),
|
|
704
|
+
responseSecretFormat(response),
|
|
687
705
|
)
|
|
688
706
|
} catch {
|
|
689
707
|
// Error state is handled by request.run().
|
|
@@ -717,7 +735,12 @@ export function usePluginSettings<TSettings = Record<string, unknown>>(
|
|
|
717
735
|
revision?: string
|
|
718
736
|
}>(
|
|
719
737
|
`/plugins/${encodeURIComponent(resolvedPluginName.value)}/config`,
|
|
720
|
-
{
|
|
738
|
+
{
|
|
739
|
+
config: withSecretFormat(
|
|
740
|
+
topLevelSettingsPatch(payload, typedKeys),
|
|
741
|
+
secretFormat.value,
|
|
742
|
+
),
|
|
743
|
+
},
|
|
721
744
|
),
|
|
722
745
|
{ success: 'save', errorMessage: 'Failed to save plugin settings' },
|
|
723
746
|
)
|
|
@@ -740,7 +763,11 @@ export function usePluginSettings<TSettings = Record<string, unknown>>(
|
|
|
740
763
|
}
|
|
741
764
|
|
|
742
765
|
if (!response) return true
|
|
743
|
-
applyLoaded(
|
|
766
|
+
applyLoaded(
|
|
767
|
+
responseSettingsPayload(response),
|
|
768
|
+
nextRevision,
|
|
769
|
+
responseSecretFormat(response) ?? secretFormat.value,
|
|
770
|
+
)
|
|
744
771
|
return true
|
|
745
772
|
} else {
|
|
746
773
|
const ifMatch = revision.value
|
|
@@ -751,13 +778,14 @@ export function usePluginSettings<TSettings = Record<string, unknown>>(
|
|
|
751
778
|
settings: Record<string, unknown>
|
|
752
779
|
mode?: string
|
|
753
780
|
revision?: string
|
|
754
|
-
}>('/settings', payload, ifMatch),
|
|
781
|
+
}>('/settings', withSecretFormat(payload, secretFormat.value), ifMatch),
|
|
755
782
|
{ success: 'save', errorMessage: 'Failed to save plugin settings' },
|
|
756
783
|
)
|
|
757
784
|
}
|
|
758
785
|
applyLoaded(
|
|
759
786
|
responseSettingsPayload(response),
|
|
760
787
|
responseSettingsRevision(response) ?? revision.value,
|
|
788
|
+
responseSecretFormat(response) ?? secretFormat.value,
|
|
761
789
|
)
|
|
762
790
|
return true
|
|
763
791
|
} catch {
|
|
@@ -797,13 +825,13 @@ export function usePluginSettings<TSettings = Record<string, unknown>>(
|
|
|
797
825
|
}
|
|
798
826
|
|
|
799
827
|
function streamRequestAuth(
|
|
800
|
-
|
|
828
|
+
requestHeaders: HeadersInit | undefined,
|
|
801
829
|
policy: { requiresAuth: boolean },
|
|
802
830
|
): {
|
|
803
831
|
headers: Headers
|
|
804
832
|
token?: string
|
|
805
833
|
} {
|
|
806
|
-
const headers = new Headers(
|
|
834
|
+
const headers = new Headers(requestHeaders)
|
|
807
835
|
const authStore = useAuthStore()
|
|
808
836
|
if (!authStore.isInitialized) {
|
|
809
837
|
authStore.initialize()
|
|
@@ -811,7 +839,6 @@ function streamRequestAuth(
|
|
|
811
839
|
if (policy.requiresAuth && authStore.token && !headers.has('Authorization')) {
|
|
812
840
|
headers.set('Authorization', `Bearer ${authStore.token}`)
|
|
813
841
|
}
|
|
814
|
-
headers.set('Accept', 'text/event-stream')
|
|
815
842
|
const token = policy.requiresAuth ? authStore.token : undefined
|
|
816
843
|
return {
|
|
817
844
|
headers,
|
|
@@ -819,40 +846,22 @@ function streamRequestAuth(
|
|
|
819
846
|
}
|
|
820
847
|
}
|
|
821
848
|
|
|
822
|
-
function
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
let retry: number | undefined
|
|
829
|
-
const dataLines: string[] = []
|
|
830
|
-
|
|
831
|
-
for (const line of block.split(/\r?\n/)) {
|
|
832
|
-
if (!line || line.startsWith(':')) continue
|
|
833
|
-
const separator = line.indexOf(':')
|
|
834
|
-
const field = separator === -1 ? line : line.slice(0, separator)
|
|
835
|
-
const value = separator === -1
|
|
836
|
-
? ''
|
|
837
|
-
: line.slice(separator + 1).replace(/^ /, '')
|
|
838
|
-
|
|
839
|
-
if (field === 'event') event = value || 'message'
|
|
840
|
-
if (field === 'data') dataLines.push(value)
|
|
841
|
-
if (field === 'id') id = value
|
|
842
|
-
if (field === 'retry') {
|
|
843
|
-
const parsed = Number(value)
|
|
844
|
-
if (Number.isFinite(parsed)) retry = parsed
|
|
849
|
+
function pluginEventStreamTransport(
|
|
850
|
+
endpoint: PluginEndpointDefinition,
|
|
851
|
+
): EventStreamTransport {
|
|
852
|
+
return async (url, init = {}) => {
|
|
853
|
+
if (typeof fetch !== 'function') {
|
|
854
|
+
throw new Error('[MINT SDK] fetch is required for plugin event streams.')
|
|
845
855
|
}
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
raw: block,
|
|
856
|
+
const requestAuth = streamRequestAuth(
|
|
857
|
+
init.headers,
|
|
858
|
+
{ requiresAuth: endpoint.requiresAuth !== false },
|
|
859
|
+
)
|
|
860
|
+
const response = await fetch(url, { ...init, headers: requestAuth.headers })
|
|
861
|
+
if (response.status === 401) {
|
|
862
|
+
throw authenticationRequiredError(response, requestAuth.token)
|
|
863
|
+
}
|
|
864
|
+
return response
|
|
856
865
|
}
|
|
857
866
|
}
|
|
858
867
|
|
|
@@ -891,6 +900,9 @@ export function usePluginEventStream<TData = string>(
|
|
|
891
900
|
payloadOrOptions?: unknown,
|
|
892
901
|
maybeOptions?: PluginEventStreamOptions<TData>,
|
|
893
902
|
): UsePluginEventStreamReturn<TData> {
|
|
903
|
+
if (endpoint.method !== 'get') {
|
|
904
|
+
throw new Error(`[MINT SDK] Plugin event streams must use GET; got ${endpoint.method}`)
|
|
905
|
+
}
|
|
894
906
|
const payload = maybeOptions === undefined && looksLikeEventStreamOptions(payloadOrOptions)
|
|
895
907
|
? undefined
|
|
896
908
|
: payloadOrOptions
|
|
@@ -899,198 +911,25 @@ export function usePluginEventStream<TData = string>(
|
|
|
899
911
|
? payloadOrOptions
|
|
900
912
|
: maybeOptions ?? {}
|
|
901
913
|
) as PluginEventStreamOptions<TData>
|
|
902
|
-
const isConnected = ref(false)
|
|
903
|
-
const isConnecting = ref(false)
|
|
904
|
-
const error = ref<string | null>(null)
|
|
905
|
-
const lastMessage = shallowRef<PluginEventStreamMessage<TData> | null>(null)
|
|
906
|
-
const lastEventId = ref<string | null>(null)
|
|
907
914
|
const responseType = endpoint.responseType?.trim()
|
|
908
915
|
const parseJson = options.parseJson ?? Boolean(responseType && responseType !== 'string')
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
&& generation === connectionGeneration
|
|
927
|
-
&& controller === connectionController
|
|
928
|
-
}
|
|
929
|
-
|
|
930
|
-
function scheduleReconnect(connectionGeneration: number): void {
|
|
931
|
-
if (
|
|
932
|
-
stopped
|
|
933
|
-
|| generation !== connectionGeneration
|
|
934
|
-
|| options.reconnect === false
|
|
935
|
-
) return
|
|
936
|
-
clearReconnectTimer()
|
|
937
|
-
reconnectTimer = setTimeout(() => {
|
|
938
|
-
reconnectTimer = null
|
|
939
|
-
if (stopped || generation !== connectionGeneration) return
|
|
940
|
-
void connect(connectionGeneration)
|
|
941
|
-
}, options.reconnectDelayMs ?? 2000)
|
|
942
|
-
}
|
|
943
|
-
|
|
944
|
-
async function connect(connectionGeneration: number): Promise<void> {
|
|
945
|
-
if (stopped || generation !== connectionGeneration) return
|
|
946
|
-
if (endpoint.method !== 'get') {
|
|
947
|
-
throw new Error(`[MINT SDK] Plugin event streams must use GET; got ${endpoint.method}`)
|
|
948
|
-
}
|
|
949
|
-
if (typeof fetch !== 'function') {
|
|
950
|
-
throw new Error('[MINT SDK] fetch is required for plugin event streams.')
|
|
951
|
-
}
|
|
952
|
-
|
|
953
|
-
controller?.abort()
|
|
954
|
-
const connectionController = new AbortController()
|
|
955
|
-
controller = connectionController
|
|
956
|
-
isConnecting.value = true
|
|
957
|
-
if (!ownsConnection(connectionGeneration, connectionController)) return
|
|
958
|
-
error.value = null
|
|
959
|
-
if (!ownsConnection(connectionGeneration, connectionController)) return
|
|
960
|
-
|
|
961
|
-
let authenticationFailed = false
|
|
962
|
-
try {
|
|
963
|
-
const url = buildPluginEndpointUrl(contract, endpoint, payload, {
|
|
964
|
-
baseUrl: options.baseUrl,
|
|
965
|
-
})
|
|
966
|
-
const requestAuth = streamRequestAuth(
|
|
967
|
-
options as PluginEventStreamOptions<unknown>,
|
|
968
|
-
{ requiresAuth: endpoint.requiresAuth !== false },
|
|
969
|
-
)
|
|
970
|
-
const response = await fetch(url, {
|
|
971
|
-
method: 'GET',
|
|
972
|
-
headers: requestAuth.headers,
|
|
973
|
-
credentials: options.credentials ?? 'same-origin',
|
|
974
|
-
signal: connectionController.signal,
|
|
975
|
-
})
|
|
976
|
-
|
|
977
|
-
if (!ownsConnection(connectionGeneration, connectionController)) return
|
|
978
|
-
|
|
979
|
-
if (!response.ok) {
|
|
980
|
-
if (response.status === 401) {
|
|
981
|
-
authenticationFailed = true
|
|
982
|
-
throw authenticationRequiredError(response, requestAuth.token)
|
|
983
|
-
}
|
|
984
|
-
throw new Error(`Plugin event stream failed with HTTP ${response.status}`)
|
|
985
|
-
}
|
|
986
|
-
if (!response.body) {
|
|
987
|
-
throw new Error('Plugin event stream response did not include a readable body.')
|
|
988
|
-
}
|
|
989
|
-
|
|
990
|
-
isConnected.value = true
|
|
991
|
-
if (!ownsConnection(connectionGeneration, connectionController)) return
|
|
992
|
-
options.onOpen?.()
|
|
993
|
-
if (!ownsConnection(connectionGeneration, connectionController)) return
|
|
994
|
-
const reader = response.body.getReader()
|
|
995
|
-
const decoder = new TextDecoder()
|
|
996
|
-
let buffer = ''
|
|
997
|
-
|
|
998
|
-
for (;;) {
|
|
999
|
-
const { value, done } = await reader.read()
|
|
1000
|
-
if (!ownsConnection(connectionGeneration, connectionController)) return
|
|
1001
|
-
if (done) break
|
|
1002
|
-
buffer += decoder.decode(value, { stream: true })
|
|
1003
|
-
|
|
1004
|
-
let boundary = buffer.search(/\r?\n\r?\n/)
|
|
1005
|
-
while (boundary !== -1) {
|
|
1006
|
-
const block = buffer.slice(0, boundary)
|
|
1007
|
-
buffer = buffer.slice(buffer[boundary] === '\r' ? boundary + 4 : boundary + 2)
|
|
1008
|
-
const message = parseSseEvent<TData>(block, parseJson)
|
|
1009
|
-
if (message) {
|
|
1010
|
-
lastMessage.value = message
|
|
1011
|
-
if (!ownsConnection(connectionGeneration, connectionController)) return
|
|
1012
|
-
if (message.id !== undefined) {
|
|
1013
|
-
lastEventId.value = message.id
|
|
1014
|
-
if (!ownsConnection(connectionGeneration, connectionController)) return
|
|
1015
|
-
}
|
|
1016
|
-
if (message.retry !== undefined) {
|
|
1017
|
-
options.reconnectDelayMs = message.retry
|
|
1018
|
-
}
|
|
1019
|
-
if (!ownsConnection(connectionGeneration, connectionController)) return
|
|
1020
|
-
options.onMessage?.(message)
|
|
1021
|
-
if (!ownsConnection(connectionGeneration, connectionController)) return
|
|
1022
|
-
}
|
|
1023
|
-
boundary = buffer.search(/\r?\n\r?\n/)
|
|
1024
|
-
}
|
|
1025
|
-
}
|
|
1026
|
-
} catch (err) {
|
|
1027
|
-
if (err instanceof AuthenticationRequiredError) authenticationFailed = true
|
|
1028
|
-
if (
|
|
1029
|
-
ownsConnection(connectionGeneration, connectionController)
|
|
1030
|
-
&& !(err instanceof DOMException && err.name === 'AbortError')
|
|
1031
|
-
) {
|
|
1032
|
-
const message = err instanceof Error ? err.message : 'Plugin event stream failed'
|
|
1033
|
-
error.value = message
|
|
1034
|
-
if (ownsConnection(connectionGeneration, connectionController)) {
|
|
1035
|
-
options.onError?.(err)
|
|
1036
|
-
}
|
|
1037
|
-
}
|
|
1038
|
-
} finally {
|
|
1039
|
-
if (ownsConnection(connectionGeneration, connectionController)) {
|
|
1040
|
-
isConnecting.value = false
|
|
1041
|
-
if (ownsConnection(connectionGeneration, connectionController)) {
|
|
1042
|
-
isConnected.value = false
|
|
1043
|
-
if (ownsConnection(connectionGeneration, connectionController)) {
|
|
1044
|
-
controller = null
|
|
1045
|
-
if (authenticationFailed) {
|
|
1046
|
-
stopped = true
|
|
1047
|
-
} else {
|
|
1048
|
-
scheduleReconnect(connectionGeneration)
|
|
1049
|
-
}
|
|
1050
|
-
}
|
|
1051
|
-
}
|
|
1052
|
-
}
|
|
1053
|
-
}
|
|
1054
|
-
}
|
|
1055
|
-
|
|
1056
|
-
function start(): void {
|
|
1057
|
-
if (!stopped) return
|
|
1058
|
-
stopped = false
|
|
1059
|
-
clearReconnectTimer()
|
|
1060
|
-
generation += 1
|
|
1061
|
-
void connect(generation)
|
|
1062
|
-
}
|
|
1063
|
-
|
|
1064
|
-
function stop(): void {
|
|
1065
|
-
if (stopped) return
|
|
1066
|
-
stopped = true
|
|
1067
|
-
generation += 1
|
|
1068
|
-
clearReconnectTimer()
|
|
1069
|
-
controller?.abort()
|
|
1070
|
-
controller = null
|
|
1071
|
-
isConnecting.value = false
|
|
1072
|
-
isConnected.value = false
|
|
1073
|
-
}
|
|
1074
|
-
|
|
1075
|
-
const currentInstance = getCurrentInstance()
|
|
1076
|
-
if (currentInstance && options.immediate !== false && typeof window === 'undefined') {
|
|
1077
|
-
onMounted(start)
|
|
1078
|
-
}
|
|
1079
|
-
if (currentInstance) onUnmounted(stop)
|
|
1080
|
-
|
|
1081
|
-
if (options.immediate !== false && (typeof window !== 'undefined' || !currentInstance)) {
|
|
1082
|
-
start()
|
|
1083
|
-
}
|
|
1084
|
-
|
|
1085
|
-
return {
|
|
1086
|
-
isConnected,
|
|
1087
|
-
isConnecting,
|
|
1088
|
-
error,
|
|
1089
|
-
lastMessage,
|
|
1090
|
-
lastEventId,
|
|
1091
|
-
start,
|
|
1092
|
-
stop,
|
|
1093
|
-
}
|
|
916
|
+
return useEventStream<TData>(
|
|
917
|
+
() => buildPluginEndpointUrl(contract, endpoint, payload, { baseUrl: options.baseUrl }),
|
|
918
|
+
{
|
|
919
|
+
transport: pluginEventStreamTransport(endpoint),
|
|
920
|
+
immediate: options.immediate,
|
|
921
|
+
reconnect: options.reconnect,
|
|
922
|
+
reconnectDelayMs: options.reconnectDelayMs,
|
|
923
|
+
parseJson,
|
|
924
|
+
credentials: options.credentials,
|
|
925
|
+
headers: options.headers,
|
|
926
|
+
shouldReconnect: cause => !(cause instanceof AuthenticationRequiredError),
|
|
927
|
+
onOpen: options.onOpen,
|
|
928
|
+
onMessage: options.onMessage,
|
|
929
|
+
onError: options.onError,
|
|
930
|
+
errorLabel: 'Plugin event stream',
|
|
931
|
+
},
|
|
932
|
+
)
|
|
1094
933
|
}
|
|
1095
934
|
|
|
1096
935
|
/** Read and optionally load the current platform experiment for integrated plugin views. */
|
|
@@ -75,7 +75,9 @@ export interface UsePluginConfigReturn {
|
|
|
75
75
|
reset: () => void
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
/**
|
|
78
|
+
/**
|
|
79
|
+
* @deprecated Unused by the MINT platform and scheduled for removal in MINT 1.3; use `usePluginSettings()` for typed plugin settings.
|
|
80
|
+
*/
|
|
79
81
|
export function usePluginConfig(pluginName?: string): UsePluginConfigReturn {
|
|
80
82
|
const injectedContext = getInjectedPlatformContext()
|
|
81
83
|
const { plugin } = usePlatformContext()
|