expo-file-system 56.0.5 → 56.0.6
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.
- package/CHANGELOG.md +15 -0
- package/android/build.gradle +2 -3
- package/build/Directory.d.ts.map +1 -1
- package/build/File.d.ts +2 -0
- package/build/File.d.ts.map +1 -1
- package/expo-module.config.json +1 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.filesystem/{56.0.5/expo.modules.filesystem-56.0.5.module → 56.0.6/expo.modules.filesystem-56.0.6.module} +7 -21
- package/local-maven-repo/host/exp/exponent/expo.modules.filesystem/56.0.6/expo.modules.filesystem-56.0.6.module.md5 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.filesystem/56.0.6/expo.modules.filesystem-56.0.6.module.sha1 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.filesystem/56.0.6/expo.modules.filesystem-56.0.6.module.sha256 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.filesystem/56.0.6/expo.modules.filesystem-56.0.6.module.sha512 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.filesystem/{56.0.5/expo.modules.filesystem-56.0.5.pom → 56.0.6/expo.modules.filesystem-56.0.6.pom} +1 -7
- package/local-maven-repo/host/exp/exponent/expo.modules.filesystem/56.0.6/expo.modules.filesystem-56.0.6.pom.md5 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.filesystem/56.0.6/expo.modules.filesystem-56.0.6.pom.sha1 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.filesystem/56.0.6/expo.modules.filesystem-56.0.6.pom.sha256 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.filesystem/56.0.6/expo.modules.filesystem-56.0.6.pom.sha512 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.filesystem/maven-metadata.xml +4 -4
- package/local-maven-repo/host/exp/exponent/expo.modules.filesystem/maven-metadata.xml.md5 +1 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.filesystem/maven-metadata.xml.sha1 +1 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.filesystem/maven-metadata.xml.sha256 +1 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.filesystem/maven-metadata.xml.sha512 +1 -1
- package/mocks/FileSystem.ts +787 -51
- package/package.json +5 -5
- package/prebuilds/output/debug/xcframeworks/ExpoFileSystem.tar.gz +0 -0
- package/prebuilds/output/release/xcframeworks/ExpoFileSystem.tar.gz +0 -0
- package/src/Directory.ts +0 -2
- package/src/File.ts +10 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.filesystem/56.0.5/expo.modules.filesystem-56.0.5.module.md5 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.filesystem/56.0.5/expo.modules.filesystem-56.0.5.module.sha1 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.filesystem/56.0.5/expo.modules.filesystem-56.0.5.module.sha256 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.filesystem/56.0.5/expo.modules.filesystem-56.0.5.module.sha512 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.filesystem/56.0.5/expo.modules.filesystem-56.0.5.pom.md5 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.filesystem/56.0.5/expo.modules.filesystem-56.0.5.pom.sha1 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.filesystem/56.0.5/expo.modules.filesystem-56.0.5.pom.sha256 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.filesystem/56.0.5/expo.modules.filesystem-56.0.5.pom.sha512 +0 -1
- /package/local-maven-repo/host/exp/exponent/expo.modules.filesystem/{56.0.5/expo.modules.filesystem-56.0.5-sources.jar → 56.0.6/expo.modules.filesystem-56.0.6-sources.jar} +0 -0
- /package/local-maven-repo/host/exp/exponent/expo.modules.filesystem/{56.0.5/expo.modules.filesystem-56.0.5-sources.jar.md5 → 56.0.6/expo.modules.filesystem-56.0.6-sources.jar.md5} +0 -0
- /package/local-maven-repo/host/exp/exponent/expo.modules.filesystem/{56.0.5/expo.modules.filesystem-56.0.5-sources.jar.sha1 → 56.0.6/expo.modules.filesystem-56.0.6-sources.jar.sha1} +0 -0
- /package/local-maven-repo/host/exp/exponent/expo.modules.filesystem/{56.0.5/expo.modules.filesystem-56.0.5-sources.jar.sha256 → 56.0.6/expo.modules.filesystem-56.0.6-sources.jar.sha256} +0 -0
- /package/local-maven-repo/host/exp/exponent/expo.modules.filesystem/{56.0.5/expo.modules.filesystem-56.0.5-sources.jar.sha512 → 56.0.6/expo.modules.filesystem-56.0.6-sources.jar.sha512} +0 -0
- /package/local-maven-repo/host/exp/exponent/expo.modules.filesystem/{56.0.5/expo.modules.filesystem-56.0.5.aar → 56.0.6/expo.modules.filesystem-56.0.6.aar} +0 -0
- /package/local-maven-repo/host/exp/exponent/expo.modules.filesystem/{56.0.5/expo.modules.filesystem-56.0.5.aar.md5 → 56.0.6/expo.modules.filesystem-56.0.6.aar.md5} +0 -0
- /package/local-maven-repo/host/exp/exponent/expo.modules.filesystem/{56.0.5/expo.modules.filesystem-56.0.5.aar.sha1 → 56.0.6/expo.modules.filesystem-56.0.6.aar.sha1} +0 -0
- /package/local-maven-repo/host/exp/exponent/expo.modules.filesystem/{56.0.5/expo.modules.filesystem-56.0.5.aar.sha256 → 56.0.6/expo.modules.filesystem-56.0.6.aar.sha256} +0 -0
- /package/local-maven-repo/host/exp/exponent/expo.modules.filesystem/{56.0.5/expo.modules.filesystem-56.0.5.aar.sha512 → 56.0.6/expo.modules.filesystem-56.0.6.aar.sha512} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,20 @@
|
|
|
10
10
|
|
|
11
11
|
### 💡 Others
|
|
12
12
|
|
|
13
|
+
## 56.0.6 — 2026-05-19
|
|
14
|
+
|
|
15
|
+
### 🎉 New features
|
|
16
|
+
|
|
17
|
+
- Added `File.json()` and `File.formData()` to satisfy `Blob` type augmentations in consumer projects. ([#45685](https://github.com/expo/expo/pull/45685) by [@mvincentong](https://github.com/mvincentong))
|
|
18
|
+
|
|
19
|
+
### 🐛 Bug fixes
|
|
20
|
+
|
|
21
|
+
- Fixed the jest mock's `FileSystemFileHandle` to honor `FileMode` string values (`'r'`, `'w'`, `'wa'`, `'wt'`, `'rw'`) instead of the obsolete name table, expose handle and file metadata, and match the documented default mode for `content://` URIs. The dispatch is now exhaustive over `FileMode`, so future enum additions fail to compile in the mock. (by [@radko93](https://github.com/radko93))
|
|
22
|
+
|
|
23
|
+
### 💡 Others
|
|
24
|
+
|
|
25
|
+
- [Android] Remove unused native dependencies. ([#45939](https://github.com/expo/expo/pull/45939) by [@jakex7](https://github.com/jakex7))
|
|
26
|
+
|
|
13
27
|
## 56.0.5 — 2026-05-15
|
|
14
28
|
|
|
15
29
|
### 💡 Others
|
|
@@ -64,6 +78,7 @@ _This version does not introduce any user-facing changes._
|
|
|
64
78
|
|
|
65
79
|
### 💡 Others
|
|
66
80
|
|
|
81
|
+
- Add behavioral Jest mocks for the class-based `File` / `Directory` / `Paths` API, backed by an in-memory filesystem so tests can exercise create/write/read/move/copy/delete roundtrips without hand-rolling a `jest.mock`. ([#45027](https://github.com/expo/expo/pull/45027) by [@radko93](https://github.com/radko93))
|
|
67
82
|
- Deprecate `modificationTime` in favor of new `lastModified`, compatible with web `File` interface. ([#43411](https://github.com/expo/expo/pull/43411) by [@HubertBer](https://github.com/HubertBer))
|
|
68
83
|
- Deprecate `File.pickFileAsync(arg1, arg2)` in favour of new `File.pickFileAsync(options)`. ([#43411](https://github.com/expo/expo/pull/43411) by [@HubertBer](https://github.com/HubertBer))
|
|
69
84
|
- [Android] Optimized performance of copy and move operations. ([#44357](https://github.com/expo/expo/pull/44357), [#44358](https://github.com/expo/expo/pull/44358) by [@barthap](https://github.com/barthap))
|
package/android/build.gradle
CHANGED
|
@@ -4,13 +4,13 @@ plugins {
|
|
|
4
4
|
}
|
|
5
5
|
|
|
6
6
|
group = 'host.exp.exponent'
|
|
7
|
-
version = '56.0.
|
|
7
|
+
version = '56.0.6'
|
|
8
8
|
|
|
9
9
|
android {
|
|
10
10
|
namespace "expo.modules.filesystem"
|
|
11
11
|
defaultConfig {
|
|
12
12
|
versionCode 30
|
|
13
|
-
versionName "56.0.
|
|
13
|
+
versionName "56.0.6"
|
|
14
14
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
|
15
15
|
}
|
|
16
16
|
testOptions {
|
|
@@ -24,7 +24,6 @@ dependencies {
|
|
|
24
24
|
api 'com.squareup.okhttp3:okhttp:4.9.2'
|
|
25
25
|
api 'com.squareup.okhttp3:okhttp-urlconnection:4.9.2'
|
|
26
26
|
api 'com.squareup.okio:okio:2.9.0'
|
|
27
|
-
api "androidx.legacy:legacy-support-v4:1.0.0"
|
|
28
27
|
api "androidx.documentfile:documentfile:1.1.0"
|
|
29
28
|
implementation 'com.facebook.react:react-android'
|
|
30
29
|
|
package/build/Directory.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Directory.d.ts","sourceRoot":"","sources":["../src/Directory.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAI7F;;;;;;;;;;GAUG;AACH,qBAAa,SAAU,SAAQ,cAAc,CAAC,mBAAmB;IAC/D,MAAM,CAAC,kBAAkB,EAAE,CAAC,UAAU,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IAEvE;;;;;;;;;OASG;gBACS,GAAG,IAAI,EAAE,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE;IAQlD,IAAI,eAAe,cAElB;IAED;;;;OAIG;IACM,IAAI,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,EAAE;
|
|
1
|
+
{"version":3,"file":"Directory.d.ts","sourceRoot":"","sources":["../src/Directory.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAI7F;;;;;;;;;;GAUG;AACH,qBAAa,SAAU,SAAQ,cAAc,CAAC,mBAAmB;IAC/D,MAAM,CAAC,kBAAkB,EAAE,CAAC,UAAU,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IAEvE;;;;;;;;;OASG;gBACS,GAAG,IAAI,EAAE,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE;IAQlD,IAAI,eAAe,cAElB;IAED;;;;OAIG;IACM,IAAI,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,EAAE;IAMrC;;OAEG;IACH,IAAI,IAAI,WAEP;IAED,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAIvD,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS;IAIxC;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,KAAK,CACH,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,IAAI,GAAG,SAAS,CAAC,KAAK,IAAI,EACvD,OAAO,CAAC,EAAE,YAAY,GACrB,iBAAiB;CAQrB"}
|
package/build/File.d.ts
CHANGED
|
@@ -103,6 +103,8 @@ export declare class File extends ExpoFileSystem.FileSystemFile implements Blob
|
|
|
103
103
|
readableStream(): ReadableStream<Uint8Array<ArrayBuffer>>;
|
|
104
104
|
writableStream(): WritableStream<Uint8Array<ArrayBufferLike>>;
|
|
105
105
|
arrayBuffer(): Promise<ArrayBuffer>;
|
|
106
|
+
json(): Promise<any>;
|
|
107
|
+
formData(): ReturnType<Response['formData']>;
|
|
106
108
|
stream(): ReadableStream<Uint8Array<ArrayBuffer>>;
|
|
107
109
|
slice(start?: number, end?: number, contentType?: string): Blob;
|
|
108
110
|
/**
|
package/build/File.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"File.d.ts","sourceRoot":"","sources":["../src/File.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,cAAc,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAGL,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,EAC5B,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EAC1B,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACvB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EACL,KAAK,eAAe,EAEpB,KAAK,mBAAmB,EACxB,KAAK,aAAa,EAClB,KAAK,YAAY,EAClB,MAAM,sBAAsB,CAAC;AAK9B;;;;;;;;;;GAUG;AACH,qBAAa,IAAK,SAAQ,cAAc,CAAC,cAAe,YAAW,IAAI;IACrE;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,MAAM,CAAC,iBAAiB,EAAE,CACxB,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,SAAS,GAAG,IAAI,EAC7B,OAAO,CAAC,EAAE,eAAe,KACtB,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnB;;;;;;OAMG;IACH,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IACpF;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,wBAAwB,GAAG,OAAO,CAAC,uBAAuB,CAAC;IAC1F;;;;;;;;;OASG;IACH,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,EAAE,CAAC;IA8BpF;;;;;;;;;OASG;gBACS,GAAG,IAAI,EAAE,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE;IAQlD,IAAI,eAAe,cAElB;IAED;;;OAGG;IACH,IAAI,SAAS,WAEZ;IAED;;OAEG;IACH,IAAI,IAAI,WAEP;IAED,cAAc;IAId,cAAc;IAMR,WAAW,IAAI,OAAO,CAAC,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"File.d.ts","sourceRoot":"","sources":["../src/File.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,cAAc,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAGL,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,EAC5B,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EAC1B,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACvB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EACL,KAAK,eAAe,EAEpB,KAAK,mBAAmB,EACxB,KAAK,aAAa,EAClB,KAAK,YAAY,EAClB,MAAM,sBAAsB,CAAC;AAK9B;;;;;;;;;;GAUG;AACH,qBAAa,IAAK,SAAQ,cAAc,CAAC,cAAe,YAAW,IAAI;IACrE;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,MAAM,CAAC,iBAAiB,EAAE,CACxB,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,SAAS,GAAG,IAAI,EAC7B,OAAO,CAAC,EAAE,eAAe,KACtB,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnB;;;;;;OAMG;IACH,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IACpF;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,wBAAwB,GAAG,OAAO,CAAC,uBAAuB,CAAC;IAC1F;;;;;;;;;OASG;IACH,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,EAAE,CAAC;IA8BpF;;;;;;;;;OASG;gBACS,GAAG,IAAI,EAAE,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE;IAQlD,IAAI,eAAe,cAElB;IAED;;;OAGG;IACH,IAAI,SAAS,WAEZ;IAED;;OAEG;IACH,IAAI,IAAI,WAEP;IAED,cAAc;IAId,cAAc;IAMR,WAAW,IAAI,OAAO,CAAC,WAAW,CAAC;IAKnC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC;IAIpB,QAAQ,IAAI,UAAU,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IAMlD,MAAM,IAAI,cAAc,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;IAIjD,KAAK,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI;IAI/D;;;;;;;;;;OAUG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;IAInE;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,UAAU;IAIlE;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,MAAM,CAAC,kBAAkB,CACvB,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,IAAI,GAAG,SAAS,EAC7B,OAAO,CAAC,EAAE,mBAAmB,GAC5B,YAAY;IAIf;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,KAAK,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,iBAAiB;CAG9F"}
|
package/expo-module.config.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"component": {
|
|
4
4
|
"group": "host.exp.exponent",
|
|
5
5
|
"module": "expo.modules.filesystem",
|
|
6
|
-
"version": "56.0.
|
|
6
|
+
"version": "56.0.6",
|
|
7
7
|
"attributes": {
|
|
8
8
|
"org.gradle.status": "release"
|
|
9
9
|
}
|
|
@@ -58,13 +58,6 @@
|
|
|
58
58
|
"requires": "2.9.0"
|
|
59
59
|
}
|
|
60
60
|
},
|
|
61
|
-
{
|
|
62
|
-
"group": "androidx.legacy",
|
|
63
|
-
"module": "legacy-support-v4",
|
|
64
|
-
"version": {
|
|
65
|
-
"requires": "1.0.0"
|
|
66
|
-
}
|
|
67
|
-
},
|
|
68
61
|
{
|
|
69
62
|
"group": "androidx.documentfile",
|
|
70
63
|
"module": "documentfile",
|
|
@@ -75,8 +68,8 @@
|
|
|
75
68
|
],
|
|
76
69
|
"files": [
|
|
77
70
|
{
|
|
78
|
-
"name": "expo.modules.filesystem-56.0.
|
|
79
|
-
"url": "expo.modules.filesystem-56.0.
|
|
71
|
+
"name": "expo.modules.filesystem-56.0.6.aar",
|
|
72
|
+
"url": "expo.modules.filesystem-56.0.6.aar",
|
|
80
73
|
"size": 689001,
|
|
81
74
|
"sha512": "9d5a05c062694b0a80f9830a2e39a462f8e1683c304bc0496b64203468706987369437e74cfdeee056f013de1602097b6e4ff1dda3384973ea78a0fedcf30d03",
|
|
82
75
|
"sha256": "66c88fad23aaf1b650784ba1ef259cf4f0141278893a1b42472ef36b977ccd93",
|
|
@@ -147,13 +140,6 @@
|
|
|
147
140
|
"requires": "2.9.0"
|
|
148
141
|
}
|
|
149
142
|
},
|
|
150
|
-
{
|
|
151
|
-
"group": "androidx.legacy",
|
|
152
|
-
"module": "legacy-support-v4",
|
|
153
|
-
"version": {
|
|
154
|
-
"requires": "1.0.0"
|
|
155
|
-
}
|
|
156
|
-
},
|
|
157
143
|
{
|
|
158
144
|
"group": "androidx.documentfile",
|
|
159
145
|
"module": "documentfile",
|
|
@@ -171,8 +157,8 @@
|
|
|
171
157
|
],
|
|
172
158
|
"files": [
|
|
173
159
|
{
|
|
174
|
-
"name": "expo.modules.filesystem-56.0.
|
|
175
|
-
"url": "expo.modules.filesystem-56.0.
|
|
160
|
+
"name": "expo.modules.filesystem-56.0.6.aar",
|
|
161
|
+
"url": "expo.modules.filesystem-56.0.6.aar",
|
|
176
162
|
"size": 689001,
|
|
177
163
|
"sha512": "9d5a05c062694b0a80f9830a2e39a462f8e1683c304bc0496b64203468706987369437e74cfdeee056f013de1602097b6e4ff1dda3384973ea78a0fedcf30d03",
|
|
178
164
|
"sha256": "66c88fad23aaf1b650784ba1ef259cf4f0141278893a1b42472ef36b977ccd93",
|
|
@@ -191,8 +177,8 @@
|
|
|
191
177
|
},
|
|
192
178
|
"files": [
|
|
193
179
|
{
|
|
194
|
-
"name": "expo.modules.filesystem-56.0.
|
|
195
|
-
"url": "expo.modules.filesystem-56.0.
|
|
180
|
+
"name": "expo.modules.filesystem-56.0.6-sources.jar",
|
|
181
|
+
"url": "expo.modules.filesystem-56.0.6-sources.jar",
|
|
196
182
|
"size": 49979,
|
|
197
183
|
"sha512": "3bdf553eb365ff56c8d0ca441a0fbe5d58a53d94f0f2dc565579dfa6124318c1d3a929d7bbd81efffced17716316872c0c2dbadb03795b1cb9a707741da486b3",
|
|
198
184
|
"sha256": "6fb4f4458a682db136e3f8316c2c72449f51df3c9067dfab4adb7320e4cd87a0",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
a2ecf6354cd885e58e79a290ba291952
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2166df9c64b5a02d591d7c52cf949cfe88137b0d
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
8bb9edfa93e2e55af08f2fe6f06b864d62bb3702ddca2c1a947174350f7cfd87
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
61b3a1297673a1c18140ac284bb6e38d86ec406b40966aa5bec804e79b26a775de8024a0dc499f53b9e926a82595223fb9be379ac87e0c6869735973b62e0531
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
<modelVersion>4.0.0</modelVersion>
|
|
10
10
|
<groupId>host.exp.exponent</groupId>
|
|
11
11
|
<artifactId>expo.modules.filesystem</artifactId>
|
|
12
|
-
<version>56.0.
|
|
12
|
+
<version>56.0.6</version>
|
|
13
13
|
<packaging>aar</packaging>
|
|
14
14
|
<name>expo.modules.filesystem</name>
|
|
15
15
|
<url>https://github.com/expo/expo</url>
|
|
@@ -67,12 +67,6 @@
|
|
|
67
67
|
<version>2.9.0</version>
|
|
68
68
|
<scope>compile</scope>
|
|
69
69
|
</dependency>
|
|
70
|
-
<dependency>
|
|
71
|
-
<groupId>androidx.legacy</groupId>
|
|
72
|
-
<artifactId>legacy-support-v4</artifactId>
|
|
73
|
-
<version>1.0.0</version>
|
|
74
|
-
<scope>compile</scope>
|
|
75
|
-
</dependency>
|
|
76
70
|
<dependency>
|
|
77
71
|
<groupId>androidx.documentfile</groupId>
|
|
78
72
|
<artifactId>documentfile</artifactId>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
976776a9f37b1390df7b98827a4a9558
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
67ef704f8d984b984212a1c8f807c4918a9f4dd7
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
b0e49cf8d66adb123b596568005e4ebf6a5475a43850db6e49097baf39179ec5
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3912c1bd64aa96e0a94f5ab76ff34175f3e3939136d4671dbec661c22d79ec6d4d1d175ff1f55367cac6645d77724b1a9d7eb2ccd63385e70d059ff36b3a1dab
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
<groupId>host.exp.exponent</groupId>
|
|
4
4
|
<artifactId>expo.modules.filesystem</artifactId>
|
|
5
5
|
<versioning>
|
|
6
|
-
<latest>56.0.
|
|
7
|
-
<release>56.0.
|
|
6
|
+
<latest>56.0.6</latest>
|
|
7
|
+
<release>56.0.6</release>
|
|
8
8
|
<versions>
|
|
9
|
-
<version>56.0.
|
|
9
|
+
<version>56.0.6</version>
|
|
10
10
|
</versions>
|
|
11
|
-
<lastUpdated>
|
|
11
|
+
<lastUpdated>20260519105313</lastUpdated>
|
|
12
12
|
</versioning>
|
|
13
13
|
</metadata>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
76f4067aaa57513178fe3643c7f4fcee
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
333cc2767c02f5b952922e0568c4c55adcdfbab3
|
package/local-maven-repo/host/exp/exponent/expo.modules.filesystem/maven-metadata.xml.sha256
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
16478284a6e3560c72a519a3c7368ca80eb11795fb5a384ec3235bab9d8e2883
|
package/local-maven-repo/host/exp/exponent/expo.modules.filesystem/maven-metadata.xml.sha512
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
5aae03f2854561fed3217710ced5e4ef5fef073e5d075c2dcecd8d1f4c80e2fbdcb3f2960cbe5278428ccd9bf240c1c09c5b92c422eebc28350e62a05e5e8c02
|
package/mocks/FileSystem.ts
CHANGED
|
@@ -1,87 +1,728 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Hand-maintained mock for the FileSystem native module.
|
|
3
|
+
*
|
|
4
|
+
* Backs the class-based API (`File`, `Directory`, `Paths` from
|
|
5
|
+
* `expo-file-system`) with a small in-memory filesystem so tests can exercise
|
|
6
|
+
* create/write/read/move/copy/delete end-to-end. This module is what
|
|
7
|
+
* `jest-expo`'s preset feeds to `requireNativeModule('FileSystem')`.
|
|
8
|
+
* Timestamps use a logical clock reset by `__resetMockFileSystem()`; do not use
|
|
9
|
+
* `Date.now()` here.
|
|
10
|
+
*
|
|
11
|
+
* DO NOT regenerate this file with `expo-modules-test-core` — the generator
|
|
12
|
+
* emits a bare stub and will overwrite the behavior here. Same pattern as
|
|
13
|
+
* `packages/expo-crypto/mocks/ExpoCryptoAES.ts`.
|
|
14
|
+
*/
|
|
2
15
|
|
|
3
|
-
|
|
16
|
+
import { FileMode } from '../src/File.types';
|
|
4
17
|
|
|
18
|
+
export type URL = string;
|
|
19
|
+
export type FileSystemPath = any;
|
|
5
20
|
export type DownloadOptions = any;
|
|
6
|
-
|
|
7
21
|
export type InfoOptions = any;
|
|
8
|
-
|
|
9
22
|
export type TypedArray = any;
|
|
10
|
-
|
|
11
23
|
export type CreateOptions = any;
|
|
12
24
|
|
|
13
25
|
export const documentDirectory = 'file:///mock/document/';
|
|
14
26
|
export const cacheDirectory = 'file:///mock/cache/';
|
|
15
27
|
export const bundleDirectory = 'file:///mock/bundle/';
|
|
16
|
-
export const
|
|
17
|
-
export const
|
|
28
|
+
export const appleSharedContainers: Record<string, string> = {};
|
|
29
|
+
export const totalDiskSpace = 1_000_000_000;
|
|
30
|
+
export const availableDiskSpace = 500_000_000;
|
|
18
31
|
|
|
19
|
-
|
|
32
|
+
type Entry = {
|
|
33
|
+
kind: 'file' | 'dir';
|
|
34
|
+
bytes?: Uint8Array;
|
|
35
|
+
type?: string | null;
|
|
36
|
+
exists: boolean;
|
|
37
|
+
createdAt?: number;
|
|
38
|
+
modifiedAt?: number;
|
|
39
|
+
};
|
|
20
40
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
41
|
+
const store = new Map<string, Entry>();
|
|
42
|
+
|
|
43
|
+
const SEED_DIRS = [documentDirectory, cacheDirectory, bundleDirectory];
|
|
44
|
+
|
|
45
|
+
function seed() {
|
|
46
|
+
const t = nextMockTimestamp();
|
|
47
|
+
for (const uri of SEED_DIRS) {
|
|
48
|
+
store.set(normalizeKey(uri), { kind: 'dir', exists: true, createdAt: t, modifiedAt: t });
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Logical clock used for `createdAt` / `modifiedAt` on stored entries.
|
|
54
|
+
* Resetting the mock filesystem also resets it so each test sees a stable
|
|
55
|
+
* sequence of timestamps independent of wall-clock time.
|
|
56
|
+
*/
|
|
57
|
+
let mockClock = 0;
|
|
58
|
+
|
|
59
|
+
function nextMockTimestamp(): number {
|
|
60
|
+
return ++mockClock;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Test-only helper: reset the in-memory filesystem to a clean state with only
|
|
65
|
+
* the canonical `document`, `cache`, and `bundle` directories seeded.
|
|
66
|
+
* Call from a `beforeEach` to keep tests isolated.
|
|
67
|
+
*/
|
|
68
|
+
export function __resetMockFileSystem() {
|
|
69
|
+
store.clear();
|
|
70
|
+
listeners.clear();
|
|
71
|
+
cancelled.clear();
|
|
72
|
+
mockClock = 0;
|
|
73
|
+
seed();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
seed();
|
|
77
|
+
|
|
78
|
+
function normalizeKey(uri: string): string {
|
|
79
|
+
return uri.endsWith('/') ? uri.slice(0, -1) : uri;
|
|
80
|
+
}
|
|
27
81
|
|
|
28
|
-
|
|
82
|
+
function basename(uri: string): string {
|
|
83
|
+
const key = normalizeKey(uri);
|
|
84
|
+
const i = key.lastIndexOf('/');
|
|
85
|
+
return i === -1 ? key : key.slice(i + 1);
|
|
86
|
+
}
|
|
29
87
|
|
|
30
|
-
|
|
88
|
+
function parentOf(uri: string): string {
|
|
89
|
+
const key = normalizeKey(uri);
|
|
90
|
+
const i = key.lastIndexOf('/');
|
|
91
|
+
return i === -1 ? '' : key.slice(0, i);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function joinUri(dir: string, name: string): string {
|
|
95
|
+
const base = normalizeKey(dir);
|
|
96
|
+
return `${base}/${name}`;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function utf8Encode(s: string): Uint8Array {
|
|
100
|
+
return new TextEncoder().encode(s);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function utf8Decode(b: Uint8Array): string {
|
|
104
|
+
return new TextDecoder('utf-8').decode(b);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function base64Encode(bytes: Uint8Array): string {
|
|
108
|
+
return Buffer.from(bytes).toString('base64');
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function base64Decode(str: string): Uint8Array {
|
|
112
|
+
return new Uint8Array(Buffer.from(str, 'base64'));
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function fakeMd5(uri: string, size: number): string {
|
|
116
|
+
let h = 0x811c9dc5;
|
|
117
|
+
const src = `${uri}:${size}`;
|
|
118
|
+
for (let i = 0; i < src.length; i++) {
|
|
119
|
+
h = Math.imul(h ^ src.charCodeAt(i), 0x01000193);
|
|
120
|
+
}
|
|
121
|
+
const hex = (h >>> 0).toString(16).padStart(8, '0');
|
|
122
|
+
return hex.repeat(4).slice(0, 32);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const listeners = new Map<string, Set<(event: any) => void>>();
|
|
126
|
+
const cancelled = new Set<string>();
|
|
127
|
+
|
|
128
|
+
function emit(event: string, data: any) {
|
|
129
|
+
const set = listeners.get(event);
|
|
130
|
+
if (!set) return;
|
|
131
|
+
for (const fn of set) {
|
|
132
|
+
try {
|
|
133
|
+
fn(data);
|
|
134
|
+
} catch {
|
|
135
|
+
/* ignore listener errors in the mock */
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function addListener(event: string, handler: (data: any) => void) {
|
|
141
|
+
let set = listeners.get(event);
|
|
142
|
+
if (!set) {
|
|
143
|
+
set = new Set();
|
|
144
|
+
listeners.set(event, set);
|
|
145
|
+
}
|
|
146
|
+
set.add(handler);
|
|
147
|
+
return {
|
|
148
|
+
remove: () => {
|
|
149
|
+
set!.delete(handler);
|
|
150
|
+
},
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export function info(uri: string): { exists: boolean; isDirectory: boolean | null } {
|
|
155
|
+
const entry = store.get(normalizeKey(uri));
|
|
156
|
+
if (!entry || !entry.exists) return { exists: false, isDirectory: null };
|
|
157
|
+
return { exists: true, isDirectory: entry.kind === 'dir' };
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function assertParent(uri: string, allowMissing: boolean) {
|
|
161
|
+
const parent = normalizeKey(parentOf(uri));
|
|
162
|
+
if (!parent) return;
|
|
163
|
+
const entry = store.get(parent);
|
|
164
|
+
if (entry?.exists) return;
|
|
165
|
+
if (!allowMissing) {
|
|
166
|
+
throw new Error('Parent directory does not exist');
|
|
167
|
+
}
|
|
168
|
+
const missing: string[] = [];
|
|
169
|
+
let cursor = parent;
|
|
170
|
+
// Stop walking once we've peeled back to the scheme (e.g. "file://") so we
|
|
171
|
+
// don't seed nonsense keys above the root.
|
|
172
|
+
while (cursor && cursor.length >= 8 && !store.get(cursor)?.exists) {
|
|
173
|
+
missing.unshift(cursor);
|
|
174
|
+
const next = normalizeKey(parentOf(cursor));
|
|
175
|
+
if (next === cursor) break;
|
|
176
|
+
cursor = next;
|
|
177
|
+
}
|
|
178
|
+
const now = nextMockTimestamp();
|
|
179
|
+
for (const dirKey of missing) {
|
|
180
|
+
store.set(dirKey, { kind: 'dir', exists: true, createdAt: now, modifiedAt: now });
|
|
181
|
+
}
|
|
182
|
+
}
|
|
31
183
|
|
|
32
|
-
export function cancelDownloadAsync(uuid: string): void {}
|
|
33
184
|
export class FileSystemFile {
|
|
34
185
|
uri: string;
|
|
35
|
-
|
|
186
|
+
|
|
36
187
|
constructor(uri: string) {
|
|
37
188
|
this.uri = uri;
|
|
38
189
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
190
|
+
|
|
191
|
+
validatePath(): void {}
|
|
192
|
+
|
|
193
|
+
get exists(): boolean {
|
|
194
|
+
const entry = store.get(normalizeKey(this.uri));
|
|
195
|
+
return !!(entry && entry.kind === 'file' && entry.exists);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
get size(): number {
|
|
199
|
+
const entry = store.get(normalizeKey(this.uri));
|
|
200
|
+
return entry && entry.kind === 'file' && entry.exists ? (entry.bytes?.length ?? 0) : 0;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
get type(): string {
|
|
204
|
+
const entry = store.get(normalizeKey(this.uri));
|
|
205
|
+
return entry?.type ?? '';
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
get md5(): string | null {
|
|
209
|
+
return this.exists ? fakeMd5(this.uri, this.size) : null;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
get modificationTime(): number | null {
|
|
213
|
+
const entry = store.get(normalizeKey(this.uri));
|
|
214
|
+
return entry?.exists ? (entry.modifiedAt ?? null) : null;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
get lastModified(): number | null {
|
|
218
|
+
return this.modificationTime;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
get creationTime(): number | null {
|
|
222
|
+
const entry = store.get(normalizeKey(this.uri));
|
|
223
|
+
return entry?.exists ? (entry.createdAt ?? null) : null;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
get contentUri(): string {
|
|
227
|
+
return '';
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
create(options: { intermediates?: boolean; overwrite?: boolean } = {}): void {
|
|
231
|
+
const key = normalizeKey(this.uri);
|
|
232
|
+
const existing = store.get(key);
|
|
233
|
+
if (existing?.exists) {
|
|
234
|
+
if (!options.overwrite) {
|
|
235
|
+
throw new Error('File already exists');
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
assertParent(this.uri, !!options.intermediates);
|
|
239
|
+
const now = nextMockTimestamp();
|
|
240
|
+
store.set(key, {
|
|
241
|
+
kind: 'file',
|
|
242
|
+
bytes: new Uint8Array(0),
|
|
243
|
+
exists: true,
|
|
244
|
+
createdAt: now,
|
|
245
|
+
modifiedAt: now,
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
write(
|
|
250
|
+
content: string | Uint8Array,
|
|
251
|
+
options: { append?: boolean; encoding?: 'utf8' | 'base64' } = {}
|
|
252
|
+
): void {
|
|
253
|
+
assertParent(this.uri, false);
|
|
254
|
+
let bytes: Uint8Array;
|
|
255
|
+
if (typeof content === 'string') {
|
|
256
|
+
bytes = options.encoding === 'base64' ? base64Decode(content) : utf8Encode(content);
|
|
257
|
+
} else {
|
|
258
|
+
bytes = new Uint8Array(content);
|
|
259
|
+
}
|
|
260
|
+
const key = normalizeKey(this.uri);
|
|
261
|
+
const existing = store.get(key);
|
|
262
|
+
const now = nextMockTimestamp();
|
|
263
|
+
const createdAt = existing?.exists ? (existing.createdAt ?? now) : now;
|
|
264
|
+
const type = existing?.type ?? null;
|
|
265
|
+
if (options.append) {
|
|
266
|
+
const prior = existing?.bytes ?? new Uint8Array(0);
|
|
267
|
+
const merged = new Uint8Array(prior.length + bytes.length);
|
|
268
|
+
merged.set(prior, 0);
|
|
269
|
+
merged.set(bytes, prior.length);
|
|
270
|
+
store.set(key, {
|
|
271
|
+
kind: 'file',
|
|
272
|
+
bytes: merged,
|
|
273
|
+
type,
|
|
274
|
+
exists: true,
|
|
275
|
+
createdAt,
|
|
276
|
+
modifiedAt: now,
|
|
277
|
+
});
|
|
278
|
+
} else {
|
|
279
|
+
store.set(key, { kind: 'file', bytes, type, exists: true, createdAt, modifiedAt: now });
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
private readBytesOrThrow(): Uint8Array {
|
|
284
|
+
const entry = store.get(normalizeKey(this.uri));
|
|
285
|
+
if (!entry || entry.kind !== 'file' || !entry.exists) {
|
|
286
|
+
throw new Error('File does not exist');
|
|
287
|
+
}
|
|
288
|
+
return entry.bytes ?? new Uint8Array(0);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
textSync(): string {
|
|
292
|
+
return utf8Decode(this.readBytesOrThrow());
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
base64Sync(): string {
|
|
296
|
+
return base64Encode(this.readBytesOrThrow());
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
bytesSync(): Uint8Array {
|
|
300
|
+
return new Uint8Array(this.readBytesOrThrow());
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
async text(): Promise<string> {
|
|
304
|
+
return this.textSync();
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
async base64(): Promise<string> {
|
|
308
|
+
return this.base64Sync();
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
async bytes(): Promise<Uint8Array> {
|
|
312
|
+
return this.bytesSync();
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
info(options: { md5?: boolean } = {}): any {
|
|
316
|
+
const entry = store.get(normalizeKey(this.uri));
|
|
317
|
+
if (!entry || entry.kind !== 'file' || !entry.exists) {
|
|
318
|
+
return { exists: false, uri: this.uri };
|
|
319
|
+
}
|
|
320
|
+
const size = entry.bytes?.length ?? 0;
|
|
321
|
+
return {
|
|
322
|
+
exists: true,
|
|
323
|
+
uri: this.uri,
|
|
324
|
+
size,
|
|
325
|
+
modificationTime: entry.modifiedAt ?? null,
|
|
326
|
+
creationTime: entry.createdAt ?? null,
|
|
327
|
+
...(options.md5 ? { md5: fakeMd5(this.uri, size) } : {}),
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
open(mode?: FileMode): FileSystemFileHandle {
|
|
332
|
+
const key = normalizeKey(this.uri);
|
|
333
|
+
const entry = store.get(key);
|
|
334
|
+
if (!entry || entry.kind !== 'file' || !entry.exists) {
|
|
335
|
+
throw new Error('File does not exist');
|
|
336
|
+
}
|
|
337
|
+
return new FileSystemFileHandle(key, mode ?? defaultModeForUri(this.uri));
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
delete(): void {
|
|
341
|
+
const key = normalizeKey(this.uri);
|
|
342
|
+
const entry = store.get(key);
|
|
343
|
+
if (!entry || !entry.exists) {
|
|
344
|
+
throw new Error('File does not exist');
|
|
345
|
+
}
|
|
346
|
+
store.delete(key);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
private resolveDestination(destination: FileSystemFile | FileSystemDirectory): string {
|
|
350
|
+
if (destination instanceof FileSystemDirectory) {
|
|
351
|
+
return joinUri(destination.uri, basename(this.uri));
|
|
352
|
+
}
|
|
353
|
+
return normalizeKey(destination.uri);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
copySync(
|
|
357
|
+
destination: FileSystemFile | FileSystemDirectory,
|
|
358
|
+
options: { overwrite?: boolean } = {}
|
|
359
|
+
): void {
|
|
360
|
+
const srcKey = normalizeKey(this.uri);
|
|
361
|
+
const entry = store.get(srcKey);
|
|
362
|
+
if (!entry || entry.kind !== 'file' || !entry.exists) {
|
|
363
|
+
throw new Error('File does not exist');
|
|
364
|
+
}
|
|
365
|
+
const destKey = this.resolveDestination(destination);
|
|
366
|
+
const destExisting = store.get(destKey);
|
|
367
|
+
if (destExisting?.exists && !options.overwrite) {
|
|
368
|
+
throw new Error('Destination already exists');
|
|
369
|
+
}
|
|
370
|
+
assertParent(destKey, false);
|
|
371
|
+
const now = nextMockTimestamp();
|
|
372
|
+
store.set(destKey, {
|
|
373
|
+
kind: 'file',
|
|
374
|
+
bytes: new Uint8Array(entry.bytes ?? new Uint8Array(0)),
|
|
375
|
+
type: entry.type ?? null,
|
|
376
|
+
exists: true,
|
|
377
|
+
createdAt: now,
|
|
378
|
+
modifiedAt: now,
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
async copy(
|
|
383
|
+
destination: FileSystemFile | FileSystemDirectory,
|
|
384
|
+
options: { overwrite?: boolean } = {}
|
|
385
|
+
): Promise<void> {
|
|
386
|
+
this.copySync(destination, options);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
moveSync(
|
|
390
|
+
destination: FileSystemFile | FileSystemDirectory,
|
|
391
|
+
options: { overwrite?: boolean } = {}
|
|
392
|
+
): void {
|
|
393
|
+
const srcKey = normalizeKey(this.uri);
|
|
394
|
+
this.copySync(destination, options);
|
|
395
|
+
const destKey = this.resolveDestination(destination);
|
|
396
|
+
if (destKey !== srcKey) {
|
|
397
|
+
store.delete(srcKey);
|
|
398
|
+
}
|
|
399
|
+
this.uri = destKey;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
async move(
|
|
403
|
+
destination: FileSystemFile | FileSystemDirectory,
|
|
404
|
+
options: { overwrite?: boolean } = {}
|
|
405
|
+
): Promise<void> {
|
|
406
|
+
this.moveSync(destination, options);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
rename(newName: string): void {
|
|
410
|
+
const srcKey = normalizeKey(this.uri);
|
|
411
|
+
const entry = store.get(srcKey);
|
|
412
|
+
if (!entry || !entry.exists) {
|
|
413
|
+
throw new Error('File does not exist');
|
|
414
|
+
}
|
|
415
|
+
const destKey = joinUri(parentOf(this.uri), newName);
|
|
416
|
+
store.set(destKey, entry);
|
|
417
|
+
store.delete(srcKey);
|
|
418
|
+
this.uri = destKey;
|
|
419
|
+
}
|
|
420
|
+
|
|
56
421
|
watch(_callback: any, _options?: any): { remove: () => void } {
|
|
57
422
|
return { remove: () => {} };
|
|
58
423
|
}
|
|
59
424
|
}
|
|
60
425
|
|
|
61
426
|
export class FileSystemFileHandle {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
427
|
+
private readonly key: string;
|
|
428
|
+
private readonly readOnly: boolean;
|
|
429
|
+
private readonly writeOnly: boolean;
|
|
430
|
+
private cursor: number;
|
|
431
|
+
private closed = false;
|
|
432
|
+
|
|
433
|
+
constructor(key: string, mode: FileMode) {
|
|
434
|
+
this.key = key;
|
|
435
|
+
const entry = store.get(key);
|
|
436
|
+
switch (mode) {
|
|
437
|
+
case FileMode.ReadWrite:
|
|
438
|
+
this.readOnly = false;
|
|
439
|
+
this.writeOnly = false;
|
|
440
|
+
this.cursor = 0;
|
|
441
|
+
break;
|
|
442
|
+
case FileMode.ReadOnly:
|
|
443
|
+
this.readOnly = true;
|
|
444
|
+
this.writeOnly = false;
|
|
445
|
+
this.cursor = 0;
|
|
446
|
+
break;
|
|
447
|
+
case FileMode.WriteOnly:
|
|
448
|
+
this.readOnly = false;
|
|
449
|
+
this.writeOnly = true;
|
|
450
|
+
this.cursor = 0;
|
|
451
|
+
break;
|
|
452
|
+
case FileMode.Append:
|
|
453
|
+
this.readOnly = false;
|
|
454
|
+
this.writeOnly = true;
|
|
455
|
+
this.cursor = entry?.bytes?.length ?? 0;
|
|
456
|
+
break;
|
|
457
|
+
case FileMode.Truncate:
|
|
458
|
+
this.readOnly = false;
|
|
459
|
+
this.writeOnly = true;
|
|
460
|
+
store.set(key, {
|
|
461
|
+
kind: 'file',
|
|
462
|
+
bytes: new Uint8Array(0),
|
|
463
|
+
type: entry?.type ?? null,
|
|
464
|
+
exists: true,
|
|
465
|
+
createdAt: entry?.createdAt ?? nextMockTimestamp(),
|
|
466
|
+
modifiedAt: nextMockTimestamp(),
|
|
467
|
+
});
|
|
468
|
+
this.cursor = 0;
|
|
469
|
+
break;
|
|
470
|
+
default:
|
|
471
|
+
assertNever(mode);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
private ensureOpen() {
|
|
476
|
+
if (this.closed) throw new Error('File handle is closed');
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
get offset(): number | null {
|
|
480
|
+
return this.closed ? null : this.cursor;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
set offset(value: number | null) {
|
|
484
|
+
if (this.closed || value == null) {
|
|
485
|
+
return;
|
|
486
|
+
}
|
|
487
|
+
this.cursor = value;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
get size(): number | null {
|
|
491
|
+
if (this.closed) {
|
|
492
|
+
return null;
|
|
493
|
+
}
|
|
494
|
+
const entry = store.get(this.key);
|
|
495
|
+
return entry?.bytes?.length ?? 0;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
readBytes(count: number): Uint8Array {
|
|
499
|
+
this.ensureOpen();
|
|
500
|
+
if (this.writeOnly) throw new Error('File handle is write-only');
|
|
501
|
+
const entry = store.get(this.key);
|
|
502
|
+
const bytes = entry?.bytes ?? new Uint8Array(0);
|
|
503
|
+
const slice = bytes.slice(this.cursor, this.cursor + count);
|
|
504
|
+
this.cursor += slice.length;
|
|
505
|
+
return slice;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
writeBytes(buffer: Uint8Array): void {
|
|
509
|
+
this.ensureOpen();
|
|
510
|
+
if (this.readOnly) throw new Error('File handle is read-only');
|
|
511
|
+
const entry = store.get(this.key) ?? {
|
|
512
|
+
kind: 'file' as const,
|
|
513
|
+
bytes: new Uint8Array(0),
|
|
514
|
+
exists: true,
|
|
515
|
+
};
|
|
516
|
+
const prior = entry.bytes ?? new Uint8Array(0);
|
|
517
|
+
const writeOffset = Math.min(this.cursor, prior.length);
|
|
518
|
+
const newLength = Math.max(prior.length, writeOffset + buffer.length);
|
|
519
|
+
const merged = new Uint8Array(newLength);
|
|
520
|
+
merged.set(prior, 0);
|
|
521
|
+
merged.set(buffer, writeOffset);
|
|
522
|
+
store.set(this.key, {
|
|
523
|
+
...entry,
|
|
524
|
+
kind: 'file',
|
|
525
|
+
bytes: merged,
|
|
526
|
+
exists: true,
|
|
527
|
+
modifiedAt: nextMockTimestamp(),
|
|
528
|
+
});
|
|
529
|
+
this.cursor = writeOffset + buffer.length;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
close(): void {
|
|
533
|
+
this.closed = true;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
function assertNever(value: never): never {
|
|
538
|
+
throw new Error(`Unhandled FileMode in jest-expo mock: ${String(value)}`);
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
function defaultModeForUri(uri: string): FileMode {
|
|
542
|
+
return uri.startsWith('content://') ? FileMode.ReadOnly : FileMode.ReadWrite;
|
|
65
543
|
}
|
|
66
544
|
|
|
67
545
|
export class FileSystemDirectory {
|
|
68
546
|
uri: string;
|
|
69
|
-
|
|
547
|
+
|
|
70
548
|
constructor(uri: string) {
|
|
71
549
|
this.uri = uri;
|
|
72
550
|
}
|
|
73
|
-
|
|
74
|
-
validatePath():
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
551
|
+
|
|
552
|
+
validatePath(): void {}
|
|
553
|
+
|
|
554
|
+
get exists(): boolean {
|
|
555
|
+
const entry = store.get(normalizeKey(this.uri));
|
|
556
|
+
return !!(entry && entry.kind === 'dir' && entry.exists);
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
get size(): number | null {
|
|
560
|
+
const entry = store.get(normalizeKey(this.uri));
|
|
561
|
+
if (!entry || entry.kind !== 'dir' || !entry.exists) {
|
|
562
|
+
return null;
|
|
563
|
+
}
|
|
564
|
+
const prefix = `${normalizeKey(this.uri)}/`;
|
|
565
|
+
let total = 0;
|
|
566
|
+
for (const [key, e] of store) {
|
|
567
|
+
if (!e.exists || e.kind !== 'file' || !key.startsWith(prefix)) continue;
|
|
568
|
+
total += e.bytes?.length ?? 0;
|
|
569
|
+
}
|
|
570
|
+
return total;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
info(): any {
|
|
574
|
+
const entry = store.get(normalizeKey(this.uri));
|
|
575
|
+
if (!entry || entry.kind !== 'dir' || !entry.exists) {
|
|
576
|
+
return { exists: false, uri: this.uri };
|
|
577
|
+
}
|
|
578
|
+
return {
|
|
579
|
+
exists: true,
|
|
580
|
+
uri: this.uri,
|
|
581
|
+
files: directChildren(this.uri).map((child) => basename(child.uri)),
|
|
582
|
+
size: this.size,
|
|
583
|
+
modificationTime: entry.modifiedAt ?? null,
|
|
584
|
+
creationTime: entry.createdAt ?? null,
|
|
585
|
+
};
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
create(
|
|
589
|
+
options: { intermediates?: boolean; idempotent?: boolean; overwrite?: boolean } = {}
|
|
590
|
+
): void {
|
|
591
|
+
const key = normalizeKey(this.uri);
|
|
592
|
+
const existing = store.get(key);
|
|
593
|
+
if (existing?.exists) {
|
|
594
|
+
if (options.idempotent) return;
|
|
595
|
+
if (!options.overwrite) {
|
|
596
|
+
throw new Error('Directory already exists');
|
|
597
|
+
}
|
|
598
|
+
deleteSubtree(key);
|
|
599
|
+
}
|
|
600
|
+
assertParent(this.uri, !!options.intermediates);
|
|
601
|
+
const now = nextMockTimestamp();
|
|
602
|
+
store.set(key, { kind: 'dir', exists: true, createdAt: now, modifiedAt: now });
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
delete(): void {
|
|
606
|
+
const key = normalizeKey(this.uri);
|
|
607
|
+
const entry = store.get(key);
|
|
608
|
+
if (!entry || !entry.exists) {
|
|
609
|
+
throw new Error('Directory does not exist');
|
|
610
|
+
}
|
|
611
|
+
deleteSubtree(key);
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
listAsRecords(): { isDirectory: boolean; uri: string }[] {
|
|
615
|
+
const entry = store.get(normalizeKey(this.uri));
|
|
616
|
+
if (!entry || entry.kind !== 'dir' || !entry.exists) {
|
|
617
|
+
throw new Error('Directory does not exist');
|
|
618
|
+
}
|
|
619
|
+
return directChildren(this.uri).map(({ uri, kind }) => ({
|
|
620
|
+
isDirectory: kind === 'dir',
|
|
621
|
+
uri,
|
|
622
|
+
}));
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
createFile(name: string, mimeType: string | null): FileSystemFile {
|
|
626
|
+
const parentKey = normalizeKey(this.uri);
|
|
627
|
+
const parent = store.get(parentKey);
|
|
628
|
+
if (!parent || parent.kind !== 'dir' || !parent.exists) {
|
|
629
|
+
throw new Error('Parent directory does not exist');
|
|
630
|
+
}
|
|
631
|
+
const childKey = joinUri(this.uri, name);
|
|
632
|
+
if (store.get(childKey)?.exists) {
|
|
633
|
+
throw new Error('File already exists');
|
|
634
|
+
}
|
|
635
|
+
const now = nextMockTimestamp();
|
|
636
|
+
store.set(childKey, {
|
|
637
|
+
kind: 'file',
|
|
638
|
+
bytes: new Uint8Array(0),
|
|
639
|
+
type: mimeType ?? null,
|
|
640
|
+
exists: true,
|
|
641
|
+
createdAt: now,
|
|
642
|
+
modifiedAt: now,
|
|
643
|
+
});
|
|
644
|
+
return new FileSystemFile(childKey);
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
createDirectory(name: string): FileSystemDirectory {
|
|
648
|
+
const parentKey = normalizeKey(this.uri);
|
|
649
|
+
const parent = store.get(parentKey);
|
|
650
|
+
if (!parent || parent.kind !== 'dir' || !parent.exists) {
|
|
651
|
+
throw new Error('Parent directory does not exist');
|
|
652
|
+
}
|
|
653
|
+
const childKey = joinUri(this.uri, name);
|
|
654
|
+
if (store.get(childKey)?.exists) {
|
|
655
|
+
throw new Error('Directory already exists');
|
|
656
|
+
}
|
|
657
|
+
const now = nextMockTimestamp();
|
|
658
|
+
store.set(childKey, { kind: 'dir', exists: true, createdAt: now, modifiedAt: now });
|
|
659
|
+
return new FileSystemDirectory(childKey);
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
private resolveDestination(destination: FileSystemFile | FileSystemDirectory): string {
|
|
663
|
+
if (destination instanceof FileSystemDirectory) {
|
|
664
|
+
return joinUri(destination.uri, basename(this.uri));
|
|
665
|
+
}
|
|
666
|
+
return normalizeKey(destination.uri);
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
copySync(
|
|
670
|
+
destination: FileSystemFile | FileSystemDirectory,
|
|
671
|
+
options: { overwrite?: boolean } = {}
|
|
672
|
+
): void {
|
|
673
|
+
const srcKey = normalizeKey(this.uri);
|
|
674
|
+
const entry = store.get(srcKey);
|
|
675
|
+
if (!entry || entry.kind !== 'dir' || !entry.exists) {
|
|
676
|
+
throw new Error('Directory does not exist');
|
|
677
|
+
}
|
|
678
|
+
const destKey = this.resolveDestination(destination);
|
|
679
|
+
const destExisting = store.get(destKey);
|
|
680
|
+
if (destExisting?.exists && !options.overwrite) {
|
|
681
|
+
throw new Error('Destination already exists');
|
|
682
|
+
}
|
|
683
|
+
assertParent(destKey, false);
|
|
684
|
+
copySubtree(srcKey, destKey);
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
async copy(
|
|
688
|
+
destination: FileSystemFile | FileSystemDirectory,
|
|
689
|
+
options: { overwrite?: boolean } = {}
|
|
690
|
+
): Promise<void> {
|
|
691
|
+
this.copySync(destination, options);
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
moveSync(
|
|
695
|
+
destination: FileSystemFile | FileSystemDirectory,
|
|
696
|
+
options: { overwrite?: boolean } = {}
|
|
697
|
+
): void {
|
|
698
|
+
const srcKey = normalizeKey(this.uri);
|
|
699
|
+
this.copySync(destination, options);
|
|
700
|
+
const destKey = this.resolveDestination(destination);
|
|
701
|
+
if (destKey !== srcKey) {
|
|
702
|
+
deleteSubtree(srcKey);
|
|
703
|
+
}
|
|
704
|
+
this.uri = destKey;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
async move(
|
|
708
|
+
destination: FileSystemFile | FileSystemDirectory,
|
|
709
|
+
options: { overwrite?: boolean } = {}
|
|
710
|
+
): Promise<void> {
|
|
711
|
+
this.moveSync(destination, options);
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
rename(newName: string): void {
|
|
715
|
+
const srcKey = normalizeKey(this.uri);
|
|
716
|
+
const entry = store.get(srcKey);
|
|
717
|
+
if (!entry || !entry.exists) {
|
|
718
|
+
throw new Error('Directory does not exist');
|
|
719
|
+
}
|
|
720
|
+
const destKey = joinUri(parentOf(this.uri), newName);
|
|
721
|
+
copySubtree(srcKey, destKey);
|
|
722
|
+
deleteSubtree(srcKey);
|
|
723
|
+
this.uri = destKey;
|
|
724
|
+
}
|
|
725
|
+
|
|
85
726
|
watch(_callback: any, _options?: any): { remove: () => void } {
|
|
86
727
|
return { remove: () => {} };
|
|
87
728
|
}
|
|
@@ -135,3 +776,98 @@ export class FileSystemDownloadTask extends SharedObject {
|
|
|
135
776
|
}
|
|
136
777
|
cancel(): void {}
|
|
137
778
|
}
|
|
779
|
+
|
|
780
|
+
function directChildren(dirUri: string): { uri: string; kind: 'file' | 'dir' }[] {
|
|
781
|
+
const prefix = `${normalizeKey(dirUri)}/`;
|
|
782
|
+
const result: { uri: string; kind: 'file' | 'dir' }[] = [];
|
|
783
|
+
for (const [key, entry] of store) {
|
|
784
|
+
if (!entry.exists || !key.startsWith(prefix)) continue;
|
|
785
|
+
const tail = key.slice(prefix.length);
|
|
786
|
+
if (tail.length === 0 || tail.includes('/')) continue;
|
|
787
|
+
result.push({ uri: key, kind: entry.kind });
|
|
788
|
+
}
|
|
789
|
+
return result;
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
function deleteSubtree(rootKey: string) {
|
|
793
|
+
const prefix = `${rootKey}/`;
|
|
794
|
+
const keys: string[] = [rootKey];
|
|
795
|
+
for (const key of store.keys()) {
|
|
796
|
+
if (key.startsWith(prefix)) keys.push(key);
|
|
797
|
+
}
|
|
798
|
+
for (const key of keys) store.delete(key);
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
function copySubtree(srcKey: string, destKey: string) {
|
|
802
|
+
const srcEntry = store.get(srcKey);
|
|
803
|
+
if (!srcEntry) return;
|
|
804
|
+
const now = nextMockTimestamp();
|
|
805
|
+
store.set(destKey, cloneEntry(srcEntry, now));
|
|
806
|
+
const prefix = `${srcKey}/`;
|
|
807
|
+
for (const [key, entry] of store) {
|
|
808
|
+
if (!key.startsWith(prefix)) continue;
|
|
809
|
+
const rewritten = destKey + key.slice(srcKey.length);
|
|
810
|
+
store.set(rewritten, cloneEntry(entry, now));
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
function cloneEntry(entry: Entry, timestamp: number): Entry {
|
|
815
|
+
return {
|
|
816
|
+
kind: entry.kind,
|
|
817
|
+
exists: entry.exists,
|
|
818
|
+
type: entry.type ?? null,
|
|
819
|
+
bytes: entry.bytes ? new Uint8Array(entry.bytes) : undefined,
|
|
820
|
+
createdAt: timestamp,
|
|
821
|
+
modifiedAt: timestamp,
|
|
822
|
+
};
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
export async function downloadFileAsync(
|
|
826
|
+
url: URL,
|
|
827
|
+
to: { uri: string } | undefined,
|
|
828
|
+
options: any,
|
|
829
|
+
uuid: string | undefined
|
|
830
|
+
): Promise<string> {
|
|
831
|
+
if (options?.signal?.aborted) {
|
|
832
|
+
const err = new Error(options.signal.reason ?? 'The operation was aborted.');
|
|
833
|
+
err.name = 'AbortError';
|
|
834
|
+
throw err;
|
|
835
|
+
}
|
|
836
|
+
const bytes = utf8Encode(`mock:${url}`);
|
|
837
|
+
const toUri = to?.uri ?? joinUri(cacheDirectory, basename(url));
|
|
838
|
+
const toEntry = store.get(normalizeKey(toUri));
|
|
839
|
+
const destKey = toEntry?.kind === 'dir' ? joinUri(toUri, basename(url)) : normalizeKey(toUri);
|
|
840
|
+
|
|
841
|
+
if (uuid) {
|
|
842
|
+
emit('downloadProgress', {
|
|
843
|
+
uuid,
|
|
844
|
+
data: { bytesWritten: bytes.length, totalBytes: bytes.length },
|
|
845
|
+
});
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
if (uuid && cancelled.has(uuid)) {
|
|
849
|
+
cancelled.delete(uuid);
|
|
850
|
+
const err = new Error('Download was cancelled.');
|
|
851
|
+
err.name = 'AbortError';
|
|
852
|
+
throw err;
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
const now = nextMockTimestamp();
|
|
856
|
+
store.set(destKey, { kind: 'file', bytes, exists: true, createdAt: now, modifiedAt: now });
|
|
857
|
+
return destKey;
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
export function cancelDownloadAsync(uuid: string): void {
|
|
861
|
+
cancelled.add(uuid);
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
export async function pickDirectoryAsync(_initialUri?: string): Promise<{ uri: string }> {
|
|
865
|
+
return { uri: 'file:///mock/picked/directory' };
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
export async function pickFileAsync(options?: any): Promise<any> {
|
|
869
|
+
if (options?.multipleFiles) {
|
|
870
|
+
return [{ uri: 'file:///mock/picked/file1.txt' }, { uri: 'file:///mock/picked/file2.txt' }];
|
|
871
|
+
}
|
|
872
|
+
return { uri: 'file:///mock/picked/file.txt' };
|
|
873
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-file-system",
|
|
3
|
-
"version": "56.0.
|
|
3
|
+
"version": "56.0.6",
|
|
4
4
|
"description": "Provides access to the local file system on the device.",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -41,15 +41,15 @@
|
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@types/node": "^22.14.0",
|
|
44
|
-
"expo": "56.0.0-preview.
|
|
45
|
-
"
|
|
46
|
-
"expo
|
|
44
|
+
"expo": "56.0.0-preview.13",
|
|
45
|
+
"expo-module-scripts": "56.0.2",
|
|
46
|
+
"jest-expo": "56.0.3"
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
49
|
"expo": "*",
|
|
50
50
|
"react-native": "*"
|
|
51
51
|
},
|
|
52
|
-
"gitHead": "
|
|
52
|
+
"gitHead": "290368bc41026449a05a4ebf991b85c3a2fb0e3a",
|
|
53
53
|
"scripts": {
|
|
54
54
|
"build": "expo-module build",
|
|
55
55
|
"clean": "expo-module clean",
|
|
Binary file
|
|
Binary file
|
package/src/Directory.ts
CHANGED
|
@@ -46,7 +46,6 @@ export class Directory extends ExpoFileSystem.FileSystemDirectory {
|
|
|
46
46
|
* @returns An array of `Directory` and `File` instances.
|
|
47
47
|
*/
|
|
48
48
|
override list(): (Directory | File)[] {
|
|
49
|
-
// We need to wrap it in the JS File/Directory classes, and returning SharedObjects in lists is not supported yet on Android.
|
|
50
49
|
return super
|
|
51
50
|
.listAsRecords()
|
|
52
51
|
.map(({ isDirectory, uri }) => (isDirectory ? new Directory(uri) : new File(uri)));
|
|
@@ -60,7 +59,6 @@ export class Directory extends ExpoFileSystem.FileSystemDirectory {
|
|
|
60
59
|
}
|
|
61
60
|
|
|
62
61
|
createFile(name: string, mimeType: string | null): File {
|
|
63
|
-
// Wrapping with the JS child class for additional, JS-only methods.
|
|
64
62
|
return new File(super.createFile(name, mimeType).uri);
|
|
65
63
|
}
|
|
66
64
|
|
package/src/File.ts
CHANGED
|
@@ -188,6 +188,16 @@ export class File extends ExpoFileSystem.FileSystemFile implements Blob {
|
|
|
188
188
|
return bytes.buffer as ArrayBuffer;
|
|
189
189
|
}
|
|
190
190
|
|
|
191
|
+
async json(): Promise<any> {
|
|
192
|
+
return JSON.parse(await this.text());
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
async formData(): ReturnType<Response['formData']> {
|
|
196
|
+
return new Response(await this.arrayBuffer(), {
|
|
197
|
+
headers: this.type ? { 'Content-Type': this.type } : undefined,
|
|
198
|
+
}).formData();
|
|
199
|
+
}
|
|
200
|
+
|
|
191
201
|
stream(): ReadableStream<Uint8Array<ArrayBuffer>> {
|
|
192
202
|
return this.readableStream();
|
|
193
203
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
a0a5362996a1b366e44ab25e7365155d
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
f3a782e868be5ed5b5ab4af6d32d9856d4d4f10e
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
3678bcfd9bb14d4dae6430960eafacb8e557d0b17791f7885a0d65a45b729c09
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
544b1afe9f85ee8b4e8378e9a776f9172cca4608192830f051d53e15f015ffa7dc58189441844830f44753118f93f977651ea699e4c885706b7acb01b0dc3e16
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
7962a6bfeb71b8072e4edc8adf3bbee2
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
22e97534bab70438f104e0b0dffaf03b1c0a53c7
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
ca778d7b49ef6a07be35dc52f1e80020087f4c3a5cf027abc4c25de93c3f8240
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
ce05a47311b5d94dba902ae5693fe5d385b79c29bcc999dc2493286b1e6babfb2b80ca81eac595ac8e590f211438e469a5d7fd410210905a73fe5c98e556de01
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|