From 28c073056c65d4ed1600e39679497e5af964347f Mon Sep 17 00:00:00 2001 From: centdix <40307056+centdix@users.noreply.github.com> Date: Thu, 2 Apr 2026 03:57:56 +0200 Subject: [PATCH] fix: correct raw app flow inputs (#8667) * fix: correct raw app flow inputs Co-Authored-By: Claude Opus 4.5 * refactor: remove raw app legacy migration Co-Authored-By: Claude Opus 4.5 --------- Co-authored-by: Claude Opus 4.5 --- .../mainInput/RunnableSelector.svelte | 59 ++++++++----------- .../mainInput/runnableSelectorUtils.test.ts | 53 +++++++++++++++++ .../mainInput/runnableSelectorUtils.ts | 31 ++++++++++ .../src/lib/components/raw_apps/utils.test.ts | 45 ++++++++++++++ frontend/src/lib/components/raw_apps/utils.ts | 2 +- 5 files changed, 156 insertions(+), 34 deletions(-) create mode 100644 frontend/src/lib/components/apps/editor/settingsPanel/mainInput/runnableSelectorUtils.test.ts create mode 100644 frontend/src/lib/components/apps/editor/settingsPanel/mainInput/runnableSelectorUtils.ts create mode 100644 frontend/src/lib/components/raw_apps/utils.test.ts diff --git a/frontend/src/lib/components/apps/editor/settingsPanel/mainInput/RunnableSelector.svelte b/frontend/src/lib/components/apps/editor/settingsPanel/mainInput/RunnableSelector.svelte index 23419e51be..717f59ac6e 100644 --- a/frontend/src/lib/components/apps/editor/settingsPanel/mainInput/RunnableSelector.svelte +++ b/frontend/src/lib/components/apps/editor/settingsPanel/mainInput/RunnableSelector.svelte @@ -8,10 +8,10 @@ import WorkspaceFlowList from './WorkspaceFlowList.svelte' import { createEventDispatcher, untrack } from 'svelte' import type { Schema } from '$lib/common' - import { schemaToInputsSpec } from '$lib/components/apps/utils' - import { defaultIfEmptyString, emptySchema } from '$lib/utils' + import { emptySchema } from '$lib/utils' import { loadSchema } from '$lib/infer' import { workspaceStore } from '$lib/stores' + import { buildPathRunnableSelection } from './runnableSelectorUtils' type TabType = 'hubscripts' | 'workspacescripts' | 'workspaceflows' | 'inlinescripts' @@ -62,51 +62,44 @@ } async function pickScript(path: string) { - const schema = await loadSchemaFromTriggerable(path, 'script') - const fields = schemaToInputsSpec(schema.schema, defaultUserInput) - const runnable = { - type: 'path', + const selection = buildPathRunnableSelection( path, - runType: 'script', - schema: schema.schema, - name: defaultIfEmptyString(schema.summary, path) - } as const - + 'script', + await loadSchemaFromTriggerable(path, 'script'), + defaultUserInput, + rawApps + ) dispatch('pick', { - runnable, - fields + runnable: selection.runnable, + fields: selection.fields }) } async function pickFlow(path: string) { - const schema = await loadSchemaFromTriggerable(path, 'flow') - const fields = schemaToInputsSpec(schema.schema, defaultUserInput) - const runnable = { - type: 'path', + const selection = buildPathRunnableSelection( path, - runType: 'flow', - schema, - name: defaultIfEmptyString(schema.summary, path) - } as const + 'flow', + await loadSchemaFromTriggerable(path, 'flow'), + defaultUserInput, + rawApps + ) dispatch('pick', { - runnable, - fields + runnable: selection.runnable, + fields: selection.fields }) } async function pickHubScript(path: string) { - const schema = await loadSchemaFromTriggerable(path, 'hubscript') - const fields = schemaToInputsSpec(schema.schema, defaultUserInput) - const runnable = { - type: 'path', + const selection = buildPathRunnableSelection( path, - runType: 'hubscript', - schema: schema.schema, - name: defaultIfEmptyString(schema.summary, path) - } as const + 'hubscript', + await loadSchemaFromTriggerable(path, 'hubscript'), + defaultUserInput, + rawApps + ) dispatch('pick', { - runnable, - fields + runnable: selection.runnable, + fields: selection.fields }) } diff --git a/frontend/src/lib/components/apps/editor/settingsPanel/mainInput/runnableSelectorUtils.test.ts b/frontend/src/lib/components/apps/editor/settingsPanel/mainInput/runnableSelectorUtils.test.ts new file mode 100644 index 0000000000..8968363f03 --- /dev/null +++ b/frontend/src/lib/components/apps/editor/settingsPanel/mainInput/runnableSelectorUtils.test.ts @@ -0,0 +1,53 @@ +import { describe, expect, it } from 'vitest' + +import type { LoadedRunnableSchema } from './runnableSelectorUtils' +import { buildPathRunnableSelection } from './runnableSelectorUtils' + +const loadedSchema: LoadedRunnableSchema = { + summary: 'My flow', + schema: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + required: ['string_input'], + properties: { + string_input: { + type: 'string', + default: '' + } + } + } +} + +describe('buildPathRunnableSelection', () => { + it('keeps the actual schema object and defaults raw-app fields to user mode', () => { + const selection = buildPathRunnableSelection( + 'u/dev/my_flow', + 'flow', + loadedSchema, + false, + true + ) + + expect(selection.runnable).toMatchObject({ + type: 'path', + path: 'u/dev/my_flow', + runType: 'flow', + schema: loadedSchema.schema, + name: 'My flow' + }) + expect(selection.fields.string_input.type).toBe('user') + expect(selection.fields.string_input.value).toBe('') + }) + + it('preserves static defaults for non-raw-app pickers', () => { + const selection = buildPathRunnableSelection( + 'u/dev/my_flow', + 'flow', + loadedSchema, + false, + false + ) + + expect(selection.fields.string_input.type).toBe('static') + }) +}) diff --git a/frontend/src/lib/components/apps/editor/settingsPanel/mainInput/runnableSelectorUtils.ts b/frontend/src/lib/components/apps/editor/settingsPanel/mainInput/runnableSelectorUtils.ts new file mode 100644 index 0000000000..44e989e925 --- /dev/null +++ b/frontend/src/lib/components/apps/editor/settingsPanel/mainInput/runnableSelectorUtils.ts @@ -0,0 +1,31 @@ +import type { Schema } from '$lib/common' +import type { Runnable, StaticAppInput } from '$lib/components/apps/inputType' +import { schemaToInputsSpec } from '$lib/components/apps/utils' +import { defaultIfEmptyString } from '$lib/utils' + +export type LoadedRunnableSchema = { + schema: Schema + summary: string | undefined +} + +export function buildPathRunnableSelection( + path: string, + runType: 'script' | 'flow' | 'hubscript', + loadedSchema: LoadedRunnableSchema, + defaultUserInput: boolean, + rawApps: boolean +): { + runnable: Runnable + fields: Record +} { + return { + runnable: { + type: 'path', + path, + runType, + schema: loadedSchema.schema, + name: defaultIfEmptyString(loadedSchema.summary, path) + }, + fields: schemaToInputsSpec(loadedSchema.schema, defaultUserInput || rawApps) + } +} diff --git a/frontend/src/lib/components/raw_apps/utils.test.ts b/frontend/src/lib/components/raw_apps/utils.test.ts new file mode 100644 index 0000000000..e6b1fe5e36 --- /dev/null +++ b/frontend/src/lib/components/raw_apps/utils.test.ts @@ -0,0 +1,45 @@ +import { describe, expect, it } from 'vitest' + +import { genWmillTs, type Runnable } from './utils' + +const flowSchema = { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + required: ['string_input'], + properties: { + string_input: { + type: 'string', + default: '' + }, + count: { + type: 'integer' + } + } +} as const + +describe('genWmillTs', () => { + it('generates the correct flow args type for path runnables', () => { + const runnables: Record = { + myflow: { + type: 'path', + runType: 'flow', + path: 'u/dev/my_flow', + name: 'My flow', + schema: flowSchema, + fields: { + count: { + type: 'static', + value: 1, + fieldType: 'number' + } + } + } + } + + const dts = genWmillTs(runnables) + + expect(dts).toContain( + 'myflow: (args: { string_input: string }) => Promise;' + ) + }) +}) diff --git a/frontend/src/lib/components/raw_apps/utils.ts b/frontend/src/lib/components/raw_apps/utils.ts index 06264d9c5f..928a7b8d81 100644 --- a/frontend/src/lib/components/raw_apps/utils.ts +++ b/frontend/src/lib/components/raw_apps/utils.ts @@ -108,7 +108,7 @@ function hiddenRunnableToTsType(runnable: Runnable) { } } else if (isRunnableByPath(runnable)) { if (runnable?.schema) { - return schemaToTsType(removeStaticFields(runnable.schema, runnable?.fields ?? {})) + return schemaToTsType(removeStaticFields(runnable.schema as Schema, runnable?.fields ?? {})) } else { return '{}' }