Преглед изворни кода

feat(api): add `writeTextFile` and `(path, contents, options)` overload (#4228)

Lucas Fernandes Nogueira пре 3 година
родитељ
комит
3f998ca294

+ 5 - 0
.changes/write-file-rename.md

@@ -0,0 +1,5 @@
+---
+"api": patch
+---
+
+Renamed `writeFile` to `writeTextFile` but kept the original function for backwards compatibility.

+ 5 - 0
.changes/write-file-variants.md

@@ -0,0 +1,5 @@
+---
+"api": patch
+---
+
+Added `(path, contents[, options])` overload to the `writeTextFile` and `writeBinaryFile` APIs.

Разлика између датотеке није приказан због своје велике величине
+ 0 - 0
core/tauri/scripts/bundle.js


Разлика између датотеке није приказан због своје велике величине
+ 0 - 0
examples/api/dist/assets/index.js


Разлика између датотеке није приказан због своје велике величине
+ 0 - 0
examples/api/dist/assets/vendor.js


+ 8 - 7
examples/api/src-tauri/Cargo.lock

@@ -3052,7 +3052,7 @@ dependencies = [
 
 [[package]]
 name = "tauri"
-version = "1.0.0-rc.13"
+version = "1.0.0-rc.14"
 dependencies = [
  "anyhow",
  "attohttpc",
@@ -3102,6 +3102,7 @@ dependencies = [
  "tauri-utils",
  "tempfile",
  "thiserror",
+ "time",
  "tokio",
  "url",
  "uuid 1.0.0",
@@ -3113,7 +3114,7 @@ dependencies = [
 
 [[package]]
 name = "tauri-build"
-version = "1.0.0-rc.10"
+version = "1.0.0-rc.12"
 dependencies = [
  "anyhow",
  "cargo_toml",
@@ -3127,7 +3128,7 @@ dependencies = [
 
 [[package]]
 name = "tauri-codegen"
-version = "1.0.0-rc.7"
+version = "1.0.0-rc.8"
 dependencies = [
  "base64",
  "brotli",
@@ -3136,7 +3137,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "regex",
- "semver 1.0.7",
+ "semver 1.0.9",
  "serde",
  "serde_json",
  "sha2",
@@ -3148,7 +3149,7 @@ dependencies = [
 
 [[package]]
 name = "tauri-macros"
-version = "1.0.0-rc.7"
+version = "1.0.0-rc.8"
 dependencies = [
  "heck 0.4.0",
  "proc-macro2",
@@ -3194,7 +3195,7 @@ dependencies = [
 
 [[package]]
 name = "tauri-utils"
-version = "1.0.0-rc.7"
+version = "1.0.0-rc.8"
 dependencies = [
  "aes-gcm",
  "brotli",
@@ -3209,7 +3210,7 @@ dependencies = [
  "phf 0.10.1",
  "proc-macro2",
  "quote",
- "semver 1.0.7",
+ "semver 1.0.9",
  "serde",
  "serde_json",
  "serde_with",

+ 43 - 44
examples/api/src/components/FileSystem.svelte

@@ -1,78 +1,77 @@
 <script>
-  import { readBinaryFile, readDir, Dir } from "@tauri-apps/api/fs";
-  import { convertFileSrc } from "@tauri-apps/api/tauri";
+  import {
+    readBinaryFile,
+    writeTextFile,
+    readDir,
+    Dir
+  } from '@tauri-apps/api/fs'
+  import { convertFileSrc } from '@tauri-apps/api/tauri'
 
-  export let onMessage;
-  export let insecureRenderHtml;
+  export let onMessage
+  export let insecureRenderHtml
 
-  let pathToRead = "";
-  let img;
+  let pathToRead = ''
+  let img
 
   function getDir() {
-    const dirSelect = document.getElementById("dir");
-    return dirSelect.value ? parseInt(dir.value) : null;
+    const dirSelect = document.getElementById('dir')
+    return dirSelect.value ? parseInt(dir.value) : null
   }
 
   function arrayBufferToBase64(buffer, callback) {
     const blob = new Blob([buffer], {
-      type: "application/octet-binary",
-    });
-    const reader = new FileReader();
+      type: 'application/octet-binary'
+    })
+    const reader = new FileReader()
     reader.onload = function (evt) {
-      const dataurl = evt.target.result;
-      callback(dataurl.substr(dataurl.indexOf(",") + 1));
-    };
-    reader.readAsDataURL(blob);
+      const dataurl = evt.target.result
+      callback(dataurl.substr(dataurl.indexOf(',') + 1))
+    }
+    reader.readAsDataURL(blob)
   }
 
   const DirOptions = Object.keys(Dir)
     .filter((key) => isNaN(parseInt(key)))
-    .map((dir) => [dir, Dir[dir]]);
+    .map((dir) => [dir, Dir[dir]])
 
   function read() {
-    const isFile = pathToRead.match(/\S+\.\S+$/g);
+    const isFile = pathToRead.match(/\S+\.\S+$/g)
     const opts = {
-      dir: getDir(),
-    };
+      dir: getDir()
+    }
     const promise = isFile
       ? readBinaryFile(pathToRead, opts)
-      : readDir(pathToRead, opts);
+      : readDir(pathToRead, opts)
     promise
       .then(function (response) {
         if (isFile) {
-          if (pathToRead.includes(".png") || pathToRead.includes(".jpg")) {
+          if (pathToRead.includes('.png') || pathToRead.includes('.jpg')) {
             arrayBufferToBase64(new Uint8Array(response), function (base64) {
-              const src = "data:image/png;base64," + base64;
-              insecureRenderHtml('<img src="' + src + '"></img>');
-            });
+              const src = 'data:image/png;base64,' + base64
+              insecureRenderHtml('<img src="' + src + '"></img>')
+            })
           } else {
-            const value = String.fromCharCode.apply(null, response);
+            const value = String.fromCharCode.apply(null, response)
             insecureRenderHtml(
               '<textarea id="file-response"></textarea><button id="file-save">Save</button>'
-            );
+            )
             setTimeout(() => {
-              const fileInput = document.getElementById("file-response");
-              fileInput.value = value;
+              const fileInput = document.getElementById('file-response')
+              fileInput.value = value
               document
-                .getElementById("file-save")
-                .addEventListener("click", function () {
-                  writeFile(
-                    {
-                      file: pathToRead,
-                      contents: fileInput.value,
-                    },
-                    {
-                      dir: getDir(),
-                    }
-                  ).catch(onMessage);
-                });
-            });
+                .getElementById('file-save')
+                .addEventListener('click', function () {
+                  writeTextFile(pathToRead, fileInput.value, {
+                    dir: getDir()
+                  }).catch(onMessage)
+                })
+            })
           }
         } else {
-          onMessage(response);
+          onMessage(response)
         }
       })
-      .catch(onMessage);
+      .catch(onMessage)
   }
 
   function setSrc() {
@@ -95,5 +94,5 @@
   <button class="button" id="read">Read</button>
   <button class="button" type="button" on:click={setSrc}>Use as img src</button>
 
-  <img alt="file" bind:this={img}>
+  <img alt="file" bind:this={img} />
 </form>

+ 6 - 6
examples/api/yarn.lock

@@ -23,9 +23,9 @@
     svelte-hmr "^0.14.7"
 
 "@tauri-apps/api@../../tooling/api/dist":
-  version "1.0.0-rc.3"
+  version "1.0.0-rc.6"
   dependencies:
-    type-fest "2.12.2"
+    type-fest "2.13.0"
 
 "@zerodevx/svelte-json-view@0.2.0":
   version "0.2.0"
@@ -267,10 +267,10 @@ svelte@3.35.0:
   resolved "https://registry.yarnpkg.com/svelte/-/svelte-3.35.0.tgz#e0d0ba60c4852181c2b4fd851194be6fda493e65"
   integrity sha512-gknlZkR2sXheu/X+B7dDImwANVvK1R0QGQLd8CNIfxxGPeXBmePnxfzb6fWwTQRsYQG7lYkZXvpXJvxvpsoB7g==
 
-type-fest@2.12.2:
-  version "2.12.2"
-  resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.12.2.tgz#80a53614e6b9b475eb9077472fb7498dc7aa51d0"
-  integrity sha512-qt6ylCGpLjZ7AaODxbpyBZSs9fCI9SkL3Z9q2oxMBQhs/uyY+VD8jHA8ULCGmWQJlBgqvO3EJeAngOHD8zQCrQ==
+type-fest@2.13.0:
+  version "2.13.0"
+  resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.13.0.tgz#d1ecee38af29eb2e863b22299a3d68ef30d2abfb"
+  integrity sha512-lPfAm42MxE4/456+QyIaaVBAwgpJb6xZ8PRu09utnhPdWwcyj9vgy6Sq0Z5yNbJ21EdxB5dRU/Qg8bsyAMtlcw==
 
 vite@^2.6.4:
   version "2.6.14"

+ 6 - 1
tooling/api/src/dialog.ts

@@ -207,6 +207,11 @@ async function confirm(
   })
 }
 
-export type { DialogFilter, OpenDialogOptions, SaveDialogOptions }
+export type {
+  DialogFilter,
+  OpenDialogOptions,
+  SaveDialogOptions,
+  MessageDialogOptions
+}
 
 export { open, save, message, ask, confirm }

+ 103 - 13
tooling/api/src/fs.ts

@@ -96,6 +96,7 @@ export enum BaseDirectory {
 
 interface FsOptions {
   dir?: BaseDirectory
+  // note that adding fields here needs a change in the writeBinaryFile check
 }
 
 interface FsDirOptions {
@@ -111,12 +112,14 @@ interface FsTextFileOption {
   contents: string
 }
 
+type BinaryFileContents = Iterable<number> | ArrayLike<number>
+
 /** Options object used to write a binary data to a file. */
 interface FsBinaryFileOption {
   /** Path to the file to write. */
   path: string
   /** The byte array contents. */
-  contents: Iterable<number> | ArrayLike<number>
+  contents: BinaryFileContents
 }
 
 interface FileEntry {
@@ -177,19 +180,61 @@ async function readBinaryFile(
 /**
  * Writes a UTF-8 text file.
  *
- * @param file File configuration object.
+ * @param path The file path.
+ * @param contents The file contents.
+ * @param options Configuration object.
+ * @returns A promise indicating the success or failure of the operation.
+ */
+async function writeTextFile(
+  path: string,
+  contents: string,
+  options?: FsOptions
+): Promise<void>
+
+/**
+ * Writes a UTF-8 text file.
+ *
+ * @param file The object containing the file path and contents.
  * @param options Configuration object.
  * @returns A promise indicating the success or failure of the operation.
  */
-async function writeFile(
+async function writeTextFile(
   file: FsTextFileOption,
-  options: FsOptions = {}
+  options?: FsOptions
+): Promise<void>
+
+/**
+ * Writes a UTF-8 text file.
+ *
+ * @param file File configuration object.
+ * @param options Configuration object.
+ * @returns A promise indicating the success or failure of the operation.
+ */
+async function writeTextFile(
+  path: string | FsTextFileOption,
+  contents?: string | FsOptions,
+  options?: FsOptions
 ): Promise<void> {
   if (typeof options === 'object') {
     Object.freeze(options)
   }
-  if (typeof file === 'object') {
-    Object.freeze(file)
+  if (typeof path === 'object') {
+    Object.freeze(path)
+  }
+
+  const file: FsTextFileOption = { path: '', contents: '' }
+  let fileOptions: FsOptions | undefined = options
+  if (typeof path === 'string') {
+    file.path = path
+  } else {
+    file.path = path.path
+    file.contents = path.contents
+  }
+
+  if (typeof contents === 'string') {
+    file.contents = contents ?? ''
+  } else {
+    fileOptions = contents
   }
 
   return invokeTauriCommand({
@@ -198,7 +243,7 @@ async function writeFile(
       cmd: 'writeFile',
       path: file.path,
       contents: Array.from(new TextEncoder().encode(file.contents)),
-      options
+      options: fileOptions
     }
   })
 }
@@ -206,19 +251,62 @@ async function writeFile(
 /**
  * Writes a byte array content to a file.
  *
- * @param file Write configuration object.
+ * @param path The file path.
+ * @param contents The file contents.
+ * @param options Configuration object.
+ * @returns A promise indicating the success or failure of the operation.
+ */
+async function writeBinaryFile(
+  path: string,
+  contents: BinaryFileContents,
+  options?: FsOptions
+): Promise<void>
+
+/**
+ * Writes a byte array content to a file.
+ *
+ * @param file The object containing the file path and contents.
  * @param options Configuration object.
  * @returns A promise indicating the success or failure of the operation.
  */
 async function writeBinaryFile(
   file: FsBinaryFileOption,
-  options: FsOptions = {}
+  options?: FsOptions
+): Promise<void>
+
+/**
+ * Writes a byte array content to a file.
+ *
+ * @param file Write configuration object.
+ * @param options Configuration object.
+ * @returns A promise indicating the success or failure of the operation.
+ */
+async function writeBinaryFile(
+  path: string | FsBinaryFileOption,
+  contents?: BinaryFileContents | FsOptions,
+  options?: FsOptions
 ): Promise<void> {
   if (typeof options === 'object') {
     Object.freeze(options)
   }
-  if (typeof file === 'object') {
-    Object.freeze(file)
+  if (typeof path === 'object') {
+    Object.freeze(path)
+  }
+
+  const file: FsBinaryFileOption = { path: '', contents: [] }
+  let fileOptions: FsOptions | undefined = options
+  if (typeof path === 'string') {
+    file.path = path
+  } else {
+    file.path = path.path
+    file.contents = path.contents
+  }
+
+  if (contents && 'dir' in contents) {
+    fileOptions = contents
+  } else {
+    // @ts-expect-error
+    file.contents = contents ?? []
   }
 
   return invokeTauriCommand({
@@ -227,7 +315,7 @@ async function writeBinaryFile(
       cmd: 'writeFile',
       path: file.path,
       contents: Array.from(file.contents),
-      options
+      options: fileOptions
     }
   })
 }
@@ -371,6 +459,7 @@ export type {
   FsOptions,
   FsDirOptions,
   FsTextFileOption,
+  BinaryFileContents,
   FsBinaryFileOption,
   FileEntry
 }
@@ -379,7 +468,8 @@ export {
   BaseDirectory as Dir,
   readTextFile,
   readBinaryFile,
-  writeFile,
+  writeTextFile,
+  writeTextFile as writeFile,
   writeBinaryFile,
   readDir,
   createDir,

+ 1 - 1
tooling/api/src/http.ts

@@ -431,4 +431,4 @@ export type {
   FetchOptions
 }
 
-export { getClient, fetch, Body, Client, Response, ResponseType }
+export { getClient, fetch, Body, Client, Response, ResponseType, FilePart }

+ 1 - 7
tooling/cli/node/test/jest/fixtures/app/dist/index.html

@@ -31,13 +31,7 @@
         }
 
         return window.__TAURI__.fs
-          .writeFile(
-            {
-              path: 'tauri-test.txt',
-              contents: contents
-            },
-            options
-          )
+          .writeTextFile('tauri-test.txt', contents, options)
           .then(function (res) {
             reply({
               cmd: 'writeFile' + commandSuffix

Неке датотеке нису приказане због велике количине промена