mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-19 00:02:03 +00:00
fix: preproccessor ui and expanding preprocessor support (#6872)
* preproccessor php * fix * ok * remove folder * chore: publish parser --------- Co-authored-by: HugoCasa <hugo@casademont.ch>
This commit is contained in:
@@ -44,23 +44,41 @@ fn parse_default_expr(e: Expression) -> Option<Value> {
|
||||
|
||||
pub fn parse_php_signature(
|
||||
code: &str,
|
||||
override_main: Option<String>,
|
||||
override_entrypoint: Option<String>,
|
||||
) -> anyhow::Result<MainArgSignature> {
|
||||
let main_name = override_main.unwrap_or("main".to_string());
|
||||
let entrypoint_fn_name = override_entrypoint.unwrap_or("main".to_string());
|
||||
|
||||
let ast = parser::parse(code)
|
||||
.map_err(|e| anyhow::anyhow!("Error parsing code: {}", e.to_string()))?;
|
||||
|
||||
let params = ast.into_iter().find_map(|x| match x {
|
||||
Statement::Function(FunctionStatement {
|
||||
name,
|
||||
parameters: FunctionParameterList { parameters, .. },
|
||||
..
|
||||
}) if name.to_string() == main_name => Some(parameters),
|
||||
_ => None,
|
||||
});
|
||||
let mut entrypoint_params = None;
|
||||
let mut has_preprocessor = None;
|
||||
for node in ast.into_iter() {
|
||||
match node {
|
||||
Statement::Function(FunctionStatement {
|
||||
name,
|
||||
parameters: FunctionParameterList { parameters, .. },
|
||||
..
|
||||
}) => {
|
||||
let fn_name = name.to_string();
|
||||
|
||||
if let Some(params) = params {
|
||||
if has_preprocessor.is_none() && fn_name == "preprocessor" {
|
||||
has_preprocessor = Some(true);
|
||||
}
|
||||
|
||||
if entrypoint_params.is_none() && fn_name == entrypoint_fn_name {
|
||||
entrypoint_params = Some(parameters);
|
||||
}
|
||||
|
||||
if has_preprocessor.is_some() && entrypoint_params.is_some() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
|
||||
if let Some(params) = entrypoint_params {
|
||||
let args = params
|
||||
.into_iter()
|
||||
.map(|x| {
|
||||
@@ -82,7 +100,7 @@ pub fn parse_php_signature(
|
||||
star_kwargs: false,
|
||||
args,
|
||||
no_main_func: Some(false),
|
||||
has_preprocessor: None,
|
||||
has_preprocessor,
|
||||
})
|
||||
} else {
|
||||
Ok(MainArgSignature {
|
||||
@@ -90,7 +108,7 @@ pub fn parse_php_signature(
|
||||
star_kwargs: false,
|
||||
args: vec![],
|
||||
no_main_func: Some(true),
|
||||
has_preprocessor: None,
|
||||
has_preprocessor,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,8 +134,11 @@ pub fn parse_graphql(code: &str) -> String {
|
||||
|
||||
#[cfg(feature = "php-parser")]
|
||||
#[wasm_bindgen]
|
||||
pub fn parse_php(code: &str) -> String {
|
||||
wrap_sig(windmill_parser_php::parse_php_signature(code, None))
|
||||
pub fn parse_php(code: &str, main_override: Option<String>) -> String {
|
||||
wrap_sig(windmill_parser_php::parse_php_signature(
|
||||
code,
|
||||
main_override,
|
||||
))
|
||||
}
|
||||
|
||||
#[cfg(feature = "rust-parser")]
|
||||
|
||||
@@ -2232,7 +2232,7 @@ async fn push_next_flow_job(
|
||||
}
|
||||
});
|
||||
|
||||
// if this is an empty module without preprocessor of if the module has already been completed, successfully, update the parent flow
|
||||
// if this is an empty module without preprocessor or if the module has already been completed, successfully, update the parent flow
|
||||
if (flow.modules.is_empty() && !step.is_preprocessor_step())
|
||||
|| matches!(status_module, FlowStatusModule::Success { .. })
|
||||
{
|
||||
@@ -3717,11 +3717,13 @@ pub struct JobPayloadWithTag {
|
||||
pub timeout: Option<i32>,
|
||||
pub on_behalf_of: Option<OnBehalfOf>,
|
||||
}
|
||||
#[derive(Debug)]
|
||||
enum ContinuePayload {
|
||||
SingleJob(JobPayloadWithTag),
|
||||
ParallelJobs(Vec<JobPayloadWithTag>),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum NextFlowTransform {
|
||||
EmptyInnerFlows { branch_chosen: Option<BranchChosen> },
|
||||
Continue(ContinuePayload, NextStatus),
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
export function parse_php(code: string): string;
|
||||
export function parse_php(code: string, main_override?: string | null): string;
|
||||
|
||||
@@ -56,30 +56,41 @@ function passStringToWasm0(arg, malloc, realloc) {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
const cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } );
|
||||
function isLikeNone(x) {
|
||||
return x === undefined || x === null;
|
||||
}
|
||||
|
||||
let cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } );
|
||||
|
||||
if (typeof TextDecoder !== 'undefined') { cachedTextDecoder.decode(); };
|
||||
|
||||
function decodeText(ptr, len) {
|
||||
return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
|
||||
}
|
||||
|
||||
function getStringFromWasm0(ptr, len) {
|
||||
ptr = ptr >>> 0;
|
||||
return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
|
||||
return decodeText(ptr, len);
|
||||
}
|
||||
/**
|
||||
* @param {string} code
|
||||
* @param {string | null} [main_override]
|
||||
* @returns {string}
|
||||
*/
|
||||
export function parse_php(code) {
|
||||
let deferred2_0;
|
||||
let deferred2_1;
|
||||
export function parse_php(code, main_override) {
|
||||
let deferred3_0;
|
||||
let deferred3_1;
|
||||
try {
|
||||
const ptr0 = passStringToWasm0(code, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
const ret = wasm.parse_php(ptr0, len0);
|
||||
deferred2_0 = ret[0];
|
||||
deferred2_1 = ret[1];
|
||||
var ptr1 = isLikeNone(main_override) ? 0 : passStringToWasm0(main_override, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
var len1 = WASM_VECTOR_LEN;
|
||||
const ret = wasm.parse_php(ptr0, len0, ptr1, len1);
|
||||
deferred3_0 = ret[0];
|
||||
deferred3_1 = ret[1];
|
||||
return getStringFromWasm0(ret[0], ret[1]);
|
||||
} finally {
|
||||
wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
|
||||
wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
+1
-1
@@ -1,7 +1,7 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
export const memory: WebAssembly.Memory;
|
||||
export const parse_php: (a: number, b: number) => [number, number];
|
||||
export const parse_php: (a: number, b: number, c: number, d: number) => [number, number];
|
||||
export const __wbindgen_export_0: WebAssembly.Table;
|
||||
export const __wbindgen_malloc: (a: number, b: number) => number;
|
||||
export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
||||
|
||||
Generated
+4
-4
@@ -77,7 +77,7 @@
|
||||
"windmill-parser-wasm-go": "1.510.1",
|
||||
"windmill-parser-wasm-java": "1.510.1",
|
||||
"windmill-parser-wasm-nu": "1.510.1",
|
||||
"windmill-parser-wasm-php": "1.510.1",
|
||||
"windmill-parser-wasm-php": "1.574.1",
|
||||
"windmill-parser-wasm-py": "1.538.0",
|
||||
"windmill-parser-wasm-regex": "1.565.0",
|
||||
"windmill-parser-wasm-ruby": "1.526.1",
|
||||
@@ -13749,9 +13749,9 @@
|
||||
"integrity": "sha512-AJLFiUy6af+LpUe7CddDo4+JOmw3c0K/1iOWh8NdTwXcLDj90lL6089mdsVo1apyloLgrTbcuFDzZMXVGBgtCg=="
|
||||
},
|
||||
"node_modules/windmill-parser-wasm-php": {
|
||||
"version": "1.510.1",
|
||||
"resolved": "https://registry.npmjs.org/windmill-parser-wasm-php/-/windmill-parser-wasm-php-1.510.1.tgz",
|
||||
"integrity": "sha512-qM+yeaqPdMuAaPpqND31ZabpeHlPxxtmRWLs11cGHOCHU32FIaZ92/icNUoAxgBhdJjRhR4GXaeZG32nWit2cg=="
|
||||
"version": "1.574.1",
|
||||
"resolved": "https://registry.npmjs.org/windmill-parser-wasm-php/-/windmill-parser-wasm-php-1.574.1.tgz",
|
||||
"integrity": "sha512-COyid6B1RYs+bpzUCInsA4HY/WZkpDLfkQ90+AqU/TVTpzYSbAC2JCbIwy0cRElBvlhI4bQ+9Wg6hSQKMpEkpA=="
|
||||
},
|
||||
"node_modules/windmill-parser-wasm-py": {
|
||||
"version": "1.538.0",
|
||||
|
||||
@@ -142,7 +142,7 @@
|
||||
"windmill-parser-wasm-go": "1.510.1",
|
||||
"windmill-parser-wasm-java": "1.510.1",
|
||||
"windmill-parser-wasm-nu": "1.510.1",
|
||||
"windmill-parser-wasm-php": "1.510.1",
|
||||
"windmill-parser-wasm-php": "1.574.1",
|
||||
"windmill-parser-wasm-py": "1.538.0",
|
||||
"windmill-parser-wasm-regex": "1.565.0",
|
||||
"windmill-parser-wasm-ruby": "1.526.1",
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
import { aiChatManager } from './copilot/chat/AIChatManager.svelte'
|
||||
import type { Selection } from 'monaco-editor'
|
||||
import { getDbSchemas } from './apps/components/display/dbtable/utils'
|
||||
import { PYTHON_PREPROCESSOR_MODULE_CODE, TS_PREPROCESSOR_MODULE_CODE } from '$lib/script_helpers'
|
||||
import { canHavePreprocessor, getPreprocessorModuleCode } from '$lib/script_helpers'
|
||||
import { setMonacoTypescriptOptions } from './monacoLanguagesOptions'
|
||||
import { copilotInfo } from '$lib/aiStore'
|
||||
// import EditorTheme from './EditorTheme.svelte'
|
||||
@@ -620,12 +620,18 @@
|
||||
}
|
||||
|
||||
let preprocessorCompletor: IDisposable | undefined = undefined
|
||||
function addPreprocessorCompletions(lang: 'typescript' | 'python') {
|
||||
function addPreprocessorCompletions(lang: string) {
|
||||
if (preprocessorCompletor) {
|
||||
preprocessorCompletor.dispose()
|
||||
}
|
||||
const preprocessorCode =
|
||||
lang === 'typescript' ? TS_PREPROCESSOR_MODULE_CODE : PYTHON_PREPROCESSOR_MODULE_CODE
|
||||
|
||||
const windmillLang = lang === 'typescript' ? 'deno' : lang === 'python' ? 'python3' : lang
|
||||
const preprocessorCode = getPreprocessorModuleCode(windmillLang as ScriptLang)
|
||||
|
||||
if (!preprocessorCode) {
|
||||
return
|
||||
}
|
||||
|
||||
preprocessorCompletor = languages.registerCompletionItemProvider(lang, {
|
||||
provideCompletionItems: function (model, position) {
|
||||
const word = model.getWordUntilPosition(position)
|
||||
@@ -1653,8 +1659,8 @@
|
||||
})
|
||||
|
||||
$effect(() => {
|
||||
initialized && (lang === 'typescript' || lang === 'python') && enablePreprocessorSnippet
|
||||
? untrack(() => addPreprocessorCompletions(lang as 'typescript' | 'python'))
|
||||
initialized && canHavePreprocessor(lang) && enablePreprocessorSnippet
|
||||
? untrack(() => addPreprocessorCompletions(lang))
|
||||
: preprocessorCompletor?.dispose()
|
||||
})
|
||||
|
||||
|
||||
@@ -15,7 +15,12 @@
|
||||
WorkerService
|
||||
} from '$lib/gen'
|
||||
import { inferArgs } from '$lib/infer'
|
||||
import { initialCode } from '$lib/script_helpers'
|
||||
import {
|
||||
initialCode,
|
||||
canHavePreprocessor,
|
||||
getPreprocessorFullCode,
|
||||
getMainFunctionPattern
|
||||
} from '$lib/script_helpers'
|
||||
import AIFormSettings from './copilot/AIFormSettings.svelte'
|
||||
import {
|
||||
defaultScripts,
|
||||
@@ -80,12 +85,6 @@
|
||||
import DeployOverrideConfirmationModal from '$lib/components/common/confirmationModal/DeployOverrideConfirmationModal.svelte'
|
||||
import TriggersEditor from './triggers/TriggersEditor.svelte'
|
||||
import type { ScheduleTrigger, TriggerContext } from './triggers'
|
||||
import {
|
||||
TS_PREPROCESSOR_MODULE_CODE,
|
||||
TS_PREPROCESSOR_SCRIPT_INTRO,
|
||||
PYTHON_PREPROCESSOR_MODULE_CODE,
|
||||
PYTHON_PREPROCESSOR_SCRIPT_INTRO
|
||||
} from '$lib/script_helpers'
|
||||
import CaptureTable from './triggers/CaptureTable.svelte'
|
||||
import type { SavedAndModifiedValue } from './common/confirmationModal/unsavedTypes'
|
||||
import DeployButton from './DeployButton.svelte'
|
||||
@@ -313,7 +312,7 @@
|
||||
{
|
||||
value: 'preprocessor',
|
||||
title: 'Preprocessor',
|
||||
desc: 'Transform incoming requests before they are passed to the flow.',
|
||||
desc: 'Transform incoming requests before they are passed to the main entrypoint.',
|
||||
documentationLink: 'https://www.windmill.dev/docs/core_concepts/preprocessors',
|
||||
Icon: Shuffle
|
||||
}
|
||||
@@ -853,13 +852,10 @@
|
||||
function addPreprocessor() {
|
||||
const code = editor?.getCode()
|
||||
if (code) {
|
||||
const preprocessorCode =
|
||||
script.language === 'python3'
|
||||
? PYTHON_PREPROCESSOR_SCRIPT_INTRO + PYTHON_PREPROCESSOR_MODULE_CODE
|
||||
: TS_PREPROCESSOR_SCRIPT_INTRO + TS_PREPROCESSOR_MODULE_CODE
|
||||
const mainIndex = code.indexOf(
|
||||
script.language === 'python3' ? 'def main' : 'export async function main'
|
||||
)
|
||||
const preprocessorCode = getPreprocessorFullCode(script.language, false)
|
||||
const mainPattern = getMainFunctionPattern(script.language)
|
||||
const mainIndex = code.indexOf(mainPattern)
|
||||
|
||||
if (mainIndex === -1) {
|
||||
editor?.setCode(code + preprocessorCode)
|
||||
} else {
|
||||
@@ -1139,7 +1135,8 @@
|
||||
btnClasses={isPicked ? '' : 'm-[1px]'}
|
||||
on:click={() => onScriptLanguageTrigger(lang)}
|
||||
disabled={lockedLanguage ||
|
||||
(enterpriseLangs.includes(lang) && !$enterpriseLicense)}
|
||||
(enterpriseLangs.includes(lang) && !$enterpriseLicense) ||
|
||||
(script.kind == 'preprocessor' && !canHavePreprocessor(lang))}
|
||||
startIcon={{
|
||||
icon: LanguageIcon,
|
||||
props: { lang }
|
||||
@@ -1667,9 +1664,7 @@
|
||||
newItem={initialPath == ''}
|
||||
isFlow={false}
|
||||
{hasPreprocessor}
|
||||
canHavePreprocessor={script.language === 'bun' ||
|
||||
script.language === 'deno' ||
|
||||
script.language === 'python3'}
|
||||
canHavePreprocessor={canHavePreprocessor(script.language)}
|
||||
args={hasPreprocessor && selectedInputTab !== 'preprocessor' ? {} : args}
|
||||
isDeployed={savedScript && !savedScript?.draft_only}
|
||||
schema={script.schema}
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
import { aiChatManager, AIMode } from './copilot/chat/AIChatManager.svelte'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI.svelte'
|
||||
import AssetsDropdownButton from './assets/AssetsDropdownButton.svelte'
|
||||
import { canHavePreprocessor } from '$lib/script_helpers'
|
||||
import { assetEq, type AssetWithAltAccessType } from './assets/lib'
|
||||
import { editor as meditor } from 'monaco-editor'
|
||||
import type { ReviewChangesOpts } from './copilot/chat/monaco-adapter'
|
||||
@@ -741,7 +742,7 @@
|
||||
<CaptureTable
|
||||
bind:this={captureTable}
|
||||
{hasPreprocessor}
|
||||
canHavePreprocessor={lang === 'bun' || lang === 'deno' || lang === 'python3'}
|
||||
canHavePreprocessor={canHavePreprocessor(lang)}
|
||||
isFlow={false}
|
||||
path={stablePathForCaptures}
|
||||
canEdit={true}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
import type { SupportedLanguage } from '$lib/common'
|
||||
import DefaultScripts from '$lib/components/DefaultScripts.svelte'
|
||||
import type { FlowBuilderWhitelabelCustomUi } from '$lib/components/custom_ui'
|
||||
import { canHavePreprocessor } from '$lib/script_helpers'
|
||||
|
||||
interface Props {
|
||||
failureModule: boolean
|
||||
@@ -57,18 +58,51 @@
|
||||
)
|
||||
|
||||
function displayLang(lang: SupportedLanguage | 'docker', kind: string) {
|
||||
if (lang == 'bun' || lang == 'python3' || lang == 'deno') {
|
||||
if (preprocessorModule) {
|
||||
return canHavePreprocessor(lang as SupportedLanguage)
|
||||
}
|
||||
|
||||
if (failureModule || kind === 'trigger') {
|
||||
if (
|
||||
[
|
||||
'postgresql',
|
||||
'mysql',
|
||||
'bigquery',
|
||||
'snowflake',
|
||||
'mssql',
|
||||
'graphql',
|
||||
'duckdb',
|
||||
'oracledb'
|
||||
].includes(lang)
|
||||
) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
if (lang == 'go') {
|
||||
return (kind == 'script' || kind == 'trigger' || failureModule) && !preprocessorModule
|
||||
if (kind === 'script') {
|
||||
return lang !== 'docker'
|
||||
}
|
||||
|
||||
if (lang == 'bash' || lang == 'nativets') {
|
||||
return kind == 'script' && !preprocessorModule
|
||||
if (kind === 'approval') {
|
||||
if (
|
||||
[
|
||||
'postgresql',
|
||||
'mysql',
|
||||
'bigquery',
|
||||
'snowflake',
|
||||
'mssql',
|
||||
'graphql',
|
||||
'duckdb',
|
||||
'oracledb'
|
||||
].includes(lang)
|
||||
) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
return kind == 'script' && !failureModule && !preprocessorModule
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
let customUi: undefined | FlowBuilderWhitelabelCustomUi = getContext('customUi')
|
||||
|
||||
@@ -30,6 +30,12 @@
|
||||
import GenAiQuick from './GenAiQuick.svelte'
|
||||
import FlowToplevelNode from '../pickers/FlowToplevelNode.svelte'
|
||||
import { copilotInfo } from '$lib/aiStore'
|
||||
import {
|
||||
canHavePreprocessor,
|
||||
canHaveTrigger,
|
||||
canHaveApproval,
|
||||
canHaveFailure
|
||||
} from '$lib/script_helpers'
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
@@ -94,17 +100,17 @@
|
||||
kind: 'script' | 'flow' | 'approval' | 'trigger' | 'preprocessor' | 'failure'
|
||||
) {
|
||||
if (kind == 'trigger') {
|
||||
return ['python3', 'bun', 'deno', 'go'].includes(lang)
|
||||
return canHaveTrigger(lang as SupportedLanguage)
|
||||
} else if (kind == 'script') {
|
||||
return true
|
||||
} else if (kind == 'approval') {
|
||||
return ['python3', 'bun', 'deno'].includes(lang)
|
||||
return canHaveApproval(lang as SupportedLanguage)
|
||||
} else if (kind == 'flow') {
|
||||
return false
|
||||
} else if (kind == 'preprocessor') {
|
||||
return ['python3', 'bun', 'deno'].includes(lang)
|
||||
return canHavePreprocessor(lang as SupportedLanguage)
|
||||
} else if (kind == 'failure') {
|
||||
return ['python3', 'bun', 'deno', 'go'].includes(lang)
|
||||
return canHaveFailure(lang as SupportedLanguage)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,11 @@ import initPythonParser, { parse_assets_py, parse_python } from 'windmill-parser
|
||||
import initGoParser, { parse_go } from 'windmill-parser-wasm-go'
|
||||
import initPhpParser, { parse_php } from 'windmill-parser-wasm-php'
|
||||
import initRustParser, { parse_rust } from 'windmill-parser-wasm-rust'
|
||||
import initYamlParser, { parse_assets_ansible, parse_ansible, parse_ansible_delegate } from 'windmill-parser-wasm-yaml'
|
||||
import initYamlParser, {
|
||||
parse_assets_ansible,
|
||||
parse_ansible,
|
||||
parse_ansible_delegate
|
||||
} from 'windmill-parser-wasm-yaml'
|
||||
import initCSharpParser, { parse_csharp } from 'windmill-parser-wasm-csharp'
|
||||
import initNuParser, { parse_nu } from 'windmill-parser-wasm-nu'
|
||||
import initJavaParser, { parse_java } from 'windmill-parser-wasm-java'
|
||||
@@ -244,7 +248,7 @@ export async function inferArgs(
|
||||
inferedSchema = JSON.parse(parse_powershell(code))
|
||||
} else if (language == 'php') {
|
||||
await initWasmPhp()
|
||||
inferedSchema = JSON.parse(parse_php(code))
|
||||
inferedSchema = JSON.parse(parse_php(code, mainOverride))
|
||||
} else if (language == 'rust') {
|
||||
await initWasmRust()
|
||||
inferedSchema = JSON.parse(parse_rust(code))
|
||||
|
||||
@@ -969,6 +969,86 @@ def preprocessor(event: Event):
|
||||
}
|
||||
`
|
||||
|
||||
export const PHP_PREPROCESSOR_SCRIPT_INTRO = `<?php
|
||||
/**
|
||||
* Trigger preprocessor
|
||||
*
|
||||
* ⚠️ This function runs BEFORE the main function.
|
||||
*
|
||||
* It processes raw trigger data from various sources (webhook, custom HTTP route, SQS, WebSocket, Kafka, NATS, MQTT, Postgres, or email)
|
||||
* before passing it to \`main\`. This separates the trigger logic from the main logic and keeps the auto-generated runnable UI clean.
|
||||
*
|
||||
* The returned object defines the parameter values passed to \`main()\`.
|
||||
* e.g., ['b' => 1, 'a' => 2] → Calls \`main(2, 1)\`, assuming \`main\` is defined as \`main($a, $b)\`.
|
||||
* Ensure that the parameter names in \`main\` match the keys in the returned array.
|
||||
*
|
||||
* Learn more: https://www.windmill.dev/docs/core_concepts/preprocessors
|
||||
*/
|
||||
|
||||
`
|
||||
|
||||
export const PHP_PREPROCESSOR_FLOW_INTRO = `<?php
|
||||
/**
|
||||
* Trigger preprocessor
|
||||
*
|
||||
* It processes raw trigger data from various sources (webhook, custom HTTP route, SQS, WebSocket, Kafka, NATS, MQTT, Postgres, or email)
|
||||
* before passing it to the flow. This separates the trigger logic from the flow logic and keeps the auto-generated UI clean.
|
||||
*
|
||||
* The returned object determines the parameter values passed to the flow.
|
||||
* e.g., ['b' => 1, 'a' => 2] → Calls the flow with \`a = 2\` and \`b = 1\`, assuming the flow has two inputs called \`a\` and \`b\`.
|
||||
* Ensure that the input names of the flow match the keys in the returned array.
|
||||
*
|
||||
* Learn more: https://www.windmill.dev/docs/core_concepts/preprocessors
|
||||
*/
|
||||
|
||||
`
|
||||
|
||||
export const PHP_PREPROCESSOR_MODULE_CODE = `function preprocessor(object $event) {
|
||||
// $event can be one of the following types:
|
||||
//
|
||||
// Webhook event:
|
||||
// ['kind' => 'webhook', 'body' => [...], 'raw_string' => '...', 'query' => [...], 'headers' => [...]]
|
||||
//
|
||||
// HTTP event:
|
||||
// ['kind' => 'http', 'body' => [...], 'raw_string' => '...', 'route' => '...', 'path' => '...',
|
||||
// 'method' => '...', 'params' => [...], 'query' => [...], 'headers' => [...]]
|
||||
//
|
||||
// Email event:
|
||||
// ['kind' => 'email', 'parsed_email' => [...], 'raw_email' => '...', 'email_extra_args' => [...]]
|
||||
//
|
||||
// WebSocket event:
|
||||
// ['kind' => 'websocket', 'msg' => '...', 'url' => '...']
|
||||
//
|
||||
// Kafka event:
|
||||
// ['kind' => 'kafka', 'payload' => '...', 'brokers' => [...], 'topic' => '...', 'group_id' => '...']
|
||||
//
|
||||
// NATS event:
|
||||
// ['kind' => 'nats', 'payload' => '...', 'servers' => [...], 'subject' => '...',
|
||||
// 'headers' => [...], 'status' => 200, 'description' => '...', 'length' => 100]
|
||||
//
|
||||
// SQS event:
|
||||
// ['kind' => 'sqs', 'msg' => '...', 'queue_url' => '...', 'message_id' => '...',
|
||||
// 'receipt_handle' => '...', 'attributes' => [...], 'message_attributes' => [...]]
|
||||
//
|
||||
// MQTT event:
|
||||
// ['kind' => 'mqtt', 'payload' => '...', 'topic' => '...', 'retain' => true, 'pkid' => 1,
|
||||
// 'qos' => 1, 'v5' => [...]]
|
||||
//
|
||||
// GCP event:
|
||||
// ['kind' => 'gcp', 'payload' => '...', 'message_id' => '...', 'subscription' => '...',
|
||||
// 'ordering_key' => '...', 'attributes' => [...], 'delivery_type' => 'push',
|
||||
// 'headers' => [...], 'publish_time' => '...', 'ack_id' => '...']
|
||||
//
|
||||
// Postgres event:
|
||||
// ['kind' => 'postgres', 'transaction_type' => 'insert', 'schema_name' => '...',
|
||||
// 'table_name' => '...', 'old_row' => [...], 'row' => [...]]
|
||||
|
||||
return [
|
||||
// return the args to be passed to the runnable
|
||||
];
|
||||
}
|
||||
`
|
||||
|
||||
const DOCKER_INIT_CODE = `# shellcheck shell=bash
|
||||
# docker
|
||||
# The annotation "docker" above is important, it tells windmill that after
|
||||
@@ -1226,7 +1306,8 @@ export const INITIAL_CODE = {
|
||||
script: ORACLEDB_INIT_CODE
|
||||
},
|
||||
php: {
|
||||
script: PHP_INIT_CODE
|
||||
script: PHP_INIT_CODE,
|
||||
preprocessor: PHP_PREPROCESSOR_FLOW_INTRO + PHP_PREPROCESSOR_MODULE_CODE
|
||||
},
|
||||
rust: {
|
||||
script: RUST_INIT_CODE
|
||||
@@ -1349,6 +1430,9 @@ export function initialCode(
|
||||
} else if (language == 'duckdb') {
|
||||
return INITIAL_CODE.duckdb.script
|
||||
} else if (language == 'php') {
|
||||
if (kind == 'preprocessor') {
|
||||
return INITIAL_CODE.php.preprocessor
|
||||
}
|
||||
return INITIAL_CODE.php.script
|
||||
} else if (language == 'rust') {
|
||||
return INITIAL_CODE.rust.script
|
||||
@@ -1420,3 +1504,115 @@ export function getResetCode(
|
||||
return initialCode(language, kind, subkind)
|
||||
}
|
||||
}
|
||||
|
||||
export const PREPROCESSOR_SUPPORTED_LANGUAGES = [
|
||||
'typescript',
|
||||
'python',
|
||||
'python3',
|
||||
'deno',
|
||||
'bun',
|
||||
'php'
|
||||
] as const
|
||||
|
||||
export function canHavePreprocessor(language: string | undefined): boolean {
|
||||
if (!language) {
|
||||
return false
|
||||
}
|
||||
|
||||
return PREPROCESSOR_SUPPORTED_LANGUAGES.includes(language as any)
|
||||
}
|
||||
|
||||
export function canHaveTrigger(language: SupportedLanguage | undefined): boolean {
|
||||
if (!language) {
|
||||
return false
|
||||
}
|
||||
|
||||
return ['python3', 'bun', 'deno', 'go'].includes(language)
|
||||
}
|
||||
|
||||
export function canHaveApproval(language: SupportedLanguage | undefined): boolean {
|
||||
if (!language) {
|
||||
return false
|
||||
}
|
||||
|
||||
return ['python3', 'bun', 'deno'].includes(language)
|
||||
}
|
||||
|
||||
export function canHaveFailure(language: SupportedLanguage | undefined): boolean {
|
||||
if (!language) {
|
||||
return false
|
||||
}
|
||||
|
||||
return ['python3', 'bun', 'deno', 'go'].includes(language)
|
||||
}
|
||||
|
||||
export function getPreprocessorIntro(
|
||||
language: SupportedLanguage | 'docker' | 'bunnative' | undefined,
|
||||
isFlow: boolean = false
|
||||
): string {
|
||||
if (!language || !PREPROCESSOR_SUPPORTED_LANGUAGES.includes(language as any)) {
|
||||
return ''
|
||||
}
|
||||
|
||||
switch (language) {
|
||||
case 'python3':
|
||||
return isFlow ? PYTHON_PREPROCESSOR_FLOW_INTRO : PYTHON_PREPROCESSOR_SCRIPT_INTRO
|
||||
case 'deno':
|
||||
case 'bun':
|
||||
return isFlow ? TS_PREPROCESSOR_FLOW_INTRO : TS_PREPROCESSOR_SCRIPT_INTRO
|
||||
case 'php':
|
||||
return isFlow ? PHP_PREPROCESSOR_FLOW_INTRO : PHP_PREPROCESSOR_SCRIPT_INTRO
|
||||
default:
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
export function getPreprocessorModuleCode(
|
||||
language: SupportedLanguage | 'docker' | 'bunnative' | undefined
|
||||
): string {
|
||||
if (!language || !PREPROCESSOR_SUPPORTED_LANGUAGES.includes(language as any)) {
|
||||
return ''
|
||||
}
|
||||
|
||||
switch (language) {
|
||||
case 'python3':
|
||||
return PYTHON_PREPROCESSOR_MODULE_CODE
|
||||
case 'deno':
|
||||
case 'bun':
|
||||
return TS_PREPROCESSOR_MODULE_CODE
|
||||
case 'php':
|
||||
return PHP_PREPROCESSOR_MODULE_CODE
|
||||
default:
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
export function getPreprocessorFullCode(
|
||||
language: SupportedLanguage | 'docker' | 'bunnative' | undefined,
|
||||
isFlow: boolean = false
|
||||
): string {
|
||||
const intro = getPreprocessorIntro(language, isFlow)
|
||||
const moduleCode = getPreprocessorModuleCode(language)
|
||||
return intro + moduleCode
|
||||
}
|
||||
|
||||
export function getMainFunctionPattern(
|
||||
language: SupportedLanguage | 'docker' | 'bunnative' | undefined
|
||||
): string {
|
||||
if (!language) {
|
||||
return ''
|
||||
}
|
||||
|
||||
switch (language) {
|
||||
case 'python3':
|
||||
return 'def main'
|
||||
case 'deno':
|
||||
case 'bun':
|
||||
case 'nativets':
|
||||
return 'export async function main'
|
||||
case 'php':
|
||||
return 'function main'
|
||||
default:
|
||||
return 'main'
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user