Skip to content

Instantly share code, notes, and snippets.

@craftyc0der
Last active July 30, 2023 03:48

Revisions

  1. craftyc0der revised this gist Nov 27, 2022. 1 changed file with 0 additions and 811 deletions.
    811 changes: 0 additions & 811 deletions Cargo.lock
    Original file line number Diff line number Diff line change
    @@ -1,811 +0,0 @@
    # This file is automatically @generated by Cargo.
    # It is not intended for manual editing.
    version = 3

    [[package]]
    name = "anymap2"
    version = "0.13.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "d301b3b94cb4b2f23d7917810addbbaff90738e0ca2be692bd027e70d7e0330c"

    [[package]]
    name = "autocfg"
    version = "1.1.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"

    [[package]]
    name = "bincode"
    version = "1.3.3"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
    dependencies = [
    "serde",
    ]

    [[package]]
    name = "boolinator"
    version = "2.4.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "cfa8873f51c92e232f9bac4065cddef41b714152812bfc5f7672ba16d6ef8cd9"

    [[package]]
    name = "bumpalo"
    version = "3.11.1"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"

    [[package]]
    name = "cfg-if"
    version = "1.0.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"

    [[package]]
    name = "console_error_panic_hook"
    version = "0.1.7"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc"
    dependencies = [
    "cfg-if",
    "wasm-bindgen",
    ]

    [[package]]
    name = "fnv"
    version = "1.0.7"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"

    [[package]]
    name = "form_urlencoded"
    version = "1.1.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8"
    dependencies = [
    "percent-encoding",
    ]

    [[package]]
    name = "futures"
    version = "0.3.25"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0"
    dependencies = [
    "futures-channel",
    "futures-core",
    "futures-io",
    "futures-sink",
    "futures-task",
    "futures-util",
    ]

    [[package]]
    name = "futures-channel"
    version = "0.3.25"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed"
    dependencies = [
    "futures-core",
    "futures-sink",
    ]

    [[package]]
    name = "futures-core"
    version = "0.3.25"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac"

    [[package]]
    name = "futures-io"
    version = "0.3.25"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb"

    [[package]]
    name = "futures-macro"
    version = "0.3.25"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d"
    dependencies = [
    "proc-macro2",
    "quote",
    "syn",
    ]

    [[package]]
    name = "futures-sink"
    version = "0.3.25"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9"

    [[package]]
    name = "futures-task"
    version = "0.3.25"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea"

    [[package]]
    name = "futures-util"
    version = "0.3.25"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6"
    dependencies = [
    "futures-channel",
    "futures-core",
    "futures-io",
    "futures-macro",
    "futures-sink",
    "futures-task",
    "memchr",
    "pin-project-lite",
    "pin-utils",
    "slab",
    ]

    [[package]]
    name = "gist-yew-firebase"
    version = "0.1.0"
    dependencies = [
    "wasm-bindgen",
    "yew",
    ]

    [[package]]
    name = "gloo"
    version = "0.8.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "3a4bef6b277b3ab073253d4bca60761240cf8d6998f4bd142211957b69a61b20"
    dependencies = [
    "gloo-console",
    "gloo-dialogs",
    "gloo-events",
    "gloo-file",
    "gloo-history",
    "gloo-net",
    "gloo-render",
    "gloo-storage",
    "gloo-timers",
    "gloo-utils",
    "gloo-worker",
    ]

    [[package]]
    name = "gloo-console"
    version = "0.2.3"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "82b7ce3c05debe147233596904981848862b068862e9ec3e34be446077190d3f"
    dependencies = [
    "gloo-utils",
    "js-sys",
    "serde",
    "wasm-bindgen",
    "web-sys",
    ]

    [[package]]
    name = "gloo-dialogs"
    version = "0.1.1"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "67062364ac72d27f08445a46cab428188e2e224ec9e37efdba48ae8c289002e6"
    dependencies = [
    "wasm-bindgen",
    "web-sys",
    ]

    [[package]]
    name = "gloo-events"
    version = "0.1.2"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "68b107f8abed8105e4182de63845afcc7b69c098b7852a813ea7462a320992fc"
    dependencies = [
    "wasm-bindgen",
    "web-sys",
    ]

    [[package]]
    name = "gloo-file"
    version = "0.2.3"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "a8d5564e570a38b43d78bdc063374a0c3098c4f0d64005b12f9bbe87e869b6d7"
    dependencies = [
    "gloo-events",
    "js-sys",
    "wasm-bindgen",
    "web-sys",
    ]

    [[package]]
    name = "gloo-history"
    version = "0.1.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "f81af52c0d31e86242eecefe1ed4d066deb79cfb80f9f7da0847fac417396bfe"
    dependencies = [
    "gloo-events",
    "gloo-utils",
    "serde",
    "serde-wasm-bindgen",
    "serde_urlencoded",
    "thiserror",
    "wasm-bindgen",
    "web-sys",
    ]

    [[package]]
    name = "gloo-net"
    version = "0.2.4"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "ec897194fb9ac576c708f63d35604bc58f2a262b8cec0fabfed26f3991255f21"
    dependencies = [
    "futures-channel",
    "futures-core",
    "futures-sink",
    "gloo-utils",
    "js-sys",
    "pin-project",
    "serde",
    "serde_json",
    "thiserror",
    "wasm-bindgen",
    "wasm-bindgen-futures",
    "web-sys",
    ]

    [[package]]
    name = "gloo-render"
    version = "0.1.1"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "2fd9306aef67cfd4449823aadcd14e3958e0800aa2183955a309112a84ec7764"
    dependencies = [
    "wasm-bindgen",
    "web-sys",
    ]

    [[package]]
    name = "gloo-storage"
    version = "0.2.2"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "5d6ab60bf5dbfd6f0ed1f7843da31b41010515c745735c970e821945ca91e480"
    dependencies = [
    "gloo-utils",
    "js-sys",
    "serde",
    "serde_json",
    "thiserror",
    "wasm-bindgen",
    "web-sys",
    ]

    [[package]]
    name = "gloo-timers"
    version = "0.2.4"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "5fb7d06c1c8cc2a29bee7ec961009a0b2caa0793ee4900c2ffb348734ba1c8f9"
    dependencies = [
    "js-sys",
    "wasm-bindgen",
    ]

    [[package]]
    name = "gloo-utils"
    version = "0.1.5"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "40913a05c8297adca04392f707b1e73b12ba7b8eab7244a4961580b1fd34063c"
    dependencies = [
    "js-sys",
    "serde",
    "serde_json",
    "wasm-bindgen",
    "web-sys",
    ]

    [[package]]
    name = "gloo-worker"
    version = "0.2.1"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "13471584da78061a28306d1359dd0178d8d6fc1c7c80e5e35d27260346e0516a"
    dependencies = [
    "anymap2",
    "bincode",
    "gloo-console",
    "gloo-utils",
    "js-sys",
    "serde",
    "wasm-bindgen",
    "wasm-bindgen-futures",
    "web-sys",
    ]

    [[package]]
    name = "hashbrown"
    version = "0.12.3"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"

    [[package]]
    name = "hermit-abi"
    version = "0.1.19"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
    dependencies = [
    "libc",
    ]

    [[package]]
    name = "implicit-clone"
    version = "0.3.2"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "a937e630d3907d421944abd8edb5288936f1fde83aaaf1a8c6c89bb4222f0677"
    dependencies = [
    "indexmap",
    ]

    [[package]]
    name = "indexmap"
    version = "1.9.2"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
    dependencies = [
    "autocfg",
    "hashbrown",
    ]

    [[package]]
    name = "itoa"
    version = "1.0.4"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc"

    [[package]]
    name = "js-sys"
    version = "0.3.60"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47"
    dependencies = [
    "wasm-bindgen",
    ]

    [[package]]
    name = "libc"
    version = "0.2.137"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"

    [[package]]
    name = "log"
    version = "0.4.17"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
    dependencies = [
    "cfg-if",
    ]

    [[package]]
    name = "memchr"
    version = "2.5.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"

    [[package]]
    name = "num_cpus"
    version = "1.14.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5"
    dependencies = [
    "hermit-abi",
    "libc",
    ]

    [[package]]
    name = "once_cell"
    version = "1.16.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"

    [[package]]
    name = "percent-encoding"
    version = "2.2.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"

    [[package]]
    name = "pin-project"
    version = "1.0.12"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc"
    dependencies = [
    "pin-project-internal",
    ]

    [[package]]
    name = "pin-project-internal"
    version = "1.0.12"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55"
    dependencies = [
    "proc-macro2",
    "quote",
    "syn",
    ]

    [[package]]
    name = "pin-project-lite"
    version = "0.2.9"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"

    [[package]]
    name = "pin-utils"
    version = "0.1.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"

    [[package]]
    name = "pinned"
    version = "0.1.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "a829027bd95e54cfe13e3e258a1ae7b645960553fb82b75ff852c29688ee595b"
    dependencies = [
    "futures",
    "rustversion",
    "thiserror",
    ]

    [[package]]
    name = "prettyplease"
    version = "0.1.21"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "c142c0e46b57171fe0c528bee8c5b7569e80f0c17e377cd0e30ea57dbc11bb51"
    dependencies = [
    "proc-macro2",
    "syn",
    ]

    [[package]]
    name = "proc-macro-error"
    version = "1.0.4"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
    dependencies = [
    "proc-macro-error-attr",
    "proc-macro2",
    "quote",
    "syn",
    "version_check",
    ]

    [[package]]
    name = "proc-macro-error-attr"
    version = "1.0.4"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
    dependencies = [
    "proc-macro2",
    "quote",
    "version_check",
    ]

    [[package]]
    name = "proc-macro2"
    version = "1.0.47"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
    dependencies = [
    "unicode-ident",
    ]

    [[package]]
    name = "prokio"
    version = "0.1.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "03b55e106e5791fa5a13abd13c85d6127312e8e09098059ca2bc9b03ca4cf488"
    dependencies = [
    "futures",
    "gloo",
    "num_cpus",
    "once_cell",
    "pin-project",
    "pinned",
    "tokio",
    "tokio-stream",
    "wasm-bindgen-futures",
    ]

    [[package]]
    name = "quote"
    version = "1.0.21"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
    dependencies = [
    "proc-macro2",
    ]

    [[package]]
    name = "rustversion"
    version = "1.0.9"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8"

    [[package]]
    name = "ryu"
    version = "1.0.11"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"

    [[package]]
    name = "serde"
    version = "1.0.147"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965"
    dependencies = [
    "serde_derive",
    ]

    [[package]]
    name = "serde-wasm-bindgen"
    version = "0.3.1"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "618365e8e586c22123d692b72a7d791d5ee697817b65a218cdf12a98870af0f7"
    dependencies = [
    "fnv",
    "js-sys",
    "serde",
    "wasm-bindgen",
    ]

    [[package]]
    name = "serde_derive"
    version = "1.0.147"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852"
    dependencies = [
    "proc-macro2",
    "quote",
    "syn",
    ]

    [[package]]
    name = "serde_json"
    version = "1.0.89"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db"
    dependencies = [
    "itoa",
    "ryu",
    "serde",
    ]

    [[package]]
    name = "serde_urlencoded"
    version = "0.7.1"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
    dependencies = [
    "form_urlencoded",
    "itoa",
    "ryu",
    "serde",
    ]

    [[package]]
    name = "slab"
    version = "0.4.7"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef"
    dependencies = [
    "autocfg",
    ]

    [[package]]
    name = "syn"
    version = "1.0.103"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d"
    dependencies = [
    "proc-macro2",
    "quote",
    "unicode-ident",
    ]

    [[package]]
    name = "thiserror"
    version = "1.0.37"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e"
    dependencies = [
    "thiserror-impl",
    ]

    [[package]]
    name = "thiserror-impl"
    version = "1.0.37"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb"
    dependencies = [
    "proc-macro2",
    "quote",
    "syn",
    ]

    [[package]]
    name = "tokio"
    version = "1.22.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "d76ce4a75fb488c605c54bf610f221cea8b0dafb53333c1a67e8ee199dcd2ae3"
    dependencies = [
    "autocfg",
    "pin-project-lite",
    ]

    [[package]]
    name = "tokio-stream"
    version = "0.1.11"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce"
    dependencies = [
    "futures-core",
    "pin-project-lite",
    "tokio",
    ]

    [[package]]
    name = "tracing"
    version = "0.1.37"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
    dependencies = [
    "cfg-if",
    "pin-project-lite",
    "tracing-attributes",
    "tracing-core",
    ]

    [[package]]
    name = "tracing-attributes"
    version = "0.1.23"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a"
    dependencies = [
    "proc-macro2",
    "quote",
    "syn",
    ]

    [[package]]
    name = "tracing-core"
    version = "0.1.30"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
    dependencies = [
    "once_cell",
    ]

    [[package]]
    name = "unicode-ident"
    version = "1.0.5"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"

    [[package]]
    name = "version_check"
    version = "0.9.4"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"

    [[package]]
    name = "wasm-bindgen"
    version = "0.2.83"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
    dependencies = [
    "cfg-if",
    "serde",
    "serde_json",
    "wasm-bindgen-macro",
    ]

    [[package]]
    name = "wasm-bindgen-backend"
    version = "0.2.83"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142"
    dependencies = [
    "bumpalo",
    "log",
    "once_cell",
    "proc-macro2",
    "quote",
    "syn",
    "wasm-bindgen-shared",
    ]

    [[package]]
    name = "wasm-bindgen-futures"
    version = "0.4.33"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d"
    dependencies = [
    "cfg-if",
    "js-sys",
    "wasm-bindgen",
    "web-sys",
    ]

    [[package]]
    name = "wasm-bindgen-macro"
    version = "0.2.83"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810"
    dependencies = [
    "quote",
    "wasm-bindgen-macro-support",
    ]

    [[package]]
    name = "wasm-bindgen-macro-support"
    version = "0.2.83"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
    dependencies = [
    "proc-macro2",
    "quote",
    "syn",
    "wasm-bindgen-backend",
    "wasm-bindgen-shared",
    ]

    [[package]]
    name = "wasm-bindgen-shared"
    version = "0.2.83"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"

    [[package]]
    name = "web-sys"
    version = "0.3.60"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f"
    dependencies = [
    "js-sys",
    "wasm-bindgen",
    ]

    [[package]]
    name = "yew"
    version = "0.20.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "5dbecfe44343b70cc2932c3eb445425969ae21754a8ab3a0966981c1cf7af1cc"
    dependencies = [
    "console_error_panic_hook",
    "futures",
    "gloo",
    "implicit-clone",
    "indexmap",
    "js-sys",
    "prokio",
    "rustversion",
    "serde",
    "slab",
    "thiserror",
    "tokio",
    "tracing",
    "wasm-bindgen",
    "wasm-bindgen-futures",
    "web-sys",
    "yew-macro",
    ]

    [[package]]
    name = "yew-macro"
    version = "0.20.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "b64c253c1d401f1ea868ca9988db63958cfa15a69f739101f338d6f05eea8301"
    dependencies = [
    "boolinator",
    "once_cell",
    "prettyplease",
    "proc-macro-error",
    "proc-macro2",
    "quote",
    "syn",
    ]
  2. craftyc0der renamed this gist Nov 27, 2022. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  3. craftyc0der revised this gist Nov 27, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -189,7 +189,7 @@ The `update` function is responsible for processing the messages sent from the J

    The rest of the code is just for rendering the data returned from Firebase.

    ![Haiku App](screenshot.png)
    ![Haiku App](https://gist.githubusercontent.com/craftyc0der/1e71964cc3e85d533f0f70985c22a74a/raw/01dd8ce087bcfd25aecf77c5a71959ae5df541ed/screenshot.png)

    ## Run this *gist*

  4. craftyc0der revised this gist Nov 27, 2022. 1 changed file with 0 additions and 2 deletions.
    2 changes: 0 additions & 2 deletions .gitignore
    Original file line number Diff line number Diff line change
    @@ -1,2 +0,0 @@
    /target
    /dist
  5. craftyc0der revised this gist Nov 27, 2022. 6 changed files with 15 additions and 14 deletions.
    4 changes: 4 additions & 0 deletions Cargo.toml
    Original file line number Diff line number Diff line change
    @@ -5,6 +5,10 @@ edition = "2021"

    # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

    [[bin]]
    name = "gist-yew-firebase"
    path = "main.rs"

    [dependencies]
    yew = { version = "0.20.0", features = ["csr"] }
    wasm-bindgen = {version = "^0.2"}
    16 changes: 9 additions & 7 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -58,7 +58,9 @@ You can find my `index.html` below in this *gist*. The critical thing to include

    The sample website we will build here will query a Firebase database for a list of rows that contain an object that contains a haiku poem. We will then render these data in the DOM using Yew. Because the Firebase SDK provided by Google is written in JavaScript, we will need `wasm-bindgen` to bridge the gap between Rust and JavaScript.

    #### Create src/main.rs
    In order to squeeze this into a *gist*, I've flattened the directory structure. Normally the `.rs` files would be in a `src` directory.

    #### Create main.rs

    You can find my `main.rs` below in this *gist*.

    @@ -81,7 +83,7 @@ For this example, the critical pieces are in `create` and `update`. We query Fir

    #### Write JavaScript code to interact with Firebase

    You can find my `src/js/index.js` below in this *gist*.
    You can find my `index.js` below in this *gist*.

    ```javascript
    const app = initializeApp(firebaseConfig);
    @@ -110,24 +112,24 @@ export function getHaiku(fnHaikuClear, fnHaikuAdd) {

    #### Setup `wasm-bindgen` for the JavaScript code

    You can find my `src/js/caller.rs` below in this *gist*.
    You can find my `caller.rs` below in this *gist*.

    ```rust
    use wasm_bindgen::prelude::*;

    // wasm-bindgen will automatically take care of including this script
    #[wasm_bindgen(module = "/src/js/index.js")]
    #[wasm_bindgen(module = "/index.js")]
    extern "C" {
    #[wasm_bindgen(js_name = "getHaiku")]
    pub fn get_haiku(callbackClear: JsValue, callbackAdd: JsValue);
    }
    ```

    This basically tells `wasm-bindgen` to include the `src/js/index.js` file in the final wasm file it creates and to expose the `getHaiku` function to Rust as `get_haiku(callbackClear: JsValue, callbackAdd: JsValue)`.
    This basically tells `wasm-bindgen` to include the `index.js` file in the final wasm file it creates and to expose the `getHaiku` function to Rust as `get_haiku(callbackClear: JsValue, callbackAdd: JsValue)`.

    #### Bring it all together in src/main.rs
    #### Bring it all together in main.rs

    You can find my `src/main.rs` below in this *gist*.
    You can find my `main.rs` below in this *gist*.

    The `create` function is responsible for querying Firebase and setting up the callbacks to process the data returned from Firebase. Note we do not manage the closures in the Rust compiler. We are cheating a little here and just using the `.into_js_value()` method to convert the closures to a `JsValue` which calls `drop()` on the closure so that we can call it multiple times in JavaScript land. This is not ideal, but it works for this example.

    2 changes: 1 addition & 1 deletion src/js/caller.rs → caller.rs
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    use wasm_bindgen::prelude::*;

    // wasm-bindgen will automatically take care of including this script
    #[wasm_bindgen(module = "/src/js/index.js")]
    #[wasm_bindgen(module = "/index.js")]
    extern "C" {
    #[wasm_bindgen(js_name = "getHaiku")]
    pub fn get_haiku(callbackClear: JsValue, callbackAdd: JsValue);
    File renamed without changes.
    6 changes: 1 addition & 5 deletions src/main.rs → main.rs
    Original file line number Diff line number Diff line change
    @@ -1,11 +1,7 @@
    use yew::prelude::*;
    use yew::{Component, Context, Html};
    use wasm_bindgen::{JsValue, closure::Closure};
    mod js;

    use crate::{
    js::caller
    };
    mod caller;

    pub enum Msg {
    HaikuClear,
    1 change: 0 additions & 1 deletion src/js/mod.rs
    Original file line number Diff line number Diff line change
    @@ -1 +0,0 @@
    pub mod caller;
  6. craftyc0der revised this gist Nov 27, 2022. 1 changed file with 6 additions and 0 deletions.
    6 changes: 6 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -189,6 +189,12 @@ The rest of the code is just for rendering the data returned from Firebase.

    ![Haiku App](screenshot.png)

    ## Run this *gist*

    ```bash
    trunk serve
    ```

    ## Future Work

    It would be a much better experience if we used `wasm-bindgen` to control the Firebase SDK directly rather than using the JavaScript SDK. This would allow us to use Rust types and memory management rather than having to convert everything to `JsValue` and back again. We could take that a step further and build idiomatic Rust wrappers around the Firebase SDK to make it more intuitive to use.
  7. craftyc0der revised this gist Nov 27, 2022. No changes.
  8. craftyc0der created this gist Nov 27, 2022.
    2 changes: 2 additions & 0 deletions .gitignore
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,2 @@
    /target
    /dist
    811 changes: 811 additions & 0 deletions Cargo.lock
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,811 @@
    # This file is automatically @generated by Cargo.
    # It is not intended for manual editing.
    version = 3

    [[package]]
    name = "anymap2"
    version = "0.13.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "d301b3b94cb4b2f23d7917810addbbaff90738e0ca2be692bd027e70d7e0330c"

    [[package]]
    name = "autocfg"
    version = "1.1.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"

    [[package]]
    name = "bincode"
    version = "1.3.3"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
    dependencies = [
    "serde",
    ]

    [[package]]
    name = "boolinator"
    version = "2.4.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "cfa8873f51c92e232f9bac4065cddef41b714152812bfc5f7672ba16d6ef8cd9"

    [[package]]
    name = "bumpalo"
    version = "3.11.1"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"

    [[package]]
    name = "cfg-if"
    version = "1.0.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"

    [[package]]
    name = "console_error_panic_hook"
    version = "0.1.7"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc"
    dependencies = [
    "cfg-if",
    "wasm-bindgen",
    ]

    [[package]]
    name = "fnv"
    version = "1.0.7"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"

    [[package]]
    name = "form_urlencoded"
    version = "1.1.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8"
    dependencies = [
    "percent-encoding",
    ]

    [[package]]
    name = "futures"
    version = "0.3.25"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0"
    dependencies = [
    "futures-channel",
    "futures-core",
    "futures-io",
    "futures-sink",
    "futures-task",
    "futures-util",
    ]

    [[package]]
    name = "futures-channel"
    version = "0.3.25"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed"
    dependencies = [
    "futures-core",
    "futures-sink",
    ]

    [[package]]
    name = "futures-core"
    version = "0.3.25"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac"

    [[package]]
    name = "futures-io"
    version = "0.3.25"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb"

    [[package]]
    name = "futures-macro"
    version = "0.3.25"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d"
    dependencies = [
    "proc-macro2",
    "quote",
    "syn",
    ]

    [[package]]
    name = "futures-sink"
    version = "0.3.25"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9"

    [[package]]
    name = "futures-task"
    version = "0.3.25"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea"

    [[package]]
    name = "futures-util"
    version = "0.3.25"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6"
    dependencies = [
    "futures-channel",
    "futures-core",
    "futures-io",
    "futures-macro",
    "futures-sink",
    "futures-task",
    "memchr",
    "pin-project-lite",
    "pin-utils",
    "slab",
    ]

    [[package]]
    name = "gist-yew-firebase"
    version = "0.1.0"
    dependencies = [
    "wasm-bindgen",
    "yew",
    ]

    [[package]]
    name = "gloo"
    version = "0.8.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "3a4bef6b277b3ab073253d4bca60761240cf8d6998f4bd142211957b69a61b20"
    dependencies = [
    "gloo-console",
    "gloo-dialogs",
    "gloo-events",
    "gloo-file",
    "gloo-history",
    "gloo-net",
    "gloo-render",
    "gloo-storage",
    "gloo-timers",
    "gloo-utils",
    "gloo-worker",
    ]

    [[package]]
    name = "gloo-console"
    version = "0.2.3"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "82b7ce3c05debe147233596904981848862b068862e9ec3e34be446077190d3f"
    dependencies = [
    "gloo-utils",
    "js-sys",
    "serde",
    "wasm-bindgen",
    "web-sys",
    ]

    [[package]]
    name = "gloo-dialogs"
    version = "0.1.1"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "67062364ac72d27f08445a46cab428188e2e224ec9e37efdba48ae8c289002e6"
    dependencies = [
    "wasm-bindgen",
    "web-sys",
    ]

    [[package]]
    name = "gloo-events"
    version = "0.1.2"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "68b107f8abed8105e4182de63845afcc7b69c098b7852a813ea7462a320992fc"
    dependencies = [
    "wasm-bindgen",
    "web-sys",
    ]

    [[package]]
    name = "gloo-file"
    version = "0.2.3"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "a8d5564e570a38b43d78bdc063374a0c3098c4f0d64005b12f9bbe87e869b6d7"
    dependencies = [
    "gloo-events",
    "js-sys",
    "wasm-bindgen",
    "web-sys",
    ]

    [[package]]
    name = "gloo-history"
    version = "0.1.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "f81af52c0d31e86242eecefe1ed4d066deb79cfb80f9f7da0847fac417396bfe"
    dependencies = [
    "gloo-events",
    "gloo-utils",
    "serde",
    "serde-wasm-bindgen",
    "serde_urlencoded",
    "thiserror",
    "wasm-bindgen",
    "web-sys",
    ]

    [[package]]
    name = "gloo-net"
    version = "0.2.4"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "ec897194fb9ac576c708f63d35604bc58f2a262b8cec0fabfed26f3991255f21"
    dependencies = [
    "futures-channel",
    "futures-core",
    "futures-sink",
    "gloo-utils",
    "js-sys",
    "pin-project",
    "serde",
    "serde_json",
    "thiserror",
    "wasm-bindgen",
    "wasm-bindgen-futures",
    "web-sys",
    ]

    [[package]]
    name = "gloo-render"
    version = "0.1.1"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "2fd9306aef67cfd4449823aadcd14e3958e0800aa2183955a309112a84ec7764"
    dependencies = [
    "wasm-bindgen",
    "web-sys",
    ]

    [[package]]
    name = "gloo-storage"
    version = "0.2.2"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "5d6ab60bf5dbfd6f0ed1f7843da31b41010515c745735c970e821945ca91e480"
    dependencies = [
    "gloo-utils",
    "js-sys",
    "serde",
    "serde_json",
    "thiserror",
    "wasm-bindgen",
    "web-sys",
    ]

    [[package]]
    name = "gloo-timers"
    version = "0.2.4"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "5fb7d06c1c8cc2a29bee7ec961009a0b2caa0793ee4900c2ffb348734ba1c8f9"
    dependencies = [
    "js-sys",
    "wasm-bindgen",
    ]

    [[package]]
    name = "gloo-utils"
    version = "0.1.5"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "40913a05c8297adca04392f707b1e73b12ba7b8eab7244a4961580b1fd34063c"
    dependencies = [
    "js-sys",
    "serde",
    "serde_json",
    "wasm-bindgen",
    "web-sys",
    ]

    [[package]]
    name = "gloo-worker"
    version = "0.2.1"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "13471584da78061a28306d1359dd0178d8d6fc1c7c80e5e35d27260346e0516a"
    dependencies = [
    "anymap2",
    "bincode",
    "gloo-console",
    "gloo-utils",
    "js-sys",
    "serde",
    "wasm-bindgen",
    "wasm-bindgen-futures",
    "web-sys",
    ]

    [[package]]
    name = "hashbrown"
    version = "0.12.3"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"

    [[package]]
    name = "hermit-abi"
    version = "0.1.19"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
    dependencies = [
    "libc",
    ]

    [[package]]
    name = "implicit-clone"
    version = "0.3.2"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "a937e630d3907d421944abd8edb5288936f1fde83aaaf1a8c6c89bb4222f0677"
    dependencies = [
    "indexmap",
    ]

    [[package]]
    name = "indexmap"
    version = "1.9.2"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
    dependencies = [
    "autocfg",
    "hashbrown",
    ]

    [[package]]
    name = "itoa"
    version = "1.0.4"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc"

    [[package]]
    name = "js-sys"
    version = "0.3.60"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47"
    dependencies = [
    "wasm-bindgen",
    ]

    [[package]]
    name = "libc"
    version = "0.2.137"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"

    [[package]]
    name = "log"
    version = "0.4.17"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
    dependencies = [
    "cfg-if",
    ]

    [[package]]
    name = "memchr"
    version = "2.5.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"

    [[package]]
    name = "num_cpus"
    version = "1.14.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5"
    dependencies = [
    "hermit-abi",
    "libc",
    ]

    [[package]]
    name = "once_cell"
    version = "1.16.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"

    [[package]]
    name = "percent-encoding"
    version = "2.2.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"

    [[package]]
    name = "pin-project"
    version = "1.0.12"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc"
    dependencies = [
    "pin-project-internal",
    ]

    [[package]]
    name = "pin-project-internal"
    version = "1.0.12"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55"
    dependencies = [
    "proc-macro2",
    "quote",
    "syn",
    ]

    [[package]]
    name = "pin-project-lite"
    version = "0.2.9"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"

    [[package]]
    name = "pin-utils"
    version = "0.1.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"

    [[package]]
    name = "pinned"
    version = "0.1.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "a829027bd95e54cfe13e3e258a1ae7b645960553fb82b75ff852c29688ee595b"
    dependencies = [
    "futures",
    "rustversion",
    "thiserror",
    ]

    [[package]]
    name = "prettyplease"
    version = "0.1.21"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "c142c0e46b57171fe0c528bee8c5b7569e80f0c17e377cd0e30ea57dbc11bb51"
    dependencies = [
    "proc-macro2",
    "syn",
    ]

    [[package]]
    name = "proc-macro-error"
    version = "1.0.4"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
    dependencies = [
    "proc-macro-error-attr",
    "proc-macro2",
    "quote",
    "syn",
    "version_check",
    ]

    [[package]]
    name = "proc-macro-error-attr"
    version = "1.0.4"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
    dependencies = [
    "proc-macro2",
    "quote",
    "version_check",
    ]

    [[package]]
    name = "proc-macro2"
    version = "1.0.47"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
    dependencies = [
    "unicode-ident",
    ]

    [[package]]
    name = "prokio"
    version = "0.1.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "03b55e106e5791fa5a13abd13c85d6127312e8e09098059ca2bc9b03ca4cf488"
    dependencies = [
    "futures",
    "gloo",
    "num_cpus",
    "once_cell",
    "pin-project",
    "pinned",
    "tokio",
    "tokio-stream",
    "wasm-bindgen-futures",
    ]

    [[package]]
    name = "quote"
    version = "1.0.21"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
    dependencies = [
    "proc-macro2",
    ]

    [[package]]
    name = "rustversion"
    version = "1.0.9"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8"

    [[package]]
    name = "ryu"
    version = "1.0.11"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"

    [[package]]
    name = "serde"
    version = "1.0.147"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965"
    dependencies = [
    "serde_derive",
    ]

    [[package]]
    name = "serde-wasm-bindgen"
    version = "0.3.1"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "618365e8e586c22123d692b72a7d791d5ee697817b65a218cdf12a98870af0f7"
    dependencies = [
    "fnv",
    "js-sys",
    "serde",
    "wasm-bindgen",
    ]

    [[package]]
    name = "serde_derive"
    version = "1.0.147"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852"
    dependencies = [
    "proc-macro2",
    "quote",
    "syn",
    ]

    [[package]]
    name = "serde_json"
    version = "1.0.89"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db"
    dependencies = [
    "itoa",
    "ryu",
    "serde",
    ]

    [[package]]
    name = "serde_urlencoded"
    version = "0.7.1"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
    dependencies = [
    "form_urlencoded",
    "itoa",
    "ryu",
    "serde",
    ]

    [[package]]
    name = "slab"
    version = "0.4.7"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef"
    dependencies = [
    "autocfg",
    ]

    [[package]]
    name = "syn"
    version = "1.0.103"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d"
    dependencies = [
    "proc-macro2",
    "quote",
    "unicode-ident",
    ]

    [[package]]
    name = "thiserror"
    version = "1.0.37"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e"
    dependencies = [
    "thiserror-impl",
    ]

    [[package]]
    name = "thiserror-impl"
    version = "1.0.37"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb"
    dependencies = [
    "proc-macro2",
    "quote",
    "syn",
    ]

    [[package]]
    name = "tokio"
    version = "1.22.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "d76ce4a75fb488c605c54bf610f221cea8b0dafb53333c1a67e8ee199dcd2ae3"
    dependencies = [
    "autocfg",
    "pin-project-lite",
    ]

    [[package]]
    name = "tokio-stream"
    version = "0.1.11"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce"
    dependencies = [
    "futures-core",
    "pin-project-lite",
    "tokio",
    ]

    [[package]]
    name = "tracing"
    version = "0.1.37"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
    dependencies = [
    "cfg-if",
    "pin-project-lite",
    "tracing-attributes",
    "tracing-core",
    ]

    [[package]]
    name = "tracing-attributes"
    version = "0.1.23"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a"
    dependencies = [
    "proc-macro2",
    "quote",
    "syn",
    ]

    [[package]]
    name = "tracing-core"
    version = "0.1.30"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
    dependencies = [
    "once_cell",
    ]

    [[package]]
    name = "unicode-ident"
    version = "1.0.5"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"

    [[package]]
    name = "version_check"
    version = "0.9.4"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"

    [[package]]
    name = "wasm-bindgen"
    version = "0.2.83"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
    dependencies = [
    "cfg-if",
    "serde",
    "serde_json",
    "wasm-bindgen-macro",
    ]

    [[package]]
    name = "wasm-bindgen-backend"
    version = "0.2.83"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142"
    dependencies = [
    "bumpalo",
    "log",
    "once_cell",
    "proc-macro2",
    "quote",
    "syn",
    "wasm-bindgen-shared",
    ]

    [[package]]
    name = "wasm-bindgen-futures"
    version = "0.4.33"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d"
    dependencies = [
    "cfg-if",
    "js-sys",
    "wasm-bindgen",
    "web-sys",
    ]

    [[package]]
    name = "wasm-bindgen-macro"
    version = "0.2.83"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810"
    dependencies = [
    "quote",
    "wasm-bindgen-macro-support",
    ]

    [[package]]
    name = "wasm-bindgen-macro-support"
    version = "0.2.83"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
    dependencies = [
    "proc-macro2",
    "quote",
    "syn",
    "wasm-bindgen-backend",
    "wasm-bindgen-shared",
    ]

    [[package]]
    name = "wasm-bindgen-shared"
    version = "0.2.83"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"

    [[package]]
    name = "web-sys"
    version = "0.3.60"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f"
    dependencies = [
    "js-sys",
    "wasm-bindgen",
    ]

    [[package]]
    name = "yew"
    version = "0.20.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "5dbecfe44343b70cc2932c3eb445425969ae21754a8ab3a0966981c1cf7af1cc"
    dependencies = [
    "console_error_panic_hook",
    "futures",
    "gloo",
    "implicit-clone",
    "indexmap",
    "js-sys",
    "prokio",
    "rustversion",
    "serde",
    "slab",
    "thiserror",
    "tokio",
    "tracing",
    "wasm-bindgen",
    "wasm-bindgen-futures",
    "web-sys",
    "yew-macro",
    ]

    [[package]]
    name = "yew-macro"
    version = "0.20.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "b64c253c1d401f1ea868ca9988db63958cfa15a69f739101f338d6f05eea8301"
    dependencies = [
    "boolinator",
    "once_cell",
    "prettyplease",
    "proc-macro-error",
    "proc-macro2",
    "quote",
    "syn",
    ]
    10 changes: 10 additions & 0 deletions Cargo.toml
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,10 @@
    [package]
    name = "gist-yew-firebase"
    version = "0.1.0"
    edition = "2021"

    # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

    [dependencies]
    yew = { version = "0.20.0", features = ["csr"] }
    wasm-bindgen = {version = "^0.2"}
    198 changes: 198 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,198 @@
    # Firebase & Yew

    ## Motivation

    I often use [Firebase](https://firebase.google.com/docs/reference/js) to store data for small projects. I've been using `wasm-bindgen` to build web tools for a while now (both in production and for personal use). Until now, I have not tried Yew to build a web app. If Yew works well with Firebase, I thought I might give it a shot for the next single page app (SPA) I build.

    ## Goals

    - Create basic Yew page
    - Add Firebase JS SDK
    - Write minimal JS code to interact with Firebase and do all rendering in Rust/Yew via callbacks

    ## Steps

    ### [Setup Yew](https://yew.rs/docs/getting-started/introduction)

    #### Setup Rust environment for wasm32-unknown-unknown target:

    ```bash
    rustup target add wasm32-unknown-unknown
    ```

    #### Install Trunk (packaging tool)

    ```bash
    cargo install --locked trunk
    ```
    ### [Setup Sample Yew App](https://yew.rs/docs/getting-started/build-a-sample-app)

    #### Create a new Yew project

    ```bash
    cargo new yew-app
    cd yew-app
    ```

    #### Update Cargo.toml to use Yew and wasm-bindgen

    ```toml
    ...
    [dependencies]
    yew = { version = "0.20.0", features = ["csr"] }
    wasm-bindgen = {version = "^0.2"}
    ```

    #### Create index.html

    You can find my `index.html` below in this *gist*. The critical thing to include is the hint for `trunk` to render the wasm files it creates.

    ```html
    <head>
    ...
    <link data-trunk rel="rust" />
    </head>
    ```

    ### Website Premise

    The sample website we will build here will query a Firebase database for a list of rows that contain an object that contains a haiku poem. We will then render these data in the DOM using Yew. Because the Firebase SDK provided by Google is written in JavaScript, we will need `wasm-bindgen` to bridge the gap between Rust and JavaScript.

    #### Create src/main.rs

    You can find my `main.rs` below in this *gist*.

    Things of note:

    - `Msg` enum is used to define messages that can be sent to the `HaikuPage` struct which is the main component of the app
    - `Msg::HaikuClear` is used to send a message to the `HaikuPage` to clear the haiku data
    - `Msg::HaikuRecord(Haiku)` is used to send a message to the `HaikuPage` to add a new haiku to the list
    - `Haiku` struct stores a single haiku row from Firebase
    - Firebase stores three fields for each haiku
    1. `int64` id
    2. `int64` featured
    3. `string` text
    - `HaikuPage` struct is the main component of the app
    - `haikus` is a vector of `Haiku` structs

    You should read the [Yew Documentation on Lifecycles](https://yew.rs/docs/advanced-topics/struct-components/lifecycle) to understand how the `create`, `update`, `view`, and `changed` functions work.

    For this example, the critical pieces are in `create` and `update`. We query Firebase in the `create` function and process the callbacks from Javascript land within the `update` function.

    #### Write JavaScript code to interact with Firebase

    You can find my `src/js/index.js` below in this *gist*.

    ```javascript
    const app = initializeApp(firebaseConfig);
    const database = getDatabase(app);

    // query Firebase for Haiku
    // `fnHaikuClear` and `fnHaikuAdd` are closures defined in Rust
    // that emit `Msg` messages to the `HaikuPage` `update` function
    export function getHaiku(fnHaikuClear, fnHaikuAdd) {
    const haikuRef = query(ref(database, 'haiku/'), orderByChild("featured"));
    onValue(haikuRef, (snapshot) => {
    // when data is returned, clear the current haiku list by
    // calling a closure passed in from the Rust
    fnHaikuClear();
    // then loop over the returned data
    snapshot.forEach((childSnapshot) => {
    var childKey = childSnapshot.key;
    var childData = childSnapshot.val();
    // and send each haiku to the Rust closure passed in above
    fnHaikuAdd(childKey, childData.featured, childData.text);
    });
    });
    console.log("Get Haiku");
    }
    ```

    #### Setup `wasm-bindgen` for the JavaScript code

    You can find my `src/js/caller.rs` below in this *gist*.

    ```rust
    use wasm_bindgen::prelude::*;

    // wasm-bindgen will automatically take care of including this script
    #[wasm_bindgen(module = "/src/js/index.js")]
    extern "C" {
    #[wasm_bindgen(js_name = "getHaiku")]
    pub fn get_haiku(callbackClear: JsValue, callbackAdd: JsValue);
    }
    ```

    This basically tells `wasm-bindgen` to include the `src/js/index.js` file in the final wasm file it creates and to expose the `getHaiku` function to Rust as `get_haiku(callbackClear: JsValue, callbackAdd: JsValue)`.

    #### Bring it all together in src/main.rs

    You can find my `src/main.rs` below in this *gist*.

    The `create` function is responsible for querying Firebase and setting up the callbacks to process the data returned from Firebase. Note we do not manage the closures in the Rust compiler. We are cheating a little here and just using the `.into_js_value()` method to convert the closures to a `JsValue` which calls `drop()` on the closure so that we can call it multiple times in JavaScript land. This is not ideal, but it works for this example.

    ```rust
    fn create(ctx: &Context<Self>) -> Self {
    // define callback for clearing the haiku list
    let callback_clear = ctx.link().callback(|_| Msg::HaikuClear);
    // define closure for clearing the haiku list
    let closure_clear = Closure::wrap(Box::new(move || {
    // call the clear callback
    // we want to clear the data array before we update all the data
    callback_clear.emit(());
    }) as Box<dyn FnMut()>);
    // define callback for adding a haiku to the list
    let callback_add = ctx.link().callback(Msg::HaikuRecord);
    // define closure for adding a haiku to the list
    let closure_add = Closure::wrap(Box::new(move |key: JsValue, featured: JsValue, text: JsValue| {
    let key_str = key.as_string().unwrap();
    let featured_int = featured.as_f64().unwrap() as i64;
    let key_int = key_str.parse::<i64>().unwrap();
    let haiku = Haiku {
    id: key_int,
    featured: featured_int,
    content: text.as_string().unwrap(),
    };
    callback_add.emit(haiku);
    }) as Box<dyn FnMut(JsValue, JsValue, JsValue)>);
    // call the get_haiku function in index.js
    // we use `into_js_value()` to convert the closures into javacript managed closures
    // they are no longer managed by rust
    // an unfortunate side effect of needing to use these more than once in JS land
    caller::get_haiku(closure_clear.into_js_value(), closure_add.into_js_value());
    Self {
    haikus: Vec::new(),
    }
    }
    ```

    The `update` function is responsible for processing the messages sent from the JavaScript land via the closures defined above.

    ```rust
    fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
    match msg {
    Msg::HaikuClear => {
    // clear the haiku list
    self.haikus.clear();
    true
    }
    Msg::HaikuRecord(haiku) => {
    // add a haiku to the list
    self.haikus.push(haiku);
    true
    }
    }
    }
    ```

    The rest of the code is just for rendering the data returned from Firebase.

    ![Haiku App](screenshot.png)

    ## Future Work

    It would be a much better experience if we used `wasm-bindgen` to control the Firebase SDK directly rather than using the JavaScript SDK. This would allow us to use Rust types and memory management rather than having to convert everything to `JsValue` and back again. We could take that a step further and build idiomatic Rust wrappers around the Firebase SDK to make it more intuitive to use.

    ## Conclusion

    Yew is an interesting framework. I am more accustomed to using [Lit](https://lit.dev/) and [Angular](https://angular.io/) for web development. I would be happier if Yew had first class debugging support. I think the solution is to build a lib around all the business logic so that you can debug that independently from the wasm code. But, that is a topic for another day.
    20 changes: 20 additions & 0 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,20 @@
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />

    <title>Firebase & Yew</title>
    <base data-trunk-public-url />
    <link
    rel="stylesheet"
    href="https://cdn.jsdelivr.net/npm/bulma@0.9.0/css/bulma.min.css"
    />
    <link data-trunk rel="sass" href="index.scss" />

    <link data-trunk rel="rust" />
    </head>

    <body>
    </body>
    </html>
    18 changes: 18 additions & 0 deletions index.scss
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,18 @@
    .hero {
    &.has-background {
    position: relative;
    overflow: hidden;
    }

    &-background {
    position: absolute;
    object-fit: cover;
    object-position: bottom;
    width: 100%;
    height: 100%;

    &.is-transparent {
    opacity: 0.3;
    }
    }
    }
    Binary file added screenshot.png
    Loading
    Sorry, something went wrong. Reload?
    Sorry, we cannot display this file.
    Sorry, this file is invalid so it cannot be displayed.
    8 changes: 8 additions & 0 deletions src/js/caller.rs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,8 @@
    use wasm_bindgen::prelude::*;

    // wasm-bindgen will automatically take care of including this script
    #[wasm_bindgen(module = "/src/js/index.js")]
    extern "C" {
    #[wasm_bindgen(js_name = "getHaiku")]
    pub fn get_haiku(callbackClear: JsValue, callbackAdd: JsValue);
    }
    37 changes: 37 additions & 0 deletions src/js/index.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,37 @@
    // import Firebase 9.14.0 SDK
    import { initializeApp } from "https://www.gstatic.com/firebasejs/9.14.0/firebase-app.js";
    import { getDatabase, query, onValue, orderByChild, ref } from "https://www.gstatic.com/firebasejs/9.14.0/firebase-database.js";

    // Initialize Firebase
    const firebaseConfig = {
    apiKey: "AIzaSyDM0TICdsfwD0Mj3j__oULR5EQg__hFTl0",
    authDomain: "craftycoder-e95a2.firebaseapp.com",
    databaseURL: "https://craftycoder-e95a2.firebaseio.com",
    projectId: "craftycoder-e95a2",
    storageBucket: "craftycoder-e95a2.appspot.com",
    messagingSenderId: "605879826235",
    appId: "1:605879826235:web:59773e7c77b01c6b6b691e",
    measurementId: "G-JS38X3LLBK"
    };
    const app = initializeApp(firebaseConfig);
    const database = getDatabase(app);

    // query Firebase for Haiku
    // `fnHaikuClear` and `fnHaikuAdd` are closures defined in Rust
    // that emit `Msg` messages to the `HaikuPage` `update` function
    export function getHaiku(fnHaikuClear, fnHaikuAdd) {
    const haikuRef = query(ref(database, 'haiku/'), orderByChild("featured"));
    onValue(haikuRef, (snapshot) => {
    // when data is returned, clear the current haiku list by
    // calling a closure passed in from the Rust
    fnHaikuClear();
    // then loop over the returned data
    snapshot.forEach((childSnapshot) => {
    var childKey = childSnapshot.key;
    var childData = childSnapshot.val();
    // and send each haiku to the Rust closure passed in above
    fnHaikuAdd(childKey, childData.featured, childData.text);
    });
    });
    console.log("Get Haiku");
    }
    1 change: 1 addition & 0 deletions src/js/mod.rs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1 @@
    pub mod caller;
    140 changes: 140 additions & 0 deletions src/main.rs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,140 @@
    use yew::prelude::*;
    use yew::{Component, Context, Html};
    use wasm_bindgen::{JsValue, closure::Closure};
    mod js;

    use crate::{
    js::caller
    };

    pub enum Msg {
    HaikuClear,
    HaikuRecord(Haiku),
    }

    #[derive(Clone, Debug, Eq, PartialEq)]
    pub struct Haiku {
    pub id: i64,
    pub featured: i64,
    pub content: String,
    }


    pub struct HaikuPage {
    haikus: Vec<Haiku>,
    }
    impl Component for HaikuPage {
    type Message = Msg;
    type Properties = ();
    fn create(ctx: &Context<Self>) -> Self {
    // define callback for clearing the haiku list
    let callback_clear = ctx.link().callback(|_| Msg::HaikuClear);
    // define closure for clearing the haiku list
    let closure_clear = Closure::wrap(Box::new(move || {
    // call the clear callback
    // we want to clear the data array before we update all the data
    callback_clear.emit(());
    }) as Box<dyn FnMut()>);
    // define callback for adding a haiku to the list
    let callback_add = ctx.link().callback(Msg::HaikuRecord);
    // define closure for adding a haiku to the list
    let closure_add = Closure::wrap(Box::new(move |key: JsValue, featured: JsValue, text: JsValue| {
    let key_str = key.as_string().unwrap();
    let featured_int = featured.as_f64().unwrap() as i64;
    let key_int = key_str.parse::<i64>().unwrap();
    let haiku = Haiku {
    id: key_int,
    featured: featured_int,
    content: text.as_string().unwrap(),
    };
    callback_add.emit(haiku);
    }) as Box<dyn FnMut(JsValue, JsValue, JsValue)>);
    // call the get_haiku function in index.js
    // we use `into_js_value()` to convert the closures into javacript managed closures
    // they are no longer managed by rust
    // an unfortunate side effect of needing to use these more than once in JS land
    caller::get_haiku(closure_clear.into_js_value(), closure_add.into_js_value());
    Self {
    haikus: Vec::new(),
    }
    }

    fn changed(&mut self, _ctx: &Context<Self>, _old_props: &Self::Properties) -> bool {
    true
    }

    fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
    match msg {
    Msg::HaikuClear => {
    // clear the haiku list
    // log::info!("clear");
    self.haikus.clear();
    true
    }
    Msg::HaikuRecord(haiku) => {
    // add a haiku to the list
    // log::info!("value: {:?}", value);
    self.haikus.push(haiku);
    true
    }
    }
    }

    fn view(&self, _ctx: &Context<Self>) -> Html {
    html! {
    <>
    <section class="hero is-small is-light has-background">
    <div class="hero-body">
    <div class="container">
    <h1 class="title">
    { "Haiku" }
    </h1>
    </div>
    </div>
    </section>
    <div class="section container">
    { self.view_content() }
    </div>
    </>
    }
    }
    }
    impl HaikuPage {
    fn view_content(&self) -> Html {
    html! {
    <div class="columns is-multiline is-mobile">
    // loop through the haiku list
    { for self.haikus.iter().map(|haiku| {
    //split haiku into array on <br>
    let haiku_array: Vec<&str> = haiku.content.split("<br>").collect();
    html! {
    <div class="column is-half">
    <div class="card">
    <div class="card-content">
    <div class="content">
    <h5 style="text-align: center;">
    {
    for haiku_array.iter().map(|line| {
    html! {
    <div>
    { line }
    </div>
    }
    })
    }
    </h5>
    </div>
    </div>
    </div>
    </div>
    }})
    }
    </div>
    }
    }
    }


    fn main() {
    yew::Renderer::<HaikuPage>::new().render();
    }
  9. craftyc0der created this gist Nov 27, 2022.
    198 changes: 198 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,198 @@
    # Firebase & Yew

    ## Motivation

    I often use [Firebase](https://firebase.google.com/docs/reference/js) to store data for small projects. I've been using `wasm-bindgen` to build web tools for a while now (both in production and for personal use). Until now, I have not tried Yew to build a web app. If Yew works well with Firebase, I thought I might give it a shot for the next single page app (SPA) I build.

    ## Goals

    - Create basic Yew page
    - Add Firebase JS SDK
    - Write minimal JS code to interact with Firebase and do all rendering in Rust/Yew via callbacks

    ## Steps

    ### [Setup Yew](https://yew.rs/docs/getting-started/introduction)

    #### Setup Rust environment for wasm32-unknown-unknown target:

    ```bash
    rustup target add wasm32-unknown-unknown
    ```

    #### Install Trunk (packaging tool)

    ```bash
    cargo install --locked trunk
    ```
    ### [Setup Sample Yew App](https://yew.rs/docs/getting-started/build-a-sample-app)

    #### Create a new Yew project

    ```bash
    cargo new yew-app
    cd yew-app
    ```

    #### Update Cargo.toml to use Yew and wasm-bindgen

    ```toml
    ...
    [dependencies]
    yew = { version = "0.20.0", features = ["csr"] }
    wasm-bindgen = {version = "^0.2"}
    ```

    #### Create index.html

    You can find my `index.html` below in this *gist*. The critical thing to include is the hint for `trunk` to render the wasm files it creates.

    ```html
    <head>
    ...
    <link data-trunk rel="rust" />
    </head>
    ```

    ### Website Premise

    The sample website we will build here will query a Firebase database for a list of rows that contain an object that contains a haiku poem. We will then render these data in the DOM using Yew. Because the Firebase SDK provided by Google is written in JavaScript, we will need `wasm-bindgen` to bridge the gap between Rust and JavaScript.

    #### Create src/main.rs

    You can find my `main.rs` below in this *gist*.

    Things of note:

    - `Msg` enum is used to define messages that can be sent to the `HaikuPage` struct which is the main component of the app
    - `Msg::HaikuClear` is used to send a message to the `HaikuPage` to clear the haiku data
    - `Msg::HaikuRecord(Haiku)` is used to send a message to the `HaikuPage` to add a new haiku to the list
    - `Haiku` struct stores a single haiku row from Firebase
    - Firebase stores three fields for each haiku
    1. `int64` id
    2. `int64` featured
    3. `string` text
    - `HaikuPage` struct is the main component of the app
    - `haikus` is a vector of `Haiku` structs

    You should read the [Yew Documentation on Lifecycles](https://yew.rs/docs/advanced-topics/struct-components/lifecycle) to understand how the `create`, `update`, `view`, and `changed` functions work.

    For this example, the critical pieces are in `create` and `update`. We query Firebase in the `create` function and process the callbacks from Javascript land within the `update` function.

    #### Write JavaScript code to interact with Firebase

    You can find my `src/js/index.js` below in this *gist*.

    ```javascript
    const app = initializeApp(firebaseConfig);
    const database = getDatabase(app);

    // query Firebase for Haiku
    // `fnHaikuClear` and `fnHaikuAdd` are closures defined in Rust
    // that emit `Msg` messages to the `HaikuPage` `update` function
    export function getHaiku(fnHaikuClear, fnHaikuAdd) {
    const haikuRef = query(ref(database, 'haiku/'), orderByChild("featured"));
    onValue(haikuRef, (snapshot) => {
    // when data is returned, clear the current haiku list by
    // calling a closure passed in from the Rust
    fnHaikuClear();
    // then loop over the returned data
    snapshot.forEach((childSnapshot) => {
    var childKey = childSnapshot.key;
    var childData = childSnapshot.val();
    // and send each haiku to the Rust closure passed in above
    fnHaikuAdd(childKey, childData.featured, childData.text);
    });
    });
    console.log("Get Haiku");
    }
    ```

    #### Setup `wasm-bindgen` for the JavaScript code

    You can find my `src/js/caller.rs` below in this *gist*.

    ```rust
    use wasm_bindgen::prelude::*;

    // wasm-bindgen will automatically take care of including this script
    #[wasm_bindgen(module = "/src/js/index.js")]
    extern "C" {
    #[wasm_bindgen(js_name = "getHaiku")]
    pub fn get_haiku(callbackClear: JsValue, callbackAdd: JsValue);
    }
    ```

    This basically tells `wasm-bindgen` to include the `src/js/index.js` file in the final wasm file it creates and to expose the `getHaiku` function to Rust as `get_haiku(callbackClear: JsValue, callbackAdd: JsValue)`.

    #### Bring it all together in src/main.rs

    You can find my `src/main.rs` below in this *gist*.

    The `create` function is responsible for querying Firebase and setting up the callbacks to process the data returned from Firebase. Note we do not manage the closures in the Rust compiler. We are cheating a little here and just using the `.into_js_value()` method to convert the closures to a `JsValue` which calls `drop()` on the closure so that we can call it multiple times in JavaScript land. This is not ideal, but it works for this example.

    ```rust
    fn create(ctx: &Context<Self>) -> Self {
    // define callback for clearing the haiku list
    let callback_clear = ctx.link().callback(|_| Msg::HaikuClear);
    // define closure for clearing the haiku list
    let closure_clear = Closure::wrap(Box::new(move || {
    // call the clear callback
    // we want to clear the data array before we update all the data
    callback_clear.emit(());
    }) as Box<dyn FnMut()>);
    // define callback for adding a haiku to the list
    let callback_add = ctx.link().callback(Msg::HaikuRecord);
    // define closure for adding a haiku to the list
    let closure_add = Closure::wrap(Box::new(move |key: JsValue, featured: JsValue, text: JsValue| {
    let key_str = key.as_string().unwrap();
    let featured_int = featured.as_f64().unwrap() as i64;
    let key_int = key_str.parse::<i64>().unwrap();
    let haiku = Haiku {
    id: key_int,
    featured: featured_int,
    content: text.as_string().unwrap(),
    };
    callback_add.emit(haiku);
    }) as Box<dyn FnMut(JsValue, JsValue, JsValue)>);
    // call the get_haiku function in index.js
    // we use `into_js_value()` to convert the closures into javacript managed closures
    // they are no longer managed by rust
    // an unfortunate side effect of needing to use these more than once in JS land
    caller::get_haiku(closure_clear.into_js_value(), closure_add.into_js_value());
    Self {
    haikus: Vec::new(),
    }
    }
    ```

    The `update` function is responsible for processing the messages sent from the JavaScript land via the closures defined above.

    ```rust
    fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
    match msg {
    Msg::HaikuClear => {
    // clear the haiku list
    self.haikus.clear();
    true
    }
    Msg::HaikuRecord(haiku) => {
    // add a haiku to the list
    self.haikus.push(haiku);
    true
    }
    }
    }
    ```

    The rest of the code is just for rendering the data returned from Firebase.

    ![Haiku App](screenshot.png)

    ## Future Work

    It would be a much better experience if we used `wasm-bindgen` to control the Firebase SDK directly rather than using the JavaScript SDK. This would allow us to use Rust types and memory management rather than having to convert everything to `JsValue` and back again. We could take that a step further and build idiomatic Rust wrappers around the Firebase SDK to make it more intuitive to use.

    ## Conclusion

    Yew is an interesting framework. I am more accustomed to using [Lit](https://lit.dev/) and [Angular](https://angular.io/) for web development. I would be happier if Yew had first class debugging support. I think the solution is to build a lib around all the business logic so that you can debug that independently from the wasm code. But, that is a topic for another day.