fix: track dollar-quoted strings in SQL block splitter (#8891)

* fix: track dollar-quoted strings in SQL block splitter

Queries like `CREATE FUNCTION ... AS $$ ... ; ... $$ LANGUAGE plpgsql;`
were being shredded on every `;` inside the function body because the
SQL splitter's state machine didn't recognize PostgreSQL dollar-quoted
strings. Add an `InDollarQuote(tag)` state so `$$ ... $$` and
`$tag$ ... $tag$` regions are treated as a single quoted span.

Opt-in via a new `track_dollar_quotes` flag on `parse_sql_blocks`;
enabled for PostgreSQL and DuckDB, disabled for MySQL/Oracle/BigQuery/
Snowflake which don't support the syntax.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix: make windmill-parser-wasm a self-contained workspace

The wasm parser crate is excluded from the backend workspace (its
nightly-only `cargo-features = ["panic-immediate-abort"]` would break
stable cargo on the whole workspace), but its manifest still used
`.workspace = true` inheritance — which fails with "failed to find a
workspace root" once the parent no longer considers it a member.

Declare the crate as its own workspace by adding `[workspace]`,
`[workspace.package]`, and `[workspace.dependencies]` tables. Mirror
the relevant entries from the parent `backend/Cargo.toml` (same
version specs, same path targets) so resolution stays byte-identical
to what the parent would have produced.

Also:
- Teach `.github/change-versions.sh` (+ mac variant) to update this
  crate's own `Cargo.toml` version and bulk-bump the `windmill-*`
  entries in its `Cargo.lock` on each release.
- Bump the frontend's pinned `windmill-parser-wasm-regex` to 1.688.0
  to match the freshly-built package, and refresh `package-lock.json`.
- Regenerate the wasm crate's `Cargo.lock` from scratch (first build
  under the new workspace re-resolves the full graph; target-gated
  deps from sibling crates like `windmill-parser-py-imports` are
  now recorded in the lockfile but not compiled when targeting
  wasm32).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
