windmill-components 1.504.5 → 1.510.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.
Files changed (202) hide show
  1. package/package/ata/index.js +1 -1
  2. package/package/components/AppConnectInner.svelte +161 -29
  3. package/package/components/ArgInput.svelte +33 -103
  4. package/package/components/AuthSettings.svelte +45 -1
  5. package/package/components/Dev.svelte +31 -24
  6. package/package/components/DisplayResult.svelte +53 -26
  7. package/package/components/DisplayResult.svelte.d.ts +1 -1
  8. package/package/components/DynSelect.svelte +3 -3
  9. package/package/components/Editor.svelte +7 -4
  10. package/package/components/EditorBar.svelte +2 -2
  11. package/package/components/ErrorOrRecoveryHandler.svelte +73 -67
  12. package/package/components/ErrorOrRecoveryHandler.svelte.d.ts +8 -24
  13. package/package/components/FlowBuilder.svelte +11 -2
  14. package/package/components/FlowJobResult.svelte +12 -17
  15. package/package/components/FlowJobResult.svelte.d.ts +5 -18
  16. package/package/components/FlowPreviewContent.svelte +13 -10
  17. package/package/components/FlowPreviewContent.svelte.d.ts +1 -1
  18. package/package/components/FlowPreviewResult.svelte +14 -6
  19. package/package/components/FlowStatusViewer.svelte +11 -24
  20. package/package/components/FlowStatusViewer.svelte.d.ts +19 -18
  21. package/package/components/FlowStatusViewerInner.svelte +110 -131
  22. package/package/components/FlowStatusViewerInner.svelte.d.ts +20 -18
  23. package/package/components/GitDiffPreview.svelte +55 -0
  24. package/package/components/GitDiffPreview.svelte.d.ts +13 -0
  25. package/package/components/HistoricInputs.svelte +2 -2
  26. package/package/components/InitGitRepoPopover.svelte +410 -0
  27. package/package/components/InitGitRepoPopover.svelte.d.ts +13 -0
  28. package/package/components/InstanceSetting.svelte +21 -9
  29. package/package/components/InstanceSettings.svelte +16 -3
  30. package/package/components/JobLoader.svelte +567 -0
  31. package/package/components/JobLoader.svelte.d.ts +53 -0
  32. package/package/components/JobLogs.svelte +6 -4
  33. package/package/components/JobLogs.svelte.d.ts +5 -18
  34. package/package/components/LightweightResourcePicker.svelte +18 -39
  35. package/package/components/LightweightResourcePicker.svelte.d.ts +6 -22
  36. package/package/components/LogViewer.svelte +35 -41
  37. package/package/components/LogViewer.svelte.d.ts +6 -20
  38. package/package/components/ModulePreviewResultViewer.svelte +3 -1
  39. package/package/components/ModulePreviewResultViewer.svelte.d.ts +1 -0
  40. package/package/components/ModuleTest.svelte +16 -11
  41. package/package/components/PullGitRepoPopover.svelte +355 -0
  42. package/package/components/PullGitRepoPopover.svelte.d.ts +18 -0
  43. package/package/components/S3FilePicker.svelte +5 -3
  44. package/package/components/SavedInputs.svelte +2 -2
  45. package/package/components/ScriptBuilder.svelte +4 -3
  46. package/package/components/ScriptEditor.svelte +34 -31
  47. package/package/components/ScriptEditor.svelte.d.ts +3 -3
  48. package/package/components/ServiceLogsInner.svelte +2 -1
  49. package/package/components/ServiceLogsInner.svelte.d.ts +1 -0
  50. package/package/components/UserSettings.svelte +1 -1
  51. package/package/components/WorkerTagSelect.svelte +32 -3
  52. package/package/components/apps/components/buttons/AppButton.svelte +7 -1
  53. package/package/components/apps/components/buttons/AppButton.svelte.d.ts +1 -0
  54. package/package/components/apps/components/display/AppCustomComponent.svelte +1 -1
  55. package/package/components/apps/components/display/AppDisplayComponentByJobId.svelte +16 -11
  56. package/package/components/apps/components/display/AppJobIdLogComponent.svelte +13 -10
  57. package/package/components/apps/components/display/AppMenu.svelte +5 -0
  58. package/package/components/apps/components/display/dbtable/AppDbExplorer.svelte +3 -3
  59. package/package/components/apps/components/display/dbtable/DeleteRow.svelte +3 -3
  60. package/package/components/apps/components/display/dbtable/InsertRowRunnable.svelte +3 -3
  61. package/package/components/apps/components/display/dbtable/UpdateCell.svelte +3 -3
  62. package/package/components/apps/components/display/table/AppAggridInfiniteTable.svelte +3 -3
  63. package/package/components/apps/components/helpers/RunnableComponent.svelte +65 -54
  64. package/package/components/apps/components/helpers/RunnableComponent.svelte.d.ts +5 -5
  65. package/package/components/apps/components/inputs/AppUserResource.svelte +26 -8
  66. package/package/components/apps/editor/AppEditorHeader.svelte +11 -5
  67. package/package/components/apps/editor/AppJobsDrawer.svelte +5 -5
  68. package/package/components/apps/editor/RunnableJobPanel.svelte +4 -4
  69. package/package/components/apps/editor/component/components.d.ts +12 -0
  70. package/package/components/apps/editor/component/components.js +19 -7
  71. package/package/components/assets/AssetButtons.svelte +38 -0
  72. package/package/components/assets/AssetButtons.svelte.d.ts +15 -0
  73. package/package/components/assets/AssetsDropdownButton.svelte +60 -72
  74. package/package/components/assets/AssetsDropdownButton.svelte.d.ts +3 -4
  75. package/package/components/assets/AssetsUsageDrawer.svelte +10 -10
  76. package/package/components/assets/JobAssetsViewer.svelte +79 -0
  77. package/package/components/assets/JobAssetsViewer.svelte.d.ts +7 -0
  78. package/package/components/assets/README_DEV.md +0 -0
  79. package/package/components/assets/lib.d.ts +9 -1
  80. package/package/components/assets/lib.js +48 -7
  81. package/package/components/common/fileUpload/FileUpload.svelte +126 -84
  82. package/package/components/common/fileUpload/FileUpload.svelte.d.ts +13 -3
  83. package/package/components/common/fileUpload/S3ArgInput.svelte +111 -0
  84. package/package/components/common/fileUpload/S3ArgInput.svelte.d.ts +21 -0
  85. package/package/components/common/table/ScriptRow.svelte +3 -1
  86. package/package/components/copilot/autocomplete/Autocompletor.js +23 -5
  87. package/package/components/copilot/chat/AIChatDisplay.svelte +8 -0
  88. package/package/components/copilot/chat/AIChatManager.svelte.js +13 -8
  89. package/package/components/copilot/chat/flow/ModuleAcceptReject.svelte +5 -5
  90. package/package/components/copilot/chat/flow/core.d.ts +1 -1
  91. package/package/components/copilot/chat/flow/core.js +2 -38
  92. package/package/components/copilot/chat/navigator/apiTools.d.ts +8 -0
  93. package/package/components/copilot/chat/navigator/apiTools.js +95 -15
  94. package/package/components/copilot/chat/navigator/core.d.ts +1 -1
  95. package/package/components/copilot/chat/navigator/core.js +2 -1
  96. package/package/components/copilot/chat/script/core.d.ts +11 -2
  97. package/package/components/copilot/chat/script/core.js +135 -1
  98. package/package/components/copilot/chat/shared.d.ts +10 -0
  99. package/package/components/copilot/chat/shared.js +56 -0
  100. package/package/components/copilot/lib.d.ts +1 -0
  101. package/package/components/copilot/lib.js +27 -9
  102. package/package/components/custom_ui.d.ts +1 -0
  103. package/package/components/flows/FlowAssetsHandler.svelte +133 -0
  104. package/package/components/flows/FlowAssetsHandler.svelte.d.ts +14 -0
  105. package/package/components/flows/content/FlowModuleComponent.svelte +16 -18
  106. package/package/components/flows/flowStore.d.ts +1 -1
  107. package/package/components/flows/map/FlowModuleSchemaItem.svelte +1 -0
  108. package/package/components/flows/propPicker/OutputPicker.svelte +9 -4
  109. package/package/components/flows/scheduleUtils.js +1 -1
  110. package/package/components/flows/types.d.ts +2 -1
  111. package/package/components/graph/FlowGraphV2.svelte +8 -104
  112. package/package/components/graph/FlowGraphV2.svelte.d.ts +0 -2
  113. package/package/components/graph/graphBuilder.svelte.d.ts +6 -3
  114. package/package/components/graph/graphBuilder.svelte.js +35 -9
  115. package/package/components/graph/renderers/edges/BaseEdge.svelte +2 -5
  116. package/package/components/graph/renderers/edges/BaseEdge.svelte.d.ts +1 -0
  117. package/package/components/graph/renderers/nodes/AssetNode.svelte +23 -20
  118. package/package/components/graph/renderers/nodes/AssetNode.svelte.d.ts +5 -10
  119. package/package/components/graph/renderers/nodes/AssetsOverflowedNode.svelte +1 -1
  120. package/package/components/graph/util.js +1 -1
  121. package/package/components/home/ItemsList.svelte +2 -0
  122. package/package/components/icons/AssetGenericIcon.svelte +0 -3
  123. package/package/components/jobs/JobPreview.svelte +10 -6
  124. package/package/components/raw_apps/RawAppInlineScriptRunnable.svelte +13 -12
  125. package/package/components/runs/BatchReRunOptionsPane.svelte +5 -1
  126. package/package/components/runs/JobPreview.svelte +26 -16
  127. package/package/components/runs/{JobLoader.svelte.d.ts → JobsLoader.svelte.d.ts} +3 -3
  128. package/package/components/runs/NoWorkerWithTagWarning.svelte +2 -2
  129. package/package/components/runs/NoWorkerWithTagWarning.svelte.d.ts +1 -0
  130. package/package/components/runs/RunsFilter.svelte.d.ts +1 -1
  131. package/package/components/schema/AddPropertyFormV2.svelte +42 -33
  132. package/package/components/schema/AddPropertyFormV2.svelte.d.ts +1 -0
  133. package/package/components/schema/AddPropertyV2.svelte +2 -1
  134. package/package/components/schema/AddPropertyV2.svelte.d.ts +1 -0
  135. package/package/components/schema/EditableSchemaWrapper.svelte +3 -1
  136. package/package/components/schema/editable_schema_wrapper.d.ts +3 -0
  137. package/package/components/scriptEditor/LogPanel.svelte +3 -2
  138. package/package/components/script_builder.d.ts +2 -2
  139. package/package/components/settings/CreateToken.svelte +76 -41
  140. package/package/components/settings/CreateToken.svelte.d.ts +1 -1
  141. package/package/components/settings/ScopeSelector.svelte +613 -0
  142. package/package/components/settings/ScopeSelector.svelte.d.ts +8 -0
  143. package/package/components/settings/TokenDisplay.svelte +103 -0
  144. package/package/components/settings/TokenDisplay.svelte.d.ts +10 -0
  145. package/package/components/settings/TokensTable.svelte +70 -349
  146. package/package/components/sidebar/CriticalAlertModal.svelte +3 -0
  147. package/package/components/triggers/DeleteTriggerButton.svelte +1 -1
  148. package/package/components/triggers/TriggerEditorToolbar.svelte +3 -3
  149. package/package/components/triggers/TriggerRetriesAndErrorHandler.svelte +55 -0
  150. package/package/components/triggers/TriggerRetriesAndErrorHandler.svelte.d.ts +13 -0
  151. package/package/components/triggers/TriggersEditor.svelte +45 -3
  152. package/package/components/triggers/TriggersWrapper.svelte +2 -2
  153. package/package/components/triggers/gcp/GcpTriggerEditorInner.svelte +43 -2
  154. package/package/components/triggers/gcp/utils.js +9 -1
  155. package/package/components/triggers/http/OpenAPISpecGenerator.svelte +1 -0
  156. package/package/components/triggers/http/RouteEditorInner.svelte +208 -164
  157. package/package/components/triggers/http/RouteEditorInner.svelte.d.ts +6 -2
  158. package/package/components/triggers/http/utils.js +9 -3
  159. package/package/components/triggers/kafka/KafkaTriggerEditorInner.svelte +43 -2
  160. package/package/components/triggers/kafka/utils.js +9 -1
  161. package/package/components/triggers/mqtt/MqttEditorConfigSection.svelte +4 -132
  162. package/package/components/triggers/mqtt/MqttEditorConfigSection.svelte.d.ts +2 -5
  163. package/package/components/triggers/mqtt/MqttTriggerEditorInner.svelte +178 -9
  164. package/package/components/triggers/mqtt/utils.js +9 -1
  165. package/package/components/triggers/nats/NatsTriggerEditorInner.svelte +43 -2
  166. package/package/components/triggers/nats/utils.js +9 -1
  167. package/package/components/triggers/postgres/PostgresTriggerEditorInner.svelte +41 -2
  168. package/package/components/triggers/postgres/utils.js +9 -1
  169. package/package/components/triggers/schedules/ScheduleEditorInner.svelte +34 -88
  170. package/package/components/triggers/sqs/SqsTriggerEditorInner.svelte +43 -2
  171. package/package/components/triggers/sqs/utils.js +9 -1
  172. package/package/components/triggers/utils.js +12 -0
  173. package/package/components/triggers/websocket/WebsocketTriggerEditorInner.svelte +43 -2
  174. package/package/components/triggers/websocket/utils.js +11 -1
  175. package/package/components/workspaceSettings/AISettings.svelte +0 -2
  176. package/package/components/workspaceSettings/FilterList.svelte +56 -0
  177. package/package/components/workspaceSettings/FilterList.svelte.d.ts +8 -0
  178. package/package/components/workspaceSettings/GitSyncFilterSettings.svelte +785 -0
  179. package/package/components/workspaceSettings/GitSyncFilterSettings.svelte.d.ts +18 -0
  180. package/package/gen/core/OpenAPI.js +1 -1
  181. package/package/gen/schemas.gen.d.ts +305 -23
  182. package/package/gen/schemas.gen.js +305 -23
  183. package/package/gen/services.gen.d.ts +33 -1
  184. package/package/gen/services.gen.js +66 -2
  185. package/package/gen/types.gen.d.ts +216 -11
  186. package/package/history.svelte.js +0 -2
  187. package/package/hub.d.ts +1 -0
  188. package/package/hubPaths.json +5 -2
  189. package/package/infer.js +16 -10
  190. package/package/svelte5Utils.svelte.d.ts +1 -0
  191. package/package/svelte5Utils.svelte.js +25 -18
  192. package/package/toast.js +10 -0
  193. package/package/utils.d.ts +3 -2
  194. package/package/utils.js +20 -5
  195. package/package.json +11 -11
  196. package/package/components/ResultJobLoader.svelte +0 -219
  197. package/package/components/ResultJobLoader.svelte.d.ts +0 -52
  198. package/package/components/TestJobLoader.svelte +0 -274
  199. package/package/components/TestJobLoader.svelte.d.ts +0 -43
  200. package/package/components/icons/AssetVarIcon.svelte +0 -31
  201. package/package/components/icons/AssetVarIcon.svelte.d.ts +0 -9
  202. /package/package/components/runs/{JobLoader.svelte → JobsLoader.svelte} +0 -0
