tauri.ts 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  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. __TAURI_IPC__: (message: any) => void
  15. ipc: {
  16. postMessage: (args: string) => void
  17. }
  18. }
  19. }
  20. /** @ignore */
  21. function uid(): number {
  22. return window.crypto.getRandomValues(new Uint32Array(1))[0]
  23. }
  24. /**
  25. * Transforms a callback function to a string identifier that can be passed to the backend.
  26. * The backend uses the identifier to `eval()` the callback.
  27. *
  28. * @return A unique identifier associated with the callback function.
  29. */
  30. function transformCallback(
  31. callback?: (response: any) => void,
  32. once = false
  33. ): number {
  34. const identifier = uid()
  35. const prop = `_${identifier}`
  36. Object.defineProperty(window, prop, {
  37. value: (result: any) => {
  38. if (once) {
  39. Reflect.deleteProperty(window, prop)
  40. }
  41. return callback?.(result)
  42. },
  43. writable: false,
  44. configurable: true
  45. })
  46. return identifier
  47. }
  48. /** Command arguments. */
  49. interface InvokeArgs {
  50. [key: string]: unknown
  51. }
  52. /**
  53. * Sends a message to the backend.
  54. * @example
  55. * ```typescript
  56. * import { invoke } from '@tauri-apps/api/tauri';
  57. * await invoke('login', { user: 'tauri', password: 'poiwe3h4r5ip3yrhtew9ty' });
  58. * ```
  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: T) => {
  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.__TAURI_IPC__({
  75. cmd,
  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:` and `https://asset.localhost` must be allowed on the `csp` value configured on `tauri.conf.json > tauri > security`.
  85. * Example CSP value: `"csp": "default-src 'self'; img-src 'self' asset: https://asset.localhost"` to use the asset protocol on image sources.
  86. *
  87. * Additionally, the `asset` must be allowlisted under `tauri.conf.json > tauri > allowlist > protocol`,
  88. * and its access scope must be defined on the `assetScope` array on the same `protocol` object.
  89. *
  90. * @param filePath The file path.
  91. * @param protocol The protocol to use. Defaults to `asset`. You only need to set this when using a custom protocol.
  92. * @example
  93. * ```typescript
  94. * import { appDir, join } from '@tauri-apps/api/path';
  95. * import { convertFileSrc } from '@tauri-apps/api/tauri';
  96. * const appDirPath = await appDir();
  97. * const filePath = await join(appDir, 'assets/video.mp4');
  98. * const assetUrl = convertFileSrc(filePath);
  99. *
  100. * const video = document.getElementById('my-video');
  101. * const source = document.createElement('source');
  102. * source.type = 'video/mp4';
  103. * source.src = assetUrl;
  104. * video.appendChild(source);
  105. * video.load();
  106. * ```
  107. *
  108. * @return the URL that can be used as source on the webview.
  109. */
  110. function convertFileSrc(filePath: string, protocol = 'asset'): string {
  111. const path = encodeURIComponent(filePath)
  112. return navigator.userAgent.includes('Windows')
  113. ? `https://${protocol}.localhost/${path}`
  114. : `${protocol}://${path}`
  115. }
  116. export type { InvokeArgs }
  117. export { transformCallback, invoke, convertFileSrc }