windmill-components 1.504.0 → 1.504.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 (87) hide show
  1. package/package/components/AppWrapper.svelte +0 -3
  2. package/package/components/{DBManagerDrawerButton.svelte → DBManagerDrawer.svelte} +38 -38
  3. package/package/components/DBManagerDrawer.svelte.d.ts +7 -0
  4. package/package/components/DarkModeObserver.svelte +30 -16
  5. package/package/components/DarkModeObserver.svelte.d.ts +9 -4
  6. package/package/components/Dev.svelte +1 -1
  7. package/package/components/EditorBar.svelte +108 -67
  8. package/package/components/FlowBuilder.svelte +2 -3
  9. package/package/components/FlowStatusViewerInner.svelte +19 -0
  10. package/package/components/FlowWrapper.svelte +0 -3
  11. package/package/components/ItemPicker.svelte +1 -1
  12. package/package/components/ItemPicker.svelte.d.ts +1 -1
  13. package/package/components/MoveDrawer.svelte.d.ts +2 -2
  14. package/package/components/ResourcePicker.svelte +11 -4
  15. package/package/components/S3FilePicker.svelte +10 -3
  16. package/package/components/S3FilePicker.svelte.d.ts +6 -4
  17. package/package/components/ScriptBuilder.svelte +3 -1
  18. package/package/components/ScriptEditor.svelte +31 -3
  19. package/package/components/ScriptEditor.svelte.d.ts +3 -1
  20. package/package/components/ScriptWrapper.svelte +0 -3
  21. package/package/components/ShareModal.svelte.d.ts +1 -1
  22. package/package/components/apps/editor/AppEditor.svelte +1 -1
  23. package/package/components/apps/editor/AppEditorHeader.svelte +1 -1
  24. package/package/components/apps/editor/GridEditor.svelte +1 -1
  25. package/package/components/apps/editor/SubGridEditor.svelte +1 -1
  26. package/package/components/apps/editor/component/componentCallbacks.svelte.js +1 -1
  27. package/package/components/apps/editor/componentsPanel/ComponentList.svelte +1 -1
  28. package/package/components/apps/editor/settingsPanel/ComponentPanel.svelte +1 -1
  29. package/package/components/apps/editor/settingsPanel/DeleteComponent.svelte +1 -1
  30. package/package/components/apps/types.d.ts +2 -2
  31. package/package/components/assets/AssetsDropdownButton.svelte +178 -0
  32. package/package/components/assets/AssetsDropdownButton.svelte.d.ts +16 -0
  33. package/package/components/assets/AssetsUsageDrawer.svelte +43 -0
  34. package/package/components/assets/AssetsUsageDrawer.svelte.d.ts +12 -0
  35. package/package/components/assets/lib.d.ts +16 -0
  36. package/package/components/assets/lib.js +60 -0
  37. package/package/components/auditLogs/AuditLogsFilters.svelte.d.ts +1 -1
  38. package/package/components/common/OnChange.svelte +18 -0
  39. package/package/components/common/OnChange.svelte.d.ts +21 -0
  40. package/package/components/common/button/UndoRedo.svelte +2 -2
  41. package/package/components/common/button/UndoRedo.svelte.d.ts +5 -6
  42. package/package/components/copilot/chat/script/core.js +4 -4
  43. package/package/components/custom_ui.d.ts +1 -0
  44. package/package/components/flows/content/FlowModuleComponent.svelte +20 -1
  45. package/package/components/flows/types.d.ts +15 -1
  46. package/package/components/graph/FlowGraphV2.svelte +111 -8
  47. package/package/components/graph/FlowGraphV2.svelte.d.ts +2 -0
  48. package/package/components/graph/graphBuilder.svelte.d.ts +14 -1
  49. package/package/components/graph/renderers/edges/BaseEdge.svelte +10 -1
  50. package/package/components/graph/renderers/edges/EmptyEdge.svelte +7 -1
  51. package/package/components/graph/renderers/edges/EmptyEdge.svelte.d.ts +3 -0
  52. package/package/components/graph/renderers/nodes/AssetNode.svelte +257 -0
  53. package/package/components/graph/renderers/nodes/AssetNode.svelte.d.ts +21 -0
  54. package/package/components/graph/renderers/nodes/AssetsOverflowedNode.svelte +55 -0
  55. package/package/components/graph/renderers/nodes/AssetsOverflowedNode.svelte.d.ts +7 -0
  56. package/package/components/icons/AssetGenericIcon.svelte +16 -0
  57. package/package/components/icons/AssetGenericIcon.svelte.d.ts +10 -0
  58. package/package/components/icons/AssetResIcon.svelte +32 -0
  59. package/package/components/icons/AssetResIcon.svelte.d.ts +9 -0
  60. package/package/components/icons/AssetS3Icon.svelte +30 -0
  61. package/package/components/icons/AssetS3Icon.svelte.d.ts +9 -0
  62. package/package/components/icons/AssetVarIcon.svelte +31 -0
  63. package/package/components/icons/AssetVarIcon.svelte.d.ts +9 -0
  64. package/package/components/meltComponents/Popover.svelte +2 -0
  65. package/package/components/meltComponents/Popover.svelte.d.ts +2 -0
  66. package/package/components/schema/EditableSchemaSdkWrapper.svelte +1 -4
  67. package/package/components/script_builder.d.ts +2 -0
  68. package/package/components/settings/WorkspaceOperatorSettings.svelte +20 -17
  69. package/package/components/sidebar/OperatorMenu.svelte +5 -0
  70. package/package/components/sidebar/SidebarContent.svelte +9 -1
  71. package/package/components/tutorials/app/AppTutorial.svelte +1 -1
  72. package/package/components/tutorials/app/ConnectionTutorial.svelte +1 -1
  73. package/package/gen/schemas.gen.d.ts +69 -1
  74. package/package/gen/schemas.gen.js +69 -1
  75. package/package/gen/services.gen.d.ts +20 -1
  76. package/package/gen/services.gen.js +37 -0
  77. package/package/gen/types.gen.d.ts +103 -0
  78. package/package/history.svelte.d.ts +2 -2
  79. package/package/history.svelte.js +6 -6
  80. package/package/infer.d.ts +2 -0
  81. package/package/infer.js +31 -5
  82. package/package/svelte5Utils.svelte.d.ts +2 -1
  83. package/package/svelte5Utils.svelte.js +3 -2
  84. package/package/utils.d.ts +12 -0
  85. package/package/utils.js +22 -0
  86. package/package.json +5 -5
  87. package/package/components/DBManagerDrawerButton.svelte.d.ts +0 -9