@@ -0,0 +1,567 @@
1
+ <script lang="ts">import { JobService } from '../gen';
2
+ import { workspaceStore } from '../stores';
3
+ import { onDestroy, tick, untrack } from 'svelte';
4
+ import { sendUserToast } from '../toast';
5
+ import { isScriptPreview } from '../utils';
6
+ let { isLoading = $bindable(false), job = $bindable(undefined), noCode = false, allowConcurentRequests = false, workspaceOverride = undefined, notfound = $bindable(false), jobUpdateLastFetch = $bindable(undefined), toastError = false, lazyLogs = false, onlyResult = false, scriptProgress = $bindable(undefined), noLogs = false, children } = $props();
7
+ /// Last time asked for job progress
8
+ let lastTimeCheckedProgress = undefined;
9
+ /// Will try to poll progress every 5s and if once progress returned was not undefined, will be ignored
10
+ /// and getProgressRate will be used instead
11
+ const getProgressRetryRate = 5000;
12
+ /// How often loader poll progress
13
+ const getProgressRate = 1000;
14
+ let workspace = $derived(workspaceOverride ?? $workspaceStore);
15
+ let syncIteration = 0;
16
+ let errorIteration = 0;
17
+ let logOffset = 0;
18
+ let lastCallbacks = undefined;
19
+ let finished = [];
20
+ let ITERATIONS_BEFORE_SLOW_REFRESH = 10;
21
+ let ITERATIONS_BEFORE_SUPER_SLOW_REFRESH = 100;
22
+ let lastStartedAt = Date.now();
23
+ let currentId = $state(undefined);
24
+ let noPingTimeout = undefined;
25
+ $effect(() => {
26
+ let newIsLoading = currentId !== undefined;
27
+ untrack(() => {
28
+ if (isLoading !== newIsLoading) {
29
+ isLoading = newIsLoading;
30
+ }
31
+ });
32
+ });
33
+ function clearCurrentId() {
34
+ if (currentId) {
35
+ if (allowConcurentRequests) {
36
+ finished.push(currentId);
37
+ }
38
+ else {
39
+ currentId = undefined;
40
+ }
41
+ }
42
+ }
43
+ export async function abstractRun(fn, callbacks) {
44
+ try {
45
+ isLoading = true;
46
+ clearCurrentJob();
47
+ lastCallbacks = callbacks;
48
+ noPingTimeout = undefined;
49
+ const startedAt = Date.now();
50
+ const testId = await fn();
51
+ if (lastStartedAt < startedAt || allowConcurentRequests) {
52
+ lastStartedAt = startedAt;
53
+ if (testId) {
54
+ callbacks?.started?.({ id: testId });
55
+ try {
56
+ await watchJob(testId, callbacks);
57
+ }
58
+ catch {
59
+ if (currentId === testId) {
60
+ clearCurrentId();
61
+ }
62
+ }
63
+ }
64
+ }
65
+ return testId;
66
+ }
67
+ catch (err) {
68
+ if (toastError) {
69
+ sendUserToast(err.body, true);
70
+ }
71
+ callbacks?.doneError?.({ error: err });
72
+ // if error happens on submitting the job, reset UI state so the user can try again
73
+ isLoading = false;
74
+ currentId = undefined;
75
+ job = undefined;
76
+ throw err;
77
+ }
78
+ }
79
+ export async function runScriptByPath(path, args, callbacks) {
80
+ return abstractRun(() => JobService.runScriptByPath({
81
+ workspace: $workspaceStore,
82
+ path: path ?? '',
83
+ requestBody: args,
84
+ skipPreprocessor: true
85
+ }), callbacks);
86
+ }
87
+ export async function runScriptByHash(hash, args, callbacks) {
88
+ return abstractRun(() => JobService.runScriptByHash({
89
+ workspace: $workspaceStore,
90
+ hash: hash ?? '',
91
+ requestBody: args,
92
+ skipPreprocessor: true
93
+ }), callbacks);
94
+ }
95
+ export async function runFlowByPath(path, args, callbacks) {
96
+ return abstractRun(() => JobService.runFlowByPath({
97
+ workspace: $workspaceStore,
98
+ path: path ?? '',
99
+ requestBody: args,
100
+ skipPreprocessor: true
101
+ }), callbacks);
102
+ }
103
+ function refreshLogOffset() {
104
+ if (logOffset == 0) {
105
+ logOffset = job?.logs?.length ? job.logs?.length + 1 : 0;
106
+ }
107
+ }
108
+ export async function getLogs() {
109
+ if (job) {
110
+ refreshLogOffset();
111
+ const getUpdate = await JobService.getJobUpdates({
112
+ workspace: workspace,
113
+ id: job.id,
114
+ running: `running` in job && job.running,
115
+ logOffset: logOffset
116
+ });
117
+ if ((job?.logs ?? '').length == 0) {
118
+ job.logs = getUpdate.new_logs ?? '';
119
+ logOffset = getUpdate.log_offset ?? 0;
120
+ }
121
+ }
122
+ }
123
+ export async function runPreview(path, code, lang, args, tag, lock, hash, callbacks) {
124
+ // Reset in case we rerun job without reloading
125
+ scriptProgress = undefined;
126
+ lastTimeCheckedProgress = undefined;
127
+ return abstractRun(() => JobService.runScriptPreview({
128
+ workspace: $workspaceStore,
129
+ requestBody: {
130
+ path,
131
+ content: code,
132
+ args,
133
+ language: lang,
134
+ tag,
135
+ lock,
136
+ script_hash: hash
137
+ }
138
+ }), callbacks);
139
+ }
140
+ export async function cancelJob() {
141
+ const id = currentId;
142
+ if (id) {
143
+ lastCallbacks?.cancel?.({ id });
144
+ lastCallbacks = undefined;
145
+ clearCurrentId();
146
+ // Clean up SSE connection
147
+ currentEventSource?.close();
148
+ currentEventSource = undefined;
149
+ try {
150
+ await JobService.cancelQueuedJob({
151
+ workspace: $workspaceStore ?? '',
152
+ id,
153
+ requestBody: {}
154
+ });
155
+ }
156
+ catch (err) {
157
+ console.error(err);
158
+ }
159
+ }
160
+ }
161
+ export async function clearCurrentJob() {
162
+ if (currentId && !allowConcurentRequests) {
163
+ job = undefined;
164
+ lastCallbacks?.cancel?.({ id: currentId });
165
+ lastCallbacks = undefined;
166
+ await cancelJob();
167
+ }
168
+ }
169
+ function supportsSSE() {
170
+ const sseSupported = typeof EventSource !== 'undefined';
171
+ if (!sseSupported) {
172
+ console.error('SSE not supported, falling back to polling');
173
+ }
174
+ return sseSupported;
175
+ }
176
+ let startedWatchingJob = undefined;
177
+ export async function watchJob(testId, callbacks) {
178
+ logOffset = 0;
179
+ syncIteration = 0;
180
+ errorIteration = 0;
181
+ currentId = testId;
182
+ job = undefined;
183
+ startedWatchingJob = Date.now();
184
+ // Clean up any existing SSE connection
185
+ currentEventSource?.close();
186
+ currentEventSource = undefined;
187
+ // Try SSE first, fall back to polling if needed
188
+ if (supportsSSE()) {
189
+ await loadTestJobWithSSE(testId, 0, callbacks);
190
+ }
191
+ else {
192
+ syncer(testId, callbacks);
193
+ }
194
+ }
195
+ function setJobProgress(job) {
196
+ let getProgress = undefined;
197
+ // We only pull individual job progress this way
198
+ // Flow's progress we are getting from FlowStatusModule of flow job
199
+ if (job.job_kind == 'script' || isScriptPreview(job.job_kind)) {
200
+ // First time, before running job, lastTimeCheckedProgress is always undefined
201
+ if (lastTimeCheckedProgress) {
202
+ const lastTimeCheckedMs = Date.now() - lastTimeCheckedProgress;
203
+ // Ask for progress if the last time we asked is >5s OR the progress was once not undefined
204
+ if (lastTimeCheckedMs > getProgressRetryRate ||
205
+ (scriptProgress != undefined && lastTimeCheckedMs > getProgressRate)) {
206
+ lastTimeCheckedProgress = Date.now();
207
+ getProgress = true;
208
+ }
209
+ }
210
+ else {
211
+ // Make it think we asked for progress, but in reality we didnt. First 5s we want to wait without putting extra work on db
212
+ // 99.99% of the jobs won't have progress be set so we have to do a balance between having low-latency for jobs that use it and job that don't
213
+ // we would usually not care to have progress the first 5s and jobs that are less than 5s
214
+ lastTimeCheckedProgress = Date.now();
215
+ }
216
+ }
217
+ return getProgress;
218
+ }
219
+ const clamp = (num, min, max) => Math.min(Math.max(num, min), max);
220
+ function updateJobFromProgress(previewJobUpdates, job, callbacks) {
221
+ // Clamp number between two values with the following line:
222
+ if (previewJobUpdates.running) {
223
+ if (job && job.type == 'QueuedJob' && !job.running) {
224
+ callbacks?.running?.({ id: job.id });
225
+ job.running = true;
226
+ }
227
+ }
228
+ if (previewJobUpdates.progress) {
229
+ // Progress cannot go back and cannot be set to 100
230
+ scriptProgress = clamp(previewJobUpdates.progress, scriptProgress ?? 0, 99);
231
+ }
232
+ if (previewJobUpdates.new_logs) {
233
+ if (logOffset == 0) {
234
+ job.logs = previewJobUpdates.new_logs ?? '';
235
+ }
236
+ else {
237
+ job.logs = (job?.logs ?? '').concat(previewJobUpdates.new_logs);
238
+ }
239
+ }
240
+ if (previewJobUpdates.log_offset) {
241
+ logOffset = previewJobUpdates.log_offset ?? 0;
242
+ }
243
+ if (previewJobUpdates.flow_status) {
244
+ job.flow_status = previewJobUpdates.flow_status;
245
+ }
246
+ if (previewJobUpdates.workflow_as_code_status) {
247
+ job.workflow_as_code_status = previewJobUpdates.workflow_as_code_status;
248
+ }
249
+ if (previewJobUpdates.mem_peak && job) {
250
+ job.mem_peak = previewJobUpdates.mem_peak;
251
+ }
252
+ if (job &&
253
+ (previewJobUpdates.running ||
254
+ previewJobUpdates.progress ||
255
+ previewJobUpdates.new_logs ||
256
+ previewJobUpdates.flow_status ||
257
+ previewJobUpdates.mem_peak)) {
258
+ callbacks?.change?.(job);
259
+ }
260
+ }
261
+ async function loadTestJob(id, callbacks) {
262
+ let isCompleted = false;
263
+ if (isCurrentJob(id)) {
264
+ try {
265
+ if (job && `running` in job) {
266
+ callbacks?.running?.({ id });
267
+ let getProgress = setJobProgress(job);
268
+ refreshLogOffset();
269
+ let previewJobUpdates = await JobService.getJobUpdates({
270
+ workspace: workspace,
271
+ id,
272
+ running: job.running,
273
+ logOffset: logOffset,
274
+ getProgress: getProgress
275
+ });
276
+ if ((previewJobUpdates.running ?? false) || (previewJobUpdates.completed ?? false)) {
277
+ job = await JobService.getJob({
278
+ workspace: workspace,
279
+ id,
280
+ noCode,
281
+ noLogs: onlyResult || noLogs
282
+ });
283
+ callbacks?.change?.(job);
284
+ }
285
+ updateJobFromProgress(previewJobUpdates, job, callbacks);
286
+ }
287
+ else {
288
+ job = await JobService.getJob({
289
+ workspace: workspace,
290
+ id,
291
+ noLogs: lazyLogs || onlyResult || noLogs,
292
+ noCode
293
+ });
294
+ }
295
+ jobUpdateLastFetch = new Date();
296
+ if (job?.type === 'CompletedJob') {
297
+ //only CompletedJob has success property
298
+ isCompleted = true;
299
+ if (onlyResult) {
300
+ callbacks?.doneResult?.({
301
+ id,
302
+ result: job?.result
303
+ });
304
+ clearCurrentId();
305
+ }
306
+ else {
307
+ onJobCompleted(id, job, callbacks);
308
+ }
309
+ }
310
+ notfound = false;
311
+ }
312
+ catch (err) {
313
+ errorIteration += 1;
314
+ if (errorIteration == 5) {
315
+ notfound = true;
316
+ job = undefined;
317
+ clearCurrentId();
318
+ }
319
+ callbacks?.doneError?.({ error: err, id });
320
+ console.warn(err);
321
+ }
322
+ return isCompleted;
323
+ }
324
+ else {
325
+ return true;
326
+ }
327
+ }
328
+ let currentEventSource = undefined;
329
+ async function onJobCompleted(id, job, callbacks) {
330
+ if (isCurrentJob(id)) {
331
+ await tick();
332
+ if (callbacks?.doneError &&
333
+ !job?.success &&
334
+ typeof job?.result == 'object' &&
335
+ 'error' in (job?.result ?? {})) {
336
+ callbacks?.doneError?.({
337
+ id,
338
+ error: job.result.error
339
+ });
340
+ }
341
+ else {
342
+ callbacks?.done?.(job);
343
+ }
344
+ callbacks?.change?.(job);
345
+ clearCurrentId();
346
+ }
347
+ }
348
+ function setNoPingTimeout(id, attempt, callbacks) {
349
+ if (noPingTimeout) {
350
+ clearTimeout(noPingTimeout);
351
+ }
352
+ if (isCurrentJob(id)) {
353
+ noPingTimeout = setTimeout(() => {
354
+ if (isCurrentJob(id)) {
355
+ currentEventSource?.close();
356
+ currentEventSource = undefined;
357
+ loadTestJobWithSSE(id, attempt + 1, callbacks);
358
+ }
359
+ }, 10000);
360
+ }
361
+ }
362
+ function isCurrentJob(id) {
363
+ return currentId === id || (allowConcurentRequests && !finished.includes(id));
364
+ }
365
+ async function loadTestJobWithSSE(id, attempt, callbacks) {
366
+ let isCompleted = false;
367
+ if (isCurrentJob(id)) {
368
+ try {
369
+ // First load the job to get initial state
370
+ if (!job && !onlyResult) {
371
+ job = await JobService.getJob({
372
+ workspace: workspace,
373
+ id,
374
+ noLogs: lazyLogs || noLogs,
375
+ noCode
376
+ });
377
+ }
378
+ // If job is already completed, don't start SSE
379
+ if (job?.type === 'CompletedJob') {
380
+ isCompleted = true;
381
+ if (isCurrentJob(id)) {
382
+ onJobCompleted(id, job, callbacks);
383
+ }
384
+ return isCompleted;
385
+ }
386
+ else if (onlyResult || (job?.type === 'QueuedJob' && !currentEventSource)) {
387
+ if (job?.type === 'QueuedJob' && job?.running) {
388
+ callbacks?.running?.({ id });
389
+ if (!job.running) {
390
+ job.running = true;
391
+ }
392
+ }
393
+ let getProgress = onlyResult || !job ? undefined : setJobProgress(job);
394
+ refreshLogOffset();
395
+ // Build SSE URL with query parameters
396
+ const params = new URLSearchParams({
397
+ log_offset: logOffset.toString()
398
+ });
399
+ if (job && job.type === 'QueuedJob') {
400
+ params.set('running', job.running.toString());
401
+ }
402
+ else if (onlyResult && callbacks?.running) {
403
+ params.set('running', 'false');
404
+ }
405
+ if (getProgress !== undefined) {
406
+ params.set('get_progress', getProgress.toString());
407
+ }
408
+ if (onlyResult) {
409
+ params.set('only_result', 'true');
410
+ }
411
+ if (startedWatchingJob && startedWatchingJob > Date.now() - 5000) {
412
+ params.set('fast', 'true');
413
+ }
414
+ const sseUrl = `/api/w/${workspace}/jobs_u/getupdate_sse/${id}?${params.toString()}`;
415
+ currentEventSource = new EventSource(sseUrl);
416
+ setNoPingTimeout(id, attempt, callbacks);
417
+ currentEventSource.onmessage = async (event) => {
418
+ if (!isCurrentJob(id)) {
419
+ currentEventSource?.close();
420
+ currentEventSource = undefined;
421
+ return;
422
+ }
423
+ try {
424
+ const previewJobUpdates = JSON.parse(event.data);
425
+ let type = previewJobUpdates.type;
426
+ if (type == 'timeout') {
427
+ currentEventSource?.close();
428
+ currentEventSource = undefined;
429
+ loadTestJobWithSSE(id, 0, callbacks);
430
+ return;
431
+ }
432
+ else if (type == 'ping') {
433
+ setNoPingTimeout(id, attempt, callbacks);
434
+ return;
435
+ }
436
+ else if (type == 'error') {
437
+ currentEventSource?.close();
438
+ currentEventSource = undefined;
439
+ console.error('SSE error:', previewJobUpdates);
440
+ throw new Error('SSE error: ' + previewJobUpdates);
441
+ }
442
+ else if (type == 'not_found') {
443
+ currentEventSource?.close();
444
+ currentEventSource = undefined;
445
+ console.error('Not found');
446
+ throw new Error('Not found');
447
+ }
448
+ jobUpdateLastFetch = new Date();
449
+ if (job) {
450
+ updateJobFromProgress(previewJobUpdates, job, callbacks);
451
+ }
452
+ else if (onlyResult && callbacks?.running && previewJobUpdates.running) {
453
+ callbacks?.running?.({ id });
454
+ }
455
+ // Check if job is completed
456
+ if (previewJobUpdates.completed) {
457
+ currentEventSource?.close();
458
+ currentEventSource = undefined;
459
+ noPingTimeout = undefined;
460
+ isCompleted = true;
461
+ if (onlyResult) {
462
+ callbacks?.doneResult?.({
463
+ id,
464
+ result: previewJobUpdates?.only_result
465
+ });
466
+ clearCurrentId();
467
+ }
468
+ else {
469
+ const njob = previewJobUpdates.job;
470
+ njob.logs = job?.logs ?? '';
471
+ job = njob;
472
+ onJobCompleted(id, job, callbacks);
473
+ }
474
+ }
475
+ }
476
+ catch (parseErr) {
477
+ console.warn('Failed to parse SSE data:', parseErr);
478
+ }
479
+ };
480
+ currentEventSource.onerror = (error) => {
481
+ console.warn('SSE error:', error);
482
+ currentEventSource?.close();
483
+ currentEventSource = undefined;
484
+ if (attempt < 3) {
485
+ console.log(`SSE error (1), retrying ... attempt: ${attempt + 1}/3`);
486
+ setTimeout(() => loadTestJobWithSSE(id, attempt + 1, callbacks), 1000);
487
+ }
488
+ else {
489
+ // Fall back to polling on error
490
+ setTimeout(() => syncer(id, callbacks), 1000);
491
+ }
492
+ };
493
+ currentEventSource.onopen = () => {
494
+ console.log('SSE connection opened for job:', id);
495
+ };
496
+ }
497
+ notfound = false;
498
+ }
499
+ catch (err) {
500
+ errorIteration += 1;
501
+ if (errorIteration == 5) {
502
+ notfound = true;
503
+ job = undefined;
504
+ }
505
+ console.warn(err);
506
+ // Fall back to polling on error
507
+ currentEventSource?.close();
508
+ currentEventSource = undefined;
509
+ if (attempt < 3) {
510
+ console.log(`SSE error (2), retrying ... attempt: ${attempt}/3`);
511
+ attempt++;
512
+ loadTestJobWithSSE(id, attempt, callbacks);
513
+ }
514
+ else {
515
+ // Fall back to polling on error
516
+ setTimeout(() => syncer(id, callbacks), 1000);
517
+ }
518
+ }
519
+ return isCompleted;
520
+ }
521
+ else {
522
+ // Clean up SSE connection if current ID changed
523
+ currentEventSource?.close();
524
+ currentEventSource = undefined;
525
+ return true;
526
+ }
527
+ }
528
+ async function syncer(id, callbacks) {
529
+ if (!isCurrentJob(id)) {
530
+ callbacks?.cancel?.({ id });
531
+ return;
532
+ }
533
+ syncIteration++;
534
+ if (await loadTestJob(id, callbacks)) {
535
+ return;
536
+ }
537
+ let nextIteration = 50;
538
+ if (syncIteration > ITERATIONS_BEFORE_SLOW_REFRESH) {
539
+ nextIteration = 500;
540
+ }
541
+ else if (syncIteration > ITERATIONS_BEFORE_SUPER_SLOW_REFRESH) {
542
+ nextIteration = 2000;
543
+ }
544
+ setTimeout(() => syncer(id, callbacks), nextIteration);
545
+ }
546
+ onDestroy(async () => {
547
+ clearCurrentId();
548
+ currentEventSource?.close();
549
+ currentEventSource = undefined;
550
+ });
551
+ </script>
552
+
553
+ {@render children?.({
554
+ job,
555
+ isLoading,
556
+ workspaceOverride,
557
+ notfound,
558
+ abstractRun,
559
+ runScriptByPath,
560
+ runFlowByPath,
561
+ runPreview,
562
+ cancelJob,
563
+ clearCurrentJob,
564
+ watchJob,
565
+ loadTestJob,
566
+ syncer
567
+ })}
@@ -0,0 +1,53 @@
1
+ import { type Job } from '../gen';
2
+ import type { SupportedLanguage } from '../common';
3
+ export type Callbacks = {
4
+ done?: (x: Job & {
5
+ result?: any;
6
+ }) => void;
7
+ doneResult?: ({ id, result }: {
8
+ id: string;
9
+ result: any;
10
+ }) => void;
11
+ doneError?: ({ id, error }: {
12
+ id?: string;
13
+ error: Error;
14
+ }) => void;
15
+ change?: (x: Job) => void;
16
+ cancel?: ({ id }: {
17
+ id: string;
18
+ }) => void;
19
+ started?: ({ id }: {
20
+ id: string;
21
+ }) => void;
22
+ running?: ({ id }: {
23
+ id: string;
24
+ }) => void;
25
+ };
26
+ interface Props {
27
+ isLoading?: boolean;
28
+ job?: Job | undefined;
29
+ noCode?: boolean;
30
+ noLogs?: boolean;
31
+ workspaceOverride?: string | undefined;
32
+ notfound?: boolean;
33
+ allowConcurentRequests?: boolean;
34
+ jobUpdateLastFetch?: Date | undefined;
35
+ toastError?: boolean;
36
+ lazyLogs?: boolean;
37
+ onlyResult?: boolean;
38
+ scriptProgress?: number | undefined;
39
+ children?: import('svelte').Snippet<[any]>;
40
+ }
41
+ declare const JobLoader: import("svelte").Component<Props, {
42
+ abstractRun: (fn: () => Promise<string>, callbacks?: Callbacks) => Promise<string>;
43
+ runScriptByPath: (path: string, args: Record<string, any>, callbacks?: Callbacks) => Promise<string>;
44
+ runScriptByHash: (hash: string, args: Record<string, any>, callbacks?: Callbacks) => Promise<string>;
45
+ runFlowByPath: (path: string, args: Record<string, any>, callbacks?: Callbacks) => Promise<string>;
46
+ getLogs: () => Promise<void>;
47
+ runPreview: (path: string | undefined, code: string, lang: SupportedLanguage | undefined, args: Record<string, any>, tag: string | undefined, lock?: string, hash?: string, callbacks?: Callbacks) => Promise<string>;
48
+ cancelJob: () => Promise<void>;
49
+ clearCurrentJob: () => Promise<void>;
50
+ watchJob: (testId: string, callbacks?: Callbacks) => Promise<void>;
51
+ }, "job" | "isLoading" | "notfound" | "jobUpdateLastFetch" | "scriptProgress">;
52
+ type JobLoader = ReturnType<typeof JobLoader>;
53
+ export default JobLoader;
@@ -1,12 +1,14 @@
1
1
  <script lang="ts">import { JobService } from '../gen';
