tauri.ts 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. // Copyright 2019-2021 Tauri Programme within The Commons Conservancy
  2. // SPDX-License-Identifier: Apache-2.0
  3. // SPDX-License-Identifier: MIT
  4. /**
  5. * Invoke your custom commands.
  6. *
  7. * This package is also accessible with `window.__TAURI__.tauri` when `tauri.conf.json > build > withGlobalTauri` is set to true.
  8. * @module
  9. */
  10. /** @ignore */
  11. declare global {
  12. // eslint-disable-next-line @typescript-eslint/no-unused-vars
  13. interface Window {
  14. rpc: {
  15. notify: (command: string, args?: { [key: string]: unknown }) => void
  16. }
  17. }
  18. }
  19. // the `__TAURI_INVOKE_KEY__` variable is injected at runtime by Tauri
  20. // eslint-disable-next-line @typescript-eslint/naming-convention
  21. declare let __TAURI_INVOKE_KEY__: number
  22. /** @ignore */
  23. function uid(): string {
  24. const length = new Int8Array(1)
  25. window.crypto.getRandomValues(length)
  26. const array = new Uint8Array(Math.max(16, Math.abs(length[0])))
  27. window.crypto.getRandomValues(array)
  28. return array.join('')
  29. }
  30. /**
  31. * Transforms a callback function to a string identifier that can be passed to the backend.
  32. * The backend uses the identifier to `eval()` the callback.
  33. *
  34. * @return A unique identifier associated with the callback function.
  35. */
  36. function transformCallback(
  37. callback?: (response: any) => void,
  38. once = false
  39. ): string {
  40. const identifier = uid()
  41. Object.defineProperty(window, identifier, {
  42. value: (result: any) => {
  43. if (once) {
  44. Reflect.deleteProperty(window, identifier)
  45. }
  46. return callback?.(result)
  47. },
  48. writable: false,
  49. configurable: true
  50. })
  51. return identifier
  52. }
  53. /** Command arguments. */
  54. interface InvokeArgs {
  55. [key: string]: unknown
  56. }
  57. /**
  58. * Sends a message to the backend.
  59. *
  60. * @param cmd The command name.
  61. * @param args The optional arguments to pass to the command.
  62. * @return A promise resolving or rejecting to the backend response.
  63. */
  64. async function invoke<T>(cmd: string, args: InvokeArgs = {}): Promise<T> {
  65. return new Promise((resolve, reject) => {
  66. const callback = transformCallback((e) => {
  67. resolve(e)
  68. Reflect.deleteProperty(window, error)
  69. }, true)
  70. const error = transformCallback((e) => {
  71. reject(e)
  72. Reflect.deleteProperty(window, callback)
  73. }, true)
  74. window.rpc.notify(cmd, {
  75. __invokeKey: __TAURI_INVOKE_KEY__,
  76. callback,
  77. error,
  78. ...args
  79. })
  80. })
  81. }
  82. /**
  83. * Convert a device file path to an URL that can be loaded by the webview.
  84. * Note that `asset:` must be allowed on the `csp` value configured on `tauri.conf.json`.
  85. *
  86. * @param filePath the file path. On Windows, the drive name must be omitted, i.e. using `/Users/user/file.png` instead of `C:/Users/user/file.png`.
  87. *
  88. * @return the URL that can be used as source on the webview
  89. */
  90. function convertFileSrc(filePath: string): string {
  91. return navigator.userAgent.includes('Windows')
  92. ? `https://custom.protocol.asset_${filePath}`
  93. : `asset://${filePath}`
  94. }
  95. export type { InvokeArgs }
  96. export { transformCallback, invoke, convertFileSrc }