@@ -0,0 +1,18 @@
1
+ <!--
2
+ Useful to listen to changes on a list without recomputing the whole list
3
+ when a single item changes
4
+ -->
5
+
6
+ <script lang="ts" generics="T">import { untrack } from 'svelte';
7
+ let { key, onChange, runFirstEffect = false } = $props();
8
+ let isFirstRun = true;
9
+ $effect(() => {
10
+ key;
11
+ if (isFirstRun) {
12
+ isFirstRun = false;
13
+ if (!runFirstEffect)
14
+ return;
15
+ }
16
+ untrack(() => onChange());
17
+ });
18
+ </script>
@@ -0,0 +1,21 @@
1
+ declare class __sveltets_Render<T> {
2
+ props(): {
3
+ key: T;
4
+ onChange: () => void;
5
+ runFirstEffect?: boolean;
6
+ };
7
+ events(): {};
8
+ slots(): {};
9
+ bindings(): "";
10
+ exports(): {};
11
+ }
12
+ interface $$IsomorphicComponent {
13
+ new <T>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> & {
14
+ $$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
15
+ } & ReturnType<__sveltets_Render<T>['exports']>;
16
+ <T>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
17
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
18
+ }
19
+ declare const OnChange: $$IsomorphicComponent;
20
+ type OnChange<T> = InstanceType<typeof OnChange<T>>;
21
+ export default OnChange;
@@ -1,7 +1,8 @@
1
1
  <script lang="ts">import { Redo, Undo } from 'lucide-svelte';
2
2
  import { createEventDispatcher } from 'svelte';
3
3
  import { Button } from '..';
4
- let { undoProps = {}, redoProps = {} } = $props();
4
+ export let undoProps = {};
5
+ export let redoProps = {};
5
6
  const dispatch = createEventDispatcher();
6
7
  </script>
7
8
 
@@ -28,5 +29,4 @@ const dispatch = createEventDispatcher();
28
29
  >
29
30
  <Redo size={14} />
30
31
  </Button>
31
-
32
32
  </div>
@@ -1,7 +1,3 @@
1
- interface Props {
2
- undoProps?: Record<string, any>;
3
- redoProps?: Record<string, any>;
4
- }
5
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> {
6
2
  new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
7
3
  $$bindings?: Bindings;
@@ -15,11 +11,14 @@ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> =
15
11
  };
