@capacitor/filesystem 7.0.2-nightly-20250526T150552.0 → 7.1.0-dev.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/CapacitorFilesystem.podspec +4 -3
  2. package/LICENSE +17 -19
  3. package/Package.swift +10 -4
  4. package/README.md +149 -78
  5. package/android/build.gradle +12 -22
  6. package/android/src/main/kotlin/com/capacitorjs/plugins/filesystem/FilesystemErrors.kt +101 -0
  7. package/android/src/main/kotlin/com/capacitorjs/plugins/filesystem/FilesystemMethodOptions.kt +129 -0
  8. package/android/src/main/kotlin/com/capacitorjs/plugins/filesystem/FilesystemMethodResults.kt +65 -0
  9. package/android/src/main/kotlin/com/capacitorjs/plugins/filesystem/FilesystemPlugin.kt +412 -0
  10. package/android/src/main/kotlin/com/capacitorjs/plugins/filesystem/LegacyFilesystemImplementation.kt +169 -0
  11. package/android/src/main/kotlin/com/capacitorjs/plugins/filesystem/PluginResultExtensions.kt +25 -0
  12. package/dist/docs.json +227 -145
  13. package/dist/esm/definitions.d.ts +102 -64
  14. package/dist/esm/definitions.js +25 -3
  15. package/dist/esm/definitions.js.map +1 -1
  16. package/dist/esm/index.js +3 -1
  17. package/dist/esm/index.js.map +1 -1
  18. package/dist/esm/web.d.ts +3 -1
  19. package/dist/esm/web.js +10 -10
  20. package/dist/esm/web.js.map +1 -1
  21. package/dist/plugin.cjs.js +40 -14
  22. package/dist/plugin.cjs.js.map +1 -1
  23. package/dist/plugin.js +41 -16
  24. package/dist/plugin.js.map +1 -1
  25. package/ios/Sources/FilesystemPlugin/CAPPluginCall+Accelerators.swift +73 -0
  26. package/ios/Sources/FilesystemPlugin/FilesystemConstants.swift +61 -0
  27. package/ios/Sources/FilesystemPlugin/FilesystemError.swift +57 -0
  28. package/ios/Sources/FilesystemPlugin/FilesystemLocationResolver.swift +39 -0
  29. package/ios/Sources/FilesystemPlugin/FilesystemOperation.swift +24 -0
  30. package/ios/Sources/FilesystemPlugin/FilesystemOperationExecutor.swift +116 -0
  31. package/ios/Sources/FilesystemPlugin/FilesystemPlugin.swift +103 -264
  32. package/ios/Sources/FilesystemPlugin/IONFileStructures+Converters.swift +60 -0
  33. package/ios/Sources/FilesystemPlugin/{Filesystem.swift → LegacyFilesystemImplementation.swift} +18 -179
  34. package/package.json +28 -24
  35. package/android/src/main/java/com/capacitorjs/plugins/filesystem/Filesystem.java +0 -414
  36. package/android/src/main/java/com/capacitorjs/plugins/filesystem/FilesystemPlugin.java +0 -551
  37. package/android/src/main/java/com/capacitorjs/plugins/filesystem/exceptions/CopyFailedException.java +0 -16
  38. package/android/src/main/java/com/capacitorjs/plugins/filesystem/exceptions/DirectoryExistsException.java +0 -16
  39. package/android/src/main/java/com/capacitorjs/plugins/filesystem/exceptions/DirectoryNotFoundException.java +0 -16
@@ -7,11 +7,12 @@ Pod::Spec.new do |s|
7
7
  s.version = package['version']
8
8
  s.summary = package['description']
9
9
  s.license = package['license']
10
- s.homepage = 'https://capacitorjs.com'
10
+ s.homepage = package['repository']['url']
11
11
  s.author = package['author']
12
- s.source = { :git => 'https://github.com/ionic-team/capacitor-plugins.git', :tag => package['name'] + '@' + package['version'] }
13
- s.source_files = 'ios/Sources/**/*.{swift,h,m,c,cc,mm,cpp}', 'filesystem/ios/Sources/**/*.{swift,h,m,c,cc,mm,cpp}'
12
+ s.source = { :git => package['repository']['url'], :tag => s.version.to_s }
13
+ s.source_files = 'ios/Sources/**/*.{swift,h,m,c,cc,mm,cpp}'
14
14
  s.ios.deployment_target = '14.0'
