@morscherlab/mint-sdk 1.1.25 → 1.2.0-beta.2

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 (72) hide show
  1. package/README.md +9 -7
  2. package/dist/{ExperimentSelectorModal-B6P2msT4.js → ExperimentSelectorModal-DyPAUCLw.js} +3 -3
  3. package/dist/{ExperimentSelectorModal-B6P2msT4.js.map → ExperimentSelectorModal-DyPAUCLw.js.map} +1 -1
  4. package/dist/{SettingsModal-BW3Ar-uy.js → SettingsModal-BgKY93zh.js} +4 -4
  5. package/dist/{SettingsModal-BW3Ar-uy.js.map → SettingsModal-BgKY93zh.js.map} +1 -1
  6. package/dist/__tests__/composables/useEventStream.test.d.ts +1 -0
  7. package/dist/components/AutoGroupModal.vue.d.ts +1 -1
  8. package/dist/components/BioTemplateExperimentWorkspaceView.vue.d.ts +1 -1
  9. package/dist/components/JobsStatusTray.vue.d.ts +2 -9
  10. package/dist/components/SampleLegend.vue.d.ts +1 -1
  11. package/dist/components/SampleSelector.vue.d.ts +1 -1
  12. package/dist/components/SettingsModal.vue.d.ts +1 -1
  13. package/dist/components/SmartGroupFieldRecipe.vue.d.ts +1 -1
  14. package/dist/components/index.js +4 -4
  15. package/dist/{components-DQt0tcpY.js → components-DkHddRMl.js} +10 -16
  16. package/dist/components-DkHddRMl.js.map +1 -0
  17. package/dist/composables/index.d.ts +2 -3
  18. package/dist/composables/index.js +8 -8
  19. package/dist/composables/useEventStream.d.ts +43 -0
  20. package/dist/composables/useGeneratedAnalysis.d.ts +1 -3
  21. package/dist/composables/useJobsStatusTray.d.ts +1 -25
  22. package/dist/composables/usePluginClient.d.ts +3 -18
  23. package/dist/{composables-CkXDe7nm.js → composables-C_i90sGS.js} +32 -308
  24. package/dist/composables-C_i90sGS.js.map +1 -0
  25. package/dist/{experiment-Y9Iz7KYi.js → experiment-Cq145oEW.js} +2 -2
  26. package/dist/{experiment-Y9Iz7KYi.js.map → experiment-Cq145oEW.js.map} +1 -1
  27. package/dist/index.js +12 -12
  28. package/dist/install.js +4 -4
  29. package/dist/stores/auth.d.ts +0 -6
  30. package/dist/stores/index.js +2 -2
  31. package/dist/templates/index.js +2 -2
  32. package/dist/{templates-CovvRZ-9.js → templates-DsP51i-S.js} +2 -2
  33. package/dist/{templates-CovvRZ-9.js.map → templates-DsP51i-S.js.map} +1 -1
  34. package/dist/types/auth.d.ts +0 -1
  35. package/dist/{useApi-CDBq6z23.js → useApi-J6zFkHmn.js} +1 -2
  36. package/dist/useApi-J6zFkHmn.js.map +1 -0
  37. package/dist/{useControlSchema-BhoJzWzx.js → useControlSchema-BDx2Olha.js} +239 -103
  38. package/dist/useControlSchema-BDx2Olha.js.map +1 -0
  39. package/dist/{useExperimentSelector-D0pjj9WH.js → useExperimentSelector-CV4iNfMS.js} +2 -2
  40. package/dist/{useExperimentSelector-D0pjj9WH.js.map → useExperimentSelector-CV4iNfMS.js.map} +1 -1
  41. package/dist/{useFormBuilder-DiEcDis2.js → useFormBuilder-BLxG3BOX.js} +2 -2
  42. package/dist/{useFormBuilder-DiEcDis2.js.map → useFormBuilder-BLxG3BOX.js.map} +1 -1
  43. package/dist/{useProtocolTemplates-DHwSveE6.js → useProtocolTemplates-CS_SQl6U.js} +22 -113
  44. package/dist/useProtocolTemplates-CS_SQl6U.js.map +1 -0
  45. package/package.json +1 -1
  46. package/src/__tests__/components/GeneratedPluginView.test.ts +0 -5
  47. package/src/__tests__/components/JobsStatusTray.test.ts +20 -18
  48. package/src/__tests__/composables/useAuth.test.ts +23 -0
  49. package/src/__tests__/composables/useEventStream.test.ts +140 -0
  50. package/src/__tests__/composables/useGeneratedAnalysis.test.ts +103 -0
  51. package/src/__tests__/composables/useJobsStatusTray.test.ts +25 -161
  52. package/src/__tests__/composables/usePluginClient.test.ts +8 -13
  53. package/src/__tests__/docs/frontendDocsCatalog.test.ts +22 -1
  54. package/src/components/JobsStatusTray.story.vue +6 -10
  55. package/src/components/JobsStatusTray.vue +1 -16
  56. package/src/composables/index.ts +0 -7
  57. package/src/composables/useAuth.ts +0 -3
  58. package/src/composables/useEventStream.ts +314 -0
  59. package/src/composables/useGeneratedAnalysis.ts +40 -109
  60. package/src/composables/useJobsStatusTray.ts +17 -184
  61. package/src/composables/usePluginClient.ts +45 -249
  62. package/src/stores/auth.ts +0 -1
  63. package/src/types/auth.ts +0 -1
  64. package/dist/__tests__/composables/usePluginConfig.test.d.ts +0 -15
  65. package/dist/components-DQt0tcpY.js.map +0 -1
  66. package/dist/composables/usePluginConfig.d.ts +0 -25
  67. package/dist/composables-CkXDe7nm.js.map +0 -1
  68. package/dist/useApi-CDBq6z23.js.map +0 -1
  69. package/dist/useControlSchema-BhoJzWzx.js.map +0 -1
  70. package/dist/useProtocolTemplates-DHwSveE6.js.map +0 -1
  71. package/src/__tests__/composables/usePluginConfig.test.ts +0 -497
  72. package/src/composables/usePluginConfig.ts +0 -250
