react-native-cloud-storage 2.2.2 → 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.
- package/LICENSE +1 -1
- package/README.md +1 -1
- package/android/build.gradle +88 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +3 -0
- package/android/src/main/AndroidManifestNew.xml +2 -0
- package/android/src/main/java/com/voicekit/CloudStorageError.kt +86 -0
- package/android/src/main/java/com/voicekit/CloudStorageLocalFileSystemModule.kt +232 -0
- package/android/src/main/java/com/voicekit/CloudStoragePackage.kt +32 -0
- package/android/src/main/java/com/voicekit/FileUtils.kt +41 -0
- package/android/src/main/java/com/voicekit/Types.kt +6 -0
- package/app.plugin.js +1 -1
- package/{lib/commonjs/RNCloudStorage.js → dist/commonjs/cloud-storage.js} +177 -92
- package/dist/commonjs/cloud-storage.js.map +1 -0
- package/dist/commonjs/expo-plugin/index.js +13 -0
- package/dist/commonjs/expo-plugin/index.js.map +1 -0
- package/{lib/commonjs/expo-plugin/withRNCloudStorageIos.js → dist/commonjs/expo-plugin/ios.js} +1 -1
- package/dist/commonjs/expo-plugin/ios.js.map +1 -0
- package/{lib/commonjs/hooks/useCloudFile.js → dist/commonjs/hooks/use-cloud-file.js} +26 -8
- package/dist/commonjs/hooks/use-cloud-file.js.map +1 -0
- package/{lib/commonjs/hooks/useIsCloudAvailable.js → dist/commonjs/hooks/use-is-cloud-available.js} +3 -3
- package/dist/commonjs/hooks/use-is-cloud-available.js.map +1 -0
- package/{lib → dist}/commonjs/index.js +10 -10
- package/dist/commonjs/index.js.map +1 -0
- package/dist/commonjs/specs/NativeCloudStorageCloudKitIOS.js +9 -0
- package/dist/commonjs/specs/NativeCloudStorageCloudKitIOS.js.map +1 -0
- package/dist/commonjs/specs/NativeCloudStorageLocalFileSystem.js +9 -0
- package/dist/commonjs/specs/NativeCloudStorageLocalFileSystem.js.map +1 -0
- package/dist/commonjs/storages/cloudkit.js +12 -0
- package/dist/commonjs/storages/cloudkit.js.map +1 -0
- package/{lib/commonjs → dist/commonjs/storages}/google-drive/client.js +83 -40
- package/dist/commonjs/storages/google-drive/client.js.map +1 -0
- package/dist/commonjs/storages/google-drive/index.js +399 -0
- package/dist/commonjs/storages/google-drive/index.js.map +1 -0
- package/dist/commonjs/storages/google-drive/types.js.map +1 -0
- package/{lib → dist}/commonjs/types/main.js.map +1 -1
- package/dist/commonjs/types/native.js +28 -0
- package/dist/commonjs/types/native.js.map +1 -0
- package/{lib/commonjs/utils/CloudStorageError.js → dist/commonjs/utils/cloud-storage-error.js} +3 -1
- package/dist/commonjs/utils/cloud-storage-error.js.map +1 -0
- package/dist/commonjs/utils/constants.js +25 -0
- package/dist/commonjs/utils/constants.js.map +1 -0
- package/dist/commonjs/utils/local-fs.js +17 -0
- package/dist/commonjs/utils/local-fs.js.map +1 -0
- package/dist/commonjs/utils/native.js +35 -0
- package/dist/commonjs/utils/native.js.map +1 -0
- package/{lib/module/RNCloudStorage.js → dist/module/cloud-storage.js} +178 -93
- package/dist/module/cloud-storage.js.map +1 -0
- package/dist/module/expo-plugin/index.js +8 -0
- package/dist/module/expo-plugin/index.js.map +1 -0
- package/{lib/module/expo-plugin/withRNCloudStorageIos.js → dist/module/expo-plugin/ios.js} +1 -1
- package/dist/module/expo-plugin/ios.js.map +1 -0
- package/{lib/module/hooks/useCloudFile.js → dist/module/hooks/use-cloud-file.js} +25 -7
- package/dist/module/hooks/use-cloud-file.js.map +1 -0
- package/{lib/module/hooks/useIsCloudAvailable.js → dist/module/hooks/use-is-cloud-available.js} +2 -2
- package/dist/module/hooks/use-is-cloud-available.js.map +1 -0
- package/dist/module/index.js +9 -0
- package/dist/module/index.js.map +1 -0
- package/dist/module/specs/NativeCloudStorageCloudKitIOS.js +5 -0
- package/dist/module/specs/NativeCloudStorageCloudKitIOS.js.map +1 -0
- package/dist/module/specs/NativeCloudStorageLocalFileSystem.js +5 -0
- package/dist/module/specs/NativeCloudStorageLocalFileSystem.js.map +1 -0
- package/dist/module/storages/cloudkit.js +7 -0
- package/dist/module/storages/cloudkit.js.map +1 -0
- package/{lib/module → dist/module/storages}/google-drive/client.js +83 -40
- package/dist/module/storages/google-drive/client.js.map +1 -0
- package/dist/module/storages/google-drive/index.js +392 -0
- package/dist/module/storages/google-drive/index.js.map +1 -0
- package/dist/module/storages/google-drive/types.js.map +1 -0
- package/{lib → dist}/module/types/main.js.map +1 -1
- package/dist/module/types/native.js +24 -0
- package/dist/module/types/native.js.map +1 -0
- package/{lib/module/utils/CloudStorageError.js → dist/module/utils/cloud-storage-error.js} +3 -1
- package/dist/module/utils/cloud-storage-error.js.map +1 -0
- package/dist/module/utils/constants.js +21 -0
- package/dist/module/utils/constants.js.map +1 -0
- package/dist/module/utils/local-fs.js +12 -0
- package/dist/module/utils/local-fs.js.map +1 -0
- package/dist/module/utils/native.js +30 -0
- package/dist/module/utils/native.js.map +1 -0
- package/{lib/typescript/RNCloudStorage.d.ts → dist/typescript/cloud-storage.d.ts} +67 -8
- package/dist/typescript/cloud-storage.d.ts.map +1 -0
- package/{lib/typescript/expo-plugin/withRNCloudStorage.d.ts → dist/typescript/expo-plugin/index.d.ts} +1 -1
- package/dist/typescript/expo-plugin/index.d.ts.map +1 -0
- package/{lib/typescript/expo-plugin/withRNCloudStorageIos.d.ts → dist/typescript/expo-plugin/ios.d.ts} +1 -1
- package/dist/typescript/expo-plugin/ios.d.ts.map +1 -0
- package/{lib/typescript/hooks/useCloudFile.d.ts → dist/typescript/hooks/use-cloud-file.d.ts} +22 -4
- package/dist/typescript/hooks/use-cloud-file.d.ts.map +1 -0
- package/{lib/typescript/hooks/useIsCloudAvailable.d.ts → dist/typescript/hooks/use-is-cloud-available.d.ts} +2 -2
- package/dist/typescript/hooks/use-is-cloud-available.d.ts.map +1 -0
- package/dist/typescript/index.d.ts +7 -0
- package/dist/typescript/index.d.ts.map +1 -0
- package/dist/typescript/specs/NativeCloudStorageCloudKitIOS.d.ts +30 -0
- package/dist/typescript/specs/NativeCloudStorageCloudKitIOS.d.ts.map +1 -0
- package/dist/typescript/specs/NativeCloudStorageLocalFileSystem.d.ts +24 -0
- package/dist/typescript/specs/NativeCloudStorageLocalFileSystem.d.ts.map +1 -0
- package/dist/typescript/storages/cloudkit.d.ts +6 -0
- package/dist/typescript/storages/cloudkit.d.ts.map +1 -0
- package/{lib/typescript → dist/typescript/storages}/google-drive/client.d.ts +10 -3
- package/dist/typescript/storages/google-drive/client.d.ts.map +1 -0
- package/dist/typescript/storages/google-drive/index.d.ts +41 -0
- package/dist/typescript/storages/google-drive/index.d.ts.map +1 -0
- package/dist/typescript/storages/google-drive/types.d.ts.map +1 -0
- package/{lib → dist}/typescript/types/main.d.ts +8 -0
- package/dist/typescript/types/main.d.ts.map +1 -0
- package/dist/typescript/types/native.d.ts +27 -0
- package/dist/typescript/types/native.d.ts.map +1 -0
- package/dist/typescript/utils/cloud-storage-error.d.ts +8 -0
- package/dist/typescript/utils/cloud-storage-error.d.ts.map +1 -0
- package/dist/typescript/utils/constants.d.ts +4 -0
- package/dist/typescript/utils/constants.d.ts.map +1 -0
- package/{lib → dist}/typescript/utils/helpers.d.ts.map +1 -1
- package/dist/typescript/utils/local-fs.d.ts +2 -0
- package/dist/typescript/utils/local-fs.d.ts.map +1 -0
- package/dist/typescript/utils/native.d.ts +7 -0
- package/dist/typescript/utils/native.d.ts.map +1 -0
- package/ios/CloudStorage-Bridging-Header.h +0 -1
- package/ios/CloudStorage.xcodeproj/project.pbxproj +12 -6
- package/ios/CloudStorageCloudKit.swift +159 -0
- package/ios/CloudStorageLocalFileSystem.swift +216 -0
- package/ios/RCTCloudStorageCloudKit.mm +209 -0
- package/ios/RCTCloudStorageLocalFileSystem.mm +149 -0
- package/ios/Utils/CloudKitUtils.swift +12 -6
- package/ios/Utils/CloudStorageError.swift +8 -0
- package/ios/Utils/FileUtils.swift +21 -4
- package/ios/Utils/Promise.swift +1 -0
- package/ios/Utils/Types.swift +8 -1
- package/ios/react_native_cloud_storage.h +6 -0
- package/package.json +64 -110
- package/react-native-cloud-storage.podspec +2 -0
- package/src/{RNCloudStorage.ts → cloud-storage.ts} +210 -100
- package/src/expo-plugin/{withRNCloudStorage.ts → index.ts} +2 -2
- package/src/hooks/{useCloudFile.ts → use-cloud-file.ts} +24 -6
- package/src/hooks/{useIsCloudAvailable.ts → use-is-cloud-available.ts} +1 -1
- package/src/index.ts +5 -6
- package/src/specs/NativeCloudStorageCloudKitIOS.ts +33 -0
- package/src/specs/NativeCloudStorageLocalFileSystem.ts +28 -0
- package/src/storages/cloudkit.ts +13 -0
- package/src/{google-drive → storages/google-drive}/client.ts +100 -41
- package/src/storages/google-drive/index.ts +488 -0
- package/src/types/main.ts +9 -0
- package/src/types/native.ts +14 -22
- package/src/utils/cloud-storage-error.ts +15 -0
- package/src/utils/constants.ts +21 -0
- package/src/utils/local-fs.ts +19 -0
- package/src/utils/native.ts +40 -0
- package/ios/CloudStorage.m +0 -22
- package/ios/CloudStorage.swift +0 -103
- package/ios/CloudStorageEventEmitter.m +0 -16
- package/ios/CloudStorageEventEmitter.swift +0 -30
- package/lib/commonjs/RNCloudStorage.js.map +0 -1
- package/lib/commonjs/expo-plugin/withRNCloudStorage.js +0 -13
- package/lib/commonjs/expo-plugin/withRNCloudStorage.js.map +0 -1
- package/lib/commonjs/expo-plugin/withRNCloudStorageIos.js.map +0 -1
- package/lib/commonjs/google-drive/client.js.map +0 -1
- package/lib/commonjs/google-drive/index.js +0 -321
- package/lib/commonjs/google-drive/index.js.map +0 -1
- package/lib/commonjs/google-drive/types.js.map +0 -1
- package/lib/commonjs/hooks/useCloudFile.js.map +0 -1
- package/lib/commonjs/hooks/useIsCloudAvailable.js.map +0 -1
- package/lib/commonjs/index.js.map +0 -1
- package/lib/commonjs/types/native.js +0 -26
- package/lib/commonjs/types/native.js.map +0 -1
- package/lib/commonjs/utils/CloudStorageError.js.map +0 -1
- package/lib/module/RNCloudStorage.js.map +0 -1
- package/lib/module/expo-plugin/withRNCloudStorage.js +0 -8
- package/lib/module/expo-plugin/withRNCloudStorage.js.map +0 -1
- package/lib/module/expo-plugin/withRNCloudStorageIos.js.map +0 -1
- package/lib/module/google-drive/client.js.map +0 -1
- package/lib/module/google-drive/index.js +0 -313
- package/lib/module/google-drive/index.js.map +0 -1
- package/lib/module/google-drive/types.js.map +0 -1
- package/lib/module/hooks/useCloudFile.js.map +0 -1
- package/lib/module/hooks/useIsCloudAvailable.js.map +0 -1
- package/lib/module/index.js +0 -10
- package/lib/module/index.js.map +0 -1
- package/lib/module/types/native.js +0 -22
- package/lib/module/types/native.js.map +0 -1
- package/lib/module/utils/CloudStorageError.js.map +0 -1
- package/lib/typescript/RNCloudStorage.d.ts.map +0 -1
- package/lib/typescript/expo-plugin/withRNCloudStorage.d.ts.map +0 -1
- package/lib/typescript/expo-plugin/withRNCloudStorageIos.d.ts.map +0 -1
- package/lib/typescript/google-drive/client.d.ts.map +0 -1
- package/lib/typescript/google-drive/index.d.ts +0 -34
- package/lib/typescript/google-drive/index.d.ts.map +0 -1
- package/lib/typescript/google-drive/types.d.ts.map +0 -1
- package/lib/typescript/hooks/useCloudFile.d.ts.map +0 -1
- package/lib/typescript/hooks/useIsCloudAvailable.d.ts.map +0 -1
- package/lib/typescript/index.d.ts +0 -8
- package/lib/typescript/index.d.ts.map +0 -1
- package/lib/typescript/types/main.d.ts.map +0 -1
- package/lib/typescript/types/native.d.ts +0 -40
- package/lib/typescript/types/native.d.ts.map +0 -1
- package/lib/typescript/utils/CloudStorageError.d.ts +0 -8
- package/lib/typescript/utils/CloudStorageError.d.ts.map +0 -1
- package/src/google-drive/index.ts +0 -399
- package/src/utils/CloudStorageError.ts +0 -14
- /package/{lib → dist}/commonjs/expo-plugin/types/index.js +0 -0
- /package/{lib → dist}/commonjs/expo-plugin/types/index.js.map +0 -0
- /package/{lib/commonjs → dist/commonjs/storages}/google-drive/types.js +0 -0
- /package/{lib → dist}/commonjs/types/main.js +0 -0
- /package/{lib → dist}/commonjs/utils/helpers.js +0 -0
- /package/{lib → dist}/commonjs/utils/helpers.js.map +0 -0
- /package/{lib → dist}/module/expo-plugin/types/index.js +0 -0
- /package/{lib → dist}/module/expo-plugin/types/index.js.map +0 -0
- /package/{lib → dist}/module/package.json +0 -0
- /package/{lib/module → dist/module/storages}/google-drive/types.js +0 -0
- /package/{lib → dist}/module/types/main.js +0 -0
- /package/{lib → dist}/module/utils/helpers.js +0 -0
- /package/{lib → dist}/module/utils/helpers.js.map +0 -0
- /package/{lib → dist}/typescript/expo-plugin/types/index.d.ts +0 -0
- /package/{lib → dist}/typescript/expo-plugin/types/index.d.ts.map +0 -0
- /package/{lib/typescript → dist/typescript/storages}/google-drive/types.d.ts +0 -0
- /package/{lib → dist}/typescript/utils/helpers.d.ts +0 -0
- /package/src/expo-plugin/{withRNCloudStorageIos.ts → ios.ts} +0 -0
- /package/src/{google-drive → storages/google-drive}/types.ts +0 -0
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
import {
|
|
2
|
+
NativeCloudStorageErrorCode,
|
|
3
|
+
NativeStorage,
|
|
4
|
+
type NativeStorageFileStat,
|
|
5
|
+
type NativeStorageScope,
|
|
6
|
+
} from '../../types/native';
|
|
7
|
+
import CloudStorageError from '../../utils/cloud-storage-error';
|
|
8
|
+
import { MimeTypes, type GoogleDriveFile, type GoogleDriveFileSpace } from './types';
|
|
9
|
+
import GoogleDriveApiClient, { GoogleDriveHttpError } from './client';
|
|
10
|
+
import { type CloudStorageProviderOptions, type DeepRequired } from '../../types/main';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* A JavaScript-based implementation of the Google Drive API that implements the cloud storage interface.
|
|
14
|
+
*/
|
|
15
|
+
export default class GoogleDrive implements NativeStorage {
|
|
16
|
+
private drive: GoogleDriveApiClient;
|
|
17
|
+
private options: DeepRequired<CloudStorageProviderOptions['googledrive']>;
|
|
18
|
+
|
|
19
|
+
constructor(options: DeepRequired<CloudStorageProviderOptions['googledrive']>) {
|
|
20
|
+
this.options = options;
|
|
21
|
+
this.drive = new GoogleDriveApiClient(options);
|
|
22
|
+
|
|
23
|
+
return new Proxy(this, {
|
|
24
|
+
// before calling any function, check if the access token is set
|
|
25
|
+
get(target: GoogleDrive, property: keyof GoogleDrive) {
|
|
26
|
+
const allowedFunctions = ['isCloudAvailable'];
|
|
27
|
+
if (typeof target[property] === 'function' && !allowedFunctions.includes(property.toString())) {
|
|
28
|
+
const { accessToken } = options;
|
|
29
|
+
if (!accessToken?.length) {
|
|
30
|
+
throw new CloudStorageError(
|
|
31
|
+
`Google Drive access token is not set, cannot call function ${property.toString()}`,
|
|
32
|
+
NativeCloudStorageErrorCode.ACCESS_TOKEN_MISSING
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return target[property];
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public isCloudAvailable: () => Promise<boolean> = async () => {
|
|
43
|
+
const { accessToken } = this.options;
|
|
44
|
+
return !!accessToken?.length;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
private getRootDirectory(scope: NativeStorageScope): GoogleDriveFileSpace {
|
|
48
|
+
switch (scope) {
|
|
49
|
+
case 'documents': {
|
|
50
|
+
return 'drive';
|
|
51
|
+
}
|
|
52
|
+
case 'documents_legacy': {
|
|
53
|
+
return 'drive';
|
|
54
|
+
}
|
|
55
|
+
case 'app_data': {
|
|
56
|
+
return 'appDataFolder';
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
private isRootPath(path: string): boolean {
|
|
62
|
+
return path === '' || path === '/';
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
private resolvePathToDirectories(path: string): {
|
|
66
|
+
directories: string[];
|
|
67
|
+
filename: string;
|
|
68
|
+
} {
|
|
69
|
+
if (path.startsWith('/')) path = path.slice(1);
|
|
70
|
+
if (path.endsWith('/')) path = path.slice(0, -1);
|
|
71
|
+
const directories = path.split('/');
|
|
72
|
+
const actualFilename = directories.pop() ?? '';
|
|
73
|
+
return { directories, filename: actualFilename };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
private escapeDriveQueryValue(value: string): string {
|
|
77
|
+
return value.replaceAll('\\', String.raw`\\`).replaceAll("'", String.raw`\'`);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
private async getQueryRootParentId(scope: NativeStorageScope): Promise<string> {
|
|
81
|
+
if (scope === 'app_data') {
|
|
82
|
+
return this.getRootDirectory(scope);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return this.getRootDirectoryId(scope);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
private async findDirectoryByNameAndParent(
|
|
89
|
+
name: string,
|
|
90
|
+
parentId: string,
|
|
91
|
+
scope: NativeStorageScope
|
|
92
|
+
): Promise<GoogleDriveFile[]> {
|
|
93
|
+
const escapedName = this.escapeDriveQueryValue(name);
|
|
94
|
+
const escapedParentId = this.escapeDriveQueryValue(parentId);
|
|
95
|
+
const query = `name = '${escapedName}' and '${escapedParentId}' in parents and mimeType = '${MimeTypes.FOLDER}' and trashed = false`;
|
|
96
|
+
return this.drive.listFiles(this.getRootDirectory(scope), query);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
private async findFilesByNameAndParent(
|
|
100
|
+
name: string,
|
|
101
|
+
parentId: string,
|
|
102
|
+
scope: NativeStorageScope
|
|
103
|
+
): Promise<GoogleDriveFile[]> {
|
|
104
|
+
const escapedName = this.escapeDriveQueryValue(name);
|
|
105
|
+
const escapedParentId = this.escapeDriveQueryValue(parentId);
|
|
106
|
+
const query = `name = '${escapedName}' and '${escapedParentId}' in parents and trashed = false`;
|
|
107
|
+
return this.drive.listFiles(this.getRootDirectory(scope), query);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
private async findFilesByParent(parentId: string, scope: NativeStorageScope): Promise<GoogleDriveFile[]> {
|
|
111
|
+
const escapedParentId = this.escapeDriveQueryValue(parentId);
|
|
112
|
+
const query = `'${escapedParentId}' in parents and trashed = false`;
|
|
113
|
+
return this.drive.listFiles(this.getRootDirectory(scope), query);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
private async findParentDirectoryId(directoryTree: string[], scope: NativeStorageScope): Promise<string | null> {
|
|
117
|
+
let parentDirectoryId = await this.getQueryRootParentId(scope);
|
|
118
|
+
|
|
119
|
+
for (const directoryName of directoryTree) {
|
|
120
|
+
const directories = await this.findDirectoryByNameAndParent(directoryName, parentDirectoryId, scope);
|
|
121
|
+
if (directories.length === 0) {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
parentDirectoryId = directories[0]!.id;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return parentDirectoryId;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Gets the Google Drive ID of the root directory for the given scope.
|
|
133
|
+
* @param scope The scope to get the root directory for.
|
|
134
|
+
* @returns A promise that resolves to the ID of the root directory.
|
|
135
|
+
*/
|
|
136
|
+
private async getRootDirectoryId(scope: NativeStorageScope): Promise<string> {
|
|
137
|
+
if (scope !== 'app_data') {
|
|
138
|
+
return 'root';
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const files = await this.drive.listFiles(this.getRootDirectory(scope));
|
|
142
|
+
for (const file of files) {
|
|
143
|
+
const parentId = file.parents?.[0];
|
|
144
|
+
if (parentId && !files.some((candidate) => candidate.id === parentId)) {
|
|
145
|
+
return parentId;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return this.getRootDirectory(scope);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
private checkIfMultipleFilesWithSameName(path: string, files: GoogleDriveFile[]) {
|
|
153
|
+
const { strictFilenames } = this.options;
|
|
154
|
+
|
|
155
|
+
if (files.length <= 1) return;
|
|
156
|
+
|
|
157
|
+
if (strictFilenames) {
|
|
158
|
+
throw new CloudStorageError(
|
|
159
|
+
`Multiple files with the same name found at path ${path}: ${files.map((f) => f.id).join(', ')}`,
|
|
160
|
+
NativeCloudStorageErrorCode.MULTIPLE_FILES_SAME_NAME
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
private async getFileId(
|
|
166
|
+
path: string,
|
|
167
|
+
scope: NativeStorageScope,
|
|
168
|
+
throwIf: 'directory' | 'file' | false = false
|
|
169
|
+
): Promise<string> {
|
|
170
|
+
try {
|
|
171
|
+
if (this.isRootPath(path)) {
|
|
172
|
+
if (throwIf === 'directory') {
|
|
173
|
+
throw new CloudStorageError(`Path ${path} is a directory`, NativeCloudStorageErrorCode.PATH_IS_DIRECTORY);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const rootDirectoryId = await this.getRootDirectoryId(scope);
|
|
177
|
+
if (scope !== 'app_data') {
|
|
178
|
+
await this.drive.getFile(rootDirectoryId);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return rootDirectoryId;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const { directories, filename } = this.resolvePathToDirectories(path);
|
|
185
|
+
const parentDirectoryId = await this.findParentDirectoryId(directories, scope);
|
|
186
|
+
if (parentDirectoryId === null) {
|
|
187
|
+
throw new CloudStorageError(`File not found`, NativeCloudStorageErrorCode.FILE_NOT_FOUND);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const files = await this.findFilesByNameAndParent(filename, parentDirectoryId, scope);
|
|
191
|
+
this.checkIfMultipleFilesWithSameName(path, files);
|
|
192
|
+
|
|
193
|
+
const file = files[0];
|
|
194
|
+
if (!file) throw new CloudStorageError(`File not found`, NativeCloudStorageErrorCode.FILE_NOT_FOUND);
|
|
195
|
+
if (file.mimeType === MimeTypes.FOLDER && throwIf === 'directory') {
|
|
196
|
+
throw new CloudStorageError(`Path ${path} is a directory`, NativeCloudStorageErrorCode.PATH_IS_DIRECTORY);
|
|
197
|
+
} else if (file.mimeType !== MimeTypes.FOLDER && throwIf === 'file') {
|
|
198
|
+
throw new CloudStorageError(`Path ${path} is a file`, NativeCloudStorageErrorCode.FILE_NOT_FOUND);
|
|
199
|
+
}
|
|
200
|
+
return file.id;
|
|
201
|
+
} catch (error: unknown) {
|
|
202
|
+
if (error instanceof GoogleDriveHttpError && error.json?.error?.status === 'UNAUTHENTICATED') {
|
|
203
|
+
throw new CloudStorageError(
|
|
204
|
+
`Could not authenticate with Google Drive`,
|
|
205
|
+
NativeCloudStorageErrorCode.AUTHENTICATION_FAILED,
|
|
206
|
+
error.json
|
|
207
|
+
);
|
|
208
|
+
} else {
|
|
209
|
+
if (error instanceof CloudStorageError) throw error;
|
|
210
|
+
throw new CloudStorageError(
|
|
211
|
+
`Could not get file id for path ${path}`,
|
|
212
|
+
NativeCloudStorageErrorCode.UNKNOWN,
|
|
213
|
+
error
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
async fileExists(path: string, scope: NativeStorageScope): Promise<boolean> {
|
|
220
|
+
try {
|
|
221
|
+
await this.getFileId(path, scope);
|
|
222
|
+
return true;
|
|
223
|
+
} catch (error: unknown) {
|
|
224
|
+
if (error instanceof CloudStorageError && error.code === NativeCloudStorageErrorCode.FILE_NOT_FOUND) return false;
|
|
225
|
+
else throw error;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
async appendToFile(path: string, data: string, scope: NativeStorageScope): Promise<void> {
|
|
230
|
+
let fileId: string | undefined;
|
|
231
|
+
let previousContent = '';
|
|
232
|
+
try {
|
|
233
|
+
fileId = await this.getFileId(path, scope, 'directory');
|
|
234
|
+
previousContent = await this.drive.getFileText(fileId);
|
|
235
|
+
} catch (error: unknown) {
|
|
236
|
+
if (error instanceof CloudStorageError && error.code === NativeCloudStorageErrorCode.FILE_NOT_FOUND) {
|
|
237
|
+
/* do nothing, simply create the file */
|
|
238
|
+
} else {
|
|
239
|
+
throw error;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (fileId) {
|
|
244
|
+
await this.drive.updateFile(fileId, {
|
|
245
|
+
body: previousContent + data,
|
|
246
|
+
mimeType: MimeTypes.TEXT,
|
|
247
|
+
});
|
|
248
|
+
} else {
|
|
249
|
+
const { directories, filename } = this.resolvePathToDirectories(path);
|
|
250
|
+
const parentDirectoryId = await this.findParentDirectoryId(directories, scope);
|
|
251
|
+
if (parentDirectoryId === null) {
|
|
252
|
+
throw new CloudStorageError(`Directory not found`, NativeCloudStorageErrorCode.DIRECTORY_NOT_FOUND);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
await this.drive.createFile(
|
|
256
|
+
{
|
|
257
|
+
name: filename,
|
|
258
|
+
parents: [parentDirectoryId],
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
body: data,
|
|
262
|
+
mimeType: MimeTypes.TEXT,
|
|
263
|
+
}
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
async createFile(path: string, data: string, scope: NativeStorageScope, overwrite: boolean): Promise<void> {
|
|
269
|
+
let fileId: string | undefined;
|
|
270
|
+
if (overwrite) {
|
|
271
|
+
try {
|
|
272
|
+
fileId = await this.getFileId(path, scope, 'directory');
|
|
273
|
+
} catch (error: unknown) {
|
|
274
|
+
if (error instanceof CloudStorageError && error.code === NativeCloudStorageErrorCode.FILE_NOT_FOUND) {
|
|
275
|
+
/* do nothing, simply create the file */
|
|
276
|
+
} else {
|
|
277
|
+
throw error;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
} else {
|
|
281
|
+
try {
|
|
282
|
+
await this.getFileId(path, scope, 'directory');
|
|
283
|
+
throw new CloudStorageError(`File ${path} already exists`, NativeCloudStorageErrorCode.FILE_ALREADY_EXISTS);
|
|
284
|
+
} catch (error: unknown) {
|
|
285
|
+
if (error instanceof CloudStorageError && error.code === NativeCloudStorageErrorCode.FILE_NOT_FOUND) {
|
|
286
|
+
/* do nothing, simply create the file */
|
|
287
|
+
} else {
|
|
288
|
+
throw error;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
if (fileId) {
|
|
294
|
+
await this.drive.updateFile(fileId, {
|
|
295
|
+
body: data,
|
|
296
|
+
mimeType: MimeTypes.TEXT,
|
|
297
|
+
});
|
|
298
|
+
} else {
|
|
299
|
+
const { directories, filename } = this.resolvePathToDirectories(path);
|
|
300
|
+
const parentDirectoryId = await this.findParentDirectoryId(directories, scope);
|
|
301
|
+
if (parentDirectoryId === null) {
|
|
302
|
+
throw new CloudStorageError(`Directory not found`, NativeCloudStorageErrorCode.DIRECTORY_NOT_FOUND);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
await this.drive.createFile(
|
|
306
|
+
{
|
|
307
|
+
name: filename,
|
|
308
|
+
parents: [parentDirectoryId],
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
body: data,
|
|
312
|
+
mimeType: MimeTypes.TEXT,
|
|
313
|
+
}
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
async listFiles(path: string, scope: NativeStorageScope): Promise<string[]> {
|
|
319
|
+
const parentDirectoryId = this.isRootPath(path)
|
|
320
|
+
? await this.getQueryRootParentId(scope)
|
|
321
|
+
: await this.getFileId(path, scope);
|
|
322
|
+
|
|
323
|
+
const files = await this.findFilesByParent(parentDirectoryId, scope);
|
|
324
|
+
return [...new Set(files.map((f) => f.name))];
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
async createDirectory(path: string, scope: NativeStorageScope): Promise<void> {
|
|
328
|
+
if (this.isRootPath(path)) {
|
|
329
|
+
throw new CloudStorageError(`Directory ${path} already exists`, NativeCloudStorageErrorCode.FILE_ALREADY_EXISTS);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
try {
|
|
333
|
+
await this.getFileId(path, scope);
|
|
334
|
+
throw new CloudStorageError(`File ${path} already exists`, NativeCloudStorageErrorCode.FILE_ALREADY_EXISTS);
|
|
335
|
+
} catch (error: unknown) {
|
|
336
|
+
if (error instanceof CloudStorageError && error.code === NativeCloudStorageErrorCode.FILE_NOT_FOUND) {
|
|
337
|
+
/* do nothing, simply create the directory */
|
|
338
|
+
} else if (error instanceof CloudStorageError && error.code === NativeCloudStorageErrorCode.PATH_IS_DIRECTORY) {
|
|
339
|
+
throw new CloudStorageError(
|
|
340
|
+
`Directory ${path} already exists`,
|
|
341
|
+
NativeCloudStorageErrorCode.FILE_ALREADY_EXISTS
|
|
342
|
+
);
|
|
343
|
+
} else {
|
|
344
|
+
throw error;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
const { directories, filename } = this.resolvePathToDirectories(path);
|
|
349
|
+
const parentDirectoryId = await this.findParentDirectoryId(directories, scope);
|
|
350
|
+
if (parentDirectoryId === null) {
|
|
351
|
+
throw new CloudStorageError(`Directory not found`, NativeCloudStorageErrorCode.DIRECTORY_NOT_FOUND);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
await this.drive.createDirectory({
|
|
355
|
+
name: filename,
|
|
356
|
+
parents: [parentDirectoryId],
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
async readFile(path: string, scope: NativeStorageScope): Promise<string> {
|
|
361
|
+
const fileId = await this.getFileId(path, scope, 'directory');
|
|
362
|
+
const content = await this.drive.getFileText(fileId);
|
|
363
|
+
return content;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
async triggerSync(_path: string, _scope: NativeStorageScope): Promise<void> {
|
|
367
|
+
// Triggering file synchronization in Google Drive is not necessary / possible, as they need to be downloaded on every read operation via the API anyway
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
async deleteFile(path: string, scope: NativeStorageScope): Promise<void> {
|
|
372
|
+
// if trying to pass a directory, throw an error
|
|
373
|
+
const fileId = await this.getFileId(path, scope, 'directory');
|
|
374
|
+
await this.drive.deleteFile(fileId);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
async deleteDirectory(path: string, recursive: boolean, scope: NativeStorageScope): Promise<void> {
|
|
378
|
+
// if trying to pass a file, throw an error
|
|
379
|
+
const fileId = await this.getFileId(path, scope, 'file');
|
|
380
|
+
|
|
381
|
+
if (!recursive) {
|
|
382
|
+
// check if the directory is empty
|
|
383
|
+
const filesInDirectory = await this.findFilesByParent(fileId, scope);
|
|
384
|
+
if (filesInDirectory.length > 0) {
|
|
385
|
+
throw new CloudStorageError(
|
|
386
|
+
`Directory ${path} is not empty`,
|
|
387
|
+
NativeCloudStorageErrorCode.DELETE_ERROR,
|
|
388
|
+
filesInDirectory
|
|
389
|
+
);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
await this.drive.deleteFile(fileId);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
async statFile(path: string, scope: NativeStorageScope): Promise<NativeStorageFileStat> {
|
|
397
|
+
const fileId = await this.getFileId(path, scope, false);
|
|
398
|
+
const file = await this.drive.getFile(fileId!);
|
|
399
|
+
|
|
400
|
+
return {
|
|
401
|
+
size: file.size ?? 0,
|
|
402
|
+
birthtimeMs: new Date(file.createdTime!).getTime(),
|
|
403
|
+
mtimeMs: new Date(file.modifiedTime!).getTime(),
|
|
404
|
+
isDirectory: file.mimeType === MimeTypes.FOLDER,
|
|
405
|
+
isFile: file.mimeType !== MimeTypes.FOLDER,
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
async downloadFile(remotePath: string, localPath: string, scope: NativeStorageScope): Promise<void> {
|
|
410
|
+
const fileId = await this.getFileId(remotePath, scope, 'directory');
|
|
411
|
+
|
|
412
|
+
try {
|
|
413
|
+
await this.drive.downloadFile(fileId, localPath);
|
|
414
|
+
} catch (error: unknown) {
|
|
415
|
+
if (error instanceof CloudStorageError) throw error;
|
|
416
|
+
|
|
417
|
+
throw new CloudStorageError(
|
|
418
|
+
`Could not download file ${remotePath} to ${localPath}`,
|
|
419
|
+
NativeCloudStorageErrorCode.UNKNOWN,
|
|
420
|
+
error
|
|
421
|
+
);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
async uploadFile(
|
|
426
|
+
remotePath: string,
|
|
427
|
+
localPath: string,
|
|
428
|
+
mimeType: string,
|
|
429
|
+
scope: NativeStorageScope,
|
|
430
|
+
overwrite: boolean
|
|
431
|
+
): Promise<void> {
|
|
432
|
+
let fileId: string | undefined;
|
|
433
|
+
|
|
434
|
+
if (overwrite) {
|
|
435
|
+
try {
|
|
436
|
+
fileId = await this.getFileId(remotePath, scope, 'directory');
|
|
437
|
+
} catch (error: unknown) {
|
|
438
|
+
if (error instanceof CloudStorageError && error.code === NativeCloudStorageErrorCode.FILE_NOT_FOUND) {
|
|
439
|
+
/* File doesn't exist -> we'll create it below */
|
|
440
|
+
} else {
|
|
441
|
+
throw error;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
} else {
|
|
445
|
+
try {
|
|
446
|
+
await this.getFileId(remotePath, scope, 'directory');
|
|
447
|
+
throw new CloudStorageError(
|
|
448
|
+
`File ${remotePath} already exists`,
|
|
449
|
+
NativeCloudStorageErrorCode.FILE_ALREADY_EXISTS
|
|
450
|
+
);
|
|
451
|
+
} catch (error: unknown) {
|
|
452
|
+
if (error instanceof CloudStorageError && error.code === NativeCloudStorageErrorCode.FILE_NOT_FOUND) {
|
|
453
|
+
/* not found -> ok, we'll create */
|
|
454
|
+
} else if (error instanceof CloudStorageError) {
|
|
455
|
+
throw error;
|
|
456
|
+
} else {
|
|
457
|
+
throw error;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
if (fileId) {
|
|
463
|
+
// Overwrite existing file
|
|
464
|
+
await this.drive.updateFile(fileId, {
|
|
465
|
+
mimeType,
|
|
466
|
+
localPath,
|
|
467
|
+
});
|
|
468
|
+
} else {
|
|
469
|
+
// Need to create a new file first
|
|
470
|
+
const { directories, filename } = this.resolvePathToDirectories(remotePath);
|
|
471
|
+
const parentDirectoryId = await this.findParentDirectoryId(directories, scope);
|
|
472
|
+
if (parentDirectoryId === null) {
|
|
473
|
+
throw new CloudStorageError(`Directory not found`, NativeCloudStorageErrorCode.DIRECTORY_NOT_FOUND);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
await this.drive.createFile(
|
|
477
|
+
{
|
|
478
|
+
name: filename,
|
|
479
|
+
parents: [parentDirectoryId],
|
|
480
|
+
},
|
|
481
|
+
{
|
|
482
|
+
mimeType,
|
|
483
|
+
localPath,
|
|
484
|
+
}
|
|
485
|
+
);
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
}
|
package/src/types/main.ts
CHANGED
|
@@ -8,6 +8,8 @@ export enum CloudStorageScope {
|
|
|
8
8
|
AppData = 'app_data',
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
+
export type ICloudDocumentsMode = 'icloud' | 'legacy_sandbox';
|
|
12
|
+
|
|
11
13
|
export interface CloudStorageFileStat {
|
|
12
14
|
size: number;
|
|
13
15
|
birthtimeMs: number;
|
|
@@ -29,6 +31,13 @@ export interface CloudStorageProviderOptions {
|
|
|
29
31
|
* The directory scope to use for iCloud operations. Defaults to 'app_data'.
|
|
30
32
|
*/
|
|
31
33
|
scope?: CloudStorageScope;
|
|
34
|
+
/**
|
|
35
|
+
* The directory mode to use for CloudStorageScope.Documents.
|
|
36
|
+
* `icloud` uses the user-facing iCloud Documents directory, while
|
|
37
|
+
* `legacy_sandbox` uses the local app sandbox Documents directory.
|
|
38
|
+
* Defaults to `icloud`.
|
|
39
|
+
*/
|
|
40
|
+
documentsMode?: ICloudDocumentsMode;
|
|
32
41
|
};
|
|
33
42
|
|
|
34
43
|
[CloudStorageProvider.GoogleDrive]: {
|
package/src/types/native.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
|
|
1
|
+
import type {
|
|
2
|
+
CloudStorageFileStat,
|
|
3
|
+
Spec as NativeCloudStorageCloudKitSpec,
|
|
4
|
+
} from '../specs/NativeCloudStorageCloudKitIOS';
|
|
5
|
+
import type { Spec as NativeCloudStorageLocalFileSystemSpec } from '../specs/NativeCloudStorageLocalFileSystem';
|
|
2
6
|
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
mtimeMs: number;
|
|
7
|
-
isDirectory: boolean;
|
|
8
|
-
isFile: boolean;
|
|
9
|
-
}
|
|
7
|
+
export type NativeStorageScope = 'documents' | 'documents_legacy' | 'app_data';
|
|
8
|
+
|
|
9
|
+
export type NativeStorageFileStat = CloudStorageFileStat;
|
|
10
10
|
|
|
11
|
-
export enum
|
|
11
|
+
export enum NativeCloudStorageErrorCode {
|
|
12
12
|
INVALID_SCOPE = 'ERR_INVALID_SCOPE',
|
|
13
13
|
FILE_NOT_FOUND = 'ERR_FILE_NOT_FOUND',
|
|
14
14
|
PATH_IS_FILE = 'ERR_PATH_IS_FILE',
|
|
@@ -25,18 +25,10 @@ export enum CloudStorageErrorCode {
|
|
|
25
25
|
UNKNOWN = 'ERR_UNKNOWN',
|
|
26
26
|
FILE_NOT_DOWNLOADABLE = 'ERR_FILE_NOT_DOWNLOADABLE',
|
|
27
27
|
ACCESS_TOKEN_MISSING = 'ERR_ACCESS_TOKEN_MISSING',
|
|
28
|
+
INVALID_URL = 'ERR_INVALID_URL',
|
|
29
|
+
NETWORK_ERROR = 'ERR_NETWORK_ERROR',
|
|
28
30
|
}
|
|
29
31
|
|
|
30
|
-
export
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
createFile: (path: string, data: string, scope: NativeRNCloudCloudStorageScope, overwrite: boolean) => Promise<void>;
|
|
34
|
-
createDirectory: (path: string, scope: NativeRNCloudCloudStorageScope) => Promise<void>;
|
|
35
|
-
listFiles: (path: string, scope: NativeRNCloudCloudStorageScope) => Promise<string[]>;
|
|
36
|
-
readFile: (path: string, scope: NativeRNCloudCloudStorageScope) => Promise<string>;
|
|
37
|
-
downloadFile: (path: string, scope: NativeRNCloudCloudStorageScope) => Promise<void>;
|
|
38
|
-
deleteFile: (path: string, scope: NativeRNCloudCloudStorageScope) => Promise<void>;
|
|
39
|
-
deleteDirectory: (path: string, recursively: boolean, scope: NativeRNCloudCloudStorageScope) => Promise<void>;
|
|
40
|
-
statFile: (path: string, scope: NativeRNCloudCloudStorageScope) => Promise<NativeRNCloudCloudStorageFileStat>;
|
|
41
|
-
isCloudAvailable: () => Promise<boolean>;
|
|
42
|
-
}
|
|
32
|
+
export type NativeLocalFileSystem = NativeCloudStorageLocalFileSystemSpec;
|
|
33
|
+
|
|
34
|
+
export type NativeStorage = Omit<NativeCloudStorageCloudKitSpec, 'onCloudAvailabilityChanged'>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import type { NativeCloudStorageErrorCode } from '../types/native';
|
|
3
|
+
|
|
4
|
+
class CloudStorageError extends Error {
|
|
5
|
+
code: NativeCloudStorageErrorCode;
|
|
6
|
+
details?: any;
|
|
7
|
+
|
|
8
|
+
constructor(message: string, code: NativeCloudStorageErrorCode, details?: any) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.code = code;
|
|
11
|
+
this.details = details;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export default CloudStorageError;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Platform } from 'react-native';
|
|
2
|
+
import { CloudStorageProvider, CloudStorageProviderOptions, CloudStorageScope, DeepRequired } from '../types/main';
|
|
3
|
+
|
|
4
|
+
export const LINKING_ERROR =
|
|
5
|
+
`The package 'react-native-cloud-storage' doesn't seem to be linked. Make sure: \n\n` +
|
|
6
|
+
Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) +
|
|
7
|
+
'- You rebuilt the app after installing the package\n' +
|
|
8
|
+
'- You are not using Expo Go\n';
|
|
9
|
+
|
|
10
|
+
export const DEFAULT_PROVIDER_OPTIONS: DeepRequired<CloudStorageProviderOptions> = {
|
|
11
|
+
[CloudStorageProvider.ICloud]: {
|
|
12
|
+
scope: CloudStorageScope.AppData,
|
|
13
|
+
documentsMode: 'icloud',
|
|
14
|
+
},
|
|
15
|
+
[CloudStorageProvider.GoogleDrive]: {
|
|
16
|
+
scope: CloudStorageScope.AppData,
|
|
17
|
+
accessToken: null,
|
|
18
|
+
strictFilenames: false,
|
|
19
|
+
timeout: 3000,
|
|
20
|
+
},
|
|
21
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import NativeCloudStorageLocalFileSystem from '../specs/NativeCloudStorageLocalFileSystem';
|
|
2
|
+
import { NativeLocalFileSystem as TNativeLocalFileSystem } from '../types/native';
|
|
3
|
+
import { createProxiedNativeModule } from '../utils/native';
|
|
4
|
+
import { LINKING_ERROR } from './constants';
|
|
5
|
+
|
|
6
|
+
const NativeLocalFileSystem = createProxiedNativeModule<TNativeLocalFileSystem>(
|
|
7
|
+
NativeCloudStorageLocalFileSystem as unknown as TNativeLocalFileSystem | null
|
|
8
|
+
);
|
|
9
|
+
|
|
10
|
+
export const localFileSystem =
|
|
11
|
+
NativeLocalFileSystem ??
|
|
12
|
+
(new Proxy(
|
|
13
|
+
{},
|
|
14
|
+
{
|
|
15
|
+
get() {
|
|
16
|
+
throw new Error(LINKING_ERROR);
|
|
17
|
+
},
|
|
18
|
+
}
|
|
19
|
+
) as TNativeLocalFileSystem);
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { NativeCloudStorageErrorCode } from '../types/native';
|
|
2
|
+
import CloudStorageError from './cloud-storage-error';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Creates a proxied native module that wraps thrown errors in a CloudStorageError.
|
|
6
|
+
* @param nativeModule The native module to proxy.
|
|
7
|
+
* @returns The proxied native module.
|
|
8
|
+
*/
|
|
9
|
+
export const createProxiedNativeModule = <T extends object>(nativeModule: T | null | undefined): T | null => {
|
|
10
|
+
if (!nativeModule) return null;
|
|
11
|
+
|
|
12
|
+
return new Proxy(nativeModule, {
|
|
13
|
+
get(target: T, property: string | symbol, receiver: unknown) {
|
|
14
|
+
const originalValue = Reflect.get(target, property, receiver);
|
|
15
|
+
|
|
16
|
+
if (typeof originalValue === 'function') {
|
|
17
|
+
return async (...arguments_: unknown[]) => {
|
|
18
|
+
try {
|
|
19
|
+
return await Reflect.apply(originalValue, target, arguments_);
|
|
20
|
+
} catch (error: unknown) {
|
|
21
|
+
const error_ =
|
|
22
|
+
typeof error === 'object' &&
|
|
23
|
+
error !== null &&
|
|
24
|
+
'code' in error &&
|
|
25
|
+
typeof error.code === 'string' &&
|
|
26
|
+
Object.values(NativeCloudStorageErrorCode).includes(error.code as NativeCloudStorageErrorCode)
|
|
27
|
+
? new CloudStorageError(
|
|
28
|
+
'message' in error && typeof error.message === 'string' ? error.message : 'Unknown error',
|
|
29
|
+
error.code as NativeCloudStorageErrorCode
|
|
30
|
+
)
|
|
31
|
+
: new CloudStorageError('Unknown error', NativeCloudStorageErrorCode.UNKNOWN, error);
|
|
32
|
+
throw error_;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return originalValue;
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
};
|
package/ios/CloudStorage.m
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
#import <React/RCTBridgeModule.h>
|
|
2
|
-
|
|
3
|
-
@interface RCT_EXTERN_MODULE(CloudStorage, NSObject)
|
|
4
|
-
|
|
5
|
-
RCT_EXTERN_METHOD(fileExists:(NSString *)path withScope:(NSString *)scope withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject)
|
|
6
|
-
RCT_EXTERN_METHOD(appendToFile:(NSString *)path withData:(NSString *)data withScope:(NSString *)scope withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject)
|
|
7
|
-
RCT_EXTERN_METHOD(createFile:(NSString *)path withData:(NSString *)data withScope:(NSString *)scope withOverwrite:(BOOL)overwrite withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject)
|
|
8
|
-
RCT_EXTERN_METHOD(createDirectory:(NSString *)path withScope:(NSString *)scope withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject)
|
|
9
|
-
RCT_EXTERN_METHOD(listFiles:(NSString *)path withScope:(NSString *)scope withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject)
|
|
10
|
-
RCT_EXTERN_METHOD(readFile:(NSString *)path withScope:(NSString *)scope withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject)
|
|
11
|
-
RCT_EXTERN_METHOD(downloadFile:(NSString *)path withScope:(NSString *)scope withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject)
|
|
12
|
-
RCT_EXTERN_METHOD(deleteFile:(NSString *)path withScope:(NSString *)scope withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject)
|
|
13
|
-
RCT_EXTERN_METHOD(deleteDirectory:(NSString *)path withRecursive:(BOOL)recursive withScope:(NSString *)scope withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject)
|
|
14
|
-
RCT_EXTERN_METHOD(statFile:(NSString *)path withScope:(NSString *)scope withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject)
|
|
15
|
-
RCT_EXTERN_METHOD(isCloudAvailable:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject)
|
|
16
|
-
|
|
17
|
-
+ (BOOL)requiresMainQueueSetup
|
|
18
|
-
{
|
|
19
|
-
return NO;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
@end
|