├── .editorconfig ├── .github └── workflows │ └── build.yml ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── deno.jsonc ├── deno.lock ├── images └── macos_soundName_typings.png ├── run_tests.sh ├── src └── lib.rs ├── tests ├── basic.test.ts ├── options.test.ts └── platforms.test.ts └── ts ├── mod.ts ├── notification.ts └── plugin.ts /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # All files 7 | [*] 8 | charset = utf-8 9 | end_of_line = lf 10 | indent_size = 2 11 | indent_style = space 12 | insert_final_newline = true 13 | trim_trailing_whitespace = true 14 | 15 | [*.rust] 16 | indent_size = 4 -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | paths: 7 | - "Cargo.toml" 8 | - "src/**" 9 | - "ts/**" 10 | - ".github/workflows/**" 11 | - "deno.jsonc" 12 | 13 | jobs: 14 | build: 15 | name: ${{ matrix.kind }} ${{ matrix.os }} 16 | runs-on: ${{ matrix.os }} 17 | timeout-minutes: 15 18 | strategy: 19 | matrix: 20 | os: [macOS-latest, ubuntu-latest, windows-latest] 21 | 22 | env: 23 | GH_ACTIONS: true 24 | CARGO_TERM_COLOR: always 25 | RUST_BACKTRACE: full 26 | DENO_BUILD_MODE: release 27 | 28 | steps: 29 | - name: Clone repository 30 | uses: actions/checkout@v3 31 | 32 | - name: Setup deno 33 | uses: denoland/setup-deno@v1 34 | with: 35 | deno-version: v1.x 36 | 37 | # TODO: Replace this with actions-rs 38 | - name: Setup rust 39 | # When rustup is updated, it tries to replace its binary, which on Windows is somehow locked. 40 | # This can result in the CI failure, see: https://github.com/rust-lang/rustup/issues/3029 41 | run: | 42 | rustup set auto-self-update disable 43 | rustup toolchain install stable --profile minimal 44 | 45 | - name: Install x86_64 AND aarch64 targets (mac) 46 | if: matrix.os == 'macOS-latest' 47 | run: | 48 | rustup target install x86_64-apple-darwin 49 | rustup target install aarch64-apple-darwin 50 | 51 | - name: Setup rust-cache 52 | uses: Swatinem/rust-cache@v2.2.0 53 | 54 | - name: Install required build packages (linux) 55 | if: matrix.os == 'ubuntu-latest' 56 | run: | 57 | sudo apt-get update 58 | sudo apt-get install libdbus-1-dev pkg-config libdbus-1-3 59 | 60 | - name: Log versions 61 | run: | 62 | deno --version 63 | rustc --version 64 | cargo --version 65 | 66 | - name: Build (linux, windows) 67 | if: matrix.os == 'ubuntu-latest' || matrix.os == 'windows-latest' 68 | run: deno task build:release 69 | 70 | - name: Build (macos x86_64) 71 | if: matrix.os == 'macOS-latest' 72 | run: | 73 | deno task build:release --target x86_64-apple-darwin 74 | cp ./target/x86_64-apple-darwin/release/libdeno_notify.dylib ./target/x86_64-apple-darwin/release/libdeno_notify.x86_64.dylib 75 | 76 | - name: Build (macos aarch64) 77 | if: matrix.os == 'macOS-latest' 78 | run: | 79 | deno task build:release --target aarch64-apple-darwin 80 | cp ./target/aarch64-apple-darwin/release/libdeno_notify.dylib ./target/aarch64-apple-darwin/release/libdeno_notify.aarch64.dylib 81 | 82 | # - name: Run tests 83 | # env: 84 | # NOTIFY_PLUGIN_URL: ./target/release/ 85 | # run: deno test --unstable --allow-all ./tests/*.ts 86 | 87 | - name: Release Plugin 88 | uses: softprops/action-gh-release@master 89 | env: 90 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 91 | with: 92 | tag_name: "deno_notify release" 93 | draft: true 94 | files: | 95 | ./target/x86_64-apple-darwin/release/libdeno_notify.x86_64.dylib 96 | ./target/aarch64-apple-darwin/release/libdeno_notify.aarch64.dylib 97 | ./target/release/libdeno_notify.so 98 | ./target/release/deno_notify.dll 99 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | .deno_plugins 3 | .DS_STORE 4 | .vscode -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "aho-corasick" 7 | version = "0.7.18" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" 10 | dependencies = [ 11 | "memchr", 12 | ] 13 | 14 | [[package]] 15 | name = "anyhow" 16 | version = "1.0.68" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61" 19 | 20 | [[package]] 21 | name = "async-broadcast" 22 | version = "0.5.0" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "1b19760fa2b7301cf235360ffd6d3558b1ed4249edd16d6cca8d690cee265b95" 25 | dependencies = [ 26 | "event-listener", 27 | "futures-core", 28 | "parking_lot", 29 | ] 30 | 31 | [[package]] 32 | name = "async-executor" 33 | version = "1.5.0" 34 | source = "registry+https://github.com/rust-lang/crates.io-index" 35 | checksum = "17adb73da160dfb475c183343c8cccd80721ea5a605d3eb57125f0a7b7a92d0b" 36 | dependencies = [ 37 | "async-lock", 38 | "async-task", 39 | "concurrent-queue", 40 | "fastrand", 41 | "futures-lite", 42 | "slab", 43 | ] 44 | 45 | [[package]] 46 | name = "async-io" 47 | version = "1.12.0" 48 | source = "registry+https://github.com/rust-lang/crates.io-index" 49 | checksum = "8c374dda1ed3e7d8f0d9ba58715f924862c63eae6849c92d3a18e7fbde9e2794" 50 | dependencies = [ 51 | "async-lock", 52 | "autocfg", 53 | "concurrent-queue", 54 | "futures-lite", 55 | "libc", 56 | "log", 57 | "parking", 58 | "polling", 59 | "slab", 60 | "socket2", 61 | "waker-fn", 62 | "windows-sys", 63 | ] 64 | 65 | [[package]] 66 | name = "async-lock" 67 | version = "2.6.0" 68 | source = "registry+https://github.com/rust-lang/crates.io-index" 69 | checksum = "c8101efe8695a6c17e02911402145357e718ac92d3ff88ae8419e84b1707b685" 70 | dependencies = [ 71 | "event-listener", 72 | "futures-lite", 73 | ] 74 | 75 | [[package]] 76 | name = "async-recursion" 77 | version = "1.0.2" 78 | source = "registry+https://github.com/rust-lang/crates.io-index" 79 | checksum = "3b015a331cc64ebd1774ba119538573603427eaace0a1950c423ab971f903796" 80 | dependencies = [ 81 | "proc-macro2", 82 | "quote", 83 | "syn", 84 | ] 85 | 86 | [[package]] 87 | name = "async-task" 88 | version = "4.3.0" 89 | source = "registry+https://github.com/rust-lang/crates.io-index" 90 | checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524" 91 | 92 | [[package]] 93 | name = "async-trait" 94 | version = "0.1.61" 95 | source = "registry+https://github.com/rust-lang/crates.io-index" 96 | checksum = "705339e0e4a9690e2908d2b3d049d85682cf19fbd5782494498fbf7003a6a282" 97 | dependencies = [ 98 | "proc-macro2", 99 | "quote", 100 | "syn", 101 | ] 102 | 103 | [[package]] 104 | name = "autocfg" 105 | version = "1.1.0" 106 | source = "registry+https://github.com/rust-lang/crates.io-index" 107 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 108 | 109 | [[package]] 110 | name = "base64" 111 | version = "0.13.1" 112 | source = "registry+https://github.com/rust-lang/crates.io-index" 113 | checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" 114 | 115 | [[package]] 116 | name = "bitflags" 117 | version = "1.3.2" 118 | source = "registry+https://github.com/rust-lang/crates.io-index" 119 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 120 | 121 | [[package]] 122 | name = "block" 123 | version = "0.1.6" 124 | source = "registry+https://github.com/rust-lang/crates.io-index" 125 | checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" 126 | 127 | [[package]] 128 | name = "block-buffer" 129 | version = "0.10.3" 130 | source = "registry+https://github.com/rust-lang/crates.io-index" 131 | checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" 132 | dependencies = [ 133 | "generic-array", 134 | ] 135 | 136 | [[package]] 137 | name = "byteorder" 138 | version = "1.4.3" 139 | source = "registry+https://github.com/rust-lang/crates.io-index" 140 | checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" 141 | 142 | [[package]] 143 | name = "bytes" 144 | version = "1.2.1" 145 | source = "registry+https://github.com/rust-lang/crates.io-index" 146 | checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" 147 | 148 | [[package]] 149 | name = "cc" 150 | version = "1.0.72" 151 | source = "registry+https://github.com/rust-lang/crates.io-index" 152 | checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" 153 | 154 | [[package]] 155 | name = "cfg-if" 156 | version = "1.0.0" 157 | source = "registry+https://github.com/rust-lang/crates.io-index" 158 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 159 | 160 | [[package]] 161 | name = "concurrent-queue" 162 | version = "2.1.0" 163 | source = "registry+https://github.com/rust-lang/crates.io-index" 164 | checksum = "c278839b831783b70278b14df4d45e1beb1aad306c07bb796637de9a0e323e8e" 165 | dependencies = [ 166 | "crossbeam-utils", 167 | ] 168 | 169 | [[package]] 170 | name = "convert_case" 171 | version = "0.4.0" 172 | source = "registry+https://github.com/rust-lang/crates.io-index" 173 | checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" 174 | 175 | [[package]] 176 | name = "cpufeatures" 177 | version = "0.2.5" 178 | source = "registry+https://github.com/rust-lang/crates.io-index" 179 | checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" 180 | dependencies = [ 181 | "libc", 182 | ] 183 | 184 | [[package]] 185 | name = "crossbeam-utils" 186 | version = "0.8.14" 187 | source = "registry+https://github.com/rust-lang/crates.io-index" 188 | checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" 189 | dependencies = [ 190 | "cfg-if", 191 | ] 192 | 193 | [[package]] 194 | name = "crypto-common" 195 | version = "0.1.6" 196 | source = "registry+https://github.com/rust-lang/crates.io-index" 197 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 198 | dependencies = [ 199 | "generic-array", 200 | "typenum", 201 | ] 202 | 203 | [[package]] 204 | name = "deno_core" 205 | version = "0.168.0" 206 | source = "registry+https://github.com/rust-lang/crates.io-index" 207 | checksum = "9be5363b163146294f1f329b47691d7ec459540d1cee353ef7df63a972a84ac9" 208 | dependencies = [ 209 | "anyhow", 210 | "bytes", 211 | "deno_ops", 212 | "futures", 213 | "indexmap", 214 | "libc", 215 | "log", 216 | "once_cell", 217 | "parking_lot", 218 | "pin-project", 219 | "serde", 220 | "serde_json", 221 | "serde_v8", 222 | "smallvec", 223 | "sourcemap", 224 | "url", 225 | "v8", 226 | ] 227 | 228 | [[package]] 229 | name = "deno_notify" 230 | version = "1.4.3" 231 | dependencies = [ 232 | "deno_core", 233 | "futures", 234 | "notify-rust", 235 | "serde", 236 | ] 237 | 238 | [[package]] 239 | name = "deno_ops" 240 | version = "0.46.0" 241 | source = "registry+https://github.com/rust-lang/crates.io-index" 242 | checksum = "14347263e2433b60c689f9aaf545cc93f1b4be57d4735c3c498e165545550a14" 243 | dependencies = [ 244 | "once_cell", 245 | "pmutil", 246 | "proc-macro-crate", 247 | "proc-macro2", 248 | "quote", 249 | "regex", 250 | "syn", 251 | ] 252 | 253 | [[package]] 254 | name = "derivative" 255 | version = "2.2.0" 256 | source = "registry+https://github.com/rust-lang/crates.io-index" 257 | checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" 258 | dependencies = [ 259 | "proc-macro2", 260 | "quote", 261 | "syn", 262 | ] 263 | 264 | [[package]] 265 | name = "derive_more" 266 | version = "0.99.17" 267 | source = "registry+https://github.com/rust-lang/crates.io-index" 268 | checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" 269 | dependencies = [ 270 | "convert_case", 271 | "proc-macro2", 272 | "quote", 273 | "rustc_version 0.4.0", 274 | "syn", 275 | ] 276 | 277 | [[package]] 278 | name = "digest" 279 | version = "0.10.6" 280 | source = "registry+https://github.com/rust-lang/crates.io-index" 281 | checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" 282 | dependencies = [ 283 | "block-buffer", 284 | "crypto-common", 285 | ] 286 | 287 | [[package]] 288 | name = "dirs" 289 | version = "4.0.0" 290 | source = "registry+https://github.com/rust-lang/crates.io-index" 291 | checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" 292 | dependencies = [ 293 | "dirs-sys", 294 | ] 295 | 296 | [[package]] 297 | name = "dirs-next" 298 | version = "2.0.0" 299 | source = "registry+https://github.com/rust-lang/crates.io-index" 300 | checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" 301 | dependencies = [ 302 | "cfg-if", 303 | "dirs-sys-next", 304 | ] 305 | 306 | [[package]] 307 | name = "dirs-sys" 308 | version = "0.3.7" 309 | source = "registry+https://github.com/rust-lang/crates.io-index" 310 | checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" 311 | dependencies = [ 312 | "libc", 313 | "redox_users", 314 | "winapi", 315 | ] 316 | 317 | [[package]] 318 | name = "dirs-sys-next" 319 | version = "0.1.2" 320 | source = "registry+https://github.com/rust-lang/crates.io-index" 321 | checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" 322 | dependencies = [ 323 | "libc", 324 | "redox_users", 325 | "winapi", 326 | ] 327 | 328 | [[package]] 329 | name = "either" 330 | version = "1.6.1" 331 | source = "registry+https://github.com/rust-lang/crates.io-index" 332 | checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" 333 | 334 | [[package]] 335 | name = "enumflags2" 336 | version = "0.7.5" 337 | source = "registry+https://github.com/rust-lang/crates.io-index" 338 | checksum = "e75d4cd21b95383444831539909fbb14b9dc3fdceb2a6f5d36577329a1f55ccb" 339 | dependencies = [ 340 | "enumflags2_derive", 341 | "serde", 342 | ] 343 | 344 | [[package]] 345 | name = "enumflags2_derive" 346 | version = "0.7.4" 347 | source = "registry+https://github.com/rust-lang/crates.io-index" 348 | checksum = "f58dc3c5e468259f19f2d46304a6b28f1c3d034442e14b322d2b850e36f6d5ae" 349 | dependencies = [ 350 | "proc-macro2", 351 | "quote", 352 | "syn", 353 | ] 354 | 355 | [[package]] 356 | name = "event-listener" 357 | version = "2.5.3" 358 | source = "registry+https://github.com/rust-lang/crates.io-index" 359 | checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" 360 | 361 | [[package]] 362 | name = "fastrand" 363 | version = "1.6.0" 364 | source = "registry+https://github.com/rust-lang/crates.io-index" 365 | checksum = "779d043b6a0b90cc4c0ed7ee380a6504394cee7efd7db050e3774eee387324b2" 366 | dependencies = [ 367 | "instant", 368 | ] 369 | 370 | [[package]] 371 | name = "form_urlencoded" 372 | version = "1.1.0" 373 | source = "registry+https://github.com/rust-lang/crates.io-index" 374 | checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" 375 | dependencies = [ 376 | "percent-encoding", 377 | ] 378 | 379 | [[package]] 380 | name = "fslock" 381 | version = "0.1.8" 382 | source = "registry+https://github.com/rust-lang/crates.io-index" 383 | checksum = "57eafdd0c16f57161105ae1b98a1238f97645f2f588438b2949c99a2af9616bf" 384 | dependencies = [ 385 | "libc", 386 | "winapi", 387 | ] 388 | 389 | [[package]] 390 | name = "futures" 391 | version = "0.3.25" 392 | source = "registry+https://github.com/rust-lang/crates.io-index" 393 | checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0" 394 | dependencies = [ 395 | "futures-channel", 396 | "futures-core", 397 | "futures-executor", 398 | "futures-io", 399 | "futures-sink", 400 | "futures-task", 401 | "futures-util", 402 | ] 403 | 404 | [[package]] 405 | name = "futures-channel" 406 | version = "0.3.25" 407 | source = "registry+https://github.com/rust-lang/crates.io-index" 408 | checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" 409 | dependencies = [ 410 | "futures-core", 411 | "futures-sink", 412 | ] 413 | 414 | [[package]] 415 | name = "futures-core" 416 | version = "0.3.25" 417 | source = "registry+https://github.com/rust-lang/crates.io-index" 418 | checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" 419 | 420 | [[package]] 421 | name = "futures-executor" 422 | version = "0.3.25" 423 | source = "registry+https://github.com/rust-lang/crates.io-index" 424 | checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2" 425 | dependencies = [ 426 | "futures-core", 427 | "futures-task", 428 | "futures-util", 429 | ] 430 | 431 | [[package]] 432 | name = "futures-io" 433 | version = "0.3.25" 434 | source = "registry+https://github.com/rust-lang/crates.io-index" 435 | checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" 436 | 437 | [[package]] 438 | name = "futures-lite" 439 | version = "1.12.0" 440 | source = "registry+https://github.com/rust-lang/crates.io-index" 441 | checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" 442 | dependencies = [ 443 | "fastrand", 444 | "futures-core", 445 | "futures-io", 446 | "memchr", 447 | "parking", 448 | "pin-project-lite", 449 | "waker-fn", 450 | ] 451 | 452 | [[package]] 453 | name = "futures-macro" 454 | version = "0.3.25" 455 | source = "registry+https://github.com/rust-lang/crates.io-index" 456 | checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" 457 | dependencies = [ 458 | "proc-macro2", 459 | "quote", 460 | "syn", 461 | ] 462 | 463 | [[package]] 464 | name = "futures-sink" 465 | version = "0.3.25" 466 | source = "registry+https://github.com/rust-lang/crates.io-index" 467 | checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" 468 | 469 | [[package]] 470 | name = "futures-task" 471 | version = "0.3.25" 472 | source = "registry+https://github.com/rust-lang/crates.io-index" 473 | checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" 474 | 475 | [[package]] 476 | name = "futures-util" 477 | version = "0.3.25" 478 | source = "registry+https://github.com/rust-lang/crates.io-index" 479 | checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" 480 | dependencies = [ 481 | "futures-channel", 482 | "futures-core", 483 | "futures-io", 484 | "futures-macro", 485 | "futures-sink", 486 | "futures-task", 487 | "memchr", 488 | "pin-project-lite", 489 | "pin-utils", 490 | "slab", 491 | ] 492 | 493 | [[package]] 494 | name = "generic-array" 495 | version = "0.14.6" 496 | source = "registry+https://github.com/rust-lang/crates.io-index" 497 | checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" 498 | dependencies = [ 499 | "typenum", 500 | "version_check", 501 | ] 502 | 503 | [[package]] 504 | name = "getrandom" 505 | version = "0.2.5" 506 | source = "registry+https://github.com/rust-lang/crates.io-index" 507 | checksum = "d39cd93900197114fa1fcb7ae84ca742095eed9442088988ae74fa744e930e77" 508 | dependencies = [ 509 | "cfg-if", 510 | "libc", 511 | "wasi", 512 | ] 513 | 514 | [[package]] 515 | name = "hashbrown" 516 | version = "0.11.2" 517 | source = "registry+https://github.com/rust-lang/crates.io-index" 518 | checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" 519 | 520 | [[package]] 521 | name = "heck" 522 | version = "0.3.3" 523 | source = "registry+https://github.com/rust-lang/crates.io-index" 524 | checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" 525 | dependencies = [ 526 | "unicode-segmentation", 527 | ] 528 | 529 | [[package]] 530 | name = "hex" 531 | version = "0.4.3" 532 | source = "registry+https://github.com/rust-lang/crates.io-index" 533 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" 534 | 535 | [[package]] 536 | name = "idna" 537 | version = "0.3.0" 538 | source = "registry+https://github.com/rust-lang/crates.io-index" 539 | checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" 540 | dependencies = [ 541 | "unicode-bidi", 542 | "unicode-normalization", 543 | ] 544 | 545 | [[package]] 546 | name = "if_chain" 547 | version = "1.0.2" 548 | source = "registry+https://github.com/rust-lang/crates.io-index" 549 | checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed" 550 | 551 | [[package]] 552 | name = "indexmap" 553 | version = "1.8.0" 554 | source = "registry+https://github.com/rust-lang/crates.io-index" 555 | checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" 556 | dependencies = [ 557 | "autocfg", 558 | "hashbrown", 559 | ] 560 | 561 | [[package]] 562 | name = "instant" 563 | version = "0.1.12" 564 | source = "registry+https://github.com/rust-lang/crates.io-index" 565 | checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" 566 | dependencies = [ 567 | "cfg-if", 568 | ] 569 | 570 | [[package]] 571 | name = "itoa" 572 | version = "1.0.1" 573 | source = "registry+https://github.com/rust-lang/crates.io-index" 574 | checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" 575 | 576 | [[package]] 577 | name = "lazy_static" 578 | version = "1.4.0" 579 | source = "registry+https://github.com/rust-lang/crates.io-index" 580 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 581 | 582 | [[package]] 583 | name = "libc" 584 | version = "0.2.139" 585 | source = "registry+https://github.com/rust-lang/crates.io-index" 586 | checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" 587 | 588 | [[package]] 589 | name = "lock_api" 590 | version = "0.4.9" 591 | source = "registry+https://github.com/rust-lang/crates.io-index" 592 | checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" 593 | dependencies = [ 594 | "autocfg", 595 | "scopeguard", 596 | ] 597 | 598 | [[package]] 599 | name = "log" 600 | version = "0.4.17" 601 | source = "registry+https://github.com/rust-lang/crates.io-index" 602 | checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" 603 | dependencies = [ 604 | "cfg-if", 605 | ] 606 | 607 | [[package]] 608 | name = "mac-notification-sys" 609 | version = "0.5.6" 610 | source = "registry+https://github.com/rust-lang/crates.io-index" 611 | checksum = "3e72d50edb17756489e79d52eb146927bec8eba9dd48faadf9ef08bca3791ad5" 612 | dependencies = [ 613 | "cc", 614 | "dirs-next", 615 | "objc-foundation", 616 | "objc_id", 617 | "time", 618 | ] 619 | 620 | [[package]] 621 | name = "malloc_buf" 622 | version = "0.0.6" 623 | source = "registry+https://github.com/rust-lang/crates.io-index" 624 | checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" 625 | dependencies = [ 626 | "libc", 627 | ] 628 | 629 | [[package]] 630 | name = "memchr" 631 | version = "2.5.0" 632 | source = "registry+https://github.com/rust-lang/crates.io-index" 633 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" 634 | 635 | [[package]] 636 | name = "memoffset" 637 | version = "0.6.5" 638 | source = "registry+https://github.com/rust-lang/crates.io-index" 639 | checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" 640 | dependencies = [ 641 | "autocfg", 642 | ] 643 | 644 | [[package]] 645 | name = "nix" 646 | version = "0.25.1" 647 | source = "registry+https://github.com/rust-lang/crates.io-index" 648 | checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" 649 | dependencies = [ 650 | "autocfg", 651 | "bitflags", 652 | "cfg-if", 653 | "libc", 654 | "memoffset", 655 | "pin-utils", 656 | ] 657 | 658 | [[package]] 659 | name = "notify-rust" 660 | version = "4.7.0" 661 | source = "registry+https://github.com/rust-lang/crates.io-index" 662 | checksum = "3ce656bb6d22a93ae276a23de52d1aec5ba4db3ece3c0eb79dfd5add7384db6a" 663 | dependencies = [ 664 | "mac-notification-sys", 665 | "serde", 666 | "tauri-winrt-notification", 667 | "zbus", 668 | ] 669 | 670 | [[package]] 671 | name = "num_threads" 672 | version = "0.1.5" 673 | source = "registry+https://github.com/rust-lang/crates.io-index" 674 | checksum = "aba1801fb138d8e85e11d0fc70baf4fe1cdfffda7c6cd34a854905df588e5ed0" 675 | dependencies = [ 676 | "libc", 677 | ] 678 | 679 | [[package]] 680 | name = "objc" 681 | version = "0.2.7" 682 | source = "registry+https://github.com/rust-lang/crates.io-index" 683 | checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" 684 | dependencies = [ 685 | "malloc_buf", 686 | ] 687 | 688 | [[package]] 689 | name = "objc-foundation" 690 | version = "0.1.1" 691 | source = "registry+https://github.com/rust-lang/crates.io-index" 692 | checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" 693 | dependencies = [ 694 | "block", 695 | "objc", 696 | "objc_id", 697 | ] 698 | 699 | [[package]] 700 | name = "objc_id" 701 | version = "0.1.1" 702 | source = "registry+https://github.com/rust-lang/crates.io-index" 703 | checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" 704 | dependencies = [ 705 | "objc", 706 | ] 707 | 708 | [[package]] 709 | name = "once_cell" 710 | version = "1.16.0" 711 | source = "registry+https://github.com/rust-lang/crates.io-index" 712 | checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" 713 | 714 | [[package]] 715 | name = "ordered-stream" 716 | version = "0.1.3" 717 | source = "registry+https://github.com/rust-lang/crates.io-index" 718 | checksum = "d4eb9ba3f3e42dbdd3b7b122de5ca169c81e93d561eb900da3a8c99bcfcf381a" 719 | dependencies = [ 720 | "futures-core", 721 | "pin-project-lite", 722 | ] 723 | 724 | [[package]] 725 | name = "parking" 726 | version = "2.0.0" 727 | source = "registry+https://github.com/rust-lang/crates.io-index" 728 | checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" 729 | 730 | [[package]] 731 | name = "parking_lot" 732 | version = "0.12.1" 733 | source = "registry+https://github.com/rust-lang/crates.io-index" 734 | checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" 735 | dependencies = [ 736 | "lock_api", 737 | "parking_lot_core", 738 | ] 739 | 740 | [[package]] 741 | name = "parking_lot_core" 742 | version = "0.9.6" 743 | source = "registry+https://github.com/rust-lang/crates.io-index" 744 | checksum = "ba1ef8814b5c993410bb3adfad7a5ed269563e4a2f90c41f5d85be7fb47133bf" 745 | dependencies = [ 746 | "cfg-if", 747 | "libc", 748 | "redox_syscall", 749 | "smallvec", 750 | "windows-sys", 751 | ] 752 | 753 | [[package]] 754 | name = "percent-encoding" 755 | version = "2.2.0" 756 | source = "registry+https://github.com/rust-lang/crates.io-index" 757 | checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" 758 | 759 | [[package]] 760 | name = "pin-project" 761 | version = "1.0.12" 762 | source = "registry+https://github.com/rust-lang/crates.io-index" 763 | checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" 764 | dependencies = [ 765 | "pin-project-internal", 766 | ] 767 | 768 | [[package]] 769 | name = "pin-project-internal" 770 | version = "1.0.12" 771 | source = "registry+https://github.com/rust-lang/crates.io-index" 772 | checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" 773 | dependencies = [ 774 | "proc-macro2", 775 | "quote", 776 | "syn", 777 | ] 778 | 779 | [[package]] 780 | name = "pin-project-lite" 781 | version = "0.2.9" 782 | source = "registry+https://github.com/rust-lang/crates.io-index" 783 | checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" 784 | 785 | [[package]] 786 | name = "pin-utils" 787 | version = "0.1.0" 788 | source = "registry+https://github.com/rust-lang/crates.io-index" 789 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 790 | 791 | [[package]] 792 | name = "pmutil" 793 | version = "0.5.3" 794 | source = "registry+https://github.com/rust-lang/crates.io-index" 795 | checksum = "3894e5d549cccbe44afecf72922f277f603cd4bb0219c8342631ef18fffbe004" 796 | dependencies = [ 797 | "proc-macro2", 798 | "quote", 799 | "syn", 800 | ] 801 | 802 | [[package]] 803 | name = "polling" 804 | version = "2.2.0" 805 | source = "registry+https://github.com/rust-lang/crates.io-index" 806 | checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259" 807 | dependencies = [ 808 | "cfg-if", 809 | "libc", 810 | "log", 811 | "wepoll-ffi", 812 | "winapi", 813 | ] 814 | 815 | [[package]] 816 | name = "ppv-lite86" 817 | version = "0.2.16" 818 | source = "registry+https://github.com/rust-lang/crates.io-index" 819 | checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" 820 | 821 | [[package]] 822 | name = "proc-macro-crate" 823 | version = "1.2.1" 824 | source = "registry+https://github.com/rust-lang/crates.io-index" 825 | checksum = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9" 826 | dependencies = [ 827 | "once_cell", 828 | "thiserror", 829 | "toml", 830 | ] 831 | 832 | [[package]] 833 | name = "proc-macro2" 834 | version = "1.0.50" 835 | source = "registry+https://github.com/rust-lang/crates.io-index" 836 | checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2" 837 | dependencies = [ 838 | "unicode-ident", 839 | ] 840 | 841 | [[package]] 842 | name = "quick-xml" 843 | version = "0.23.1" 844 | source = "registry+https://github.com/rust-lang/crates.io-index" 845 | checksum = "11bafc859c6815fbaffbbbf4229ecb767ac913fecb27f9ad4343662e9ef099ea" 846 | dependencies = [ 847 | "memchr", 848 | ] 849 | 850 | [[package]] 851 | name = "quote" 852 | version = "1.0.23" 853 | source = "registry+https://github.com/rust-lang/crates.io-index" 854 | checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" 855 | dependencies = [ 856 | "proc-macro2", 857 | ] 858 | 859 | [[package]] 860 | name = "rand" 861 | version = "0.8.5" 862 | source = "registry+https://github.com/rust-lang/crates.io-index" 863 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 864 | dependencies = [ 865 | "libc", 866 | "rand_chacha", 867 | "rand_core", 868 | ] 869 | 870 | [[package]] 871 | name = "rand_chacha" 872 | version = "0.3.1" 873 | source = "registry+https://github.com/rust-lang/crates.io-index" 874 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 875 | dependencies = [ 876 | "ppv-lite86", 877 | "rand_core", 878 | ] 879 | 880 | [[package]] 881 | name = "rand_core" 882 | version = "0.6.3" 883 | source = "registry+https://github.com/rust-lang/crates.io-index" 884 | checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" 885 | dependencies = [ 886 | "getrandom", 887 | ] 888 | 889 | [[package]] 890 | name = "redox_syscall" 891 | version = "0.2.12" 892 | source = "registry+https://github.com/rust-lang/crates.io-index" 893 | checksum = "8ae183fc1b06c149f0c1793e1eb447c8b04bfe46d48e9e48bfb8d2d7ed64ecf0" 894 | dependencies = [ 895 | "bitflags", 896 | ] 897 | 898 | [[package]] 899 | name = "redox_users" 900 | version = "0.4.2" 901 | source = "registry+https://github.com/rust-lang/crates.io-index" 902 | checksum = "7776223e2696f1aa4c6b0170e83212f47296a00424305117d013dfe86fb0fe55" 903 | dependencies = [ 904 | "getrandom", 905 | "redox_syscall", 906 | "thiserror", 907 | ] 908 | 909 | [[package]] 910 | name = "regex" 911 | version = "1.6.0" 912 | source = "registry+https://github.com/rust-lang/crates.io-index" 913 | checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" 914 | dependencies = [ 915 | "aho-corasick", 916 | "memchr", 917 | "regex-syntax", 918 | ] 919 | 920 | [[package]] 921 | name = "regex-syntax" 922 | version = "0.6.28" 923 | source = "registry+https://github.com/rust-lang/crates.io-index" 924 | checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" 925 | 926 | [[package]] 927 | name = "remove_dir_all" 928 | version = "0.5.3" 929 | source = "registry+https://github.com/rust-lang/crates.io-index" 930 | checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" 931 | dependencies = [ 932 | "winapi", 933 | ] 934 | 935 | [[package]] 936 | name = "rustc_version" 937 | version = "0.2.3" 938 | source = "registry+https://github.com/rust-lang/crates.io-index" 939 | checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" 940 | dependencies = [ 941 | "semver 0.9.0", 942 | ] 943 | 944 | [[package]] 945 | name = "rustc_version" 946 | version = "0.4.0" 947 | source = "registry+https://github.com/rust-lang/crates.io-index" 948 | checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" 949 | dependencies = [ 950 | "semver 1.0.7", 951 | ] 952 | 953 | [[package]] 954 | name = "ryu" 955 | version = "1.0.9" 956 | source = "registry+https://github.com/rust-lang/crates.io-index" 957 | checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" 958 | 959 | [[package]] 960 | name = "scopeguard" 961 | version = "1.1.0" 962 | source = "registry+https://github.com/rust-lang/crates.io-index" 963 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 964 | 965 | [[package]] 966 | name = "semver" 967 | version = "0.9.0" 968 | source = "registry+https://github.com/rust-lang/crates.io-index" 969 | checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" 970 | dependencies = [ 971 | "semver-parser", 972 | ] 973 | 974 | [[package]] 975 | name = "semver" 976 | version = "1.0.7" 977 | source = "registry+https://github.com/rust-lang/crates.io-index" 978 | checksum = "d65bd28f48be7196d222d95b9243287f48d27aca604e08497513019ff0502cc4" 979 | 980 | [[package]] 981 | name = "semver-parser" 982 | version = "0.7.0" 983 | source = "registry+https://github.com/rust-lang/crates.io-index" 984 | checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" 985 | 986 | [[package]] 987 | name = "serde" 988 | version = "1.0.149" 989 | source = "registry+https://github.com/rust-lang/crates.io-index" 990 | checksum = "256b9932320c590e707b94576e3cc1f7c9024d0ee6612dfbcf1cb106cbe8e055" 991 | dependencies = [ 992 | "serde_derive", 993 | ] 994 | 995 | [[package]] 996 | name = "serde_bytes" 997 | version = "0.11.5" 998 | source = "registry+https://github.com/rust-lang/crates.io-index" 999 | checksum = "16ae07dd2f88a366f15bd0632ba725227018c69a1c8550a927324f8eb8368bb9" 1000 | dependencies = [ 1001 | "serde", 1002 | ] 1003 | 1004 | [[package]] 1005 | name = "serde_derive" 1006 | version = "1.0.149" 1007 | source = "registry+https://github.com/rust-lang/crates.io-index" 1008 | checksum = "b4eae9b04cbffdfd550eb462ed33bc6a1b68c935127d008b27444d08380f94e4" 1009 | dependencies = [ 1010 | "proc-macro2", 1011 | "quote", 1012 | "syn", 1013 | ] 1014 | 1015 | [[package]] 1016 | name = "serde_json" 1017 | version = "1.0.85" 1018 | source = "registry+https://github.com/rust-lang/crates.io-index" 1019 | checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" 1020 | dependencies = [ 1021 | "indexmap", 1022 | "itoa", 1023 | "ryu", 1024 | "serde", 1025 | ] 1026 | 1027 | [[package]] 1028 | name = "serde_repr" 1029 | version = "0.1.10" 1030 | source = "registry+https://github.com/rust-lang/crates.io-index" 1031 | checksum = "9a5ec9fa74a20ebbe5d9ac23dac1fc96ba0ecfe9f50f2843b52e537b10fbcb4e" 1032 | dependencies = [ 1033 | "proc-macro2", 1034 | "quote", 1035 | "syn", 1036 | ] 1037 | 1038 | [[package]] 1039 | name = "serde_v8" 1040 | version = "0.79.0" 1041 | source = "registry+https://github.com/rust-lang/crates.io-index" 1042 | checksum = "66e41ffaede17c5ce641cd520a21207f12078f8bc86580aeb416851febe9863b" 1043 | dependencies = [ 1044 | "bytes", 1045 | "derive_more", 1046 | "serde", 1047 | "serde_bytes", 1048 | "smallvec", 1049 | "v8", 1050 | ] 1051 | 1052 | [[package]] 1053 | name = "sha1" 1054 | version = "0.10.5" 1055 | source = "registry+https://github.com/rust-lang/crates.io-index" 1056 | checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" 1057 | dependencies = [ 1058 | "cfg-if", 1059 | "cpufeatures", 1060 | "digest", 1061 | ] 1062 | 1063 | [[package]] 1064 | name = "slab" 1065 | version = "0.4.5" 1066 | source = "registry+https://github.com/rust-lang/crates.io-index" 1067 | checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" 1068 | 1069 | [[package]] 1070 | name = "smallvec" 1071 | version = "1.10.0" 1072 | source = "registry+https://github.com/rust-lang/crates.io-index" 1073 | checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" 1074 | 1075 | [[package]] 1076 | name = "socket2" 1077 | version = "0.4.2" 1078 | source = "registry+https://github.com/rust-lang/crates.io-index" 1079 | checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516" 1080 | dependencies = [ 1081 | "libc", 1082 | "winapi", 1083 | ] 1084 | 1085 | [[package]] 1086 | name = "sourcemap" 1087 | version = "6.2.1" 1088 | source = "registry+https://github.com/rust-lang/crates.io-index" 1089 | checksum = "aebe057d110ddba043708da3fb010bf562ff6e9d4d60c9ee92860527bcbeccd6" 1090 | dependencies = [ 1091 | "base64", 1092 | "if_chain", 1093 | "rustc_version 0.2.3", 1094 | "serde", 1095 | "serde_json", 1096 | "unicode-id", 1097 | "url", 1098 | ] 1099 | 1100 | [[package]] 1101 | name = "static_assertions" 1102 | version = "1.1.0" 1103 | source = "registry+https://github.com/rust-lang/crates.io-index" 1104 | checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" 1105 | 1106 | [[package]] 1107 | name = "strum" 1108 | version = "0.22.0" 1109 | source = "registry+https://github.com/rust-lang/crates.io-index" 1110 | checksum = "f7ac893c7d471c8a21f31cfe213ec4f6d9afeed25537c772e08ef3f005f8729e" 1111 | dependencies = [ 1112 | "strum_macros", 1113 | ] 1114 | 1115 | [[package]] 1116 | name = "strum_macros" 1117 | version = "0.22.0" 1118 | source = "registry+https://github.com/rust-lang/crates.io-index" 1119 | checksum = "339f799d8b549e3744c7ac7feb216383e4005d94bdb22561b3ab8f3b808ae9fb" 1120 | dependencies = [ 1121 | "heck", 1122 | "proc-macro2", 1123 | "quote", 1124 | "syn", 1125 | ] 1126 | 1127 | [[package]] 1128 | name = "syn" 1129 | version = "1.0.107" 1130 | source = "registry+https://github.com/rust-lang/crates.io-index" 1131 | checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" 1132 | dependencies = [ 1133 | "proc-macro2", 1134 | "quote", 1135 | "unicode-ident", 1136 | ] 1137 | 1138 | [[package]] 1139 | name = "tauri-winrt-notification" 1140 | version = "0.1.0" 1141 | source = "registry+https://github.com/rust-lang/crates.io-index" 1142 | checksum = "c58de036c4d2e20717024de2a3c4bf56c301f07b21bc8ef9b57189fce06f1f3b" 1143 | dependencies = [ 1144 | "quick-xml", 1145 | "strum", 1146 | "windows", 1147 | ] 1148 | 1149 | [[package]] 1150 | name = "tempfile" 1151 | version = "3.3.0" 1152 | source = "registry+https://github.com/rust-lang/crates.io-index" 1153 | checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" 1154 | dependencies = [ 1155 | "cfg-if", 1156 | "fastrand", 1157 | "libc", 1158 | "redox_syscall", 1159 | "remove_dir_all", 1160 | "winapi", 1161 | ] 1162 | 1163 | [[package]] 1164 | name = "thiserror" 1165 | version = "1.0.30" 1166 | source = "registry+https://github.com/rust-lang/crates.io-index" 1167 | checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" 1168 | dependencies = [ 1169 | "thiserror-impl", 1170 | ] 1171 | 1172 | [[package]] 1173 | name = "thiserror-impl" 1174 | version = "1.0.30" 1175 | source = "registry+https://github.com/rust-lang/crates.io-index" 1176 | checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" 1177 | dependencies = [ 1178 | "proc-macro2", 1179 | "quote", 1180 | "syn", 1181 | ] 1182 | 1183 | [[package]] 1184 | name = "time" 1185 | version = "0.3.9" 1186 | source = "registry+https://github.com/rust-lang/crates.io-index" 1187 | checksum = "c2702e08a7a860f005826c6815dcac101b19b5eb330c27fe4a5928fec1d20ddd" 1188 | dependencies = [ 1189 | "libc", 1190 | "num_threads", 1191 | ] 1192 | 1193 | [[package]] 1194 | name = "tinyvec" 1195 | version = "1.5.1" 1196 | source = "registry+https://github.com/rust-lang/crates.io-index" 1197 | checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" 1198 | dependencies = [ 1199 | "tinyvec_macros", 1200 | ] 1201 | 1202 | [[package]] 1203 | name = "tinyvec_macros" 1204 | version = "0.1.0" 1205 | source = "registry+https://github.com/rust-lang/crates.io-index" 1206 | checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" 1207 | 1208 | [[package]] 1209 | name = "toml" 1210 | version = "0.5.8" 1211 | source = "registry+https://github.com/rust-lang/crates.io-index" 1212 | checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" 1213 | dependencies = [ 1214 | "serde", 1215 | ] 1216 | 1217 | [[package]] 1218 | name = "tracing" 1219 | version = "0.1.37" 1220 | source = "registry+https://github.com/rust-lang/crates.io-index" 1221 | checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" 1222 | dependencies = [ 1223 | "cfg-if", 1224 | "pin-project-lite", 1225 | "tracing-attributes", 1226 | "tracing-core", 1227 | ] 1228 | 1229 | [[package]] 1230 | name = "tracing-attributes" 1231 | version = "0.1.23" 1232 | source = "registry+https://github.com/rust-lang/crates.io-index" 1233 | checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" 1234 | dependencies = [ 1235 | "proc-macro2", 1236 | "quote", 1237 | "syn", 1238 | ] 1239 | 1240 | [[package]] 1241 | name = "tracing-core" 1242 | version = "0.1.30" 1243 | source = "registry+https://github.com/rust-lang/crates.io-index" 1244 | checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" 1245 | dependencies = [ 1246 | "once_cell", 1247 | ] 1248 | 1249 | [[package]] 1250 | name = "typenum" 1251 | version = "1.16.0" 1252 | source = "registry+https://github.com/rust-lang/crates.io-index" 1253 | checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" 1254 | 1255 | [[package]] 1256 | name = "uds_windows" 1257 | version = "1.0.2" 1258 | source = "registry+https://github.com/rust-lang/crates.io-index" 1259 | checksum = "ce65604324d3cce9b966701489fbd0cf318cb1f7bd9dd07ac9a4ee6fb791930d" 1260 | dependencies = [ 1261 | "tempfile", 1262 | "winapi", 1263 | ] 1264 | 1265 | [[package]] 1266 | name = "unicode-bidi" 1267 | version = "0.3.7" 1268 | source = "registry+https://github.com/rust-lang/crates.io-index" 1269 | checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" 1270 | 1271 | [[package]] 1272 | name = "unicode-id" 1273 | version = "0.3.3" 1274 | source = "registry+https://github.com/rust-lang/crates.io-index" 1275 | checksum = "d70b6494226b36008c8366c288d77190b3fad2eb4c10533139c1c1f461127f1a" 1276 | 1277 | [[package]] 1278 | name = "unicode-ident" 1279 | version = "1.0.6" 1280 | source = "registry+https://github.com/rust-lang/crates.io-index" 1281 | checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" 1282 | 1283 | [[package]] 1284 | name = "unicode-normalization" 1285 | version = "0.1.19" 1286 | source = "registry+https://github.com/rust-lang/crates.io-index" 1287 | checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" 1288 | dependencies = [ 1289 | "tinyvec", 1290 | ] 1291 | 1292 | [[package]] 1293 | name = "unicode-segmentation" 1294 | version = "1.8.0" 1295 | source = "registry+https://github.com/rust-lang/crates.io-index" 1296 | checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" 1297 | 1298 | [[package]] 1299 | name = "url" 1300 | version = "2.3.1" 1301 | source = "registry+https://github.com/rust-lang/crates.io-index" 1302 | checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" 1303 | dependencies = [ 1304 | "form_urlencoded", 1305 | "idna", 1306 | "percent-encoding", 1307 | "serde", 1308 | ] 1309 | 1310 | [[package]] 1311 | name = "v8" 1312 | version = "0.60.1" 1313 | source = "registry+https://github.com/rust-lang/crates.io-index" 1314 | checksum = "07fd5b3ed559897ff02c0f62bc0a5f300bfe79bb4c77a50031b8df771701c628" 1315 | dependencies = [ 1316 | "bitflags", 1317 | "fslock", 1318 | "lazy_static", 1319 | "which", 1320 | ] 1321 | 1322 | [[package]] 1323 | name = "version_check" 1324 | version = "0.9.4" 1325 | source = "registry+https://github.com/rust-lang/crates.io-index" 1326 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 1327 | 1328 | [[package]] 1329 | name = "waker-fn" 1330 | version = "1.1.0" 1331 | source = "registry+https://github.com/rust-lang/crates.io-index" 1332 | checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" 1333 | 1334 | [[package]] 1335 | name = "wasi" 1336 | version = "0.10.0+wasi-snapshot-preview1" 1337 | source = "registry+https://github.com/rust-lang/crates.io-index" 1338 | checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" 1339 | 1340 | [[package]] 1341 | name = "wepoll-ffi" 1342 | version = "0.1.2" 1343 | source = "registry+https://github.com/rust-lang/crates.io-index" 1344 | checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" 1345 | dependencies = [ 1346 | "cc", 1347 | ] 1348 | 1349 | [[package]] 1350 | name = "which" 1351 | version = "4.3.0" 1352 | source = "registry+https://github.com/rust-lang/crates.io-index" 1353 | checksum = "1c831fbbee9e129a8cf93e7747a82da9d95ba8e16621cae60ec2cdc849bacb7b" 1354 | dependencies = [ 1355 | "either", 1356 | "libc", 1357 | "once_cell", 1358 | ] 1359 | 1360 | [[package]] 1361 | name = "winapi" 1362 | version = "0.3.9" 1363 | source = "registry+https://github.com/rust-lang/crates.io-index" 1364 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 1365 | dependencies = [ 1366 | "winapi-i686-pc-windows-gnu", 1367 | "winapi-x86_64-pc-windows-gnu", 1368 | ] 1369 | 1370 | [[package]] 1371 | name = "winapi-i686-pc-windows-gnu" 1372 | version = "0.4.0" 1373 | source = "registry+https://github.com/rust-lang/crates.io-index" 1374 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 1375 | 1376 | [[package]] 1377 | name = "winapi-x86_64-pc-windows-gnu" 1378 | version = "0.4.0" 1379 | source = "registry+https://github.com/rust-lang/crates.io-index" 1380 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1381 | 1382 | [[package]] 1383 | name = "windows" 1384 | version = "0.39.0" 1385 | source = "registry+https://github.com/rust-lang/crates.io-index" 1386 | checksum = "f1c4bd0a50ac6020f65184721f758dba47bb9fbc2133df715ec74a237b26794a" 1387 | dependencies = [ 1388 | "windows_aarch64_msvc 0.39.0", 1389 | "windows_i686_gnu 0.39.0", 1390 | "windows_i686_msvc 0.39.0", 1391 | "windows_x86_64_gnu 0.39.0", 1392 | "windows_x86_64_msvc 0.39.0", 1393 | ] 1394 | 1395 | [[package]] 1396 | name = "windows-sys" 1397 | version = "0.42.0" 1398 | source = "registry+https://github.com/rust-lang/crates.io-index" 1399 | checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" 1400 | dependencies = [ 1401 | "windows_aarch64_gnullvm", 1402 | "windows_aarch64_msvc 0.42.1", 1403 | "windows_i686_gnu 0.42.1", 1404 | "windows_i686_msvc 0.42.1", 1405 | "windows_x86_64_gnu 0.42.1", 1406 | "windows_x86_64_gnullvm", 1407 | "windows_x86_64_msvc 0.42.1", 1408 | ] 1409 | 1410 | [[package]] 1411 | name = "windows_aarch64_gnullvm" 1412 | version = "0.42.1" 1413 | source = "registry+https://github.com/rust-lang/crates.io-index" 1414 | checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" 1415 | 1416 | [[package]] 1417 | name = "windows_aarch64_msvc" 1418 | version = "0.39.0" 1419 | source = "registry+https://github.com/rust-lang/crates.io-index" 1420 | checksum = "ec7711666096bd4096ffa835238905bb33fb87267910e154b18b44eaabb340f2" 1421 | 1422 | [[package]] 1423 | name = "windows_aarch64_msvc" 1424 | version = "0.42.1" 1425 | source = "registry+https://github.com/rust-lang/crates.io-index" 1426 | checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" 1427 | 1428 | [[package]] 1429 | name = "windows_i686_gnu" 1430 | version = "0.39.0" 1431 | source = "registry+https://github.com/rust-lang/crates.io-index" 1432 | checksum = "763fc57100a5f7042e3057e7e8d9bdd7860d330070251a73d003563a3bb49e1b" 1433 | 1434 | [[package]] 1435 | name = "windows_i686_gnu" 1436 | version = "0.42.1" 1437 | source = "registry+https://github.com/rust-lang/crates.io-index" 1438 | checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" 1439 | 1440 | [[package]] 1441 | name = "windows_i686_msvc" 1442 | version = "0.39.0" 1443 | source = "registry+https://github.com/rust-lang/crates.io-index" 1444 | checksum = "7bc7cbfe58828921e10a9f446fcaaf649204dcfe6c1ddd712c5eebae6bda1106" 1445 | 1446 | [[package]] 1447 | name = "windows_i686_msvc" 1448 | version = "0.42.1" 1449 | source = "registry+https://github.com/rust-lang/crates.io-index" 1450 | checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" 1451 | 1452 | [[package]] 1453 | name = "windows_x86_64_gnu" 1454 | version = "0.39.0" 1455 | source = "registry+https://github.com/rust-lang/crates.io-index" 1456 | checksum = "6868c165637d653ae1e8dc4d82c25d4f97dd6605eaa8d784b5c6e0ab2a252b65" 1457 | 1458 | [[package]] 1459 | name = "windows_x86_64_gnu" 1460 | version = "0.42.1" 1461 | source = "registry+https://github.com/rust-lang/crates.io-index" 1462 | checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" 1463 | 1464 | [[package]] 1465 | name = "windows_x86_64_gnullvm" 1466 | version = "0.42.1" 1467 | source = "registry+https://github.com/rust-lang/crates.io-index" 1468 | checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" 1469 | 1470 | [[package]] 1471 | name = "windows_x86_64_msvc" 1472 | version = "0.39.0" 1473 | source = "registry+https://github.com/rust-lang/crates.io-index" 1474 | checksum = "5e4d40883ae9cae962787ca76ba76390ffa29214667a111db9e0a1ad8377e809" 1475 | 1476 | [[package]] 1477 | name = "windows_x86_64_msvc" 1478 | version = "0.42.1" 1479 | source = "registry+https://github.com/rust-lang/crates.io-index" 1480 | checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" 1481 | 1482 | [[package]] 1483 | name = "zbus" 1484 | version = "3.7.0" 1485 | source = "registry+https://github.com/rust-lang/crates.io-index" 1486 | checksum = "379d587c0ccb632d1179cf44082653f682842f0535f0fdfaefffc34849cc855e" 1487 | dependencies = [ 1488 | "async-broadcast", 1489 | "async-executor", 1490 | "async-io", 1491 | "async-lock", 1492 | "async-recursion", 1493 | "async-task", 1494 | "async-trait", 1495 | "byteorder", 1496 | "derivative", 1497 | "dirs", 1498 | "enumflags2", 1499 | "event-listener", 1500 | "futures-core", 1501 | "futures-sink", 1502 | "futures-util", 1503 | "hex", 1504 | "nix", 1505 | "once_cell", 1506 | "ordered-stream", 1507 | "rand", 1508 | "serde", 1509 | "serde_repr", 1510 | "sha1", 1511 | "static_assertions", 1512 | "tracing", 1513 | "uds_windows", 1514 | "winapi", 1515 | "zbus_macros", 1516 | "zbus_names", 1517 | "zvariant", 1518 | ] 1519 | 1520 | [[package]] 1521 | name = "zbus_macros" 1522 | version = "3.7.0" 1523 | source = "registry+https://github.com/rust-lang/crates.io-index" 1524 | checksum = "66492a2e90c0df7190583eccb8424aa12eb7ff06edea415a4fff6688fae18cf8" 1525 | dependencies = [ 1526 | "proc-macro-crate", 1527 | "proc-macro2", 1528 | "quote", 1529 | "regex", 1530 | "syn", 1531 | ] 1532 | 1533 | [[package]] 1534 | name = "zbus_names" 1535 | version = "2.5.0" 1536 | source = "registry+https://github.com/rust-lang/crates.io-index" 1537 | checksum = "f34f314916bd89bdb9934154627fab152f4f28acdda03e7c4c68181b214fe7e3" 1538 | dependencies = [ 1539 | "serde", 1540 | "static_assertions", 1541 | "zvariant", 1542 | ] 1543 | 1544 | [[package]] 1545 | name = "zvariant" 1546 | version = "3.10.0" 1547 | source = "registry+https://github.com/rust-lang/crates.io-index" 1548 | checksum = "576cc41e65c7f283e5460f5818073e68fb1f1631502b969ef228c2e03c862efb" 1549 | dependencies = [ 1550 | "byteorder", 1551 | "enumflags2", 1552 | "libc", 1553 | "serde", 1554 | "static_assertions", 1555 | "zvariant_derive", 1556 | ] 1557 | 1558 | [[package]] 1559 | name = "zvariant_derive" 1560 | version = "3.10.0" 1561 | source = "registry+https://github.com/rust-lang/crates.io-index" 1562 | checksum = "0fd4aafc0dee96ae7242a24249ce9babf21e1562822f03df650d4e68c20e41ed" 1563 | dependencies = [ 1564 | "proc-macro-crate", 1565 | "proc-macro2", 1566 | "quote", 1567 | "syn", 1568 | ] 1569 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "deno_notify" 3 | version = "1.4.3" 4 | authors = ["Pandawan "] 5 | edition = "2021" 6 | publish = false 7 | 8 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 9 | 10 | [lib] 11 | crate-type = ["cdylib"] 12 | 13 | [dependencies] 14 | futures = "0.3.25" 15 | deno_core = "0.168.0" 16 | notify-rust = "4.7.0" 17 | serde = "1.0.149" 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Pandawan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # deno_notify 2 | 3 | [![license](https://img.shields.io/github/license/Pandawan/deno_notify)](https://github.com/Pandawan/deno_notify/blob/master/LICENSE) 4 | [![build](https://img.shields.io/github/actions/workflow/status/Pandawan/deno_notify/.github/workflows/build.yml?branch=master)](https://github.com/Pandawan/deno_notify/actions/workflows/build.yml) 5 | [![deno version](https://img.shields.io/badge/deno-1.31.1-success)](https://github.com/denoland/deno) 6 | [![deno doc](https://doc.deno.land/badge.svg)](https://doc.deno.land/https/deno.land/x/deno_notify/ts/mod.ts) 7 | 8 | Send desktop notifications on all platforms in Deno.\ 9 | Supports Windows, macOS, and linux using 10 | [notify-rust](https://github.com/hoodie/notify-rust) though some features are 11 | platform-specific. 12 | 13 | Note: More features are in the works and the API may change as a result. 14 | 15 | ## Usage 16 | 17 | The `mod.ts` entrypoint uses [Plug](https://github.com/denosaurs/plug) 18 | internally so you don't have to download or open the plugin manually. 19 | 20 | _You will need to run using the `--unstable` and `--allow-all` permissions to 21 | allow for automatic plugin loading and caching._ 22 | 23 | ```ts 24 | import { Notification } from "https://deno.land/x/deno_notify@1.4.3/ts/mod.ts"; 25 | 26 | // Create a new notification 27 | const notif = new Notification(); 28 | 29 | // Add a simple message 30 | notif.title("My message"); 31 | 32 | // Display it 33 | notif.show(); 34 | ``` 35 | 36 | Or stack together your desired options: 37 | 38 | ```ts 39 | new Notification({ macos: true }) 40 | .title("My message") 41 | .subtitle("It's very important...") 42 | .body("Hello, World!") 43 | .soundName("Basso") 44 | .show(); 45 | ``` 46 | 47 | ## Documentation 48 | 49 | Check out the 50 | [Documentation](https://doc.deno.land/https/deno.land/x/deno_notify/ts/mod.ts) 51 | for a list of available features. 52 | 53 | ### Platform-Specific Features 54 | 55 | By default, only cross-platform features are available. In order to enable 56 | platform-specific features (e.g. icons), you can pass in booleans flags to 57 | specify the supported platforms in the `Notification`'s constructor. 58 | 59 | ```ts 60 | // Enable linux-specific-features 61 | const notif = new Notification({ linux: true }); 62 | 63 | // Notification.icon() is now available 64 | notif.icon("/path/to/icon"); 65 | ``` 66 | 67 | Specifying platforms may also provide different documentation and typings for 68 | the `Notification` API. 69 | 70 | For example, macOS has specific sound names that are available for 71 | Notifications; these are reflected in the macOS-specific Notification API. 72 | 73 | ![IntelliSense Suggesting MacOS Sound Names When Calling Notification.soundName()](./images/macos_soundName_typings.png) 74 | 75 | #### Strict Platform Checking 76 | 77 | The second parameter of the `Notification`'s constructor can be used to 78 | determine whether the platform-features should be checked at runtime. When 79 | `true` (default), any platform-specific feature will error if used on a platform 80 | that does not support it. When `false`, the error will be silently ignored. 81 | 82 | Note: Platform checking is performed both at compile time (TypeScript) and at 83 | runtime. 84 | 85 | ```ts 86 | // Icons are not supported on macOS 87 | // If notif.icon() is called on a macOS computer, this will error. 88 | const notif = new Notification({ linux: true }, true); 89 | notif.icon("/path/to/icon"); 90 | 91 | // This will not error; however, no icon will be displayed on macOS. 92 | const notif = new Notification({ linux: true }, false); 93 | notif.icon("/path/to/icon"); 94 | ``` 95 | 96 | ## FAQ 97 | 98 | ### Error: Deno.dlopen is not a function 99 | 100 | If you are getting the error "Deno.dlopen is not a function" then you likely 101 | haven't enabled the unstable ffi features when running your code. **Please run 102 | with the `--unstable` flag.** (You might also need the `--allow-ffi` flag). 103 | 104 | #### Reason 105 | 106 | This library relies on native (Rust) libraries to launch notifications. However, 107 | Deno hasn't yet stabilized foreign function interfaces (which allow Deno to call 108 | these native libraries). To allow running these unstable features, you must 109 | explictly tell Deno to allow calls to the unstable `Deno.dlopen` function. 110 | 111 | ### Installing Manually 112 | 113 | By default, the ffi library will automatically be downloaded via 114 | [Plug](https://github.com/denosaurs/plug) to match your `deno_notify` version. 115 | 116 | However, in some cases you may want to refer to a local version of the library 117 | files. To do so, you can set the environment variable `NOTIFY_PLUGIN_URL` to the 118 | path of the library file(s). 119 | 120 | You can set the environment variable via command line, or directly through Deno 121 | via `Deno.env.set()`. (Note that you must import `deno_notify` **after** having 122 | set the environment variable for this option to take effect). 123 | 124 | ### Known Issues 125 | 126 | - Many platform-specific features are not implemented 127 | - Features like actions, hints, etc. 128 | - Need to integrate new mac-notification-sys changes into notify-rust 129 | - Icons/app_id on macOS are not implemented because of following issues: 130 | - Custom app icons are only applied if the notification requesting it is the 131 | first one being sent on mac 132 | - This means an app icon cannot be changed once set, and cannot be changed 133 | even if it wasn't set in the first one. 134 | - Using a custom app icon on mac sometimes crashes 135 | - From my own experience, this seems to happen with non-system applications 136 | - [See this GitHub issue for more information](https://github.com/h4llow3En/mac-notification-sys/issues/8) 137 | 138 | ## Contributing 139 | 140 | Pull request, issues and feedback are very welcome. Code style is formatted 141 | using `deno fmt -c deno.jsonc`. When adding new features, please also add 142 | [tests](https://deno.land/manual/testing) in the `tests` directory. 143 | 144 | ## Acknowledgments 145 | 146 | - Notification system from [notify-rust](https://github.com/hoodie/notify-rust) 147 | - Plugin import from [Plug](https://github.com/denosaurs/plug) 148 | -------------------------------------------------------------------------------- /deno.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "tasks": { 3 | "check": "deno check --unstable ./ts/mod.ts", 4 | "fmt": "deno fmt --unstable", 5 | "fmt:check": "deno fmt --unstable --check", 6 | "lint": "deno lint --unstable", 7 | "build:release": "cargo build --verbose --release --locked", 8 | "build:debug": "cargo build", 9 | "run:release": "export NOTIFY_PLUGIN_URL=\"./target/release/\" && deno run -A --unstable", 10 | "run:debug": "export NOTIFY_PLUGIN_URL=\"./target/debug/\" && deno run -A --unstable" 11 | // TODO: Wait for deno task to support glob expansions (https://github.com/denoland/deno_task_shell/issues/6) 12 | // "test:release": "export NOTIFY_PLUGIN_URL=\"./target/release/\" && deno test -A --unstable tests/*.ts", 13 | // "test:debug": "export NOTIFY_PLUGIN_URL=\"./target/debug/\" && deno test -A --unstable tests/*.ts", 14 | // "test:doc": "deno test -A --unstable --doc", 15 | }, 16 | "fmt": { 17 | "files": { 18 | "exclude": ["target"] 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /deno.lock: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2", 3 | "remote": { 4 | "https://deno.land/std@0.134.0/fmt/colors.ts": "30455035d6d728394781c10755351742dd731e3db6771b1843f9b9e490104d37", 5 | "https://deno.land/std@0.134.0/testing/_diff.ts": "9d849cd6877694152e01775b2d93f9d6b7aef7e24bfe3bfafc4d7a1ac8e9f392", 6 | "https://deno.land/std@0.134.0/testing/asserts.ts": "b0ef969032882b1f7eb1c7571e313214baa1485f7b61cf35807b2434e254365c", 7 | "https://deno.land/std@0.173.0/_util/asserts.ts": "178dfc49a464aee693a7e285567b3d0b555dc805ff490505a8aae34f9cfb1462", 8 | "https://deno.land/std@0.173.0/_util/os.ts": "d932f56d41e4f6a6093d56044e29ce637f8dcc43c5a90af43504a889cf1775e3", 9 | "https://deno.land/std@0.173.0/encoding/hex.ts": "50f8c95b52eae24395d3dfcb5ec1ced37c5fe7610ef6fffdcc8b0fdc38e3b32f", 10 | "https://deno.land/std@0.173.0/fmt/colors.ts": "938c5d44d889fb82eff6c358bea8baa7e85950a16c9f6dae3ec3a7a729164471", 11 | "https://deno.land/std@0.173.0/fs/_util.ts": "65381f341af1ff7f40198cee15c20f59951ac26e51ddc651c5293e24f9ce6f32", 12 | "https://deno.land/std@0.173.0/fs/copy.ts": "14214efd94fc3aa6db1e4af2b4b9578e50f7362b7f3725d5a14ad259a5df26c8", 13 | "https://deno.land/std@0.173.0/fs/empty_dir.ts": "c3d2da4c7352fab1cf144a1ecfef58090769e8af633678e0f3fabaef98594688", 14 | "https://deno.land/std@0.173.0/fs/ensure_dir.ts": "724209875497a6b4628dfb256116e5651c4f7816741368d6c44aab2531a1e603", 15 | "https://deno.land/std@0.173.0/fs/ensure_file.ts": "c38602670bfaf259d86ca824a94e6cb9e5eb73757fefa4ebf43a90dd017d53d9", 16 | "https://deno.land/std@0.173.0/fs/ensure_link.ts": "c0f5b2f0ec094ed52b9128eccb1ee23362a617457aa0f699b145d4883f5b2fb4", 17 | "https://deno.land/std@0.173.0/fs/ensure_symlink.ts": "2955cc8332aeca9bdfefd05d8d3976b94e282b0f353392a71684808ed2ffdd41", 18 | "https://deno.land/std@0.173.0/fs/eol.ts": "f1f2eb348a750c34500741987b21d65607f352cf7205f48f4319d417fff42842", 19 | "https://deno.land/std@0.173.0/fs/exists.ts": "b8c8a457b71e9d7f29b9d2f87aad8dba2739cbe637e8926d6ba6e92567875f8e", 20 | "https://deno.land/std@0.173.0/fs/expand_glob.ts": "45d17e89796a24bd6002e4354eda67b4301bb8ba67d2cac8453cdabccf1d9ab0", 21 | "https://deno.land/std@0.173.0/fs/mod.ts": "bc3d0acd488cc7b42627044caf47d72019846d459279544e1934418955ba4898", 22 | "https://deno.land/std@0.173.0/fs/move.ts": "4cb47f880e3f0582c55e71c9f8b1e5e8cfaacb5e84f7390781dd563b7298ec19", 23 | "https://deno.land/std@0.173.0/fs/walk.ts": "ea95ffa6500c1eda6b365be488c056edc7c883a1db41ef46ec3bf057b1c0fe32", 24 | "https://deno.land/std@0.173.0/path/_constants.ts": "e49961f6f4f48039c0dfed3c3f93e963ca3d92791c9d478ac5b43183413136e0", 25 | "https://deno.land/std@0.173.0/path/_interface.ts": "6471159dfbbc357e03882c2266d21ef9afdb1e4aa771b0545e90db58a0ba314b", 26 | "https://deno.land/std@0.173.0/path/_util.ts": "86c2375a996c1931b2f2ac71fefd5ddf0cf0e579fa4ab12d3e4c552d4223b8d8", 27 | "https://deno.land/std@0.173.0/path/common.ts": "ee7505ab01fd22de3963b64e46cff31f40de34f9f8de1fff6a1bd2fe79380000", 28 | "https://deno.land/std@0.173.0/path/glob.ts": "d479e0a695621c94d3fd7fe7abd4f9499caf32a8de13f25073451c6ef420a4e1", 29 | "https://deno.land/std@0.173.0/path/mod.ts": "4b83694ac500d7d31b0cdafc927080a53dc0c3027eb2895790fb155082b0d232", 30 | "https://deno.land/std@0.173.0/path/posix.ts": "0874b341c2c6968ca38d323338b8b295ea1dae10fa872a768d812e2e7d634789", 31 | "https://deno.land/std@0.173.0/path/separator.ts": "0fb679739d0d1d7bf45b68dacfb4ec7563597a902edbaf3c59b50d5bcadd93b1", 32 | "https://deno.land/std@0.173.0/path/win32.ts": "672942919dd66ce1b8c224e77d3447e2ad8254eaff13fe6946420a9f78fa141e", 33 | "https://deno.land/x/plug@1.0.0/deps.ts": "2bb283d1fa7724dd00476f7fbf6e27466960b1d80b93075179ef814e4bf44fb1", 34 | "https://deno.land/x/plug@1.0.0/download.ts": "8be0c00518f2e92f91efb5b83bff5b37f1658bba45e79d085e19842533a46efb", 35 | "https://deno.land/x/plug@1.0.0/mod.ts": "6db7edf982efedf8c9e1002754fbb109c22201fd8fb89ba715fe70171b5e821c", 36 | "https://deno.land/x/plug@1.0.0/types.ts": "d8eb738fc6ed883e6abf77093442c2f0b71af9090f15c7613621d4039e410ee1", 37 | "https://deno.land/x/plug@1.0.0/util.ts": "5ba8127b9adc36e070b9e22971fb8106869eea1741f452a87b4861e574f13481" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /images/macos_soundName_typings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pandawan/deno_notify/0d3dc105e5bca5729680d32f229b9793ecf60515/images/macos_soundName_typings.png -------------------------------------------------------------------------------- /run_tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Local Debug Mode: ./run_tests.sh 4 | # Add "release" to build a release version of the rust lib 5 | # Or add "online" to run the tests using the online lib instead 6 | # Example: ./run_tests.sh online 7 | 8 | set -e 9 | 10 | is_local=true 11 | 12 | # Build in release mode if needed 13 | if [ "$1" = "release" ]; then 14 | cargo build -p deno_notify --release 15 | 16 | export NOTIFY_PLUGIN_URL=./target/release 17 | 18 | # Build in debug mode if not release and not online 19 | elif [ "$1" != "online" ]; then 20 | cargo build -p deno_notify 21 | 22 | is_local=false 23 | 24 | export NOTIFY_PLUGIN_URL=./target/debug 25 | fi 26 | 27 | # Rename to the architecture-specific name of the library 28 | if [ "$is_local" = true ] && [ "$OSTYPE" = "darwin"* ]; then 29 | arch=$(uname -m) 30 | if [ "$arch" == "arm64" ]; then 31 | arch="aarch64" 32 | fi 33 | 34 | cp $NOTIFY_PLUGIN_URL/libdeno_notify.dylib $NOTIFY_PLUGIN_URL/libdeno_notify.$arch.dylib 35 | fi 36 | 37 | deno test --unstable --allow-all tests/*.ts 38 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | use deno_core::serde::Deserialize; 2 | use deno_core::serde_json; 3 | use notify_rust::{self, error::Error as NotifyRustError, Notification}; 4 | 5 | #[derive(Debug, Deserialize)] 6 | #[serde(tag = "type")] 7 | enum NotificationTimeout { 8 | /// Do not expire, user will have to close this manually. 9 | Never, 10 | /// Expire after n milliseconds. 11 | Milliseconds { value: u32 }, 12 | } 13 | 14 | impl Into for NotificationTimeout { 15 | fn into(self) -> notify_rust::Timeout { 16 | match self { 17 | NotificationTimeout::Never => notify_rust::Timeout::Never, 18 | NotificationTimeout::Milliseconds { value } => { 19 | notify_rust::Timeout::Milliseconds(value) 20 | } 21 | } 22 | } 23 | } 24 | 25 | #[derive(Debug, Deserialize)] 26 | struct NotificationOptions { 27 | #[serde(rename = "_title")] 28 | title: String, 29 | 30 | #[serde(rename = "_subtitle")] 31 | subtitle: Option, 32 | 33 | #[serde(rename = "_body")] 34 | body: Option, 35 | 36 | #[serde(rename = "_icon")] 37 | icon: Option, 38 | 39 | #[serde(rename = "_soundName")] 40 | sound_name: Option, 41 | 42 | #[serde(rename = "_timeout")] 43 | timeout: Option, 44 | } 45 | 46 | /// Read the given NotificationOptions and send it as a notification. 47 | fn send_notification(options: NotificationOptions) -> Result<(), NotifyRustError> { 48 | let mut notification = Notification::new(); 49 | 50 | // Set Notification options 51 | notification.summary(&options.title); 52 | 53 | if let Some(subtitle) = &options.subtitle { 54 | notification.subtitle(subtitle); 55 | } 56 | 57 | if let Some(body) = &options.body { 58 | notification.body(body); 59 | } 60 | 61 | if let Some(icon) = &options.icon { 62 | notification.icon(icon); 63 | } 64 | 65 | if let Some(sound_name) = &options.sound_name { 66 | notification.sound_name(sound_name); 67 | } 68 | 69 | if let Some(timeout) = options.timeout { 70 | notification.timeout(timeout); 71 | } 72 | 73 | // Display it 74 | match notification.show() { 75 | Ok(_) => Ok(()), 76 | Err(error) => Err(error), 77 | } 78 | } 79 | 80 | // Set the app bundle on macos 81 | #[cfg(target_os = "macos")] 82 | fn set_bundle() { 83 | use notify_rust::error::{ApplicationError, MacOsError}; 84 | 85 | match notify_rust::set_application("com.apple.Terminal") { 86 | // Success 87 | Ok(_) => {} 88 | // If already set, ignore 89 | Err(MacOsError::Application(ApplicationError::AlreadySet(_))) => {} 90 | // Another error, report it (but don't fail) 91 | Err(err) => eprintln!("Error setting application bundle: {}", err), 92 | } 93 | } 94 | 95 | /// Convert the given str to a buffer pointer to be returned by ffi. 96 | /// Inspired by https://github.com/denoland/deno_bindgen 97 | fn to_result_str(str: String) -> *const u8 { 98 | let length = (str.len() as u32).to_be_bytes(); 99 | let mut v = length.to_vec(); 100 | 101 | let bytes = str.as_bytes(); 102 | v.extend_from_slice(bytes); 103 | 104 | std::mem::forget(str); 105 | let result = v.as_ptr(); 106 | // Leak the result to JS land. 107 | std::mem::forget(v); 108 | result 109 | } 110 | 111 | #[no_mangle] 112 | pub extern "C" fn notify_send(ptr: *const u8, len: usize) -> *const u8 { 113 | let buf = unsafe { std::slice::from_raw_parts(ptr, len) }; 114 | 115 | // Try parsing JSON into NotificationOptions object 116 | let options: NotificationOptions = match serde_json::from_slice(buf) { 117 | Ok(opt) => opt, 118 | Err(error) => { 119 | return to_result_str(format!( 120 | r#"{{"type":"error","when":"parsing_input","message":"{}"}}"#, 121 | error.to_string().replace("\"", "\\\"") 122 | )) 123 | } 124 | }; 125 | 126 | // Set the app bundle (if necessary) 127 | #[cfg(target_os = "macos")] 128 | set_bundle(); 129 | 130 | // Try sending the notification 131 | match send_notification(options) { 132 | Ok(_) => to_result_str(r#"{"type":"success"}"#.to_string()), 133 | Err(error) => to_result_str(format!( 134 | r#"{{"type":"error","when":"sending_notification","message":"{}"}}"#, 135 | error.to_string().replace("\"", "\\\"") 136 | )), 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /tests/basic.test.ts: -------------------------------------------------------------------------------- 1 | import { Notification } from "../ts/notification.ts"; 2 | import { 3 | assert, 4 | assertNotStrictEquals, 5 | assertThrows, 6 | } from "https://deno.land/std@0.134.0/testing/asserts.ts"; 7 | 8 | Deno.test("Creating a notification", () => { 9 | new Notification(); 10 | }); 11 | 12 | Deno.test("Chaining option calls", () => { 13 | const notif = new Notification() 14 | .title("Example title") 15 | .body("Example body"); 16 | 17 | assert(notif instanceof Notification); 18 | }); 19 | 20 | Deno.test("Require title", () => { 21 | const notif = new Notification(); 22 | assertThrows( 23 | () => notif.show(), 24 | Error, 25 | "Notification instance must have a title", 26 | ); 27 | }); 28 | 29 | Deno.test("Send basic notification", () => { 30 | // Create a new notification 31 | const notif = new Notification(); 32 | 33 | // Add a simple message 34 | notif.title("My message"); 35 | 36 | // Display it 37 | notif.show(); 38 | }); 39 | 40 | Deno.test("Send complex notification", () => { 41 | // Create a new notification 42 | const notif = new Notification( 43 | { macos: true, windows: true, linux: true }, 44 | // Attempting to use all options, so silently fail on other platforms 45 | false, 46 | ); 47 | 48 | // Set options 49 | notif 50 | .title("Title") 51 | .subtitle("Subtitle") 52 | .body("Body") 53 | .icon("utilities-terminal") 54 | .soundName("Basso") 55 | .timeout(10); 56 | 57 | // Display it 58 | notif.show(); 59 | }); 60 | 61 | Deno.test("Cloning notifications", () => { 62 | // Create a new notification 63 | const notif = new Notification(); 64 | 65 | // Add a simple message 66 | notif.title("My message"); 67 | 68 | // Make sure the clone is not the same object 69 | const newNotif = notif.clone(); 70 | assertNotStrictEquals(notif, newNotif); 71 | 72 | // Make sure the title is not the same 73 | newNotif.title("Another message"); 74 | assertNotStrictEquals((notif as any)._title, (newNotif as any)._title); 75 | }); 76 | -------------------------------------------------------------------------------- /tests/options.test.ts: -------------------------------------------------------------------------------- 1 | import { Notification } from "../ts/notification.ts"; 2 | import { 3 | assertEquals, 4 | assertStrictEquals, 5 | assertThrows, 6 | } from "https://deno.land/std@0.134.0/testing/asserts.ts"; 7 | 8 | Deno.test("Set title", () => { 9 | const title = "Example title"; 10 | const notif = new Notification().title(title); 11 | assertStrictEquals((notif as any)._title, title); 12 | }); 13 | 14 | Deno.test({ 15 | name: "Set subtitle", 16 | ignore: Deno.build.os !== "darwin" && Deno.build.os !== "windows", 17 | fn() { 18 | const subtitle = "Example subtitle"; 19 | const notif = new Notification({ macos: true, windows: true }).subtitle( 20 | subtitle, 21 | ); 22 | assertStrictEquals((notif as any)._subtitle, subtitle); 23 | }, 24 | }); 25 | 26 | Deno.test("Set body", () => { 27 | const body = "Example body"; 28 | const notif = new Notification().body(body); 29 | assertStrictEquals((notif as any)._body, body); 30 | }); 31 | 32 | Deno.test({ 33 | name: "Set icon", 34 | ignore: Deno.build.os !== "linux", 35 | fn() { 36 | const icon = "/path/to/icon"; 37 | const notif = new Notification({ linux: true }).icon(icon); 38 | assertStrictEquals((notif as any)._icon, icon); 39 | }, 40 | }); 41 | 42 | Deno.test("Set soundName", () => { 43 | const soundName = "Basso"; 44 | const notif = new Notification().soundName(soundName); 45 | assertStrictEquals((notif as any)._soundName, soundName); 46 | }); 47 | 48 | Deno.test({ 49 | name: "Set timeout", 50 | ignore: Deno.build.os !== "windows" && Deno.build.os !== "linux", 51 | fn() { 52 | const notif = new Notification({ linux: true, windows: true }).timeout( 53 | "never", 54 | ); 55 | assertEquals((notif as any)._timeout, { type: "Never" }); 56 | 57 | notif.timeout(10); 58 | assertEquals((notif as any)._timeout, { 59 | type: "Milliseconds", 60 | value: 10, 61 | }); 62 | }, 63 | }); 64 | 65 | Deno.test({ 66 | name: "Error on negative timeout", 67 | ignore: Deno.build.os !== "windows" && Deno.build.os !== "linux", 68 | fn() { 69 | const notif = new Notification({ linux: true, windows: true }); 70 | assertThrows( 71 | () => notif.timeout(-5), 72 | Error, 73 | `Notification timeout must be a number greater than 0 (or 'never').`, 74 | ); 75 | }, 76 | }); 77 | -------------------------------------------------------------------------------- /tests/platforms.test.ts: -------------------------------------------------------------------------------- 1 | import { Notification } from "../ts/notification.ts"; 2 | import { assertThrows } from "https://deno.land/std@0.134.0/testing/asserts.ts"; 3 | 4 | Deno.test("Attempt unsupported platform feature (strict)", () => { 5 | const notif = new Notification(); 6 | assertThrows( 7 | () => (notif as any).icon("/path/to/icon"), 8 | Error, 9 | "Notification instance does not explicitly support", 10 | ); 11 | }); 12 | 13 | Deno.test({ 14 | name: "Attempt supported platform feature (strict, linux)", 15 | ignore: Deno.build.os !== "linux", 16 | fn() { 17 | const notif = new Notification({ linux: true }); 18 | (notif as any).icon("/path/to/icon"); 19 | }, 20 | }); 21 | 22 | Deno.test({ 23 | name: "Attempt supported platform feature (strict, windows)", 24 | ignore: Deno.build.os !== "windows", 25 | fn() { 26 | const notif = new Notification({ windows: true }); 27 | (notif as any).subtitle("Example subtitle"); 28 | }, 29 | }); 30 | 31 | Deno.test({ 32 | name: "Attempt supported platform feature (strict, macos)", 33 | ignore: Deno.build.os !== "darwin", 34 | fn() { 35 | const notif = new Notification({ macos: true }); 36 | (notif as any).subtitle("Example subtitle"); 37 | }, 38 | }); 39 | 40 | Deno.test({ 41 | name: "Attempt supported platform feature on invalid os (strict, macos)", 42 | ignore: Deno.build.os !== "darwin", 43 | fn() { 44 | const notif = new Notification({ linux: true }); 45 | assertThrows( 46 | () => (notif as any).icon("/path/to/icon"), 47 | Error, 48 | "Current operating system (macos) does not support icon.", 49 | ); 50 | }, 51 | }); 52 | 53 | Deno.test({ 54 | name: "Attempt supported platform feature on invalid os (strict, windows)", 55 | ignore: Deno.build.os !== "windows", 56 | fn() { 57 | const notif = new Notification({ linux: true }); 58 | assertThrows( 59 | () => (notif as any).icon("/path/to/icon"), 60 | Error, 61 | `Current operating system (windows) does not support icon.`, 62 | ); 63 | }, 64 | }); 65 | 66 | Deno.test({ 67 | name: "Attempt supported platform feature on invalid os (strict, linux)", 68 | ignore: Deno.build.os !== "linux", 69 | fn() { 70 | const notif = new Notification({ macos: true, windows: true }); 71 | assertThrows( 72 | () => (notif as any).subtitle("Example subtitle"), 73 | Error, 74 | `Current operating system (linux) does not support subtitle.`, 75 | ); 76 | }, 77 | }); 78 | 79 | Deno.test({ 80 | name: "Attempt unsupported platform feature (non-strict, non-linux)", 81 | ignore: Deno.build.os === "linux", 82 | fn() { 83 | const notif = new Notification({ linux: true }, false); 84 | // Should not throw on windows/macos 85 | (notif as any).icon("/path/to/icon"); 86 | }, 87 | }); 88 | 89 | Deno.test({ 90 | name: "Attempt unsupported platform feature (non-strict, non-macos)", 91 | ignore: Deno.build.os === "darwin", 92 | fn() { 93 | const notif = new Notification({ macos: true }, false); 94 | // Show not throw on windows/linux 95 | (notif as any).subtitle("Example subtitle"); 96 | }, 97 | }); 98 | 99 | Deno.test({ 100 | name: "Attempt unsupported platform feature (non-strict, non-windows)", 101 | ignore: Deno.build.os === "windows", 102 | fn() { 103 | const notif = new Notification({ windows: true }, false); 104 | // Should not throw on linux/macos 105 | (notif as any).subtitle("Example subtitle"); 106 | }, 107 | }); 108 | 109 | Deno.test({ 110 | name: "Attempt supported multi-platform feature (strict, windows and macos)", 111 | ignore: Deno.build.os !== "windows" && Deno.build.os !== "darwin", 112 | fn() { 113 | const notif = new Notification({ windows: true, macos: true }); 114 | (notif as any).subtitle("Example subtitle"); 115 | }, 116 | }); 117 | -------------------------------------------------------------------------------- /ts/mod.ts: -------------------------------------------------------------------------------- 1 | import "./plugin.ts"; 2 | export * from "./notification.ts"; 3 | -------------------------------------------------------------------------------- /ts/notification.ts: -------------------------------------------------------------------------------- 1 | import { notify_send } from "./plugin.ts"; 2 | 3 | type PlatformFeature = Platform extends 4 | true ? FunctionType : never; 5 | 6 | // Resources 7 | // Web Notifications API: https://developer.mozilla.org/en-US/docs/Web/API/Notification 8 | // Notify-rust API: https://github.com/hoodie/notify-rust/blob/main/src/notification.rs 9 | 10 | export type MacSoundNames = 11 | | "Basso" 12 | | "Frog" 13 | | "Hero" 14 | | "Pop" 15 | | "Submarine" 16 | | "Blow" 17 | | "Funk" 18 | | "Morse" 19 | | "Purr" 20 | | "Tink" 21 | | "Bottle" 22 | | "Glass" 23 | | "Ping" 24 | | "Sosumi"; 25 | 26 | export class Notification< 27 | MacOS extends boolean = false, 28 | Windows extends boolean = false, 29 | Linux extends boolean = false, 30 | > { 31 | /** 32 | * Which platform-specific features to support in this notification. 33 | */ 34 | public readonly supports: { macos: MacOS; windows: Windows; linux: Linux }; 35 | /** 36 | * Whether or not to error if a feature is called on an operating system that does not support it. 37 | */ 38 | public readonly strictSupport: boolean; 39 | 40 | private _title: string | null = null; 41 | private _subtitle: string | null = null; 42 | private _body: string | null = null; 43 | private _icon: string | null = null; 44 | private _soundName: string | null = null; 45 | private _timeout: 46 | | { type: "Never" } 47 | | { type: "Milliseconds"; value: number } 48 | | null = null; 49 | 50 | /** 51 | * Create a Notification. 52 | * Most fields are empty by default. 53 | * 54 | * Platform specific-features are locked behind the `supports` parameter. 55 | * 56 | * @param supports Which platform-specific features to support in this notification. 57 | * @param strictSupport Whether or not to error if a feature is called on an operating system that does not support it. 58 | * 59 | * @example 60 | * ```ts 61 | * // By default, no platform-specific features are allowed. 62 | * const n1 = new Notification(); 63 | * 64 | * // Allow macos-specific features. 65 | * // This will throw if a macos-specific feature is called on non-macos platforms. 66 | * const n2 = new Notification({ macos: true }); 67 | * 68 | * // Allow macos-specific features. 69 | * // This will ignore macos-specific features on non-macos platforms. 70 | * const n3 = new Notification({ macos: true }, false); 71 | * ``` 72 | */ 73 | public constructor( 74 | { 75 | macos = false as MacOS, 76 | windows = false as Windows, 77 | linux = false as Linux, 78 | }: { macos?: MacOS; windows?: Windows; linux?: Linux } = {}, 79 | strictSupport: boolean = true, 80 | ) { 81 | this.supports = { 82 | macos, 83 | windows, 84 | linux, 85 | }; 86 | this.strictSupport = strictSupport; 87 | } 88 | 89 | /** 90 | * Set the `title`. 91 | * This is a required field. 92 | * Available on all platforms. 93 | * 94 | * For more elaborate content, use the `body` field. 95 | * 96 | * @param title 97 | */ 98 | public title = (title: string): this => { 99 | this._title = title; 100 | return this; 101 | }; 102 | 103 | /** 104 | * Set the `subtitle`. 105 | * Available on macOS and Windows. 106 | * 107 | * For more elaborate content, use the `body` field. 108 | * 109 | * @param subtitle 110 | */ 111 | public subtitle = ((subtitle: string): this => { 112 | if (this.#verifyPlatform(["macos", "windows"], "subtitle") === false) { 113 | return this; 114 | } 115 | this._subtitle = subtitle; 116 | return this; 117 | }) as PlatformFeature this>; 118 | 119 | /** 120 | * Set the `body`. 121 | * Available on all platforms. 122 | * 123 | * Multiline textual content of the notification. 124 | * Each line should be treated as a paragraph. 125 | * Simple html markup may be supported on some platforms. 126 | * 127 | * @param body 128 | */ 129 | public body = (body: string): this => { 130 | this._body = body; 131 | return this; 132 | }; 133 | 134 | /** 135 | * Set the `icon`. 136 | * Available on Linux. 137 | * 138 | * Can either be a file:// URI, 139 | * or a common icon name, usually those in `/usr/share/icons` 140 | * can all be used (or freedesktop.org names). 141 | * 142 | * @param icon 143 | */ 144 | public icon = ((icon: string): this => { 145 | if (this.#verifyPlatform(["linux"], "icon") === false) return this; 146 | this._icon = icon; 147 | return this; 148 | }) as PlatformFeature this>; 149 | 150 | /** 151 | * Set the `soundName` to play with the notification. 152 | * 153 | * With macOS support, a list of default sound names is provided. 154 | * 155 | * @param soundName 156 | */ 157 | public soundName = ( 158 | soundName: MacOS extends true ? MacSoundNames : string, 159 | ): this => { 160 | this._soundName = soundName; 161 | return this; 162 | }; 163 | 164 | /** 165 | * Set the `timeout`. 166 | * Available on Windows and Linux. 167 | * 168 | * This sets the time (in milliseconds) from the time the notification is displayed 169 | * until it is closed again by the Notification Server. 170 | * 171 | * Setting this to `'never'` will cause the notification to never expire. 172 | * 173 | * @param timeout 174 | */ 175 | public timeout = ((timeout: "never" | number): this => { 176 | if (this.#verifyPlatform(["windows", "linux"], "timeout") === false) { 177 | return this; 178 | } 179 | 180 | // TODO: Maybe compile-time check for positive numbers (once TS supports it) 181 | if (typeof timeout === "number" && timeout <= 0) { 182 | throw new Error( 183 | "Notification timeout must be a number greater than 0 (or 'never').", 184 | ); 185 | } 186 | 187 | if (timeout === "never") { 188 | this._timeout = { type: "Never" }; 189 | } else if (typeof timeout === "number") { 190 | this._timeout = { type: "Milliseconds", value: timeout }; 191 | } 192 | 193 | return this; 194 | }) as PlatformFeature this>; 195 | 196 | /** 197 | * Display the notification to the user. 198 | * 199 | * @throws When an error occurs while sending the notification. 200 | */ 201 | public show = () => { 202 | // Check has minimum requirements to be sent 203 | if (this.#verifyCanBeSent() !== true) return; 204 | 205 | const json = JSON.stringify(this); 206 | const result = notify_send(json); 207 | 208 | if (result.type === "error") { 209 | throw new Error(`${result.message} (when: ${result.when})`); 210 | } 211 | }; 212 | 213 | /** 214 | * Clone the notification into a separate instance, maintaining all the properties. 215 | * 216 | * @returns The new notification instance. 217 | */ 218 | public clone = (): Notification => { 219 | return Object.assign( 220 | Object.create(Object.getPrototypeOf(this)), 221 | this, 222 | ) as Notification; 223 | }; 224 | 225 | /** 226 | * Verify whether or not the notification has the minimum required fields to be sent. 227 | * 228 | * @throws If the notification cannot be sent with the appropriate explanation error. 229 | * @returns True if the notification can be sent. 230 | */ 231 | #verifyCanBeSent = (): boolean => { 232 | // Notification NEEDS at least a title 233 | if (this._title === null) { 234 | throw new Error(`Notification instance must have a title.`); 235 | } 236 | return true; 237 | }; 238 | 239 | /** 240 | * Verify whether a feature meant for a given platform should be run on the current platform. 241 | * 242 | * @param requestedPlatforms The requested platform to verify against the current platform. 243 | * @throws If the platform is not supported by the notification instance. 244 | * @throws If the feature should not be run (while in strict mode). 245 | * @returns True if the feature should be run, false if the feature should not be run (while in non-strict mode). 246 | */ 247 | #verifyPlatform = ( 248 | requestedPlatforms: ("macos" | "linux" | "windows")[], 249 | featureName: string, 250 | ): boolean => { 251 | const currentPlatform = Deno.build.os === "darwin" 252 | ? "macos" 253 | : Deno.build.os; 254 | 255 | // List of platforms that are supported by the notification instance 256 | const supportedPlatforms = requestedPlatforms.filter((platform) => 257 | this.supports[platform] 258 | ); 259 | 260 | // If the requested platforms are not supported by this Notification instance, throw an error 261 | if (supportedPlatforms.length === 0) { 262 | const unsupportedPlatforms = requestedPlatforms.filter((platform) => 263 | this.supports[platform] === false 264 | ); 265 | throw new Error( 266 | `Notification instance does not explicitly support ${ 267 | unsupportedPlatforms.join(", or ") 268 | }.`, 269 | ); 270 | } 271 | 272 | // Whether or not the oen of the requested & supported platform is the current platform 273 | const isPlatformValid = supportedPlatforms.some((platform) => ( 274 | currentPlatform === platform 275 | )); 276 | 277 | // If we're not strictly checking for support, just return whether or not the platform is valid 278 | if (this.strictSupport === false) { 279 | return isPlatformValid; 280 | } 281 | // Otherwise, we are strictly checking for support 282 | 283 | // If we are strictly checking for support, and the platform is not valid, throw an error 284 | if (isPlatformValid === false) { 285 | throw new Error( 286 | `Current operating system (${currentPlatform}) does not support ${featureName}.`, 287 | ); 288 | } 289 | // Otherwise, we are strictly checking for support AND the platform is valid 290 | return true; 291 | }; 292 | } 293 | -------------------------------------------------------------------------------- /ts/plugin.ts: -------------------------------------------------------------------------------- 1 | import { CacheSetting, dlopen } from "https://deno.land/x/plug@1.0.0/mod.ts"; 2 | 3 | const VERSION = "1.4.3"; 4 | const CACHE_POLICY: CacheSetting = 5 | Deno.env.get("NOTIFY_PLUGIN_URL") === undefined ? "use" : "reloadAll"; 6 | const NOTIFY_PLUGIN_URL = Deno.env.get("NOTIFY_PLUGIN_URL") ?? 7 | `https://github.com/Pandawan/deno_notify/releases/download/${VERSION}/`; 8 | 9 | const library = await dlopen({ 10 | name: "deno_notify", 11 | url: NOTIFY_PLUGIN_URL, 12 | cache: CACHE_POLICY, 13 | suffixes: { 14 | darwin: `.${Deno.build.arch}`, 15 | }, 16 | }, { 17 | notify_send: { parameters: ["buffer", "usize"], result: "buffer" }, 18 | }); 19 | 20 | // TODO: Check out https://github.com/webview/webview_deno/blob/main/src/ffi.ts 21 | function readPointer(v: Deno.PointerValue): Uint8Array | null { 22 | if (v == null) return null; 23 | 24 | const ptr = new Deno.UnsafePointerView(v); 25 | const lengthBe = new Uint8Array(4); 26 | const view = new DataView(lengthBe.buffer); 27 | ptr.copyInto(lengthBe, 0); 28 | const buf = new Uint8Array(view.getUint32(0)); 29 | ptr.copyInto(buf, 4); 30 | return buf; 31 | } 32 | 33 | type NotifySendResult = { 34 | type: "success"; 35 | } | { 36 | type: "error"; 37 | when: string; 38 | message: string; 39 | }; 40 | 41 | function notify_send(json: string): NotifySendResult { 42 | const encodedJson = new TextEncoder().encode(json); 43 | const ptrResult = library.symbols.notify_send( 44 | encodedJson, 45 | encodedJson.length, 46 | ); 47 | 48 | // Get the contents at the resulting pointer 49 | const bufResult = readPointer(ptrResult); 50 | if (bufResult == null) { 51 | return { 52 | type: "error", 53 | when: "parsing_result", 54 | message: 55 | "Native deno_notify library returned a null pointer. Something is wrong.", 56 | }; 57 | } 58 | 59 | // TODO: Use Deno.UnsafePointerView#getCString 60 | const decodedJson = new TextDecoder().decode(bufResult); 61 | const result = JSON.parse(decodedJson); 62 | return result as NotifySendResult; 63 | } 64 | 65 | export { notify_send }; 66 | --------------------------------------------------------------------------------