@amazon-devices/expo-file-system 2.0.9000000000 → 3.0.0

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.
@@ -7,12 +7,21 @@
7
7
  */
8
8
  #pragma once
9
9
 
10
- #include <KeplerScript/modules/KeplerTurboModule.h>
10
+ #include <Kepler/turbomodule/KeplerTurboModule.h>
11
+ #include "expo-export.h"
11
12
 
12
- class KEPLERSCRIPT_EXPORT ExponentFileSystem : public volta::react::KeplerTurboModule {
13
+ #include <memory>
14
+
15
+ #include "CurlWrapper.h"
16
+
17
+ class EXPO_EXPORT ExponentFileSystem : public com::amazon::kepler::turbomodule::KeplerTurboModule {
13
18
  public:
14
19
  ExponentFileSystem();
15
20
 
21
+ void aggregateMethods(
22
+ com::amazon::kepler::turbomodule::MethodAggregator<com::amazon::kepler::turbomodule::KeplerTurboModule>&
23
+ methodAggregator) const noexcept override;
24
+
16
25
  #ifndef UNIT_TEST
17
26
  protected:
18
27
  #endif
@@ -20,41 +29,47 @@ protected:
20
29
  std::string cacheDirectory();
21
30
  std::string bundleDirectory();
22
31
 
23
- volta::react::Promise getInfoAsync(const std::string fileUri, volta::react::NativeJSObject options);
24
- volta::react::Promise readAsStringAsync(const std::string fileUri, volta::react::NativeJSObject options);
25
- volta::react::Promise getContentUriAsync(const std::string fileUri);
26
- volta::react::Promise writeAsStringAsync(
32
+ com::amazon::kepler::turbomodule::Promise getInfoAsync(
33
+ const std::string fileUri,
34
+ com::amazon::kepler::turbomodule::NativeJSObject options);
35
+ com::amazon::kepler::turbomodule::Promise readAsStringAsync(
36
+ const std::string fileUri,
37
+ com::amazon::kepler::turbomodule::NativeJSObject options);
38
+ com::amazon::kepler::turbomodule::Promise getContentUriAsync(const std::string fileUri);
39
+ com::amazon::kepler::turbomodule::Promise writeAsStringAsync(
27
40
  const std::string fileUri,
28
41
  const std::string contents,
29
- volta::react::NativeJSObject options);
30
- volta::react::Promise writeArrayBufferAsync(
31
- const std::string fileUri,
32
- const volta::react::ArrayBuffer arrayBuffer);
33
- volta::react::Promise deleteAsync(const std::string fileUri, volta::react::NativeJSObject options);
34
- volta::react::Promise moveAsync(volta::react::NativeJSObject options);
35
- volta::react::Promise copyAsync(volta::react::NativeJSObject options);
36
- volta::react::Promise makeDirectoryAsync(const std::string fileUri, volta::react::NativeJSObject options);
37
- volta::react::Promise readDirectoryAsync(const std::string fileUri);
38
- volta::react::Promise getFreeDiskStorageAsync();
39
- volta::react::Promise getTotalDiskCapacityAsync();
40
- volta::react::Promise downloadAsync(
42
+ com::amazon::kepler::turbomodule::NativeJSObject options);
43
+ com::amazon::kepler::turbomodule::Promise writeArrayBufferAsync(
44
+ const std::string fileUri,
45
+ const com::amazon::kepler::turbomodule::ArrayBuffer arrayBuffer);
46
+ com::amazon::kepler::turbomodule::Promise deleteAsync(
47
+ const std::string fileUri,
48
+ com::amazon::kepler::turbomodule::NativeJSObject options);
49
+ com::amazon::kepler::turbomodule::Promise moveAsync(com::amazon::kepler::turbomodule::NativeJSObject options);
50
+ com::amazon::kepler::turbomodule::Promise copyAsync(com::amazon::kepler::turbomodule::NativeJSObject options);
51
+ com::amazon::kepler::turbomodule::Promise makeDirectoryAsync(
52
+ const std::string fileUri,
53
+ com::amazon::kepler::turbomodule::NativeJSObject options);
54
+ com::amazon::kepler::turbomodule::Promise readDirectoryAsync(const std::string fileUri);
55
+ com::amazon::kepler::turbomodule::Promise getFreeDiskStorageAsync();
56
+ com::amazon::kepler::turbomodule::Promise getTotalDiskCapacityAsync();
57
+ com::amazon::kepler::turbomodule::Promise downloadAsync(
41
58
  const std::string url,
42
59
  const std::string fileUri,
43
- volta::react::NativeJSObject options,
60
+ com::amazon::kepler::turbomodule::NativeJSObject options,
44
61
  double requestId,
45
62
  std::vector<utils::json::JsonContainer> headers);
46
- volta::react::Promise uploadAsync(
63
+ com::amazon::kepler::turbomodule::Promise uploadAsync(
47
64
  const std::string url,
48
65
  const std::string fileUri,
49
- volta::react::NativeJSObject options,
66
+ com::amazon::kepler::turbomodule::NativeJSObject options,
50
67
  double requestId,
51
68
  std::vector<utils::json::JsonContainer> headers);
52
69
 
53
- void aggregateMethods(
54
- volta::react::MethodAggregator<volta::react::KeplerTurboModule>& methodAggregator) const noexcept override;
55
-
56
70
  private:
57
71
  static constexpr int DIRECTORY_SIZE = 4096;
58
72
 
59
73
  std::uintmax_t getSize(const std::string& path);
74
+ std::unique_ptr<CurlWrapper> curlWrapper_;
60
75
  };
@@ -6,20 +6,15 @@
6
6
  * Use is subject to license terms.
7
7
  */
8
8
 
9
- #include <KeplerScript/logger/KPLog.h>
10
- #include <KeplerScript/utils/autolink/KeplerAutoLinkInfo.h>
11
- #include <keplerui-072/keplerscript-export.h>
9
+ #include <Kepler/turbomodule/KeplerTurboModuleRegistration.h>
10
+ #include <Kepler/turbomodule/TMLog.h>
12
11
 
13
12
  #include "ExponentFileSystem.h"
14
- #include "RegisterModule.h"
15
13
 
16
14
  extern "C" {
17
- KEPLERSCRIPT_EXPORT void keplerAutoLinkInitV1(const kepler::autolink::v1::KeplerAutoLinkInfo* autoLinkInfo) noexcept {
18
- volta::react::KPLog.debug("keplerAutoLinkInitV1 for ExponentFileSystem");
19
-
20
- REGISTER_MODULE(autoLinkInfo, ExponentFileSystem, "ExponentFileSystem");
21
-
22
- volta::react::KPLog.debug("after registering module");
15
+ __attribute__((visibility("default"))) void autoLinkKeplerTurboModulesV1() noexcept {
16
+ TMDEBUG("autoLinkKeplerTurboModulesV1 for expo-file-system");
17
+ KEPLER_REGISTER_TURBO_MODULE_WITH_NAME("ExponentFileSystemAppTM", ExponentFileSystem);
23
18
  }
24
19
  }
25
20
 
package/package.json CHANGED
@@ -1 +1 @@
1
- {"name": "@amazon-devices/expo-file-system", "version": "2.0.9000000000+15.8.0", "description": "Provides access to the local file system on the device.", "main": "build/index.js", "types": "build/index.d.ts", "sideEffects": false, "scripts": {"build": "expo-module build", "clean": "expo-module clean", "lint": "expo-module lint", "test": "expo-module test", "prepublishOnly": "expo-module prepublishOnly", "expo-module": "expo-module"}, "kepler": {"temporary-alias-for-package": {"name": "expo-file-system", "version": "15.8.0"}}, "keywords": ["react-native", "expo", "file-system", "file"], "repository": {"type": "git", "url": "https://github.com/expo/expo.git", "directory": "packages/expo-file-system"}, "bugs": {"url": "https://github.com/expo/expo/issues"}, "author": "650 Industries, Inc.", "license": "See license in LICENSE", "homepage": "https://docs.expo.dev/versions/latest/sdk/filesystem/", "dependencies": {"uuid": "^3.4.0", "@amazon-devices/keplerscript-turbomodule-api": "^1.0.0"}, "devDependencies": {"expo-module-scripts": "^3.0.0", "jest-expo": "~50.0.0-alpha.0", "@types/glob": "^7.2.0", "@types/minimatch": "^3.0.5"}, "peerDependencies": {"expo": "*"}}
1
+ {"name": "@amazon-devices/expo-file-system", "version": "3.0.0+15.8.0", "description": "Provides access to the local file system on the device.", "main": "build/index.js", "types": "build/index.d.ts", "sideEffects": false, "scripts": {"build": "expo-module build", "clean": "expo-module clean", "lint": "expo-module lint", "test": "expo-module test", "prepublishOnly": "expo-module prepublishOnly", "expo-module": "expo-module"}, "kepler": {"temporary-alias-for-package": {"name": "expo-file-system", "version": "15.8.0"}}, "keywords": ["react-native", "expo", "file-system", "file"], "repository": {"type": "git", "url": "https://github.com/expo/expo.git", "directory": "packages/expo-file-system"}, "bugs": {"url": "https://github.com/expo/expo/issues"}, "author": "650 Industries, Inc.", "license": "See license in LICENSE", "homepage": "https://docs.expo.dev/versions/latest/sdk/filesystem/", "dependencies": {"uuid": "^3.4.0", "@amazon-devices/keplerscript-turbomodule-api": "^1.0.0"}, "devDependencies": {"expo-module-scripts": "^3.0.0", "jest-expo": "~50.0.0-alpha.0", "@types/glob": "^7.2.0", "@types/minimatch": "^3.0.5"}, "peerDependencies": {"expo": "^50.0.0-alpha.1"}}
@@ -10,9 +10,11 @@ module.exports = {
10
10
  platforms: {
11
11
  kepler: {
12
12
  autolink: {
13
- ExponentFileSystemLib: {
14
- provider: 'system',
15
- turbomodules: ['ExponentFileSystem'],
13
+ ExponentFileSystemAppLib: {
14
+ provider: 'application',
15
+ linkDynamic: true,
16
+ libraryName: 'libexpo-file-system-3.so',
17
+ turbomodules: ['ExponentFileSystemAppTM'],
16
18
  },
17
19
  },
18
20
  },
@@ -12,7 +12,6 @@ import {
12
12
  ReadingOptions,
13
13
  RelocatingOptions,
14
14
  WritingOptions,
15
- FileSystemHttpResult,
16
15
  } from './FileSystem.types';
17
16
  import { ExponentFileSystemModule } from './types';
18
17
 
@@ -36,22 +35,17 @@ interface Spec extends KeplerTurboModule {
36
35
  readonly readDirectoryAsync: (fileUri: string) => Promise<string[]>;
37
36
  readonly getFreeDiskStorageAsync: () => Promise<string>;
38
37
  readonly getTotalDiskCapacityAsync: () => Promise<string | undefined>;
38
+ readonly downloadAsync: (url: string, fileUri: string, options: Record<string, any>, requestId: number, headers: Array<{key: string, value: string}>) => Promise<FileSystemDownloadResult>;
39
+ readonly uploadAsync: (url: string, fileUri: string, options: Record<string, any>, requestId: number, headers: Array<{key: string, value: string}>) => Promise<FileSystemUploadResult>;
39
40
  }
40
41
 
41
- const nativeModule = TurboModuleRegistry.getEnforcing<Spec>('ExponentFileSystem') as Spec;
42
- const expoCryptoNativeModule = TurboModuleRegistry.getEnforcing<any>('ExpoCrypto');
42
+ const nativeModule = TurboModuleRegistry.getEnforcing<Spec>('ExponentFileSystemAppTM') as Spec;
43
43
 
44
- function getHeadersFromResponse(response: Response): FileSystemHttpResult['headers'] {
45
- const responseHeaders: FileSystemDownloadResult['headers'] = {};
46
- response.headers.forEach((value: string, key: string) => {
47
- responseHeaders[key] = value;
48
- })
49
- return responseHeaders;
50
- }
44
+ let _requestId = 1;
45
+ const generateRequestId = (): number => { return _requestId++; };
51
46
 
52
- function getMimeTypeFromHeaders(responseHeaders: FileSystemHttpResult['headers']): FileSystemHttpResult['mimeType'] {
53
- const contentTypeKey = Object.keys(responseHeaders).find((key) => key.toLowerCase() === "content-type");
54
- return contentTypeKey ? responseHeaders[contentTypeKey].split(';')[0] : null;
47
+ function toHeadersList(headers?: Record<string, string>): Array<{key: string, value: string}> {
48
+ return Object.entries(headers ?? {}).map(([key, value]) => ({ key, value }));
55
49
  }
56
50
 
57
51
  const module: ExponentFileSystemModule = {
@@ -108,57 +102,36 @@ const module: ExponentFileSystemModule = {
108
102
  return result ? parseInt(result) : 0;
109
103
  },
110
104
  async downloadAsync(url: string, fileUri: string, options: DownloadOptions): Promise<FileSystemDownloadResult> {
111
- const { headers, md5 } = options;
112
- const response = await fetch(url, { headers });
113
-
114
- if (!response.ok) {
115
- throw new Error('Failed to download the file!');
116
- }
117
-
118
- const data = await response.arrayBuffer();
119
-
120
- await nativeModule.writeArrayBufferAsync(fileUri, data);
121
-
122
- const responseHeaders = getHeadersFromResponse(response);
123
-
124
- let downloadResult: FileSystemDownloadResult = {
125
- uri: fileUri,
126
- headers: responseHeaders,
127
- status: response.status,
128
- mimeType: getMimeTypeFromHeaders(responseHeaders)
129
- };
130
-
131
- if (md5) {
132
- const md5ArrayBuffer = await expoCryptoNativeModule.digestAsync("MD5", data);
133
- downloadResult.md5 = [...new Uint8Array(md5ArrayBuffer)]
134
- .map(x => x.toString(16).padStart(2, '0'))
135
- .join('');
105
+ console.log("[ExponentFileSystem] downloadAsync: native streaming download via libcurl");
106
+ console.log(`DOWNLOAD URL: ${url}`);
107
+ console.log(`FILE URL: ${fileUri}`);
108
+
109
+ try {
110
+ const result = await nativeModule.downloadAsync(url, fileUri, {
111
+ md5: options.md5 ?? false,
112
+ }, generateRequestId(), toHeadersList(options.headers));
113
+
114
+ return result as FileSystemDownloadResult;
115
+ } catch (error: any) {
116
+ console.error("[ExponentFileSystem] Download failed:", error?.message);
117
+ const message = error?.message ?? JSON.stringify(error);
118
+ throw new Error(`Download failed: ${message}`);
136
119
  }
137
-
138
- return downloadResult;
139
120
  },
140
121
  async uploadAsync(url: string, fileUri: string, options: FileSystemUploadOptions): Promise<FileSystemUploadResult> {
141
- const { headers, httpMethod } = options;
142
- const method = httpMethod ?? "POST";
143
-
144
- const data = await nativeModule.readAsStringAsync(fileUri, {});
145
-
146
- const response = await fetch(url, { method, headers, body: data });
147
-
148
- if (!response.ok) {
149
- throw new Error('Failed to upload the file!');
122
+ console.log("[ExponentFileSystem] uploadAsync: native streaming upload via libcurl");
123
+
124
+ try {
125
+ const result = await nativeModule.uploadAsync(url, fileUri, {
126
+ httpMethod: options.httpMethod ?? "POST",
127
+ }, generateRequestId(), toHeadersList(options.headers));
128
+
129
+ return result as FileSystemUploadResult;
130
+ } catch (error: any) {
131
+ console.error("[ExponentFileSystem] Upload failed:", error?.message);
132
+ const message = error?.message ?? JSON.stringify(error);
133
+ throw new Error(`Upload failed: ${message}`);
150
134
  }
151
-
152
- const uploadResult = await response.text();
153
-
154
- const responseHeaders = getHeadersFromResponse(response);
155
-
156
- return {
157
- body: uploadResult,
158
- headers: responseHeaders,
159
- status: response.status,
160
- mimeType: getMimeTypeFromHeaders(responseHeaders)
161
- };
162
135
  },
163
136
  addListener(eventName: string): void{},
164
137
  removeListeners(count: number): void{},
package/src/FileSystem.ts CHANGED
@@ -30,8 +30,6 @@ if (!ExponentFileSystem) {
30
30
  "No native ExponentFileSystem module found, are you sure the expo-file-system's module is linked properly?"
31
31
  );
32
32
  }
33
- // Prevent webpack from pruning this.
34
- const _unused = new EventEmitter(ExponentFileSystem); // eslint-disable-line
35
33
 
36
34
  function normalizeEndingSlash(p: string | null): string | null {
37
35
  if (p != null) {
@@ -1,47 +0,0 @@
1
- #include "NetworkingRequestHandler.h"
2
-
3
- #include <fstream>
4
-
5
- bool NetworkingRequestHandler::supports(utils::json::JsonContainer& data) {
6
- return data["fileUri"].isValue();
7
- }
8
-
9
- void NetworkingRequestHandler::decorateRequest(
10
- utils::json::JsonContainer& data,
11
- const std::string& contentType,
12
- volta::react::NetworkRequest& request) {
13
- auto type = data["type"].getValue<std::string>("");
14
-
15
- if (type.empty()) {
16
- type = "application/octet-stream";
17
- }
18
-
19
- request.addHeader(volta::react::NetworkingModule::CONTENT_TYPE_HEADER_KEY, type);
20
-
21
- try {
22
- auto dataPtr = std::make_shared<std::vector<uint8_t>>();
23
-
24
- auto fileUri = data["fileUri"].getValue<std::string>();
25
-
26
- std::ifstream file(fileUri, std::ios::binary);
27
-
28
- if (file.fail()) {
29
- volta::react::KPLog.error("[ExponentFileSystem] unable to open file at {} for response read", fileUri);
30
- } else {
31
- std::copy(
32
- std::istreambuf_iterator<char>(file),
33
- std::istreambuf_iterator<char>(),
34
- std::back_inserter(*dataPtr));
35
-
36
- if (file.fail()) {
37
- volta::react::KPLog.error("[ExponentFileSystem] error while reading response from file");
38
- } else {
39
- volta::react::KPLog.debug("[ExponentFileSystem] successfully read response from file");
40
- volta::react::ArrayBuffer buf(dataPtr);
41
- request.bodyDataBuffer = volta::react::ArrayBuffer(buf.dataVector());
42
- }
43
- }
44
- } catch (std::exception& e) {
45
- volta::react::KPLog.error("[ExponentFileSystem] reading response from file exception reason: {}", e.what());
46
- }
47
- }