@amazon-devices/expo-file-system 2.0.9000000001 → 3.0.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.
- package/CMakeLists.txt +30 -5
- package/build/ExponentFileSystem.kepler.js +1 -1
- package/build/ExponentFileSystem.kepler.js.map +1 -1
- package/kepler/CurlWrapper.cpp +19 -14
- package/kepler/ExponentFileSystem.cpp +73 -59
- package/kepler/KeplerInit.cpp +1 -1
- package/lib/aarch64-release/libexpo-file-system-3.so +0 -0
- package/lib/armv7-release/libexpo-file-system-3.so +0 -0
- package/lib/x86_64-release/libexpo-file-system-3.so +0 -0
- package/package.json +1 -1
- package/plugin/tsconfig.tsbuildinfo +1 -0
- package/react-native.config.js +5 -4
- package/src/ExponentFileSystem.kepler.ts +1 -1
- package/kepler-compatibility.json +0 -7
package/CMakeLists.txt
CHANGED
|
@@ -12,35 +12,51 @@
|
|
|
12
12
|
# FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
|
|
13
13
|
#
|
|
14
14
|
set(PACKAGE_NAME "expo-file-system")
|
|
15
|
-
|
|
15
|
+
# The npm major versions the app-deployed artifact so it cannot collide with the frozen system lib
|
|
16
|
+
set(AUTO_LINK_PACKAGE_NAME "${PACKAGE_NAME}-3")
|
|
16
17
|
set(SOURCES_KEPLER
|
|
17
18
|
kepler/ExponentFileSystem.cpp
|
|
18
19
|
kepler/CurlWrapper.cpp
|
|
19
20
|
)
|
|
20
21
|
|
|
22
|
+
# Embed the static VodkaCurl stack (find_package resolves shared libs here).
|
|
23
|
+
# Link order matters: curl -> nghttp2 -> ssl -> crypto -> z.
|
|
21
24
|
find_package(OpenSSL REQUIRED)
|
|
22
25
|
find_package(CURL REQUIRED)
|
|
23
26
|
|
|
27
|
+
set(_expo_fs_orig_suffixes "${CMAKE_FIND_LIBRARY_SUFFIXES}")
|
|
28
|
+
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
|
|
29
|
+
find_library(CURL_STATIC NAMES curl REQUIRED)
|
|
30
|
+
find_library(NGHTTP2_STATIC NAMES nghttp2 REQUIRED)
|
|
31
|
+
find_library(SSL_STATIC NAMES ssl REQUIRED)
|
|
32
|
+
find_library(CRYPTO_STATIC NAMES crypto REQUIRED)
|
|
33
|
+
find_library(Z_STATIC NAMES z REQUIRED)
|
|
34
|
+
find_library(PSL_STATIC NAMES psl REQUIRED)
|
|
35
|
+
set(CMAKE_FIND_LIBRARY_SUFFIXES "${_expo_fs_orig_suffixes}")
|
|
36
|
+
|
|
24
37
|
add_library(${PACKAGE_NAME} STATIC ${SOURCES_KEPLER})
|
|
25
38
|
|
|
26
39
|
target_include_directories(
|
|
27
40
|
${PACKAGE_NAME}
|
|
28
41
|
PRIVATE
|
|
29
42
|
${CURL_INCLUDE_DIRS}
|
|
43
|
+
${OPENSSL_INCLUDE_DIR}
|
|
30
44
|
)
|
|
31
45
|
|
|
32
46
|
target_link_libraries(
|
|
33
47
|
${PACKAGE_NAME}
|
|
34
48
|
PUBLIC
|
|
35
49
|
turbomoduleAPI::turbomoduleAPI
|
|
36
|
-
|
|
37
|
-
${
|
|
50
|
+
${CURL_STATIC}
|
|
51
|
+
${NGHTTP2_STATIC}
|
|
52
|
+
${SSL_STATIC}
|
|
53
|
+
${CRYPTO_STATIC}
|
|
54
|
+
${Z_STATIC}
|
|
55
|
+
${PSL_STATIC}
|
|
38
56
|
)
|
|
39
57
|
|
|
40
58
|
add_library(${AUTO_LINK_PACKAGE_NAME} SHARED kepler/KeplerInit.cpp)
|
|
41
59
|
|
|
42
|
-
set_target_properties(${AUTO_LINK_PACKAGE_NAME} PROPERTIES SOVERSION ${KEPLER_REACT_NATIVE_MAJOR_VERSION}.${KEPLER_REACT_NATIVE_MINOR_VERSION})
|
|
43
|
-
|
|
44
60
|
target_link_libraries(
|
|
45
61
|
${AUTO_LINK_PACKAGE_NAME}
|
|
46
62
|
PRIVATE
|
|
@@ -48,6 +64,15 @@ target_link_libraries(
|
|
|
48
64
|
${PACKAGE_NAME}
|
|
49
65
|
)
|
|
50
66
|
|
|
67
|
+
# Hide embedded archive symbols per archive since ALL would also hide our own
|
|
68
|
+
target_link_options(${AUTO_LINK_PACKAGE_NAME} PRIVATE
|
|
69
|
+
"-Wl,--exclude-libs,libcurl.a"
|
|
70
|
+
"-Wl,--exclude-libs,libnghttp2.a"
|
|
71
|
+
"-Wl,--exclude-libs,libssl.a"
|
|
72
|
+
"-Wl,--exclude-libs,libcrypto.a"
|
|
73
|
+
"-Wl,--exclude-libs,libz.a"
|
|
74
|
+
"-Wl,--exclude-libs,libpsl.a")
|
|
75
|
+
|
|
51
76
|
# Helps in checking undefined references
|
|
52
77
|
add_executable(${AUTO_LINK_PACKAGE_NAME}_exe kepler/KeplerInit.cpp)
|
|
53
78
|
target_link_libraries(${AUTO_LINK_PACKAGE_NAME}_exe
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TurboModuleRegistry } from '@amazon-devices/keplerscript-turbomodule-api';
|
|
2
|
-
const nativeModule = TurboModuleRegistry.getEnforcing('
|
|
2
|
+
const nativeModule = TurboModuleRegistry.getEnforcing('ExponentFileSystemAppTM');
|
|
3
3
|
let _requestId = 1;
|
|
4
4
|
const generateRequestId = () => { return _requestId++; };
|
|
5
5
|
function toHeadersList(headers) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExponentFileSystem.kepler.js","sourceRoot":"","sources":["../src/ExponentFileSystem.kepler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AAyC5F,MAAM,YAAY,GAAG,mBAAmB,CAAC,YAAY,CAAO,
|
|
1
|
+
{"version":3,"file":"ExponentFileSystem.kepler.js","sourceRoot":"","sources":["../src/ExponentFileSystem.kepler.ts"],"names":[],"mappings":"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","sourcesContent":["import { KeplerTurboModule, TurboModuleRegistry } from '@amazon-devices/keplerscript-turbomodule-api';\n\nimport {\n DeletingOptions,\n DownloadOptions,\n FileInfo,\n FileSystemDownloadResult,\n FileSystemUploadOptions,\n FileSystemUploadResult,\n InfoOptions,\n MakeDirectoryOptions,\n ReadingOptions,\n RelocatingOptions,\n WritingOptions,\n} from './FileSystem.types';\nimport { ExponentFileSystemModule } from './types';\n\ninterface Spec extends KeplerTurboModule {\n readonly documentDirectory: () => string;\n readonly cacheDirectory: () => string;\n /**\n * @deprecated this property was removed from expo\n */\n readonly bundledAssets: () => string;\n readonly bundleDirectory: () => string;\n readonly getInfoAsync: (fileUri: string, options: InfoOptions) => Promise<FileInfo>;\n readonly readAsStringAsync: (fileUri: string, options: ReadingOptions) => Promise<string>;\n readonly getContentUriAsync: (fileUri: string) => Promise<string>;\n readonly writeAsStringAsync: (fileUri: string, contents: string, options: WritingOptions) => Promise<void>;\n readonly writeArrayBufferAsync: (fileUri: string, contents: ArrayBuffer) => Promise<void>;\n readonly deleteAsync: (fileUri: string, options: DeletingOptions) => Promise<void>;\n readonly moveAsync: (options: RelocatingOptions) => Promise<void>;\n readonly copyAsync: (options: RelocatingOptions) => Promise<void>;\n readonly makeDirectoryAsync: (fileUri: string, options: MakeDirectoryOptions) => Promise<void>;\n readonly readDirectoryAsync: (fileUri: string) => Promise<string[]>;\n readonly getFreeDiskStorageAsync: () => Promise<string>;\n readonly getTotalDiskCapacityAsync: () => Promise<string | undefined>;\n readonly downloadAsync: (url: string, fileUri: string, options: Record<string, any>, requestId: number, headers: Array<{key: string, value: string}>) => Promise<FileSystemDownloadResult>;\n readonly uploadAsync: (url: string, fileUri: string, options: Record<string, any>, requestId: number, headers: Array<{key: string, value: string}>) => Promise<FileSystemUploadResult>;\n}\n\nconst nativeModule = TurboModuleRegistry.getEnforcing<Spec>('ExponentFileSystemAppTM') as Spec;\n\nlet _requestId = 1;\nconst generateRequestId = (): number => { return _requestId++; };\n\nfunction toHeadersList(headers?: Record<string, string>): Array<{key: string, value: string}> {\n return Object.entries(headers ?? {}).map(([key, value]) => ({ key, value }));\n}\n\nconst module: ExponentFileSystemModule = {\n get name(): 'ExponentFileSystem' {\n return 'ExponentFileSystem';\n },\n get documentDirectory() {\n return nativeModule.documentDirectory();\n },\n get cacheDirectory() {\n return nativeModule.cacheDirectory();\n },\n /**\n * @deprecated this property was removed from expo\n */\n get bundledAssets() {\n return null;\n },\n get bundleDirectory() {\n return nativeModule.bundleDirectory();\n },\n async getInfoAsync(fileUri: string, options: InfoOptions) {\n return nativeModule.getInfoAsync(fileUri, options);\n },\n async readAsStringAsync(fileUri: string, options: ReadingOptions) {\n return nativeModule.readAsStringAsync(fileUri, options);\n },\n async getContentUriAsync(fileUri: string) {\n return nativeModule.getContentUriAsync(fileUri);\n },\n async writeAsStringAsync(fileUri: string, contents: string, options: WritingOptions) {\n return nativeModule.writeAsStringAsync(fileUri, contents, options);\n },\n async deleteAsync(fileUri: string, options: DeletingOptions) {\n return nativeModule.deleteAsync(fileUri, options);\n },\n async moveAsync(options: RelocatingOptions) {\n return nativeModule.moveAsync(options);\n },\n async copyAsync(options: RelocatingOptions) {\n return nativeModule.copyAsync(options);\n },\n async makeDirectoryAsync(fileUri: string, options: MakeDirectoryOptions) {\n return nativeModule.makeDirectoryAsync(fileUri, options);\n },\n async readDirectoryAsync(fileUri: string) {\n return nativeModule.readDirectoryAsync(fileUri);\n },\n async getFreeDiskStorageAsync() {\n return nativeModule.getFreeDiskStorageAsync().then(parseInt);\n },\n async getTotalDiskCapacityAsync() {\n const result = await nativeModule.getTotalDiskCapacityAsync();\n return result ? parseInt(result) : 0;\n },\n async downloadAsync(url: string, fileUri: string, options: DownloadOptions): Promise<FileSystemDownloadResult> {\n console.log(\"[ExponentFileSystem] downloadAsync: native streaming download via libcurl\");\n console.log(`DOWNLOAD URL: ${url}`);\n console.log(`FILE URL: ${fileUri}`);\n\n try {\n const result = await nativeModule.downloadAsync(url, fileUri, {\n md5: options.md5 ?? false,\n }, generateRequestId(), toHeadersList(options.headers));\n\n return result as FileSystemDownloadResult;\n } catch (error: any) {\n console.error(\"[ExponentFileSystem] Download failed:\", error?.message);\n const message = error?.message ?? JSON.stringify(error);\n throw new Error(`Download failed: ${message}`);\n }\n },\n async uploadAsync(url: string, fileUri: string, options: FileSystemUploadOptions): Promise<FileSystemUploadResult> {\n console.log(\"[ExponentFileSystem] uploadAsync: native streaming upload via libcurl\");\n\n try {\n const result = await nativeModule.uploadAsync(url, fileUri, {\n httpMethod: options.httpMethod ?? \"POST\",\n }, generateRequestId(), toHeadersList(options.headers));\n\n return result as FileSystemUploadResult;\n } catch (error: any) {\n console.error(\"[ExponentFileSystem] Upload failed:\", error?.message);\n const message = error?.message ?? JSON.stringify(error);\n throw new Error(`Upload failed: ${message}`);\n }\n },\n addListener(eventName: string): void{},\n removeListeners(count: number): void{},\n};\n\nexport default module;\n"]}
|
package/kepler/CurlWrapper.cpp
CHANGED
|
@@ -9,17 +9,17 @@
|
|
|
9
9
|
#include "CurlWrapper.h"
|
|
10
10
|
|
|
11
11
|
#include <Kepler/turbomodule/TMLog.h>
|
|
12
|
-
#include <fmt/format.h>
|
|
13
12
|
|
|
14
13
|
#include <cstring>
|
|
15
14
|
#include <fstream>
|
|
16
15
|
#include <mutex>
|
|
16
|
+
#include <string>
|
|
17
17
|
|
|
18
18
|
static std::once_flag curlInitFlag;
|
|
19
19
|
|
|
20
20
|
CurlWrapper::CurlWrapper() {
|
|
21
21
|
std::call_once(curlInitFlag, []() {
|
|
22
|
-
TMDEBUG(
|
|
22
|
+
TMDEBUG("[CurlWrapper] Initializing libcurl (once)");
|
|
23
23
|
curl_global_init(CURL_GLOBAL_ALL);
|
|
24
24
|
});
|
|
25
25
|
}
|
|
@@ -35,7 +35,7 @@ size_t CurlWrapper::writeToFileCallback(void* contents, size_t size, size_t nmem
|
|
|
35
35
|
size_t totalBytes = size * nmemb;
|
|
36
36
|
file->write(static_cast<const char*>(contents), totalBytes);
|
|
37
37
|
if (file->fail()) {
|
|
38
|
-
TMERROR(
|
|
38
|
+
TMERROR(std::string("[CurlWrapper] Failed to write ") + std::to_string(totalBytes) + " bytes to file");
|
|
39
39
|
return 0;
|
|
40
40
|
}
|
|
41
41
|
return totalBytes;
|
|
@@ -78,6 +78,11 @@ void CurlWrapper::setCommonOptions(
|
|
|
78
78
|
curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS);
|
|
79
79
|
curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "");
|
|
80
80
|
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L);
|
|
81
|
+
// libcurl/OpenSSL are statically linked, so their compiled-in default CA
|
|
82
|
+
// location does not match the device. Point TLS verification at the device
|
|
83
|
+
// CA trust store explicitly.
|
|
84
|
+
curl_easy_setopt(curl, CURLOPT_CAINFO, "/etc/ssl/certs/ca-certificates.crt");
|
|
85
|
+
curl_easy_setopt(curl, CURLOPT_CAPATH, "/etc/ssl/certs");
|
|
81
86
|
// Abort if transfer speed drops below 1 byte/sec for 60 seconds
|
|
82
87
|
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, 1L);
|
|
83
88
|
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, 60L);
|
|
@@ -100,14 +105,14 @@ CurlResponse CurlWrapper::downloadToFile(
|
|
|
100
105
|
std::shared_ptr<CURL> curl(curl_easy_init(), curl_easy_cleanup);
|
|
101
106
|
if (!curl) {
|
|
102
107
|
response.errorMessage = "Failed to initialize curl";
|
|
103
|
-
TMERROR(
|
|
108
|
+
TMERROR(std::string("[CurlWrapper] ") + response.errorMessage);
|
|
104
109
|
return response;
|
|
105
110
|
}
|
|
106
111
|
|
|
107
112
|
std::ofstream outputFile(filePath, std::ios::binary);
|
|
108
113
|
if (!outputFile.is_open()) {
|
|
109
114
|
response.errorMessage = "Failed to open output file: " + filePath;
|
|
110
|
-
TMERROR(
|
|
115
|
+
TMERROR(std::string("[CurlWrapper] ") + response.errorMessage);
|
|
111
116
|
return response;
|
|
112
117
|
}
|
|
113
118
|
|
|
@@ -122,18 +127,18 @@ CurlResponse CurlWrapper::downloadToFile(
|
|
|
122
127
|
curl_easy_setopt(curl.get(), CURLOPT_ERRORBUFFER, errorBuffer);
|
|
123
128
|
setCommonOptions(curl.get(), requestHeaders, &headerList);
|
|
124
129
|
|
|
125
|
-
TMDEBUG(
|
|
130
|
+
TMDEBUG(std::string("[CurlWrapper] Starting download: ") + url + " -> " + filePath);
|
|
126
131
|
CURLcode res = curl_easy_perform(curl.get());
|
|
127
132
|
outputFile.close();
|
|
128
133
|
|
|
129
134
|
if (res != CURLE_OK) {
|
|
130
135
|
std::string errorDetail = (errorBuffer[0] != '\0') ? errorBuffer : curl_easy_strerror(res);
|
|
131
136
|
response.errorMessage = "Download failed: " + errorDetail;
|
|
132
|
-
TMERROR(
|
|
137
|
+
TMERROR(std::string("[CurlWrapper] ") + response.errorMessage);
|
|
133
138
|
std::remove(filePath.c_str());
|
|
134
139
|
} else {
|
|
135
140
|
curl_easy_getinfo(curl.get(), CURLINFO_RESPONSE_CODE, &response.statusCode);
|
|
136
|
-
TMDEBUG(
|
|
141
|
+
TMDEBUG(std::string("[CurlWrapper] Download complete, HTTP status: ") + std::to_string(response.statusCode));
|
|
137
142
|
if (response.statusCode >= 200 && response.statusCode < 300) {
|
|
138
143
|
response.success = true;
|
|
139
144
|
} else {
|
|
@@ -158,14 +163,14 @@ CurlResponse CurlWrapper::uploadFromFile(
|
|
|
158
163
|
std::shared_ptr<CURL> curl(curl_easy_init(), curl_easy_cleanup);
|
|
159
164
|
if (!curl) {
|
|
160
165
|
response.errorMessage = "Failed to initialize curl";
|
|
161
|
-
TMERROR(
|
|
166
|
+
TMERROR(std::string("[CurlWrapper] ") + response.errorMessage);
|
|
162
167
|
return response;
|
|
163
168
|
}
|
|
164
169
|
|
|
165
170
|
std::ifstream inputFile(filePath, std::ios::binary | std::ios::ate);
|
|
166
171
|
if (!inputFile.is_open()) {
|
|
167
172
|
response.errorMessage = "Failed to open input file: " + filePath;
|
|
168
|
-
TMERROR(
|
|
173
|
+
TMERROR(std::string("[CurlWrapper] ") + response.errorMessage);
|
|
169
174
|
return response;
|
|
170
175
|
}
|
|
171
176
|
auto fileSize = inputFile.tellg();
|
|
@@ -218,17 +223,17 @@ CurlResponse CurlWrapper::uploadFromFile(
|
|
|
218
223
|
|
|
219
224
|
setCommonOptions(curl.get(), requestHeaders, &headerList);
|
|
220
225
|
|
|
221
|
-
TMDEBUG(
|
|
226
|
+
TMDEBUG(std::string("[CurlWrapper] Starting upload: ") + filePath + " -> " + url + " (" + httpMethod + ")");
|
|
222
227
|
CURLcode res = curl_easy_perform(curl.get());
|
|
223
228
|
inputFile.close();
|
|
224
229
|
|
|
225
230
|
if (res != CURLE_OK) {
|
|
226
231
|
std::string errorDetail = (errorBuffer[0] != '\0') ? errorBuffer : curl_easy_strerror(res);
|
|
227
232
|
response.errorMessage = "Upload failed: " + errorDetail;
|
|
228
|
-
TMERROR(
|
|
233
|
+
TMERROR(std::string("[CurlWrapper] ") + response.errorMessage);
|
|
229
234
|
} else {
|
|
230
235
|
curl_easy_getinfo(curl.get(), CURLINFO_RESPONSE_CODE, &response.statusCode);
|
|
231
|
-
TMDEBUG(
|
|
236
|
+
TMDEBUG(std::string("[CurlWrapper] Upload complete, HTTP status: ") + std::to_string(response.statusCode));
|
|
232
237
|
if (response.statusCode >= 200 && response.statusCode < 300) {
|
|
233
238
|
response.success = true;
|
|
234
239
|
} else {
|
|
@@ -237,7 +242,7 @@ CurlResponse CurlWrapper::uploadFromFile(
|
|
|
237
242
|
}
|
|
238
243
|
|
|
239
244
|
if (responseBodyTruncated) {
|
|
240
|
-
TMDEBUG(
|
|
245
|
+
TMDEBUG(std::string("[CurlWrapper] Response body truncated at ") + std::to_string(MAX_RESPONSE_BODY_SIZE) + "B");
|
|
241
246
|
responseBody += "\n... [truncated]";
|
|
242
247
|
}
|
|
243
248
|
response.headers["__response_body__"] = responseBody;
|
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
|
|
11
11
|
#include <JsonContainer/JsonContainer.h>
|
|
12
12
|
#include <Kepler/turbomodule/TMLog.h>
|
|
13
|
-
#include <fmt/format.h>
|
|
14
13
|
#include <openssl/evp.h>
|
|
15
14
|
#include <openssl/md5.h>
|
|
16
15
|
#include <sys/stat.h>
|
|
@@ -72,7 +71,7 @@ T getOrDefault(NativeJSObject map, std::string key, const T& defaultValue) {
|
|
|
72
71
|
} // namespace
|
|
73
72
|
|
|
74
73
|
ExponentFileSystem::ExponentFileSystem() : com::amazon::kepler::turbomodule::KeplerTurboModule("ExponentFileSystem") {
|
|
75
|
-
TMDEBUG(
|
|
74
|
+
TMDEBUG(std::string("ExponentFileSystem constructor ") + name());
|
|
76
75
|
curlWrapper_ = std::make_unique<CurlWrapper>();
|
|
77
76
|
};
|
|
78
77
|
|
|
@@ -111,10 +110,7 @@ Promise ExponentFileSystem::getInfoAsync(const std::string fileUri, NativeJSObje
|
|
|
111
110
|
int status = stat(fileUri.c_str(), &fileStat);
|
|
112
111
|
if (status != 0) {
|
|
113
112
|
std::string errorMessage = std::strerror(errno);
|
|
114
|
-
TMERROR(
|
|
115
|
-
"[ExponentFileSystem] error in `stat()` call: {} while obtaining information about the file: {}!",
|
|
116
|
-
errorMessage,
|
|
117
|
-
fileUri));
|
|
113
|
+
TMERROR(std::string("[ExponentFileSystem] error in `stat()` call: ") + errorMessage + " while obtaining information about the file: " + fileUri + "!");
|
|
118
114
|
promise->reject(
|
|
119
115
|
"Error while obtaining information about the file! `stat()` call exited with error: " +
|
|
120
116
|
errorMessage);
|
|
@@ -135,20 +131,20 @@ Promise ExponentFileSystem::getInfoAsync(const std::string fileUri, NativeJSObje
|
|
|
135
131
|
|
|
136
132
|
if (shouldIncludeMD5Hash) {
|
|
137
133
|
std::ifstream stream(fileUri);
|
|
138
|
-
TMDEBUG(
|
|
134
|
+
TMDEBUG(std::string("[MD5] trying to open the file: ") + fileUri + " for read");
|
|
139
135
|
if (stream.fail()) {
|
|
140
136
|
std::string errorMessage = std::strerror(errno);
|
|
141
|
-
TMERROR(
|
|
137
|
+
TMERROR(std::string("[MD5] unable to open file at ") + fileUri + " for read: " + errorMessage);
|
|
142
138
|
promise->reject("Error while trying to open the file: " + errorMessage);
|
|
143
139
|
return;
|
|
144
140
|
} else {
|
|
145
141
|
std::stringstream buffer;
|
|
146
142
|
buffer << stream.rdbuf();
|
|
147
143
|
std::string content = buffer.str();
|
|
148
|
-
TMDEBUG(
|
|
144
|
+
TMDEBUG(std::string("[MD5] content: ") + content);
|
|
149
145
|
TMDEBUG("[MD5] calculating the file content hash...");
|
|
150
146
|
std::string hash = md5Hash(content);
|
|
151
|
-
TMDEBUG(
|
|
147
|
+
TMDEBUG(std::string("[MD5] file hash: ") + hash);
|
|
152
148
|
fileInfo.insert({"md5", hash});
|
|
153
149
|
}
|
|
154
150
|
}
|
|
@@ -163,17 +159,14 @@ Promise ExponentFileSystem::readAsStringAsync(const std::string fileUri, NativeJ
|
|
|
163
159
|
|
|
164
160
|
return Promise([this, fileUri, desiredEncoding, bytesToSkip, length](std::shared_ptr<Promise> promise) {
|
|
165
161
|
try {
|
|
166
|
-
TMDEBUG(
|
|
162
|
+
TMDEBUG(std::string("[ExponentFileSystem] path: ") + fileUri);
|
|
167
163
|
std::int32_t fileSize = std::filesystem::file_size(fileUri);
|
|
168
164
|
|
|
169
165
|
std::ifstream stream(fileUri);
|
|
170
|
-
TMDEBUG(
|
|
166
|
+
TMDEBUG(std::string("[ExponentFileSystem] trying to open the file: ") + fileUri + " for read");
|
|
171
167
|
if (stream.fail()) {
|
|
172
168
|
std::string errorMessage = std::strerror(errno);
|
|
173
|
-
TMERROR(
|
|
174
|
-
"[ExponentFileSystem] unable to open file at {} for read: {}",
|
|
175
|
-
fileUri,
|
|
176
|
-
errorMessage));
|
|
169
|
+
TMERROR(std::string("[ExponentFileSystem] unable to open file at ") + fileUri + " for read: " + errorMessage);
|
|
177
170
|
promise->reject("Error while trying to open the file: " + errorMessage);
|
|
178
171
|
return;
|
|
179
172
|
}
|
|
@@ -191,7 +184,7 @@ Promise ExponentFileSystem::readAsStringAsync(const std::string fileUri, NativeJ
|
|
|
191
184
|
std::string content;
|
|
192
185
|
content.resize(bytesToRead);
|
|
193
186
|
stream.read(&content[0], bytesToRead);
|
|
194
|
-
TMDEBUG(
|
|
187
|
+
TMDEBUG(std::string("[ExponentFileSystem] content: ") + content);
|
|
195
188
|
|
|
196
189
|
if (desiredEncoding == "base64") {
|
|
197
190
|
TMDEBUG("[base64] base64 encoding...");
|
|
@@ -200,7 +193,7 @@ Promise ExponentFileSystem::readAsStringAsync(const std::string fileUri, NativeJ
|
|
|
200
193
|
promise->resolve(content);
|
|
201
194
|
}
|
|
202
195
|
} catch (std::exception& e) {
|
|
203
|
-
TMERROR(
|
|
196
|
+
TMERROR(std::string("[ExponentFileSystem] reading file exception reason: ") + e.what());
|
|
204
197
|
promise->reject(e.what());
|
|
205
198
|
}
|
|
206
199
|
});
|
|
@@ -223,13 +216,10 @@ Promise ExponentFileSystem::writeAsStringAsync(
|
|
|
223
216
|
return Promise([this, fileUri, contents, desiredEncoding](std::shared_ptr<Promise> promise) {
|
|
224
217
|
try {
|
|
225
218
|
std::ofstream stream(fileUri);
|
|
226
|
-
TMDEBUG(
|
|
219
|
+
TMDEBUG(std::string("[ExponentFileSystem] trying to open the file: ") + fileUri + " for write");
|
|
227
220
|
if (stream.fail()) {
|
|
228
221
|
std::string errorMessage = std::strerror(errno);
|
|
229
|
-
TMERROR(
|
|
230
|
-
"[ExponentFileSystem] unable to open file at {} for write: {}",
|
|
231
|
-
fileUri,
|
|
232
|
-
errorMessage));
|
|
222
|
+
TMERROR(std::string("[ExponentFileSystem] unable to open file at ") + fileUri + " for write: " + errorMessage);
|
|
233
223
|
promise->reject("Error while trying to open the file: " + errorMessage);
|
|
234
224
|
return;
|
|
235
225
|
} else {
|
|
@@ -241,7 +231,7 @@ Promise ExponentFileSystem::writeAsStringAsync(
|
|
|
241
231
|
|
|
242
232
|
if (stream.fail()) {
|
|
243
233
|
std::string errorMessage = std::strerror(errno);
|
|
244
|
-
TMERROR(
|
|
234
|
+
TMERROR(std::string("[ExponentFileSystem] error while writing to file: ") + errorMessage);
|
|
245
235
|
promise->reject("Error while trying to write to the file: " + errorMessage);
|
|
246
236
|
return;
|
|
247
237
|
}
|
|
@@ -249,7 +239,7 @@ Promise ExponentFileSystem::writeAsStringAsync(
|
|
|
249
239
|
}
|
|
250
240
|
promise->resolve(NULL);
|
|
251
241
|
} catch (std::exception& e) {
|
|
252
|
-
TMERROR(
|
|
242
|
+
TMERROR(std::string("[ExponentFileSystem] writing file exception reason: ") + e.what());
|
|
253
243
|
promise->reject(e.what());
|
|
254
244
|
}
|
|
255
245
|
});
|
|
@@ -264,10 +254,7 @@ Promise ExponentFileSystem::writeArrayBufferAsync(const std::string fileUri, con
|
|
|
264
254
|
|
|
265
255
|
if (file.fail()) {
|
|
266
256
|
std::string errorMessage = std::strerror(errno);
|
|
267
|
-
TMERROR(
|
|
268
|
-
"[ExponentFileSystem] unable to open file at {} for response write: {}",
|
|
269
|
-
fileUri,
|
|
270
|
-
errorMessage));
|
|
257
|
+
TMERROR(std::string("[ExponentFileSystem] unable to open file at ") + fileUri + " for response write: " + errorMessage);
|
|
271
258
|
promise->reject("File while tring to open the file: " + errorMessage);
|
|
272
259
|
return;
|
|
273
260
|
} else {
|
|
@@ -275,9 +262,7 @@ Promise ExponentFileSystem::writeArrayBufferAsync(const std::string fileUri, con
|
|
|
275
262
|
file.write(reinterpret_cast<const char*>(dataPtr->data()), dataPtr->size());
|
|
276
263
|
if (file.fail()) {
|
|
277
264
|
std::string errorMessage = std::strerror(errno);
|
|
278
|
-
TMERROR(
|
|
279
|
-
"[ExponentFileSystem] error while writing response to file: {}",
|
|
280
|
-
errorMessage));
|
|
265
|
+
TMERROR(std::string("[ExponentFileSystem] error while writing response to file: ") + errorMessage);
|
|
281
266
|
promise->reject("Error while trying to write response to file: " + errorMessage);
|
|
282
267
|
return;
|
|
283
268
|
}
|
|
@@ -285,7 +270,7 @@ Promise ExponentFileSystem::writeArrayBufferAsync(const std::string fileUri, con
|
|
|
285
270
|
}
|
|
286
271
|
promise->resolve(NULL);
|
|
287
272
|
} catch (std::exception& e) {
|
|
288
|
-
TMERROR(
|
|
273
|
+
TMERROR(std::string("[ExponentFileSystem] writing file exception reason: ") + e.what());
|
|
289
274
|
promise->reject(e.what());
|
|
290
275
|
}
|
|
291
276
|
});
|
|
@@ -311,7 +296,7 @@ Promise ExponentFileSystem::deleteAsync(const std::string fileUri, NativeJSObjec
|
|
|
311
296
|
std::filesystem::remove(fileUri);
|
|
312
297
|
promise->resolve(NULL);
|
|
313
298
|
} catch (std::filesystem::filesystem_error& e) {
|
|
314
|
-
TMERROR(
|
|
299
|
+
TMERROR(std::string("[ExponentFileSystem] file deletion exception, reason: ") + e.what());
|
|
315
300
|
promise->reject(e.what());
|
|
316
301
|
}
|
|
317
302
|
} else {
|
|
@@ -336,7 +321,7 @@ Promise ExponentFileSystem::moveAsync(NativeJSObject options) {
|
|
|
336
321
|
std::filesystem::rename(from, to);
|
|
337
322
|
promise->resolve(NULL);
|
|
338
323
|
} catch (std::filesystem::filesystem_error& e) {
|
|
339
|
-
TMERROR(
|
|
324
|
+
TMERROR(std::string("[ExponentFileSystem] file transfer exception, reason: ") + e.what());
|
|
340
325
|
promise->reject(e.what());
|
|
341
326
|
}
|
|
342
327
|
});
|
|
@@ -353,11 +338,49 @@ Promise ExponentFileSystem::copyAsync(NativeJSObject options) {
|
|
|
353
338
|
return;
|
|
354
339
|
}
|
|
355
340
|
|
|
341
|
+
// Run the copy on a background thread to avoid blocking the JS thread.
|
|
342
|
+
// std::filesystem::copy is synchronous and blocks for the whole copy
|
|
343
|
+
// duration, which trips the KeplerScript thread watchdog on large files.
|
|
356
344
|
try {
|
|
357
|
-
std::
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
345
|
+
std::thread([promise, from, to]() {
|
|
346
|
+
// If we cannot tell whether the destination already exists,
|
|
347
|
+
// assume it does. Then a failed copy never deletes data we did
|
|
348
|
+
// not create.
|
|
349
|
+
std::error_code existsError;
|
|
350
|
+
bool destExisted = true;
|
|
351
|
+
bool destExistsResult = std::filesystem::exists(to, existsError);
|
|
352
|
+
if (!existsError) {
|
|
353
|
+
destExisted = destExistsResult;
|
|
354
|
+
}
|
|
355
|
+
// A failed copy can leave a truncated destination, but only if
|
|
356
|
+
// this copy created it. Remove just that.
|
|
357
|
+
auto removePartialDestination = [&to, destExisted]() {
|
|
358
|
+
if (destExisted) {
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
std::error_code cleanupError;
|
|
362
|
+
std::filesystem::remove_all(to, cleanupError);
|
|
363
|
+
if (cleanupError) {
|
|
364
|
+
TMERROR(std::string("[ExponentFileSystem] could not remove partial destination, reason: ") + cleanupError.message());
|
|
365
|
+
}
|
|
366
|
+
};
|
|
367
|
+
try {
|
|
368
|
+
std::filesystem::copy(from, to, std::filesystem::copy_options::recursive);
|
|
369
|
+
promise->resolve(NULL);
|
|
370
|
+
} catch (std::exception& e) {
|
|
371
|
+
TMERROR(std::string("[ExponentFileSystem] file transfer exception, reason: ") + e.what());
|
|
372
|
+
removePartialDestination();
|
|
373
|
+
promise->reject(e.what());
|
|
374
|
+
} catch (...) {
|
|
375
|
+
TMERROR(std::string("[ExponentFileSystem] file transfer failed with an unknown exception"));
|
|
376
|
+
removePartialDestination();
|
|
377
|
+
promise->reject("unknown file transfer error");
|
|
378
|
+
}
|
|
379
|
+
}).detach();
|
|
380
|
+
} catch (std::exception& e) {
|
|
381
|
+
// The thread could not start. Reject here so the promise always
|
|
382
|
+
// settles and the JS caller does not wait forever.
|
|
383
|
+
TMERROR(std::string("[ExponentFileSystem] could not start copy thread, reason: ") + e.what());
|
|
361
384
|
promise->reject(e.what());
|
|
362
385
|
}
|
|
363
386
|
});
|
|
@@ -385,15 +408,13 @@ Promise ExponentFileSystem::makeDirectoryAsync(const std::string fileUri, Native
|
|
|
385
408
|
if (std::filesystem::create_directories(fileUri, errorCode)) {
|
|
386
409
|
TMDEBUG("[ExponentFileSystem] directory created successfully!");
|
|
387
410
|
} else {
|
|
388
|
-
TMERROR(
|
|
389
|
-
"[ExponentFileSystem] directory creation failed, message: {}",
|
|
390
|
-
errorCode.message()));
|
|
411
|
+
TMERROR(std::string("[ExponentFileSystem] directory creation failed, message: ") + errorCode.message());
|
|
391
412
|
promise->reject(errorCode.message());
|
|
392
413
|
return;
|
|
393
414
|
}
|
|
394
415
|
promise->resolve(NULL);
|
|
395
416
|
} catch (std::exception& e) {
|
|
396
|
-
TMERROR(
|
|
417
|
+
TMERROR(std::string("[ExponentFileSystem] directory creation exception, reason: ") + e.what());
|
|
397
418
|
promise->reject(e.what());
|
|
398
419
|
}
|
|
399
420
|
});
|
|
@@ -422,7 +443,7 @@ Promise ExponentFileSystem::readDirectoryAsync(const std::string fileUri) {
|
|
|
422
443
|
|
|
423
444
|
promise->resolve(childrenNames);
|
|
424
445
|
} catch (std::exception& e) {
|
|
425
|
-
TMERROR(
|
|
446
|
+
TMERROR(std::string("[ExponentFileSystem] Reading directory exception: ") + e.what());
|
|
426
447
|
promise->reject(e.what());
|
|
427
448
|
}
|
|
428
449
|
});
|
|
@@ -436,16 +457,14 @@ Promise ExponentFileSystem::getFreeDiskStorageAsync() {
|
|
|
436
457
|
std::error_code errorCode;
|
|
437
458
|
std::filesystem::space_info spaceInfo = std::filesystem::space(path, errorCode);
|
|
438
459
|
if (errorCode) {
|
|
439
|
-
TMERROR(
|
|
440
|
-
"[ExponentFileSystem] Error when getting free disk space: {}",
|
|
441
|
-
errorCode.message()));
|
|
460
|
+
TMERROR(std::string("[ExponentFileSystem] Error when getting free disk space: ") + errorCode.message());
|
|
442
461
|
promise->reject(errorCode.message());
|
|
443
462
|
return;
|
|
444
463
|
}
|
|
445
|
-
TMDEBUG(
|
|
464
|
+
TMDEBUG(std::string("[ExponentFileSystem] Free space: ") + std::to_string(spaceInfo.available));
|
|
446
465
|
promise->resolve(std::to_string(spaceInfo.available));
|
|
447
466
|
} catch (std::exception& e) {
|
|
448
|
-
TMERROR(
|
|
467
|
+
TMERROR(std::string("[ExponentFileSystem] Getting free disk storage exception: ") + e.what());
|
|
449
468
|
promise->reject(e.what());
|
|
450
469
|
}
|
|
451
470
|
});
|
|
@@ -477,8 +496,7 @@ Promise ExponentFileSystem::downloadAsync(
|
|
|
477
496
|
|
|
478
497
|
return Promise(
|
|
479
498
|
[this, url, fileUri, shouldComputeMd5, requestHeaders](std::shared_ptr<Promise> promise) {
|
|
480
|
-
TMDEBUG(
|
|
481
|
-
"[ExponentFileSystem] downloadAsync: {} -> {}", url, fileUri));
|
|
499
|
+
TMDEBUG(std::string("[ExponentFileSystem] downloadAsync: ") + url + " -> " + fileUri);
|
|
482
500
|
|
|
483
501
|
// Run curl on a background thread to avoid blocking the JS thread.
|
|
484
502
|
// curl_easy_perform is synchronous and will block for the entire download
|
|
@@ -488,8 +506,7 @@ Promise ExponentFileSystem::downloadAsync(
|
|
|
488
506
|
auto result = curlWrapper->downloadToFile(url, fileUri, requestHeaders);
|
|
489
507
|
|
|
490
508
|
if (!result.success) {
|
|
491
|
-
TMERROR(
|
|
492
|
-
"[ExponentFileSystem] downloadAsync failed: {}", result.errorMessage));
|
|
509
|
+
TMERROR(std::string("[ExponentFileSystem] downloadAsync failed: ") + result.errorMessage);
|
|
493
510
|
promise->reject(result.errorMessage);
|
|
494
511
|
return;
|
|
495
512
|
}
|
|
@@ -522,8 +539,7 @@ Promise ExponentFileSystem::downloadAsync(
|
|
|
522
539
|
downloadResult.insert({"md5", md5Hash(buffer.str())});
|
|
523
540
|
}
|
|
524
541
|
} catch (std::exception& e) {
|
|
525
|
-
TMERROR(
|
|
526
|
-
"[ExponentFileSystem] MD5 computation failed: {}", e.what()));
|
|
542
|
+
TMERROR(std::string("[ExponentFileSystem] MD5 computation failed: ") + e.what());
|
|
527
543
|
}
|
|
528
544
|
}
|
|
529
545
|
|
|
@@ -554,8 +570,7 @@ Promise ExponentFileSystem::uploadAsync(
|
|
|
554
570
|
|
|
555
571
|
return Promise(
|
|
556
572
|
[this, url, fileUri, httpMethod, requestHeaders](std::shared_ptr<Promise> promise) {
|
|
557
|
-
TMDEBUG(
|
|
558
|
-
"[ExponentFileSystem] uploadAsync: {} -> {} ({})", fileUri, url, httpMethod));
|
|
573
|
+
TMDEBUG(std::string("[ExponentFileSystem] uploadAsync: ") + fileUri + " -> " + url + " (" + httpMethod + ")");
|
|
559
574
|
|
|
560
575
|
// Run curl on a background thread to avoid blocking the JS thread.
|
|
561
576
|
auto curlWrapper = curlWrapper_.get();
|
|
@@ -563,8 +578,7 @@ Promise ExponentFileSystem::uploadAsync(
|
|
|
563
578
|
auto result = curlWrapper->uploadFromFile(url, fileUri, httpMethod, requestHeaders);
|
|
564
579
|
|
|
565
580
|
if (!result.success) {
|
|
566
|
-
TMERROR(
|
|
567
|
-
"[ExponentFileSystem] uploadAsync failed: {}", result.errorMessage));
|
|
581
|
+
TMERROR(std::string("[ExponentFileSystem] uploadAsync failed: ") + result.errorMessage);
|
|
568
582
|
promise->reject(result.errorMessage);
|
|
569
583
|
return;
|
|
570
584
|
}
|
package/kepler/KeplerInit.cpp
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
extern "C" {
|
|
15
15
|
__attribute__((visibility("default"))) void autoLinkKeplerTurboModulesV1() noexcept {
|
|
16
16
|
TMDEBUG("autoLinkKeplerTurboModulesV1 for expo-file-system");
|
|
17
|
-
KEPLER_REGISTER_TURBO_MODULE_WITH_NAME("
|
|
17
|
+
KEPLER_REGISTER_TURBO_MODULE_WITH_NAME("ExponentFileSystemAppTM", ExponentFileSystem);
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name": "@amazon-devices/expo-file-system", "version": "
|
|
1
|
+
{"name": "@amazon-devices/expo-file-system", "version": "3.0.2+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"}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"root":["./src/withFileSystem.ts"],"version":"5.9.3"}
|
package/react-native.config.js
CHANGED
|
@@ -10,10 +10,11 @@ module.exports = {
|
|
|
10
10
|
platforms: {
|
|
11
11
|
kepler: {
|
|
12
12
|
autolink: {
|
|
13
|
-
|
|
14
|
-
provider: '
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
ExponentFileSystemAppLib: {
|
|
14
|
+
provider: 'application',
|
|
15
|
+
linkDynamic: true,
|
|
16
|
+
libraryName: 'libexpo-file-system-3.so',
|
|
17
|
+
turbomodules: ['ExponentFileSystemAppTM'],
|
|
17
18
|
},
|
|
18
19
|
},
|
|
19
20
|
},
|
|
@@ -39,7 +39,7 @@ interface Spec extends KeplerTurboModule {
|
|
|
39
39
|
readonly uploadAsync: (url: string, fileUri: string, options: Record<string, any>, requestId: number, headers: Array<{key: string, value: string}>) => Promise<FileSystemUploadResult>;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
const nativeModule = TurboModuleRegistry.getEnforcing<Spec>('
|
|
42
|
+
const nativeModule = TurboModuleRegistry.getEnforcing<Spec>('ExponentFileSystemAppTM') as Spec;
|
|
43
43
|
|
|
44
44
|
let _requestId = 1;
|
|
45
45
|
const generateRequestId = (): number => { return _requestId++; };
|