@revenexx/studio-integrations 0.5.0 → 0.5.1

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/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@revenexx/studio-integrations",
3
3
  "configKey": "studioIntegrations",
4
- "version": "0.5.0",
4
+ "version": "0.5.1",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "unknown"
@@ -6,6 +6,8 @@ type __VLS_Props = {
6
6
  workflow: Workflow;
7
7
  /** Busy flag for the control-pane Play button (a run is being triggered). */
8
8
  runBusy?: boolean;
9
+ /** The run is queued behind a bundle build — busy, but worth saying why. */
10
+ runWaiting?: boolean;
9
11
  };
10
12
  declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
11
13
  change: (blob: WorkflowBlob) => any;
@@ -50,7 +50,8 @@ import { layoutWorkflowNodes } from "./workflowLayout";
50
50
  import { TRIGGER_TEMPLATES, findManifest } from "../../data/integrationNodeCatalog";
51
51
  const props = defineProps({
52
52
  workflow: { type: Object, required: true },
53
- runBusy: { type: Boolean, required: false }
53
+ runBusy: { type: Boolean, required: false },
54
+ runWaiting: { type: Boolean, required: false }
54
55
  });
55
56
  const emit = defineEmits(["change", "run", "toggleActive", "openSettings"]);
56
57
  const { keys: secretKeys } = useIntegrationsSecrets();
