feat: eval v2, blazing fast eval triggered only upon the right changes (#2164)

* progress

* progress

* progress

* add suggestions to frontend scripts

* all eval

* remove onlyStatic

* handle better conversions

* handle better conversions

* remove variable picker

* fix pen positioning

* fix v1
This commit is contained in:
Ruben Fiszel
2023-08-23 19:50:35 +02:00
committed by GitHub
parent daa2c75853
commit ff3e8e6cf8
38 changed files with 719 additions and 470 deletions
+150 -171
View File
@@ -197,15 +197,15 @@ dependencies = [
[[package]]
name = "ast_node"
version = "0.9.4"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c704e2f6ee1a98223f5a7629a6ef0f3decb3b552ed282889dc957edff98ce1e6"
checksum = "c09c69dffe06d222d072c878c3afe86eee2179806f20503faec97250268b4c24"
dependencies = [
"pmutil",
"proc-macro2",
"quote",
"swc_macros_common",
"syn 1.0.109",
"syn 2.0.29",
]
[[package]]
@@ -511,7 +511,7 @@ dependencies = [
"cc",
"cfg-if",
"libc",
"miniz_oxide 0.7.1",
"miniz_oxide",
"object",
"rustc-demangle",
]
@@ -1395,10 +1395,33 @@ dependencies = [
]
[[package]]
name = "deno_ast"
version = "0.27.3"
name = "deno-proc-macro-rules"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b17e25531279d9795aeb076909c91c9b369fa63fd4d801486950577d0457d22"
checksum = "3c65c2ffdafc1564565200967edc4851c7b55422d3913466688907efd05ea26f"
dependencies = [
"deno-proc-macro-rules-macros",
"proc-macro2",
"syn 2.0.29",
]
[[package]]
name = "deno-proc-macro-rules-macros"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3047b312b7451e3190865713a4dd6e1f821aed614ada219766ebc3024a690435"
dependencies = [
"once_cell",
"proc-macro2",
"quote",
"syn 2.0.29",
]
[[package]]
name = "deno_ast"
version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00c93119b1c487a85603406a988a0ca9a1d0e5315404cccc5c158fb484b1f5a2"
dependencies = [
"anyhow",
"base64 0.13.1",
@@ -1409,11 +1432,11 @@ dependencies = [
"swc_common",
"swc_config",
"swc_config_macro",
"swc_ecma_ast 0.104.5",
"swc_ecma_ast",
"swc_ecma_codegen",
"swc_ecma_codegen_macros",
"swc_ecma_loader",
"swc_ecma_parser 0.134.12",
"swc_ecma_parser",
"swc_ecma_transforms_base",
"swc_ecma_transforms_classes",
"swc_ecma_transforms_macros",
@@ -1432,18 +1455,18 @@ dependencies = [
[[package]]
name = "deno_console"
version = "0.109.0"
version = "0.115.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04eb3b6a0337c1f2122d6d859586e6d011925a183ae6f588e08f42f3a4affecf"
checksum = "19ab05b798826985966deb29fc6773ed29570de2f2147a30c4289c7cdf635214"
dependencies = [
"deno_core",
]
[[package]]
name = "deno_core"
version = "0.191.0"
version = "0.200.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "495704f95457631b366e8cbf427f817db8cdaf4b17832c69faa6b5b91e58fa2a"
checksum = "a8ba264b90ceb6e95b39d82e674d8ecae86ca012f900338ea50d1a077d9d75fd"
dependencies = [
"anyhow",
"bytes",
@@ -1467,9 +1490,9 @@ dependencies = [
[[package]]
name = "deno_fetch"
version = "0.133.0"
version = "0.139.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60389ff20e9eda3f75ab253f3e46b2d4de9c0e462bfd4144d125f4f1433cc12d"
checksum = "e4f1b9a643427c7f732a4540e250560e1801970f033bae0d5e4abc7b83e36160"
dependencies = [
"bytes",
"data-url",
@@ -1480,7 +1503,6 @@ dependencies = [
"reqwest",
"serde",
"tokio",
"tokio-stream",
"tokio-util",
]
@@ -1497,10 +1519,11 @@ dependencies = [
[[package]]
name = "deno_ops"
version = "0.69.0"
version = "0.78.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "511999e75fa5712d483a40811e8b600964893ddf3948d20e0aecf7dac6a1969f"
checksum = "ffd1c83b1fd465ee0156f2917c9af9ca09fe2bf54052a2cae1a8dcbc7b89aefc"
dependencies = [
"deno-proc-macro-rules",
"lazy-regex",
"once_cell",
"pmutil",
@@ -1508,14 +1531,18 @@ dependencies = [
"proc-macro2",
"quote",
"regex",
"strum",
"strum_macros",
"syn 1.0.109",
"syn 2.0.29",
"thiserror",
]
[[package]]
name = "deno_tls"
version = "0.96.0"
version = "0.102.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b35acb8674e9473f44b8b061a584508eee6fda01e195e59395d112da0428ded"
checksum = "010ce5e0a920b2364c75a9e38bcd3344bfe55a6b6cd9ef6717d78e5478f9bcb3"
dependencies = [
"deno_core",
"once_cell",
@@ -1529,21 +1556,20 @@ dependencies = [
[[package]]
name = "deno_url"
version = "0.109.0"
version = "0.115.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "429e44733a4e59af6c1db8ea5215b86665a6f7b2022c2d7e968529af920884a4"
checksum = "20490fff3b0f8c176a815e26371ff23313ea7f39cd51057701524c5b6fc36f6c"
dependencies = [
"deno_core",
"serde",
"serde_repr",
"urlpattern",
]
[[package]]
name = "deno_web"
version = "0.140.0"
version = "0.146.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5db59bdc78f43d2bc31ad448b1bc75369aa48f1c68ae330f9b3e3a48b9d37b6"
checksum = "1dc8dda6e1337d4739ae9e94d75521689824d82a7deb154a2972b6eedac64507"
dependencies = [
"async-trait",
"base64-simd",
@@ -1558,9 +1584,9 @@ dependencies = [
[[package]]
name = "deno_webidl"
version = "0.109.0"
version = "0.115.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35e30dc4f727a4ca397528c944dbc74087df86b2268171995949031f1fbc663b"
checksum = "73159d81053ead02e938b46d4bb7224c8e7cf25273ac16a250fb45bb09af7635"
dependencies = [
"deno_core",
]
@@ -1713,17 +1739,17 @@ checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
[[package]]
name = "dprint-swc-ext"
version = "0.10.0"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd4dda8a1b920e8be367aeaad035753d21bb69b3c50515afb41ab1eefbb886b5"
checksum = "3f115ea5b6f5d0d02a25a9364f41b8c4f857452c299309dcfd29a694724d0566"
dependencies = [
"bumpalo",
"num-bigint",
"rustc-hash",
"swc_atoms",
"swc_common",
"swc_ecma_ast 0.104.5",
"swc_ecma_parser 0.134.12",
"swc_ecma_ast",
"swc_ecma_parser",
"text_lines",
]
@@ -1851,13 +1877,14 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
[[package]]
name = "flate2"
version = "1.0.24"
version = "1.0.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6"
checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010"
dependencies = [
"crc32fast",
"libz-ng-sys",
"libz-sys",
"miniz_oxide 0.5.4",
"miniz_oxide",
]
[[package]]
@@ -1904,14 +1931,14 @@ dependencies = [
[[package]]
name = "from_variant"
version = "0.1.5"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d449976075322384507443937df2f1d5577afbf4282f12a5a66ef29fa3e6307"
checksum = "03ec5dc38ee19078d84a692b1c41181ff9f94331c76cee66ff0208c770b5e54f"
dependencies = [
"pmutil",
"proc-macro2",
"swc_macros_common",
"syn 1.0.109",
"syn 2.0.29",
]
[[package]]
@@ -2588,15 +2615,15 @@ checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6"
[[package]]
name = "is-macro"
version = "0.2.2"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a7d079e129b77477a49c5c4f1cfe9ce6c2c909ef52520693e8e811a714c7b20"
checksum = "f4467ed1321b310c2625c5aa6c1b1ffc5de4d9e42668cf697a08fb033ee8265e"
dependencies = [
"Inflector",
"pmutil",
"proc-macro2",
"quote",
"syn 1.0.109",
"syn 2.0.29",
]
[[package]]
@@ -2888,6 +2915,16 @@ dependencies = [
"vcpkg",
]
[[package]]
name = "libz-ng-sys"
version = "1.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dd9f43e75536a46ee0f92b758f6b63846e594e86638c61a9251338a65baea63"
dependencies = [
"cmake",
"libc",
]
[[package]]
name = "libz-sys"
version = "1.1.12"
@@ -3081,15 +3118,6 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "miniz_oxide"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34"
dependencies = [
"adler",
]
[[package]]
name = "miniz_oxide"
version = "0.7.1"
@@ -3742,13 +3770,13 @@ checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
[[package]]
name = "pmutil"
version = "0.5.3"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3894e5d549cccbe44afecf72922f277f603cd4bb0219c8342631ef18fffbe004"
checksum = "52a40bc70c2c58040d2d8b167ba9a5ff59fc9dab7ad44771cfde3dcfde7a09c6"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
"syn 2.0.29",
]
[[package]]
@@ -4941,17 +4969,6 @@ dependencies = [
"thiserror",
]
[[package]]
name = "serde_repr"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fe39d9fbb0ebf5eb2c7cb7e2a47e4f462fad1379f1166b8ae49ad9eae89a7ca"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "serde_spanned"
version = "0.6.3"
@@ -4987,9 +5004,9 @@ dependencies = [
[[package]]
name = "serde_v8"
version = "0.102.0"
version = "0.111.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b80e857f45543c24c52f62bbccf138d2a9715a17d3bde69e697fc261ae655ac"
checksum = "309b3060a9627882514f3a3ce3cc08ceb347a76aeeadc58f138c3f189cf88b71"
dependencies = [
"bytes",
"derive_more",
@@ -5537,15 +5554,15 @@ dependencies = [
[[package]]
name = "string_enum"
version = "0.4.0"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0090512bdfee4b56d82480d66c0fd8a6f53f0fe0f97e075e949b252acdd482e0"
checksum = "8fa4d4f81d7c05b9161f8de839975d3326328b8ba2831164b465524cc2f55252"
dependencies = [
"pmutil",
"proc-macro2",
"quote",
"swc_macros_common",
"syn 1.0.109",
"syn 2.0.29",
]
[[package]]
@@ -5604,9 +5621,9 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
[[package]]
name = "swc_atoms"
version = "0.5.6"
version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93d0307dc4bfd107d49c7528350c372758cfca94fb503629b9a056e6a1572860"
checksum = "b8066e17abb484602da673e2d35138ab32ce53f26368d9c92113510e1659220b"
dependencies = [
"once_cell",
"rustc-hash",
@@ -5618,11 +5635,10 @@ dependencies = [
[[package]]
name = "swc_common"
version = "0.31.12"
version = "0.31.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19c774005489d2907fb67909cf42af926e72edee1366512777c605ba2ef19c94"
checksum = "de5823ef063f116ad281cde9700f5be6dfb182e543ce3f62c42cee1c03ffbc6b"
dependencies = [
"ahash 0.7.6",
"ast_node",
"better_scoped_tls",
"cfg-if",
@@ -5646,9 +5662,9 @@ dependencies = [
[[package]]
name = "swc_config"
version = "0.1.5"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89c8fc2c12bb1634c7c32fc3c9b6b963ad8f034cc62c4ecddcf215dc4f6f959d"
checksum = "9ba1c7a40d38f9dd4e9a046975d3faf95af42937b34b2b963be4d8f01239584b"
dependencies = [
"indexmap 1.9.3",
"serde",
@@ -5658,22 +5674,22 @@ dependencies = [
[[package]]
name = "swc_config_macro"
version = "0.1.1"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dadb9998d4f5fc36ef558ed5a092579441579ee8c6fcce84a5228cca9df4004"
checksum = "e5b5aaca9a0082be4515f0fbbecc191bf5829cd25b5b9c0a2810f6a2bb0d6829"
dependencies = [
"pmutil",
"proc-macro2",
"quote",
"swc_macros_common",
"syn 1.0.109",
"syn 2.0.29",
]
[[package]]
name = "swc_ecma_ast"
version = "0.104.5"
version = "0.107.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5cf9dd351d0c285dcd36535267953a18995d4dda0cbe34ac9d1df61aa415b26"
checksum = "b7191c8c57af059b75a2aadc927a2608c3962d19e4d09ce8f9c3f03739ddf833"
dependencies = [
"bitflags 2.4.0",
"is-macro",
@@ -5686,27 +5702,11 @@ dependencies = [
"unicode-id",
]
[[package]]
name = "swc_ecma_ast"
version = "0.106.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd5b138534f6f673afa83b6168d67158ad0fff54b4071287e83cfe87a82cfb04"
dependencies = [
"bitflags 2.4.0",
"is-macro",
"num-bigint",
"scoped-tls",
"string_enum",
"swc_atoms",
"swc_common",
"unicode-id",
]
[[package]]
name = "swc_ecma_codegen"
version = "0.139.17"
version = "0.142.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c66d1ea16bb9b7ea6f87f17325742ff256fcbd65b188af57c2bf415fe4afc945"
checksum = "1e4e3ee8a1f0bfaf630febbe0f6a03f2c28d66d373a9bbdb3f500f6bfb536b43"
dependencies = [
"memchr",
"num-bigint",
@@ -5716,31 +5716,30 @@ dependencies = [
"sourcemap",
"swc_atoms",
"swc_common",
"swc_ecma_ast 0.104.5",
"swc_ecma_ast",
"swc_ecma_codegen_macros",
"tracing",
]
[[package]]
name = "swc_ecma_codegen_macros"
version = "0.7.2"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf4ee0caee1018808d94ecd09490cb7affd3d504b19aa11c49238f5fc4b54901"
checksum = "dcdff076dccca6cc6a0e0b2a2c8acfb066014382bc6df98ec99e755484814384"
dependencies = [
"pmutil",
"proc-macro2",
"quote",
"swc_macros_common",
"syn 1.0.109",
"syn 2.0.29",
]
[[package]]
name = "swc_ecma_loader"
version = "0.43.14"
version = "0.43.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe45f1e5dcc1b005544ff78253b787dea5dfd5e2f712b133964cdc3545c954a4"
checksum = "82f47bb1ab686f603da93a8b6e559d69b42369ab47d5dee6bdda38ae5902dc2a"
dependencies = [
"ahash 0.7.6",
"anyhow",
"pathdiff",
"serde",
@@ -5750,49 +5749,29 @@ dependencies = [
[[package]]
name = "swc_ecma_parser"
version = "0.134.12"
version = "0.137.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0a3fcfe3d83dd445cbd9321882e47b467594433d9a21c4d6c37a27f534bb89e"
checksum = "29c0d554865a63bfa58cf1c433fa91d7d4adf40030fa8e4530e8065d0578166a"
dependencies = [
"either",
"lexical",
"num-bigint",
"num-traits",
"serde",
"smallvec",
"smartstring",
"stacker",
"swc_atoms",
"swc_common",
"swc_ecma_ast 0.104.5",
"tracing",
"typed-arena",
]
[[package]]
name = "swc_ecma_parser"
version = "0.136.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "079abb34fdd8b4b20402d61dcd4c45f3f4171670bae3b9466927067ad7861a8b"
dependencies = [
"either",
"lexical",
"num-bigint",
"serde",
"smallvec",
"smartstring",
"stacker",
"swc_atoms",
"swc_common",
"swc_ecma_ast 0.106.2",
"swc_ecma_ast",
"tracing",
"typed-arena",
]
[[package]]
name = "swc_ecma_transforms_base"
version = "0.127.18"
version = "0.130.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9c33ec5369178f3a0580ab86cfe89ffb9c3fbd122aed379cfb71d469d9d61c1"
checksum = "d8d8ca5dd849cea79e6a9792d725f4082ad3ade7a9541fba960c42d55ae778f2"
dependencies = [
"better_scoped_tls",
"bitflags 2.4.0",
@@ -5804,8 +5783,8 @@ dependencies = [
"smallvec",
"swc_atoms",
"swc_common",
"swc_ecma_ast 0.104.5",
"swc_ecma_parser 0.134.12",
"swc_ecma_ast",
"swc_ecma_parser",
"swc_ecma_utils",
"swc_ecma_visit",
"tracing",
@@ -5813,13 +5792,13 @@ dependencies = [
[[package]]
name = "swc_ecma_transforms_classes"
version = "0.116.18"
version = "0.119.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e3b0d5f362f0da97be1f1b06d7b0d8667ea70b4adeabff0dcaecb6259c09525"
checksum = "a09d0e350963d4fb14bf9dc31c85eb28e58a88614e779c75f49296710f9cb381"
dependencies = [
"swc_atoms",
"swc_common",
"swc_ecma_ast 0.104.5",
"swc_ecma_ast",
"swc_ecma_transforms_base",
"swc_ecma_utils",
"swc_ecma_visit",
@@ -5827,22 +5806,22 @@ dependencies = [
[[package]]
name = "swc_ecma_transforms_macros"
version = "0.5.1"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "984d5ac69b681fc5438f9abf82b0fda34fe04e119bc75f8213b7e01128c7c9a2"
checksum = "f59c4b6ed5d78d3ad9fc7c6f8ab4f85bba99573d31d9a2c0a712077a6b45efd2"
dependencies = [
"pmutil",
"proc-macro2",
"quote",
"swc_macros_common",
"syn 1.0.109",
"syn 2.0.29",
]
[[package]]
name = "swc_ecma_transforms_proposal"
version = "0.161.22"
version = "0.164.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0cdce42d44ef775bc29f5ada3678a80ff72fa17a0ef705e14f63cfd0e0155e0e"
checksum = "62d3a04de35f6c79d8f343822138e7313934d3530cc4e4f891a079f7e2415c1a"
dependencies = [
"either",
"rustc-hash",
@@ -5850,7 +5829,7 @@ dependencies = [
"smallvec",
"swc_atoms",
"swc_common",
"swc_ecma_ast 0.104.5",
"swc_ecma_ast",
"swc_ecma_transforms_base",
"swc_ecma_transforms_classes",
"swc_ecma_transforms_macros",
@@ -5860,11 +5839,10 @@ dependencies = [
[[package]]
name = "swc_ecma_transforms_react"
version = "0.173.20"
version = "0.176.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fb9481ad4e2acba34c6fbb6d4ccc64efe9f1821675e883dcfa732d7220f4b1e"
checksum = "607017e6fbfe3229b69ffce7b47383eb9b62025ea93a50cd1cc1788d2a29a4ca"
dependencies = [
"ahash 0.7.6",
"base64 0.13.1",
"dashmap",
"indexmap 1.9.3",
@@ -5875,8 +5853,8 @@ dependencies = [
"swc_atoms",
"swc_common",
"swc_config",
"swc_ecma_ast 0.104.5",
"swc_ecma_parser 0.134.12",
"swc_ecma_ast",
"swc_ecma_parser",
"swc_ecma_transforms_base",
"swc_ecma_transforms_macros",
"swc_ecma_utils",
@@ -5885,14 +5863,14 @@ dependencies = [
[[package]]
name = "swc_ecma_transforms_typescript"
version = "0.177.23"
version = "0.180.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fe2eea4f5b8a25c93cdaa29fb1ce4108893da88a11e61e04b7f5295b5468829"
checksum = "ea349e787a62af0dcf1b8b52d507045345871571c18cb78a2f892912f7d6b753"
dependencies = [
"serde",
"swc_atoms",
"swc_common",
"swc_ecma_ast 0.104.5",
"swc_ecma_ast",
"swc_ecma_transforms_base",
"swc_ecma_transforms_react",
"swc_ecma_utils",
@@ -5901,9 +5879,9 @@ dependencies = [
[[package]]
name = "swc_ecma_utils"
version = "0.117.13"
version = "0.120.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad791bbfdafcebd878584021e050964c8ab68aba7eeac9d0ee4afba4c284a629"
checksum = "2cb60e20e1eb9e9f7c88d99ac8659fd0561d70abd27853f550fbd907a448c878"
dependencies = [
"indexmap 1.9.3",
"num_cpus",
@@ -5911,7 +5889,7 @@ dependencies = [
"rustc-hash",
"swc_atoms",
"swc_common",
"swc_ecma_ast 0.104.5",
"swc_ecma_ast",
"swc_ecma_visit",
"tracing",
"unicode-id",
@@ -5919,47 +5897,47 @@ dependencies = [
[[package]]
name = "swc_ecma_visit"
version = "0.90.5"
version = "0.93.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ce3ac941ae1d6c7e683aa375fc71fbf58df58b441f614d757fbb10554936ca2"
checksum = "bb23a48abd9f5731b6275dbf4ea89f6e03dc60b7c8e3e1e383bb4a6c39fd7e25"
dependencies = [
"num-bigint",
"swc_atoms",
"swc_common",
"swc_ecma_ast 0.104.5",
"swc_ecma_ast",
"swc_visit",
"tracing",
]
[[package]]
name = "swc_eq_ignore_macros"
version = "0.1.1"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c20468634668c2bbab581947bb8c75c97158d5a6959f4ba33df20983b20b4f6"
checksum = "05a95d367e228d52484c53336991fdcf47b6b553ef835d9159db4ba40efb0ee8"
dependencies = [
"pmutil",
"proc-macro2",
"quote",
"syn 1.0.109",
"syn 2.0.29",
]
[[package]]
name = "swc_macros_common"
version = "0.3.7"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e582c3e3c2269238524923781df5be49e011dbe29cf7683a2215d600a562ea6"
checksum = "7a273205ccb09b51fabe88c49f3b34c5a4631c4c00a16ae20e03111d6a42e832"
dependencies = [
"pmutil",
"proc-macro2",
"quote",
"syn 1.0.109",
"syn 2.0.29",
]
[[package]]
name = "swc_visit"
version = "0.5.6"
version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f412dd4fbc58f509a04e64f5c8038333142fc139e8232f01b883db0094b3b51"
checksum = "e87c337fbb2d191bf371173dea6a957f01899adb8f189c6c31b122a6cfc98fc3"
dependencies = [
"either",
"swc_visit_macros",
@@ -5967,16 +5945,16 @@ dependencies = [
[[package]]
name = "swc_visit_macros"
version = "0.5.7"
version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4cfc226380ba54a5feed2c12f3ccd33f1ae8e959160290e5d2d9b4e918b6472a"
checksum = "0f322730fb82f3930a450ac24de8c98523af7d34ab8cb2f46bcb405839891a99"
dependencies = [
"Inflector",
"pmutil",
"proc-macro2",
"quote",
"swc_macros_common",
"syn 1.0.109",
"syn 2.0.29",
]
[[package]]
@@ -6804,9 +6782,9 @@ dependencies = [
[[package]]
name = "v8"
version = "0.73.0"
version = "0.74.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1bd3f04ba5065795dae6e3db668ff0b628920fbd2e39c1755e9b62d93660c3c"
checksum = "2eedac634b8dd39b889c5b62349cbc55913780226239166435c5cf66771792ea"
dependencies = [
"bitflags 1.3.2",
"fslock",
@@ -7337,8 +7315,9 @@ dependencies = [
"serde-wasm-bindgen",
"serde_json",
"swc_common",
"swc_ecma_ast 0.106.2",
"swc_ecma_parser 0.136.3",
"swc_ecma_ast",
"swc_ecma_parser",
"swc_ecma_visit",
"wasm-bindgen",
"windmill-parser",
]
+11 -10
View File
@@ -131,17 +131,18 @@ tokio-util = { version = "^0", features = ["io"] }
json-pointer = "^0"
itertools = "^0"
regex = "^1"
deno_fetch = "0.133.0"
deno_console = "0.109.0"
deno_url = "0.109.0"
deno_webidl = "0.109.0"
deno_web = "0.140.0"
deno_core = "0.191.0"
deno_ast = { version = "0.27.2", features = ["transpiling"] }
deno_fetch = "0.139.0"
deno_console = "0.115.0"
deno_url = "0.115.0"
deno_webidl = "0.115.0"
deno_web = "0.146.0"
deno_core = "0.200.0"
deno_ast = { version = "0.28.0", features = ["transpiling"] }
async-recursion = "^1"
swc_common = "0.31.12"
swc_ecma_parser = "0.136.2"
swc_ecma_ast = "0.106.2"
swc_common = "0.31.21"
swc_ecma_parser = "0.137.15"
swc_ecma_ast = "0.107.7"
swc_ecma_visit = "0.93.7"
base64 = "0.21.0"
hmac = "0.12.1"
sha2 = "0.10.6"
@@ -18,6 +18,7 @@ windmill-parser.workspace = true
swc_common.workspace = true
swc_ecma_parser.workspace = true
swc_ecma_ast.workspace = true
swc_ecma_visit.workspace = true
serde_json.workspace = true
anyhow.workspace = true
convert_case.workspace = true
+62 -5
View File
@@ -9,21 +9,78 @@ use regex::Regex;
*/
// use deno_core::{serde_v8, v8, JsRuntime, RuntimeOptions};
use serde_json::Value;
use std::collections::HashSet;
use swc_ecma_visit::{noop_visit_type, Visit, VisitWith};
use windmill_parser::{json_to_typ, Arg, MainArgSignature, ObjectProperty, Typ};
use swc_common::{sync::Lrc, FileName, SourceMap, SourceMapper, Span, Spanned};
use swc_ecma_ast::{
ArrayLit, AssignPat, BigInt, BindingIdent, Bool, Decl, ExportDecl, Expr, FnDecl, Ident, Lit,
ModuleDecl, ModuleItem, Number, ObjectLit, ObjectPat, Param, Pat, Str, TsArrayType,
TsEntityName, TsKeywordType, TsKeywordTypeKind, TsLit, TsLitType, TsOptionalType,
MemberExpr, MemberProp, ModuleDecl, ModuleItem, Number, ObjectLit, ObjectPat, Param, Pat, Str,
TsArrayType, TsEntityName, TsKeywordType, TsKeywordTypeKind, TsLit, TsLitType, TsOptionalType,
TsParenthesizedType, TsPropertySignature, TsType, TsTypeAnn, TsTypeElement, TsTypeLit,
TsTypeRef, TsUnionOrIntersectionType, TsUnionType,
};
use swc_ecma_parser::{lexer::Lexer, Parser, StringInput, Syntax, TsConfig};
use swc_ecma_parser::{lexer::Lexer, EsConfig, Parser, StringInput, Syntax, TsConfig};
#[cfg(target_arch = "wasm32")]
use wasm_bindgen::prelude::*;
struct OutputFinder {
idents: HashSet<(String, String)>,
}
impl Visit for OutputFinder {
noop_visit_type!();
fn visit_member_expr(&mut self, m: &MemberExpr) {
m.obj.visit_with(self);
if let MemberProp::Computed(c) = &m.prop {
c.visit_with(self);
}
match m {
MemberExpr { obj, prop: MemberProp::Ident(Ident { sym, .. }), .. } => {
match *obj.to_owned() {
Expr::Ident(Ident { sym: sym_i, .. }) => {
self.idents.insert((sym_i.to_string(), sym.to_string()));
}
_ => (),
}
}
_ => (),
}
}
}
pub fn parse_expr_for_ids(code: &str) -> anyhow::Result<Vec<(String, String)>> {
let cm: Lrc<SourceMap> = Default::default();
let fm = cm.new_source_file(FileName::Custom("main.ts".into()), code.into());
let lexer = Lexer::new(
// We want to parse ecmascript
Syntax::Es(EsConfig { jsx: false, ..Default::default() }),
// EsVersion defaults to es5
Default::default(),
StringInput::from(&*fm),
None,
);
let mut parser = Parser::new_from(lexer);
let mut err_s = "".to_string();
for e in parser.take_errors() {
err_s += &e.into_kind().msg().to_string();
}
let expr = parser
.parse_module()
.map_err(|_| anyhow::anyhow!("Error while parsing code, it is invalid TypeScript"))?;
let mut visitor = OutputFinder { idents: HashSet::new() };
swc_ecma_visit::visit_module(&mut visitor, &expr);
Ok(visitor.idents.into_iter().collect())
}
pub fn parse_deno_signature(code: &str, skip_dflt: bool) -> anyhow::Result<MainArgSignature> {
let cm: Lrc<SourceMap> = Default::default();
let fm = cm.new_source_file(FileName::Custom("main.ts".into()), code.into());
@@ -308,8 +365,8 @@ fn tstype_to_typ(ts_type: &TsType) -> (Typ, bool) {
extern "C" {
pub fn eval(s: &str) -> JsValue;
pub fn alert(s: &str);
// #[wasm_bindgen(js_namespace = console)]
// fn log(s: &str);
#[wasm_bindgen(js_namespace = console)]
fn log(s: &str);
}
@@ -3,7 +3,7 @@
"collaborators": [
"Ruben Fiszel <ruben@windmill.dev>"
],
"version": "1.147.3",
"version": "1.154.3",
"files": [
"windmill_parser_wasm_bg.wasm",
"windmill_parser_wasm.js",
@@ -14,4 +14,4 @@
"sideEffects": [
"./snippets/*"
]
}
}
@@ -9,6 +9,11 @@ export function parse_deno(code: string): string;
* @param {string} code
* @returns {string}
*/
export function parse_outputs(code: string): string;
/**
* @param {string} code
* @returns {string}
*/
export function parse_bash(code: string): string;
/**
* @param {string} code
@@ -56,6 +61,7 @@ export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembl
export interface InitOutput {
readonly memory: WebAssembly.Memory;
readonly parse_deno: (a: number, b: number, c: number) => void;
readonly parse_outputs: (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;
@@ -220,6 +220,29 @@ export function parse_deno(code) {
}
}
/**
* @param {string} code
* @returns {string}
*/
export function parse_outputs(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_outputs(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}
@@ -469,6 +492,10 @@ async function __wbg_load(module, imports) {
function __wbg_get_imports() {
const imports = {};
imports.wbg = {};
imports.wbg.__wbg_eval_bfffb337c5ad9d0f = function(arg0, arg1) {
const ret = eval(getStringFromWasm0(arg0, arg1));
return addHeapObject(ret);
};
imports.wbg.__wbindgen_object_drop_ref = function(arg0) {
takeObject(arg0);
};
@@ -520,10 +547,6 @@ function __wbg_get_imports() {
const ret = new Error(getStringFromWasm0(arg0, arg1));
return addHeapObject(ret);
};
imports.wbg.__wbg_eval_2824c9167fe66e96 = function(arg0, arg1) {
const ret = eval(getStringFromWasm0(arg0, arg1));
return addHeapObject(ret);
};
imports.wbg.__wbindgen_jsval_loose_eq = function(arg0, arg1) {
const ret = getObject(arg0) == getObject(arg1);
return ret;
@@ -2,6 +2,7 @@
/* eslint-disable */
export const memory: WebAssembly.Memory;
export function parse_deno(a: number, b: number, c: number): void;
export function parse_outputs(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;
@@ -1,6 +1,7 @@
use serde_json;
use serde_json::{self, json};
use wasm_bindgen::prelude::*;
use windmill_parser::MainArgSignature;
use windmill_parser_ts::parse_expr_for_ids;
fn wrap_sig(r: anyhow::Result<MainArgSignature>) -> String {
if let Ok(r) = r {
@@ -15,6 +16,17 @@ pub fn parse_deno(code: &str) -> String {
wrap_sig(windmill_parser_ts::parse_deno_signature(code, false))
}
#[wasm_bindgen]
pub fn parse_outputs(code: &str) -> String {
let parsed = parse_expr_for_ids(code);
let r = if let Ok(parsed) = parsed {
json!({ "outputs": parsed })
} else {
json!({"error": parsed.err().unwrap().to_string()})
};
return serde_json::to_string(&r).unwrap();
}
#[wasm_bindgen]
pub fn parse_bash(code: &str) -> String {
wrap_sig(windmill_parser_bash::parse_bash_sig(code))
@@ -1,7 +1,7 @@
use serde_json::json;
use wasm_bindgen_test::wasm_bindgen_test;
use windmill_parser::{Arg, MainArgSignature, ObjectProperty, Typ};
use windmill_parser_ts::parse_deno_signature;
use windmill_parser_ts::{parse_deno_signature, parse_expr_for_ids};
#[wasm_bindgen_test]
fn test_parse_deno_sig() -> anyhow::Result<()> {
@@ -256,3 +256,22 @@ export function main(foo: (\"foo\" | \"bar\")[]) {
Ok(())
}
#[wasm_bindgen_test]
fn test_parse_extract_ident() -> anyhow::Result<()> {
let code = "
let foo = 3;
bar
baroof.foob.ar
foobar[barfoo.x]
";
assert_eq!(
parse_expr_for_ids(code)?,
vec![
("baroof".to_string(), "foob".to_string()),
("barfoo".to_string(), "x".to_string())
]
);
Ok(())
}
+6 -2
View File
@@ -3,6 +3,7 @@ use deno_fetch::FetchPermissions;
use deno_web::{BlobStore, TimersPermission};
use std::env;
use std::path::PathBuf;
use std::sync::Arc;
pub struct PermissionsContainer;
@@ -48,7 +49,10 @@ fn main() {
deno_webidl::deno_webidl::init_ops_and_esm(),
deno_url::deno_url::init_ops_and_esm(),
deno_console::deno_console::init_ops_and_esm(),
deno_web::deno_web::init_ops_and_esm::<PermissionsContainer>(BlobStore::default(), None),
deno_web::deno_web::init_ops_and_esm::<PermissionsContainer>(
Arc::new(BlobStore::default()),
None,
),
deno_fetch::deno_fetch::init_ops_and_esm::<PermissionsContainer>(Default::default()),
fetch::init_ops_and_esm(),
];
@@ -65,7 +69,7 @@ fn main() {
startup_snapshot: None,
extensions: exts,
compression_cb: None,
snapshot_module_load_cb: None,
with_runtime_cb: None,
},
);
}
+14 -10
View File
@@ -6,14 +6,14 @@
* LICENSE-AGPL for a copy of the license.
*/
use std::{cell::RefCell, collections::HashMap, rc::Rc};
use std::{cell::RefCell, collections::HashMap, rc::Rc, sync::Arc};
use deno_ast::{ParseParams, SourceTextInfo};
use deno_core::{
op, serde_v8,
v8::IsolateHandle,
v8::{self},
Extension, JsRuntime, OpState, RuntimeOptions, Snapshot,
Extension, JsRuntime, Op, OpState, RuntimeOptions, Snapshot,
};
use deno_fetch::FetchPermissions;
use deno_web::{BlobStore, TimersPermission};
@@ -88,17 +88,17 @@ pub async fn eval_timeout(
// An op for summing an array of numbers
// The op-layer automatically deserializes inputs
// and serializes the returned Result & value
op_variable::decl(),
op_resource::decl(),
op_variable::DECL,
op_resource::DECL,
])
}
if by_id.is_some() && authed_client.is_some() {
ops.push(op_get_result::decl());
ops.push(op_get_id::decl());
ops.push(op_get_result::DECL);
ops.push(op_get_id::DECL);
}
let ext = Extension::builder("js_eval").ops(ops).build();
let ext = Extension { name: "js_eval", ops: ops.into(), ..Default::default() };
let exts = vec![ext];
// Use our snapshot to provision our new runtime
let options = RuntimeOptions {
@@ -444,15 +444,19 @@ pub async fn eval_fetch_timeout(
timeout(
std::time::Duration::from_millis(100000),
tokio::task::spawn_blocking(move || {
let ops = vec![op_get_static_args::decl(), op_log::decl()];
let ext = Extension::builder("windmill").ops(ops).build();
let ops = vec![op_get_static_args::DECL, op_log::DECL];
let ext = Extension {
name: "windmill",
ops: ops.into(),
..Default::default()
};
let exts: Vec<Extension> = vec![
deno_webidl::deno_webidl::init_ops(),
deno_url::deno_url::init_ops(),
deno_console::deno_console::init_ops(),
deno_web::deno_web::init_ops::<PermissionsContainer>(
BlobStore::default(),
Arc::new(BlobStore::default()),
None,
),
deno_fetch::deno_fetch::init_ops::<PermissionsContainer>(
+7 -7
View File
@@ -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.147.3",
"windmill-parser-wasm": "^1.154.3",
"y-monaco": "^0.1.4",
"y-websocket": "^1.5.0",
"yjs": "^13.6.7"
@@ -9770,9 +9770,9 @@
}
},
"node_modules/windmill-parser-wasm": {
"version": "1.147.3",
"resolved": "https://registry.npmjs.org/windmill-parser-wasm/-/windmill-parser-wasm-1.147.3.tgz",
"integrity": "sha512-fo7fEq/Wodv/p8MQhU4XjmOIsvANmqOYuQprkhn38wkYbdEbnni+A9m+Ln6YnLtya6xeO/rAbKES5MwILV7/Ug=="
"version": "1.154.3",
"resolved": "https://registry.npmjs.org/windmill-parser-wasm/-/windmill-parser-wasm-1.154.3.tgz",
"integrity": "sha512-mrp9HFhxVzNJRGr7L8Am/JawQkoTsQi9Ht3TkT9b+VzSEzSC5wZD1mukPFBK/oEQK+NReDcvNCg5LTSPv1caAQ=="
},
"node_modules/wordwrap": {
"version": "1.0.0",
@@ -16709,9 +16709,9 @@
}
},
"windmill-parser-wasm": {
"version": "1.147.3",
"resolved": "https://registry.npmjs.org/windmill-parser-wasm/-/windmill-parser-wasm-1.147.3.tgz",
"integrity": "sha512-fo7fEq/Wodv/p8MQhU4XjmOIsvANmqOYuQprkhn38wkYbdEbnni+A9m+Ln6YnLtya6xeO/rAbKES5MwILV7/Ug=="
"version": "1.154.3",
"resolved": "https://registry.npmjs.org/windmill-parser-wasm/-/windmill-parser-wasm-1.154.3.tgz",
"integrity": "sha512-mrp9HFhxVzNJRGr7L8Am/JawQkoTsQi9Ht3TkT9b+VzSEzSC5wZD1mukPFBK/oEQK+NReDcvNCg5LTSPv1caAQ=="
},
"wordwrap": {
"version": "1.0.0",
+1 -1
View File
@@ -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.147.3",
"windmill-parser-wasm": "^1.154.3",
"y-monaco": "^0.1.4",
"y-websocket": "^1.5.0",
"yjs": "^13.6.7"
@@ -1,6 +1,6 @@
<script lang="ts">
import { createEventDispatcher, getContext, onDestroy, tick } from 'svelte'
import type { AppInput, EvalAppInput, UploadAppInput } from '../../inputType'
import type { AppInput, EvalAppInput, EvalV2AppInput, UploadAppInput } from '../../inputType'
import type { AppViewerContext, ListContext, RichConfiguration } from '../../types'
import { accessPropertyByPath } from '../../utils'
import { computeGlobalContext, eval_like } from './eval'
@@ -14,7 +14,6 @@
export let value: T
export let id: string | undefined = undefined
export let error: string = ''
export let extraContext: Record<string, any> = {}
export let key: string = ''
const { componentControl, runnableComponents } = getContext<AppViewerContext>('AppViewerContext')
@@ -22,25 +21,35 @@
const iterContext = getContext<ListContext>('ListWrapperContext')
const rowContext = getContext<ListContext>('RowWrapperContext')
let previousConnectedValue: any | undefined = undefined
let previousConnectedValues: Record<string, any> = {}
$: fullContext = {
...extraContext,
iter: iterContext ? $iterContext : undefined,
row: rowContext ? $rowContext : undefined
}
$: lastInput?.type == 'evalv2' &&
(fullContext.iter != undefined || fullContext.row != undefined) &&
lastInput.connections.some((x) => x.componentId == 'row' || x.componentId == 'iter') &&
debounceEval()
const dispatch = createEventDispatcher()
if (input == undefined) {
dispatch('done')
}
let lastInput = input ? JSON.parse(JSON.stringify(input)) : undefined
let lastInput: AppInput | undefined = input ? JSON.parse(JSON.stringify(input)) : undefined
onDestroy(() => (lastInput = undefined))
$: if (input && !deepEqualWithOrderedArray(input, lastInput)) {
lastInput = JSON.parse(JSON.stringify(input))
// Needed because of file uploads
if (input?.['value'] instanceof ArrayBuffer) {
if (lastInput && input?.['value'] instanceof ArrayBuffer) {
// @ts-ignore
lastInput.value = input?.['value']
}
}
@@ -55,7 +64,7 @@
const debounce_ms = 50
export async function computeExpr() {
value = await evalExpr(lastInput)
value = await evalExpr(lastInput as EvalAppInput)
return value
}
@@ -86,7 +95,7 @@
$: lastInput && $worldStore && debounce(handleConnection)
const debounceTemplate = async () => {
let nvalue = await getValue(lastInput)
let nvalue = await getValue(lastInput as EvalAppInput)
if (!deepEqual(nvalue, value)) {
value = nvalue
}
@@ -102,7 +111,7 @@
let lastExpr: any = undefined
const debounceEval = async () => {
let nvalue = await evalExpr(lastInput)
let nvalue = await evalExpr(lastInput as EvalAppInput)
if (!deepEqual(nvalue, value)) {
if (
typeof nvalue == 'string' ||
@@ -123,13 +132,39 @@
$: lastInput && lastInput.type == 'eval' && $stateId && $state && debounce2(debounceEval)
$: lastInput?.type == 'evalv2' && lastInput.expr && debounceEval()
async function handleConnection() {
if (lastInput?.type === 'connected') {
$worldStore?.connect<any>(lastInput, onValueChange, `${id}-${key}`, value)
if (lastInput.connection) {
const { path, componentId } = lastInput.connection
const [p] = path ? path.split('.')[0].split('[') : [undefined]
if (p) {
$worldStore?.connect<any>(
{ componentId: componentId, id: p },
onValueChange,
`${id}-${key}`,
previousConnectedValue
)
} else {
console.debug('path was invalid for connection', lastInput.connection)
}
}
} else if (lastInput?.type === 'static' || lastInput?.type == 'template') {
value = await getValue(lastInput)
} else if (lastInput?.type == 'eval') {
value = await evalExpr(lastInput as EvalAppInput)
} else if (lastInput?.type == 'evalv2') {
const input = lastInput as EvalV2AppInput
for (const c of input.connections ?? []) {
const previousValueKey = `${c.componentId}-${c.id}`
$worldStore?.connect<any>(
c,
onEvalChange(previousValueKey),
`${id}-${key}`,
previousConnectedValues[previousValueKey]
)
}
} else if (lastInput?.type == 'upload') {
value = (lastInput as UploadAppInput).value
} else {
@@ -140,6 +175,13 @@
dispatch('done')
}
function onEvalChange(previousValueKey: string) {
return (newValue) => {
previousConnectedValues[previousValueKey] = newValue
debounceEval()
}
}
async function evalExpr(input: EvalAppInput): Promise<any> {
if (iterContext && $iterContext.disabled) return
try {
@@ -201,6 +243,8 @@
return
}
previousConnectedValue = newValue
let { path }: { path: string } = connection
path = path.replace(/\[(\d+)\]/g, '.$1').replace(/\[\"(.*)\"\]/g, '.$1')
@@ -254,7 +254,7 @@ export function appComponentFromType<T extends keyof typeof components>(
return {
type,
//TODO remove tooltip and onlyStatic from there
//TODO remove tooltip from there
configuration: deepMergeWithPriority(configuration, overrideConfiguration ?? {}),
componentInput: init.componentInput,
panes: init.panes,
@@ -336,7 +336,6 @@ const onSuccessClick = {
type: 'static',
value: '',
placeholder: 'Hello there',
noVariablePicker: true
}
},
openModal: {
@@ -345,7 +344,6 @@ const onSuccessClick = {
fieldType: 'text',
type: 'static',
value: '',
noVariablePicker: true
}
},
closeModal: {
@@ -354,7 +352,6 @@ const onSuccessClick = {
fieldType: 'text',
type: 'static',
value: '',
noVariablePicker: true
}
}
}
@@ -442,7 +439,7 @@ const paginationOneOf = {
type: 'static',
fieldType: 'number',
value: 20,
onlyStatic: true,
tooltip: 'Number of rows per page'
}
},
@@ -666,21 +663,20 @@ export const components = {
style: {
fieldType: 'select',
type: 'static',
onlyStatic: true,
selectOptions: selectOptions.textStyleOptions,
value: 'Body' as 'Title' | 'Subtitle' | 'Body' | 'Label' | 'Caption'
},
copyButton: {
type: 'static',
value: false,
fieldType: 'boolean',
onlyStatic: true
fieldType: 'boolean'
},
tooltip: {
type: 'static',
value: '',
fieldType: 'text',
onlyStatic: true,
tooltip: 'Tooltip text if not empty'
}
}
@@ -720,14 +716,14 @@ export const components = {
size: {
fieldType: 'select',
type: 'static',
onlyStatic: true,
selectOptions: selectOptions.buttonSizeOptions,
value: 'xs'
},
fillContainer: {
fieldType: 'boolean',
type: 'static',
onlyStatic: true,
value: false,
tooltip:
'This will make the button fill the container width and height. Height and width can be overwritten with custom styles.'
@@ -740,20 +736,17 @@ export const components = {
beforeIcon: {
type: 'static',
value: undefined,
fieldType: 'icon-select',
onlyStatic: true
fieldType: 'icon-select'
},
afterIcon: {
type: 'static',
value: undefined,
fieldType: 'icon-select',
onlyStatic: true
fieldType: 'icon-select'
},
triggerOnAppLoad: {
type: 'static',
value: false,
fieldType: 'boolean',
onlyStatic: true
fieldType: 'boolean'
},
onSuccess: onSuccessClick,
onError: onErrorClick
@@ -800,27 +793,25 @@ export const components = {
size: {
fieldType: 'select',
type: 'static',
onlyStatic: true,
selectOptions: selectOptions.buttonSizeOptions,
value: 'xs'
},
fillContainer: {
fieldType: 'boolean',
type: 'static',
onlyStatic: true,
value: false
},
beforeIcon: {
type: 'static',
value: undefined,
fieldType: 'icon-select',
onlyStatic: true
fieldType: 'icon-select'
},
afterIcon: {
type: 'static',
value: undefined,
fieldType: 'icon-select',
onlyStatic: true
fieldType: 'icon-select'
}
}
}
@@ -859,7 +850,7 @@ export const components = {
fieldType: 'select',
type: 'static',
value: 'xs',
onlyStatic: true,
selectOptions: selectOptions.buttonSizeOptions
},
onSuccess: onSuccessClick,
@@ -890,8 +881,7 @@ export const components = {
modalTitle: {
type: 'static',
fieldType: 'text',
value: 'Modal title',
onlyStatic: true
value: 'Modal title'
},
label: {
type: 'static',
@@ -909,7 +899,7 @@ export const components = {
fieldType: 'select',
type: 'static',
value: 'xs',
onlyStatic: true,
selectOptions: selectOptions.buttonSizeOptions
},
onSuccess: onSuccessClick,
@@ -934,14 +924,14 @@ export const components = {
configuration: {
theme: {
type: 'static',
onlyStatic: true,
fieldType: 'select',
selectOptions: selectOptions.chartThemeOptions,
value: 'theme1'
},
doughnutStyle: {
type: 'static',
onlyStatic: true,
fieldType: 'boolean',
value: false
}
@@ -965,7 +955,7 @@ export const components = {
configuration: {
type: {
type: 'static',
onlyStatic: true,
fieldType: 'select',
selectOptions: selectOptions.chartTypeOptions,
value: 'pie'
@@ -1004,14 +994,14 @@ export const components = {
configuration: {
theme: {
type: 'static',
onlyStatic: true,
fieldType: 'select',
selectOptions: selectOptions.chartThemeOptions,
value: 'theme1'
},
line: {
type: 'static',
onlyStatic: true,
fieldType: 'boolean',
value: false
}
@@ -1070,7 +1060,7 @@ This is a paragraph.
type: 'static',
selectOptions: selectOptions.prose,
value: 'Default',
onlyStatic: true,
tooltip: 'See Tailwind documentation: https://tailwindcss.com/docs/typography-plugin'
}
}
@@ -1105,7 +1095,7 @@ This is a paragraph.
configuration: {
canvas: {
type: 'static',
onlyStatic: true,
fieldType: 'boolean',
value: false,
tooltip: 'Use the canvas renderer instead of the svg one for more interactive plots'
@@ -1141,8 +1131,7 @@ This is a paragraph.
fieldType: 'object',
value: {},
tooltip:
'Layout options for the plot. See https://plotly.com/javascript/reference/layout/ for more information',
onlyStatic: false
'Layout options for the plot. See https://plotly.com/javascript/reference/layout/ for more information'
}
}
}
@@ -1159,19 +1148,19 @@ This is a paragraph.
configuration: {
logarithmicScale: {
type: 'static',
onlyStatic: true,
fieldType: 'boolean',
value: false
},
zoomable: {
type: 'static',
onlyStatic: true,
fieldType: 'boolean',
value: false
},
pannable: {
type: 'static',
onlyStatic: true,
fieldType: 'boolean',
value: false
}
@@ -1233,13 +1222,13 @@ This is a paragraph.
configuration: {
zoomable: {
type: 'static',
onlyStatic: true,
fieldType: 'boolean',
value: false
},
pannable: {
type: 'static',
onlyStatic: true,
fieldType: 'boolean',
value: false
}
@@ -1287,7 +1276,7 @@ This is a paragraph.
search: {
fieldType: 'select',
type: 'static',
onlyStatic: true,
selectOptions: selectOptions.tableSearchOptions,
value: 'Disabled' as string,
tooltip:
@@ -1298,7 +1287,7 @@ This is a paragraph.
type: 'static',
fieldType: 'boolean',
value: true,
onlyStatic: true,
tooltip: 'display a button to download the table as a csv file'
},
initialState: {
@@ -1306,8 +1295,7 @@ This is a paragraph.
fieldType: 'object',
value: {},
tooltip:
'any configuration that can be passed to the tanstack table component as initial state (https://tanstack.com/table/v8/docs/api/core/table#initialstate)',
onlyStatic: true
'any configuration that can be passed to the tanstack table component as initial state (https://tanstack.com/table/v8/docs/api/core/table#initialstate)'
}
},
componentInput: {
@@ -1348,42 +1336,40 @@ This is a paragraph.
type: 'static',
fieldType: 'boolean',
value: true,
onlyStatic: true,
tooltip: 'default col flex is 1 (see ag-grid docs)'
},
allEditable: {
type: 'static',
fieldType: 'boolean',
value: false,
onlyStatic: true,
tooltip: 'Configure all columns as Editable by users'
},
multipleSelectable: {
type: 'static',
fieldType: 'boolean',
value: false,
onlyStatic: true,
tooltip: 'Make multiple rows selectable at once'
},
rowMultiselectWithClick: {
type: 'static',
fieldType: 'boolean',
value: true,
onlyStatic: true,
tooltip: 'If multiple selectable, allow multiselect with click'
},
pagination: {
type: 'static',
fieldType: 'boolean',
value: false,
onlyStatic: true
value: false
},
extraConfig: {
type: 'static',
fieldType: 'object',
value: {},
tooltip: 'any configuration that can be passed to ag-grid top level',
onlyStatic: true
tooltip: 'any configuration that can be passed to ag-grid top level'
}
},
componentInput: {
@@ -1451,8 +1437,7 @@ This is a paragraph.
placeholder: {
type: 'static',
value: 'Type...',
fieldType: 'text',
onlyStatic: true
fieldType: 'text'
},
defaultValue: {
type: 'static',
@@ -1476,8 +1461,7 @@ This is a paragraph.
placeholder: {
type: 'static',
value: 'Type...',
fieldType: 'text',
onlyStatic: true
fieldType: 'text'
},
defaultValue: {
type: 'static',
@@ -1501,8 +1485,7 @@ This is a paragraph.
placeholder: {
type: 'static',
value: 'Type...',
fieldType: 'text',
onlyStatic: true
fieldType: 'text'
},
defaultValue: {
type: 'static',
@@ -1541,15 +1524,14 @@ This is a paragraph.
type: 'static',
fieldType: 'boolean',
value: false,
onlyStatic: true,
tooltip: 'Allows user to manually add new value',
customTitle: 'User creatable'
},
placeholder: {
type: 'static',
fieldType: 'text',
value: 'Select an item',
onlyStatic: true
value: 'Select an item'
},
disabled: {
fieldType: 'boolean',
@@ -1565,14 +1547,14 @@ This is a paragraph.
type: 'static',
value: true,
fieldType: 'boolean',
onlyStatic: true,
tooltip: 'Preselect first item in the options if no default value is set'
},
fullWidth: {
type: 'static',
fieldType: 'boolean',
value: true,
onlyStatic: true,
tooltip: 'Set the width of the options popup to 100% of the select width'
}
}
@@ -1608,14 +1590,13 @@ This is a paragraph.
placeholder: {
type: 'static',
fieldType: 'text',
value: 'Select items',
onlyStatic: true
value: 'Select items'
},
create: {
type: 'static',
fieldType: 'boolean',
value: false,
onlyStatic: true,
tooltip: 'Allows user to manually add new value',
customTitle: 'User creatable'
},
@@ -1623,7 +1604,7 @@ This is a paragraph.
type: 'static',
fieldType: 'boolean',
value: true,
onlyStatic: true,
tooltip:
'If too many items, the box overflow its container instead of having an internal scroll'
}
@@ -1651,14 +1632,13 @@ This is a paragraph.
placeholder: {
type: 'static',
fieldType: 'text',
value: 'Select an item',
onlyStatic: true
value: 'Select an item'
},
fullWidth: {
type: 'static',
fieldType: 'boolean',
value: true,
onlyStatic: true,
tooltip: 'Set the width of the options popup to 100% of the select width'
}
}
@@ -1679,8 +1659,7 @@ This is a paragraph.
placeholder: {
type: 'static',
value: 'Type...',
fieldType: 'text',
onlyStatic: true
fieldType: 'text'
},
defaultValue: {
type: 'static',
@@ -1726,21 +1705,20 @@ This is a paragraph.
isNegativeAllowed: {
type: 'static',
value: false,
fieldType: 'boolean',
onlyStatic: true
fieldType: 'boolean'
},
currency: {
type: 'static',
value: 'USD',
fieldType: 'select',
onlyStatic: true,
selectOptions: selectOptions.currencyOptions
},
locale: {
type: 'static',
value: 'en-US',
fieldType: 'select',
onlyStatic: true,
selectOptions: selectOptions.localeOptions,
tooltip: 'Currency format'
}
@@ -1786,8 +1764,7 @@ This is a paragraph.
vertical: {
type: 'static',
fieldType: 'boolean',
value: false,
onlyStatic: true
value: false
}
}
}
@@ -1837,7 +1814,7 @@ This is a paragraph.
type: 'static',
value: false,
fieldType: 'boolean',
onlyStatic: true,
tooltip:
'Determine if the slider is disabled, or enabled (only disables interactions, and events)'
}
@@ -1859,8 +1836,7 @@ This is a paragraph.
placeholder: {
type: 'static',
value: 'Password',
fieldType: 'text',
onlyStatic: true
fieldType: 'text'
}
}
}
@@ -1880,8 +1856,7 @@ This is a paragraph.
placeholder: {
type: 'static',
value: 'Email',
fieldType: 'text',
onlyStatic: true
fieldType: 'text'
},
defaultValue: {
type: 'static',
@@ -1942,7 +1917,7 @@ This is a paragraph.
tabsKind: {
fieldType: 'select',
type: 'static',
onlyStatic: true,
selectOptions: selectOptions.tabsKindOptions,
value: 'tabs' as string,
tooltip: `Tabs can be configured to be either horizontal (tabs), vertical (sidebar), or invisible.`
@@ -1986,7 +1961,7 @@ This is a paragraph.
timingFunction: {
fieldType: 'select',
type: 'static',
onlyStatic: true,
selectOptions: selectOptions.animationTimingFunctionOptions,
value: 'linear',
tooltip: 'See https://developer.mozilla.org/en-US/docs/Web/CSS/animation-timing-function'
@@ -2031,14 +2006,12 @@ This is a paragraph.
size: {
type: 'static',
value: 24,
fieldType: 'number',
onlyStatic: true
fieldType: 'number'
},
strokeWidth: {
type: 'static',
value: 2,
fieldType: 'number',
onlyStatic: true
fieldType: 'number'
}
}
}
@@ -2064,7 +2037,7 @@ This is a paragraph.
type: 'static',
value: 2,
fieldType: 'number',
onlyStatic: true,
tooltip:
'The height of the divider in pixels can be overridden by the `height` property in the styling menu'
},
@@ -2072,7 +2045,7 @@ This is a paragraph.
type: 'static',
value: '#00000060',
fieldType: 'color',
onlyStatic: true,
tooltip:
'The color of the divider can be overridden by the `background-color` property in the styling menu'
}
@@ -2096,7 +2069,7 @@ This is a paragraph.
type: 'static',
value: 2,
fieldType: 'number',
onlyStatic: true,
tooltip:
'The width of the divider in pixels can be overridden by the `width` property in the styling menu'
},
@@ -2104,7 +2077,7 @@ This is a paragraph.
type: 'static',
value: '#00000060',
fieldType: 'color',
onlyStatic: true,
tooltip:
'The color of the divider can be overridden by the `background-color` property in the styling menu'
}
@@ -2125,28 +2098,24 @@ This is a paragraph.
acceptedFileTypes: {
type: 'static',
value: ['image/*', 'application/pdf'] as string[],
fieldType: 'array',
onlyStatic: true
fieldType: 'array'
},
allowMultiple: {
type: 'static',
value: false,
fieldType: 'boolean',
tooltip: 'If allowed, the user will be able to select more than one file',
onlyStatic: true
tooltip: 'If allowed, the user will be able to select more than one file'
},
text: {
type: 'static',
value: 'Drag and drop files or click to select them',
fieldType: 'text',
onlyStatic: true
fieldType: 'text'
},
includeMimeType: {
type: 'static',
value: false,
fieldType: 'boolean',
tooltip: 'If enabled, the mime type of the file will be included.',
onlyStatic: true
tooltip: 'If enabled, the mime type of the file will be included.'
}
}
}
@@ -2174,7 +2143,7 @@ This is a paragraph.
imageFit: {
fieldType: 'select',
type: 'static',
onlyStatic: true,
selectOptions: selectOptions.objectFitOptions,
value: 'contain',
tooltip:
@@ -2184,7 +2153,7 @@ This is a paragraph.
type: 'static',
value: '',
fieldType: 'text',
onlyStatic: true,
tooltip: "This text will appear if the image can't be loaded for any reason"
}
}
@@ -2206,8 +2175,7 @@ This is a paragraph.
drawerTitle: {
type: 'static',
fieldType: 'text',
value: 'Drawer title',
onlyStatic: false
value: 'Drawer title'
},
label: {
type: 'static',
@@ -2225,14 +2193,14 @@ This is a paragraph.
size: {
fieldType: 'select',
type: 'static',
onlyStatic: true,
selectOptions: selectOptions.buttonSizeOptions,
value: 'xs'
},
fillContainer: {
fieldType: 'boolean',
type: 'static',
onlyStatic: true,
value: false,
tooltip:
'This will make the button fill the container width and height. Height and width can be overwritten with custom styles.'
@@ -2377,8 +2345,7 @@ This is a paragraph.
modalTitle: {
type: 'static',
fieldType: 'text',
value: 'Modal title',
onlyStatic: true
value: 'Modal title'
},
buttonLabel: {
type: 'static',
@@ -2388,7 +2355,7 @@ This is a paragraph.
buttonColor: {
fieldType: 'select',
type: 'static',
onlyStatic: true,
selectOptions: buttonColorOptions,
value: 'blue',
tooltip: 'Theses presets can be overwritten with custom styles.'
@@ -2396,14 +2363,14 @@ This is a paragraph.
buttonSize: {
fieldType: 'select',
type: 'static',
onlyStatic: true,
selectOptions: selectOptions.buttonSizeOptions,
value: 'xs'
},
buttonFillContainer: {
fieldType: 'boolean',
type: 'static',
onlyStatic: true,
value: false,
tooltip:
'This will make the button fill the container width and height. Height and width can be overwritten with custom styles.'
@@ -2448,14 +2415,14 @@ This is a paragraph.
fieldType: 'boolean',
type: 'static',
value: false,
onlyStatic: true,
tooltip: 'This will diplay the type and/or the format on the field next to the label.'
},
largeGap: {
fieldType: 'boolean',
type: 'static',
value: false,
onlyStatic: true,
tooltip: 'This will add a large gap between the form elements.'
}
}
@@ -45,7 +45,7 @@
$selectedComponent = [id]
}}
title="Edit ID"
class="flex items-center px-1 rounded-sm bg-surface-secondary hover:text-primary text-secondary"
class="flex items-center px-1 rounded-sm bg-surface-secondary hover:text-primary text-secondary h-5"
aria-label="Open component ID editor"
>
<Pencil size={14} />
@@ -209,11 +209,13 @@
{/if}
</button>
{#if selectable && renamable && ($selectedComponent?.includes(id) || $hoverStore === id)}
<IdEditor
{id}
on:selected={() => ($selectedComponent = [id])}
on:change={({ detail }) => renameId(detail)}
/>
<div class="h-3">
<IdEditor
{id}
on:selected={() => ($selectedComponent = [id])}
on:change={({ detail }) => renameId(detail)}
/></div
>
{/if}
</div>
<div class="text-2xs font-bold flex flex-row gap-2 items-center truncate">
@@ -5,11 +5,11 @@
import type { AppViewerContext, InlineScript } from '../../types'
import { Maximize2, Trash2 } from 'lucide-svelte'
import InlineScriptEditorDrawer from './InlineScriptEditorDrawer.svelte'
import { inferArgs } from '$lib/infer'
import { inferArgs, parseOutputs } from '$lib/infer'
import type { Schema } from '$lib/common'
import Badge from '$lib/components/common/badge/Badge.svelte'
import Editor from '$lib/components/Editor.svelte'
import { defaultIfEmptyString, emptySchema, getModifierKey } from '$lib/utils'
import { defaultIfEmptyString, emptySchema, getModifierKey, itemsExists } from '$lib/utils'
import { computeFields } from './utils'
import { deepEqual } from 'fast-equals'
import type { AppInput } from '../../inputType'
@@ -75,6 +75,9 @@
if (inlineScript?.schema && inlineScript.language != 'frontend') {
loadSchemaAndInputsByName()
}
if (inlineScript?.language == 'frontend' && inlineScript.content) {
inferSuggestions(inlineScript.content)
}
})
const dispatch = createEventDispatcher()
@@ -126,6 +129,25 @@
: undefined
let drawerIsOpen: boolean | undefined = undefined
async function inferSuggestions(code: string) {
const outputs = await parseOutputs(code, true)
if (outputs) {
for (const [key, id] of outputs) {
if (
id in ($worldStore?.outputsById[key] ?? {}) &&
inlineScript &&
!itemsExists(inlineScript.refreshOn, { key, id }) &&
!itemsExists(inlineScript.suggestedRefreshOn, { key, id })
) {
inlineScript.suggestedRefreshOn = [
...(inlineScript?.suggestedRefreshOn ?? []),
{ key, id }
]
}
}
}
}
</script>
{#if inlineScript}
@@ -262,7 +284,8 @@
)
runLoading = false
}}
on:change={() => {
on:change={async (e) => {
inferSuggestions(e.detail.code)
$app = $app
}}
/>
@@ -178,7 +178,6 @@
subFieldType={componentInput?.subFieldType}
format={componentInput?.format}
bind:componentInput={componentSettings.item.data.componentInput}
noVariablePicker
/>
{:else if componentSettings.item.data.componentInput.type === 'template' && componentSettings.item.data.componentInput !== undefined}
<div class="py-1 min-h-[28px] rounded border border-1 border-gray-500">
@@ -162,12 +162,10 @@
format={condition?.['format']}
selectOptions={condition?.['selectOptions']}
tooltip={condition?.['tooltip']}
onlyStatic={condition?.['onlyStatic']}
fileUpload={condition?.['fileUpload']}
placeholder={condition?.['placeholder']}
customTitle={condition?.['customTitle']}
displayType={false}
noVariablePicker={true}
/>
</div>
@@ -47,12 +47,10 @@
format={field?.['format']}
selectOptions={field?.['selectOptions']}
tooltip={field?.['tooltip']}
onlyStatic={field?.['onlyStatic']}
fileUpload={field?.['fileUpload']}
placeholder={field?.['placeholder']}
customTitle={field?.['customTitle']}
displayType={false}
noVariablePicker={true}
/>
</div>
{/if}
@@ -14,6 +14,7 @@
import ToggleButton from '$lib/components/common/toggleButton-v2/ToggleButton.svelte'
import { FunctionSquare, Pen, Plug2, Upload, User } from 'lucide-svelte'
import { fieldTypeToTsType } from '../../utils'
import EvalV2InputEditor from './inputEditor/EvalV2InputEditor.svelte'
export let id: string
export let componentInput: RichConfiguration
@@ -22,7 +23,6 @@
export let shouldCapitalize: boolean = true
export let resourceOnly = false
export let tooltip: string | undefined = undefined
export let onlyStatic: boolean = false
export let fieldType: InputType
export let subFieldType: InputType | undefined
export let format: string | undefined
@@ -31,7 +31,6 @@
export let placeholder: string | undefined
export let customTitle: string | undefined = undefined
export let displayType: boolean = false
export let noVariablePicker: boolean | undefined = undefined
const { connectingInput, app } = getContext<AppViewerContext>('AppViewerContext')
@@ -52,12 +51,7 @@
</script>
{#if !(resourceOnly && (fieldType !== 'object' || !format?.startsWith('resource-')))}
<div
class={classNames(
'flex gap-1',
onlyStatic && fieldType != 'object' ? 'flex-row items-center justify-between' : 'flex-col'
)}
>
<div class={classNames('flex gap-1', 'flex-col')}>
<div class="flex justify-between items-end">
<div class="flex flex-row gap-4 items-center">
<span class="text-xs font-semibold truncate text-primary">
@@ -82,7 +76,7 @@
</div>
<div class={classNames('flex gap-x-2 gap-y-1 flex-wrap justify-end items-center')}>
{#if !onlyStatic && componentInput?.type}
{#if componentInput?.type}
<ToggleButtonGroup
class="h-7"
bind:selected={componentInput.type}
@@ -111,7 +105,10 @@
<ToggleButton value="upload" icon={Upload} iconOnly tooltip="Upload" />
{/if}
<ToggleButton value="connected" icon={Plug2} iconOnly tooltip="Connect" />
<ToggleButton value="eval" icon={FunctionSquare} iconOnly tooltip="Eval" />
{#if componentInput?.type === 'eval'}
<ToggleButton value="eval" icon={FunctionSquare} iconOnly tooltip="Eval Legacy" />
{/if}
<ToggleButton value="evalv2" icon={FunctionSquare} iconOnly tooltip="Eval" />
</ToggleButtonGroup>
{/if}
</div>
@@ -122,23 +119,20 @@
{:else if componentInput?.type === 'row'}
<RowInputEditor bind:componentInput />
{:else if componentInput?.type === 'static'}
<div
class={onlyStatic && fieldType != 'object'
? 'w-2/3 flex justify-end'
: 'w-full flex flex-row-reverse'}
>
<div class={'w-full flex flex-row-reverse'}>
<StaticInputEditor
{fieldType}
{subFieldType}
{selectOptions}
{format}
{placeholder}
noVariablePicker={noVariablePicker ?? false}
bind:componentInput
/>
</div>
{:else if componentInput?.type === 'eval'}
<EvalInputEditor {id} bind:componentInput />
{:else if componentInput?.type === 'evalv2'}
<EvalV2InputEditor {id} bind:componentInput />
{:else if componentInput?.type === 'upload'}
<UploadInputEditor bind:componentInput {fileUpload} />
{:else if componentInput?.type === 'user'}
@@ -43,11 +43,9 @@
format={meta?.['format']}
selectOptions={meta?.['selectOptions']}
tooltip={meta?.['tooltip']}
onlyStatic={meta?.['onlyStatic']}
fileUpload={meta?.['fileUpload']}
placeholder={meta?.['placeholder']}
customTitle={meta?.['customTitle']}
noVariablePicker={meta?.['noVariablePicker']}
{displayType}
/>
{/if}
@@ -77,9 +77,7 @@
format={config?.['format']}
selectOptions={config?.['selectOptions']}
placeholder={config?.['placeholder']}
onlyStatic={config?.['onlyStatic']}
customTitle={config?.['customTitle']}
noVariablePicker={config?.['noVariablePicker']}
tooltip={config?.['tooltip']}
/>
{/if}
@@ -15,8 +15,4 @@
$: fakeComponentInput && (value = fakeComponentInput.value)
</script>
<StaticInputEditor
noVariablePicker
fieldType={subFieldType}
bind:componentInput={fakeComponentInput}
/>
<StaticInputEditor fieldType={subFieldType} bind:componentInput={fakeComponentInput} />
@@ -0,0 +1,80 @@
<script lang="ts">
import type { EvalV2AppInput } from '../../../inputType'
import { getContext } from 'svelte'
import type { AppViewerContext } from '$lib/components/apps/types'
import SimpleEditor from '$lib/components/SimpleEditor.svelte'
import { buildExtraLib } from '$lib/components/apps/utils'
import { parseOutputs } from '$lib/infer'
import { deepEqual } from 'fast-equals'
export let componentInput: EvalV2AppInput | undefined
export let id: string
const { onchange, worldStore, state, app } = getContext<AppViewerContext>('AppViewerContext')
$: extraLib =
componentInput?.expr && $worldStore
? buildExtraLib($worldStore?.outputsById ?? {}, id, $state, false)
: undefined
if (
componentInput &&
componentInput.expr &&
componentInput.expr != '' &&
componentInput.connections == undefined
) {
inferDeps(componentInput.expr)
}
if (componentInput && componentInput.connections == undefined) {
componentInput.connections = []
}
async function inferDeps(code: string) {
const outputs = await parseOutputs(code, true)
if (outputs && componentInput) {
const noutputs = outputs
.filter(
([key, id]) =>
key == 'row' || key == 'iter' || id in ($worldStore?.outputsById[key] ?? {})
)
.map(([key, id]) => ({
componentId: key,
id: id
}))
if (!deepEqual(noutputs, componentInput.connections)) {
componentInput.connections = noutputs
$app = $app
}
}
}
</script>
{#if componentInput?.type === 'evalv2'}
<div class="border">
<SimpleEditor
lang="javascript"
bind:code={componentInput.expr}
shouldBindKey={false}
{extraLib}
autoHeight
on:change={async (e) => {
if (onchange) {
onchange()
}
inferDeps(e.detail.code)
}}
/>
</div>
{#if componentInput.connections.length > 0}
<div class="mt-2">
<div class="text-sm font-medium text-secondary">Automatically connected to</div>
<div class="mt-1 flex flex-wrap gap-1">
{#each componentInput.connections as connection (connection.componentId + '-' + connection.id)}
<span class="inline-flex items-center rounded-md px-2 py-0.5 text-xs font-medium border"
>{connection.componentId + '.' + connection.id}</span
>
{/each}
</div>
</div>
{/if}
{/if}
@@ -4,11 +4,10 @@
import ResourcePicker from '$lib/components/ResourcePicker.svelte'
import JsonEditor from './JsonEditor.svelte'
import { getContext } from 'svelte'
import type { AppEditorContext, AppViewerContext } from '$lib/components/apps/types'
import type { AppViewerContext } from '$lib/components/apps/types'
import IconSelectInput from './IconSelectInput.svelte'
import ColorInput from './ColorInput.svelte'
import TabSelectInput from './TabSelectInput.svelte'
import { DollarSign } from 'lucide-svelte'
import Toggle from '$lib/components/Toggle.svelte'
import SchemaEditor from '$lib/components/SchemaEditor.svelte'
import autosize from 'svelte-autosize'
@@ -20,10 +19,8 @@
export let placeholder: string | undefined = undefined
export let format: string | undefined = undefined
export let noVariablePicker: boolean = false
const { onchange } = getContext<AppViewerContext>('AppViewerContext')
const { pickVariableCallback } = getContext<AppEditorContext>('AppEditorContext')
$: componentInput && onchange?.()
</script>
@@ -126,22 +123,6 @@
bind:value={componentInput.value}
class="!pr-12"
/>
{#if !noVariablePicker}
<!-- svelte-ignore a11y-click-events-have-key-events -->
<button
class="absolute right-1 top-1 py-1 min-w-min !px-2 items-center text-gray-800 bg-gray-100 border rounded center-center hover:bg-gray-300 transition-all cursor-pointer"
on:click={() => {
$pickVariableCallback = (variable) => {
if (componentInput) {
componentInput.value = `$var:${variable}`
}
}
}}
title="Use a Variable"
>
<DollarSign size={14} />
</button>
{/if}
</div>
{/if}
{/if}
@@ -1,12 +1,13 @@
<script lang="ts">
import type { InputConnection } from '$lib/components/apps/inputType'
import Alert from '$lib/components/common/alert/Alert.svelte'
import { classNames } from '$lib/utils'
import { classNames, itemsExists } from '$lib/utils'
import { Plus, X } from 'lucide-svelte'
import { Button } from '$lib/components/common'
import { getContext } from 'svelte'
import type { AppViewerContext, InlineScript } from '$lib/components/apps/types'
import Tooltip from '$lib/components/Tooltip.svelte'
import { deepEqual } from 'fast-equals'
export let triggerEvents: string[] = []
export let inlineScript: InlineScript | undefined = undefined
@@ -47,37 +48,14 @@
if (!inlineScript.refreshOn) {
inlineScript.refreshOn = [refresh]
} else {
inlineScript.refreshOn.push(refresh)
} else if (!itemsExists(inlineScript.refreshOn, refresh)) {
inlineScript.refreshOn = [...inlineScript.refreshOn, refresh]
}
inlineScript = JSON.parse(JSON.stringify(inlineScript))
inlineScript = inlineScript
$app = $app
}
</script>
{#if isFrontend && shoudlDisplayChangeEvents}
<div class="flex mb-4">
<Button
size="xs2"
color="dark"
on:click={() => {
$connectingInput = {
opened: true,
input: undefined,
hoveredComponent: undefined,
onConnect: applyConnection
}
}}
>
<div class="flex flex-row gap-1 items-center">
<Plus size={14} />
Add dependency
</div>
</Button>
</div>
{/if}
{#if hasNoTriggers}
<Alert type="warning" title="No triggers" size="xs">
This script has no triggers. It will never run.
@@ -112,7 +90,17 @@
inlineScript.refreshOn = inlineScript.refreshOn.filter(
(x) => `${x.id} - ${x.key}` !== changeEvent
)
inlineScript = JSON.parse(JSON.stringify(inlineScript))
const ch = changeEvent.split(' - ')
const suggestion = {
id: ch[0],
key: ch[1]
}
if (!itemsExists(inlineScript.suggestedRefreshOn, suggestion)) {
inlineScript.suggestedRefreshOn = [
...(inlineScript.suggestedRefreshOn ?? []),
suggestion
]
}
}
}}
>
@@ -124,3 +112,49 @@
</div>
{/if}
{/if}
{#if isFrontend && shoudlDisplayChangeEvents}
<div class="flex my-4">
<Button
size="xs2"
color="dark"
on:click={() => {
$connectingInput = {
opened: true,
input: undefined,
hoveredComponent: undefined,
onConnect: applyConnection
}
}}
>
<div class="flex flex-row gap-1 items-center">
<Plus size={14} />
Add dependency
</div>
</Button>
</div>
{#if (inlineScript?.suggestedRefreshOn ?? []).length > 0}
<div class="gap-1 flex flex-wrap mb-2"
><span class="text-secondary text-sm">Quick add:</span>
{#each inlineScript?.suggestedRefreshOn ?? [] as suggestion}
<button
class={classNames(
'p-0.5 rounded-md hover:bg-blue-400 cursor-pointer !text-2xs text-secondary',
badgeClass
)}
on:click={() => {
if (inlineScript) {
if (!itemsExists(inlineScript.refreshOn, suggestion)) {
inlineScript.refreshOn = [...(inlineScript.refreshOn ?? []), suggestion]
inlineScript.suggestedRefreshOn = inlineScript.suggestedRefreshOn?.filter(
(x) => !deepEqual(x, suggestion)
)
}
}
}}
>
+{suggestion.key}-{suggestion.id}
</button>
{/each}
</div>
{/if}
{/if}
@@ -29,6 +29,11 @@ export type InputConnection = {
path: string
}
export type InputConnectionEval = {
componentId: string
id: string
}
// Connected input, connected to an output of another component by the developer
export type ConnectedInput = {
type: 'connected'
@@ -52,6 +57,12 @@ export type EvalInput = {
expr: string
}
export type EvalInputV2 = {
type: 'evalv2'
expr: string
connections: InputConnectionEval[]
}
export type RowInput = {
type: 'row'
column: string
@@ -104,6 +115,7 @@ export type AppInputSpec<T extends InputType, U, V extends InputType = never> =
| UserInput<U>
| RowInput
| EvalInput
| EvalInputV2
| UploadInput
| ResultInput
| TemplateInput
@@ -171,6 +183,7 @@ export type ConnectedAppInput = Extract<AppInput, { type: 'connected' }>
export type UserAppInput = Extract<AppInput, { type: 'user' }>
export type ResultAppInput = Extract<AppInput, { type: 'runnable' }>
export type EvalAppInput = Extract<AppInput, { type: 'eval' }>
export type EvalV2AppInput = Extract<AppInput, { type: 'evalv2' }>
export type UploadAppInput = Extract<AppInput, { type: 'upload' }>
export type RichAppInput =
+24 -41
View File
@@ -1,4 +1,4 @@
import type { AppInput } from './inputType'
import type { InputConnectionEval } from './inputType'
import { writable, type Writable } from 'svelte/store'
import { deepEqual } from 'fast-equals'
@@ -22,7 +22,7 @@ export interface Input<T> extends Subscriber<T> {
export type World = {
outputsById: Record<string, Record<string, Output<any>>>
connect: <T>(
inputSpec: AppInput,
connection: InputConnectionEval,
next: (x: T) => void,
id: string,
previousValue: any
@@ -70,54 +70,37 @@ export function buildObservableWorld() {
const observables: Record<string, Output<any>> = {}
function connect<T>(
inputSpec: AppInput,
connection: InputConnectionEval,
next: (x: T) => void,
id: string,
previousValue: T
): Input<T> {
if (inputSpec.type === 'static') {
if (!connection) {
return {
id,
peak: () => inputSpec.value,
peak: () => undefined,
next: () => {}
}
} else if (inputSpec.type === 'connected') {
const connection = inputSpec.connection
if (!connection) {
return {
id,
peak: () => undefined,
next: () => {}
}
}
const { componentId, path } = connection
const input = cachedInput(next, `${componentId}-${path}-${id}`)
const [p] = path ? path.split('.')[0].split('[') : [undefined]
let obs = observables[`${componentId}.${p}`]
if (!obs) {
console.warn('Observable at ' + componentId + '.' + p + ' not found')
return {
peak: () => undefined,
next: () => {}
}
}
obs.subscribe(input, previousValue)
return input
} else if (inputSpec.type === 'user') {
return {
id,
peak: () => inputSpec.value,
next: () => {}
}
} else {
throw Error('Unknown input type ' + inputSpec)
}
const input = cachedInput(next, id)
const { componentId, id: idc } = connection
let obs = observables[`${componentId}.${idc}`]
if (!obs) {
if (componentId != 'row' && componentId != 'iter') {
console.warn('Observable at ' + componentId + '.' + idc + ' not found')
}
return {
peak: () => undefined,
next: () => {}
}
}
obs.subscribe(input, previousValue)
return input
}
function newOutput<T>(
+3 -1
View File
@@ -14,6 +14,7 @@ import type {
ConnectedAppInput,
ConnectedInput,
EvalAppInput,
EvalV2AppInput,
InputConnection,
ResultAppInput,
RowAppInput,
@@ -34,7 +35,6 @@ export type Aligned = {
}
export interface GeneralAppInput {
onlyStatic?: boolean
tooltip?: string
placeholder?: string
customTitle?: string
@@ -55,6 +55,7 @@ export type Configuration =
| UserAppInput
| RowAppInput
| EvalAppInput
| EvalV2AppInput
| UploadAppInput
| ResultAppInput
@@ -106,6 +107,7 @@ export type InlineScript = {
path?: string
schema?: Schema
refreshOn?: { id: string; key: string }[]
suggestedRefreshOn?: { id: string; key: string }[]
}
export type AppCssItemName = 'viewer' | 'grid' | AppComponent['type']
@@ -135,8 +135,10 @@
{/if}
{:else if topBrackets}
<span class="text-primary">{openBracket}{closeBracket}</span>
{:else if json == undefined}
<span class="text-tertiary text-2xs ml-2">undefined</span>
{:else}
<span class="text-tertiary text-xs ml-2">No items ([])</span>
<span class="text-tertiary text-2xs ml-2">No items ([])</span>
{/if}
<style lang="postcss">
+18 -1
View File
@@ -13,7 +13,8 @@ import init, {
parse_bigquery,
parse_snowflake,
parse_graphql,
parse_powershell
parse_powershell,
parse_outputs
} from 'windmill-parser-wasm'
import wasmUrl from 'windmill-parser-wasm/windmill_parser_wasm_bg.wasm?url'
import { workspaceStore } from './stores.js'
@@ -269,3 +270,19 @@ export async function loadSchema(
return { schema: script.schema, summary: script.summary }
}
}
export async function parseOutputs(
code: string,
ignoreError
): Promise<[string, string][] | undefined> {
await init(wasmUrl)
const getOutputs = await parse_outputs(code)
const outputs = JSON.parse(getOutputs)
if (outputs.error) {
if (ignoreError) {
return undefined
}
throw new Error(outputs.error)
}
return outputs.error ? [] : outputs.outputs
}
+13
View File
@@ -7,6 +7,7 @@
// import { page } from '$app/stores'
// import { get } from 'svelte/store'
import { deepEqual } from 'fast-equals'
import type { UserExt } from './stores'
import { sendUserToast } from './toast'
export { sendUserToast }
@@ -172,6 +173,18 @@ export function decodeState(query: string): any {
return JSON.parse(decodeURIComponent(atob(query)))
}
export function itemsExists<T>(arr: T[] | undefined, item: T): boolean {
if (!arr) {
return false
}
for (const i of arr) {
if (deepEqual(i, item)) {
return true
}
}
return false
}
export function decodeArgs(queryArgs: string | undefined): any {
if (queryArgs) {
const parsed = decodeState(queryArgs)
@@ -162,7 +162,7 @@
{/if}
{#if schema}
<SchemaForm bind:isValid={valid} {schema} bind:args={payload} noVariablePicker />
<SchemaForm bind:isValid={valid} {schema} bind:args={payload} />
{/if}
<div class="w-max-md flex flex-row gap-x-4 gap-y-4 justify-between w-full flex-wrap mt-2">