@@ -1,9 +1,9 @@
1
1
  import { d as resolveExperimentCode } from "./experiment-utils-CLnzPPq5.js";
2
2
  import { r as useRequestSyncState } from "./EmptyState-p90quq8Z.js";
3
- import { A as useConcentrationUnits, H as parseExperimentId, J as isActiveJobStatus, Q as normalizeJobState, U as resolveCurrentExperimentId, V as getInjectedPlatformContext, u as useControlWorkspace } from "./useControlSchema-BhoJzWzx.js";
4
- import { o as useSettingsStore, r as useApi } from "./useApi-CDBq6z23.js";
5
- import { t as useExperimentStore } from "./experiment-Y9Iz7KYi.js";
6
- import { B as toBioTemplateComponentProps, F as getBioTemplateComponentProps$1, H as toBioTemplateComponentPropsById, Jt as getBioTemplatePresetInfo, L as toBioTemplateComponentBindings, P as getBioTemplateComponentBindings, Qt as getBioTemplatePackInfo, R as toBioTemplateComponentBindingsById, U as toBioTemplateComponentSnippets, V as toBioTemplateComponentPropsByComponent$1, W as toBioTemplateComponentUsage, d as createBioTemplatePresetCollectionFromControls, dn as extractTemplateCollection, i as createBioTemplateControlToolkit, p as createBioTemplatePackCollection, sn as createTemplateCollection, u as createBioTemplatePresetCollection, un as ensureTemplateFromCollection, z as toBioTemplateComponentImports } from "./templates-CovvRZ-9.js";
3
+ import { A as useConcentrationUnits, H as parseExperimentId, J as isActiveJobStatus, Q as normalizeJobState, U as resolveCurrentExperimentId, V as getInjectedPlatformContext, u as useControlWorkspace } from "./useControlSchema-BDx2Olha.js";
4
+ import { o as useSettingsStore, r as useApi } from "./useApi-J6zFkHmn.js";
5
+ import { t as useExperimentStore } from "./experiment-Cq145oEW.js";
6
+ import { B as toBioTemplateComponentProps, F as getBioTemplateComponentProps$1, H as toBioTemplateComponentPropsById, Jt as getBioTemplatePresetInfo, L as toBioTemplateComponentBindings, P as getBioTemplateComponentBindings, Qt as getBioTemplatePackInfo, R as toBioTemplateComponentBindingsById, U as toBioTemplateComponentSnippets, V as toBioTemplateComponentPropsByComponent$1, W as toBioTemplateComponentUsage, d as createBioTemplatePresetCollectionFromControls, dn as extractTemplateCollection, i as createBioTemplateControlToolkit, p as createBioTemplatePackCollection, sn as createTemplateCollection, u as createBioTemplatePresetCollection, un as ensureTemplateFromCollection, z as toBioTemplateComponentImports } from "./templates-DsP51i-S.js";
7
7
  import { computed, effectScope, getCurrentScope, inject, onMounted, onScopeDispose, onUnmounted, provide, reactive, readonly, ref, shallowRef, toRaw, toValue, unref, watch } from "vue";
