fs.ts 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. import { promisified } from './tauri'
  2. export enum BaseDirectory {
  3. Audio = 1,
  4. Cache,
  5. Config,
  6. Data,
  7. LocalData,
  8. Desktop,
  9. Document,
  10. Download,
  11. Executable,
  12. Font,
  13. Home,
  14. Picture,
  15. Public,
  16. Runtime,
  17. Template,
  18. Video,
  19. Resource,
  20. App,
  21. }
  22. export interface FsOptions {
  23. dir?: BaseDirectory
  24. }
  25. export interface FsTextFileOption {
  26. path: string
  27. contents: string
  28. }
  29. export interface FsBinaryFileOption {
  30. path: string
  31. contents: ArrayBuffer
  32. }
  33. export interface FileEntry {
  34. path: string
  35. // name of the directory/file
  36. // can be null if the path terminates with `..`
  37. name?: string
  38. // children of this entry if it's a directory; null otherwise
  39. children?: FileEntry[]
  40. }
  41. /**
  42. * reads a file as text
  43. *
  44. * @param filePath path to the file
  45. * @param [options] configuration object
  46. * @param [options.dir] base directory
  47. * @return
  48. */
  49. async function readTextFile(filePath: string, options: FsOptions = {}): Promise<string> {
  50. return await promisified({
  51. cmd: 'readTextFile',
  52. path: filePath,
  53. options
  54. })
  55. }
  56. /**
  57. * reads a file as binary
  58. *
  59. * @param filePath path to the file
  60. * @param {Object} [options] configuration object
  61. * @param {BaseDirectory} [options.dir] base directory
  62. * @return {Promise<int[]>}
  63. */
  64. async function readBinaryFile(filePath: string, options: FsOptions = {}): Promise<string> {
  65. return await promisified({
  66. cmd: 'readBinaryFile',
  67. path: filePath,
  68. options
  69. })
  70. }
  71. /**
  72. * writes a text file
  73. *
  74. * @param file
  75. * @param file.path path of the file
  76. * @param file.contents contents of the file
  77. * @param [options] configuration object
  78. * @param [options.dir] base directory
  79. * @return
  80. */
  81. async function writeFile(file: FsTextFileOption, options: FsOptions = {}): Promise<void> {
  82. if (typeof options === 'object') {
  83. Object.freeze(options)
  84. }
  85. if (typeof file === 'object') {
  86. Object.freeze(file)
  87. }
  88. return await promisified({
  89. cmd: 'writeFile',
  90. file: file.path,
  91. contents: file.contents,
  92. options
  93. })
  94. }
  95. const CHUNK_SIZE = 65536
  96. /**
  97. * convert an Uint8Array to ascii string
  98. *
  99. * @param arr
  100. * @return ASCII string
  101. */
  102. function uint8ArrayToString(arr: Uint8Array): string {
  103. if (arr.length < CHUNK_SIZE) {
  104. return String.fromCharCode.apply(null, Array.from(arr))
  105. }
  106. let result = ''
  107. const arrLen = arr.length
  108. for (let i = 0; i < arrLen; i++) {
  109. const chunk = arr.subarray(i * CHUNK_SIZE, (i + 1) * CHUNK_SIZE)
  110. result += String.fromCharCode.apply(null, Array.from(chunk))
  111. }
  112. return result
  113. }
  114. /**
  115. * convert an ArrayBuffer to base64 encoded string
  116. *
  117. * @param buffer
  118. * @return base64 encoded string
  119. */
  120. function arrayBufferToBase64(buffer: ArrayBuffer): string {
  121. const str = uint8ArrayToString(new Uint8Array(buffer))
  122. return btoa(str)
  123. }
  124. /**
  125. * writes a binary file
  126. *
  127. * @param file
  128. * @param file.path path of the file
  129. * @param file.contents contents of the file
  130. * @param [options] configuration object
  131. * @param [options.dir] base directory
  132. * @return
  133. */
  134. async function writeBinaryFile(file: FsBinaryFileOption, options: FsOptions = {}): Promise<void> {
  135. if (typeof options === 'object') {
  136. Object.freeze(options)
  137. }
  138. if (typeof file === 'object') {
  139. Object.freeze(file)
  140. }
  141. return await promisified({
  142. cmd: 'writeFile',
  143. file: file.path,
  144. contents: arrayBufferToBase64(file.contents),
  145. options
  146. })
  147. }
  148. /**
  149. * list directory files
  150. *
  151. * @param dir path to the directory to read
  152. * @param [options] configuration object
  153. * @param [options.recursive] whether to list dirs recursively or not
  154. * @param [options.dir] base directory
  155. * @return
  156. */
  157. async function readDir(dir: string, options: FsOptions = {}): Promise<FileEntry[]> {
  158. return await promisified({
  159. cmd: 'readDir',
  160. path: dir,
  161. options
  162. })
  163. }
  164. /**
  165. * Creates a directory
  166. * If one of the path's parent components doesn't exist
  167. * and the `recursive` option isn't set to true, it will be rejected
  168. *
  169. * @param dir path to the directory to create
  170. * @param [options] configuration object
  171. * @param [options.recursive] whether to create the directory's parent components or not
  172. * @param [options.dir] base directory
  173. * @return
  174. */
  175. async function createDir(dir: string, options: FsOptions = {}): Promise<void> {
  176. return await promisified({
  177. cmd: 'createDir',
  178. path: dir,
  179. options
  180. })
  181. }
  182. /**
  183. * Removes a directory
  184. * If the directory is not empty and the `recursive` option isn't set to true, it will be rejected
  185. *
  186. * @param dir path to the directory to remove
  187. * @param [options] configuration object
  188. * @param [options.recursive] whether to remove all of the directory's content or not
  189. * @param [options.dir] base directory
  190. * @return
  191. */
  192. async function removeDir(dir: string, options: FsOptions = {}): Promise<void> {
  193. return await promisified({
  194. cmd: 'removeDir',
  195. path: dir,
  196. options
  197. })
  198. }
  199. /**
  200. * Copy file
  201. *
  202. * @param source
  203. * @param destination
  204. * @param [options] configuration object
  205. * @param [options.dir] base directory
  206. * @return
  207. */
  208. async function copyFile(source: string, destination: string, options: FsOptions = {}): Promise<void> {
  209. return await promisified({
  210. cmd: 'copyFile',
  211. source,
  212. destination,
  213. options
  214. })
  215. }
  216. /**
  217. * Removes a file
  218. *
  219. * @param file path to the file to remove
  220. * @param [options] configuration object
  221. * @param [options.dir] base directory
  222. * @return
  223. */
  224. async function removeFile(file: string, options: FsOptions = {}): Promise<void> {
  225. return await promisified({
  226. cmd: 'removeFile',
  227. path: file,
  228. options: options
  229. })
  230. }
  231. /**
  232. * Renames a file
  233. *
  234. * @param oldPath
  235. * @param newPath
  236. * @param [options] configuration object
  237. * @param [options.dir] base directory
  238. * @return
  239. */
  240. async function renameFile(oldPath: string, newPath: string, options: FsOptions = {}): Promise<void> {
  241. return await promisified({
  242. cmd: 'renameFile',
  243. oldPath,
  244. newPath,
  245. options
  246. })
  247. }
  248. export {
  249. BaseDirectory as Dir,
  250. readTextFile,
  251. readBinaryFile,
  252. writeFile,
  253. writeBinaryFile,
  254. readDir,
  255. createDir,
  256. removeDir,
  257. copyFile,
  258. removeFile,
  259. renameFile
  260. }