react-native-cloud-storage 1.2.2 → 1.2.4
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/README.md +66 -10
- package/ios/CloudStorage.swift +30 -28
- package/lib/commonjs/RNCloudStorage.js.map +1 -1
- package/lib/commonjs/createRNCloudStorage.js.map +1 -1
- package/lib/commonjs/google-drive/client.js +169 -0
- package/lib/commonjs/google-drive/client.js.map +1 -0
- package/lib/commonjs/google-drive/index.js +53 -50
- package/lib/commonjs/google-drive/index.js.map +1 -1
- package/lib/commonjs/google-drive/types.js +15 -0
- package/lib/commonjs/google-drive/types.js.map +1 -1
- package/lib/module/RNCloudStorage.js +4 -4
- package/lib/module/RNCloudStorage.js.map +1 -1
- package/lib/module/createRNCloudStorage.js +2 -2
- package/lib/module/createRNCloudStorage.js.map +1 -1
- package/lib/module/google-drive/client.js +161 -0
- package/lib/module/google-drive/client.js.map +1 -0
- package/lib/module/google-drive/index.js +46 -44
- package/lib/module/google-drive/index.js.map +1 -1
- package/lib/module/google-drive/types.js +9 -1
- package/lib/module/google-drive/types.js.map +1 -1
- package/lib/typescript/RNCloudStorage.d.ts +2 -2
- package/lib/typescript/RNCloudStorage.d.ts.map +1 -1
- package/lib/typescript/google-drive/client.d.ts +33 -0
- package/lib/typescript/google-drive/client.d.ts.map +1 -0
- package/lib/typescript/google-drive/index.d.ts +6 -4
- package/lib/typescript/google-drive/index.d.ts.map +1 -1
- package/lib/typescript/google-drive/types.d.ts +10 -3
- package/lib/typescript/google-drive/types.d.ts.map +1 -1
- package/package.json +1 -4
- package/src/RNCloudStorage.ts +5 -5
- package/src/createRNCloudStorage.ts +2 -2
- package/src/google-drive/client.ts +177 -0
- package/src/google-drive/index.ts +71 -69
- package/src/google-drive/types.ts +12 -4
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { GDrive, HttpError, MimeTypes } from 'react-native-google-drive-api-wrapper-js';
|
|
2
1
|
import type NativeRNCloudStorage from '../types/native';
|
|
3
2
|
import {
|
|
4
3
|
CloudStorageErrorCode,
|
|
@@ -6,23 +5,27 @@ import {
|
|
|
6
5
|
type NativeRNCloudCloudStorageScope,
|
|
7
6
|
} from '../types/native';
|
|
8
7
|
import CloudStorageError from '../utils/CloudStorageError';
|
|
9
|
-
import
|
|
8
|
+
import { MimeTypes, type GoogleDriveFile, type GoogleDriveFileSpace } from './types';
|
|
10
9
|
import { DeviceEventEmitter } from 'react-native';
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
import GoogleDriveApiClient, { GoogleDriveHttpError } from './client';
|
|
11
|
+
|
|
12
|
+
// TODO: replace legacyDrive fully with new drive implementation
|
|
13
|
+
/**
|
|
14
|
+
* A proxy class that wraps the Google Drive API client implementation to match the native iOS interface.
|
|
15
|
+
*/
|
|
16
|
+
export default class GoogleDrive implements NativeRNCloudStorage {
|
|
17
|
+
private static drive: GoogleDriveApiClient = new GoogleDriveApiClient();
|
|
14
18
|
public static throwOnFilesWithSameName = false;
|
|
15
19
|
public filesWithSameNameSubscribers: (({ path, fileIds }: { path: string; fileIds: string[] }) => void)[];
|
|
16
20
|
|
|
17
21
|
constructor() {
|
|
18
22
|
this.filesWithSameNameSubscribers = [];
|
|
19
|
-
GoogleDriveApiClient.drive.fetchTimeout = 3000;
|
|
20
23
|
return new Proxy(this, {
|
|
21
24
|
// before calling any function, check if the access token is set
|
|
22
|
-
get(target:
|
|
25
|
+
get(target: GoogleDrive, prop: keyof GoogleDrive) {
|
|
23
26
|
const allowedFunctions = ['isCloudAvailable', 'subscribeToFilesWithSameName'];
|
|
24
27
|
if (typeof target[prop] === 'function' && !allowedFunctions.includes(prop.toString())) {
|
|
25
|
-
if (!
|
|
28
|
+
if (!GoogleDrive.drive.accessToken.length) {
|
|
26
29
|
throw new CloudStorageError(
|
|
27
30
|
`Google Drive access token is not set, cannot call function ${prop.toString()}`,
|
|
28
31
|
CloudStorageErrorCode.GOOGLE_DRIVE_ACCESS_TOKEN_MISSING
|
|
@@ -36,8 +39,8 @@ export default class GoogleDriveApiClient implements NativeRNCloudStorage {
|
|
|
36
39
|
}
|
|
37
40
|
|
|
38
41
|
// when setting accessToken, set it on the GDrive instance
|
|
39
|
-
public static set accessToken(accessToken: string |
|
|
40
|
-
|
|
42
|
+
public static set accessToken(accessToken: string | null) {
|
|
43
|
+
GoogleDrive.drive.accessToken = accessToken ?? '';
|
|
41
44
|
|
|
42
45
|
// emit an event for the useIsCloudAvailable hook
|
|
43
46
|
DeviceEventEmitter.emit('RNCloudStorage.cloud.availability-changed', {
|
|
@@ -45,8 +48,8 @@ export default class GoogleDriveApiClient implements NativeRNCloudStorage {
|
|
|
45
48
|
});
|
|
46
49
|
}
|
|
47
50
|
|
|
48
|
-
public static get accessToken(): string |
|
|
49
|
-
return
|
|
51
|
+
public static get accessToken(): string | null {
|
|
52
|
+
return GoogleDrive.drive.accessToken.length ? GoogleDrive.drive.accessToken : null;
|
|
50
53
|
}
|
|
51
54
|
|
|
52
55
|
public subscribeToFilesWithSameName(subscriber: ({ path, fileIds }: { path: string; fileIds: string[] }) => void): {
|
|
@@ -61,9 +64,9 @@ export default class GoogleDriveApiClient implements NativeRNCloudStorage {
|
|
|
61
64
|
};
|
|
62
65
|
}
|
|
63
66
|
|
|
64
|
-
public isCloudAvailable: () => Promise<boolean> = async () => !!
|
|
67
|
+
public isCloudAvailable: () => Promise<boolean> = async () => !!GoogleDrive.drive.accessToken.length;
|
|
65
68
|
|
|
66
|
-
private getRootDirectory(scope: NativeRNCloudCloudStorageScope):
|
|
69
|
+
private getRootDirectory(scope: NativeRNCloudCloudStorageScope): GoogleDriveFileSpace {
|
|
67
70
|
switch (scope) {
|
|
68
71
|
case 'documents':
|
|
69
72
|
return 'drive';
|
|
@@ -135,7 +138,7 @@ export default class GoogleDriveApiClient implements NativeRNCloudStorage {
|
|
|
135
138
|
* @returns A promise that resolves to the ID of the root directory or null if it could not be found.
|
|
136
139
|
*/
|
|
137
140
|
private async getRootDirectoryId(scope: NativeRNCloudCloudStorageScope): Promise<string | null> {
|
|
138
|
-
const files = await this.
|
|
141
|
+
const files = await GoogleDrive.drive.listFiles(this.getRootDirectory(scope));
|
|
139
142
|
for (const file of files) {
|
|
140
143
|
if (!files.find((f) => f.id === file.parents![0])) return file.parents![0] ?? null;
|
|
141
144
|
}
|
|
@@ -143,15 +146,6 @@ export default class GoogleDriveApiClient implements NativeRNCloudStorage {
|
|
|
143
146
|
return null;
|
|
144
147
|
}
|
|
145
148
|
|
|
146
|
-
private async listInternalFiles(scope: NativeRNCloudCloudStorageScope): Promise<GoogleDriveFile[]> {
|
|
147
|
-
const files: GoogleDriveListOperationResponse = await GoogleDriveApiClient.drive.files.list({
|
|
148
|
-
spaces: [this.getRootDirectory(scope)],
|
|
149
|
-
fields: 'files(id,kind,mimeType,name,parents,spaces)',
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
return files.files;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
149
|
private checkIfMultipleFilesWithSameName(
|
|
156
150
|
path: string,
|
|
157
151
|
files: GoogleDriveFile[],
|
|
@@ -167,7 +161,7 @@ export default class GoogleDriveApiClient implements NativeRNCloudStorage {
|
|
|
167
161
|
|
|
168
162
|
if (possibleFiles.length <= 1) return;
|
|
169
163
|
|
|
170
|
-
if (
|
|
164
|
+
if (GoogleDrive.throwOnFilesWithSameName) {
|
|
171
165
|
throw new CloudStorageError(
|
|
172
166
|
`Multiple files with the same name found at path ${path}: ${possibleFiles.map((f) => f.id).join(', ')}`,
|
|
173
167
|
CloudStorageErrorCode.MULTIPLE_FILES_SAME_NAME
|
|
@@ -183,7 +177,7 @@ export default class GoogleDriveApiClient implements NativeRNCloudStorage {
|
|
|
183
177
|
throwIfDirectory = true
|
|
184
178
|
): Promise<string> {
|
|
185
179
|
try {
|
|
186
|
-
const files = await this.
|
|
180
|
+
const files = await GoogleDrive.drive.listFiles(this.getRootDirectory(scope));
|
|
187
181
|
|
|
188
182
|
if (path === '' || path === '/') {
|
|
189
183
|
const rootDirectoryId = await this.getRootDirectoryId(scope);
|
|
@@ -213,7 +207,7 @@ export default class GoogleDriveApiClient implements NativeRNCloudStorage {
|
|
|
213
207
|
}
|
|
214
208
|
return file.id;
|
|
215
209
|
} catch (e: unknown) {
|
|
216
|
-
if (e instanceof
|
|
210
|
+
if (e instanceof GoogleDriveHttpError && e.json?.error?.status === 'UNAUTHENTICATED') {
|
|
217
211
|
throw new CloudStorageError(
|
|
218
212
|
`Could not authenticate with Google Drive`,
|
|
219
213
|
CloudStorageErrorCode.AUTHENTICATION_FAILED,
|
|
@@ -241,7 +235,7 @@ export default class GoogleDriveApiClient implements NativeRNCloudStorage {
|
|
|
241
235
|
let prevContent = '';
|
|
242
236
|
try {
|
|
243
237
|
fileId = await this.getFileId(path, scope);
|
|
244
|
-
prevContent = await
|
|
238
|
+
prevContent = await GoogleDrive.drive.getFileText(fileId);
|
|
245
239
|
} catch (e: any) {
|
|
246
240
|
if (e instanceof CloudStorageError && e.code === CloudStorageErrorCode.FILE_NOT_FOUND) {
|
|
247
241
|
/* do nothing, simply create the file */
|
|
@@ -250,24 +244,30 @@ export default class GoogleDriveApiClient implements NativeRNCloudStorage {
|
|
|
250
244
|
}
|
|
251
245
|
}
|
|
252
246
|
|
|
253
|
-
|
|
254
|
-
.
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
247
|
+
if (fileId) {
|
|
248
|
+
await GoogleDrive.drive.updateFile(fileId, {
|
|
249
|
+
body: prevContent + data,
|
|
250
|
+
mimeType: MimeTypes.TEXT,
|
|
251
|
+
});
|
|
252
|
+
} else {
|
|
253
|
+
const files = await GoogleDrive.drive.listFiles(this.getRootDirectory(scope));
|
|
259
254
|
const { directories, filename } = this.resolvePathToDirectories(path);
|
|
260
255
|
const parentDirectoryId = this.findParentDirectoryId(files, directories);
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
256
|
+
await GoogleDrive.drive.createFile(
|
|
257
|
+
{
|
|
258
|
+
name: filename,
|
|
259
|
+
parents: parentDirectoryId
|
|
260
|
+
? [parentDirectoryId]
|
|
261
|
+
: scope === 'app_data'
|
|
262
|
+
? [this.getRootDirectory(scope)]
|
|
263
|
+
: undefined,
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
body: data,
|
|
267
|
+
mimeType: MimeTypes.TEXT,
|
|
268
|
+
}
|
|
269
|
+
);
|
|
269
270
|
}
|
|
270
|
-
await uploader.execute();
|
|
271
271
|
}
|
|
272
272
|
|
|
273
273
|
async createFile(
|
|
@@ -300,26 +300,34 @@ export default class GoogleDriveApiClient implements NativeRNCloudStorage {
|
|
|
300
300
|
}
|
|
301
301
|
}
|
|
302
302
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
303
|
+
if (fileId) {
|
|
304
|
+
await GoogleDrive.drive.updateFile(fileId, {
|
|
305
|
+
body: data,
|
|
306
|
+
mimeType: MimeTypes.TEXT,
|
|
307
|
+
});
|
|
308
|
+
} else {
|
|
309
|
+
const files = await GoogleDrive.drive.listFiles(this.getRootDirectory(scope));
|
|
307
310
|
const { directories, filename } = this.resolvePathToDirectories(path);
|
|
308
311
|
const parentDirectoryId = this.findParentDirectoryId(files, directories);
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
312
|
+
await GoogleDrive.drive.createFile(
|
|
313
|
+
{
|
|
314
|
+
name: filename,
|
|
315
|
+
parents: parentDirectoryId
|
|
316
|
+
? [parentDirectoryId]
|
|
317
|
+
: scope === 'app_data'
|
|
318
|
+
? [this.getRootDirectory(scope)]
|
|
319
|
+
: undefined,
|
|
320
|
+
},
|
|
321
|
+
{
|
|
322
|
+
body: data,
|
|
323
|
+
mimeType: MimeTypes.TEXT,
|
|
324
|
+
}
|
|
325
|
+
);
|
|
317
326
|
}
|
|
318
|
-
await uploader.execute();
|
|
319
327
|
}
|
|
320
328
|
|
|
321
329
|
async listFiles(path: string, scope: NativeRNCloudCloudStorageScope): Promise<string[]> {
|
|
322
|
-
const allFiles = await this.
|
|
330
|
+
const allFiles = await GoogleDrive.drive.listFiles(this.getRootDirectory(scope));
|
|
323
331
|
if (path !== '') {
|
|
324
332
|
const fileId = await this.getFileId(path, scope, false);
|
|
325
333
|
const files = allFiles.filter((f) => (f.parents ?? [])[0] === fileId);
|
|
@@ -345,25 +353,23 @@ export default class GoogleDriveApiClient implements NativeRNCloudStorage {
|
|
|
345
353
|
}
|
|
346
354
|
}
|
|
347
355
|
|
|
348
|
-
const
|
|
349
|
-
const files = await this.listInternalFiles(scope);
|
|
356
|
+
const files = await GoogleDrive.drive.listFiles(this.getRootDirectory(scope));
|
|
350
357
|
const { directories, filename } = this.resolvePathToDirectories(path);
|
|
351
358
|
const parentDirectoryId = this.findParentDirectoryId(files, directories);
|
|
352
|
-
|
|
359
|
+
|
|
360
|
+
await GoogleDrive.drive.createDirectory({
|
|
353
361
|
name: filename,
|
|
354
|
-
mimeType: MimeTypes.FOLDER,
|
|
355
362
|
parents: parentDirectoryId
|
|
356
363
|
? [parentDirectoryId]
|
|
357
364
|
: scope === 'app_data'
|
|
358
365
|
? [this.getRootDirectory(scope)]
|
|
359
366
|
: undefined,
|
|
360
367
|
});
|
|
361
|
-
await uploader.execute();
|
|
362
368
|
}
|
|
363
369
|
|
|
364
370
|
async readFile(path: string, scope: NativeRNCloudCloudStorageScope): Promise<string> {
|
|
365
371
|
const fileId = await this.getFileId(path, scope);
|
|
366
|
-
const content = await
|
|
372
|
+
const content = await GoogleDrive.drive.getFileText(fileId);
|
|
367
373
|
return content;
|
|
368
374
|
}
|
|
369
375
|
|
|
@@ -374,16 +380,12 @@ export default class GoogleDriveApiClient implements NativeRNCloudStorage {
|
|
|
374
380
|
|
|
375
381
|
async deleteFile(path: string, scope: NativeRNCloudCloudStorageScope): Promise<void> {
|
|
376
382
|
const fileId = await this.getFileId(path, scope);
|
|
377
|
-
await
|
|
383
|
+
await GoogleDrive.drive.deleteFile(fileId);
|
|
378
384
|
}
|
|
379
385
|
|
|
380
386
|
async statFile(path: string, scope: NativeRNCloudCloudStorageScope): Promise<NativeRNCloudCloudStorageFileStat> {
|
|
381
387
|
const fileId = await this.getFileId(path, scope, false);
|
|
382
|
-
const file
|
|
383
|
-
await GoogleDriveApiClient.drive.files.get(fileId!, {
|
|
384
|
-
fields: 'id,kind,mimeType,name,parents,spaces,size,createdTime,modifiedTime',
|
|
385
|
-
})
|
|
386
|
-
).json();
|
|
388
|
+
const file = await GoogleDrive.drive.getFile(fileId!);
|
|
387
389
|
|
|
388
390
|
return {
|
|
389
391
|
size: file.size ?? 0,
|
|
@@ -1,13 +1,21 @@
|
|
|
1
|
+
export type GoogleDriveFileSpace = 'appDataFolder' | 'drive';
|
|
2
|
+
|
|
3
|
+
export enum MimeTypes {
|
|
4
|
+
BINARY = 'application/octet-stream',
|
|
5
|
+
CSV = 'text/csv',
|
|
6
|
+
FOLDER = 'application/vnd.google-apps.folder',
|
|
7
|
+
JSON = 'application/json',
|
|
8
|
+
PDF = 'application/pdf',
|
|
9
|
+
TEXT = 'text/plain',
|
|
10
|
+
}
|
|
11
|
+
|
|
1
12
|
export interface GoogleDriveFile {
|
|
2
13
|
id: string;
|
|
3
14
|
kind: 'drive#file';
|
|
4
15
|
mimeType: string;
|
|
5
16
|
name: string;
|
|
6
17
|
parents: string[];
|
|
7
|
-
spaces:
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export interface GoogleDriveDetailedFile extends GoogleDriveFile {
|
|
18
|
+
spaces: GoogleDriveFileSpace[];
|
|
11
19
|
createdTime: string;
|
|
12
20
|
modifiedTime: string;
|
|
13
21
|
size?: number;
|