From 2fe623cf6b0a14bea09f295e11648c8f78cd1d09 Mon Sep 17 00:00:00 2001 From: HugoCasa Date: Fri, 10 Nov 2023 11:16:13 +0100 Subject: [PATCH] feat: add sql server (#2604) * feat: add sql server * feat: mssql test, db schema, AI * chore: update to latest parser * fix: clean mssql executor --- backend/Cargo.lock | 140 +++++++++++ backend/Cargo.toml | 1 + .../20231109101743_add_mssql.down.sql | 1 + .../20231109101743_add_mssql.up.sql | 4 + .../parsers/windmill-parser-sql/src/lib.rs | 57 +++++ .../windmill-parser-wasm/pkg/package.json | 2 +- .../pkg/windmill_parser_wasm.d.ts | 6 + .../pkg/windmill_parser_wasm.js | 101 +++++--- .../pkg/windmill_parser_wasm_bg.wasm | Bin 4837570 -> 4790612 bytes .../pkg/windmill_parser_wasm_bg.wasm.d.ts | 1 + .../parsers/windmill-parser-wasm/src/lib.rs | 5 + backend/windmill-api/openapi.yaml | 5 + backend/windmill-api/src/workspaces.rs | 1 + backend/windmill-common/src/scripts.rs | 2 + backend/windmill-common/src/worker.rs | 1 + backend/windmill-worker/Cargo.toml | 4 +- backend/windmill-worker/src/lib.rs | 2 + backend/windmill-worker/src/mssql_executor.rs | 236 ++++++++++++++++++ backend/windmill-worker/src/worker.rs | 23 +- cli/dev.ts | 2 + cli/script.ts | 3 + cli/sync.ts | 1 + frontend/package-lock.json | 14 +- frontend/package.json | 2 +- frontend/src/lib/components/AppConnect.svelte | 9 +- .../lib/components/DBSchemaExplorer.svelte | 54 +++- .../src/lib/components/ScriptBuilder.svelte | 3 +- .../src/lib/components/TestConnection.svelte | 5 + .../src/lib/components/WorkspaceGroup.svelte | 10 +- .../EmptyInlineScript.svelte | 1 + .../common/languageIcons/LanguageIcon.svelte | 5 +- .../lib/components/copilot/ScriptGen.svelte | 11 +- frontend/src/lib/components/copilot/lib.ts | 5 +- .../lib/components/copilot/prompts/edit.yaml | 14 +- .../components/copilot/prompts/editPrompt.ts | 11 +- .../lib/components/copilot/prompts/fix.yaml | 11 + .../components/copilot/prompts/fixPrompt.ts | 3 + .../lib/components/copilot/prompts/gen.yaml | 3 + .../components/copilot/prompts/genPrompt.ts | 3 + .../flows/content/FlowInputs.svelte | 14 ++ .../flows/pickers/FlowScriptPicker.svelte | 2 +- .../components/icons/MSSqlServerIcon.svelte | 65 +++++ frontend/src/lib/components/icons/index.ts | 2 + frontend/src/lib/infer.ts | 9 +- frontend/src/lib/script_helpers.ts | 11 +- frontend/src/lib/scripts.ts | 2 + frontend/src/lib/stores.ts | 3 +- .../(root)/(logged)/run/[...run]/+page.svelte | 2 +- openflow.openapi.yaml | 1 + 49 files changed, 792 insertions(+), 81 deletions(-) create mode 100644 backend/migrations/20231109101743_add_mssql.down.sql create mode 100644 backend/migrations/20231109101743_add_mssql.up.sql create mode 100644 backend/windmill-worker/src/mssql_executor.rs create mode 100644 frontend/src/lib/components/icons/MSSqlServerIcon.svelte diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 5d68ce437c..b76088fa89 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -434,6 +434,19 @@ dependencies = [ "tokio", ] +[[package]] +name = "asynchronous-codec" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4057f2c32adbb2fc158e22fb38433c8e9bbf76b75a4732c7c0cbaf695fb65568" +dependencies = [ + "bytes", + "futures-sink", + "futures-util", + "memchr", + "pin-project-lite", +] + [[package]] name = "atoi" version = "1.0.0" @@ -1260,6 +1273,12 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "connection-string" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "510ca239cf13b7f8d16a2b48f263de7b4f8c566f0af58d901031473c76afb1e3" + [[package]] name = "console" version = "0.15.7" @@ -2055,6 +2074,70 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" +[[package]] +name = "encoding" +version = "0.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec" +dependencies = [ + "encoding-index-japanese", + "encoding-index-korean", + "encoding-index-simpchinese", + "encoding-index-singlebyte", + "encoding-index-tradchinese", +] + +[[package]] +name = "encoding-index-japanese" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91" +dependencies = [ + "encoding_index_tests", +] + +[[package]] +name = "encoding-index-korean" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81" +dependencies = [ + "encoding_index_tests", +] + +[[package]] +name = "encoding-index-simpchinese" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7" +dependencies = [ + "encoding_index_tests", +] + +[[package]] +name = "encoding-index-singlebyte" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a" +dependencies = [ + "encoding_index_tests", +] + +[[package]] +name = "encoding-index-tradchinese" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18" +dependencies = [ + "encoding_index_tests", +] + +[[package]] +name = "encoding_index_tests" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" + [[package]] name = "encoding_rs" version = "0.8.31" @@ -2064,6 +2147,26 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "enumflags2" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5998b4f30320c9d93aed72f63af821bfdac50465b75428fce77b48ec482c3939" +dependencies = [ + "enumflags2_derive", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f95e2801cd355d4a1a3e3953ce6ee5ae9603a5c833455343a8bfe3f44d418246" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -4334,6 +4437,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" +[[package]] +name = "pretty-hex" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6fa0831dd7cc608c38a5e323422a0077678fa5744aa2be4ad91c4ece8eec8d5" + [[package]] name = "prettyplease" version = "0.1.25" @@ -6792,6 +6901,34 @@ dependencies = [ "once_cell", ] +[[package]] +name = "tiberius" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc6e2bf3e4b5be181a2a2ceff4b9b12e2684010d436a6958bd564fbc8094d44d" +dependencies = [ + "async-trait", + "asynchronous-codec", + "byteorder", + "bytes", + "chrono", + "connection-string", + "encoding", + "enumflags2", + "futures-util", + "num-traits", + "once_cell", + "pin-project-lite", + "pretty-hex", + "rustls-native-certs", + "rustls-pemfile", + "thiserror", + "tokio-rustls 0.23.4", + "tokio-util", + "tracing", + "uuid 1.5.0", +] + [[package]] name = "tiger" version = "0.1.0" @@ -7049,6 +7186,7 @@ checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" dependencies = [ "bytes", "futures-core", + "futures-io", "futures-sink", "pin-project-lite", "tokio", @@ -8284,8 +8422,10 @@ dependencies = [ "serde_json", "sha2 0.10.8", "sqlx 0.7.2", + "tiberius", "tokio", "tokio-postgres", + "tokio-util", "tracing", "urlencoding", "uuid 1.5.0", diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 7b2c98ba1c..448462ba16 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -203,3 +203,4 @@ tokenizers = "0.14.1" candle-core = "0.3.0" candle-transformers = "0.3.0" candle-nn = "0.3.0" +tiberius = { version = "0.12.2", default-features = false, features = ["rustls", "tds73", "chrono"] } \ No newline at end of file diff --git a/backend/migrations/20231109101743_add_mssql.down.sql b/backend/migrations/20231109101743_add_mssql.down.sql new file mode 100644 index 0000000000..d2f607c5b8 --- /dev/null +++ b/backend/migrations/20231109101743_add_mssql.down.sql @@ -0,0 +1 @@ +-- Add down migration script here diff --git a/backend/migrations/20231109101743_add_mssql.up.sql b/backend/migrations/20231109101743_add_mssql.up.sql new file mode 100644 index 0000000000..e933699070 --- /dev/null +++ b/backend/migrations/20231109101743_add_mssql.up.sql @@ -0,0 +1,4 @@ +-- Add up migration script here +ALTER TYPE SCRIPT_LANG ADD VALUE IF NOT EXISTS 'mssql'; +-- Add up migration script here +UPDATE config set config = '{"worker_tags": ["nativets", "postgresql", "mysql", "graphql", "snowflake", "bigquery", "mssql"]}'::jsonb where name = 'worker__native' and config = '{"worker_tags": ["nativets", "postgresql", "mysql", "graphql", "snowflake", "bigquery"]}'::jsonb ; \ No newline at end of file diff --git a/backend/parsers/windmill-parser-sql/src/lib.rs b/backend/parsers/windmill-parser-sql/src/lib.rs index 44f005a7db..9e24c33c0b 100644 --- a/backend/parsers/windmill-parser-sql/src/lib.rs +++ b/backend/parsers/windmill-parser-sql/src/lib.rs @@ -47,6 +47,16 @@ pub fn parse_snowflake_sig(code: &str) -> anyhow::Result { } } +pub fn parse_mssql_sig(code: &str) -> anyhow::Result { + let parsed = parse_mssql_file(&code)?; + if let Some(x) = parsed { + let args = x; + Ok(MainArgSignature { star_args: false, star_kwargs: false, args }) + } else { + Err(anyhow!("Error parsing sql".to_string())) + } +} + lazy_static::lazy_static! { static ref RE_CODE_PGSQL: Regex = Regex::new(r#"(?m)\$(\d+)(?:::(\w+(?:\[\])?))?"#).unwrap(); @@ -60,6 +70,9 @@ lazy_static::lazy_static! { static ref RE_ARG_SNOWFLAKE: Regex = Regex::new(r#"(?m)^-- \? (\w+) \((\w+)\)(?: ?\= ?(.+))? *[\r\n$]"#).unwrap(); + + static ref RE_ARG_MSSQL: Regex = Regex::new(r#"(?m)^-- @(?:P|p)\d+ (\w+) \((\w+)\)(?: ?\= ?(.+))? *[\r\n$]"#).unwrap(); + } fn parse_mysql_file(code: &str) -> anyhow::Result>> { @@ -200,6 +213,36 @@ fn parse_snowflake_file(code: &str) -> anyhow::Result>> { Ok(Some(args)) } +fn parse_mssql_file(code: &str) -> anyhow::Result>> { + let mut args: Vec = vec![]; + + for cap in RE_ARG_MSSQL.captures_iter(code) { + let name = cap.get(1).map(|x| x.as_str().to_string()).unwrap(); + let typ = cap + .get(2) + .map(|x| x.as_str().to_string().to_lowercase()) + .unwrap(); + let default = cap.get(3).map(|x| x.as_str().to_string()); + let has_default = default.is_some(); + let parsed_typ = parse_mssql_typ(typ.as_str()); + + let parsed_default = default.and_then(|x| match parsed_typ { + Typ::Int => x.parse::().ok().map(|x| json!(x)), + Typ::Float => x.parse::().ok().map(|x| json!(x)), + _ => Some(json!(x)), + }); + args.push(Arg { + name, + typ: parsed_typ, + default: parsed_default, + otyp: Some(typ), + has_default, + }); + } + + Ok(Some(args)) +} + pub fn parse_mysql_typ(typ: &str) -> Typ { match typ { "varchar" | "char" | "binary" | "varbinary" | "blob" | "text" | "enum" | "set" => { @@ -269,6 +312,20 @@ pub fn parse_snowflake_typ(typ: &str) -> Typ { } } +pub fn parse_mssql_typ(typ: &str) -> Typ { + match typ { + "char" | "text" | "varchar" | "nchar" | "nvarchar" | "ntext" => Typ::Str(None), + "binary" | "varbinary" | "image" => Typ::Bytes, + "date" | "datetime2" | "datetime" | "datetimeoffset" | "smalldatetime" | "time" => { + Typ::Datetime + } + "bigint" | "int" | "tinyint" | "smallint" => Typ::Int, + "float" | "real" | "numeric" | "decimal" => Typ::Float, + "bit" => Typ::Bool, + _ => Typ::Str(None), + } +} + #[cfg(test)] mod tests { diff --git a/backend/parsers/windmill-parser-wasm/pkg/package.json b/backend/parsers/windmill-parser-wasm/pkg/package.json index b2ada6eca7..d48f357e2f 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.190.0", + "version": "1.202.1", "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 5c8a98c76f..987dd381cc 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 @@ -54,6 +54,11 @@ export function parse_snowflake(code: string): string; * @param {string} code * @returns {string} */ +export function parse_mssql(code: string): string; +/** +* @param {string} code +* @returns {string} +*/ export function parse_graphql(code: string): string; export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module; @@ -70,6 +75,7 @@ export interface InitOutput { readonly parse_mysql: (a: number, b: number, c: number) => void; readonly parse_bigquery: (a: number, b: number, c: number) => void; readonly parse_snowflake: (a: number, b: number, c: number) => void; + readonly parse_mssql: (a: number, b: number, c: number) => void; readonly parse_graphql: (a: number, b: number, c: number) => void; readonly __wbindgen_malloc: (a: number, b: number) => number; readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number; 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 cc0c9b8310..b5949c2113 100644 --- a/backend/parsers/windmill-parser-wasm/pkg/windmill_parser_wasm.js +++ b/backend/parsers/windmill-parser-wasm/pkg/windmill_parser_wasm.js @@ -97,15 +97,6 @@ function getInt32Memory0() { return cachedInt32Memory0; } -function addHeapObject(obj) { - if (heap_next === heap.length) heap.push(heap.length + 1); - const idx = heap_next; - heap_next = heap[idx]; - - heap[idx] = obj; - return idx; -} - const cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } ); if (typeof TextDecoder !== 'undefined') { cachedTextDecoder.decode(); }; @@ -115,6 +106,15 @@ function getStringFromWasm0(ptr, len) { return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len)); } +function addHeapObject(obj) { + if (heap_next === heap.length) heap.push(heap.length + 1); + const idx = heap_next; + heap_next = heap[idx]; + + heap[idx] = obj; + return idx; +} + let cachedFloat64Memory0 = null; function getFloat64Memory0() { @@ -427,6 +427,29 @@ export function parse_snowflake(code) { } } +/** +* @param {string} code +* @returns {string} +*/ +export function parse_mssql(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_mssql(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} @@ -503,6 +526,14 @@ function __wbg_get_imports() { getInt32Memory0()[arg0 / 4 + 1] = len1; getInt32Memory0()[arg0 / 4 + 0] = ptr1; }; + imports.wbg.__wbg_eval_f742bccbdcf34b02 = function(arg0, arg1) { + const ret = eval(getStringFromWasm0(arg0, arg1)); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_error_new = function(arg0, arg1) { + const ret = new Error(getStringFromWasm0(arg0, arg1)); + return addHeapObject(ret); + }; imports.wbg.__wbindgen_boolean_get = function(arg0) { const v = getObject(arg0); const ret = typeof(v) === 'boolean' ? (v ? 1 : 0) : 2; @@ -520,14 +551,6 @@ function __wbg_get_imports() { const ret = getObject(arg0) === getObject(arg1); return ret; }; - imports.wbg.__wbindgen_bigint_from_u64 = function(arg0) { - const ret = BigInt.asUintN(64, arg0); - return addHeapObject(ret); - }; - imports.wbg.__wbindgen_error_new = function(arg0, arg1) { - const ret = new Error(getStringFromWasm0(arg0, arg1)); - return addHeapObject(ret); - }; imports.wbg.__wbindgen_number_get = function(arg0, arg1) { const obj = getObject(arg1); const ret = typeof(obj) === 'number' ? obj : undefined; @@ -543,19 +566,19 @@ function __wbg_get_imports() { const ret = getObject(arg0) in getObject(arg1); return ret; }; - imports.wbg.__wbg_eval_d090ffdbb4b6658b = function(arg0, arg1) { - const ret = eval(getStringFromWasm0(arg0, arg1)); + imports.wbg.__wbindgen_bigint_from_u64 = function(arg0) { + const ret = BigInt.asUintN(64, arg0); return addHeapObject(ret); }; imports.wbg.__wbindgen_jsval_loose_eq = function(arg0, arg1) { const ret = getObject(arg0) == getObject(arg1); return ret; }; - imports.wbg.__wbg_get_44be0491f933a435 = function(arg0, arg1) { + imports.wbg.__wbg_get_4a9aa5157afeb382 = function(arg0, arg1) { const ret = getObject(arg0)[arg1 >>> 0]; return addHeapObject(ret); }; - imports.wbg.__wbg_length_fff51ee6522a1a18 = function(arg0) { + imports.wbg.__wbg_length_cace2e0b3ddc0502 = function(arg0) { const ret = getObject(arg0).length; return ret; }; @@ -563,76 +586,76 @@ function __wbg_get_imports() { const ret = typeof(getObject(arg0)) === 'function'; return ret; }; - imports.wbg.__wbg_next_526fc47e980da008 = function(arg0) { + imports.wbg.__wbg_next_15da6a3df9290720 = function(arg0) { const ret = getObject(arg0).next; return addHeapObject(ret); }; - imports.wbg.__wbg_next_ddb3312ca1c4e32a = function() { return handleError(function (arg0) { + imports.wbg.__wbg_next_1989a20442400aaa = function() { return handleError(function (arg0) { const ret = getObject(arg0).next(); return addHeapObject(ret); }, arguments) }; - imports.wbg.__wbg_done_5c1f01fb660d73b5 = function(arg0) { + imports.wbg.__wbg_done_bc26bf4ada718266 = function(arg0) { const ret = getObject(arg0).done; return ret; }; - imports.wbg.__wbg_value_1695675138684bd5 = function(arg0) { + imports.wbg.__wbg_value_0570714ff7d75f35 = function(arg0) { const ret = getObject(arg0).value; return addHeapObject(ret); }; - imports.wbg.__wbg_iterator_97f0c81209c6c35a = function() { + imports.wbg.__wbg_iterator_7ee1a391d310f8e4 = function() { const ret = Symbol.iterator; return addHeapObject(ret); }; - imports.wbg.__wbg_get_97b561fb56f034b5 = function() { return handleError(function (arg0, arg1) { + imports.wbg.__wbg_get_2aff440840bb6202 = function() { return handleError(function (arg0, arg1) { const ret = Reflect.get(getObject(arg0), getObject(arg1)); return addHeapObject(ret); }, arguments) }; - imports.wbg.__wbg_call_cb65541d95d71282 = function() { return handleError(function (arg0, arg1) { + imports.wbg.__wbg_call_669127b9d730c650 = function() { return handleError(function (arg0, arg1) { const ret = getObject(arg0).call(getObject(arg1)); return addHeapObject(ret); }, arguments) }; - imports.wbg.__wbg_isArray_4c24b343cb13cfb1 = function(arg0) { + imports.wbg.__wbg_isArray_38525be7442aa21e = function(arg0) { const ret = Array.isArray(getObject(arg0)); return ret; }; - imports.wbg.__wbg_instanceof_ArrayBuffer_39ac22089b74fddb = function(arg0) { + imports.wbg.__wbg_instanceof_ArrayBuffer_c7cc317e5c29cc0d = function(arg0) { let result; try { result = getObject(arg0) instanceof ArrayBuffer; - } catch { + } catch (_) { result = false; } const ret = result; return ret; }; - imports.wbg.__wbg_isSafeInteger_bb8e18dd21c97288 = function(arg0) { + imports.wbg.__wbg_isSafeInteger_c38b0a16d0c7cef7 = function(arg0) { const ret = Number.isSafeInteger(getObject(arg0)); return ret; }; - imports.wbg.__wbg_entries_e51f29c7bba0c054 = function(arg0) { + imports.wbg.__wbg_entries_6d727b73ee02b7ce = function(arg0) { const ret = Object.entries(getObject(arg0)); return addHeapObject(ret); }; - imports.wbg.__wbg_buffer_085ec1f694018c4f = function(arg0) { + imports.wbg.__wbg_buffer_344d9b41efe96da7 = function(arg0) { const ret = getObject(arg0).buffer; return addHeapObject(ret); }; - imports.wbg.__wbg_new_8125e318e6245eed = function(arg0) { + imports.wbg.__wbg_new_d8a000788389a31e = function(arg0) { const ret = new Uint8Array(getObject(arg0)); return addHeapObject(ret); }; - imports.wbg.__wbg_set_5cf90238115182c3 = function(arg0, arg1, arg2) { + imports.wbg.__wbg_set_dcfd613a3420f908 = function(arg0, arg1, arg2) { getObject(arg0).set(getObject(arg1), arg2 >>> 0); }; - imports.wbg.__wbg_length_72e2208bbc0efc61 = function(arg0) { + imports.wbg.__wbg_length_a5587d6cd79ab197 = function(arg0) { const ret = getObject(arg0).length; return ret; }; - imports.wbg.__wbg_instanceof_Uint8Array_d8d9cb2b8e8ac1d4 = function(arg0) { + imports.wbg.__wbg_instanceof_Uint8Array_19e6f142a5e7e1e1 = function(arg0) { let result; try { result = getObject(arg0) instanceof Uint8Array; - } catch { + } catch (_) { result = false; } const ret = result; 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 3b14273e74ea9b6ba43c2e72877bbd6dbd03f441..3b96f0069d1c1efe882b8588f77e00698bec751f 100644 GIT binary patch literal 4790612 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