123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739 |
- 'use strict';
- Object.defineProperty(exports, '__esModule', { value: true });
- var core = require('@capacitor/core');
- var synapse = require('@capacitor/synapse');
- exports.Directory = void 0;
- (function (Directory) {
- /**
- * The Documents directory.
- * On iOS it's the app's documents directory.
- * Use this directory to store user-generated content.
- * On Android it's the Public Documents folder, so it's accessible from other apps.
- * It's not accessible on Android 10 unless the app enables legacy External Storage
- * by adding `android:requestLegacyExternalStorage="true"` in the `application` tag
- * in the `AndroidManifest.xml`.
- * On Android 11 or newer the app can only access the files/folders the app created.
- *
- * @since 1.0.0
- */
- Directory["Documents"] = "DOCUMENTS";
- /**
- * The Data directory.
- * On iOS it will use the Documents directory.
- * On Android it's the directory holding application files.
- * Files will be deleted when the application is uninstalled.
- *
- * @since 1.0.0
- */
- Directory["Data"] = "DATA";
- /**
- * The Library directory.
- * On iOS it will use the Library directory.
- * On Android it's the directory holding application files.
- * Files will be deleted when the application is uninstalled.
- *
- * @since 1.1.0
- */
- Directory["Library"] = "LIBRARY";
- /**
- * The Cache directory.
- * Can be deleted in cases of low memory, so use this directory to write app-specific files.
- * that your app can re-create easily.
- *
- * @since 1.0.0
- */
- Directory["Cache"] = "CACHE";
- /**
- * The external directory.
- * On iOS it will use the Documents directory.
- * On Android it's the directory on the primary shared/external
- * storage device where the application can place persistent files it owns.
- * These files are internal to the applications, and not typically visible
- * to the user as media.
- * Files will be deleted when the application is uninstalled.
- *
- * @since 1.0.0
- */
- Directory["External"] = "EXTERNAL";
- /**
- * The external storage directory.
- * On iOS it will use the Documents directory.
- * On Android it's the primary shared/external storage directory.
- * It's not accessible on Android 10 unless the app enables legacy External Storage
- * by adding `android:requestLegacyExternalStorage="true"` in the `application` tag
- * in the `AndroidManifest.xml`.
- * It's not accessible on Android 11 or newer.
- *
- * @since 1.0.0
- */
- Directory["ExternalStorage"] = "EXTERNAL_STORAGE";
- /**
- * The external cache directory.
- * On iOS it will use the Documents directory.
- * On Android it's the primary shared/external cache.
- *
- * @since 7.1.0
- */
- Directory["ExternalCache"] = "EXTERNAL_CACHE";
- /**
- * The Library directory without cloud backup. Used in iOS.
- * On Android it's the directory holding application files.
- *
- * @since 7.1.0
- */
- Directory["LibraryNoCloud"] = "LIBRARY_NO_CLOUD";
- /**
- * A temporary directory for iOS.
- * On Android it's the directory holding the application cache.
- *
- * @since 7.1.0
- */
- Directory["Temporary"] = "TEMPORARY";
- })(exports.Directory || (exports.Directory = {}));
- exports.Encoding = void 0;
- (function (Encoding) {
- /**
- * Eight-bit UCS Transformation Format
- *
- * @since 1.0.0
- */
- Encoding["UTF8"] = "utf8";
- /**
- * Seven-bit ASCII, a.k.a. ISO646-US, a.k.a. the Basic Latin block of the
- * Unicode character set
- * This encoding is only supported on Android.
- *
- * @since 1.0.0
- */
- Encoding["ASCII"] = "ascii";
- /**
- * Sixteen-bit UCS Transformation Format, byte order identified by an
- * optional byte-order mark
- * This encoding is only supported on Android.
- *
- * @since 1.0.0
- */
- Encoding["UTF16"] = "utf16";
- })(exports.Encoding || (exports.Encoding = {}));
- /**
- * @deprecated Use `Directory`.
- * @since 1.0.0
- */
- const FilesystemDirectory = exports.Directory;
- /**
- * @deprecated Use `Encoding`.
- * @since 1.0.0
- */
- const FilesystemEncoding = exports.Encoding;
- const Filesystem = core.registerPlugin('Filesystem', {
- web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.FilesystemWeb()),
- });
- synapse.exposeSynapse();
- function resolve(path) {
- const posix = path.split('/').filter((item) => item !== '.');
- const newPosix = [];
- posix.forEach((item) => {
- if (item === '..' && newPosix.length > 0 && newPosix[newPosix.length - 1] !== '..') {
- newPosix.pop();
- }
- else {
- newPosix.push(item);
- }
- });
- return newPosix.join('/');
- }
- function isPathParent(parent, children) {
- parent = resolve(parent);
- children = resolve(children);
- const pathsA = parent.split('/');
- const pathsB = children.split('/');
- return parent !== children && pathsA.every((value, index) => value === pathsB[index]);
- }
- class FilesystemWeb extends core.WebPlugin {
- constructor() {
- super(...arguments);
- this.DB_VERSION = 1;
- this.DB_NAME = 'Disc';
- this._writeCmds = ['add', 'put', 'delete'];
- /**
- * Function that performs a http request to a server and downloads the file to the specified destination
- *
- * @deprecated Use the @capacitor/file-transfer plugin instead.
- * @param options the options for the download operation
- * @returns a promise that resolves with the download file result
- */
- this.downloadFile = async (options) => {
- var _a, _b;
- const requestInit = core.buildRequestInit(options, options.webFetchExtra);
- const response = await fetch(options.url, requestInit);
- let blob;
- if (!options.progress)
- blob = await response.blob();
- else if (!(response === null || response === void 0 ? void 0 : response.body))
- blob = new Blob();
- else {
- const reader = response.body.getReader();
- let bytes = 0;
- const chunks = [];
- const contentType = response.headers.get('content-type');
- const contentLength = parseInt(response.headers.get('content-length') || '0', 10);
- while (true) {
- const { done, value } = await reader.read();
- if (done)
- break;
- chunks.push(value);
- bytes += (value === null || value === void 0 ? void 0 : value.length) || 0;
- const status = {
- url: options.url,
- bytes,
- contentLength,
- };
- this.notifyListeners('progress', status);
- }
- const allChunks = new Uint8Array(bytes);
- let position = 0;
- for (const chunk of chunks) {
- if (typeof chunk === 'undefined')
- continue;
- allChunks.set(chunk, position);
- position += chunk.length;
- }
- blob = new Blob([allChunks.buffer], { type: contentType || undefined });
- }
- const result = await this.writeFile({
- path: options.path,
- directory: (_a = options.directory) !== null && _a !== void 0 ? _a : undefined,
- recursive: (_b = options.recursive) !== null && _b !== void 0 ? _b : false,
- data: blob,
- });
- return { path: result.uri, blob };
- };
- }
- readFileInChunks(_options, _callback) {
- throw this.unavailable('Method not implemented.');
- }
- async initDb() {
- if (this._db !== undefined) {
- return this._db;
- }
- if (!('indexedDB' in window)) {
- throw this.unavailable("This browser doesn't support IndexedDB");
- }
- return new Promise((resolve, reject) => {
- const request = indexedDB.open(this.DB_NAME, this.DB_VERSION);
- request.onupgradeneeded = FilesystemWeb.doUpgrade;
- request.onsuccess = () => {
- this._db = request.result;
- resolve(request.result);
- };
- request.onerror = () => reject(request.error);
- request.onblocked = () => {
- console.warn('db blocked');
- };
- });
- }
- static doUpgrade(event) {
- const eventTarget = event.target;
- const db = eventTarget.result;
- switch (event.oldVersion) {
- case 0:
- case 1:
- default: {
- if (db.objectStoreNames.contains('FileStorage')) {
- db.deleteObjectStore('FileStorage');
- }
- const store = db.createObjectStore('FileStorage', { keyPath: 'path' });
- store.createIndex('by_folder', 'folder');
- }
- }
- }
- async dbRequest(cmd, args) {
- const readFlag = this._writeCmds.indexOf(cmd) !== -1 ? 'readwrite' : 'readonly';
- return this.initDb().then((conn) => {
- return new Promise((resolve, reject) => {
- const tx = conn.transaction(['FileStorage'], readFlag);
- const store = tx.objectStore('FileStorage');
- const req = store[cmd](...args);
- req.onsuccess = () => resolve(req.result);
- req.onerror = () => reject(req.error);
- });
- });
- }
- async dbIndexRequest(indexName, cmd, args) {
- const readFlag = this._writeCmds.indexOf(cmd) !== -1 ? 'readwrite' : 'readonly';
- return this.initDb().then((conn) => {
- return new Promise((resolve, reject) => {
- const tx = conn.transaction(['FileStorage'], readFlag);
- const store = tx.objectStore('FileStorage');
- const index = store.index(indexName);
- const req = index[cmd](...args);
- req.onsuccess = () => resolve(req.result);
- req.onerror = () => reject(req.error);
- });
- });
- }
- getPath(directory, uriPath) {
- const cleanedUriPath = uriPath !== undefined ? uriPath.replace(/^[/]+|[/]+$/g, '') : '';
- let fsPath = '';
- if (directory !== undefined)
- fsPath += '/' + directory;
- if (uriPath !== '')
- fsPath += '/' + cleanedUriPath;
- return fsPath;
- }
- async clear() {
- const conn = await this.initDb();
- const tx = conn.transaction(['FileStorage'], 'readwrite');
- const store = tx.objectStore('FileStorage');
- store.clear();
- }
- /**
- * Read a file from disk
- * @param options options for the file read
- * @return a promise that resolves with the read file data result
- */
- async readFile(options) {
- const path = this.getPath(options.directory, options.path);
- // const encoding = options.encoding;
- const entry = (await this.dbRequest('get', [path]));
- if (entry === undefined)
- throw Error('File does not exist.');
- return { data: entry.content ? entry.content : '' };
- }
- /**
- * Write a file to disk in the specified location on device
- * @param options options for the file write
- * @return a promise that resolves with the file write result
- */
- async writeFile(options) {
- const path = this.getPath(options.directory, options.path);
- let data = options.data;
- const encoding = options.encoding;
- const doRecursive = options.recursive;
- const occupiedEntry = (await this.dbRequest('get', [path]));
- if (occupiedEntry && occupiedEntry.type === 'directory')
- throw Error('The supplied path is a directory.');
- const parentPath = path.substr(0, path.lastIndexOf('/'));
- const parentEntry = (await this.dbRequest('get', [parentPath]));
- if (parentEntry === undefined) {
- const subDirIndex = parentPath.indexOf('/', 1);
- if (subDirIndex !== -1) {
- const parentArgPath = parentPath.substr(subDirIndex);
- await this.mkdir({
- path: parentArgPath,
- directory: options.directory,
- recursive: doRecursive,
- });
- }
- }
- if (!encoding && !(data instanceof Blob)) {
- data = data.indexOf(',') >= 0 ? data.split(',')[1] : data;
- if (!this.isBase64String(data))
- throw Error('The supplied data is not valid base64 content.');
- }
- const now = Date.now();
- const pathObj = {
- path: path,
- folder: parentPath,
- type: 'file',
- size: data instanceof Blob ? data.size : data.length,
- ctime: now,
- mtime: now,
- content: data,
- };
- await this.dbRequest('put', [pathObj]);
- return {
- uri: pathObj.path,
- };
- }
- /**
- * Append to a file on disk in the specified location on device
- * @param options options for the file append
- * @return a promise that resolves with the file write result
- */
- async appendFile(options) {
- const path = this.getPath(options.directory, options.path);
- let data = options.data;
- const encoding = options.encoding;
- const parentPath = path.substr(0, path.lastIndexOf('/'));
- const now = Date.now();
- let ctime = now;
- const occupiedEntry = (await this.dbRequest('get', [path]));
- if (occupiedEntry && occupiedEntry.type === 'directory')
- throw Error('The supplied path is a directory.');
- const parentEntry = (await this.dbRequest('get', [parentPath]));
- if (parentEntry === undefined) {
- const subDirIndex = parentPath.indexOf('/', 1);
- if (subDirIndex !== -1) {
- const parentArgPath = parentPath.substr(subDirIndex);
- await this.mkdir({
- path: parentArgPath,
- directory: options.directory,
- recursive: true,
- });
- }
- }
- if (!encoding && !this.isBase64String(data))
- throw Error('The supplied data is not valid base64 content.');
- if (occupiedEntry !== undefined) {
- if (occupiedEntry.content instanceof Blob) {
- throw Error('The occupied entry contains a Blob object which cannot be appended to.');
- }
- if (occupiedEntry.content !== undefined && !encoding) {
- data = btoa(atob(occupiedEntry.content) + atob(data));
- }
- else {
- data = occupiedEntry.content + data;
- }
- ctime = occupiedEntry.ctime;
- }
- const pathObj = {
- path: path,
- folder: parentPath,
- type: 'file',
- size: data.length,
- ctime: ctime,
- mtime: now,
- content: data,
- };
- await this.dbRequest('put', [pathObj]);
- }
- /**
- * Delete a file from disk
- * @param options options for the file delete
- * @return a promise that resolves with the deleted file data result
- */
- async deleteFile(options) {
- const path = this.getPath(options.directory, options.path);
- const entry = (await this.dbRequest('get', [path]));
- if (entry === undefined)
- throw Error('File does not exist.');
- const entries = await this.dbIndexRequest('by_folder', 'getAllKeys', [IDBKeyRange.only(path)]);
- if (entries.length !== 0)
- throw Error('Folder is not empty.');
- await this.dbRequest('delete', [path]);
- }
- /**
- * Create a directory.
- * @param options options for the mkdir
- * @return a promise that resolves with the mkdir result
- */
- async mkdir(options) {
- const path = this.getPath(options.directory, options.path);
- const doRecursive = options.recursive;
- const parentPath = path.substr(0, path.lastIndexOf('/'));
- const depth = (path.match(/\//g) || []).length;
- const parentEntry = (await this.dbRequest('get', [parentPath]));
- const occupiedEntry = (await this.dbRequest('get', [path]));
- if (depth === 1)
- throw Error('Cannot create Root directory');
- if (occupiedEntry !== undefined)
- throw Error('Current directory does already exist.');
- if (!doRecursive && depth !== 2 && parentEntry === undefined)
- throw Error('Parent directory must exist');
- if (doRecursive && depth !== 2 && parentEntry === undefined) {
- const parentArgPath = parentPath.substr(parentPath.indexOf('/', 1));
- await this.mkdir({
- path: parentArgPath,
- directory: options.directory,
- recursive: doRecursive,
- });
- }
- const now = Date.now();
- const pathObj = {
- path: path,
- folder: parentPath,
- type: 'directory',
- size: 0,
- ctime: now,
- mtime: now,
- };
- await this.dbRequest('put', [pathObj]);
- }
- /**
- * Remove a directory
- * @param options the options for the directory remove
- */
- async rmdir(options) {
- const { path, directory, recursive } = options;
- const fullPath = this.getPath(directory, path);
- const entry = (await this.dbRequest('get', [fullPath]));
- if (entry === undefined)
- throw Error('Folder does not exist.');
- if (entry.type !== 'directory')
- throw Error('Requested path is not a directory');
- const readDirResult = await this.readdir({ path, directory });
- if (readDirResult.files.length !== 0 && !recursive)
- throw Error('Folder is not empty');
- for (const entry of readDirResult.files) {
- const entryPath = `${path}/${entry.name}`;
- const entryObj = await this.stat({ path: entryPath, directory });
- if (entryObj.type === 'file') {
- await this.deleteFile({ path: entryPath, directory });
- }
- else {
- await this.rmdir({ path: entryPath, directory, recursive });
- }
- }
- await this.dbRequest('delete', [fullPath]);
- }
- /**
- * Return a list of files from the directory (not recursive)
- * @param options the options for the readdir operation
- * @return a promise that resolves with the readdir directory listing result
- */
- async readdir(options) {
- const path = this.getPath(options.directory, options.path);
- const entry = (await this.dbRequest('get', [path]));
- if (options.path !== '' && entry === undefined)
- throw Error('Folder does not exist.');
- const entries = await this.dbIndexRequest('by_folder', 'getAllKeys', [IDBKeyRange.only(path)]);
- const files = await Promise.all(entries.map(async (e) => {
- let subEntry = (await this.dbRequest('get', [e]));
- if (subEntry === undefined) {
- subEntry = (await this.dbRequest('get', [e + '/']));
- }
- return {
- name: e.substring(path.length + 1),
- type: subEntry.type,
- size: subEntry.size,
- ctime: subEntry.ctime,
- mtime: subEntry.mtime,
- uri: subEntry.path,
- };
- }));
- return { files: files };
- }
- /**
- * Return full File URI for a path and directory
- * @param options the options for the stat operation
- * @return a promise that resolves with the file stat result
- */
- async getUri(options) {
- const path = this.getPath(options.directory, options.path);
- let entry = (await this.dbRequest('get', [path]));
- if (entry === undefined) {
- entry = (await this.dbRequest('get', [path + '/']));
- }
- return {
- uri: (entry === null || entry === void 0 ? void 0 : entry.path) || path,
- };
- }
- /**
- * Return data about a file
- * @param options the options for the stat operation
- * @return a promise that resolves with the file stat result
- */
- async stat(options) {
- const path = this.getPath(options.directory, options.path);
- let entry = (await this.dbRequest('get', [path]));
- if (entry === undefined) {
- entry = (await this.dbRequest('get', [path + '/']));
- }
- if (entry === undefined)
- throw Error('Entry does not exist.');
- return {
- name: entry.path.substring(path.length + 1),
- type: entry.type,
- size: entry.size,
- ctime: entry.ctime,
- mtime: entry.mtime,
- uri: entry.path,
- };
- }
- /**
- * Rename a file or directory
- * @param options the options for the rename operation
- * @return a promise that resolves with the rename result
- */
- async rename(options) {
- await this._copy(options, true);
- return;
- }
- /**
- * Copy a file or directory
- * @param options the options for the copy operation
- * @return a promise that resolves with the copy result
- */
- async copy(options) {
- return this._copy(options, false);
- }
- async requestPermissions() {
- return { publicStorage: 'granted' };
- }
- async checkPermissions() {
- return { publicStorage: 'granted' };
- }
- /**
- * Function that can perform a copy or a rename
- * @param options the options for the rename operation
- * @param doRename whether to perform a rename or copy operation
- * @return a promise that resolves with the result
- */
- async _copy(options, doRename = false) {
- let { toDirectory } = options;
- const { to, from, directory: fromDirectory } = options;
- if (!to || !from) {
- throw Error('Both to and from must be provided');
- }
- // If no "to" directory is provided, use the "from" directory
- if (!toDirectory) {
- toDirectory = fromDirectory;
- }
- const fromPath = this.getPath(fromDirectory, from);
- const toPath = this.getPath(toDirectory, to);
- // Test that the "to" and "from" locations are different
- if (fromPath === toPath) {
- return {
- uri: toPath,
- };
- }
- if (isPathParent(fromPath, toPath)) {
- throw Error('To path cannot contain the from path');
- }
- // Check the state of the "to" location
- let toObj;
- try {
- toObj = await this.stat({
- path: to,
- directory: toDirectory,
- });
- }
- catch (e) {
- // To location does not exist, ensure the directory containing "to" location exists and is a directory
- const toPathComponents = to.split('/');
- toPathComponents.pop();
- const toPath = toPathComponents.join('/');
- // Check the containing directory of the "to" location exists
- if (toPathComponents.length > 0) {
- const toParentDirectory = await this.stat({
- path: toPath,
- directory: toDirectory,
- });
- if (toParentDirectory.type !== 'directory') {
- throw new Error('Parent directory of the to path is a file');
- }
- }
- }
- // Cannot overwrite a directory
- if (toObj && toObj.type === 'directory') {
- throw new Error('Cannot overwrite a directory with a file');
- }
- // Ensure the "from" object exists
- const fromObj = await this.stat({
- path: from,
- directory: fromDirectory,
- });
- // Set the mtime/ctime of the supplied path
- const updateTime = async (path, ctime, mtime) => {
- const fullPath = this.getPath(toDirectory, path);
- const entry = (await this.dbRequest('get', [fullPath]));
- entry.ctime = ctime;
- entry.mtime = mtime;
- await this.dbRequest('put', [entry]);
- };
- const ctime = fromObj.ctime ? fromObj.ctime : Date.now();
- switch (fromObj.type) {
- // The "from" object is a file
- case 'file': {
- // Read the file
- const file = await this.readFile({
- path: from,
- directory: fromDirectory,
- });
- // Optionally remove the file
- if (doRename) {
- await this.deleteFile({
- path: from,
- directory: fromDirectory,
- });
- }
- let encoding;
- if (!(file.data instanceof Blob) && !this.isBase64String(file.data)) {
- encoding = exports.Encoding.UTF8;
- }
- // Write the file to the new location
- const writeResult = await this.writeFile({
- path: to,
- directory: toDirectory,
- data: file.data,
- encoding: encoding,
- });
- // Copy the mtime/ctime of a renamed file
- if (doRename) {
- await updateTime(to, ctime, fromObj.mtime);
- }
- // Resolve promise
- return writeResult;
- }
- case 'directory': {
- if (toObj) {
- throw Error('Cannot move a directory over an existing object');
- }
- try {
- // Create the to directory
- await this.mkdir({
- path: to,
- directory: toDirectory,
- recursive: false,
- });
- // Copy the mtime/ctime of a renamed directory
- if (doRename) {
- await updateTime(to, ctime, fromObj.mtime);
- }
- }
- catch (e) {
- // ignore
- }
- // Iterate over the contents of the from location
- const contents = (await this.readdir({
- path: from,
- directory: fromDirectory,
- })).files;
- for (const filename of contents) {
- // Move item from the from directory to the to directory
- await this._copy({
- from: `${from}/${filename.name}`,
- to: `${to}/${filename.name}`,
- directory: fromDirectory,
- toDirectory,
- }, doRename);
- }
- // Optionally remove the original from directory
- if (doRename) {
- await this.rmdir({
- path: from,
- directory: fromDirectory,
- });
- }
- }
- }
- return {
- uri: toPath,
- };
- }
- isBase64String(str) {
- try {
- return btoa(atob(str)) == str;
- }
- catch (err) {
- return false;
- }
- }
- }
- FilesystemWeb._debug = true;
- var web = /*#__PURE__*/Object.freeze({
- __proto__: null,
- FilesystemWeb: FilesystemWeb
- });
- exports.Filesystem = Filesystem;
- exports.FilesystemDirectory = FilesystemDirectory;
- exports.FilesystemEncoding = FilesystemEncoding;
- //# sourceMappingURL=plugin.cjs.js.map
|