Compare commits
1 commit
Author | SHA1 | Date | |
---|---|---|---|
43e334ad25 |
32 changed files with 3476 additions and 382 deletions
8
.swcrc
8
.swcrc
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"jsc": {
|
||||
"parser": {
|
||||
"syntax": "typescript"
|
||||
},
|
||||
"target": "es2021"
|
||||
}
|
||||
}
|
214
Cargo.lock
generated
214
Cargo.lock
generated
|
@ -41,8 +41,8 @@ version = "0.1.51"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44318e776df68115a881de9a8fd1b9e53368d7a4a5ce4cc48517da3393233a5e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.30",
|
||||
"quote 1.0.10",
|
||||
"syn",
|
||||
]
|
||||
|
||||
|
@ -118,8 +118,8 @@ dependencies = [
|
|||
"lazy_static",
|
||||
"lazycell",
|
||||
"peeking_take_while",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.30",
|
||||
"quote 1.0.10",
|
||||
"regex",
|
||||
"rustc-hash",
|
||||
"shlex",
|
||||
|
@ -200,6 +200,12 @@ dependencies = [
|
|||
"nom 6.1.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
|
@ -212,7 +218,7 @@ version = "0.8.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "01b72a433d0cf2aef113ba70f62634c56fddb0f244e6377185c56a7cadbd8f91"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"cipher",
|
||||
"cpufeatures",
|
||||
"zeroize",
|
||||
|
@ -291,8 +297,8 @@ checksum = "0b5bb0d655624a0b8770d1c178fb8ffcb1f91cc722cb08f451e3dc72465421ac"
|
|||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.30",
|
||||
"quote 1.0.10",
|
||||
"syn",
|
||||
]
|
||||
|
||||
|
@ -302,7 +308,7 @@ version = "0.1.7"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
|
@ -330,7 +336,7 @@ version = "0.8.28"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "80df024fbc5ac80f87dfef0d9f5209a252f2a497f7f42944cff24d8253cac065"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -361,6 +367,12 @@ version = "1.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7"
|
||||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.1.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678"
|
||||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.17"
|
||||
|
@ -417,8 +429,8 @@ checksum = "18e4a4b95cea4b4ccbcf1c5675ca7c4ee4e9e75eb79944d07defde18068f79bb"
|
|||
dependencies = [
|
||||
"autocfg",
|
||||
"proc-macro-hack",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.30",
|
||||
"quote 1.0.10",
|
||||
"syn",
|
||||
]
|
||||
|
||||
|
@ -471,7 +483,7 @@ version = "0.2.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"js-sys",
|
||||
"libc",
|
||||
"wasi",
|
||||
|
@ -712,7 +724,7 @@ version = "0.7.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0cf036d15402bea3c5d4de17b3fce76b3e4a56ebc1f577be0e7a72f7c607cf0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
|
@ -734,7 +746,7 @@ version = "0.4.14"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -881,6 +893,7 @@ dependencies = [
|
|||
"sha2",
|
||||
"thiserror",
|
||||
"url",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
|
@ -903,26 +916,6 @@ dependencies = [
|
|||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "omegaupload-web"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"byte-unit",
|
||||
"bytes",
|
||||
"console_error_panic_hook",
|
||||
"getrandom",
|
||||
"gloo-console",
|
||||
"http",
|
||||
"js-sys",
|
||||
"omegaupload-common",
|
||||
"reqwasm",
|
||||
"tree_magic_mini",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.8.0"
|
||||
|
@ -978,8 +971,8 @@ version = "1.0.8"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e8fe8163d14ce7f0cdac2e040116f22eac817edabff0be91e8aff7e9accf389"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.30",
|
||||
"quote 1.0.10",
|
||||
"syn",
|
||||
]
|
||||
|
||||
|
@ -1019,8 +1012,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.30",
|
||||
"quote 1.0.10",
|
||||
"syn",
|
||||
"version_check",
|
||||
]
|
||||
|
@ -1031,8 +1024,8 @@ version = "1.0.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.30",
|
||||
"quote 1.0.10",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
|
@ -1048,13 +1041,31 @@ version = "0.1.7"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "0.4.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
|
||||
dependencies = [
|
||||
"unicode-xid 0.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "edc3358ebc67bc8b7fa0c007f945b0b18226f78437d61bec735a9eb96b61ee70"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
"unicode-xid 0.2.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "0.6.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.30",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1063,7 +1074,7 @@ version = "1.0.10"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"proc-macro2 1.0.30",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1145,13 +1156,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "e34bf31941fb867ae9386a4b443b388e6713574944e6517136ee21a6a93cf996"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"futures",
|
||||
"futures 0.3.17",
|
||||
"js-sys",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"wasm-bindgen-futures 0.4.28",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
|
@ -1185,7 +1196,7 @@ dependencies = [
|
|||
"tokio-rustls",
|
||||
"url",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"wasm-bindgen-futures 0.4.28",
|
||||
"web-sys",
|
||||
"webpki-roots",
|
||||
"winreg",
|
||||
|
@ -1216,6 +1227,27 @@ dependencies = [
|
|||
"librocksdb-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-webpack-template"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"byte-unit",
|
||||
"bytes",
|
||||
"console_error_panic_hook",
|
||||
"getrandom",
|
||||
"gloo-console",
|
||||
"http",
|
||||
"js-sys",
|
||||
"omegaupload-common",
|
||||
"reqwasm",
|
||||
"tree_magic_mini",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures 0.4.28",
|
||||
"wasm-bindgen-test",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "1.1.0"
|
||||
|
@ -1241,6 +1273,12 @@ version = "1.0.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
|
||||
|
||||
[[package]]
|
||||
name = "scoped-tls"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
|
||||
|
||||
[[package]]
|
||||
name = "sct"
|
||||
version = "0.6.1"
|
||||
|
@ -1276,8 +1314,8 @@ version = "1.0.130"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.30",
|
||||
"quote 1.0.10",
|
||||
"syn",
|
||||
]
|
||||
|
||||
|
@ -1311,7 +1349,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"cpufeatures",
|
||||
"digest",
|
||||
"opaque-debug",
|
||||
|
@ -1324,7 +1362,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "b69f9a4c9740d74c5baa3fd2e547f9525fa8088a8a958e0ca2409a514e33f5fa"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"cpufeatures",
|
||||
"digest",
|
||||
"opaque-debug",
|
||||
|
@ -1391,9 +1429,9 @@ version = "1.0.80"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d010a1623fbd906d51d650a9916aaefc05ffa0e4053ff7fe601167f3e715d194"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
"proc-macro2 1.0.30",
|
||||
"quote 1.0.10",
|
||||
"unicode-xid 0.2.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1441,8 +1479,8 @@ version = "1.0.30"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.30",
|
||||
"quote 1.0.10",
|
||||
"syn",
|
||||
]
|
||||
|
||||
|
@ -1503,8 +1541,8 @@ version = "1.5.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2dd85aeaba7b68df939bd357c6afb36c87951be9e80bf9c859f2fc3e9fca0fd"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.30",
|
||||
"quote 1.0.10",
|
||||
"syn",
|
||||
]
|
||||
|
||||
|
@ -1584,7 +1622,7 @@ version = "0.1.29"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"log",
|
||||
"pin-project-lite",
|
||||
"tracing-attributes",
|
||||
|
@ -1597,8 +1635,8 @@ version = "0.1.18"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4f480b8f81512e825f337ad51e94c1eb5d3bbdf2b363dcd01e2b19a9ffe3f8e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.30",
|
||||
"quote 1.0.10",
|
||||
"syn",
|
||||
]
|
||||
|
||||
|
@ -1714,6 +1752,12 @@ version = "0.1.9"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.2"
|
||||
|
@ -1788,7 +1832,7 @@ version = "0.2.78"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"wasm-bindgen-macro",
|
||||
|
@ -1803,19 +1847,32 @@ dependencies = [
|
|||
"bumpalo",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.30",
|
||||
"quote 1.0.10",
|
||||
"syn",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-futures"
|
||||
version = "0.3.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "83420b37346c311b9ed822af41ec2e82839bfe99867ec6c54e2da43b7538771c"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10",
|
||||
"futures 0.1.31",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-futures"
|
||||
version = "0.4.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e8d7523cb1f2a4c96c1317ca690031b714a51cc14e05f712446691f413f5d39"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
|
@ -1827,7 +1884,7 @@ version = "0.2.78"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"quote 1.0.10",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
|
@ -1837,8 +1894,8 @@ version = "0.2.78"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.30",
|
||||
"quote 1.0.10",
|
||||
"syn",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
|
@ -1850,6 +1907,31 @@ version = "0.2.78"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-test"
|
||||
version = "0.2.50"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2d9693b63a742d481c7f80587e057920e568317b2806988c59cd71618bc26c1"
|
||||
dependencies = [
|
||||
"console_error_panic_hook",
|
||||
"futures 0.1.31",
|
||||
"js-sys",
|
||||
"scoped-tls",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures 0.3.27",
|
||||
"wasm-bindgen-test-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-test-macro"
|
||||
version = "0.2.50"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0789dac148a8840bbcf9efe13905463b733fa96543bfbf263790535c11af7ba5"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.30",
|
||||
"quote 0.6.13",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.55"
|
||||
|
|
13
Trunk.toml
13
Trunk.toml
|
@ -1,13 +0,0 @@
|
|||
|
||||
[build]
|
||||
target = "web/index.html"
|
||||
release = true
|
||||
|
||||
[[proxy]]
|
||||
backend = "http://localhost:8081"
|
||||
rewrite = "/api/"
|
||||
|
||||
[[hooks]]
|
||||
stage="post_build"
|
||||
command="npx"
|
||||
command_arguments=["swc", "$TRUNK_SOURCE_DIR/src/main.ts", "-o", "$TRUNK_STAGING_DIR/main.js"]
|
|
@ -18,8 +18,10 @@ sha2 = "0.9"
|
|||
thiserror = "1"
|
||||
url = "2"
|
||||
|
||||
# Wasm deps
|
||||
web-sys = { version = "0.3", features = ["Headers"], optional = true }
|
||||
http = { version = "0.2", optional = true }
|
||||
wasm-bindgen = { version = "0.2", optional = true }
|
||||
|
||||
[features]
|
||||
wasm = ["web-sys", "http"]
|
||||
wasm = ["web-sys", "http", "wasm-bindgen"]
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"devDependencies": {
|
||||
"@swc/cli": "^0.1.51",
|
||||
"@swc/core": "^1.2.102"
|
||||
}
|
||||
}
|
6
web/.gitignore
vendored
Normal file
6
web/.gitignore
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
node_modules
|
||||
/dist
|
||||
/target
|
||||
/pkg
|
||||
/wasm-pack.log
|
||||
yarn-error.log
|
|
@ -1,9 +1,15 @@
|
|||
# You must change these to your own details.
|
||||
[package]
|
||||
name = "omegaupload-web"
|
||||
name = "rust-webpack-template"
|
||||
description = "My super awesome Rust, WebAssembly, and Webpack project!"
|
||||
version = "0.1.0"
|
||||
authors = ["You <you@example.com>"]
|
||||
categories = ["wasm"]
|
||||
readme = "README.md"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
omegaupload-common = { path = "../common", features = ["wasm"] }
|
||||
|
@ -40,4 +46,7 @@ features = [
|
|||
"Window",
|
||||
"Performance",
|
||||
"Location",
|
||||
]
|
||||
]
|
||||
|
||||
[dev-dependencies]
|
||||
wasm-bindgen-test = "0.2.45"
|
||||
|
|
|
@ -1,10 +1,48 @@
|
|||
Contains the codebase used for the frontend
|
||||
## How to install
|
||||
|
||||
Notes on licensing:
|
||||
```sh
|
||||
npm install
|
||||
```
|
||||
|
||||
https://www.gnu.org/licenses/gpl-faq.html#AllCompatibility
|
||||
## How to run in debug mode
|
||||
|
||||
Because there is a statically linked in dependency on `shared-mime-types`, this
|
||||
crate MUST be under a GPLv2 or later license. This has been confirmed as of
|
||||
2021-10-24.
|
||||
```sh
|
||||
# Builds the project and opens it in a new browser tab. Auto-reloads when the project changes.
|
||||
npm start
|
||||
```
|
||||
|
||||
## How to build in release mode
|
||||
|
||||
```sh
|
||||
# Builds the project and places it into the `dist` folder.
|
||||
npm run build
|
||||
```
|
||||
|
||||
## How to run unit tests
|
||||
|
||||
```sh
|
||||
# Runs tests in Firefox
|
||||
npm test -- --firefox
|
||||
|
||||
# Runs tests in Chrome
|
||||
npm test -- --chrome
|
||||
|
||||
# Runs tests in Safari
|
||||
npm test -- --safari
|
||||
```
|
||||
|
||||
## What does each file do?
|
||||
|
||||
* `Cargo.toml` contains the standard Rust metadata. You put your Rust dependencies in here. You must change this file with your details (name, description, version, authors, categories)
|
||||
|
||||
* `package.json` contains the standard npm metadata. You put your JavaScript dependencies in here. You must change this file with your details (author, name, version)
|
||||
|
||||
* `webpack.config.js` contains the Webpack configuration. You shouldn't need to change this, unless you have very special needs.
|
||||
|
||||
* The `js` folder contains your JavaScript code (`index.js` is used to hook everything into Webpack, you don't need to change it).
|
||||
|
||||
* The `src` folder contains your Rust code.
|
||||
|
||||
* The `static` folder contains any files that you want copied as-is into the final build. It contains an `index.html` file which loads the `index.js` file.
|
||||
|
||||
* The `tests` folder contains your Rust unit tests.
|
||||
|
|
4
web/js/index.js
Normal file
4
web/js/index.js
Normal file
|
@ -0,0 +1,4 @@
|
|||
import { renderMessage } from './ui';
|
||||
import * as index from "../pkg/index.js";
|
||||
renderMessage("wtf");
|
||||
console.log(index);
|
196
web/js/ui.js
Normal file
196
web/js/ui.js
Normal file
|
@ -0,0 +1,196 @@
|
|||
import hljs from 'hljs';
|
||||
|
||||
window.addEventListener("hashchange", () => location.reload());
|
||||
|
||||
function loadFromDb() {
|
||||
const dbReq = window.indexedDB.open("omegaupload", 1);
|
||||
dbReq.onsuccess = (evt) => {
|
||||
const db = evt.target.result;
|
||||
const obj_store = db
|
||||
.transaction("decrypted data")
|
||||
.objectStore("decrypted data");
|
||||
let fetchReq = obj_store.get(window.location.pathname);
|
||||
fetchReq.onsuccess = (evt) => {
|
||||
const data = evt.target.result;
|
||||
switch (data.type) {
|
||||
case "string":
|
||||
createStringPasteUi(data);
|
||||
break;
|
||||
case "blob":
|
||||
createBlobPasteUi(data);
|
||||
break;
|
||||
case "image":
|
||||
createImagePasteUi(data);
|
||||
break;
|
||||
case "audio":
|
||||
createAudioPasteUi(data);
|
||||
break;
|
||||
case "video":
|
||||
createVideoPasteUi(data);
|
||||
break;
|
||||
default:
|
||||
renderMessage("Something went wrong. Try clearing local data.");
|
||||
break;
|
||||
}
|
||||
|
||||
// IDB was only used as a temporary medium;
|
||||
window.onbeforeunload = (e) => {
|
||||
// See https://link.eddie.sh/NrIIq on why .commit is necessary.
|
||||
const transaction = db.transaction("decrypted data", "readwrite");
|
||||
transaction
|
||||
.objectStore("decrypted data")
|
||||
.delete(window.location.pathname);
|
||||
transaction.commit();
|
||||
transaction.oncomplete = () => {
|
||||
console.log("Item deleted from cache");
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
fetchReq.onerror = (evt) => {
|
||||
console.log("err");
|
||||
console.log(evt);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
function createStringPasteUi(data) {
|
||||
let bodyEle = document.getElementsByTagName("body")[0];
|
||||
bodyEle.textContent = '';
|
||||
|
||||
let mainEle = document.createElement("main");
|
||||
let preEle = document.createElement("pre");
|
||||
preEle.classList.add("paste");
|
||||
|
||||
let headerEle = document.createElement("header");
|
||||
headerEle.classList.add("unselectable");
|
||||
headerEle.textContent = data.expiration;
|
||||
preEle.appendChild(headerEle);
|
||||
|
||||
preEle.appendChild(document.createElement("hr"));
|
||||
|
||||
let codeEle = document.createElement("code");
|
||||
codeEle.textContent = data.data;
|
||||
preEle.appendChild(codeEle);
|
||||
|
||||
mainEle.appendChild(preEle);
|
||||
bodyEle.appendChild(mainEle);
|
||||
|
||||
hljs.highlightAll();
|
||||
hljs.initLineNumbersOnLoad();
|
||||
}
|
||||
|
||||
function createBlobPasteUi(data) {
|
||||
let bodyEle = document.getElementsByTagName("body")[0];
|
||||
bodyEle.textContent = '';
|
||||
|
||||
let mainEle = document.createElement("main");
|
||||
mainEle.classList.add("hljs");
|
||||
mainEle.classList.add("centered");
|
||||
mainEle.classList.add("fullscreen");
|
||||
|
||||
let divEle = document.createElement("div");
|
||||
divEle.classList.add("centered");
|
||||
|
||||
let expirationEle = document.createElement("p");
|
||||
expirationEle.textContent = data.expiration;
|
||||
divEle.appendChild(expirationEle);
|
||||
|
||||
let downloadEle = document.createElement("a");
|
||||
downloadEle.href = URL.createObjectURL(data.data);
|
||||
downloadEle.download = window.location.pathname;
|
||||
downloadEle.classList.add("hljs-meta");
|
||||
downloadEle.textContent = "Download binary file.";
|
||||
divEle.appendChild(downloadEle);
|
||||
|
||||
|
||||
mainEle.appendChild(divEle);
|
||||
|
||||
let displayAnywayEle = document.createElement("p");
|
||||
displayAnywayEle.classList.add("display-anyways");
|
||||
displayAnywayEle.classList.add("hljs-comment");
|
||||
displayAnywayEle.textContent = "Display anyways?";
|
||||
displayAnywayEle.onclick = () => {
|
||||
data.data.text().then(text => {
|
||||
data.data = text;
|
||||
createStringPasteUi(data);
|
||||
})
|
||||
};
|
||||
mainEle.appendChild(displayAnywayEle);
|
||||
bodyEle.appendChild(mainEle);
|
||||
}
|
||||
|
||||
function createImagePasteUi({ expiration, data, file_size }) {
|
||||
createMultiMediaPasteUi("img", expiration, data, (downloadEle, imgEle) => {
|
||||
imgEle.onload = () => {
|
||||
downloadEle.textContent = "Download " + file_size + " \u2014 " + imgEle.naturalWidth + " by " + imgEle.naturalHeight;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function createAudioPasteUi({ expiration, data }) {
|
||||
createMultiMediaPasteUi("audio", expiration, data, "Download");
|
||||
}
|
||||
|
||||
function createVideoPasteUi({ expiration, data }) {
|
||||
createMultiMediaPasteUi("video", expiration, data, "Download");
|
||||
}
|
||||
|
||||
function createMultiMediaPasteUi(tag, expiration, data, on_create) {
|
||||
let bodyEle = document.getElementsByTagName("body")[0];
|
||||
bodyEle.textContent = '';
|
||||
|
||||
let mainEle = document.createElement("main");
|
||||
mainEle.classList.add("hljs");
|
||||
mainEle.classList.add("centered");
|
||||
mainEle.classList.add("fullscreen");
|
||||
|
||||
const downloadLink = URL.createObjectURL(data);
|
||||
|
||||
let expirationEle = document.createElement("p");
|
||||
expirationEle.textContent = expiration;
|
||||
mainEle.appendChild(expirationEle);
|
||||
|
||||
let mediaEle = document.createElement(tag);
|
||||
mediaEle.src = downloadLink;
|
||||
mediaEle.controls = true;
|
||||
mainEle.appendChild(mediaEle);
|
||||
|
||||
let downloadEle = document.createElement("a");
|
||||
downloadEle.href = downloadLink;
|
||||
downloadEle.download = window.location.pathname;
|
||||
downloadEle.classList.add("hljs-meta");
|
||||
mainEle.appendChild(downloadEle);
|
||||
|
||||
bodyEle.appendChild(mainEle);
|
||||
|
||||
if (on_create instanceof Function) {
|
||||
on_create(downloadEle, mediaEle);
|
||||
} else {
|
||||
downloadEle.textContent = on_create;
|
||||
}
|
||||
}
|
||||
|
||||
function renderMessage(message) {
|
||||
let body = document.getElementsByTagName("body")[0];
|
||||
body.textContent = '';
|
||||
let mainEle = document.createElement("main");
|
||||
mainEle.classList.add("hljs");
|
||||
mainEle.classList.add("centered");
|
||||
mainEle.classList.add("fullscreen");
|
||||
mainEle.textContent = message;
|
||||
body.appendChild(mainEle);
|
||||
}
|
||||
|
||||
function renderIndex() {
|
||||
console.log("index");
|
||||
// TODO: find a way to not hard code this.
|
||||
// https://docs.rs/chacha20poly1305/0.9.0/chacha20poly1305/type.Key.html
|
||||
// https://docs.rs/chacha20poly1305/0.9.0/chacha20poly1305/type.XNonce.html
|
||||
const key = crypto.getRandomValues(new Uint8Array(32));
|
||||
const nonce = crypto.getRandomValues(new Uint8Array(24));
|
||||
console.log(key, nonce);
|
||||
}
|
||||
|
||||
|
||||
export { renderIndex, renderMessage, loadFromDb };
|
23
web/package.json
Normal file
23
web/package.json
Normal file
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"author": "Edward Shen <code@eddie.sh>",
|
||||
"name": "omegaupload-web",
|
||||
"version": "0.1.0",
|
||||
"scripts": {
|
||||
"build": "rimraf dist pkg && webpack",
|
||||
"start": "rimraf dist pkg && webpack-dev-server --open",
|
||||
"test": "cargo test && wasm-pack test --headless"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@wasm-tool/wasm-pack-plugin": "^1.1.0",
|
||||
"copy-webpack-plugin": "^9.0.1",
|
||||
"rimraf": "^3.0.0",
|
||||
"ts-loader": "^9.2.6",
|
||||
"webpack": "^5.60.0",
|
||||
"webpack-cli": "^4.9.1",
|
||||
"webpack-dev-server": "^4.3.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"hljs": "^6.2.3",
|
||||
"typescript": "^4.4.4"
|
||||
}
|
||||
}
|
253
web/src/lib.rs
Normal file
253
web/src/lib.rs
Normal file
|
@ -0,0 +1,253 @@
|
|||
#![warn(clippy::nursery, clippy::pedantic)]
|
||||
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::{anyhow, bail, Context, Result};
|
||||
use byte_unit::{n_mib_bytes, Byte};
|
||||
use decrypt::DecryptedData;
|
||||
use gloo_console::{error, log};
|
||||
use http::uri::PathAndQuery;
|
||||
use http::{StatusCode, Uri};
|
||||
use js_sys::{JsString, Object, Uint8Array};
|
||||
use omegaupload_common::crypto::{Key, Nonce};
|
||||
use omegaupload_common::{hash, Expiration, PartialParsedUrl};
|
||||
use reqwasm::http::Request;
|
||||
use wasm_bindgen::prelude::{wasm_bindgen, Closure};
|
||||
use wasm_bindgen::{JsCast, JsValue};
|
||||
use wasm_bindgen_futures::{spawn_local, JsFuture};
|
||||
use web_sys::{Event, IdbObjectStore, IdbOpenDbRequest, IdbTransactionMode, Location, Window};
|
||||
|
||||
use crate::decrypt::decrypt;
|
||||
use crate::idb_object::IdbObject;
|
||||
use crate::util::as_idb_db;
|
||||
|
||||
mod decrypt;
|
||||
mod idb_object;
|
||||
mod util;
|
||||
|
||||
const DOWNLOAD_SIZE_LIMIT: u128 = n_mib_bytes!(500);
|
||||
|
||||
#[wasm_bindgen(raw_module = "../js/ui.js")]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(js_name = renderIndex)]
|
||||
pub fn render_index();
|
||||
#[wasm_bindgen(js_name = loadFromDb)]
|
||||
pub fn load_from_db();
|
||||
#[wasm_bindgen(js_name = renderMessage)]
|
||||
pub fn render_message(message: JsString);
|
||||
}
|
||||
|
||||
fn window() -> Window {
|
||||
web_sys::window().expect("Failed to get a reference of the window")
|
||||
}
|
||||
|
||||
fn location() -> Location {
|
||||
window().location()
|
||||
}
|
||||
|
||||
fn open_idb() -> Result<IdbOpenDbRequest> {
|
||||
window()
|
||||
.indexed_db()
|
||||
.unwrap()
|
||||
.context("Missing browser idb impl")?
|
||||
.open("omegaupload")
|
||||
.map_err(|_| anyhow!("Failed to open idb"))
|
||||
}
|
||||
|
||||
// This is like the `main` function, except for JavaScript.
|
||||
#[wasm_bindgen(start)]
|
||||
pub fn js_main() {
|
||||
std::panic::set_hook(Box::new(console_error_panic_hook::hook));
|
||||
|
||||
if location().pathname().unwrap() == "/" {
|
||||
render_index();
|
||||
} else {
|
||||
render_message("Loading paste...".into());
|
||||
|
||||
let url = String::from(location().to_string());
|
||||
let request_uri = {
|
||||
let mut uri_parts = url.parse::<Uri>().unwrap().into_parts();
|
||||
if let Some(parts) = uri_parts.path_and_query.as_mut() {
|
||||
*parts = PathAndQuery::from_str(&format!("/api{}", parts.path())).unwrap();
|
||||
}
|
||||
Uri::from_parts(uri_parts).unwrap()
|
||||
};
|
||||
|
||||
log!(&url);
|
||||
log!(&request_uri.to_string());
|
||||
log!(&location().pathname().unwrap());
|
||||
let (key, nonce, needs_pw) = {
|
||||
let partial_parsed_url = url
|
||||
.split_once('#')
|
||||
.map(|(_, fragment)| PartialParsedUrl::from(fragment))
|
||||
.unwrap_or_default();
|
||||
let key = if let Some(key) = partial_parsed_url.decryption_key {
|
||||
key
|
||||
} else {
|
||||
error!("Key is missing in url; bailing.");
|
||||
render_message("Invalid paste link: Missing decryption key.".into());
|
||||
return;
|
||||
};
|
||||
let nonce = if let Some(nonce) = partial_parsed_url.nonce {
|
||||
nonce
|
||||
} else {
|
||||
error!("Nonce is missing in url; bailing.");
|
||||
render_message("Invalid paste link: Missing nonce.".into());
|
||||
return;
|
||||
};
|
||||
(key, nonce, partial_parsed_url.needs_password)
|
||||
};
|
||||
|
||||
let password = if needs_pw {
|
||||
loop {
|
||||
let pw =
|
||||
window().prompt_with_message("A password is required to decrypt this paste:");
|
||||
|
||||
if let Ok(Some(password)) = pw {
|
||||
if !password.is_empty() {
|
||||
break Some(hash(password));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
spawn_local(async move {
|
||||
if let Err(e) = fetch_resources(request_uri, key, nonce, password).await {
|
||||
log!(e.to_string());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::future_not_send)]
|
||||
async fn fetch_resources(
|
||||
request_uri: Uri,
|
||||
key: Key,
|
||||
nonce: Nonce,
|
||||
password: Option<Key>,
|
||||
) -> Result<()> {
|
||||
match Request::get(&request_uri.to_string()).send().await {
|
||||
Ok(resp) if resp.status() == StatusCode::OK => {
|
||||
let expires = Expiration::try_from(resp.headers()).map_or_else(
|
||||
|_| "This item does not expire.".to_string(),
|
||||
|expires| expires.to_string(),
|
||||
);
|
||||
|
||||
let data = {
|
||||
let data_fut = resp
|
||||
.as_raw()
|
||||
.array_buffer()
|
||||
.expect("to get raw bytes from a response");
|
||||
let data = match JsFuture::from(data_fut).await {
|
||||
Ok(data) => data,
|
||||
Err(e) => {
|
||||
render_message(
|
||||
"Network failure: Failed to completely read encryption paste.".into(),
|
||||
);
|
||||
bail!(format!(
|
||||
"JsFuture returned an error while fetching resp buffer: {:?}",
|
||||
e
|
||||
));
|
||||
}
|
||||
};
|
||||
Uint8Array::new(&data).to_vec()
|
||||
};
|
||||
|
||||
if data.len() as u128 > DOWNLOAD_SIZE_LIMIT {
|
||||
render_message("The paste is too large to decrypt from the web browser. You must use the CLI tool to download this paste.".into());
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let decrypted = decrypt(data, key, nonce, password)?;
|
||||
let db_open_req = open_idb()?;
|
||||
|
||||
// On success callback
|
||||
let on_success = Closure::once(Box::new(move |event: Event| {
|
||||
let transaction: IdbObjectStore = as_idb_db(&event)
|
||||
.transaction_with_str_and_mode("decrypted data", IdbTransactionMode::Readwrite)
|
||||
.unwrap()
|
||||
.object_store("decrypted data")
|
||||
.unwrap();
|
||||
|
||||
let decrypted_object = match &decrypted {
|
||||
DecryptedData::String(s) => IdbObject::new()
|
||||
.string()
|
||||
.expiration_text(&expires)
|
||||
.data(&JsValue::from_str(s)),
|
||||
DecryptedData::Blob(blob) => {
|
||||
IdbObject::new().blob().expiration_text(&expires).data(blob)
|
||||
}
|
||||
DecryptedData::Image(blob, size) => IdbObject::new()
|
||||
.image()
|
||||
.expiration_text(&expires)
|
||||
.data(blob)
|
||||
.extra(
|
||||
"file_size",
|
||||
Byte::from_bytes(*size as u128)
|
||||
.get_appropriate_unit(true)
|
||||
.to_string(),
|
||||
),
|
||||
DecryptedData::Audio(blob) => IdbObject::new()
|
||||
.audio()
|
||||
.expiration_text(&expires)
|
||||
.data(blob),
|
||||
DecryptedData::Video(blob) => IdbObject::new()
|
||||
.video()
|
||||
.expiration_text(&expires)
|
||||
.data(blob),
|
||||
};
|
||||
|
||||
let put_action = transaction
|
||||
.put_with_key(
|
||||
&Object::from(decrypted_object),
|
||||
&JsString::from(location().pathname().unwrap()),
|
||||
)
|
||||
.unwrap();
|
||||
put_action.set_onsuccess(Some(
|
||||
Closure::wrap(Box::new(|| {
|
||||
log!("success");
|
||||
load_from_db();
|
||||
}) as Box<dyn Fn()>)
|
||||
.into_js_value()
|
||||
.unchecked_ref(),
|
||||
));
|
||||
put_action.set_onerror(Some(
|
||||
Closure::wrap(Box::new(|e| {
|
||||
log!(e);
|
||||
}) as Box<dyn Fn(Event)>)
|
||||
.into_js_value()
|
||||
.unchecked_ref(),
|
||||
));
|
||||
}) as Box<dyn FnOnce(Event)>);
|
||||
|
||||
db_open_req.set_onsuccess(Some(on_success.into_js_value().unchecked_ref()));
|
||||
db_open_req.set_onerror(Some(
|
||||
Closure::wrap(Box::new(|e| {
|
||||
log!(e);
|
||||
}) as Box<dyn Fn(Event)>)
|
||||
.into_js_value()
|
||||
.unchecked_ref(),
|
||||
));
|
||||
let on_upgrade = Closure::wrap(Box::new(move |event: Event| {
|
||||
let db = as_idb_db(&event);
|
||||
let _obj_store = db.create_object_store("decrypted data").unwrap();
|
||||
}) as Box<dyn FnMut(Event)>);
|
||||
db_open_req.set_onupgradeneeded(Some(on_upgrade.into_js_value().unchecked_ref()));
|
||||
}
|
||||
Ok(resp) if resp.status() == StatusCode::NOT_FOUND => {
|
||||
render_message("Either the paste was burned or it never existed.".into());
|
||||
}
|
||||
Ok(resp) if resp.status() == StatusCode::BAD_REQUEST => {
|
||||
render_message("Invalid paste URL.".into());
|
||||
}
|
||||
Ok(err) => {
|
||||
render_message(err.status_text().into());
|
||||
}
|
||||
Err(err) => {
|
||||
render_message(format!("{}", err).into());
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
15
web/static/index.html
Normal file
15
web/static/index.html
Normal file
|
@ -0,0 +1,15 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Omegaupload</title>
|
||||
|
||||
<!-- <script src="highlightjs-line-numbers.min.js" defer></script> -->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script src="index.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
30
web/tests/app.rs
Normal file
30
web/tests/app.rs
Normal file
|
@ -0,0 +1,30 @@
|
|||
use wasm_bindgen::JsValue;
|
||||
use wasm_bindgen_futures::JsFuture;
|
||||
use wasm_bindgen_test::{wasm_bindgen_test, wasm_bindgen_test_configure};
|
||||
|
||||
wasm_bindgen_test_configure!(run_in_browser);
|
||||
|
||||
// This runs a unit test in native Rust, so it can only use Rust APIs.
|
||||
#[test]
|
||||
fn rust_test() {
|
||||
assert_eq!(1, 1);
|
||||
}
|
||||
|
||||
// This runs a unit test in the browser, so it can use browser APIs.
|
||||
#[wasm_bindgen_test]
|
||||
fn web_test() {
|
||||
assert_eq!(1, 1);
|
||||
}
|
||||
|
||||
// This runs a unit test in the browser, and in addition it supports asynchronous Future APIs.
|
||||
#[wasm_bindgen_test(async)]
|
||||
async fn async_test() -> Result<(), JsValue> {
|
||||
// Creates a JavaScript Promise which will asynchronously resolve with the value 42.
|
||||
let promise = js_sys::Promise::resolve(&JsValue::from(42));
|
||||
|
||||
// Converts that Promise into a Future.
|
||||
// The unit test will wait for the Future to resolve.
|
||||
JsFuture::from(promise).map(|x| {
|
||||
assert_eq!(x, 42);
|
||||
})
|
||||
}
|
11
web/tsconfig.json
Normal file
11
web/tsconfig.json
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist/",
|
||||
"noImplicitAny": false,
|
||||
"module": "esnext",
|
||||
"target": "es5",
|
||||
"allowJs": true,
|
||||
"moduleResolution": "node",
|
||||
"sourceMap": true,
|
||||
}
|
||||
}
|
51
web/webpack.config.js
Normal file
51
web/webpack.config.js
Normal file
|
@ -0,0 +1,51 @@
|
|||
const path = require("path");
|
||||
const CopyPlugin = require("copy-webpack-plugin");
|
||||
const WasmPackPlugin = require("@wasm-tool/wasm-pack-plugin");
|
||||
|
||||
const dist = path.resolve(__dirname, "dist");
|
||||
|
||||
module.exports = {
|
||||
mode: "development",
|
||||
entry: {
|
||||
index: "./js/index.js"
|
||||
},
|
||||
devtool: 'inline-source-map',
|
||||
output: {
|
||||
path: dist,
|
||||
filename: "[name].js"
|
||||
},
|
||||
devServer: {
|
||||
static: {
|
||||
directory: dist,
|
||||
},
|
||||
proxy: {
|
||||
'/api': {
|
||||
target: 'http://localhost:8081',
|
||||
pathRewrite: { '^/api': '' }
|
||||
}
|
||||
},
|
||||
watchFiles: ['src/**', 'js/**'],
|
||||
},
|
||||
plugins: [
|
||||
new CopyPlugin({
|
||||
patterns: [
|
||||
path.resolve(__dirname, "static")
|
||||
]
|
||||
}),
|
||||
new WasmPackPlugin({
|
||||
crateDirectory: __dirname,
|
||||
}),
|
||||
],
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.tsx?$/,
|
||||
use: 'ts-loader',
|
||||
exclude: /node_modules/,
|
||||
}
|
||||
]
|
||||
},
|
||||
experiments: {
|
||||
asyncWebAssembly: true,
|
||||
},
|
||||
};
|
2356
web/yarn.lock
Normal file
2356
web/yarn.lock
Normal file
File diff suppressed because it is too large
Load diff
43
web_old/Cargo.toml
Normal file
43
web_old/Cargo.toml
Normal file
|
@ -0,0 +1,43 @@
|
|||
[package]
|
||||
name = "omegaupload-web"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
omegaupload-common = { path = "../common", features = ["wasm"] }
|
||||
# Enables wasm support
|
||||
getrandom = { version = "*", features = ["js"] }
|
||||
|
||||
anyhow = "1"
|
||||
bytes = "1"
|
||||
byte-unit = "4"
|
||||
console_error_panic_hook = "0.1"
|
||||
gloo-console = "0.1"
|
||||
http = "0.2"
|
||||
js-sys = "0.3"
|
||||
reqwasm = "0.2"
|
||||
tree_magic_mini = { version = "3", features = ["with-gpl-data"] }
|
||||
wasm-bindgen = "0.2"
|
||||
wasm-bindgen-futures = "0.4"
|
||||
|
||||
[dependencies.web-sys]
|
||||
version = "0.3"
|
||||
features = [
|
||||
"TextDecoder",
|
||||
"IdbFactory",
|
||||
"IdbOpenDbRequest",
|
||||
"IdbRequest",
|
||||
"IdbDatabase",
|
||||
"IdbObjectStore",
|
||||
"IdbTransaction",
|
||||
"IdbTransactionMode",
|
||||
"IdbIndex",
|
||||
"IdbIndexParameters",
|
||||
"Event",
|
||||
"EventTarget",
|
||||
"Window",
|
||||
"Performance",
|
||||
"Location",
|
||||
]
|
10
web_old/README.md
Normal file
10
web_old/README.md
Normal file
|
@ -0,0 +1,10 @@
|
|||
Contains the codebase used for the frontend
|
||||
|
||||
Notes on licensing:
|
||||
|
||||
https://www.gnu.org/licenses/gpl-faq.html#AllCompatibility
|
||||
|
||||
Because there is a statically linked in dependency on `shared-mime-types`, this
|
||||
crate MUST be under a GPLv2 or later license. This has been confirmed as of
|
||||
2021-10-24.
|
||||
|
105
web_old/src/decrypt.rs
Normal file
105
web_old/src/decrypt.rs
Normal file
|
@ -0,0 +1,105 @@
|
|||
use std::fmt::{Display, Formatter};
|
||||
use std::sync::Arc;
|
||||
|
||||
use gloo_console::log;
|
||||
use js_sys::{Array, Uint8Array};
|
||||
use omegaupload_common::crypto::{open_in_place, Key, Nonce};
|
||||
use wasm_bindgen::JsCast;
|
||||
use web_sys::Blob;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum DecryptedData {
|
||||
String(Arc<String>),
|
||||
Blob(Arc<Blob>),
|
||||
Image(Arc<Blob>, usize),
|
||||
Audio(Arc<Blob>),
|
||||
Video(Arc<Blob>),
|
||||
}
|
||||
|
||||
fn now() -> f64 {
|
||||
web_sys::window()
|
||||
.expect("should have a Window")
|
||||
.performance()
|
||||
.expect("should have a Performance")
|
||||
.now()
|
||||
}
|
||||
|
||||
pub fn decrypt(
|
||||
mut container: Vec<u8>,
|
||||
key: Key,
|
||||
nonce: Nonce,
|
||||
maybe_password: Option<Key>,
|
||||
) -> Result<DecryptedData, PasteCompleteConstructionError> {
|
||||
let container = &mut container;
|
||||
log!("Stage 1 decryption started.");
|
||||
let start = now();
|
||||
|
||||
if let Some(password) = maybe_password {
|
||||
crate::render_message("Decrypting Stage 1...".into());
|
||||
open_in_place(container, &nonce.increment(), &password).map_err(|_| {
|
||||
crate::render_message("Unable to decrypt paste with the provided password.".into());
|
||||
PasteCompleteConstructionError::StageOneFailure
|
||||
})?;
|
||||
}
|
||||
log!(format!("Stage 1 completed in {}ms", now() - start));
|
||||
|
||||
log!("Stage 2 decryption started.");
|
||||
let start = now();
|
||||
crate::render_message("Decrypting Stage 2...".into());
|
||||
open_in_place(container, &nonce, &key).map_err(|_| {
|
||||
crate::render_message(
|
||||
"Unable to decrypt paste with the provided encryption key and nonce.".into(),
|
||||
);
|
||||
PasteCompleteConstructionError::StageTwoFailure
|
||||
})?;
|
||||
log!(format!("Stage 2 completed in {}ms", now() - start));
|
||||
|
||||
if let Ok(decrypted) = std::str::from_utf8(container) {
|
||||
Ok(DecryptedData::String(Arc::new(decrypted.to_owned())))
|
||||
} else {
|
||||
log!("Blob conversion started.");
|
||||
let start = now();
|
||||
let blob_chunks = Array::new_with_length(container.chunks(65536).len().try_into().unwrap());
|
||||
for (i, chunk) in container.chunks(65536).enumerate() {
|
||||
let array = Uint8Array::new_with_length(chunk.len().try_into().unwrap());
|
||||
array.copy_from(chunk);
|
||||
blob_chunks.set(i.try_into().unwrap(), array.dyn_into().unwrap());
|
||||
}
|
||||
let blob =
|
||||
Arc::new(Blob::new_with_u8_array_sequence(blob_chunks.dyn_ref().unwrap()).unwrap());
|
||||
log!(format!("Blob conversion completed in {}ms", now() - start));
|
||||
|
||||
let mime_type = tree_magic_mini::from_u8(container);
|
||||
|
||||
if mime_type.starts_with("image/") || mime_type == "application/x-riff" {
|
||||
Ok(DecryptedData::Image(blob, container.len()))
|
||||
} else if mime_type.starts_with("audio/") {
|
||||
Ok(DecryptedData::Audio(blob))
|
||||
} else if mime_type.starts_with("video/") || mime_type == "application/x-matroska" {
|
||||
Ok(DecryptedData::Video(blob))
|
||||
} else {
|
||||
Ok(DecryptedData::Blob(blob))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum PasteCompleteConstructionError {
|
||||
StageOneFailure,
|
||||
StageTwoFailure,
|
||||
}
|
||||
|
||||
impl std::error::Error for PasteCompleteConstructionError {}
|
||||
|
||||
impl Display for PasteCompleteConstructionError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
PasteCompleteConstructionError::StageOneFailure => {
|
||||
write!(f, "Failed to decrypt stage one.")
|
||||
}
|
||||
PasteCompleteConstructionError::StageTwoFailure => {
|
||||
write!(f, "Failed to decrypt stage two.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
95
web_old/src/idb_object.rs
Normal file
95
web_old/src/idb_object.rs
Normal file
|
@ -0,0 +1,95 @@
|
|||
use std::{hint::unreachable_unchecked, marker::PhantomData};
|
||||
|
||||
use js_sys::{Array, JsString, Object};
|
||||
use wasm_bindgen::JsValue;
|
||||
|
||||
pub struct IdbObject<State>(Array, PhantomData<State>);
|
||||
|
||||
impl<State: IdbObjectState> IdbObject<State> {
|
||||
fn add_tuple<NextState>(self, key: &str, value: &JsValue) -> IdbObject<NextState> {
|
||||
let array = Array::new();
|
||||
array.push(&JsString::from(key));
|
||||
array.push(value);
|
||||
self.0.push(&array);
|
||||
IdbObject(self.0, PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<IdbObject<Ready>> for Object {
|
||||
fn from(db_object: IdbObject<Ready>) -> Self {
|
||||
match Self::from_entries(db_object.as_ref()) {
|
||||
Ok(o) => o,
|
||||
// SAFETY: IdbObject maintains the invariant that it can eventually
|
||||
// be constructed into a JS object.
|
||||
_ => unsafe { unreachable_unchecked() },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl IdbObject<NeedsType> {
|
||||
pub fn new() -> Self {
|
||||
Self(Array::new(), PhantomData)
|
||||
}
|
||||
|
||||
pub fn video(self) -> IdbObject<NeedsExpiration> {
|
||||
self.add_tuple("type", &JsString::from("video"))
|
||||
}
|
||||
|
||||
pub fn audio(self) -> IdbObject<NeedsExpiration> {
|
||||
self.add_tuple("type", &JsString::from("audio"))
|
||||
}
|
||||
|
||||
pub fn image(self) -> IdbObject<NeedsExpiration> {
|
||||
self.add_tuple("type", &JsString::from("image"))
|
||||
}
|
||||
|
||||
pub fn blob(self) -> IdbObject<NeedsExpiration> {
|
||||
self.add_tuple("type", &JsString::from("blob"))
|
||||
}
|
||||
|
||||
pub fn string(self) -> IdbObject<NeedsExpiration> {
|
||||
self.add_tuple("type", &JsString::from("string"))
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for IdbObject<NeedsType> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl IdbObject<NeedsExpiration> {
|
||||
pub fn expiration_text(self, expires: &str) -> IdbObject<NeedsData> {
|
||||
self.add_tuple("expiration", &JsString::from(expires))
|
||||
}
|
||||
}
|
||||
|
||||
impl IdbObject<NeedsData> {
|
||||
pub fn data(self, value: &JsValue) -> IdbObject<Ready> {
|
||||
self.add_tuple("data", value)
|
||||
}
|
||||
}
|
||||
|
||||
impl IdbObject<Ready> {
|
||||
pub fn extra(self, key: &str, value: impl Into<JsValue>) -> Self {
|
||||
self.add_tuple(key, &value.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<JsValue> for IdbObject<Ready> {
|
||||
fn as_ref(&self) -> &JsValue {
|
||||
self.0.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_idb_object_state {
|
||||
($($ident:ident),*) => {
|
||||
pub trait IdbObjectState {}
|
||||
$(
|
||||
pub enum $ident {}
|
||||
impl IdbObjectState for $ident {}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
impl_idb_object_state!(NeedsType, NeedsExpiration, NeedsData, Ready);
|
|
@ -29,6 +29,8 @@ const DOWNLOAD_SIZE_LIMIT: u128 = n_mib_bytes!(500);
|
|||
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(js_name = renderIndex)]
|
||||
pub fn render_index();
|
||||
#[wasm_bindgen(js_name = loadFromDb)]
|
||||
pub fn load_from_db();
|
||||
#[wasm_bindgen(js_name = renderMessage)]
|
||||
|
@ -55,58 +57,59 @@ fn open_idb() -> Result<IdbOpenDbRequest> {
|
|||
fn main() {
|
||||
std::panic::set_hook(Box::new(console_error_panic_hook::hook));
|
||||
|
||||
render_message("Loading paste...".into());
|
||||
if location().pathname().unwrap() == "/" {
|
||||
render_index();
|
||||
} else {
|
||||
render_message("Loading paste...".into());
|
||||
|
||||
let url = String::from(location().to_string());
|
||||
let request_uri = {
|
||||
let mut uri_parts = url.parse::<Uri>().unwrap().into_parts();
|
||||
if let Some(parts) = uri_parts.path_and_query.as_mut() {
|
||||
*parts = PathAndQuery::from_str(&format!("/api{}", parts.path())).unwrap();
|
||||
}
|
||||
Uri::from_parts(uri_parts).unwrap()
|
||||
};
|
||||
|
||||
log!(&url);
|
||||
log!(&request_uri.to_string());
|
||||
log!(&location().pathname().unwrap());
|
||||
let (key, nonce, needs_pw) = {
|
||||
let partial_parsed_url = url
|
||||
.split_once('#')
|
||||
.map(|(_, fragment)| PartialParsedUrl::from(fragment))
|
||||
.unwrap_or_default();
|
||||
let key = if let Some(key) = partial_parsed_url.decryption_key {
|
||||
key
|
||||
} else {
|
||||
error!("Key is missing in url; bailing.");
|
||||
render_message("Invalid paste link: Missing decryption key.".into());
|
||||
return;
|
||||
let url = String::from(location().to_string());
|
||||
let request_uri = {
|
||||
let mut uri_parts = url.parse::<Uri>().unwrap().into_parts();
|
||||
if let Some(parts) = uri_parts.path_and_query.as_mut() {
|
||||
*parts = PathAndQuery::from_str(&format!("/api{}", parts.path())).unwrap();
|
||||
}
|
||||
Uri::from_parts(uri_parts).unwrap()
|
||||
};
|
||||
let nonce = if let Some(nonce) = partial_parsed_url.nonce {
|
||||
nonce
|
||||
} else {
|
||||
error!("Nonce is missing in url; bailing.");
|
||||
render_message("Invalid paste link: Missing nonce.".into());
|
||||
return;
|
||||
|
||||
log!(&url);
|
||||
log!(&request_uri.to_string());
|
||||
log!(&location().pathname().unwrap());
|
||||
let (key, nonce, needs_pw) = {
|
||||
let partial_parsed_url = url
|
||||
.split_once('#')
|
||||
.map(|(_, fragment)| PartialParsedUrl::from(fragment))
|
||||
.unwrap_or_default();
|
||||
let key = if let Some(key) = partial_parsed_url.decryption_key {
|
||||
key
|
||||
} else {
|
||||
error!("Key is missing in url; bailing.");
|
||||
render_message("Invalid paste link: Missing decryption key.".into());
|
||||
return;
|
||||
};
|
||||
let nonce = if let Some(nonce) = partial_parsed_url.nonce {
|
||||
nonce
|
||||
} else {
|
||||
error!("Nonce is missing in url; bailing.");
|
||||
render_message("Invalid paste link: Missing nonce.".into());
|
||||
return;
|
||||
};
|
||||
(key, nonce, partial_parsed_url.needs_password)
|
||||
};
|
||||
(key, nonce, partial_parsed_url.needs_password)
|
||||
};
|
||||
|
||||
let password = if needs_pw {
|
||||
loop {
|
||||
let pw = window().prompt_with_message("A password is required to decrypt this paste:");
|
||||
let password = if needs_pw {
|
||||
loop {
|
||||
let pw =
|
||||
window().prompt_with_message("A password is required to decrypt this paste:");
|
||||
|
||||
if let Ok(Some(password)) = pw {
|
||||
if !password.is_empty() {
|
||||
break Some(hash(password));
|
||||
if let Ok(Some(password)) = pw {
|
||||
if !password.is_empty() {
|
||||
break Some(hash(password));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
if location().pathname().unwrap() == "/" {
|
||||
} else {
|
||||
} else {
|
||||
None
|
||||
};
|
||||
spawn_local(async move {
|
||||
if let Err(e) = fetch_resources(request_uri, key, nonce, password).await {
|
||||
log!(e.to_string());
|
|
@ -1,3 +1,6 @@
|
|||
|
||||
window.addEventListener("hashchange", () => location.reload());
|
||||
|
||||
// Exported to main.rs
|
||||
function loadFromDb() {
|
||||
const dbReq = window.indexedDB.open("omegaupload", 1);
|
||||
|
@ -179,4 +182,13 @@ function renderMessage(message) {
|
|||
body.appendChild(mainEle);
|
||||
}
|
||||
|
||||
window.addEventListener("hashchange", () => location.reload());
|
||||
// Export to main.rs
|
||||
function renderIndex() {
|
||||
console.log("index");
|
||||
// TODO: find a way to not hard code this.
|
||||
// https://docs.rs/chacha20poly1305/0.9.0/chacha20poly1305/type.Key.html
|
||||
// https://docs.rs/chacha20poly1305/0.9.0/chacha20poly1305/type.XNonce.html
|
||||
const key = crypto.getRandomValues(new Uint8Array(32));
|
||||
const nonce = crypto.getRandomValues(new Uint8Array(24));
|
||||
console.log(key, nonce);
|
||||
}
|
10
web_old/src/util.rs
Normal file
10
web_old/src/util.rs
Normal file
|
@ -0,0 +1,10 @@
|
|||
use wasm_bindgen::JsCast;
|
||||
use web_sys::{Event, IdbDatabase, IdbOpenDbRequest};
|
||||
|
||||
/// # Panics
|
||||
///
|
||||
/// This will panic if event is not an event from the IDB API.
|
||||
pub fn as_idb_db(event: &Event) -> IdbDatabase {
|
||||
let target: IdbOpenDbRequest = event.target().map(JsCast::unchecked_into).unwrap();
|
||||
target.result().map(JsCast::unchecked_into).unwrap()
|
||||
}
|
233
yarn.lock
233
yarn.lock
|
@ -1,233 +0,0 @@
|
|||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@napi-rs/triples@^1.0.3":
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@napi-rs/triples/-/triples-1.0.3.tgz#76d6d0c3f4d16013c61e45dfca5ff1e6c31ae53c"
|
||||
integrity sha512-jDJTpta+P4p1NZTFVLHJ/TLFVYVcOqv6l8xwOeBKNPMgY/zDYH/YH7SJbvrr/h1RcS9GzbPcLKGzpuK9cV56UA==
|
||||
|
||||
"@node-rs/helper@^1.0.0":
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@node-rs/helper/-/helper-1.2.1.tgz#e079b05f21ff4329d82c4e1f71c0290e4ecdc70c"
|
||||
integrity sha512-R5wEmm8nbuQU0YGGmYVjEc0OHtYsuXdpRG+Ut/3wZ9XAvQWyThN08bTh2cBJgoZxHQUPtvRfeQuxcAgLuiBISg==
|
||||
dependencies:
|
||||
"@napi-rs/triples" "^1.0.3"
|
||||
|
||||
"@nodelib/fs.scandir@2.1.5":
|
||||
version "2.1.5"
|
||||
resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
|
||||
integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==
|
||||
dependencies:
|
||||
"@nodelib/fs.stat" "2.0.5"
|
||||
run-parallel "^1.1.9"
|
||||
|
||||
"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2":
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b"
|
||||
integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
|
||||
|
||||
"@nodelib/fs.walk@^1.2.3":
|
||||
version "1.2.8"
|
||||
resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a"
|
||||
integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==
|
||||
dependencies:
|
||||
"@nodelib/fs.scandir" "2.1.5"
|
||||
fastq "^1.6.0"
|
||||
|
||||
"@swc/cli@^0.1.51":
|
||||
version "0.1.51"
|
||||
resolved "https://registry.yarnpkg.com/@swc/cli/-/cli-0.1.51.tgz#720f2d966446558011085c2a40a65fd9079d06a1"
|
||||
integrity sha512-7eqZGpkI4QOYfF+9FV4xpT/V/LSRDs5OMJcm4Z46JnPMvv+sxumAFdCe1hHRzHgnzwis9OtjI8Tt3Srf9JudQw==
|
||||
dependencies:
|
||||
commander "^7.1.0"
|
||||
fast-glob "^3.2.5"
|
||||
slash "3.0.0"
|
||||
source-map "^0.7.3"
|
||||
|
||||
"@swc/core-android-arm64@1.2.102":
|
||||
version "1.2.102"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-android-arm64/-/core-android-arm64-1.2.102.tgz#972a47217053cc759f0bc0308a508279de1247ba"
|
||||
integrity sha512-03wXXSyzm3I/7E3HihYRwvR/v5Xq8Z6j+oXYAouNoQo0/ODTMH9ATFv30csrK3mRtVEcJUk8VpVvfyh1N4hqkw==
|
||||
|
||||
"@swc/core-darwin-arm64@1.2.102":
|
||||
version "1.2.102"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.2.102.tgz#1795a4080d1060ca8ac52f218cc4c64b73a7ef06"
|
||||
integrity sha512-DlC9+qt6gq6gGbmr9MCuMZmdHD/RyfZlf7YfkbQOlRlxaanUWz0lq0TZDWGI6MIofVOgaTle0FImPXby6dI/RA==
|
||||
|
||||
"@swc/core-darwin-x64@1.2.102":
|
||||
version "1.2.102"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.2.102.tgz#f48ab5b8b56798d36acd38838c62eb0be4af3c4b"
|
||||
integrity sha512-JQhxbDnb8RYZ4m7B1f5J05HlUfmjiniQDnpSrvo5rDhlAZWXxuAKjEJQw8Qas/vqLdmgqrZ9POZmFaMBwIgKwg==
|
||||
|
||||
"@swc/core-linux-arm-gnueabihf@1.2.102":
|
||||
version "1.2.102"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.2.102.tgz#a617cea4f5a2ff1aac9f668da12dd7a6a0a6700d"
|
||||
integrity sha512-XWr6Cm3lBOcSGjTjPDLWHBh+lOSkKFMS2gCpLmIC3StAvtcN0oQY59T4cqDfe7VcBgJcdeo/H4dEnrXvnJyCaw==
|
||||
|
||||
"@swc/core-linux-arm64-gnu@1.2.102":
|
||||
version "1.2.102"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.2.102.tgz#0abccb26af51783be141dea8b7af0baa0dcc55b4"
|
||||
integrity sha512-HVtLVBpyqpSIkXmonW75nDzpdrRtZXwEYLYG+y6Sw/8AQFQ9WntwnR+xoJ8q9o3Bby2DGpWetjR0V8rr1m+lmg==
|
||||
|
||||
"@swc/core-linux-arm64-musl@1.2.102":
|
||||
version "1.2.102"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.2.102.tgz#ab079233626a355995b8e25e3666a759edffe1c5"
|
||||
integrity sha512-XDgnkd90alnkBB+JcXaYIG5lXrv/ppLb9Z5fZ4BIsi8uNsVZgo+H/eAj/BTcYff4mpyGdCdqd7P1lC/WRR8uEg==
|
||||
|
||||
"@swc/core-linux-x64-gnu@1.2.102":
|
||||
version "1.2.102"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.2.102.tgz#6336698ffae22a491e782cb9ab7478130ceb2240"
|
||||
integrity sha512-O3XZpJ0GMghNcO5uxfhAvDTJ4FgDOcq8DBPpa4f4Mz7hU6fcGY4Koy4rUeff4BuOKlIzI/O+REszxk7Fiivh2w==
|
||||
|
||||
"@swc/core-linux-x64-musl@1.2.102":
|
||||
version "1.2.102"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.2.102.tgz#b9f557dd53647318ac6dd832f174efe8e7386e1a"
|
||||
integrity sha512-bGqatsVX3yc56YoOLGcHMUG23I2PKMe638vCBfuKVWN6UKcGJGMzqZV/efyPiHJDFcWzN/1jYW3GccGQq97G3Q==
|
||||
|
||||
"@swc/core-win32-arm64-msvc@1.2.102":
|
||||
version "1.2.102"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.2.102.tgz#e7c7958f0c2adb1e83a375e0d8d6af673e53150d"
|
||||
integrity sha512-A15tUAEDS72a2ixNQl3mKCgMD6RVzntMdWl9pDG71/xRd/U/NVIKx0x12FT5fUQH8PTJ7cgcp2Y0VqKeeEuF5w==
|
||||
|
||||
"@swc/core-win32-ia32-msvc@1.2.102":
|
||||
version "1.2.102"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.2.102.tgz#f14c93ac0c8b2ec03a8d5438b86551d962da4b0c"
|
||||
integrity sha512-uePvr9+C1Z0KVElU/Y6ZyXw7vqzRIxl+KSYfn9mCFpgYy/1BRSmxpxqTzR0rkfClXMBi2W9a0JosmWbUvRC8ZQ==
|
||||
|
||||
"@swc/core-win32-x64-msvc@1.2.102":
|
||||
version "1.2.102"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.2.102.tgz#e3cbbb58d99174b7b7d9c1c58467491d31dca269"
|
||||
integrity sha512-VsUducGCqKm0ucFrZiKQZ95Y4EcCSivg/zYBdTXM20eu/7mG9ynBXHCoKW0B+69D6J3IZsrc9Hvcu7gKkT9QfQ==
|
||||
|
||||
"@swc/core@^1.2.102":
|
||||
version "1.2.102"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.2.102.tgz#c71fd22941fa9b7b3c52c778d494ab57beef2c17"
|
||||
integrity sha512-KQEsDWb8HTSQ/I8N6qVHNSl6al/qcXxsRAjpEP8ZPnnpgThbnP9MeKpT2KeU+Qd4VD0qXM72dMm2QOPzdSlxHQ==
|
||||
dependencies:
|
||||
"@node-rs/helper" "^1.0.0"
|
||||
optionalDependencies:
|
||||
"@swc/core-android-arm64" "1.2.102"
|
||||
"@swc/core-darwin-arm64" "1.2.102"
|
||||
"@swc/core-darwin-x64" "1.2.102"
|
||||
"@swc/core-linux-arm-gnueabihf" "1.2.102"
|
||||
"@swc/core-linux-arm64-gnu" "1.2.102"
|
||||
"@swc/core-linux-arm64-musl" "1.2.102"
|
||||
"@swc/core-linux-x64-gnu" "1.2.102"
|
||||
"@swc/core-linux-x64-musl" "1.2.102"
|
||||
"@swc/core-win32-arm64-msvc" "1.2.102"
|
||||
"@swc/core-win32-ia32-msvc" "1.2.102"
|
||||
"@swc/core-win32-x64-msvc" "1.2.102"
|
||||
|
||||
braces@^3.0.1:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
|
||||
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
|
||||
dependencies:
|
||||
fill-range "^7.0.1"
|
||||
|
||||
commander@^7.1.0:
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7"
|
||||
integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==
|
||||
|
||||
fast-glob@^3.2.5:
|
||||
version "3.2.7"
|
||||
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.7.tgz#fd6cb7a2d7e9aa7a7846111e85a196d6b2f766a1"
|
||||
integrity sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==
|
||||
dependencies:
|
||||
"@nodelib/fs.stat" "^2.0.2"
|
||||
"@nodelib/fs.walk" "^1.2.3"
|
||||
glob-parent "^5.1.2"
|
||||
merge2 "^1.3.0"
|
||||
micromatch "^4.0.4"
|
||||
|
||||
fastq@^1.6.0:
|
||||
version "1.13.0"
|
||||
resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c"
|
||||
integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==
|
||||
dependencies:
|
||||
reusify "^1.0.4"
|
||||
|
||||
fill-range@^7.0.1:
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
|
||||
integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
|
||||
dependencies:
|
||||
to-regex-range "^5.0.1"
|
||||
|
||||
glob-parent@^5.1.2:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
|
||||
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
|
||||
dependencies:
|
||||
is-glob "^4.0.1"
|
||||
|
||||
is-extglob@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
|
||||
integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
|
||||
|
||||
is-glob@^4.0.1:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
|
||||
integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
|
||||
dependencies:
|
||||
is-extglob "^2.1.1"
|
||||
|
||||
is-number@^7.0.0:
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
|
||||
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
|
||||
|
||||
merge2@^1.3.0:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
|
||||
integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
|
||||
|
||||
micromatch@^4.0.4:
|
||||
version "4.0.4"
|
||||
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9"
|
||||
integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==
|
||||
dependencies:
|
||||
braces "^3.0.1"
|
||||
picomatch "^2.2.3"
|
||||
|
||||
picomatch@^2.2.3:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972"
|
||||
integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==
|
||||
|
||||
queue-microtask@^1.2.2:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
|
||||
integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
|
||||
|
||||
reusify@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
|
||||
integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
|
||||
|
||||
run-parallel@^1.1.9:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"
|
||||
integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==
|
||||
dependencies:
|
||||
queue-microtask "^1.2.2"
|
||||
|
||||
slash@3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
|
||||
integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
|
||||
|
||||
source-map@^0.7.3:
|
||||
version "0.7.3"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
|
||||
integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==
|
||||
|
||||
to-regex-range@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
|
||||
integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
|
||||
dependencies:
|
||||
is-number "^7.0.0"
|
Loading…
Reference in a new issue