2
2
  import { workspaceStore } from '../stores';
3
3
  import LogViewer from './LogViewer.svelte';
4
- export let jobId;
5
- let logs = undefined;
6
- $: jobId && loadLogs();
4
+ let { jobId, tagLabel = undefined } = $props();
5
+ let logs = $state(undefined);
7
6
  async function loadLogs() {
8
7
  logs = await JobService.getJobLogs({ workspace: $workspaceStore, id: jobId });
9
8
  }
9
+ $effect(() => {
10
+ jobId && loadLogs();
11
+ });
10
12
  </script>
11
13
 
12
- <LogViewer content={logs} isLoading={false} tag={undefined} {jobId} />
14
+ <LogViewer content={logs} isLoading={false} tag={undefined} {jobId} {tagLabel} />
@@ -1,20 +1,7 @@
1
- interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
2
- new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
3
- $$bindings?: Bindings;
4
- } & Exports;
5
- (internal: unknown, props: Props & {
6
- $$events?: Events;
7
- $$slots?: Slots;
8
- }): Exports & {
9
- $set?: any;
10
- $on?: any;
11
- };
12
- z_$$bindings?: Bindings;
13
- }
14
- declare const JobLogs: $$__sveltets_2_IsomorphicComponent<{
1
+ interface Props {
15
2
  jobId: string;
16
- }, {
17
- [evt: string]: CustomEvent<any>;
18
- }, {}, {}, string>;
19
- type JobLogs = InstanceType<typeof JobLogs>;
3
+ tagLabel?: string | undefined;
4
+ }
5
+ declare const JobLogs: import("svelte").Component<Props, {}, "">;
6
+ type JobLogs = ReturnType<typeof JobLogs>;
20
7
  export default JobLogs;