@morscherlab/mint-sdk 1.0.63 → 1.1.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.
Files changed (181) hide show
  1. package/README.md +119 -6
  2. package/dist/EmptyState-DgBRoYAy.js +647 -0
  3. package/dist/EmptyState-DgBRoYAy.js.map +1 -0
  4. package/dist/{ExperimentPopover-BbPkIFsI.js → ExperimentPopover-BFw3QX8L.js} +10 -9
  5. package/dist/{ExperimentPopover-BbPkIFsI.js.map → ExperimentPopover-BFw3QX8L.js.map} +1 -1
  6. package/dist/{ExperimentSelectorModal-DZeSd-yr.js → ExperimentSelectorModal-BBWXC7KW.js} +12 -216
  7. package/dist/ExperimentSelectorModal-BBWXC7KW.js.map +1 -0
  8. package/dist/{SettingsModal-CJgLadsN.js → SettingsModal-Dpg-X1OM.js} +12 -9
  9. package/dist/{SettingsModal-CJgLadsN.js.map → SettingsModal-Dpg-X1OM.js.map} +1 -1
  10. package/dist/__tests__/components/BaseToggle.test.d.ts +1 -0
  11. package/dist/__tests__/components/GeneratedPathInput.test.d.ts +1 -0
  12. package/dist/__tests__/components/GeneratedPlotlyResult.test.d.ts +1 -0
  13. package/dist/__tests__/components/GeneratedPluginView.test.d.ts +1 -0
  14. package/dist/__tests__/components/GeneratedResultRenderer.test.d.ts +1 -0
  15. package/dist/__tests__/components/InstrumentAlertLog.test.d.ts +1 -0
  16. package/dist/__tests__/components/SectionCard.test.d.ts +1 -0
  17. package/dist/__tests__/composables/useGeneratedAnalysis.test.d.ts +1 -0
  18. package/dist/__tests__/generatedUi.test.d.ts +1 -0
  19. package/dist/__tests__/types/GeneratedJsonSchema.test.d.ts +1 -0
  20. package/dist/{analysisArtifactTypes-Cu40dzSG.js → analysisArtifactTypes-ejqR8MX3.js} +1 -1
  21. package/dist/{analysisArtifactTypes-Cu40dzSG.js.map → analysisArtifactTypes-ejqR8MX3.js.map} +1 -1
  22. package/dist/{auth-DZAwEeis.js → auth-B87xM--s.js} +1 -1
  23. package/dist/{auth-DZAwEeis.js.map → auth-B87xM--s.js.map} +1 -1
  24. package/dist/chunk-BoAXSpZd.js +33 -0
  25. package/dist/components/AppSidebar.vue.d.ts +1 -1
  26. package/dist/components/AutoGroupModal.vue.d.ts +2 -2
  27. package/dist/components/BaseSelect.vue.d.ts +1 -1
  28. package/dist/components/BaseToggle.vue.d.ts +2 -0
  29. package/dist/components/BioTemplateExperimentWorkspaceView.vue.d.ts +2 -2
  30. package/dist/components/CollapsibleCard.vue.d.ts +1 -1
  31. package/dist/components/ComponentBindingRenderer.vue.d.ts +1 -1
  32. package/dist/components/ConfirmDialog.vue.d.ts +1 -1
  33. package/dist/components/ExperimentDataViewer.vue.d.ts +1 -1
  34. package/dist/components/ExperimentTimeline.vue.d.ts +1 -1
  35. package/dist/components/FileUploader.vue.d.ts +4 -2
  36. package/dist/components/FitPanel.vue.d.ts +2 -2
  37. package/dist/components/FormActions.vue.d.ts +1 -1
  38. package/dist/components/FormBuilder.vue.d.ts +1 -1
  39. package/dist/components/GeneratedPathInput.vue.d.ts +12 -0
  40. package/dist/components/GeneratedPlotlyResult.vue.d.ts +11 -0
  41. package/dist/components/GeneratedPluginView.vue.d.ts +10 -0
  42. package/dist/components/GeneratedResultRenderer.vue.d.ts +6 -0
  43. package/dist/components/JobsStatusTray.vue.d.ts +5 -1
  44. package/dist/components/LcmsSequenceTable.vue.d.ts +1 -1
  45. package/dist/components/PluginWorkspaceView.props.d.ts +1 -1
  46. package/dist/components/SampleLegend.vue.d.ts +1 -1
  47. package/dist/components/SampleSelector.vue.d.ts +2 -2
  48. package/dist/components/SectionCard.vue.d.ts +47 -0
  49. package/dist/components/SettingsModal.vue.d.ts +1 -1
  50. package/dist/components/SmartGroupFieldRecipe.vue.d.ts +2 -2
  51. package/dist/components/index.d.ts +5 -0
  52. package/dist/components/index.js +8 -9
  53. package/dist/components/internal/PlateMapEditorToolbarInternal.vue.d.ts +2 -2
  54. package/dist/{components-DdzHh3a_.js → components-Ci_BTx00.js} +2322 -2292
  55. package/dist/components-Ci_BTx00.js.map +1 -0
  56. package/dist/composables/index.d.ts +3 -2
  57. package/dist/composables/index.js +10 -11
  58. package/dist/composables/useGeneratedAnalysis.d.ts +62 -0
  59. package/dist/composables/useJobsStatusTray.d.ts +48 -4
  60. package/dist/composables/usePlatformContext.d.ts +3 -0
  61. package/dist/composables/usePluginClient.d.ts +17 -8
  62. package/dist/{composables-BUUphBqg.js → composables-C0VEJ73O.js} +154 -38
  63. package/dist/composables-C0VEJ73O.js.map +1 -0
  64. package/dist/experiment-utils-CxkruZ3G.js +392 -0
  65. package/dist/experiment-utils-CxkruZ3G.js.map +1 -0
  66. package/dist/generated/schema.d.ts +7 -0
  67. package/dist/generated-ui/main.d.ts +0 -0
  68. package/dist/index.d.ts +1 -0
  69. package/dist/index.js +15 -18
  70. package/dist/index.js.map +1 -1
  71. package/dist/install.js +7 -8
  72. package/dist/install.js.map +1 -1
  73. package/dist/plotly.min-BR53hja4.js +180634 -0
  74. package/dist/plotly.min-BR53hja4.js.map +1 -0
  75. package/dist/stores/auth.d.ts +2 -2
  76. package/dist/stores/index.js +1 -1
  77. package/dist/styles.css +8657 -8217
  78. package/dist/tailwind.preset.d.ts +5 -0
  79. package/dist/tailwind.preset.js +7 -2
  80. package/dist/tailwind.preset.js.map +1 -1
  81. package/dist/templates/index.js +4 -3
  82. package/dist/templates/packs.d.ts +0 -1
  83. package/dist/{templates-CNbPQNID.js → templates-Cdj93S9C.js} +2 -4
  84. package/dist/templates-Cdj93S9C.js.map +1 -0
  85. package/dist/types/components.d.ts +2 -0
  86. package/dist/types/form-builder.d.ts +1 -1
  87. package/dist/types/generated-ui.d.ts +183 -0
  88. package/dist/types/index.d.ts +2 -1
  89. package/dist/types/index.js +1 -1
  90. package/dist/types/instrument.d.ts +1 -0
  91. package/dist/types/jobs.d.ts +7 -1
  92. package/dist/types/platform.d.ts +2 -0
  93. package/dist/{useControlSchema-BZNdalmL.js → useControlSchema-B_qgU4rW.js} +1882 -172
  94. package/dist/useControlSchema-B_qgU4rW.js.map +1 -0
  95. package/dist/{useDropdownState-Bb-c_PeE.js → useDropdownState-gVaMXtwW.js} +2 -2
  96. package/dist/{useDropdownState-Bb-c_PeE.js.map → useDropdownState-gVaMXtwW.js.map} +1 -1
  97. package/dist/{useExperimentSelector-DRbj6vse.js → useExperimentSelector-BuQZRgMt.js} +4 -255
  98. package/dist/useExperimentSelector-BuQZRgMt.js.map +1 -0
  99. package/dist/{useFormBuilder-DKekvXRs.js → useFormBuilder-D1G5J5Z5.js} +2 -2
  100. package/dist/{useFormBuilder-DKekvXRs.js.map → useFormBuilder-D1G5J5Z5.js.map} +1 -1
  101. package/dist/{useAnalysisArtifacts-C3l0a0vu.js → useProtocolTemplates-DeaOmMaw.js} +307 -475
  102. package/dist/useProtocolTemplates-DeaOmMaw.js.map +1 -0
  103. package/package.json +7 -3
  104. package/src/__tests__/components/BaseSelect.test.ts +52 -0
  105. package/src/__tests__/components/BaseToggle.test.ts +40 -0
  106. package/src/__tests__/components/GeneratedPathInput.test.ts +132 -0
  107. package/src/__tests__/components/GeneratedPlotlyResult.test.ts +117 -0
  108. package/src/__tests__/components/GeneratedPluginView.test.ts +240 -0
  109. package/src/__tests__/components/GeneratedResultRenderer.test.ts +93 -0
  110. package/src/__tests__/components/InstrumentAlertLog.test.ts +59 -0
  111. package/src/__tests__/components/PluginWorkspaceView.test.ts +68 -14
  112. package/src/__tests__/components/SectionCard.test.ts +181 -0
  113. package/src/__tests__/composables/formBuilderRegistry.test.ts +5 -1
  114. package/src/__tests__/composables/useApi.test.ts +8 -0
  115. package/src/__tests__/composables/useGeneratedAnalysis.test.ts +1742 -0
  116. package/src/__tests__/composables/useJobsStatusTray.test.ts +179 -1
  117. package/src/__tests__/composables/usePlatformContext.test.ts +28 -0
  118. package/src/__tests__/composables/usePluginClient.test.ts +402 -21
  119. package/src/__tests__/composables/usePluginConfig.test.ts +323 -7
  120. package/src/__tests__/docs/extractDocsTemplates.test.ts +0 -1
  121. package/src/__tests__/generatedUi.test.ts +119 -0
  122. package/src/__tests__/templates/templates.test.ts +1 -1
  123. package/src/__tests__/types/GeneratedJsonSchema.test.ts +62 -0
  124. package/src/components/BaseSelect.vue +16 -2
  125. package/src/components/BaseToggle.vue +3 -1
  126. package/src/components/FileUploader.vue +49 -11
  127. package/src/components/GeneratedPathInput.vue +218 -0
  128. package/src/components/GeneratedPlotlyResult.vue +87 -0
  129. package/src/components/GeneratedPluginView.vue +279 -0
  130. package/src/components/GeneratedResultRenderer.vue +137 -0
  131. package/src/components/InstrumentAlertLog.vue +2 -2
  132. package/src/components/JobsStatusTray.vue +14 -8
  133. package/src/components/PluginWorkspaceView.props.ts +1 -1
  134. package/src/components/PluginWorkspaceView.vue +1 -5
  135. package/src/components/SectionCard.story.vue +163 -0
  136. package/src/components/SectionCard.vue +98 -0
  137. package/src/components/index.ts +5 -0
  138. package/src/composables/formBuilderRegistry.ts +2 -0
  139. package/src/composables/index.ts +19 -0
  140. package/src/composables/useApi.ts +1 -0
  141. package/src/composables/useGeneratedAnalysis.ts +1270 -0
  142. package/src/composables/useJobsStatusTray.ts +234 -45
  143. package/src/composables/usePluginClient.ts +164 -30
  144. package/src/composables/usePluginConfig.ts +156 -20
  145. package/src/generated/schema.ts +130 -0
  146. package/src/generated-ui/main.ts +21 -0
  147. package/src/index.ts +3 -0
  148. package/src/jobs.ts +5 -0
  149. package/src/plotly-dist.d.ts +3 -0
  150. package/src/styles/components/section-card.css +161 -0
  151. package/src/styles/index.css +1 -0
  152. package/src/styles/variables.css +25 -0
  153. package/src/tailwind.preset.ts +5 -0
  154. package/src/templates/packs.ts +0 -3
  155. package/src/types/components.ts +12 -0
  156. package/src/types/form-builder.ts +1 -0
  157. package/src/types/generated-ui.ts +189 -0
  158. package/src/types/index.ts +4 -0
  159. package/src/types/instrument.ts +1 -0
  160. package/src/types/jobs.ts +10 -1
  161. package/src/types/platform.ts +2 -0
  162. package/dist/BaseButton-Dgqrze41.js +0 -74
  163. package/dist/BaseButton-Dgqrze41.js.map +0 -1
  164. package/dist/BaseModal-B9UA8Y_I.js +0 -165
  165. package/dist/BaseModal-B9UA8Y_I.js.map +0 -1
  166. package/dist/BaseSelect-ekgr9fDo.js +0 -179
  167. package/dist/BaseSelect-ekgr9fDo.js.map +0 -1
  168. package/dist/ExperimentPopover-Ryusjrhv.js +0 -4
  169. package/dist/ExperimentSelectorModal-Cg4-LXBD.js +0 -5
  170. package/dist/ExperimentSelectorModal-DZeSd-yr.js.map +0 -1
  171. package/dist/SettingsModal-Bl_9w2Y3.js +0 -5
  172. package/dist/components-DdzHh3a_.js.map +0 -1
  173. package/dist/composables-BUUphBqg.js.map +0 -1
  174. package/dist/experiment-utils-Bfa7CwPU.js +0 -108
  175. package/dist/experiment-utils-Bfa7CwPU.js.map +0 -1
  176. package/dist/templates-CNbPQNID.js.map +0 -1
  177. package/dist/useAnalysisArtifacts-C3l0a0vu.js.map +0 -1
  178. package/dist/useControlSchema-BZNdalmL.js.map +0 -1
  179. package/dist/useEventListener-CfVkP9Xz.js +0 -57
  180. package/dist/useEventListener-CfVkP9Xz.js.map +0 -1
  181. package/dist/useExperimentSelector-DRbj6vse.js.map +0 -1