16
12
  z_$$bindings?: Bindings;
17
13
  }
18
- declare const UndoRedo: $$__sveltets_2_IsomorphicComponent<Props, {
14
+ declare const UndoRedo: $$__sveltets_2_IsomorphicComponent<{
15
+ undoProps?: Record<string, any>;
16
+ redoProps?: Record<string, any>;
17
+ }, {
19
18
  undo: CustomEvent<any>;
20
19
  redo: CustomEvent<any>;
21
20
  } & {
22
21
  [evt: string]: CustomEvent<any>;
23
- }, {}, {}, "">;
22
+ }, {}, {}, string>;
24
23
  type UndoRedo = InstanceType<typeof UndoRedo>;
25
24
  export default UndoRedo;
@@ -62,8 +62,8 @@ wmill.runScriptAsync(path: string, args?: Record<string, any>): Promise<string>
62
62
  wmill.waitJob(jobId: string): Promise<any> // Wait for job completion and get result
63
63
 
64
64
  // S3 file operations (if S3 is configured)
65
- wmill.loadS3File(s3object: S3Object): Promise<Uint8Array> // Load file content from S3
66
- wmill.writeS3File(s3object: S3Object, content: string | Blob): Promise<S3Object> // Write file to S3
65
+ wmill.loadS3File(s3object: S3Object | string): Promise<Uint8Array> // Load file content from S3
66
+ wmill.writeS3File(s3object: S3Object | string, content: string | Blob): Promise<S3Object> // Write file to S3
67
67
 
68
68
  // Flow operations
69
69
  wmill.setFlowUserState(key: string, value: any): Promise<void> // Set flow user state
@@ -97,8 +97,8 @@ wmill.run_script_async(path: str, args: dict = None, scheduled_in_secs: int = No
97
97
  wmill.wait_job(job_id: str, timeout = None) -> Any // Wait for job completion and get result
98
98
 
99
99
  // S3 file operations (if S3 is configured)
100
- wmill.load_s3_file(s3object: S3Object, s3_resource_path: str = None) -> bytes // Load file content from S3
101
- wmill.write_s3_file(s3object: S3Object, file_content: bytes, s3_resource_path: str = None) -> S3Object // Write file to S3
100
+ wmill.load_s3_file(s3object: S3Object | str, s3_resource_path: str = None) -> bytes // Load file content from S3
101
+ wmill.write_s3_file(s3object: S3Object | str, file_content: bytes, s3_resource_path: str = None) -> S3Object // Write file to S3
102
102
 
103
103
  // Flow operations
104
104
  wmill.run_flow_async(path: str, args: dict = None) -> str // Run flow asynchronously
@@ -69,6 +69,7 @@ export type EditorBarUi = {
69
69
  library?: boolean;
70
70
  useVsCode?: boolean;
71
71
  diffMode?: boolean;
72
+ s3object?: boolean;
72
73
  };
73
74
  export type EditableSchemaFormUi = {
74
75
  jsonOnly?: boolean;
@@ -45,8 +45,10 @@ import { JobService } from '../../../gen';
45
45
  import { workspaceStore } from '../../../stores';
46
46
  import { checkIfParentLoop } from '../utils';
47
47
  import ModulePreviewResultViewer from '../../ModulePreviewResultViewer.svelte';
48
- import { refreshStateStore } from '../../../svelte5Utils.svelte';
48
+ import { refreshStateStore, usePromise } from '../../../svelte5Utils.svelte';
49
49
  import { getStepHistoryLoaderContext } from '../../stepHistoryLoader.svelte';
50
+ import AssetsDropdownButton from '../../assets/AssetsDropdownButton.svelte';
51
+ import { inferAssets } from '../../../infer';
50
52
  const { selectedId, currentEditor, previewArgs, flowStateStore, flowStore, pathStore, saveDraft, customUi, executionCount } = getContext('FlowEditorContext');
51
53
  let { flowModule = $bindable(), failureModule = false, preprocessorModule = false, parentModule = $bindable(), previousModule, scriptKind = 'script', scriptTemplate = 'script', noEditor, enableAi, savedModule = undefined, forceTestTab = false, highlightArg = undefined } = $props();
52
54
  let workspaceScriptTag = $state(undefined);
@@ -220,6 +222,15 @@ $effect(() => {
220
222
  }, 100);
221
223
  }
222
224
  });
