diff --git a/backend/migrations/20230809143140_add_powershell_lang.down.sql b/backend/migrations/20230809143140_add_powershell_lang.down.sql new file mode 100644 index 0000000000..d2f607c5b8 --- /dev/null +++ b/backend/migrations/20230809143140_add_powershell_lang.down.sql @@ -0,0 +1 @@ +-- Add down migration script here diff --git a/backend/migrations/20230809143140_add_powershell_lang.up.sql b/backend/migrations/20230809143140_add_powershell_lang.up.sql new file mode 100644 index 0000000000..24f318d7cb --- /dev/null +++ b/backend/migrations/20230809143140_add_powershell_lang.up.sql @@ -0,0 +1,2 @@ +-- Add up migration script here +ALTER TYPE SCRIPT_LANG ADD VALUE IF NOT EXISTS 'powershell'; \ No newline at end of file diff --git a/backend/parsers/windmill-parser-bash/src/lib.rs b/backend/parsers/windmill-parser-bash/src/lib.rs index 23e4c0ef24..4634006e26 100644 --- a/backend/parsers/windmill-parser-bash/src/lib.rs +++ b/backend/parsers/windmill-parser-bash/src/lib.rs @@ -8,7 +8,7 @@ use std::collections::HashMap; use windmill_parser::{Arg, MainArgSignature, Typ}; pub fn parse_bash_sig(code: &str) -> anyhow::Result { - let parsed = parse_file(&code)?; + let parsed = parse_bash_file(&code)?; if let Some(x) = parsed { let args = x; Ok(MainArgSignature { star_args: false, star_kwargs: false, args }) @@ -17,13 +17,26 @@ pub fn parse_bash_sig(code: &str) -> anyhow::Result { } } -lazy_static::lazy_static! { - static ref RE: Regex = Regex::new(r#"(?m)^(\w+)="\$(?:(\d+)|\{(\d+):-(.*)\})"(?:([\t ]*#.*)?)$"#).unwrap(); +pub fn parse_powershell_sig(code: &str) -> anyhow::Result { + let parsed = parse_powershell_file(&code)?; + if let Some(x) = parsed { + let args = x; + Ok(MainArgSignature { star_args: false, star_kwargs: false, args }) + } else { + Err(anyhow!("Error parsing powershell script".to_string())) + } } -fn parse_file(code: &str) -> anyhow::Result>> { +lazy_static::lazy_static! { + static ref RE_BASH: Regex = Regex::new(r#"(?m)^(\w+)="\$(?:(\d+)|\{(\d+):-(.*)\})"(?:[\t ]*)?(?:#.*)?$"#).unwrap(); + + static ref RE_POWERSHELL_PARAM: Regex = Regex::new(r#"(?m)param[\t ]*\(([^)]*)\)"#).unwrap(); + static ref RE_POWERSHELL_ARGS: Regex = Regex::new(r#"(?:\[(\w+)\])?\$(\w+)[\t ]*(?:=[\t ]*(?:(?:(?:"|')([^"\n\r\$]*)(?:"|'))|([\d.]+)))?"#).unwrap(); +} + +fn parse_bash_file(code: &str) -> anyhow::Result>> { let mut hm: HashMap)> = HashMap::new(); - for cap in RE.captures_iter(code) { + for cap in RE_BASH.captures_iter(code) { hm.insert( cap.get(2) .or(cap.get(3)) @@ -53,6 +66,39 @@ fn parse_file(code: &str) -> anyhow::Result>> { Ok(Some(args)) } +fn parse_powershell_file(code: &str) -> anyhow::Result>> { + let param_wrapper = RE_POWERSHELL_PARAM.captures(code); + let mut args = vec![]; + if let Some(param_wrapper) = param_wrapper { + let param_wrapper = param_wrapper.get(1).unwrap().as_str(); + for cap in RE_POWERSHELL_ARGS.captures_iter(param_wrapper) { + let typ = cap + .get(1) + .map(|x| x.as_str().to_string()) + .unwrap_or("string".to_string()); + let name = cap.get(2).unwrap().as_str().to_string(); + let default = cap + .get(3) + .or(cap.get(4)) + .map(|x| json!(x.as_str().to_string())); + + args.push(Arg { + name: name, + typ: match typ.as_str() { + "string" => Typ::Str(None), + "int" | "long" => Typ::Int, + "decimal" | "double" | "single" => Typ::Float, + _ => Typ::Str(None), + }, + default: default.clone(), + otyp: None, + has_default: default.is_some(), + }); + } + } + Ok(Some(args)) +} + #[cfg(test)] mod tests { diff --git a/backend/parsers/windmill-parser-graphql/src/lib.rs b/backend/parsers/windmill-parser-graphql/src/lib.rs index 365a4e2074..4a9a28e246 100644 --- a/backend/parsers/windmill-parser-graphql/src/lib.rs +++ b/backend/parsers/windmill-parser-graphql/src/lib.rs @@ -18,7 +18,6 @@ pub fn parse_graphql_sig(code: &str) -> anyhow::Result { lazy_static::lazy_static! { static ref RE_ARG_GRAPHQL: Regex = Regex::new(r#"\$(\w+)\s*:\s*(?:(\w+)!?|\[(\w+)!?\])!?\s*(?:=\s*(\w+)\s*)?"#).unwrap(); - static ref RE_ARG_GRAPHQL_ARRAY: Regex = Regex::new(r#"^\[(\w+)!?\]!?$"#).unwrap(); } fn parse_graphql_file(code: &str) -> anyhow::Result>> { diff --git a/backend/parsers/windmill-parser-wasm/pkg/package.json b/backend/parsers/windmill-parser-wasm/pkg/package.json index 9baba9bf40..23655f63e1 100644 --- a/backend/parsers/windmill-parser-wasm/pkg/package.json +++ b/backend/parsers/windmill-parser-wasm/pkg/package.json @@ -3,7 +3,7 @@ "collaborators": [ "Ruben Fiszel " ], - "version": "1.141.0", + "version": "1.143.0", "files": [ "windmill_parser_wasm_bg.wasm", "windmill_parser_wasm.js", diff --git a/backend/parsers/windmill-parser-wasm/pkg/windmill_parser_wasm.d.ts b/backend/parsers/windmill-parser-wasm/pkg/windmill_parser_wasm.d.ts index 4a8e39017b..794b54300d 100644 --- a/backend/parsers/windmill-parser-wasm/pkg/windmill_parser_wasm.d.ts +++ b/backend/parsers/windmill-parser-wasm/pkg/windmill_parser_wasm.d.ts @@ -14,6 +14,11 @@ export function parse_bash(code: string): string; * @param {string} code * @returns {string} */ +export function parse_powershell(code: string): string; +/** +* @param {string} code +* @returns {string} +*/ export function parse_go(code: string): string; /** * @param {string} code @@ -52,6 +57,7 @@ export interface InitOutput { readonly memory: WebAssembly.Memory; readonly parse_deno: (a: number, b: number, c: number) => void; readonly parse_bash: (a: number, b: number, c: number) => void; + readonly parse_powershell: (a: number, b: number, c: number) => void; readonly parse_go: (a: number, b: number, c: number) => void; readonly parse_python: (a: number, b: number, c: number) => void; readonly parse_sql: (a: number, b: number, c: number) => void; diff --git a/backend/parsers/windmill-parser-wasm/pkg/windmill_parser_wasm.js b/backend/parsers/windmill-parser-wasm/pkg/windmill_parser_wasm.js index 7eac3e39af..a215a2ba9e 100644 --- a/backend/parsers/windmill-parser-wasm/pkg/windmill_parser_wasm.js +++ b/backend/parsers/windmill-parser-wasm/pkg/windmill_parser_wasm.js @@ -243,6 +243,29 @@ export function parse_bash(code) { } } +/** +* @param {string} code +* @returns {string} +*/ +export function parse_powershell(code) { + let deferred2_0; + let deferred2_1; + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + const ptr0 = passStringToWasm0(code, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + wasm.parse_powershell(retptr, ptr0, len0); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + deferred2_0 = r0; + deferred2_1 = r1; + return getStringFromWasm0(r0, r1); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + wasm.__wbindgen_free(deferred2_0, deferred2_1, 1); + } +} + /** * @param {string} code * @returns {string} @@ -446,7 +469,7 @@ async function __wbg_load(module, imports) { function __wbg_get_imports() { const imports = {}; imports.wbg = {}; - imports.wbg.__wbg_eval_9331e2bd3095f3d6 = function(arg0, arg1) { + imports.wbg.__wbg_eval_44bde4e76596166e = function(arg0, arg1) { const ret = eval(getStringFromWasm0(arg0, arg1)); return addHeapObject(ret); }; diff --git a/backend/parsers/windmill-parser-wasm/pkg/windmill_parser_wasm_bg.wasm b/backend/parsers/windmill-parser-wasm/pkg/windmill_parser_wasm_bg.wasm index bc52747ad5..ca21939b6c 100644 Binary files a/backend/parsers/windmill-parser-wasm/pkg/windmill_parser_wasm_bg.wasm and b/backend/parsers/windmill-parser-wasm/pkg/windmill_parser_wasm_bg.wasm differ diff --git a/backend/parsers/windmill-parser-wasm/pkg/windmill_parser_wasm_bg.wasm.d.ts b/backend/parsers/windmill-parser-wasm/pkg/windmill_parser_wasm_bg.wasm.d.ts index ed02311c3e..1dffa32882 100644 --- a/backend/parsers/windmill-parser-wasm/pkg/windmill_parser_wasm_bg.wasm.d.ts +++ b/backend/parsers/windmill-parser-wasm/pkg/windmill_parser_wasm_bg.wasm.d.ts @@ -3,6 +3,7 @@ export const memory: WebAssembly.Memory; export function parse_deno(a: number, b: number, c: number): void; export function parse_bash(a: number, b: number, c: number): void; +export function parse_powershell(a: number, b: number, c: number): void; export function parse_go(a: number, b: number, c: number): void; export function parse_python(a: number, b: number, c: number): void; export function parse_sql(a: number, b: number, c: number): void; diff --git a/backend/parsers/windmill-parser-wasm/src/lib.rs b/backend/parsers/windmill-parser-wasm/src/lib.rs index fb05db3d36..af84671b29 100644 --- a/backend/parsers/windmill-parser-wasm/src/lib.rs +++ b/backend/parsers/windmill-parser-wasm/src/lib.rs @@ -20,6 +20,11 @@ pub fn parse_bash(code: &str) -> String { wrap_sig(windmill_parser_bash::parse_bash_sig(code)) } +#[wasm_bindgen] +pub fn parse_powershell(code: &str) -> String { + wrap_sig(windmill_parser_bash::parse_powershell_sig(code)) +} + #[wasm_bindgen] pub fn parse_go(code: &str) -> String { wrap_sig(windmill_parser_go::parse_go_sig(code)) diff --git a/backend/windmill-api/openapi.yaml b/backend/windmill-api/openapi.yaml index b569209bd6..c6fe6a1551 100644 --- a/backend/windmill-api/openapi.yaml +++ b/backend/windmill-api/openapi.yaml @@ -5691,6 +5691,7 @@ components: deno, go, bash, + powershell, postgresql, mysql, bigquery, @@ -5768,6 +5769,7 @@ components: deno, go, bash, + powershell, postgresql, mysql, bigquery, @@ -5950,6 +5952,7 @@ components: deno, go, bash, + powershell, postgresql, mysql, bigquery, @@ -6052,6 +6055,7 @@ components: deno, go, bash, + powershell, postgresql, mysql, bigquery, @@ -6563,6 +6567,7 @@ components: deno, go, bash, + powershell, postgresql, mysql, bigquery, diff --git a/backend/windmill-api/src/workspaces.rs b/backend/windmill-api/src/workspaces.rs index 987ddcffb8..d6c0f5918f 100644 --- a/backend/windmill-api/src/workspaces.rs +++ b/backend/windmill-api/src/workspaces.rs @@ -1474,6 +1474,7 @@ async fn tarball_workspace( ScriptLang::Deno => "ts", ScriptLang::Go => "go", ScriptLang::Bash => "sh", + ScriptLang::Powershell => "ps1", ScriptLang::Postgresql => "pg.sql", ScriptLang::Mysql => "my.sql", ScriptLang::Bigquery => "bq.sql", diff --git a/backend/windmill-common/src/scripts.rs b/backend/windmill-common/src/scripts.rs index 9739940c32..31a313bce8 100644 --- a/backend/windmill-common/src/scripts.rs +++ b/backend/windmill-common/src/scripts.rs @@ -30,6 +30,7 @@ pub enum ScriptLang { Python3, Go, Bash, + Powershell, Postgresql, Bun, Mysql, @@ -47,6 +48,7 @@ impl ScriptLang { ScriptLang::Python3 => "python3", ScriptLang::Go => "go", ScriptLang::Bash => "bash", + ScriptLang::Powershell => "powershell", ScriptLang::Postgresql => "postgresql", ScriptLang::Mysql => "mysql", ScriptLang::Bigquery => "bigquery", diff --git a/backend/windmill-queue/src/jobs.rs b/backend/windmill-queue/src/jobs.rs index 6ec512cbb8..dec01c0b9b 100644 --- a/backend/windmill-queue/src/jobs.rs +++ b/backend/windmill-queue/src/jobs.rs @@ -69,6 +69,7 @@ lazy_static::lazy_static! { "python3".to_string(), "go".to_string(), "bash".to_string(), + "powershell".to_string(), "nativets".to_string(), "mysql".to_string(), "graphql".to_string(), diff --git a/backend/windmill-worker/src/worker.rs b/backend/windmill-worker/src/worker.rs index 16360c7db8..575927a818 100644 --- a/backend/windmill-worker/src/worker.rs +++ b/backend/windmill-worker/src/worker.rs @@ -356,6 +356,7 @@ pub async fn run_worker { + handle_powershell_job( + logs, + job, + db, + client, + &inner_content, + job_dir, + &shared_mount, + base_internal_url, + worker_name, + envs + ) + .await + } _ => panic!("unreachable, language is not supported: {language:#?}"), }; tracing::info!( @@ -1611,6 +1627,92 @@ async fn handle_bash_job( .unwrap_or_else(String::new))) } + +#[tracing::instrument(level = "trace", skip_all)] +async fn handle_powershell_job( + logs: &mut String, + job: &QueuedJob, + db: &sqlx::Pool, + client: &AuthedClientBackgroundTask, + content: &str, + job_dir: &str, + shared_mount: &str, + base_internal_url: &str, + worker_name: &str, + envs: HashMap, +) -> Result { + logs.push_str("\n\n--- POWERSHELL CODE EXECUTION ---\n"); + set_logs(logs, &job.id, db).await; + let hm: serde_json::Map = match job.args { + Some(Value::Object(ref hm)) => hm.clone(), + _ => serde_json::Map::new(), + }; + + let args_owned = windmill_parser_bash::parse_powershell_sig(&content)? + .args + .iter() + .map(|arg| { + (arg.name.clone(), hm.get(&arg.name) + .and_then(|v| match v { + Value::String(s) => Some(s.clone()), + _ => serde_json::to_string(v).ok(), + }) + .unwrap_or_else(String::new)) + }) + .collect::>(); + let pwsh_args = args_owned.iter().map(|(n, v)| format!("--{n} {v}")).join(" "); + + let content = content.replace('$', r"\$"); // escape powershell variables + write_file(job_dir, "main.sh", &format!("set -e\ncat > script.ps1 << EOF\n{content}\nEOF\npwsh -File script.ps1 {pwsh_args}\necho \"\"\nsleep 0.02")).await?; + let token = client.get_token().await; + let mut reserved_variables = get_reserved_variables(job, &token, db).await?; + reserved_variables.insert("RUST_LOG".to_string(), "info".to_string()); + + let child = if !*DISABLE_NSJAIL { + let _ = write_file( + job_dir, + "run.config.proto", + &NSJAIL_CONFIG_RUN_BASH_CONTENT + .replace("{JOB_DIR}", job_dir) + .replace("{CLONE_NEWUSER}", &(!*DISABLE_NUSER).to_string()) + .replace("{SHARED_MOUNT}", shared_mount), + ) + .await?; + let cmd_args = vec!["--config", "run.config.proto", "--", "/bin/bash", "main.sh"]; + Command::new(NSJAIL_PATH.as_str()) + .current_dir(job_dir) + .env_clear() + .envs(reserved_variables) + .env("PATH", PATH_ENV.as_str()) + .env("BASE_INTERNAL_URL", base_internal_url) + .args(cmd_args) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn()? + } else { + let cmd_args = vec!["main.sh"]; + Command::new("/bin/bash") + .current_dir(job_dir) + .env_clear() + .envs(envs) + .envs(reserved_variables) + .env("PATH", PATH_ENV.as_str()) + .env("BASE_INTERNAL_URL", base_internal_url) + .env("HOME", HOME_ENV.as_str()) + .args(cmd_args) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn()? + }; + handle_child(&job.id, db, logs, child, !*DISABLE_NSJAIL, worker_name, &job.workspace_id, "bash run", job.timeout).await?; + //for now bash jobs have an empty result object + Ok(serde_json::json!(logs + .lines() + .last() + .map(|x| x.to_string()) + .unwrap_or_else(String::new))) +} + fn get_common_deno_proc_envs(token: &str, base_internal_url: &str) -> HashMap { let hostname_base = BASE_URL.split("://").last().unwrap_or("localhost"); let hostname_internal = base_internal_url.split("://").last().unwrap_or("localhost"); @@ -2250,6 +2352,7 @@ async fn capture_dependency_job( ScriptLang::Snowflake => Ok("".to_owned()), ScriptLang::Graphql => Ok("".to_owned()), ScriptLang::Bash => Ok("".to_owned()), + ScriptLang::Powershell => Ok("".to_owned()), ScriptLang::Nativets => Ok("".to_owned()), } diff --git a/cli/dev.ts b/cli/dev.ts index 02c6df8795..b120f86c3d 100644 --- a/cli/dev.ts +++ b/cli/dev.ts @@ -31,7 +31,9 @@ async function dev(opts: GlobalOptions & { filter?: string }) { path.endsWith(".ts") || path.endsWith(".py") || path.endsWith(".sh") || - path.endsWith(".sql") + path.endsWith(".sql") || + path.endsWith(".gql") || + path.endsWith(".ps1") ); if (paths.length == 0) { return; @@ -56,6 +58,8 @@ async function dev(opts: GlobalOptions & { filter?: string }) { ? "go" : ext == "sh" ? "bash" + : ext == "ps1" + ? "powershell" : ext == "sql" ? splitted.length > 2 && splitted[splitted.length - 2] == "my" ? "mysql" diff --git a/cli/script.ts b/cli/script.ts index 16e8672765..723e25bf25 100644 --- a/cli/script.ts +++ b/cli/script.ts @@ -72,7 +72,10 @@ export async function handleFile( (path.endsWith(".ts") || path.endsWith(".py") || path.endsWith(".go") || - path.endsWith(".sh")) + path.endsWith(".sh") || + path.endsWith(".sql") || + path.endsWith(".gql") || + path.endsWith(".ps1")) ) { if (alreadySynced.includes(path)) { return true; @@ -181,16 +184,27 @@ export async function findContentFile(filePath: string) { filePath.replace(".script.json", ".py"), filePath.replace(".script.json", ".go"), filePath.replace(".script.json", ".sh"), - filePath.replace(".script.json", ".sql"), + filePath.replace(".script.json", "pg.sql"), + filePath.replace(".script.json", "my.sql"), + filePath.replace(".script.json", "bq.sql"), + filePath.replace(".script.json", "sf.sql"), filePath.replace(".script.json", ".fetch.ts"), + filePath.replace(".script.json", ".bun.ts"), + filePath.replace(".script.json", ".gql"), + filePath.replace(".script.json", ".ps1"), ] : [ filePath.replace(".script.yaml", ".ts"), filePath.replace(".script.yaml", ".py"), filePath.replace(".script.yaml", ".go"), filePath.replace(".script.yaml", ".sh"), - filePath.replace(".script.yaml", ".sql"), + filePath.replace(".script.yaml", "pg.sql"), + filePath.replace(".script.yaml", "bq.sql"), + filePath.replace(".script.yaml", "sf.sql"), filePath.replace(".script.yaml", ".fetch.ts"), + filePath.replace(".script.yaml", ".bun.ts"), + filePath.replace(".script.yaml", ".gql"), + filePath.replace(".script.yaml", ".ps1"), ]; const validCandidates = ( await Promise.all( @@ -220,21 +234,48 @@ export async function findContentFile(filePath: string) { export function inferContentTypeFromFilePath( contentPath: string -): "python3" | "deno" | "go" | "bash" { - let language = contentPath.substring(contentPath.lastIndexOf(".")); - if (language == ".ts") language = "deno"; - if (language == ".py") language = "python3"; - if (language == ".sh") language = "bash"; - if (language == ".go") language = "go"; - if ( - language != "python3" && - language != "deno" && - language != "go" && - language != "bash" - ) { - throw new Error("Invalid language: " + language); +): + | "python3" + | "deno" + | "bun" + | "nativets" + | "go" + | "bash" + | "powershell" + | "postgresql" + | "mysql" + | "bigquery" + | "snowflake" + | "graphql" { + if (contentPath.endsWith(".py")) { + return "python3"; + } else if (contentPath.endsWith("fetch.ts")) { + return "nativets"; + } else if (contentPath.endsWith("bun.ts")) { + return "bun"; + } else if (contentPath.endsWith(".ts")) { + return "deno"; + } else if (contentPath.endsWith(".go")) { + return "go"; + } else if (contentPath.endsWith(".my.sql")) { + return "mysql"; + } else if (contentPath.endsWith(".bq.sql")) { + return "bigquery"; + } else if (contentPath.endsWith(".sf.sql")) { + return "snowflake"; + } else if (contentPath.endsWith(".pg.sql")) { + return "postgresql"; + } else if (contentPath.endsWith(".gql")) { + return "graphql"; + } else if (contentPath.endsWith(".sh")) { + return "bash"; + } else if (contentPath.endsWith(".ps1")) { + return "powershell"; + } else { + throw new Error( + "Invalid language: " + contentPath.substring(contentPath.lastIndexOf(".")) + ); } - return language; } async function list(opts: GlobalOptions & { showArchived?: boolean }) { diff --git a/cli/sync.ts b/cli/sync.ts index 5b13aa1de1..a1340677d9 100644 --- a/cli/sync.ts +++ b/cli/sync.ts @@ -133,6 +133,7 @@ function ZipFSElement(zip: JSZip, useYaml: boolean): DynFSElement { else if (language == "deno") ext = "ts"; else if (language == "go") ext = "go"; else if (language == "bash") ext = "sh"; + else if (language == "powershell") ext = "ps1"; else if (language == "postgresql") ext = "pg.sql"; else if (language == "mysql") ext = "my.sql"; else if (language == "bigquery") ext = "bq.sql"; diff --git a/docker-compose.yml b/docker-compose.yml index 6a5672b4fd..8309407c09 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -60,7 +60,7 @@ services: - KEEP_JOB_DIR=false - METRICS_ADDR=false # To handle all tags, remove the env variable altogether. If you do so, you can remove the windmill_worker_native containers. - - WORKER_TAGS=deno,python3,go,bash,dependency,flow,hub,other,bun + - WORKER_TAGS=deno,python3,go,bash,powershell,dependency,flow,hub,other,bun # LICENSE_KEY is only needed for the enterprise edition - LICENSE_KEY=${WM_LICENSE_KEY} depends_on: diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 7d3ced26b1..769dce76d0 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -43,7 +43,7 @@ "svelte-timezone-picker": "^2.0.3", "tailwind-merge": "^1.13.2", "vscode-ws-jsonrpc": "3.0.0", - "windmill-parser-wasm": "^1.141.0", + "windmill-parser-wasm": "^1.143.0", "y-monaco": "^0.1.4", "y-websocket": "^1.5.0", "yjs": "^13.6.7" @@ -9811,9 +9811,9 @@ } }, "node_modules/windmill-parser-wasm": { - "version": "1.141.0", - "resolved": "https://registry.npmjs.org/windmill-parser-wasm/-/windmill-parser-wasm-1.141.0.tgz", - "integrity": "sha512-2U4wAyKOMa7YTcWGUSCCqhNEfI+dVF9JvlXzPneOUO9nD7zm5uXRB+xaJLHKtYB5gmzLz1cQElp/FpbJaLLZsw==" + "version": "1.143.0", + "resolved": "https://registry.npmjs.org/windmill-parser-wasm/-/windmill-parser-wasm-1.143.0.tgz", + "integrity": "sha512-sxkolDrUX/ywrE3tZpA3f9B4BONpW7PaHq+5qJBreCBHVkGnAx8iyXgyEvZhIpcTmuNhCy/osumoK/CjxGWWDw==" }, "node_modules/wordwrap": { "version": "1.0.0", @@ -16782,9 +16782,9 @@ } }, "windmill-parser-wasm": { - "version": "1.141.0", - "resolved": "https://registry.npmjs.org/windmill-parser-wasm/-/windmill-parser-wasm-1.141.0.tgz", - "integrity": "sha512-2U4wAyKOMa7YTcWGUSCCqhNEfI+dVF9JvlXzPneOUO9nD7zm5uXRB+xaJLHKtYB5gmzLz1cQElp/FpbJaLLZsw==" + "version": "1.143.0", + "resolved": "https://registry.npmjs.org/windmill-parser-wasm/-/windmill-parser-wasm-1.143.0.tgz", + "integrity": "sha512-sxkolDrUX/ywrE3tZpA3f9B4BONpW7PaHq+5qJBreCBHVkGnAx8iyXgyEvZhIpcTmuNhCy/osumoK/CjxGWWDw==" }, "wordwrap": { "version": "1.0.0", diff --git a/frontend/package.json b/frontend/package.json index a212b1e686..84a6a9ebb0 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -107,7 +107,7 @@ "svelte-timezone-picker": "^2.0.3", "tailwind-merge": "^1.13.2", "vscode-ws-jsonrpc": "3.0.0", - "windmill-parser-wasm": "^1.141.0", + "windmill-parser-wasm": "^1.143.0", "y-monaco": "^0.1.4", "y-websocket": "^1.5.0", "yjs": "^13.6.7" diff --git a/frontend/src/lib/components/DiffEditor.svelte b/frontend/src/lib/components/DiffEditor.svelte index 8816de7a00..e831a6da6b 100644 --- a/frontend/src/lib/components/DiffEditor.svelte +++ b/frontend/src/lib/components/DiffEditor.svelte @@ -40,7 +40,7 @@ export function setDiff( original: string, modified: string, - lang: 'typescript' | 'python' | 'go' | 'shell' | 'sql' | 'graphql' | 'javascript' + lang: 'typescript' | 'python' | 'go' | 'shell' | 'sql' | 'graphql' | 'javascript' | 'powershell' ): void { diffEditor?.setModel({ original: meditor.createModel(original, lang), diff --git a/frontend/src/lib/components/Editor.svelte b/frontend/src/lib/components/Editor.svelte index 5420a87a60..b6740949a1 100644 --- a/frontend/src/lib/components/Editor.svelte +++ b/frontend/src/lib/components/Editor.svelte @@ -22,6 +22,7 @@ import 'monaco-editor/esm/vs/basic-languages/typescript/typescript.contribution' import 'monaco-editor/esm/vs/basic-languages/sql/sql.contribution' import 'monaco-editor/esm/vs/basic-languages/graphql/graphql.contribution' + import 'monaco-editor/esm/vs/basic-languages/powershell/powershell.contribution' import 'monaco-editor/esm/vs/language/typescript/monaco.contribution' import { MonacoLanguageClient, initServices } from 'monaco-languageclient' import { toSocket, WebSocketMessageReader, WebSocketMessageWriter } from 'vscode-ws-jsonrpc' @@ -48,7 +49,7 @@ let divEl: HTMLDivElement | null = null let editor: meditor.IStandaloneCodeEditor - export let lang: 'typescript' | 'python' | 'go' | 'shell' | 'sql' | 'graphql' + export let lang: 'typescript' | 'python' | 'go' | 'shell' | 'sql' | 'graphql' | 'powershell' export let deno: boolean export let code: string = '' export let cmdEnterAction: (() => void) | undefined = undefined diff --git a/frontend/src/lib/components/ScriptBuilder.svelte b/frontend/src/lib/components/ScriptBuilder.svelte index e5cf3a942d..8037e13565 100644 --- a/frontend/src/lib/components/ScriptBuilder.svelte +++ b/frontend/src/lib/components/ScriptBuilder.svelte @@ -71,6 +71,7 @@ langs.push(['BigQuery', Script.language.BIGQUERY]) langs.push(['Snowflake', Script.language.SNOWFLAKE]) langs.push(['GraphQL', Script.language.GRAPHQL]) + langs.push(['PowerShell', Script.language.POWERSHELL]) if (SCRIPT_SHOW_GO) { langs.push(['Go', Script.language.GO]) } @@ -365,22 +366,6 @@ > Docker -