15
15
  s.dependency 'Capacitor'
16
+ s.dependency 'IONFilesystemLib', spec='~> 1.0'
16
17
  s.swift_version = '5.1'
17
18
  end
package/LICENSE CHANGED
@@ -1,23 +1,21 @@
1
- Copyright 2020-present Ionic
2
- https://ionic.io
3
-
4
1
  MIT License
5
2
 
6
- Permission is hereby granted, free of charge, to any person obtaining
7
- a copy of this software and associated documentation files (the
8
- "Software"), to deal in the Software without restriction, including
9
- without limitation the rights to use, copy, modify, merge, publish,
10
- distribute, sublicense, and/or sell copies of the Software, and to
11
- permit persons to whom the Software is furnished to do so, subject to
12
- the following conditions:
3
+ Copyright (c) 2025 Ionic
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
13
11
 
14
- The above copyright notice and this permission notice shall be
15
- included in all copies or substantial portions of the Software.
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
16
14
 
17
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/Package.swift CHANGED
@@ -2,22 +2,28 @@
2
2
  import PackageDescription
3
3
 
4
4
  let package = Package(
5
- name: "CapacitorFilesystem",
5
+ name: "FilesystemCapacitor",
6
6
  platforms: [.iOS(.v14)],
7
7
  products: [
8
8
  .library(
9
- name: "CapacitorFilesystem",
9
+ name: "FilesystemCapacitor",
10
10
  targets: ["FilesystemPlugin"])
11
11
  ],
12
12
  dependencies: [
13
- .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "7.0.0")
13
+ .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", exact: "7.1.0")
14
14
  ],