hugocasa
2026-04-21 17:07:01 +00:00
committed by GitHub
co-authored by Claude Opus 4.7
parent 2d4fadb590
commit 53badf1a8c
13 changed files with 2732 additions and 154 deletions
+6
View File
@@ -20,4 +20,10 @@ sed -i '' -e "/^wmill =/s/= .*/= \">=$VERSION\"/" ${root_dirpath}/lsp/Pipfile
sed -i '' -E "s/name = \"windmill\"\nversion = \"[^\"]*\"\\n(.*)/name = \"windmill\"\nversion = \"$VERSION\"\\n\\1/" ${root_dirpath}/backend/Cargo.lock
# windmill-parser-wasm is its own workspace (excluded from the backend workspace
# because of nightly-only cargo-features), so its version lives in
# [workspace.package] and its Cargo.lock is not regenerated by the backend step.
sed -i '' -e "/^version =/s/= .*/= \"$VERSION\"/" ${root_dirpath}/backend/parsers/windmill-parser-wasm/Cargo.toml
sed -i '' -E "s/(name = \"windmill[^\"]*\"\nversion = )\"[^\"]*\"/\\1\"$VERSION\"/g" ${root_dirpath}/backend/parsers/windmill-parser-wasm/Cargo.lock
cd ${root_dirpath}/frontend && npm i --package-lock-only
+6
View File
@@ -21,4 +21,10 @@ sed -i -e "/^wmill =/s/= .*/= \">=$VERSION\"/" ${root_dirpath}/lsp/Pipfile
sed -i -zE "s/name = \"windmill\"\nversion = \"[^\"]*\"\\n(.*)/name = \"windmill\"\nversion = \"$VERSION\"\\n\\1/" ${root_dirpath}/backend/Cargo.lock
# windmill-parser-wasm is its own workspace (excluded from the backend workspace
# because of nightly-only cargo-features), so its version lives in
# [workspace.package] and its Cargo.lock is not regenerated by the backend step.
sed -i -e "/^version =/s/= .*/= \"$VERSION\"/" ${root_dirpath}/backend/parsers/windmill-parser-wasm/Cargo.toml
sed -i -zE "s/(name = \"windmill[^\"]*\"\nversion = )\"[^\"]*\"/\\1\"$VERSION\"/g" ${root_dirpath}/backend/parsers/windmill-parser-wasm/Cargo.lock
cd ${root_dirpath}/frontend && npm i --package-lock-only --ignore-scripts
+156 -20
View File
@@ -15,7 +15,9 @@ use std::{
iter::Peekable,
str::CharIndices,
};
pub use windmill_parser::{s3_mode_extension, Arg, MainArgSignature, ObjectType, S3ModeFormat, Typ};
pub use windmill_parser::{
s3_mode_extension, Arg, MainArgSignature, ObjectType, S3ModeFormat, Typ,
};
pub const SANITIZED_ENUM_STR: &str = "__sanitized_enum__";
pub const SANITIZED_RAW_STRING_STR: &str = "__sanitized_raw_string__";
@@ -191,12 +193,13 @@ pub fn parse_s3_mode(code: &str) -> anyhow::Result<Option<S3ModeArgs>> {
Ok(Some(S3ModeArgs { prefix, storage, format }))
}
pub fn parse_sql_blocks(code: &str) -> Vec<&str> {
pub fn parse_sql_blocks(code: &str, track_dollar_quotes: bool) -> Vec<&str> {
let mut blocks = vec![];
let mut last_idx = 0;
run_on_sql_statement_matches(
code,
track_dollar_quotes,
|char, _| char == ';',
|idx, _| {
blocks.push(&code[last_idx..=idx]);
@@ -395,6 +398,44 @@ enum ParserState {
InDoubleQuote,
InSingleLineComment,
InMultiLineComment,
// Stores the full `$tag$` delimiter (including both `$`s). On re-encountering
// the same delimiter we return to `Normal`. An empty tag yields `$$`.
InDollarQuote(String),
}
// If `code[idx..]` starts with a PostgreSQL dollar-quote delimiter (`$$` or
// `$tag$`), returns the delimiter's byte length. The tag follows identifier
// rules (first char letter/underscore, subsequent letters/digits/underscores),
// which naturally rejects placeholder syntax like `$1` or `$2::int`.
fn parse_dollar_quote_delimiter(code: &str, idx: usize) -> Option<usize> {
let bytes = code.as_bytes();
if bytes.get(idx) != Some(&b'$') {
return None;
}
let mut i = idx + 1;
while i < bytes.len() {
let b = bytes[i];
if b == b'$' {
return Some(i + 1 - idx);
}
let is_first = i == idx + 1;
let ok = if is_first {
b.is_ascii_alphabetic() || b == b'_'
} else {
b.is_ascii_alphanumeric() || b == b'_'
};
if !ok {
return None;
}
i += 1;
}
None
}
fn advance_past<I: Iterator<Item = (usize, char)>>(chars: &mut Peekable<I>, target: usize) {
while chars.peek().map_or(false, |&(i, _)| i < target) {
chars.next();
}
}
fn run_on_sql_statement_matches<
@@ -402,6 +443,7 @@ fn run_on_sql_statement_matches<
F2: FnMut(usize, &mut Peekable<CharIndices>) -> (),
>(
code: &str,
track_dollar_quotes: bool,
mut cond: F1,
mut case: F2,
) {
@@ -425,6 +467,16 @@ fn run_on_sql_statement_matches<
{
state = ParserState::InMultiLineComment;
}
(ParserState::Normal, '$') if track_dollar_quotes => {
if let Some(delim_len) = parse_dollar_quote_delimiter(code, idx) {
let delim_end = idx + delim_len;
let delim = code[idx..delim_end].to_string();
advance_past(&mut chars, delim_end);
state = ParserState::InDollarQuote(delim);
} else if cond(char, &mut chars) {
case(idx, &mut chars);
}
}
(ParserState::Normal, _) if cond(char, &mut chars) => {
case(idx, &mut chars);
}
@@ -453,6 +505,13 @@ fn run_on_sql_statement_matches<
{
state = ParserState::Normal;
}
(ParserState::InDollarQuote(delim), '$') => {
if code[idx..].starts_with(delim.as_str()) {
let target = idx + delim.len();
advance_past(&mut chars, target);
state = ParserState::Normal;
}
}
_ => {}
}
}
@@ -462,6 +521,7 @@ pub fn parse_pg_statement_arg_indices(code: &str) -> HashSet<i32> {
let mut arg_indices = HashSet::new();
run_on_sql_statement_matches(
code,
true,
|char, chars| {
char == '$'
&& chars
@@ -631,6 +691,7 @@ pub fn parse_sql_statement_named_params(code: &str, prefix: char) -> HashSet<Str
let mut arg_names = HashSet::new();
run_on_sql_statement_matches(
code,
false,
|char, chars| {
char == prefix
&& chars
@@ -952,7 +1013,7 @@ SELECT * FROM table WHERE token=$1::TEXT AND image=$2::BIGINT
],
auto_kind: None,
has_preprocessor: None,
..Default::default()
..Default::default()
}
);
@@ -1002,7 +1063,7 @@ SELECT $2::TEXT;
],
auto_kind: None,
has_preprocessor: None,
..Default::default()
..Default::default()
}
);
@@ -1019,7 +1080,7 @@ SELECT '--', ';' $3::TEXT, $1::BIGINT;
-- ;
SELECT $2::TEXT;
"#;
assert_eq!(parse_sql_blocks(code).len(), 2);
assert_eq!(parse_sql_blocks(code, true).len(), 2);
Ok(())
}
@@ -1035,7 +1096,7 @@ SELECT '--', ';' $3::TEXT, $1::BIGINT;
SELECT $2::TEXT
"#;
assert_eq!(
parse_sql_blocks(code),
parse_sql_blocks(code, true),
vec![
r#"
-- $1 param1
@@ -1062,7 +1123,7 @@ SELECT '--', ';' $3::TEXT, $1::BIGINT;
-- hey
"#;
assert_eq!(
parse_sql_blocks(code),
parse_sql_blocks(code, true),
vec![
r#"
-- $1 param1
@@ -1084,7 +1145,7 @@ SELECT '--', ';' $3::TEXT, $1::BIGINT;"#,
SELECT '--', ';' $3::TEXT, $1::BIGINT
"#;
assert_eq!(
parse_sql_blocks(code),
parse_sql_blocks(code, true),
vec![
r#"
-- $1 param1
@@ -1098,6 +1159,81 @@ SELECT '--', ';' $3::TEXT, $1::BIGINT
Ok(())
}
#[test]
fn test_parse_sql_blocks_dollar_quoted_function() -> anyhow::Result<()> {
let code = r#"CREATE OR REPLACE FUNCTION track_status_change()
RETURNS TRIGGER AS $$
BEGIN
IF OLD.status IS DISTINCT FROM NEW.status THEN
INSERT INTO use_case_card_history (use_case_id, old_status, new_status)
VALUES (NEW.id, OLD.status, NEW.status);
END IF;
NEW.updated_at := NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;"#;
assert_eq!(parse_sql_blocks(code, true), vec![code]);
Ok(())
}
#[test]
fn test_parse_sql_blocks_dollar_quoted_tagged() -> anyhow::Result<()> {
let code = r#"CREATE FUNCTION f() RETURNS int AS $body$ BEGIN RETURN 1; END; $body$ LANGUAGE plpgsql;
SELECT 1;"#;
let blocks = parse_sql_blocks(code, true);
assert_eq!(blocks.len(), 2);
assert!(blocks[0].contains("$body$"));
assert!(blocks[0].contains("END;"));
assert_eq!(blocks[1], "\nSELECT 1;");
Ok(())
}
#[test]
fn test_parse_sql_blocks_dollar_quote_does_not_match_placeholder() -> anyhow::Result<()> {
// `$1`, `$2` must still be treated as placeholders, not dollar-quote openers.
let code = r#"SELECT $1::TEXT, $2::BIGINT;
SELECT $1 FROM t;"#;
assert_eq!(parse_sql_blocks(code, true).len(), 2);
Ok(())
}
#[test]
fn test_parse_pg_statement_arg_indices_inside_dollar_quote() -> anyhow::Result<()> {
// `$1` inside a dollar-quoted body is part of the string literal, not a parameter.
let code = r#"CREATE FUNCTION f() RETURNS int AS $$ SELECT $1 $$ LANGUAGE sql;
SELECT $2;"#;
let indices = parse_pg_statement_arg_indices(code);
assert!(!indices.contains(&1), "$1 inside $$...$$ should be ignored");
assert!(
indices.contains(&2),
"$2 outside dollar-quote should be collected"
);
Ok(())
}
#[test]
fn test_parse_sql_blocks_non_pg_ignores_dollar_quotes() -> anyhow::Result<()> {
// Non-Postgres dialects (MySQL/Oracle/BigQuery/Snowflake) pass `false`,
// so a bare `$tag$...;...$tag$` sequence must still split on `;`.
let code = "SELECT $foo$; SELECT 1;";
assert_eq!(parse_sql_blocks(code, false).len(), 2);
// With tracking on (PG), `$foo$` opens a dollar-quote that is never closed,
// so the whole thing becomes a single block.
assert_eq!(parse_sql_blocks(code, true).len(), 1);
Ok(())
}
#[test]
fn test_parse_sql_blocks_nested_tag_mismatch() -> anyhow::Result<()> {
// An inner tag that doesn't match the outer one does not terminate the outer quote.
let code = r#"CREATE FUNCTION f() RETURNS int AS $outer$ SELECT $inner$ x; y $inner$ ; $outer$ LANGUAGE sql;
SELECT 1;"#;
let blocks = parse_sql_blocks(code, true);
assert_eq!(blocks.len(), 2);
assert!(blocks[0].contains("$outer$ LANGUAGE sql;"));
Ok(())
}
#[test]
fn test_parse_mysql_positional_sig() -> anyhow::Result<()> {
let code = r#"
@@ -1130,7 +1266,7 @@ SELECT ?, ?;
],
auto_kind: None,
has_preprocessor: None,
..Default::default()
..Default::default()
}
);
@@ -1179,7 +1315,7 @@ SELECT :param2;
],
auto_kind: None,
has_preprocessor: None,
..Default::default()
..Default::default()
}
);
@@ -1220,7 +1356,7 @@ SELECT @token;
],
auto_kind: None,
has_preprocessor: None,
..Default::default()
..Default::default()
}
);
@@ -1269,7 +1405,7 @@ SELECT ?;
],
auto_kind: None,
has_preprocessor: None,
..Default::default()
..Default::default()
}
);
@@ -1318,7 +1454,7 @@ SELECT @P2;
],
auto_kind: None,
has_preprocessor: None,
..Default::default()
..Default::default()
}
);
@@ -1368,7 +1504,7 @@ SELECT * FROM table_name WHERE thing = :name4;
],
auto_kind: None,
has_preprocessor: None,
..Default::default()
..Default::default()
}
);
@@ -1407,7 +1543,7 @@ SELECT * FROM users WHERE id = $1 AND email = $2::text;
],
auto_kind: None,
has_preprocessor: None,
..Default::default()
..Default::default()
}
);
@@ -1446,7 +1582,7 @@ SELECT * FROM users LIMIT $1 OFFSET $2;
],
auto_kind: None,
has_preprocessor: None,
..Default::default()
..Default::default()
}
);
@@ -1497,7 +1633,7 @@ WHERE id = $1
],
auto_kind: None,
has_preprocessor: None,
..Default::default()
..Default::default()
}
);
@@ -1525,7 +1661,7 @@ SELECT * FROM users WHERE id = ANY($1);
},],
auto_kind: None,
has_preprocessor: None,
..Default::default()
..Default::default()
}
);
@@ -1555,7 +1691,7 @@ SELECT $1::integer;
},],
auto_kind: None,
has_preprocessor: None,
..Default::default()
..Default::default()
}
);
@@ -1588,7 +1724,7 @@ SELECT x
},],
auto_kind: None,
has_preprocessor: None,
..Default::default()
..Default::default()
}
);
File diff suppressed because it is too large Load Diff
@@ -1,5 +1,48 @@
cargo-features = ["panic-immediate-abort"]
# This crate is intentionally excluded from the parent backend workspace
# (see `backend/Cargo.toml` `exclude = [...]`) because it uses nightly-only
# features (`cargo-features`, `-Z build-std`) that would break stable builds.
# It declares its own workspace here so that `.workspace = true` inheritance
# resolves against its own `[workspace.package]` / `[workspace.dependencies]`
# tables below. Sibling windmill-parser-* crates are referenced by path and
# keep using the parent workspace for their own dependencies.
[workspace]
resolver = "2"
members = ["."]
[workspace.package]
version = "1.688.0"
edition = "2021"
authors = ["Ruben Fiszel <ruben@windmill.dev>"]
[workspace.dependencies]
anyhow = "^1"
serde_json = { version = "^1", features = ["preserve_order", "raw_value"] }
wasm-bindgen = "=0.2.103"
wasm-bindgen-test = "^0"
getrandom = "0.2"
windmill-parser = { path = "../windmill-parser" }
windmill-parser-ts = { path = "../windmill-parser-ts" }
windmill-parser-ts-asset = { path = "../windmill-parser-ts-asset" }
windmill-parser-py = { path = "../windmill-parser-py" }
windmill-parser-py-asset = { path = "../windmill-parser-py-asset" }
windmill-parser-py-imports = { path = "../windmill-parser-py-imports" }
windmill-parser-go = { path = "../windmill-parser-go" }
windmill-parser-rust = { path = "../windmill-parser-rust" }
windmill-parser-yaml = { path = "../windmill-parser-yaml" }
windmill-parser-csharp = { path = "../windmill-parser-csharp" }
windmill-parser-java = { path = "../windmill-parser-java" }
windmill-parser-ruby = { path = "../windmill-parser-ruby" }
windmill-parser-r = { path = "../windmill-parser-r" }
windmill-parser-nu = { path = "../windmill-parser-nu" }
windmill-parser-bash = { path = "../windmill-parser-bash" }
windmill-parser-sql = { path = "../windmill-parser-sql" }
windmill-parser-sql-asset = { path = "../windmill-parser-sql-asset" }
windmill-parser-graphql = { path = "../windmill-parser-graphql" }
windmill-parser-php = { path = "../windmill-parser-php" }
windmill-parser-wac = { path = "../windmill-parser-wac" }
[package]
name = "windmill-parser-wasm"
version.workspace = true
@@ -392,7 +392,7 @@ pub async fn do_bigquery(
&reserved_variables,
)?;
let queries = parse_sql_blocks(query);
let queries = parse_sql_blocks(query, false);
let mut statement_values: HashMap<String, Value> = HashMap::new();
@@ -110,7 +110,7 @@ pub async fn do_duckdb(
m
};
let query_block_list = parse_sql_blocks(&query);
let query_block_list = parse_sql_blocks(&query, true);
// Replace custom ATTACH statements with the real instructions
let query_block_list = {
@@ -649,7 +649,6 @@ async fn transform_attach_ducklake(
.unwrap_or(DEFAULT_STORAGE);
let data_path = ducklake.storage.path;
let extra_args = if let Some(default_extra_args) = ducklake.extra_args {
format!("{},{}", extra_args, default_extra_args)
} else {
@@ -669,7 +668,6 @@ async fn transform_attach_ducklake(
} else {
format!(", AUTOMATIC_MIGRATION TRUE{extra_args}")
};
let attach_str = format!(
"ATTACH 'ducklake:{db_type}:{db_conn_str}' AS {alias_name} (DATA_PATH 's3://{storage}/{data_path}'{extra_args});",
@@ -307,7 +307,7 @@ pub async fn do_mysql(
let mysql_conn = pool.get_conn().await.map_err(to_anyhow)?;
let conn_a = Arc::new(Mutex::new(mysql_conn));
let queries = parse_sql_blocks(query);
let queries = parse_sql_blocks(query, false);
let conn_a_ref = &conn_a;
let result_f = async move {
@@ -430,7 +430,7 @@ pub async fn do_oracledb(
let conn_a = Arc::new(std::sync::Mutex::new(oracle_conn));
let queries = parse_sql_blocks(&query);
let queries = parse_sql_blocks(&query, false);
let result_f = async move {
let mut results = vec![];
+1 -1
View File
@@ -394,7 +394,7 @@ pub async fn do_postgresql(
let (query, _) =
&sanitize_and_interpolate_unsafe_sql_args(query, &sig.args, &pg_args, &reserved_variables)?;
let queries = parse_sql_blocks(query);
let queries = parse_sql_blocks(query, true);
let (client, handle) = if let Some((client, handle)) = new_client.as_ref() {
(client, Some(handle))
@@ -659,7 +659,7 @@ pub async fn do_snowflake(
.as_secs();
body.insert("timeout".to_string(), json!(timeout));
let queries = parse_sql_blocks(query);
let queries = parse_sql_blocks(query, false);
let (timeout_duration, _, _) =
resolve_job_timeout(&conn, &job.workspace_id, job.id, job.timeout).await;
+6 -52
View File
@@ -83,7 +83,7 @@
"windmill-parser-wasm-php": "1.647.1",
"windmill-parser-wasm-py": "1.657.2",
"windmill-parser-wasm-r": "1.668.1",
"windmill-parser-wasm-regex": "^1.670.0",
"windmill-parser-wasm-regex": "1.688.0",
"windmill-parser-wasm-ruby": "1.526.1",
"windmill-parser-wasm-rust": "1.647.1",
"windmill-parser-wasm-ts": "1.657.2",
@@ -844,7 +844,6 @@
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.0.tgz",
"integrity": "sha512-0DQ98G9ZQZOxfUcQn1waV2yS8aWdZ6kJMbYCJB3oUBecjWYO1fqJ+a1DRfPF3O5JEkwqwP1A9QEN/9mYm2Yd0w==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
@@ -856,7 +855,6 @@
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.0.tgz",
"integrity": "sha512-QN75eB0IH2ywSpRpNddCRfQIhmJYBCJ1x5Lb3IscKAL8bMnVAKnRg8dCoXbHzVLLH7P38N2Z3mtulB7W0J0FKw==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
@@ -867,7 +865,6 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.0.tgz",
"integrity": "sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
@@ -1357,7 +1354,6 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.1.tgz",
"integrity": "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
@@ -1514,7 +1510,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1531,7 +1526,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1548,7 +1542,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1565,7 +1558,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1582,7 +1574,6 @@
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1599,7 +1590,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1616,7 +1606,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1633,7 +1622,6 @@
"cpu": [
"ppc64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1650,7 +1638,6 @@
"cpu": [
"s390x"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1667,7 +1654,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1684,7 +1670,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1701,7 +1686,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1718,7 +1702,6 @@
"cpu": [
"wasm32"
],
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
@@ -1735,7 +1718,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1752,7 +1734,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -2058,7 +2039,6 @@
"version": "0.10.1",
"resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz",
"integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
@@ -6834,7 +6814,7 @@
"version": "1.21.7",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz",
"integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==",
"dev": true,
"devOptional": true,
"license": "MIT",
"bin": {
"jiti": "bin/jiti.js"
@@ -7333,7 +7313,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -7354,7 +7333,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -7375,7 +7353,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -7396,7 +7373,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -7417,7 +7393,6 @@
"cpu": [
"arm"
],
"dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -7438,7 +7413,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -7459,7 +7433,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -7480,7 +7453,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -7501,7 +7473,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -7522,7 +7493,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -7543,7 +7513,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -12112,21 +12081,6 @@
}
}
},
"node_modules/svelte-check/node_modules/picomatch": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
"dev": true,
"license": "MIT",
"optional": true,
"peer": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/svelte-eslint-parser": {
"version": "0.43.0",
"resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-0.43.0.tgz",
@@ -12857,7 +12811,7 @@
"version": "5.9.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"dev": true,
"devOptional": true,
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
@@ -13671,9 +13625,9 @@
"integrity": "sha512-5YNeUibxpNBvYrxCgQcz1PxGhTFx2CyEpg2udtIhq7bx0d4gF/KDZVupMeQmAObmrEtTSFGUWNRJ4zXSWNrSpQ=="
},
"node_modules/windmill-parser-wasm-regex": {
"version": "1.670.0",
"resolved": "https://registry.npmjs.org/windmill-parser-wasm-regex/-/windmill-parser-wasm-regex-1.670.0.tgz",
"integrity": "sha512-foQBwLn7L3JpmPSzMYmFhpVvUnXB1KX4v1rGBsm5W6KircwrjW3VXl/Ih9Izjyju2RRK+tYzjN8vvd2Zo7ulKQ=="
"version": "1.688.0",
"resolved": "https://registry.npmjs.org/windmill-parser-wasm-regex/-/windmill-parser-wasm-regex-1.688.0.tgz",
"integrity": "sha512-TB6ysy8nRcWDPRR79ujDihJc3S4oJTqawWSjUF837JDxaG595P9osZErxR4MOO5Ye5MecKESeIgP3UDK6O6bhg=="
},
"node_modules/windmill-parser-wasm-ruby": {
"version": "1.526.1",
+1 -1
View File
@@ -156,7 +156,7 @@
"windmill-parser-wasm-php": "1.647.1",
"windmill-parser-wasm-py": "1.657.2",
"windmill-parser-wasm-r": "1.668.1",
"windmill-parser-wasm-regex": "^1.670.0",
"windmill-parser-wasm-regex": "1.688.0",
"windmill-parser-wasm-ruby": "1.526.1",
"windmill-parser-wasm-rust": "1.647.1",
"windmill-parser-wasm-ts": "1.657.2",