plugin.cjs.js 27 KB

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