15
15
  targets: [
16
+ .binaryTarget(
17
+ name: "IONFilesystemLib",
18
+ url: "https://github.com/ionic-team/ion-ios-filesystem/releases/download/1.0.0/IONFilesystemLib.zip",
19
+ checksum: "0279cb09ba79c2c917b049a6e388f37f025846886ecc86b0a09320da46ed2c33" // sha-256
20
+ ),
16
21
  .target(
17
22
  name: "FilesystemPlugin",
18
23
  dependencies: [
19
24
  .product(name: "Capacitor", package: "capacitor-swift-pm"),
20
- .product(name: "Cordova", package: "capacitor-swift-pm")
25
+ .product(name: "Cordova", package: "capacitor-swift-pm"),
26
+ "IONFilesystemLib"
21
27
  ],
22
28
  path: "ios/Sources/FilesystemPlugin"),
23
29
  .testTarget(
package/README.md CHANGED
@@ -75,12 +75,12 @@ Additionally, the Filesystem API supports using full `file://` paths, or reading
75
75
  ## Example
76
76
 
77
77
  ```typescript
78
- import { Filesystem, Directory, Encoding } from '@capacitor/filesystem';
78
+ import { Filesystem, Directory, Encoding } from "@capacitor/filesystem";
79
79
 
80
80
  const writeSecretFile = async () => {
81
81
  await Filesystem.writeFile({
82
- path: 'secrets/text.txt',
83
- data: 'This is a test',
82
+ path: "secrets/text.txt",
83
+ data: "This is a test",
84
84
  directory: Directory.Documents,
85
85
  encoding: Encoding.UTF8,
86
86
  });
@@ -88,17 +88,17 @@ const writeSecretFile = async () => {
88
88
 
89
89
  const readSecretFile = async () => {
90
90
  const contents = await Filesystem.readFile({
91
- path: 'secrets/text.txt',
91
+ path: "secrets/text.txt",
92
92
  directory: Directory.Documents,
93
93
  encoding: Encoding.UTF8,
94
94
  });
95
95
 
96
- console.log('secrets:', contents);
96
+ console.log("secrets:", contents);
97
97
  };
98
98
 
99
99
  const deleteSecretFile = async () => {
100
100
  await Filesystem.deleteFile({
101
- path: 'secrets/text.txt',
101
+ path: "secrets/text.txt",
102
102
  directory: Directory.Documents,
103
103
  });
104
104
  };
@@ -108,10 +108,10 @@ const readFilePath = async () => {
108
108
  // read binary data (base64 encoded) from plugins that return File URIs, such as
109
109
  // the Camera.
110
110
  const contents = await Filesystem.readFile({
111
- path: 'file:///var/mobile/Containers/Data/Application/22A433FD-D82D-4989-8BE6-9FC49DEA20BB/Documents/text.txt',
111
+ path: "file:///var/mobile/Containers/Data/Application/22A433FD-D82D-4989-8BE6-9FC49DEA20BB/Documents/text.txt",
112
112
  });
113
113
 
114
- console.log('data:', contents);
114
+ console.log("data:", contents);
115
115
  };
116
116
  ```
117
117
 
@@ -119,7 +119,10 @@ const readFilePath = async () => {
119
119
 
120
120
  <docgen-index>
121
121
 
122
+ * [`checkPermissions()`](#checkpermissions)
123
+ * [`requestPermissions()`](#requestpermissions)
122
124
  * [`readFile(...)`](#readfile)
125
+ * [`readFileInChunks(...)`](#readfileinchunks)
123
126
  * [`writeFile(...)`](#writefile)
124
127
  * [`appendFile(...)`](#appendfile)
125
128
  * [`deleteFile(...)`](#deletefile)
@@ -130,8 +133,6 @@ const readFilePath = async () => {
130
133
  * [`stat(...)`](#stat)
131
134
  * [`rename(...)`](#rename)
132
135
  * [`copy(...)`](#copy)
133
- * [`checkPermissions()`](#checkpermissions)
134
- * [`requestPermissions()`](#requestpermissions)
135
136
  * [`downloadFile(...)`](#downloadfile)
136
137
  * [`addListener('progress', ...)`](#addlistenerprogress-)
137
138
  * [`removeAllListeners()`](#removealllisteners)
@@ -141,9 +142,45 @@ const readFilePath = async () => {
141
142
 
142
143
  </docgen-index>
143
144
 
145
+ For list of existing error codes, see [Errors](#errors).
146
+
144
147
  <docgen-api>
145
148
  <!--Update the source file JSDoc comments and rerun docgen to update the docs below-->
146
149
 
150
+ ### checkPermissions()
151
+
152
+ ```typescript
153
+ checkPermissions() => Promise<PermissionStatus>
154
+ ```
155
+
156
+ Check read/write permissions.
157
+ Required on Android, only when using <a href="#directory">`Directory.Documents`</a> or
158
+ `Directory.ExternalStorage`.
159
+
160
+ **Returns:** <code>Promise&lt;<a href="#permissionstatus">PermissionStatus</a>&gt;</code>
161
+
162
+ **Since:** 1.0.0
163
+
164
+ --------------------
165
+
166
+
167
+ ### requestPermissions()
168
+
169
+ ```typescript
170
+ requestPermissions() => Promise<PermissionStatus>
171
+ ```
172
+
173
+ Request read/write permissions.
174
+ Required on Android, only when using <a href="#directory">`Directory.Documents`</a> or
175
+ `Directory.ExternalStorage`.
176
+
177
+ **Returns:** <code>Promise&lt;<a href="#permissionstatus">PermissionStatus</a>&gt;</code>
178
+
179
+ **Since:** 1.0.0
180
+
181
+ --------------------
182
+
183
+
147
184
  ### readFile(...)
148
185
 
149
186
  ```typescript
@@ -163,6 +200,29 @@ Read a file from disk
163
200
  --------------------
164
201
 
165
202
 
203
+ ### readFileInChunks(...)
204
+
205
+ ```typescript
206
+ readFileInChunks(options: ReadFileInChunksOptions, callback: ReadFileInChunksCallback) => Promise<CallbackID>
207
+ ```
208
+
209
+ Read a file from disk, in chunks.
210
+ Native only (not available in web).
211
+ Use the callback to receive each read chunk.
212
+ If empty chunk is returned, it means file has been completely read.
213
+
214
+ | Param | Type |
215
+ | -------------- | ----------------------------------------------------------------------------- |
216
+ | **`options`** | <code><a href="#readfileinchunksoptions">ReadFileInChunksOptions</a></code> |
217
+ | **`callback`** | <code><a href="#readfileinchunkscallback">ReadFileInChunksCallback</a></code> |
218
+
219
+ **Returns:** <code>Promise&lt;string&gt;</code>
220
+
221
+ **Since:** 7.1.0
222
+
223
+ --------------------
224
+
225
+
166
226
  ### writeFile(...)
167
227
 
168
228
  ```typescript
@@ -300,7 +360,7 @@ Return data about a file
300
360
  | ------------- | --------------------------------------------------- |
301
361
  | **`options`** | <code><a href="#statoptions">StatOptions</a></code> |
302
362
 
303
- **Returns:** <code>Promise&lt;<a href="#statresult">StatResult</a>&gt;</code>
363
+ **Returns:** <code>Promise&lt;<a href="#fileinfo">FileInfo</a>&gt;</code>
304
364
 
305
365
  **Since:** 1.0.0
306
366
 
@@ -343,40 +403,6 @@ Copy a file or directory
343
403
  --------------------
344
404
 
345
405
 
346
- ### checkPermissions()
347
-
348
- ```typescript
349
- checkPermissions() => Promise<PermissionStatus>
350
- ```
351
-
352
- Check read/write permissions.
353
- Required on Android, only when using <a href="#directory">`Directory.Documents`</a> or
354
- `Directory.ExternalStorage`.
355
-
356
- **Returns:** <code>Promise&lt;<a href="#permissionstatus">PermissionStatus</a>&gt;</code>
357
-
358
- **Since:** 1.0.0
359
-
360
- --------------------
361
-
362
-
363
- ### requestPermissions()
364
-
365
- ```typescript
366
- requestPermissions() => Promise<PermissionStatus>
367
- ```
368
-
369
- Request read/write permissions.
370
- Required on Android, only when using <a href="#directory">`Directory.Documents`</a> or
371
- `Directory.ExternalStorage`.
372
-
373
- **Returns:** <code>Promise&lt;<a href="#permissionstatus">PermissionStatus</a>&gt;</code>
374
-
375
- **Since:** 1.0.0
376
-
377
- --------------------
378
-
379
-
380
406
  ### downloadFile(...)
381
407
 
382
408
  ```typescript
@@ -385,6 +411,9 @@ downloadFile(options: DownloadFileOptions) => Promise<DownloadFileResult>
385
411
 
386
412
  Perform a http request to a server and download the file to the specified destination.
387
413
 
414
+ This method has been deprecated since version 7.1.0.
415
+ We recommend using the @capacitor/file-transfer plugin instead, in conjunction with this plugin.
416
+
388
417
  | Param | Type |
389
418
  | ------------- | ------------------------------------------------------------------- |
390
419
  | **`options`** | <code><a href="#downloadfileoptions">DownloadFileOptions</a></code> |
@@ -404,6 +433,9 @@ addListener(eventName: 'progress', listenerFunc: ProgressListener) => Promise<Pl
404
433
 
405
434
  Add a listener to file download progress events.
406
435
 
436
+ This method has been deprecated since version 7.1.0.
437
+ We recommend using the @capacitor/file-transfer plugin instead, in conjunction with this plugin.
438
+
407
439
  | Param | Type |
408
440
  | ------------------ | ------------------------------------------------------------- |
409
441
  | **`eventName`** | <code>'progress'</code> |
@@ -424,6 +456,9 @@ removeAllListeners() => Promise<void>
424
456
 
425
457
  Remove all listeners for this plugin.
426
458
 
459
+ This method has been deprecated since version 7.1.0.
460
+ We recommend using the @capacitor/file-transfer plugin instead, in conjunction with this plugin.
461
+
427
462
  **Since:** 5.2.0
428
463
 
429
464
  --------------------
@@ -432,6 +467,13 @@ Remove all listeners for this plugin.
432
467
  ### Interfaces
433
468
 
434
469
 
470
+ #### PermissionStatus
471
+
472
+ | Prop | Type |
473
+ | ------------------- | ----------------------------------------------------------- |
474
+ | **`publicStorage`** | <code><a href="#permissionstate">PermissionState</a></code> |
475
+
476
+
435
477
  #### ReadFileResult
436
478
 
437
479
  | Prop | Type | Description | Since |
@@ -448,6 +490,13 @@ Remove all listeners for this plugin.
448
490
  | **`encoding`** | <code><a href="#encoding">Encoding</a></code> | The encoding to read the file in, if not provided, data is read as binary and returned as base64 encoded. Pass <a href="#encoding">Encoding.UTF8</a> to read data as string | 1.0.0 |
449
491
 
450
492
 
493
+ #### ReadFileInChunksOptions
494
+
495
+ | Prop | Type | Description | Since |
496
+ | --------------- | ------------------- | ---------------------------- | ----- |
497
+ | **`chunkSize`** | <code>number</code> | Size of the chunks in bytes. | 7.1.0 |
498
+
499
+
451
500
  #### WriteFileResult
452
501
 
453
502
  | Prop | Type | Description | Since |
@@ -513,11 +562,11 @@ Remove all listeners for this plugin.
513
562
 
514
563
  | Prop | Type | Description | Since |
515
564
  | ----------- | ---------------------------------- | ------------------------------------------------------------------------------------ | ----- |
516
- | **`name`** | <code>string</code> | Name of the file or directory. | |
565
+ | **`name`** | <code>string</code> | Name of the file or directory. | 7.1.0 |
517
566
  | **`type`** | <code>'file' \| 'directory'</code> | Type of the file. | 4.0.0 |
518
567
  | **`size`** | <code>number</code> | Size of the file in bytes. | 4.0.0 |
519
- | **`ctime`** | <code>number</code> | Time of creation in milliseconds. It's not available on Android 7 and older devices. | 4.0.0 |
520
- | **`mtime`** | <code>number</code> | Time of last modification in milliseconds. | 4.0.0 |
568
+ | **`ctime`** | <code>number</code> | Time of creation in milliseconds. It's not available on Android 7 and older devices. | 7.1.0 |
569
+ | **`mtime`** | <code>number</code> | Time of last modification in milliseconds. | 7.1.0 |
521
570
  | **`uri`** | <code>string</code> | The uri of the file. | 4.0.0 |
522
571
 
523
572
 
@@ -544,17 +593,6 @@ Remove all listeners for this plugin.
544
593
  | **`directory`** | <code><a href="#directory">Directory</a></code> | The <a href="#directory">`Directory`</a> to get the file under | 1.0.0 |
545
594
 
546
595
 
547
- #### StatResult
548
-
549
- | Prop | Type | Description | Since |
550
- | ----------- | ---------------------------------- | ------------------------------------------------------------------------------------ | ----- |
551
- | **`type`** | <code>'file' \| 'directory'</code> | Type of the file. | 1.0.0 |
552
- | **`size`** | <code>number</code> | Size of the file in bytes. | 1.0.0 |
553
- | **`ctime`** | <code>number</code> | Time of creation in milliseconds. It's not available on Android 7 and older devices. | 1.0.0 |
554
- | **`mtime`** | <code>number</code> | Time of last modification in milliseconds. | 1.0.0 |
555
- | **`uri`** | <code>string</code> | The uri of the file | 1.0.0 |
556
-
557
-
558
596
  #### StatOptions
559
597
 
560
598
  | Prop | Type | Description | Since |
@@ -580,13 +618,6 @@ Remove all listeners for this plugin.
580
618
  | **`uri`** | <code>string</code> | The uri where the file was copied into | 4.0.0 |
581
619
 
582
620
 
583
- #### PermissionStatus
584
-
585
- | Prop | Type |
586
- | ------------------- | ----------------------------------------------------------- |
587
- | **`publicStorage`** | <code><a href="#permissionstate">PermissionState</a></code> |
588
-
589
-
590
621
  #### DownloadFileResult
591
622
 
592
623
  | Prop | Type | Description | Since |
@@ -624,14 +655,31 @@ Remove all listeners for this plugin.
624
655
  ### Type Aliases
625
656
 
626
657
 
627
- #### RenameOptions
658
+ #### PermissionState
628
659
 
629
- <code><a href="#copyoptions">CopyOptions</a></code>
660
+ <code>'prompt' | 'prompt-with-rationale' | 'granted' | 'denied'</code>
630
661
 
631
662
 
632
- #### PermissionState
663
+ #### ReadFileInChunksCallback
664
+
665
+ Callback for receiving chunks read from a file, or error if something went wrong.
666
+
667
+ <code>(chunkRead: <a href="#readfileresult">ReadFileResult</a> | null, err?: any): void</code>
633
668
 
634
- <code>'prompt' | 'prompt-with-rationale' | 'granted' | 'denied'</code>
669
+
670
+ #### CallbackID
671
+
672
+ <code>string</code>
673
+
674
+
675
+ #### StatResult
676
+
677
+ <code><a href="#fileinfo">FileInfo</a></code>
678
+
679
+
680
+ #### RenameOptions
681
+
682
+ <code><a href="#copyoptions">CopyOptions</a></code>
635
683
 
636
684
 
637
685
  #### ProgressListener
@@ -646,14 +694,17 @@ A listener function that receives progress events.
646
694
 
647
695
  #### Directory
648
696
 
649
- | Members | Value | Description | Since |
650
- | --------------------- | ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- |
651
- | **`Documents`** | <code>'DOCUMENTS'</code> | 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 accesible 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. | 1.0.0 |
652
- | **`Data`** | <code>'DATA'</code> | 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. | 1.0.0 |
653
- | **`Library`** | <code>'LIBRARY'</code> | 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. | 1.1.0 |
654
- | **`Cache`** | <code>'CACHE'</code> | 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. | 1.0.0 |
655
- | **`External`** | <code>'EXTERNAL'</code> | 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. | 1.0.0 |
656
- | **`ExternalStorage`** | <code>'EXTERNAL_STORAGE'</code> | 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 accesible 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 accesible on Android 11 or newer. | 1.0.0 |
697
+ | Members | Value | Description | Since |
698
+ | --------------------- | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----- |
699
+ | **`Documents`** | <code>'DOCUMENTS'</code> | 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. | 1.0.0 |
700
+ | **`Data`** | <code>'DATA'</code> | 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. | 1.0.0 |
701
+ | **`Library`** | <code>'LIBRARY'</code> | 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. | 1.1.0 |
702
+ | **`Cache`** | <code>'CACHE'</code> | 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. | 1.0.0 |
703
+ | **`External`** | <code>'EXTERNAL'</code> | 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. | 1.0.0 |
704
+ | **`ExternalStorage`** | <code>'EXTERNAL_STORAGE'</code> | 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. | 1.0.0 |
705
+ | **`ExternalCache`** | <code>'EXTERNAL_CACHE'</code> | The external cache directory. On iOS it will use the Documents directory. On Android it's the primary shared/external cache. | 7.1.0 |
706
+ | **`LibraryNoCloud`** | <code>'LIBRARY_NO_CLOUD'</code> | The Library directory without cloud backup. Used in iOS. On Android it's the directory holding application files. | 7.1.0 |
707
+ | **`Temporary`** | <code>'TEMPORARY'</code> | A temporary directory for iOS. On Android it's the directory holding the application cache. | 7.1.0 |
657
708
 
658
709
 
659
710
  #### Encoding
@@ -665,3 +716,23 @@ A listener function that receives progress events.
665
716
  | **`UTF16`** | <code>'utf16'</code> | Sixteen-bit UCS Transformation Format, byte order identified by an optional byte-order mark This encoding is only supported on Android. | 1.0.0 |
666
717
 
667
718
  </docgen-api>
719
+
720
+ ### Errors
721
+
722
+ Since version 7.1.0, the plugin returns specific errors with specific codes on native Android and iOS. Web does not follow this standard for errors.
723
+
724
+ The following table list all the plugin errors:
725
+
726
+ | Error code | Platform(s) | Message |
727
+ |-------------------|------------------|------------------------------|
728
+ | OS-PLUG-FILE-0004 | iOS | Cordova / Capacitor bridge isn’t initialized. |
729
+ | OS-PLUG-FILE-0005 | Android, iOS | The method input parameters aren’t valid. |
730
+ | OS-PLUG-FILE-0006 | Android, iOS | Invalid path was provided. |
731
+ | OS-PLUG-FILE-0007 | Android | Unable to perform file operation, user denied permission request. |
732
+ | OS-PLUG-FILE-0008 | Android, iOS | Operation failed because file does not exist. |
733
+ | OS-PLUG-FILE-0009 | Android | Operation not supported for provided input. |
734
+ | OS-PLUG-FILE-0010 | Android, iOS | Directory already exists, cannot be overwritten. |
735
+ | OS-PLUG-FILE-0011 | Android, iOS | Missing parent directory – possibly recursive=false was passed or parent directory creation failed. |
736
+ | OS-PLUG-FILE-0012 | Android, iOS | Cannot delete directory with children; received recursive=false but directory has contents. |
737
+ | OS-PLUG-FILE-0013 | Android, iOS | The operation failed with an error. |
738
+
@@ -1,5 +1,4 @@
1
1
  ext {
2
- capacitorVersion = System.getenv('CAPACITOR_VERSION')
3
2
  junitVersion = project.hasProperty('junitVersion') ? rootProject.ext.junitVersion : '4.13.2'
4
3
  androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.7.0'
5
4
  androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.2.1'
@@ -7,27 +6,19 @@ ext {
7
6
  }
8
7
 
9
8
  buildscript {
9
+ ext.kotlin_version = project.hasProperty("kotlin_version") ? rootProject.ext.kotlin_version : '1.9.24'
10
10
  repositories {
11
11
  google()
12
12
  mavenCentral()
13
- maven {
14
- url "https://plugins.gradle.org/m2/"
15
- }
16
13
  }
17
14
  dependencies {
18
- classpath 'com.android.tools.build:gradle:8.7.2'
19
- if (System.getenv("CAP_PLUGIN_PUBLISH") == "true") {
20
- classpath 'io.github.gradle-nexus:publish-plugin:1.3.0'
21
- }
15
+ classpath 'com.android.tools.build:gradle:8.7.1'
16
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
22
17
  }
23
18
  }
24
19
 
25
20
  apply plugin: 'com.android.library'
26
- if (System.getenv("CAP_PLUGIN_PUBLISH") == "true") {
27
- apply plugin: 'io.github.gradle-nexus.publish-plugin'
28
- apply from: file('../../scripts/android/publish-root.gradle')
29
- apply from: file('../../scripts/android/publish-module.gradle')
30
- }
21
+ apply plugin: 'kotlin-android'
31
22
 
32
23
  android {
33
24
  namespace "com.capacitorjs.plugins.filesystem"
@@ -52,9 +43,10 @@ android {
52
43
  sourceCompatibility JavaVersion.VERSION_21
53
44
  targetCompatibility JavaVersion.VERSION_21
54
45
  }
55
- publishing {
56
- singleVariant("release")
57
- }
46
+ }
47
+
48
+ kotlin {
49
+ jvmToolchain(21)
58
50
  }
59
51
 
60
52
  repositories {
@@ -65,14 +57,12 @@ repositories {
65
57
 
66
58
  dependencies {
67
59
  implementation fileTree(dir: 'libs', include: ['*.jar'])
60
+ implementation "io.ionic.libs:ionfilesystem-android:1.0.0"
61
+ implementation project(':capacitor-android')
62
+ implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
68
63
 
69
- if (System.getenv("CAP_PLUGIN_PUBLISH") == "true") {
70
- implementation "com.capacitorjs:core:$capacitorVersion"
71
- } else {
72
- implementation project(':capacitor-android')
73
- }
64
+ implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
74
65
 
75
- implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
76
66
  testImplementation "junit:junit:$junitVersion"
77
67
  androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
78
68
  androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
@@ -0,0 +1,101 @@
1
+ package com.capacitorjs.plugins.filesystem
2
+
3
+ import io.ionic.libs.ionfilesystemlib.model.IONFILEExceptions
4
+
5
+ object FilesystemErrors {
6
+ private fun formatErrorCode(number: Int): String {
7
+ return "OS-PLUG-FILE-" + number.toString().padStart(4, '0')
8
+ }
9
+
10
+ data class ErrorInfo(
11
+ val code: String,
12
+ val message: String
13
+ )
14
+
15
+ fun invalidInputMethod(methodName: String): ErrorInfo = ErrorInfo(
16
+ code = formatErrorCode(5),
17
+ message = "The '$methodName' input parameters aren't valid."
18
+ )
19
+
20
+ fun invalidPath(path: String): ErrorInfo = ErrorInfo(
21
+ code = formatErrorCode(6),
22
+ message = "Invalid ${if (path.isNotBlank()) "'$path' " else ""}path."
23
+ )
24
+
25
+ val filePermissionsDenied: ErrorInfo = ErrorInfo(
26
+ code = formatErrorCode(7),
27
+ message = "Unable to do file operation, user denied permission request."
28
+ )
29
+
30
+ fun doesNotExist(methodName: String, path: String): ErrorInfo = ErrorInfo(
31
+ code = formatErrorCode(8),
32
+ message = "'$methodName' failed because file ${if (path.isNotBlank()) "at '$path' " else ""}does not exist."
33
+ )
34
+
35
+ fun notAllowed(methodName: String, notAllowedFor: String): ErrorInfo = ErrorInfo(
36
+ code = formatErrorCode(9),
37
+ message = "'$methodName' not supported for $notAllowedFor."
38
+ )
39
+
40
+ fun directoryCreationAlreadyExists(path: String): ErrorInfo = ErrorInfo(
41
+ code = formatErrorCode(10),
42
+ message = "Directory ${if (path.isNotBlank()) "at '$path' " else ""}already exists, cannot be overwritten."
43
+ )
44
+
45
+ val missingParentDirectories: ErrorInfo = ErrorInfo(
46
+ code = formatErrorCode(11),
47
+ message = "Missing parent directory – possibly recursive=false was passed or parent directory creation failed."
48
+ )
49
+
50
+ val cannotDeleteChildren: ErrorInfo = ErrorInfo(
51
+ code = formatErrorCode(12),
52
+ message = "Cannot delete directory with children; received recursive=false but directory has contents."
53
+ )
54
+
55
+ fun operationFailed(methodName: String, errorMessage: String): ErrorInfo = ErrorInfo(
56
+ code = formatErrorCode(13),
57
+ message = "'$methodName' failed with${if (errorMessage.isNotBlank()) ": $errorMessage" else "an unknown error."}"
58
+ )
59
+ }
60
+
61
+ fun Throwable.toFilesystemError(methodName: String): FilesystemErrors.ErrorInfo = when (this) {
62
+
63
+ is IONFILEExceptions.UnresolvableUri -> FilesystemErrors.invalidPath(this.uri)
64
+
65
+ is IONFILEExceptions.DoesNotExist -> FilesystemErrors.doesNotExist(methodName, this.path)
66
+
67
+ is IONFILEExceptions.NotSupportedForContentScheme -> FilesystemErrors.notAllowed(
68
+ methodName,
69
+ notAllowedFor = "content:// URIs"
70
+ )
71
+
72
+ is IONFILEExceptions.NotSupportedForDirectory -> FilesystemErrors.notAllowed(
73
+ methodName,
74
+ notAllowedFor = "directories"
75
+ )
76
+
77
+ is IONFILEExceptions.NotSupportedForFiles -> FilesystemErrors.notAllowed(
78
+ methodName,
79
+ notAllowedFor = "files, only directories are supported"
80
+ )
81
+
82
+ is IONFILEExceptions.CreateFailed.AlreadyExists ->
83
+ FilesystemErrors.directoryCreationAlreadyExists(this.path)
84
+
85
+ is IONFILEExceptions.CreateFailed.NoParentDirectory -> FilesystemErrors.missingParentDirectories
86
+
87
+ is IONFILEExceptions.DeleteFailed.CannotDeleteChildren -> FilesystemErrors.cannotDeleteChildren
88
+
89
+ is IONFILEExceptions.CopyRenameFailed.MixingFilesAndDirectories,
90
+ is IONFILEExceptions.CopyRenameFailed.LocalToContent,
91
+ is IONFILEExceptions.CopyRenameFailed.SourceAndDestinationContent ->
92
+ FilesystemErrors.notAllowed(methodName, "the provided source and destinations")
93
+
94
+ is IONFILEExceptions.CopyRenameFailed.DestinationDirectoryExists ->
95
+ FilesystemErrors.directoryCreationAlreadyExists(this.path)
96
+
97
+ is IONFILEExceptions.CopyRenameFailed.NoParentDirectory ->
98
+ FilesystemErrors.missingParentDirectories
99
+
100
+ else -> FilesystemErrors.operationFailed(methodName, this.localizedMessage ?: "")
101
+ }