225
+ let assets = usePromise(async () => flowModule.value.type === 'rawscript'
226
+ ? await inferAssets(flowModule.value.language, flowModule.value.content)
227
+ : undefined, { clearValueOnRefresh: false, loadInit: false });
228
+ $effect(() => {
229
+ if (flowModule.value.type !== 'rawscript')
230
+ return;
231
+ [flowModule.value.content, flowModule.value.language];
232
+ untrack(() => assets.refresh());
233
+ });
223
234
  let rawScriptLang = $derived(flowModule.value.type == 'rawscript' ? flowModule.value.language : undefined);
224
235
  </script>
225
236
 
@@ -327,6 +338,14 @@ let rawScriptLang = $derived(flowModule.value.type == 'rawscript' ? flowModule.v
327
338
  {#if flowModule.value.type === 'rawscript'}
328
339
  {#if !noEditor}
329
340
  {#key flowModule.id}
341
+ <div class="absolute top-2 right-4 z-10 flex flex-row gap-2">
342
+ {#if assets.value?.length}
343
+ <AssetsDropdownButton
344
+ assets={assets.value}
345
+ bind:fallbackAccessTypes={flowModule.value.asset_fallback_access_types}
346
+ />
347
+ {/if}
348
+ </div>
330
349
  <Editor
331
350
  loadAsync
332
351
  folding
@@ -1,5 +1,5 @@
1
1
  import type { OpenFlow } from '../../gen';
2
- import type { History } from '../../history';
2
+ import type { History } from '../../history.svelte';
3
3
  import type { Writable } from 'svelte/store';
4
4
  import type ScriptEditorDrawer from './content/ScriptEditorDrawer.svelte';
5
5
  import type { FlowState } from './flowState';
@@ -8,6 +8,10 @@ import type Editor from '../Editor.svelte';
8
8
  import type SimpleEditor from '../SimpleEditor.svelte';
9
9
  import type { StateStore } from '../../utils';
10
10
  import type { TestSteps } from './testSteps.svelte';
11
+ import type { Asset, AssetWithAccessType } from '../assets/lib';
12
+ import type S3FilePicker from '../S3FilePicker.svelte';
13
+ import type DbManagerDrawer from '../DBManagerDrawer.svelte';
14
+ import type ResourceEditorDrawer from '../ResourceEditorDrawer.svelte';
11
15
  import type { ModulesTestStates } from '../modulesTest.svelte';
12
16
  export type FlowInput = Record<string, {
13
17
  flowStepWarnings?: Record<string, {
@@ -64,3 +68,13 @@ export type FlowEditorContext = {
64
68
  modulesTestStates: ModulesTestStates;
65
69
  outputPickerOpenFns: Record<string, () => void>;
66
70
  };
71
+ export type FlowGraphAssetContext = StateStore<{
72
+ selectedAsset: Asset | undefined;
73
+ assetsMap: Record<string, AssetWithAccessType[]>;
74
+ s3FilePicker: S3FilePicker | undefined;
75
+ dbManagerDrawer: DbManagerDrawer | undefined;
76
+ resourceEditorDrawer: ResourceEditorDrawer | undefined;
77
+ resourceMetadataCache: Record<string, {
78
+ resource_type?: string;
79
+ } | undefined>;
80
+ }>;
@@ -1,4 +1,4 @@
1
- <script lang="ts">import { FlowService } from '../../gen';
1
+ <script lang="ts">import { AssetService, FlowService, ResourceService } from '../../gen';
2
2
  import { NODE } from '.';
3
3
  import { getContext, onDestroy, setContext, tick, untrack } from 'svelte';
4
4
  import { get, writable } from 'svelte/store';
@@ -18,7 +18,7 @@ import { sugiyama, dagStratify, coordCenter, decrossTwoLayer, decrossOpt } from
18
18
  import { Expand } from 'lucide-svelte';
19
19
  import Toggle from '../Toggle.svelte';
20
20
  import DataflowEdge from './renderers/edges/DataflowEdge.svelte';
21
- import { encodeState } from '../../utils';
21
+ import { encodeState, readFieldsRecursively } from '../../utils';
22
22
  import BranchOneStart from './renderers/nodes/BranchOneStart.svelte';
23
23
  import NoBranchNode from './renderers/nodes/NoBranchNode.svelte';
24
24
  import HiddenBaseEdge from './renderers/edges/HiddenBaseEdge.svelte';
@@ -31,12 +31,21 @@ import { workspaceStore } from '../../stores';
31
31
  import SubflowBound from './renderers/nodes/SubflowBound.svelte';
32
32
  import { deepEqual } from 'fast-equals';
33
33
  import ViewportResizer from './ViewportResizer.svelte';
34
+ import AssetNode, { computeAssetNodes } from './renderers/nodes/AssetNode.svelte';
35
+ import { getAllModules } from '../flows/flowExplorer';
36
+ import { inferAssets } from '../../infer';
37
+ import OnChange from '../common/OnChange.svelte';
38
+ import S3FilePicker from '../S3FilePicker.svelte';
39
+ import DbManagerDrawer from '../DBManagerDrawer.svelte';
40
+ import ResourceEditorDrawer from '../ResourceEditorDrawer.svelte';
41
+ import { assetEq } from '../assets/lib';
42
+ import AssetsOverflowedNode from './renderers/nodes/AssetsOverflowedNode.svelte';
34
43
  let useDataflow = writable(false);
35
44
  const triggerContext = getContext('TriggerContext');
36
45
  let fullWidth = 0;
37
46
  let width = $state(0);
38
47
  let simplifiableFlow = $state(undefined);
39
- let { onInsert = undefined, onDelete = undefined, onMove = undefined, onDeleteBranch = undefined, onNewBranch = undefined, onSelect = undefined, onChangeId = undefined, onUpdateMock = undefined, onSelectedIteration = undefined, success = undefined, modules = [], failureModule = undefined, preprocessorModule = undefined, minHeight = 0, maxHeight = undefined, notSelectable = false, flowModuleStates = undefined, selectedId = writable(undefined), path = undefined, newFlow = false, insertable = false, earlyStop = false, cache = false, scroll = false, moving = undefined, download = false, fullSize = false, disableAi = false, triggerNode = false, workspace = $workspaceStore ?? 'NO_WORKSPACE', editMode = false, allowSimplifiedPoll = true, expandedSubflows = $bindable({}), onTestUpTo = undefined, onEditInput = undefined, isOwner = false, onTestFlow = undefined, isRunning = false, onCancelTestFlow = undefined, onOpenPreview = undefined, onHideJobStatus = undefined, individualStepTests = false, flowJob = undefined, showJobStatus = false, suspendStatus = writable({}), flowHasChanged = false } = $props();
48
+ let { onInsert = undefined, onDelete = undefined, onMove = undefined, onDeleteBranch = undefined, onNewBranch = undefined, onSelect = undefined, onChangeId = undefined, onUpdateMock = undefined, onSelectedIteration = undefined, success = undefined, modules = [], failureModule = undefined, preprocessorModule = undefined, minHeight = 0, maxHeight = undefined, notSelectable = false, flowModuleStates = undefined, selectedId = writable(undefined), path = undefined, newFlow = false, insertable = false, earlyStop = false, cache = false, scroll = false, moving = undefined, download = false, fullSize = false, disableAi = false, triggerNode = false, workspace = $workspaceStore ?? 'NO_WORKSPACE', editMode = false, allowSimplifiedPoll = true, expandedSubflows = $bindable({}), inputAssets, onTestUpTo = undefined, onEditInput = undefined, isOwner = false, onTestFlow = undefined, isRunning = false, onCancelTestFlow = undefined, onOpenPreview = undefined, onHideJobStatus = undefined, individualStepTests = false, flowJob = undefined, showJobStatus = false, suspendStatus = writable({}), flowHasChanged = false } = $props();
40
49
  setContext('FlowGraphContext', { selectedId, useDataflow });
41
50
  if (triggerContext && allowSimplifiedPoll) {
42
51
  if (isSimplifiable(modules)) {
@@ -46,6 +55,66 @@ if (triggerContext && allowSimplifiedPoll) {
46
55
  computeSimplifiableFlow(modules ?? [], value ?? false);
47
56
  });
48
57
  }
58
+ const flowGraphAssetsCtx = $state({
59
+ val: {
60
+ assetsMap: inputAssets ? { Input: inputAssets } : {},
61
+ selectedAsset: undefined,
62
+ dbManagerDrawer: undefined,
63
+ s3FilePicker: undefined,
64
+ resourceEditorDrawer: undefined,
65
+ resourceMetadataCache: {}
66
+ }
67
+ });
68
+ setContext('FlowGraphAssetContext', flowGraphAssetsCtx);
69
+ const assetsMap = $derived(flowGraphAssetsCtx.val.assetsMap);
70
+ $effect(() => {
71
+ if (inputAssets)
72
+ flowGraphAssetsCtx.val.assetsMap.Input = inputAssets;
73
+ });
74
+ // Fetch resource metadata for the ExploreAssetButton
75
+ const resMetadataCache = $derived(flowGraphAssetsCtx.val.resourceMetadataCache);
76
+ $effect(() => {
77
+ for (const asset of Object.values(assetsMap ?? []).flatMap((x) => x)) {
78
+ if (asset.kind !== 'resource' || asset.path in resMetadataCache)
79
+ continue;
80
+ resMetadataCache[asset.path] = undefined; // avoid fetching multiple times because of async
81
+ ResourceService.getResource({ path: asset.path, workspace: $workspaceStore }).then((r) => (resMetadataCache[asset.path] = { resource_type: r.resource_type }));
82
+ }
83
+ });
84
+ // Fetch transitive assets (path scripts and flows)
85
+ $effect(() => {
86
+ if (!$workspaceStore)
87
+ return;
88
+ let usages = [];
89
+ let modIds = [];
90
+ for (const mod of getAllModules(modules)) {
91
+ if (mod.id in assetsMap)
92
+ continue;
93
+ assetsMap[mod.id] = []; // avoid fetching multiple times because of async
94
+ if (mod.value.type === 'flow' || mod.value.type === 'script') {
95
+ usages.push({ path: mod.value.path, kind: mod.value.type });
96
+ modIds.push(mod.id);
97
+ }
98
+ }
99
+ if (usages.length) {
100
+ AssetService.listAssetsByUsage({
101
+ workspace: $workspaceStore,
102
+ requestBody: { usages }
103
+ }).then((result) => {
104
+ result.forEach((assets, idx) => {
105
+ assetsMap[modIds[idx]] = assets;
106
+ });
107
+ });
108
+ }
109
+ });
110
+ // Prune assetsMap to only contain assets that are actually used
111
+ $effect(() => {
112
+ const allModules = new Set(getAllModules(modules).map((mod) => mod.id));
113
+ for (const modId in assetsMap) {
114
+ if (modId !== 'Input' && !allModules.has(modId))
115
+ delete assetsMap[modId];
116
+ }
117
+ });
49
118
  function computeSimplifiableFlow(modules, simplifiedFlow) {
50
119
  const isSimplif = isSimplifiable(modules);
51
120
  simplifiableFlow = isSimplif ? { simplifiedFlow } : undefined;
@@ -61,7 +130,7 @@ function onModulesChange(modules) {
61
130
  let lastNodes = undefined;
62
131
  function layoutNodes(nodes) {
63
132
  let lastResult = lastNodes?.[1];
64
- if (lastResult && deepEqual(nodes, lastNodes?.[0])) {
133
+ if (lastResult && nodes === lastNodes?.[0]) {
65
134
  return lastResult;
66
135
  }
67
136
  let seenId = [];
@@ -220,8 +289,11 @@ async function updateStores() {
220
289
  }
221
290
  let newGraph = graph;
222
291
  newGraph.nodes.sort((a, b) => b.id.localeCompare(a.id));
223
- nodes = layoutNodes(newGraph.nodes);
224
- edges = newGraph.edges;
292
+ [nodes, edges] = computeAssetNodes(layoutNodes(newGraph.nodes), newGraph.edges, assetsMap, {
293
+ moving,
294
+ eventHandlers: eventHandler,
295
+ disableAi
296
+ });
225
297
  await tick();
226
298
  height = Math.max(...nodes.map((n) => n.position.y + NODE.height + 100), minHeight);
227
299
  }
@@ -239,7 +311,9 @@ const nodeTypes = {
239
311
  branchOneEnd: BranchOneEndNode,
240
312
  subflowBound: SubflowBound,
241
313
  noBranch: NoBranchNode,
242
- trigger: TriggersNode
314
+ trigger: TriggersNode,
315
+ asset: AssetNode,
316
+ assetsOverflowed: AssetsOverflowedNode
243
317
  };
244
318
  const edgeTypes = {
245
319
  edge: BaseEdge,
@@ -281,7 +355,9 @@ let graph = $derived.by(() => {
281
355
  });
282
356
  $effect(() => {
283
357
  ;
284
- (graph || allowSimplifiedPoll) && untrack(() => updateStores());
358
+ [graph, allowSimplifiedPoll];
359
+ readFieldsRecursively(assetsMap);
360
+ untrack(() => updateStores());
285
361
  });
286
362
  let showDataflow = $derived($selectedId != undefined &&
287
363
  !$selectedId.startsWith('constants') &&
@@ -405,6 +481,33 @@ export function isNodeVisible(nodeId) {
405
481
  {/if}
406
482
  </div>
407
483
 
484
+ {#each getAllModules(modules) as mod (mod.id)}
485
+ {#if mod.value.type === 'rawscript'}
486
+ {@const v = mod.value}
487
+ <OnChange
488
+ key={[v.content, v.asset_fallback_access_types]}
489
+ runFirstEffect
490
+ onChange={() =>
491
+ inferAssets(v.language, v.content)
492
+ .then((assets) => {
493
+ for (const override of v.asset_fallback_access_types ?? []) {
494
+ assets = assets.map((asset) => {
495
+ if (assetEq(asset, override) && !asset.access_type)
496
+ return { ...asset, access_type: override.access_type }
497
+ return asset
498
+ })
499
+ }
500
+ if (assetsMap && !deepEqual(assetsMap[mod.id], assets)) assetsMap[mod.id] = assets
501
+ })
502
+ .catch((e) => {})}
503
+ />
504
+ {/if}
505
+ {/each}
506
+
507
+ <S3FilePicker bind:this={flowGraphAssetsCtx.val.s3FilePicker} readOnlyMode />
508
+ <DbManagerDrawer bind:this={flowGraphAssetsCtx.val.dbManagerDrawer} />
509
+ <ResourceEditorDrawer bind:this={flowGraphAssetsCtx.val.resourceEditorDrawer} />
510
+
408
511
  <style>
409
512
  :global(.svelte-flow__handle) {
410
513
  opacity: 0;
@@ -3,6 +3,7 @@ import { type GraphModuleState } from '.';
3
3
  import { type Writable } from 'svelte/store';
4
4
  import '@xyflow/svelte/dist/base.css';
5
5
  import { type InlineScript, type InsertKind, type onSelectedIteration } from './graphBuilder.svelte';
6
+ import { type AssetWithAccessType } from '../assets/lib';
6
7
  interface Props {
7
8
  success?: boolean | undefined;
8
9
  modules?: FlowModule[] | undefined;
@@ -28,6 +29,7 @@ interface Props {
28
29
  editMode?: boolean;
29
30
  allowSimplifiedPoll?: boolean;
30
31
  expandedSubflows?: Record<string, FlowModule[]>;
32
+ inputAssets?: AssetWithAccessType[];
31
33
  isOwner?: boolean;
32
34
  isRunning?: boolean;
33
35
  individualStepTests?: boolean;
@@ -1,6 +1,7 @@
1
1
  import type { FlowModule, Job, RawScript, Script } from '../../gen';
2
2
  import { type Edge } from '@xyflow/svelte';
3
3
  import type { GraphModuleState } from './model';
4
+ import type { AssetWithAccessType } from '../assets/lib';
4
5
  import type { Writable } from 'svelte/store';
5
6
  export type InsertKind = 'script' | 'forloop' | 'whileloop' | 'branchone' | 'branchall' | 'flow' | 'trigger' | 'approval' | 'end';
6
7
  export type InlineScript = {
@@ -70,7 +71,7 @@ export type NodeLayout = {
70
71
  id: string;
71
72
  parentIds?: string[];
72
73
  } & FlowNode;
73
- export type FlowNode = InputN | ModuleN | BranchAllStartN | BranchAllEndN | ForLoopEndN | ForLoopStartN | ResultN | WhileLoopStartN | WhileLoopEndN | BranchOneStartN | BranchOneEndN | SubflowBoundN | NoBranchN | TriggerN;
74
+ export type FlowNode = InputN | ModuleN | BranchAllStartN | BranchAllEndN | ForLoopEndN | ForLoopStartN | ResultN | WhileLoopStartN | WhileLoopEndN | BranchOneStartN | BranchOneEndN | SubflowBoundN | NoBranchN | TriggerN | AssetN | AssetsOverflowedN;
74
75
  export type InputN = {
75
76
  type: 'input2';
76
77
  data: {
@@ -232,6 +233,18 @@ export type TriggerN = {
232
233
  disableAi: boolean;
233
234
  };
234
235
  };
236
+ export type AssetN = {
237
+ type: 'asset';
238
+ data: {
239
+ asset: AssetWithAccessType;
240
+ };
241
+ };
242
+ export type AssetsOverflowedN = {
243
+ type: 'assetsOverflowed';
244
+ data: {
245
+ overflowedAssets: AssetWithAccessType[];
246
+ };
247
+ };
235
248
  export declare function graphBuilder(modules: FlowModule[] | undefined, extra: {
236
249
  disableAi: boolean;
237
250
  insertable: boolean;
@@ -4,14 +4,18 @@ import { ClipboardCopy, Hourglass } from 'lucide-svelte';
4
4
  import { getContext } from 'svelte';
5
5
  import { getStraightLinePath } from '../utils';
6
6
  import { twMerge } from 'tailwind-merge';
7
+ import {} from '../../../flows/types';
8
+ import { assetDisplaysAsOutputInFlowGraph, NODE_WITH_WRITE_ASSET_Y_OFFSET } from '../nodes/AssetNode.svelte';
7
9
  import { workspaceStore } from '../../../../stores';
8
10
  import FlowStatusWaitingForEvents from '../../../FlowStatusWaitingForEvents.svelte';
9
11
  const { useDataflow } = getContext('FlowGraphContext');
12
+ const flowGraphAssetCtx = getContext('FlowGraphAssetContext');
10
13
  let {
11
14
  // id,
12
15
  sourceX, sourceY, sourcePosition, targetX, targetY, targetPosition, markerEnd,
13
16
  // style,
14
17
  data } = $props();
18
+ const shouldOffsetInsertButtonDueToAssetNode = flowGraphAssetCtx?.val.assetsMap?.[data.sourceId]?.some(assetDisplaysAsOutputInFlowGraph);
15
19
  let [edgePath] = $derived(getBezierPath({
16
20
  sourceX,
17
21
  sourceY: targetY - sourceY > 100 ? targetY - 100 : sourceY,
@@ -31,7 +35,12 @@ let waitingForEvents = $derived(data?.flowModuleStates?.[data.targetId]?.type ==
31
35
  const suspendStatus = $derived(data?.suspendStatus);
32
36
  </script>
33
37
 
34
- <EdgeLabel x={sourceX} y={sourceY + 28} class="base-edge" style="">
38
+ <EdgeLabel
39
+ x={sourceX}
40
+ y={sourceY + 28 + (shouldOffsetInsertButtonDueToAssetNode ? NODE_WITH_WRITE_ASSET_Y_OFFSET : 0)}
41
+ class="base-edge"
42
+ style=""
43
+ >
35
44
  {#if data?.insertable && !$useDataflow && !data?.moving && !waitingForEvents}
36
45
  <div
37
46
  class={twMerge('edgeButtonContainer nodrag nopan top-0')}
@@ -1,5 +1,6 @@
1
1
  <script lang="ts">import { getBezierPath, BaseEdge } from '@xyflow/svelte';
2
2
  import { getContext } from 'svelte';
3
+ import { twMerge } from 'tailwind-merge';
3
4
  export let sourceX;
4
5
  export let sourceY;
5
6
  export let sourcePosition;
@@ -7,6 +8,7 @@ export let targetX;
7
8
  export let targetY;
8
9
  export let targetPosition;
9
10
  export let markerEnd = undefined;
11
+ export let data = {};
10
12
  const { useDataflow } = getContext('FlowGraphContext');
11
13
  $: [edgePath] = getBezierPath({
12
14
  sourceX,
@@ -19,4 +21,8 @@ $: [edgePath] = getBezierPath({
19
21
  });
20
22
  </script>
21
23
 
22
- <BaseEdge path={edgePath} {markerEnd} class={$useDataflow ? 'hidden' : ''} />
24
+ <BaseEdge
25
+ path={edgePath}
26
+ {markerEnd}
27
+ class={twMerge($useDataflow ? 'hidden' : '', data.class ?? '')}
28
+ />
@@ -20,6 +20,9 @@ declare const EmptyEdge: $$__sveltets_2_IsomorphicComponent<{
20
20
  targetY: number;
21
21
  targetPosition: Position;
22
22
  markerEnd?: string | undefined;
23
+ data?: {
24
+ class?: string;
25
+ };
23
26
  }, {
24
27
  [evt: string]: CustomEvent<any>;
25
28
  }, {}, {}, string>;