8
8
  //#region src/composables/useSortedItems.ts
9
9
  /** Shared sorting for SDK tables and lists with stable empty-value handling. */
@@ -601,12 +601,6 @@ var PluginJobSourceDisposeError = class extends Error {
601
601
  function duplicatePluginJobId(jobId) {
602
602
  return /* @__PURE__ */ new Error(`Duplicate plugin job id across combined sources: ${jobId}`);
603
603
  }
604
- function responseJobs(response) {
605
- return "jobs" in response ? response.jobs : response;
606
- }
607
- function isSnapshotPayload(data) {
608
- return "jobs" in data && Array.isArray(data.jobs);
609
- }
610
604
  function errorMessage(error, fallback) {
611
605
  return error instanceof Error ? error.message : fallback;
612
606
  }
@@ -617,94 +611,38 @@ function errorMessage(error, fallback) {
617
611
  * source. The controller never mirrors source jobs into another ref.
618
612
  */
619
613
  function usePluginJobCenter(options = {}) {
620
- const legacyOverride = shallowRef(null);
621
614
  const isOpen = ref(false);
622
615
  const activeTab = ref("active");
623
616
  const isLoading = ref(false);
624
617
  const error = shallowRef(null);
625
618
  const pendingJobIds = ref(/* @__PURE__ */ new Set());
626
- const jobRevisions = /* @__PURE__ */ new Map();
627
- let stateRevision = 0;
628
619
  let requestGeneration = 0;
629
620
  let active = true;
630
621
  const source = computed(() => toValue(options.source));
631
- const adapter = computed(() => toValue(options.adapter));
632
- const jobs = computed(() => {
633
- const currentSource = source.value;
634
- if (currentSource) return [...toValue(currentSource.jobs)].map(normalizeJobState);
635
- const input = toValue(options.jobs);
636
- const override = legacyOverride.value;
637
- if (override && override.input === input) return override.jobs;
638
- return input ? [...input].map(normalizeJobState) : [];
639
- });
622
+ const jobs = computed(() => source.value ? [...toValue(source.value.jobs)].map(normalizeJobState) : []);
640
623
  const activeJobs = computed(() => jobs.value.filter((job) => isActiveJobStatus(job.status)));
641
624
  const historyJobs = computed(() => jobs.value.filter((job) => !isActiveJobStatus(job.status)));
642
625
  const deletableJobs = computed(() => historyJobs.value.filter((job) => job.can_delete));
643
626
  const featuredJob = computed(() => activeJobs.value[0] ?? historyJobs.value[0] ?? null);
644
- const canRefresh = computed(() => Boolean(source.value?.refreshJobs || adapter.value?.listJobs));
645
- const canCancel = computed(() => Boolean(source.value?.cancelJob || adapter.value?.cancelJob));
646
- const canDelete = computed(() => Boolean(source.value?.deleteJob || adapter.value?.deleteJob));
647
- const canClearFinished = computed(() => Boolean(source.value?.clearFinishedJobs || source.value?.deleteJob || adapter.value?.clearFinishedJobs || adapter.value?.deleteJob));
648
- function bumpJobRevision(jobId) {
649
- jobRevisions.set(jobId, (jobRevisions.get(jobId) ?? 0) + 1);
650
- }
651
- function replaceLegacyJobs(nextJobs) {
652
- const normalized = nextJobs.map(normalizeJobState);
653
- new Set([...jobs.value.map((job) => job.job_id), ...normalized.map((job) => job.job_id)]).forEach(bumpJobRevision);
654
- legacyOverride.value = {
655
- input: toValue(options.jobs),
656
- jobs: normalized
657
- };
658
- stateRevision += 1;
659
- }
660
- function upsertLegacyJob(nextJob) {
661
- const normalized = normalizeJobState(nextJob);
662
- const existingIndex = jobs.value.findIndex((job) => job.job_id === normalized.job_id);
663
- const nextJobs = [...jobs.value];
664
- if (existingIndex === -1) nextJobs.unshift(normalized);
665
- else nextJobs[existingIndex] = normalized;
666
- legacyOverride.value = {
667
- input: toValue(options.jobs),
668
- jobs: nextJobs
669
- };
670
- bumpJobRevision(normalized.job_id);
671
- stateRevision += 1;
672
- }
673
- function removeLegacyJobs(jobIds) {
674
- legacyOverride.value = {
675
- input: toValue(options.jobs),
676
- jobs: jobs.value.filter((job) => !jobIds.has(job.job_id))
677
- };
678
- jobIds.forEach(bumpJobRevision);
679
- stateRevision += 1;
680
- }
627
+ const canRefresh = computed(() => Boolean(source.value?.refreshJobs));
628
+ const canCancel = computed(() => Boolean(source.value?.cancelJob));
629
+ const canDelete = computed(() => Boolean(source.value?.deleteJob));
630
+ const canClearFinished = computed(() => Boolean(source.value?.clearFinishedJobs || source.value?.deleteJob));
681
631
  function setPending(jobId, pending) {
682
632
  const next = new Set(pendingJobIds.value);
683
633
  if (pending) next.add(jobId);
684
634
  else next.delete(jobId);
685
635
  pendingJobIds.value = next;
686
636
  }
687
- function applyStreamMessage(message) {
688
- if (!active || source.value) return;
689
- if (message.event === "snapshot" && isSnapshotPayload(message.data)) {
690
- replaceLegacyJobs(message.data.jobs);
691
- return;
692
- }
693
- if ((message.event === "job" || message.event === "terminal") && !isSnapshotPayload(message.data)) upsertLegacyJob(message.data);
694
- }
695
637
  async function refresh() {
696
- const currentSource = source.value;
697
- const listJobs = currentSource?.refreshJobs ?? adapter.value?.listJobs;
698
- if (!listJobs) return false;
638
+ const refreshJobs = source.value?.refreshJobs;
639
+ if (!refreshJobs) return false;
699
640
  const generation = ++requestGeneration;
700
- const revision = stateRevision;
701
641
  isLoading.value = true;
702
642
  error.value = null;
703
643
  try {
704
- const response = await listJobs();
705
- if (!active || generation !== requestGeneration || revision !== stateRevision) return false;
706
- if (!currentSource && response) replaceLegacyJobs(responseJobs(response));
707
- return true;
644
+ await refreshJobs();
645
+ return active && generation === requestGeneration;
708
646
  } catch (cause) {
709
647
  if (active && generation === requestGeneration) error.value = errorMessage(cause, "Failed to load jobs");
710
648
  return false;
@@ -714,17 +652,12 @@ function usePluginJobCenter(options = {}) {
714
652
  }
715
653
  async function cancelJob(job) {
716
654
  const sourceCancel = source.value?.cancelJob;
717
- const adapterCancel = adapter.value?.cancelJob;
718
- if (!job.can_cancel || !sourceCancel && !adapterCancel || pendingJobIds.value.has(job.job_id)) return false;
719
- const revision = jobRevisions.get(job.job_id) ?? 0;
655
+ if (!job.can_cancel || !sourceCancel || pendingJobIds.value.has(job.job_id)) return false;
720
656
  setPending(job.job_id, true);
721
657
  error.value = null;
722
658
  try {
723
- const updated = sourceCancel ? await sourceCancel(job.job_id) : await adapterCancel(job);
724
- if (!active) return false;
725
- if (!sourceCancel && revision === (jobRevisions.get(job.job_id) ?? 0)) if (updated) upsertLegacyJob(updated);
726
- else await refresh();
727
- return true;
659
+ await sourceCancel(job.job_id);
660
+ return active;
728
661
  } catch (cause) {
729
662
  if (active) error.value = errorMessage(cause, "Failed to cancel job");
730
663
  return false;
@@ -734,16 +667,12 @@ function usePluginJobCenter(options = {}) {
734
667
  }
735
668
  async function deleteJob(job) {
736
669
  const sourceDelete = source.value?.deleteJob;
737
- const adapterDelete = adapter.value?.deleteJob;
738
- if (!job.can_delete || !sourceDelete && !adapterDelete || pendingJobIds.value.has(job.job_id)) return false;
670
+ if (!job.can_delete || !sourceDelete || pendingJobIds.value.has(job.job_id)) return false;
739
671
  setPending(job.job_id, true);
740
672
  error.value = null;
741
673
  try {
742
- const deleted = sourceDelete ? await sourceDelete(job.job_id) : await adapterDelete(job);
743
- if (!active) return false;
744
- if (!sourceDelete) if (deleted === false) await refresh();
745
- else removeLegacyJobs(new Set([job.job_id]));
746
- return deleted !== false;
674
+ const deleted = await sourceDelete(job.job_id);
675
+ return active && deleted !== false;
747
676
  } catch (cause) {
748
677
  if (active) error.value = errorMessage(cause, "Failed to delete job");
749
678
  return false;
@@ -763,27 +692,12 @@ function usePluginJobCenter(options = {}) {
763
692
  return typeof deleted !== "number" || deleted === targets.length;
764
693
  }
765
694
  if (currentSource?.deleteJob) return (await Promise.all(targets.map((job) => deleteJob(job)))).every(Boolean);
766
- const currentAdapter = adapter.value;
767
- if (currentAdapter?.clearFinishedJobs) {
768
- const deleted = await currentAdapter.clearFinishedJobs(targets);
769
- if (!active) return false;
770
- if (typeof deleted === "number" && deleted !== targets.length) {
771
- await refresh();
772
- return false;
773
- }
774
- removeLegacyJobs(new Set(targets.map((job) => job.job_id)));
775
- return true;
776
- }
777
- if (!currentAdapter?.deleteJob) return false;
778
- return (await Promise.all(targets.map((job) => deleteJob(job)))).every(Boolean);
695
+ return false;
779
696
  } catch (cause) {
780
697
  if (active) error.value = errorMessage(cause, "Failed to clear jobs");
781
698
  return false;
782
699
  }
783
700
  }
784
- if (options.eventStream !== void 0) watch(() => toValue(options.eventStream)?.lastMessage.value ?? null, (message) => {
785
- if (message) applyStreamMessage(message);
786
- }, { immediate: true });
787
701
  onMounted(() => {
788
702
  if (options.loadOnMount !== false) refresh();
789
703
  });
@@ -816,17 +730,12 @@ function usePluginJobCenter(options = {}) {
816
730
  isOpen.value = !isOpen.value;
817
731
  },
818
732
  refresh,
819
- applyStreamMessage,
820
733
  cancelJob,
821
734
  deleteJob,
822
735
  clearFinished,
823
736
  isPending: (job) => pendingJobIds.value.has(job.job_id)
824
737
  };
825
738
  }
826
- /** Backward-compatible name for the plugin job-center controller. */
827
- function useJobsStatusTray(options = {}) {
828
- return usePluginJobCenter(options);
829
- }
830
739
  //#endregion
831
740
  //#region src/composables/useDoseCalculator.ts
832
741
  var VOLUME_UNITS = [
@@ -5144,6 +5053,6 @@ function useProtocolTemplates() {
5144
5053
  };
5145
5054
  }
5146
5055
  //#endregion
5147
- export { useToast as $, useFileImport as A, useDoseCalculator as B, getSampleGroupParentPath as C, detectDelimiter as D, hslToHex as E, extractSampleNamesFromDesignData as F, useMobileSupportGate as G, useJobsStatusTray as H, extractSampleOptionsFromDesignData as I, getInjectedFrontendRevision as J, APP_EXPERIMENT_KEY as K, unwrapExperimentDesignData as L, extractSamplesFromDesignData as M, useAutoGroup as N, parseDelimitedText as O, parseCSV as P, useTheme as Q, DEFAULT_COLORS as R, getSampleGroupMajorPrefix as S, hexToHsl as T, usePluginJobCenter as U, combinePluginJobSources as V, DEFAULT_MOBILE_VIEWPORT_QUERY as W, getPresenceClientId as X, useRuntimeAlignment as Y, usePresenceHeartbeat as Z, useScheduleDrag as _, useReagentSeries as a, useExpansionSet as b, useBioTemplatePresetWorkspace as c, getBioTemplateComponentProps as d, candidateMatchesSearch as et, toBioTemplateComponentPropsByComponent as f, useExperimentSave as g, useTemplateCollection as h, generateDilutionSeries as i, useSortedItems as it, validateImportFile as j, readFileAsText as k, useBioTemplatePackWorkspace as l, useBioTemplateControls as m, DEFAULT_PRESETS as n, useTextSearch as nt, useGroupAssignment as o, useBioTemplateComponents as p, useAppExperiment as q, DEFAULT_UNITS as r, compareSortValues as rt, useRackEditor as s, useProtocolTemplates as t, normalizeSearchQuery as tt, useBioTemplateWorkspace as u, useExperimentSamples as v, deriveShade as w, useSampleGroups as x, useExperimentData as y, useWellPlateEditor as z };
5056
+ export { candidateMatchesSearch as $, useFileImport as A, useDoseCalculator as B, getSampleGroupParentPath as C, detectDelimiter as D, hslToHex as E, extractSampleNamesFromDesignData as F, APP_EXPERIMENT_KEY as G, usePluginJobCenter as H, extractSampleOptionsFromDesignData as I, useRuntimeAlignment as J, useAppExperiment as K, unwrapExperimentDesignData as L, extractSamplesFromDesignData as M, useAutoGroup as N, parseDelimitedText as O, parseCSV as P, useToast as Q, DEFAULT_COLORS as R, getSampleGroupMajorPrefix as S, hexToHsl as T, DEFAULT_MOBILE_VIEWPORT_QUERY as U, combinePluginJobSources as V, useMobileSupportGate as W, usePresenceHeartbeat as X, getPresenceClientId as Y, useTheme as Z, useScheduleDrag as _, useReagentSeries as a, useExpansionSet as b, useBioTemplatePresetWorkspace as c, getBioTemplateComponentProps as d, normalizeSearchQuery as et, toBioTemplateComponentPropsByComponent as f, useExperimentSave as g, useTemplateCollection as h, generateDilutionSeries as i, validateImportFile as j, readFileAsText as k, useBioTemplatePackWorkspace as l, useBioTemplateControls as m, DEFAULT_PRESETS as n, compareSortValues as nt, useGroupAssignment as o, useBioTemplateComponents as p, getInjectedFrontendRevision as q, DEFAULT_UNITS as r, useSortedItems as rt, useRackEditor as s, useProtocolTemplates as t, useTextSearch as tt, useBioTemplateWorkspace as u, useExperimentSamples as v, deriveShade as w, useSampleGroups as x, useExperimentData as y, useWellPlateEditor as z };
5148
5057
 
5149
- //# sourceMappingURL=useProtocolTemplates-DHwSveE6.js.map
5058
+ //# sourceMappingURL=useProtocolTemplates-CS_SQl6U.js.map