@@ -1472,7 +1473,7 @@ const edgeTypes = {
1472
1473
  <!-- Smart Run: the page decides what "run" means — workflows that
1473
1474
  consume trigger.payload open the payload dialog, payload-free
1474
1475
  ones fire immediately. One button either way. -->
1475
- <IntegrationsEditorTip label="Run workflow" shortcut="mod+enter">
1476
+ <IntegrationsEditorTip :label="runWaiting ? 'The bundle is still building \u2014 the run starts when it is ready' : 'Run workflow'" shortcut="mod+enter">
1476
1477
  <button
1477
1478
  type="button"
1478
1479
  class="relative flex h-8 items-center gap-1.5 rounded-lg bg-gradient-to-b from-emerald-500 to-emerald-600 px-3.5 text-sm font-medium text-white transition after:pointer-events-none after:absolute after:inset-0 after:rounded-[inherit] after:shadow-[inset_0_1px_0_rgba(255,255,255,0.3),inset_0_-2px_0_rgba(0,0,0,0.25)] hover:from-emerald-600 hover:to-emerald-600 active:translate-y-px disabled:opacity-60"
@@ -1481,7 +1482,7 @@ const edgeTypes = {
1481
1482
  >
1482
1483
  <Loader2 v-if="runBusy" :size="14" class="animate-spin" />
1483
1484
  <Play v-else :size="14" />
1484
- Run
1485
+ {{ runWaiting ? "Waiting for build\u2026" : "Run" }}
1485
1486
  </button>
1486
1487
  </IntegrationsEditorTip>
1487
1488
 
@@ -6,6 +6,8 @@ type __VLS_Props = {
6
6
  workflow: Workflow;
7
7
  /** Busy flag for the control-pane Play button (a run is being triggered). */
8
8
  runBusy?: boolean;
9
+ /** The run is queued behind a bundle build — busy, but worth saying why. */
10
+ runWaiting?: boolean;
9
11
  };
10
12
  declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
11
13
  change: (blob: WorkflowBlob) => any;
@@ -54,11 +54,33 @@ const reauthCredentials = computed(() => {
54
54
  const blob = JSON.stringify(dirtyBlob.value ?? workflow.value?.blob ?? {});
55
55
  return needsReauth.value.filter((c) => blob.includes(c.id));
56
56
  });
57
- const buildBlocked = computed(() => {
58
- const s = workflow.value?.buildStatus;
59
- return s === "pending" || s === "building" || s === "failed";
60
- });
61
57
  const buildWorking = computed(() => workflow.value?.buildStatus === "building" || workflow.value?.buildStatus === "pending");
58
+ const buildFailed = computed(() => workflow.value?.buildStatus === "failed");
59
+ const waitingForBuild = ref(false);
60
+ const BUILD_WAIT_POLL_MS = 2500;
61
+ const BUILD_WAIT_TIMEOUT_MS = 5 * 6e4;
62
+ async function waitForBuildReady() {
63
+ waitingForBuild.value = true;
64
+ try {
65
+ const started = Date.now();
66
+ while (Date.now() - started < BUILD_WAIT_TIMEOUT_MS) {
67
+ await new Promise((resolve) => setTimeout(resolve, BUILD_WAIT_POLL_MS));
68
+ if (!workflow.value) return false;
69
+ const fresh = await get(workflow.value.id);
70
+ const status = fresh?.buildStatus;
71
+ if (status === "pending" || status === "building") continue;
72
+ if (status === "failed") {
73
+ toast.error("The workflow bundle failed to build \u2014 the run was not started.");
74
+ return false;
75
+ }
76
+ return true;
77
+ }
78
+ toast.error("The bundle build is taking unusually long \u2014 try the run again once it is ready.");
79
+ return false;
80
+ } finally {
81
+ waitingForBuild.value = false;
82
+ }
83
+ }
62
84
  const buildNotice = computed(() => {
63
85
  switch (workflow.value?.buildStatus) {
64
86
  case "building":
@@ -101,6 +123,7 @@ async function onRevisionRestored() {
101
123
  }
102
124
  const { trigger: triggerRun, loadForWorkflow, fetchRun, retryRun } = useIntegrationsRuns();
103
125
  const running = ref(false);
126
+ const waitingMode = ref(null);
104
127
  const payloadText = ref("{}");
105
128
  const payloadError = ref(null);
106
129
  const primaryMode = computed(() => workflow.value?.execution_mode === "sync_only" ? "sync" : "async");
@@ -139,6 +162,12 @@ async function run(mode) {
139
162
  return;
140
163
  }
141
164
  payloadError.value = null;
165
+ if (buildWorking.value) {
166
+ waitingMode.value = mode;
167
+ const ready = await waitForBuildReady();
168
+ waitingMode.value = null;
169
+ if (!ready) return;
170
+ }
142
171
  runModalMode.value = mode;
143
172
  runModalRunId.value = null;
144
173
  syncOpen.value = true;
@@ -574,7 +603,8 @@ function formatDateTime(iso) {
574
603
  <WorkflowEditor
575
604
  :key="editorResetKey"
576
605
  :workflow="workflow"
577
- :run-busy="running || syncLoading"
606
+ :run-busy="running || syncLoading || waitingForBuild"
607
+ :run-waiting="waitingForBuild"
578
608
  @change="onChange"
579
609
  @run="runFromEditor"
580
610
  @toggle-active="toggleActive(workflow.id)"
@@ -669,36 +699,36 @@ function formatDateTime(iso) {
669
699
  <template v-if="workflow.execution_mode === 'caller_decides'">
670
700
  <Button
671
701
  variant="outline"
672
- :disabled="running || syncLoading || buildBlocked"
673
- :title="buildBlocked ? 'The workflow bundle is not ready to run yet.' : void 0"
702
+ :disabled="running || syncLoading || waitingForBuild || buildFailed"
703
+ :title="buildFailed ? 'The workflow bundle failed to build.' : void 0"
674
704
  class="h-8 text-sm"
675
705
  @click="runFromPayloadDialog('sync')"
676
706
  >
677
- <Loader2 v-if="syncLoading" :size="14" class="animate-spin" />
707
+ <Loader2 v-if="syncLoading || waitingMode === 'sync'" :size="14" class="animate-spin" />
678
708
  <Play v-else :size="14" />
679
- Run (sync)
709
+ {{ waitingMode === "sync" ? "Waiting for build\u2026" : "Run (sync)" }}
680
710
  </Button>
681
711
  <Button
682
- :disabled="running || syncLoading || buildBlocked"
683
- :title="buildBlocked ? 'The workflow bundle is not ready to run yet.' : void 0"
712
+ :disabled="running || syncLoading || waitingForBuild || buildFailed"
713
+ :title="buildFailed ? 'The workflow bundle failed to build.' : void 0"
684
714
  class="h-8 text-sm"
685
715
  @click="runFromPayloadDialog('async')"
686
716
  >
687
- <Loader2 v-if="running" :size="14" class="animate-spin" />
717
+ <Loader2 v-if="running || waitingMode === 'async'" :size="14" class="animate-spin" />
688
718
  <Play v-else :size="14" />
689
- Run (async)
719
+ {{ waitingMode === "async" ? "Waiting for build\u2026" : "Run (async)" }}
690
720
  </Button>
691
721
  </template>
692
722
  <Button
693
723
  v-else
694
- :disabled="running || syncLoading || buildBlocked"
695
- :title="buildBlocked ? 'The workflow bundle is not ready to run yet.' : void 0"
724
+ :disabled="running || syncLoading || waitingForBuild || buildFailed"
725
+ :title="buildFailed ? 'The workflow bundle failed to build.' : void 0"
696
726
  class="h-8 text-sm"
697
727
  @click="runFromPayloadDialog(primaryMode)"
698
728
  >
699
- <Loader2 v-if="running || syncLoading" :size="14" class="animate-spin" />
729
+ <Loader2 v-if="running || syncLoading || waitingForBuild" :size="14" class="animate-spin" />
700
730
  <Play v-else :size="14" />
701
- Run ({{ primaryMode }})
731
+ {{ waitingForBuild ? "Waiting for build\u2026" : `Run (${primaryMode})` }}
702
732
  </Button>
703
733
  </div>
704
734
  </DialogContent>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@revenexx/studio-integrations",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "type": "module",
5
5
  "description": "Integration Studio (core: workflows, node editor, runs, schedules, credentials, secrets, audit) as a standalone, publishable Nuxt module.",
6
6
  "repository": {