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.
Files changed (34) hide show
  1. package/README.md +66 -10
  2. package/ios/CloudStorage.swift +30 -28
  3. package/lib/commonjs/RNCloudStorage.js.map +1 -1
  4. package/lib/commonjs/createRNCloudStorage.js.map +1 -1
  5. package/lib/commonjs/google-drive/client.js +169 -0
  6. package/lib/commonjs/google-drive/client.js.map +1 -0
  7. package/lib/commonjs/google-drive/index.js +53 -50
  8. package/lib/commonjs/google-drive/index.js.map +1 -1
  9. package/lib/commonjs/google-drive/types.js +15 -0
  10. package/lib/commonjs/google-drive/types.js.map +1 -1
  11. package/lib/module/RNCloudStorage.js +4 -4
  12. package/lib/module/RNCloudStorage.js.map +1 -1
  13. package/lib/module/createRNCloudStorage.js +2 -2
  14. package/lib/module/createRNCloudStorage.js.map +1 -1
  15. package/lib/module/google-drive/client.js +161 -0
  16. package/lib/module/google-drive/client.js.map +1 -0
  17. package/lib/module/google-drive/index.js +46 -44
  18. package/lib/module/google-drive/index.js.map +1 -1
  19. package/lib/module/google-drive/types.js +9 -1
  20. package/lib/module/google-drive/types.js.map +1 -1
  21. package/lib/typescript/RNCloudStorage.d.ts +2 -2
  22. package/lib/typescript/RNCloudStorage.d.ts.map +1 -1
  23. package/lib/typescript/google-drive/client.d.ts +33 -0
  24. package/lib/typescript/google-drive/client.d.ts.map +1 -0
  25. package/lib/typescript/google-drive/index.d.ts +6 -4
  26. package/lib/typescript/google-drive/index.d.ts.map +1 -1
  27. package/lib/typescript/google-drive/types.d.ts +10 -3
  28. package/lib/typescript/google-drive/types.d.ts.map +1 -1
  29. package/package.json +1 -4
  30. package/src/RNCloudStorage.ts +5 -5
  31. package/src/createRNCloudStorage.ts +2 -2
  32. package/src/google-drive/client.ts +177 -0
  33. package/src/google-drive/index.ts +71 -69
  34. 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 type { GoogleDriveDetailedFile, GoogleDriveFile, GoogleDriveListOperationResponse } from './types';
8
+ import { MimeTypes, type GoogleDriveFile, type GoogleDriveFileSpace } from './types';
10
9
  import { DeviceEventEmitter } from 'react-native';
11
-
12
- export default class GoogleDriveApiClient implements NativeRNCloudStorage {
13
- private static drive: GDrive = new GDrive();
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: GoogleDriveApiClient, prop: keyof GoogleDriveApiClient) {
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 (!GoogleDriveApiClient.drive.accessToken) {
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 | undefined) {
40
- GoogleDriveApiClient.drive.accessToken = accessToken;
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 | undefined {
49
- return GoogleDriveApiClient.drive.accessToken;
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 () => !!GoogleDriveApiClient.accessToken?.length;
67
+ public isCloudAvailable: () => Promise<boolean> = async () => !!GoogleDrive.drive.accessToken.length;
65
68
 
66
- private getRootDirectory(scope: NativeRNCloudCloudStorageScope): 'drive' | 'appDataFolder' {
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.listInternalFiles(scope);
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 (GoogleDriveApiClient.throwOnFilesWithSameName) {
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.listInternalFiles(scope);
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 HttpError && e.json?.error?.status === 'UNAUTHENTICATED') {
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 GoogleDriveApiClient.drive.files.getText(fileId);
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
- const uploader = GoogleDriveApiClient.drive.files
254
- .newMultipartUploader()
255
- .setData(prevContent + data, MimeTypes.TEXT);
256
- if (fileId) uploader.setIdOfFileToUpdate(fileId);
257
- else {
258
- const files = await this.listInternalFiles(scope);
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
- uploader.setRequestBody({
262
- name: filename,
263
- parents: parentDirectoryId
264
- ? [parentDirectoryId]
265
- : scope === 'app_data'
266
- ? [this.getRootDirectory(scope)]
267
- : undefined,
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
- const uploader = GoogleDriveApiClient.drive.files.newMultipartUploader().setData(data, MimeTypes.TEXT);
304
- if (fileId) uploader.setIdOfFileToUpdate(fileId);
305
- else {
306
- const files = await this.listInternalFiles(scope);
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
- uploader.setRequestBody({
310
- name: filename,
311
- parents: parentDirectoryId
312
- ? [parentDirectoryId]
313
- : scope === 'app_data'
314
- ? [this.getRootDirectory(scope)]
315
- : undefined,
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.listInternalFiles(scope);
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 uploader = GoogleDriveApiClient.drive.files.newMetadataOnlyUploader();
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
- uploader.setRequestBody({
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 GoogleDriveApiClient.drive.files.getText(fileId);
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 GoogleDriveApiClient.drive.files.delete(fileId);
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: GoogleDriveDetailedFile = await (
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: ('appDataFolder' | 'drive')[];
8
- }
9
-
10
- export interface GoogleDriveDetailedFile extends GoogleDriveFile {
18
+ spaces: GoogleDriveFileSpace[];
11
19
  createdTime: string;
12
20
  modifiedTime: string;
13
21
  size?: number;