@@ -2,7 +2,12 @@ import { mount } from '@vue/test-utils'
2
2
  import { defineComponent, nextTick, ref, shallowRef } from 'vue'
3
3
  import { describe, expect, it, vi } from 'vitest'
4
4
 
5
- import { useJobsStatusTray, type UseJobsStatusTrayOptions } from '../../composables/useJobsStatusTray'
5
+ import {
6
+ combinePluginJobSources,
7
+ useJobsStatusTray,
8
+ usePluginJobCenter,
9
+ type UseJobsStatusTrayOptions,
10
+ } from '../../composables/useJobsStatusTray'
6
11
  import type { JobState, JobStateInput, JobStatus } from '../../types/jobs'
7
12
 
8
13
  function job(status: JobStatus, id: string = status): JobStateInput {
@@ -62,6 +67,179 @@ function deferred<T>(): {
62
67
  }
63
68
 
64
69
  describe('useJobsStatusTray', () => {
70
+ it('combines live source jobs and fans out or routes source actions', async () => {
71
+ const firstJobs = shallowRef([job('running', 'first')])
72
+ const secondJobs = shallowRef([job('completed', 'second')])
73
+ const firstRefresh = vi.fn(async () => firstJobs.value)
74
+ const secondRefresh = vi.fn(async () => secondJobs.value)
75
+ const secondCancel = vi.fn(async (jobId: string) => job('cancelled', jobId))
76
+ const firstClear = vi.fn(async () => 1)
77
+ const secondClear = vi.fn(async () => 2)
78
+ const firstDispose = vi.fn()
79
+ const secondDispose = vi.fn()
80
+ const combined = combinePluginJobSources([
81
+ {
82
+ jobs: firstJobs,
83
+ refreshJobs: firstRefresh,
84
+ clearFinishedJobs: firstClear,
85
+ dispose: firstDispose,
86
+ },
87
+ {
88
+ jobs: secondJobs,
89
+ refreshJobs: secondRefresh,
90
+ cancelJob: secondCancel,
91
+ clearFinishedJobs: secondClear,
92
+ dispose: secondDispose,
93
+ },
94
+ ])
95
+
96
+ expect(combined.jobs.value.map(item => item.job_id)).toEqual(['first', 'second'])
97
+ secondJobs.value = [job('running', 'replacement')]
98
+ await nextTick()
99
+ expect(combined.jobs.value.map(item => item.job_id)).toEqual(['first', 'replacement'])
100
+
101
+ await combined.refreshJobs?.()
102
+ await combined.cancelJob?.('replacement')
103
+ await expect(combined.clearFinishedJobs?.()).resolves.toBe(3)
104
+ combined.dispose?.()
105
+
106
+ expect({
107
+ refreshes: [firstRefresh.mock.calls.length, secondRefresh.mock.calls.length],
108
+ cancelled: secondCancel.mock.calls[0]?.[0],
109
+ disposed: [firstDispose.mock.calls.length, secondDispose.mock.calls.length],
110
+ }).toEqual({
111
+ refreshes: [1, 1],
112
+ cancelled: 'replacement',
113
+ disposed: [1, 1],
114
+ })
115
+ })
116
+
117
+ it('retains every failure when disposing combined sources', () => {
118
+ const firstFailure = new Error('first dispose failed')
119
+ const secondFailure = { source: 'second', reason: 'dispose failed' }
120
+ const finalDispose = vi.fn()
121
+ const combined = combinePluginJobSources([
122
+ {
123
+ jobs: [],
124
+ dispose: () => {
125
+ throw firstFailure
126
+ },
127
+ },
128
+ {
129
+ jobs: [],
130
+ dispose: () => {
131
+ throw secondFailure
132
+ },
133
+ },
134
+ { jobs: [], dispose: finalDispose },
135
+ ])
136
+
137
+ let failure: unknown
138
+ try {
139
+ combined.dispose?.()
140
+ } catch (cause) {
141
+ failure = cause
142
+ }
143
+
144
+ expect(failure).toMatchObject({
145
+ name: 'PluginJobSourceDisposeError',
146
+ message: 'Failed to dispose plugin job sources',
147
+ cause: firstFailure,
148
+ errors: [firstFailure, secondFailure],
149
+ })
150
+ expect(finalDispose).toHaveBeenCalledOnce()
151
+ })
152
+
153
+ it('rejects duplicate ids instead of routing to an arbitrary combined source', async () => {
154
+ const firstCancel = vi.fn(async () => undefined)
155
+ const secondCancel = vi.fn(async () => undefined)
156
+ const combined = combinePluginJobSources([
157
+ { jobs: [job('running', 'duplicate')], cancelJob: firstCancel },
158
+ { jobs: [job('queued', 'duplicate')], cancelJob: secondCancel },
159
+ ])
160
+
161
+ expect(() => combined.jobs.value).toThrow('Duplicate plugin job id')
162
+ await expect(combined.cancelJob?.('duplicate')).rejects.toThrow('Duplicate plugin job id')
163
+ expect([firstCancel.mock.calls.length, secondCancel.mock.calls.length]).toEqual([0, 0])
164
+ })
165
+
166
+ it('does not expose a partial bulk clear across combined sources', () => {
167
+ const combined = combinePluginJobSources([
168
+ { jobs: [job('completed', 'first')], clearFinishedJobs: async () => 1 },
169
+ { jobs: [job('completed', 'second')] },
170
+ ])
171
+
172
+ expect(combined.clearFinishedJobs).toBeUndefined()
173
+ })
174
+
175
+ it('does not partially delete finished jobs when one combined source cannot delete', async () => {
176
+ const firstDelete = vi.fn(async () => true)
177
+ const combined = combinePluginJobSources([
178
+ { jobs: [job('completed', 'first')], deleteJob: firstDelete },
179
+ { jobs: [job('completed', 'second')] },
180
+ ])
181
+ let center!: ReturnType<typeof usePluginJobCenter>
182
+ const wrapper = mount(defineComponent({
183
+ setup() {
184
+ center = usePluginJobCenter({ source: combined, loadOnMount: false })
185
+ return () => null
186
+ },
187
+ }))
188
+
189
+ expect(combined.deleteJob).toBeUndefined()
190
+ expect(center.canClearFinished.value).toBe(false)
191
+ await expect(center.clearFinished()).resolves.toBe(false)
192
+ expect(firstDelete).not.toHaveBeenCalled()
193
+
194
+ wrapper.unmount()
195
+ })
196
+
197
+ it('derives jobs directly from a canonical source ref', async () => {
198
+ const sourceJobs = shallowRef([job('queued', 'first')])
199
+ let center!: ReturnType<typeof usePluginJobCenter>
200
+ const wrapper = mount(defineComponent({
201
+ setup() {
202
+ center = usePluginJobCenter({
203
+ source: { jobs: sourceJobs },
204
+ loadOnMount: false,
205
+ })
206
+ return () => null
207
+ },
208
+ }))
209
+
210
+ sourceJobs.value = [job('running', 'replacement')]
211
+ await nextTick()
212
+
213
+ expect(center.jobs.value.map(item => item.job_id)).toEqual(['replacement'])
214
+ wrapper.unmount()
215
+ })
216
+
217
+ it('delegates actions by id and leaves source mutation with the source', async () => {
218
+ const sourceJobs = shallowRef([job('running', 'fit')])
219
+ const cancelJob = vi.fn(async (jobId: string) => {
220
+ sourceJobs.value = [job('cancelled', jobId)]
221
+ return sourceJobs.value[0]
222
+ })
223
+ let center!: ReturnType<typeof usePluginJobCenter>
224
+ const wrapper = mount(defineComponent({
225
+ setup() {
226
+ center = usePluginJobCenter({
227
+ source: { jobs: sourceJobs, cancelJob },
228
+ loadOnMount: false,
229
+ })
230
+ return () => null
231
+ },
232
+ }))
233
+
234
+ await center.cancelJob(center.jobs.value[0]!)
235
+
236
+ expect([cancelJob.mock.calls[0]?.[0], center.jobs.value[0]?.status]).toEqual([
237
+ 'fit',
238
+ 'cancelled',
239
+ ])
240
+ wrapper.unmount()
241
+ })
242
+
65
243
  it('keeps awaiting input jobs in the active group', () => {
66
244
  const { tray } = mountComposable({
67
245
  jobs: [job('awaiting_input')],
@@ -17,6 +17,11 @@ vi.mock('vue', async () => {
17
17
  })
18
18
 
19
19
  import { usePlatformContext } from '../../composables/usePlatformContext'
20
+ import type { PlatformContext } from '../../types'
21
+
22
+ type InjectedPlatformWindow = Window & {
23
+ __MINT_PLATFORM__?: PlatformContext
24
+ }
20
25
 
21
26
  function sendThemeMessage(origin: string, theme: 'light' | 'dark' | 'system'): void {
22
27
  if (!messageHandler) {
@@ -37,6 +42,7 @@ describe('usePlatformContext', () => {
37
42
  beforeEach(() => {
38
43
  unmountedCallbacks.length = 0
39
44
  messageHandler = null
45
+ delete (window as InjectedPlatformWindow).__MINT_PLATFORM__
40
46
 
41
47
  vi.spyOn(window, 'addEventListener').mockImplementation((type, listener) => {
42
48
  if (type === 'message') {
@@ -51,9 +57,31 @@ describe('usePlatformContext', () => {
51
57
  const callback = unmountedCallbacks.pop()
52
58
  callback?.()
53
59
  }
60
+ delete (window as InjectedPlatformWindow).__MINT_PLATFORM__
54
61
  vi.restoreAllMocks()
55
62
  })
56
63
 
64
+ it('preserves the injected plugin settings API capability', () => {
65
+ const injectedContext: PlatformContext = {
66
+ isIntegrated: true,
67
+ theme: 'light',
68
+ platformApiUrl: '/api',
69
+ plugin: {
70
+ id: 'test-plugin',
71
+ name: 'test-plugin',
72
+ version: '1.0.0',
73
+ route_prefix: '/test-plugin',
74
+ api_prefix: '/api/test-plugin',
75
+ settings_api: 'plugin',
76
+ },
77
+ }
78
+ ;(window as InjectedPlatformWindow).__MINT_PLATFORM__ = injectedContext
79
+
80
+ const context = usePlatformContext()
81
+
82
+ expect(context.plugin.value?.settings_api).toBe('plugin')
83
+ })
84
+
57
85
  it('clears allowAnyOrigin policy after last consumer unmounts', () => {
58
86
  const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})
59
87