plugin.js 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741
  1. var capacitorFilesystemPluginCapacitor = (function (exports, core, synapse) {
  2. 'use strict';
  3. exports.Directory = void 0;
  4. (function (Directory) {
  5. /**
  6. * The Documents directory.
  7. * On iOS it's the app's documents directory.
  8. * Use this directory to store user-generated content.
  9. * On Android it's the Public Documents folder, so it's accessible from other apps.
  10. * It's not accessible on Android 10 unless the app enables legacy External Storage
  11. * by adding `android:requestLegacyExternalStorage="true"` in the `application` tag
  12. * in the `AndroidManifest.xml`.
  13. * On Android 11 or newer the app can only access the files/folders the app created.
  14. *
  15. * @since 1.0.0
  16. */
  17. Directory["Documents"] = "DOCUMENTS";
  18. /**
  19. * The Data directory.
  20. * On iOS it will use the Documents directory.
  21. * On Android it's the directory holding application files.
  22. * Files will be deleted when the application is uninstalled.
  23. *
  24. * @since 1.0.0
  25. */
  26. Directory["Data"] = "DATA";
  27. /**
  28. * The Library directory.
  29. * On iOS it will use the Library directory.
  30. * On Android it's the directory holding application files.
  31. * Files will be deleted when the application is uninstalled.
  32. *
  33. * @since 1.1.0
  34. */
  35. Directory["Library"] = "LIBRARY";
  36. /**
  37. * The Cache directory.
  38. * Can be deleted in cases of low memory, so use this directory to write app-specific files.
  39. * that your app can re-create easily.
  40. *
  41. * @since 1.0.0
  42. */
  43. Directory["Cache"] = "CACHE";
  44. /**
  45. * The external directory.
  46. * On iOS it will use the Documents directory.
  47. * On Android it's the directory on the primary shared/external
  48. * storage device where the application can place persistent files it owns.
  49. * These files are internal to the applications, and not typically visible
  50. * to the user as media.
  51. * Files will be deleted when the application is uninstalled.
  52. *
  53. * @since 1.0.0
  54. */
  55. Directory["External"] = "EXTERNAL";
  56. /**
  57. * The external storage directory.
  58. * On iOS it will use the Documents directory.
  59. * On Android it's the primary shared/external storage directory.
  60. * It's not accessible on Android 10 unless the app enables legacy External Storage
  61. * by adding `android:requestLegacyExternalStorage="true"` in the `application` tag
  62. * in the `AndroidManifest.xml`.
  63. * It's not accessible on Android 11 or newer.
  64. *
  65. * @since 1.0.0
  66. */
  67. Directory["ExternalStorage"] = "EXTERNAL_STORAGE";
  68. /**
  69. * The external cache directory.
  70. * On iOS it will use the Documents directory.
  71. * On Android it's the primary shared/external cache.
  72. *
  73. * @since 7.1.0
  74. */
  75. Directory["ExternalCache"] = "EXTERNAL_CACHE";
  76. /**
  77. * The Library directory without cloud backup. Used in iOS.
  78. * On Android it's the directory holding application files.
  79. *
  80. * @since 7.1.0
  81. */
  82. Directory["LibraryNoCloud"] = "LIBRARY_NO_CLOUD";
  83. /**
  84. * A temporary directory for iOS.
  85. * On Android it's the directory holding the application cache.
  86. *
  87. * @since 7.1.0
  88. */
  89. Directory["Temporary"] = "TEMPORARY";
  90. })(exports.Directory || (exports.Directory = {}));
  91. exports.Encoding = void 0;
  92. (function (Encoding) {
  93. /**
  94. * Eight-bit UCS Transformation Format
  95. *
  96. * @since 1.0.0
  97. */
  98. Encoding["UTF8"] = "utf8";
  99. /**
  100. * Seven-bit ASCII, a.k.a. ISO646-US, a.k.a. the Basic Latin block of the
  101. * Unicode character set
  102. * This encoding is only supported on Android.
  103. *
  104. * @since 1.0.0
  105. */
  106. Encoding["ASCII"] = "ascii";
  107. /**
  108. * Sixteen-bit UCS Transformation Format, byte order identified by an
  109. * optional byte-order mark
  110. * This encoding is only supported on Android.
  111. *
  112. * @since 1.0.0
  113. */
  114. Encoding["UTF16"] = "utf16";
  115. })(exports.Encoding || (exports.Encoding = {}));
  116. /**
  117. * @deprecated Use `Directory`.
  118. * @since 1.0.0
  119. */
  120. const FilesystemDirectory = exports.Directory;
  121. /**
  122. * @deprecated Use `Encoding`.
  123. * @since 1.0.0
  124. */
  125. const FilesystemEncoding = exports.Encoding;
  126. const Filesystem = core.registerPlugin('Filesystem', {
  127. web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.FilesystemWeb()),
  128. });
  129. synapse.exposeSynapse();
  130. function resolve(path) {
  131. const posix = path.split('/').filter((item) => item !== '.');
  132. const newPosix = [];
  133. posix.forEach((item) => {
  134. if (item === '..' && newPosix.length > 0 && newPosix[newPosix.length - 1] !== '..') {
  135. newPosix.pop();
  136. }
  137. else {
  138. newPosix.push(item);
  139. }
  140. });
  141. return newPosix.join('/');
  142. }
  143. function isPathParent(parent, children) {
  144. parent = resolve(parent);
  145. children = resolve(children);
  146. const pathsA = parent.split('/');
  147. const pathsB = children.split('/');
  148. return parent !== children && pathsA.every((value, index) => value === pathsB[index]);
  149. }
  150. class FilesystemWeb extends core.WebPlugin {
  151. constructor() {
  152. super(...arguments);
  153. this.DB_VERSION = 1;
  154. this.DB_NAME = 'Disc';
  155. this._writeCmds = ['add', 'put', 'delete'];
  156. /**
  157. * Function that performs a http request to a server and downloads the file to the specified destination
  158. *
  159. * @deprecated Use the @capacitor/file-transfer plugin instead.
  160. * @param options the options for the download operation
  161. * @returns a promise that resolves with the download file result
  162. */
  163. this.downloadFile = async (options) => {
  164. var _a, _b;
  165. const requestInit = core.buildRequestInit(options, options.webFetchExtra);
  166. const response = await fetch(options.url, requestInit);
  167. let blob;
  168. if (!options.progress)
  169. blob = await response.blob();
  170. else if (!(response === null || response === void 0 ? void 0 : response.body))
  171. blob = new Blob();
  172. else {
  173. const reader = response.body.getReader();
  174. let bytes = 0;
  175. const chunks = [];
  176. const contentType = response.headers.get('content-type');
  177. const contentLength = parseInt(response.headers.get('content-length') || '0', 10);
  178. while (true) {
  179. const { done, value } = await reader.read();
  180. if (done)
  181. break;
  182. chunks.push(value);
  183. bytes += (value === null || value === void 0 ? void 0 : value.length) || 0;
  184. const status = {
  185. url: options.url,
  186. bytes,
  187. contentLength,
  188. };
  189. this.notifyListeners('progress', status);
  190. }
  191. const allChunks = new Uint8Array(bytes);
  192. let position = 0;
  193. for (const chunk of chunks) {
  194. if (typeof chunk === 'undefined')
  195. continue;
  196. allChunks.set(chunk, position);
  197. position += chunk.length;
  198. }
  199. blob = new Blob([allChunks.buffer], { type: contentType || undefined });
  200. }
  201. const result = await this.writeFile({
  202. path: options.path,
  203. directory: (_a = options.directory) !== null && _a !== void 0 ? _a : undefined,
  204. recursive: (_b = options.recursive) !== null && _b !== void 0 ? _b : false,
  205. data: blob,
  206. });
  207. return { path: result.uri, blob };
  208. };
  209. }
  210. readFileInChunks(_options, _callback) {
  211. throw this.unavailable('Method not implemented.');
  212. }
  213. async initDb() {
  214. if (this._db !== undefined) {
  215. return this._db;
  216. }
  217. if (!('indexedDB' in window)) {
  218. throw this.unavailable("This browser doesn't support IndexedDB");
  219. }
  220. return new Promise((resolve, reject) => {
  221. const request = indexedDB.open(this.DB_NAME, this.DB_VERSION);
  222. request.onupgradeneeded = FilesystemWeb.doUpgrade;
  223. request.onsuccess = () => {
  224. this._db = request.result;
  225. resolve(request.result);
  226. };
  227. request.onerror = () => reject(request.error);
  228. request.onblocked = () => {
  229. console.warn('db blocked');
  230. };
  231. });
  232. }
  233. static doUpgrade(event) {
  234. const eventTarget = event.target;
  235. const db = eventTarget.result;
  236. switch (event.oldVersion) {
  237. case 0:
  238. case 1:
  239. default: {
  240. if (db.objectStoreNames.contains('FileStorage')) {
  241. db.deleteObjectStore('FileStorage');
  242. }
  243. const store = db.createObjectStore('FileStorage', { keyPath: 'path' });
  244. store.createIndex('by_folder', 'folder');
  245. }
  246. }
  247. }
  248. async dbRequest(cmd, args) {
  249. const readFlag = this._writeCmds.indexOf(cmd) !== -1 ? 'readwrite' : 'readonly';
  250. return this.initDb().then((conn) => {
  251. return new Promise((resolve, reject) => {
  252. const tx = conn.transaction(['FileStorage'], readFlag);
  253. const store = tx.objectStore('FileStorage');
  254. const req = store[cmd](...args);
  255. req.onsuccess = () => resolve(req.result);
  256. req.onerror = () => reject(req.error);
  257. });
  258. });
  259. }
  260. async dbIndexRequest(indexName, cmd, args) {
  261. const readFlag = this._writeCmds.indexOf(cmd) !== -1 ? 'readwrite' : 'readonly';
  262. return this.initDb().then((conn) => {
  263. return new Promise((resolve, reject) => {
  264. const tx = conn.transaction(['FileStorage'], readFlag);
  265. const store = tx.objectStore('FileStorage');
  266. const index = store.index(indexName);
  267. const req = index[cmd](...args);
  268. req.onsuccess = () => resolve(req.result);
  269. req.onerror = () => reject(req.error);
  270. });
  271. });
  272. }
  273. getPath(directory, uriPath) {
  274. const cleanedUriPath = uriPath !== undefined ? uriPath.replace(/^[/]+|[/]+$/g, '') : '';
  275. let fsPath = '';
  276. if (directory !== undefined)
  277. fsPath += '/' + directory;
  278. if (uriPath !== '')
  279. fsPath += '/' + cleanedUriPath;
  280. return fsPath;
  281. }
  282. async clear() {
  283. const conn = await this.initDb();
  284. const tx = conn.transaction(['FileStorage'], 'readwrite');
  285. const store = tx.objectStore('FileStorage');
  286. store.clear();
  287. }
  288. /**
  289. * Read a file from disk
  290. * @param options options for the file read
  291. * @return a promise that resolves with the read file data result
  292. */
  293. async readFile(options) {
  294. const path = this.getPath(options.directory, options.path);
  295. // const encoding = options.encoding;
  296. const entry = (await this.dbRequest('get', [path]));
  297. if (entry === undefined)
  298. throw Error('File does not exist.');
  299. return { data: entry.content ? entry.content : '' };
  300. }
  301. /**
  302. * Write a file to disk in the specified location on device
  303. * @param options options for the file write
  304. * @return a promise that resolves with the file write result
  305. */
  306. async writeFile(options) {
  307. const path = this.getPath(options.directory, options.path);
  308. let data = options.data;
  309. const encoding = options.encoding;
  310. const doRecursive = options.recursive;
  311. const occupiedEntry = (await this.dbRequest('get', [path]));
  312. if (occupiedEntry && occupiedEntry.type === 'directory')
  313. throw Error('The supplied path is a directory.');
  314. const parentPath = path.substr(0, path.lastIndexOf('/'));
  315. const parentEntry = (await this.dbRequest('get', [parentPath]));
  316. if (parentEntry === undefined) {
  317. const subDirIndex = parentPath.indexOf('/', 1);
  318. if (subDirIndex !== -1) {
  319. const parentArgPath = parentPath.substr(subDirIndex);
  320. await this.mkdir({
  321. path: parentArgPath,
  322. directory: options.directory,
  323. recursive: doRecursive,
  324. });
  325. }
  326. }
  327. if (!encoding && !(data instanceof Blob)) {
  328. data = data.indexOf(',') >= 0 ? data.split(',')[1] : data;
  329. if (!this.isBase64String(data))
  330. throw Error('The supplied data is not valid base64 content.');
  331. }
  332. const now = Date.now();
  333. const pathObj = {
  334. path: path,
  335. folder: parentPath,
  336. type: 'file',
  337. size: data instanceof Blob ? data.size : data.length,
  338. ctime: now,
  339. mtime: now,
  340. content: data,
  341. };
  342. await this.dbRequest('put', [pathObj]);
  343. return {
  344. uri: pathObj.path,
  345. };
  346. }
  347. /**
  348. * Append to a file on disk in the specified location on device
  349. * @param options options for the file append
  350. * @return a promise that resolves with the file write result
  351. */
  352. async appendFile(options) {
  353. const path = this.getPath(options.directory, options.path);
  354. let data = options.data;
  355. const encoding = options.encoding;
  356. const parentPath = path.substr(0, path.lastIndexOf('/'));
  357. const now = Date.now();
  358. let ctime = now;
  359. const occupiedEntry = (await this.dbRequest('get', [path]));
  360. if (occupiedEntry && occupiedEntry.type === 'directory')
  361. throw Error('The supplied path is a directory.');
  362. const parentEntry = (await this.dbRequest('get', [parentPath]));
  363. if (parentEntry === undefined) {
  364. const subDirIndex = parentPath.indexOf('/', 1);
  365. if (subDirIndex !== -1) {
  366. const parentArgPath = parentPath.substr(subDirIndex);
  367. await this.mkdir({
  368. path: parentArgPath,
  369. directory: options.directory,
  370. recursive: true,
  371. });
  372. }
  373. }
  374. if (!encoding && !this.isBase64String(data))
  375. throw Error('The supplied data is not valid base64 content.');
  376. if (occupiedEntry !== undefined) {
  377. if (occupiedEntry.content instanceof Blob) {
  378. throw Error('The occupied entry contains a Blob object which cannot be appended to.');
  379. }
  380. if (occupiedEntry.content !== undefined && !encoding) {
  381. data = btoa(atob(occupiedEntry.content) + atob(data));
  382. }
  383. else {
  384. data = occupiedEntry.content + data;
  385. }
  386. ctime = occupiedEntry.ctime;
  387. }
  388. const pathObj = {
  389. path: path,
  390. folder: parentPath,
  391. type: 'file',
  392. size: data.length,
  393. ctime: ctime,
  394. mtime: now,
  395. content: data,
  396. };
  397. await this.dbRequest('put', [pathObj]);
  398. }
  399. /**
  400. * Delete a file from disk
  401. * @param options options for the file delete
  402. * @return a promise that resolves with the deleted file data result
  403. */
  404. async deleteFile(options) {
  405. const path = this.getPath(options.directory, options.path);
  406. const entry = (await this.dbRequest('get', [path]));
  407. if (entry === undefined)
  408. throw Error('File does not exist.');
  409. const entries = await this.dbIndexRequest('by_folder', 'getAllKeys', [IDBKeyRange.only(path)]);
  410. if (entries.length !== 0)
  411. throw Error('Folder is not empty.');
  412. await this.dbRequest('delete', [path]);
  413. }
  414. /**
  415. * Create a directory.
  416. * @param options options for the mkdir
  417. * @return a promise that resolves with the mkdir result
  418. */
  419. async mkdir(options) {
  420. const path = this.getPath(options.directory, options.path);
  421. const doRecursive = options.recursive;
  422. const parentPath = path.substr(0, path.lastIndexOf('/'));
  423. const depth = (path.match(/\//g) || []).length;
  424. const parentEntry = (await this.dbRequest('get', [parentPath]));
  425. const occupiedEntry = (await this.dbRequest('get', [path]));
  426. if (depth === 1)
  427. throw Error('Cannot create Root directory');
  428. if (occupiedEntry !== undefined)
  429. throw Error('Current directory does already exist.');
  430. if (!doRecursive && depth !== 2 && parentEntry === undefined)
  431. throw Error('Parent directory must exist');
  432. if (doRecursive && depth !== 2 && parentEntry === undefined) {
  433. const parentArgPath = parentPath.substr(parentPath.indexOf('/', 1));
  434. await this.mkdir({
  435. path: parentArgPath,
  436. directory: options.directory,
  437. recursive: doRecursive,
  438. });
  439. }
  440. const now = Date.now();
  441. const pathObj = {
  442. path: path,
  443. folder: parentPath,
  444. type: 'directory',
  445. size: 0,
  446. ctime: now,
  447. mtime: now,
  448. };
  449. await this.dbRequest('put', [pathObj]);
  450. }
  451. /**
  452. * Remove a directory
  453. * @param options the options for the directory remove
  454. */
  455. async rmdir(options) {
  456. const { path, directory, recursive } = options;
  457. const fullPath = this.getPath(directory, path);
  458. const entry = (await this.dbRequest('get', [fullPath]));
  459. if (entry === undefined)
  460. throw Error('Folder does not exist.');
  461. if (entry.type !== 'directory')
  462. throw Error('Requested path is not a directory');
  463. const readDirResult = await this.readdir({ path, directory });
  464. if (readDirResult.files.length !== 0 && !recursive)
  465. throw Error('Folder is not empty');
  466. for (const entry of readDirResult.files) {
  467. const entryPath = `${path}/${entry.name}`;
  468. const entryObj = await this.stat({ path: entryPath, directory });
  469. if (entryObj.type === 'file') {
  470. await this.deleteFile({ path: entryPath, directory });
  471. }
  472. else {
  473. await this.rmdir({ path: entryPath, directory, recursive });
  474. }
  475. }
  476. await this.dbRequest('delete', [fullPath]);
  477. }
  478. /**
  479. * Return a list of files from the directory (not recursive)
  480. * @param options the options for the readdir operation
  481. * @return a promise that resolves with the readdir directory listing result
  482. */
  483. async readdir(options) {
  484. const path = this.getPath(options.directory, options.path);
  485. const entry = (await this.dbRequest('get', [path]));
  486. if (options.path !== '' && entry === undefined)
  487. throw Error('Folder does not exist.');
  488. const entries = await this.dbIndexRequest('by_folder', 'getAllKeys', [IDBKeyRange.only(path)]);
  489. const files = await Promise.all(entries.map(async (e) => {
  490. let subEntry = (await this.dbRequest('get', [e]));
  491. if (subEntry === undefined) {
  492. subEntry = (await this.dbRequest('get', [e + '/']));
  493. }
  494. return {
  495. name: e.substring(path.length + 1),
  496. type: subEntry.type,
  497. size: subEntry.size,
  498. ctime: subEntry.ctime,
  499. mtime: subEntry.mtime,
  500. uri: subEntry.path,
  501. };
  502. }));
  503. return { files: files };
  504. }
  505. /**
  506. * Return full File URI for a path and directory
  507. * @param options the options for the stat operation
  508. * @return a promise that resolves with the file stat result
  509. */
  510. async getUri(options) {
  511. const path = this.getPath(options.directory, options.path);
  512. let entry = (await this.dbRequest('get', [path]));
  513. if (entry === undefined) {
  514. entry = (await this.dbRequest('get', [path + '/']));
  515. }
  516. return {
  517. uri: (entry === null || entry === void 0 ? void 0 : entry.path) || path,
  518. };
  519. }
  520. /**
  521. * Return data about a file
  522. * @param options the options for the stat operation
  523. * @return a promise that resolves with the file stat result
  524. */
  525. async stat(options) {
  526. const path = this.getPath(options.directory, options.path);
  527. let entry = (await this.dbRequest('get', [path]));
  528. if (entry === undefined) {
  529. entry = (await this.dbRequest('get', [path + '/']));
  530. }
  531. if (entry === undefined)
  532. throw Error('Entry does not exist.');
  533. return {
  534. name: entry.path.substring(path.length + 1),
  535. type: entry.type,
  536. size: entry.size,
  537. ctime: entry.ctime,
  538. mtime: entry.mtime,
  539. uri: entry.path,
  540. };
  541. }
  542. /**
  543. * Rename a file or directory
  544. * @param options the options for the rename operation
  545. * @return a promise that resolves with the rename result
  546. */
  547. async rename(options) {
  548. await this._copy(options, true);
  549. return;
  550. }
  551. /**
  552. * Copy a file or directory
  553. * @param options the options for the copy operation
  554. * @return a promise that resolves with the copy result
  555. */
  556. async copy(options) {
  557. return this._copy(options, false);
  558. }
  559. async requestPermissions() {
  560. return { publicStorage: 'granted' };
  561. }
  562. async checkPermissions() {
  563. return { publicStorage: 'granted' };
  564. }
  565. /**
  566. * Function that can perform a copy or a rename
  567. * @param options the options for the rename operation
  568. * @param doRename whether to perform a rename or copy operation
  569. * @return a promise that resolves with the result
  570. */
  571. async _copy(options, doRename = false) {
  572. let { toDirectory } = options;
  573. const { to, from, directory: fromDirectory } = options;
  574. if (!to || !from) {
  575. throw Error('Both to and from must be provided');
  576. }
  577. // If no "to" directory is provided, use the "from" directory
  578. if (!toDirectory) {
  579. toDirectory = fromDirectory;
  580. }
  581. const fromPath = this.getPath(fromDirectory, from);
  582. const toPath = this.getPath(toDirectory, to);
  583. // Test that the "to" and "from" locations are different
  584. if (fromPath === toPath) {
  585. return {
  586. uri: toPath,
  587. };
  588. }
  589. if (isPathParent(fromPath, toPath)) {
  590. throw Error('To path cannot contain the from path');
  591. }
  592. // Check the state of the "to" location
  593. let toObj;
  594. try {
  595. toObj = await this.stat({
  596. path: to,
  597. directory: toDirectory,
  598. });
  599. }
  600. catch (e) {
  601. // To location does not exist, ensure the directory containing "to" location exists and is a directory
  602. const toPathComponents = to.split('/');
  603. toPathComponents.pop();
  604. const toPath = toPathComponents.join('/');
  605. // Check the containing directory of the "to" location exists
  606. if (toPathComponents.length > 0) {
  607. const toParentDirectory = await this.stat({
  608. path: toPath,
  609. directory: toDirectory,
  610. });
  611. if (toParentDirectory.type !== 'directory') {
  612. throw new Error('Parent directory of the to path is a file');
  613. }
  614. }
  615. }
  616. // Cannot overwrite a directory
  617. if (toObj && toObj.type === 'directory') {
  618. throw new Error('Cannot overwrite a directory with a file');
  619. }
  620. // Ensure the "from" object exists
  621. const fromObj = await this.stat({
  622. path: from,
  623. directory: fromDirectory,
  624. });
  625. // Set the mtime/ctime of the supplied path
  626. const updateTime = async (path, ctime, mtime) => {
  627. const fullPath = this.getPath(toDirectory, path);
  628. const entry = (await this.dbRequest('get', [fullPath]));
  629. entry.ctime = ctime;
  630. entry.mtime = mtime;
  631. await this.dbRequest('put', [entry]);
  632. };
  633. const ctime = fromObj.ctime ? fromObj.ctime : Date.now();
  634. switch (fromObj.type) {
  635. // The "from" object is a file
  636. case 'file': {
  637. // Read the file
  638. const file = await this.readFile({
  639. path: from,
  640. directory: fromDirectory,
  641. });
  642. // Optionally remove the file
  643. if (doRename) {
  644. await this.deleteFile({
  645. path: from,
  646. directory: fromDirectory,
  647. });
  648. }
  649. let encoding;
  650. if (!(file.data instanceof Blob) && !this.isBase64String(file.data)) {
  651. encoding = exports.Encoding.UTF8;
  652. }
  653. // Write the file to the new location
  654. const writeResult = await this.writeFile({
  655. path: to,
  656. directory: toDirectory,
  657. data: file.data,
  658. encoding: encoding,
  659. });
  660. // Copy the mtime/ctime of a renamed file
  661. if (doRename) {
  662. await updateTime(to, ctime, fromObj.mtime);
  663. }
  664. // Resolve promise
  665. return writeResult;
  666. }
  667. case 'directory': {
  668. if (toObj) {
  669. throw Error('Cannot move a directory over an existing object');
  670. }
  671. try {
  672. // Create the to directory
  673. await this.mkdir({
  674. path: to,
  675. directory: toDirectory,
  676. recursive: false,
  677. });
  678. // Copy the mtime/ctime of a renamed directory
  679. if (doRename) {
  680. await updateTime(to, ctime, fromObj.mtime);
  681. }
  682. }
  683. catch (e) {
  684. // ignore
  685. }
  686. // Iterate over the contents of the from location
  687. const contents = (await this.readdir({
  688. path: from,
  689. directory: fromDirectory,
  690. })).files;
  691. for (const filename of contents) {
  692. // Move item from the from directory to the to directory
  693. await this._copy({
  694. from: `${from}/${filename.name}`,
  695. to: `${to}/${filename.name}`,
  696. directory: fromDirectory,
  697. toDirectory,
  698. }, doRename);
  699. }
  700. // Optionally remove the original from directory
  701. if (doRename) {
  702. await this.rmdir({
  703. path: from,
  704. directory: fromDirectory,
  705. });
  706. }
  707. }
  708. }
  709. return {
  710. uri: toPath,
  711. };
  712. }
  713. isBase64String(str) {
  714. try {
  715. return btoa(atob(str)) == str;
  716. }
  717. catch (err) {
  718. return false;
  719. }
  720. }
  721. }
  722. FilesystemWeb._debug = true;
  723. var web = /*#__PURE__*/Object.freeze({
  724. __proto__: null,
  725. FilesystemWeb: FilesystemWeb
  726. });
  727. exports.Filesystem = Filesystem;
  728. exports.FilesystemDirectory = FilesystemDirectory;
  729. exports.FilesystemEncoding = FilesystemEncoding;
  730. Object.defineProperty(exports, '__esModule', { value: true });
  731. return exports;
  732. })({}, capacitorExports, synapse);
  733. //# sourceMappingURL=plugin.js.map