@react-native-firebase/storage 24.1.1 → 25.0.1

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 (95) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/{lib → dist/module}/StorageDownloadTask.js +4 -3
  3. package/dist/module/StorageDownloadTask.js.map +1 -0
  4. package/{lib → dist/module}/StorageListResult.js +13 -8
  5. package/dist/module/StorageListResult.js.map +1 -0
  6. package/dist/module/StorageReference.js +270 -0
  7. package/dist/module/StorageReference.js.map +1 -0
  8. package/{lib → dist/module}/StorageStatics.js +5 -16
  9. package/dist/module/StorageStatics.js.map +1 -0
  10. package/{lib → dist/module}/StorageTask.js +82 -71
  11. package/dist/module/StorageTask.js.map +1 -0
  12. package/{lib → dist/module}/StorageUploadTask.js +4 -3
  13. package/dist/module/StorageUploadTask.js.map +1 -0
  14. package/dist/module/index.js +29 -0
  15. package/dist/module/index.js.map +1 -0
  16. package/{lib/modular/index.js → dist/module/modular.js} +65 -79
  17. package/dist/module/modular.js.map +1 -0
  18. package/dist/module/namespaced.js +192 -0
  19. package/dist/module/namespaced.js.map +1 -0
  20. package/dist/module/package.json +1 -0
  21. package/dist/module/types/internal.js +4 -0
  22. package/dist/module/types/internal.js.map +1 -0
  23. package/dist/module/types/namespaced.js +64 -0
  24. package/dist/module/types/namespaced.js.map +1 -0
  25. package/dist/module/types/storage.js +139 -0
  26. package/dist/module/types/storage.js.map +1 -0
  27. package/dist/module/utils.js +105 -0
  28. package/dist/module/utils.js.map +1 -0
  29. package/dist/module/version.js +5 -0
  30. package/dist/module/version.js.map +1 -0
  31. package/dist/module/web/RNFBStorageModule.android.js +6 -0
  32. package/dist/module/web/RNFBStorageModule.android.js.map +1 -0
  33. package/dist/module/web/RNFBStorageModule.ios.js +6 -0
  34. package/dist/module/web/RNFBStorageModule.ios.js.map +1 -0
  35. package/{lib → dist/module}/web/RNFBStorageModule.js +115 -197
  36. package/dist/module/web/RNFBStorageModule.js.map +1 -0
  37. package/dist/typescript/lib/StorageDownloadTask.d.ts +6 -0
  38. package/dist/typescript/lib/StorageDownloadTask.d.ts.map +1 -0
  39. package/dist/typescript/lib/StorageListResult.d.ts +13 -0
  40. package/dist/typescript/lib/StorageListResult.d.ts.map +1 -0
  41. package/dist/typescript/lib/StorageReference.d.ts +87 -0
  42. package/dist/typescript/lib/StorageReference.d.ts.map +1 -0
  43. package/dist/typescript/lib/StorageStatics.d.ts +2 -0
  44. package/dist/typescript/lib/StorageStatics.d.ts.map +1 -0
  45. package/dist/typescript/lib/StorageTask.d.ts +43 -0
  46. package/dist/typescript/lib/StorageTask.d.ts.map +1 -0
  47. package/dist/typescript/lib/StorageUploadTask.d.ts +6 -0
  48. package/dist/typescript/lib/StorageUploadTask.d.ts.map +1 -0
  49. package/dist/typescript/lib/index.d.ts +6 -0
  50. package/dist/typescript/lib/index.d.ts.map +1 -0
  51. package/dist/typescript/lib/modular.d.ts +154 -0
  52. package/dist/typescript/lib/modular.d.ts.map +1 -0
  53. package/dist/typescript/lib/namespaced.d.ts +12 -0
  54. package/dist/typescript/lib/namespaced.d.ts.map +1 -0
  55. package/dist/typescript/lib/types/internal.d.ts +131 -0
  56. package/dist/typescript/lib/types/internal.d.ts.map +1 -0
  57. package/dist/typescript/lib/types/namespaced.d.ts +1122 -0
  58. package/dist/typescript/lib/types/namespaced.d.ts.map +1 -0
  59. package/dist/typescript/lib/types/storage.d.ts +338 -0
  60. package/dist/typescript/lib/types/storage.d.ts.map +1 -0
  61. package/dist/typescript/lib/utils.d.ts +20 -0
  62. package/dist/typescript/lib/utils.d.ts.map +1 -0
  63. package/dist/typescript/lib/version.d.ts +2 -0
  64. package/dist/typescript/lib/version.d.ts.map +1 -0
  65. package/dist/typescript/lib/web/RNFBStorageModule.android.d.ts +3 -0
  66. package/dist/typescript/lib/web/RNFBStorageModule.android.d.ts.map +1 -0
  67. package/dist/typescript/lib/web/RNFBStorageModule.d.ts +142 -0
  68. package/dist/typescript/lib/web/RNFBStorageModule.d.ts.map +1 -0
  69. package/dist/typescript/lib/web/RNFBStorageModule.ios.d.ts +3 -0
  70. package/dist/typescript/lib/web/RNFBStorageModule.ios.d.ts.map +1 -0
  71. package/dist/typescript/package.json +1 -0
  72. package/lib/StorageDownloadTask.ts +30 -0
  73. package/lib/StorageListResult.ts +61 -0
  74. package/lib/{StorageReference.js → StorageReference.ts} +103 -61
  75. package/lib/StorageStatics.ts +19 -0
  76. package/lib/StorageTask.ts +336 -0
  77. package/lib/StorageUploadTask.ts +30 -0
  78. package/lib/index.ts +27 -0
  79. package/lib/modular.ts +401 -0
  80. package/lib/{index.js → namespaced.ts} +70 -28
  81. package/lib/types/internal.ts +189 -0
  82. package/lib/{index.d.ts → types/namespaced.ts} +111 -49
  83. package/lib/types/storage.ts +417 -0
  84. package/lib/{utils.js → utils.ts} +62 -15
  85. package/lib/version.ts +2 -0
  86. package/lib/web/RNFBStorageModule.android.ts +3 -0
  87. package/lib/web/RNFBStorageModule.ios.ts +3 -0
  88. package/lib/web/RNFBStorageModule.ts +557 -0
  89. package/package.json +41 -7
  90. package/tsconfig.json +23 -0
  91. package/typedoc.json +1 -1
  92. package/lib/modular/index.d.ts +0 -276
  93. package/lib/version.js +0 -2
  94. package/lib/web/RNFBStorageModule.android.js +0 -2
  95. package/lib/web/RNFBStorageModule.ios.js +0 -2
@@ -0,0 +1,417 @@
1
+ /*
2
+ * Copyright (c) 2016-present Invertase Limited & Contributors
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this library except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+ import type { FirebaseApp, ReactNativeFirebase } from '@react-native-firebase/app';
18
+ import type {
19
+ CompleteFn,
20
+ NextFn,
21
+ Unsubscribe,
22
+ } from '@react-native-firebase/app/dist/module/types/common';
23
+ export type { CompleteFn, NextFn, Unsubscribe };
24
+ export type NativeFirebaseError = ReactNativeFirebase.NativeFirebaseError;
25
+ /**
26
+ * Storage module instance
27
+ */
28
+ export interface FirebaseStorage {
29
+ /** The FirebaseApp this module is associated with */
30
+ app: FirebaseApp;
31
+
32
+ /**
33
+ * The maximum time in milliseconds to retry an upload if a failure occurs.
34
+ */
35
+ readonly maxUploadRetryTime: number;
36
+
37
+ /**
38
+ * The maximum time in milliseconds to retry a download if a failure occurs.
39
+ */
40
+ readonly maxDownloadRetryTime: number;
41
+
42
+ /**
43
+ * The maximum time in milliseconds to retry operations if a failure occurs.
44
+ */
45
+ readonly maxOperationRetryTime: number;
46
+ }
47
+
48
+ /**
49
+ * Storage reference to a file or folder location.
50
+ */
51
+ export interface StorageReference {
52
+ /**
53
+ * A reference to the root of this object's bucket.
54
+ */
55
+ root: StorageReference;
56
+ /**
57
+ * The name of the bucket containing this reference's object.
58
+ */
59
+ bucket: string;
60
+ /**
61
+ * The full path of this object.
62
+ */
63
+ fullPath: string;
64
+ /**
65
+ * The short name of this object, which is the last component of the full path.
66
+ * For example, if fullPath is 'full/path/image.png', name is 'image.png'.
67
+ */
68
+ name: string;
69
+ /**
70
+ * The {@link FirebaseStorage} instance associated with this reference.
71
+ */
72
+ storage: FirebaseStorage;
73
+ /**
74
+ * A reference pointing to the parent location of this reference, or null if
75
+ * this reference is the root.
76
+ */
77
+ parent: StorageReference | null;
78
+ /**
79
+ * Returns the full URL string for this object in the form
80
+ * @returns The full URL string.
81
+ */
82
+ toString(): string;
83
+ }
84
+
85
+ /**
86
+ * Options for listing files and folders.
87
+ */
88
+ export interface ListOptions {
89
+ /**
90
+ * If set, limits the total number of `prefixes` and `items` to return.
91
+ * The default and maximum maxResults is 1000.
92
+ */
93
+ maxResults?: number | null;
94
+ /**
95
+ * The `nextPageToken` from a previous call to `list()`. If provided,
96
+ * listing is resumed from the previous position.
97
+ */
98
+ pageToken?: string | null;
99
+ }
100
+
101
+ /**
102
+ * Result of listing files and folders.
103
+ */
104
+ export interface ListResult {
105
+ /**
106
+ * References to prefixes (sub-folders). You can call list() on them to
107
+ * get its contents.
108
+ *
109
+ * Folders are implicit based on '/' in the object paths.
110
+ * For example, if a bucket has two objects '/a/b/1' and '/a/b/2', list('/a')
111
+ * will return '/a/b' as a prefix.
112
+ */
113
+ prefixes: StorageReference[];
114
+ /**
115
+ * Objects in this directory.
116
+ * You can call getMetadata() and getDownloadUrl() on them.
117
+ */
118
+ items: StorageReference[];
119
+ /**
120
+ * If set, there might be more results for this list. Use this token to resume the list.
121
+ */
122
+ nextPageToken?: string;
123
+ }
124
+
125
+ /**
126
+ * Object metadata that can be set at any time.
127
+ */
128
+ export interface SettableMetadata {
129
+ cacheControl?: string | undefined;
130
+ contentDisposition?: string | undefined;
131
+ contentEncoding?: string | undefined;
132
+ contentLanguage?: string | undefined;
133
+ contentType?: string | undefined;
134
+ customMetadata?: { [key: string]: string } | undefined;
135
+ }
136
+
137
+ /**
138
+ * Object metadata that can be set at upload.
139
+ * @public
140
+ */
141
+ export interface UploadMetadata extends SettableMetadata {
142
+ /**
143
+ * A Base64-encoded MD5 hash of the object being uploaded.
144
+ */
145
+ md5Hash?: string | undefined;
146
+ }
147
+
148
+ /**
149
+ * The full set of object metadata, including read-only properties.
150
+ */
151
+ export interface FullMetadata extends UploadMetadata {
152
+ /**
153
+ * The bucket this object is contained in.
154
+ */
155
+ bucket: string;
156
+
157
+ /**
158
+ * The full path of this object.
159
+ */
160
+ fullPath: string;
161
+
162
+ /**
163
+ * The object's generation.
164
+ * {@link https://cloud.google.com/storage/docs/metadata#generation-number}
165
+ */
166
+ generation: string;
167
+
168
+ /**
169
+ * The object's metageneration.
170
+ * {@link https://cloud.google.com/storage/docs/metadata#generation-number}
171
+ */
172
+ metageneration: string;
173
+
174
+ /**
175
+ * The short name of this object, which is the last component of the full path.
176
+ * For example, if fullPath is 'full/path/image.png', name is 'image.png'.
177
+ */
178
+ name: string;
179
+
180
+ /**
181
+ * The size of this object, in bytes.
182
+ */
183
+ size: number;
184
+
185
+ /**
186
+ * A date string representing when this object was created.
187
+ */
188
+ timeCreated: string;
189
+
190
+ /**
191
+ * A date string representing when this object was last updated.
192
+ */
193
+ updated: string;
194
+
195
+ /**
196
+ * Tokens to allow access to the download URL.
197
+ */
198
+ downloadTokens: string[] | undefined;
199
+
200
+ /**
201
+ * `StorageReference` associated with this upload.
202
+ */
203
+ ref?: StorageReference | undefined;
204
+ }
205
+
206
+ /**
207
+ * An enumeration of the possible string formats for upload.
208
+ * @public
209
+ */
210
+ export type StringFormat = (typeof StringFormat)[keyof typeof StringFormat];
211
+
212
+ /**
213
+ * An enumeration of the possible string formats for upload.
214
+ * @public
215
+ */
216
+ export const StringFormat = {
217
+ RAW: 'raw',
218
+ BASE64: 'base64',
219
+ BASE64URL: 'base64url',
220
+ DATA_URL: 'data_url',
221
+ } as const;
222
+
223
+ /**
224
+ * An event that is triggered on a task.
225
+ * @public
226
+ */
227
+ export type TaskEvent = (typeof TaskEvent)[keyof typeof TaskEvent];
228
+
229
+ /**
230
+ * An event that is triggered on a task.
231
+ * @public
232
+ */
233
+ export const TaskEvent = {
234
+ STATE_CHANGED: 'state_changed',
235
+ } as const;
236
+
237
+ /**
238
+ * Represents the current state of a running upload/download.
239
+ * @public
240
+ */
241
+ export type TaskState = (typeof TaskState)[keyof typeof TaskState];
242
+
243
+ /**
244
+ * Represents the current state of a running upload/download.
245
+ * @public
246
+ */
247
+ export const TaskState = {
248
+ RUNNING: 'running',
249
+ PAUSED: 'paused',
250
+ SUCCESS: 'success',
251
+ CANCELED: 'canceled',
252
+ // Backwards-compat alias
253
+ CANCELLED: 'canceled',
254
+ ERROR: 'error',
255
+ } as const;
256
+
257
+ /**
258
+ * A stream observer for Firebase Storage.
259
+ * @public
260
+ */
261
+ export interface StorageObserver<T> {
262
+ next?: NextFn<T> | null;
263
+ error?: ((error: NativeFirebaseError) => void) | null;
264
+ complete?: CompleteFn | null;
265
+ }
266
+
267
+ /**
268
+ * Represents the process of uploading an object. Allows you to monitor and manage the upload.
269
+ *
270
+ * Note: React Native Firebase returns Promises for pause/resume/cancel to communicate with native iOS/Android.
271
+ *
272
+ * @public
273
+ */
274
+ export interface UploadTask {
275
+ /**
276
+ * Cancels a running task. Has no effect on a complete or failed task.
277
+ * @returns True if the cancel had an effect.
278
+ */
279
+ cancel(): Promise<boolean>;
280
+
281
+ /**
282
+ * Equivalent to calling `then(null, onRejected)`.
283
+ */
284
+ catch(onRejected: (error: NativeFirebaseError) => unknown): Promise<unknown>;
285
+
286
+ /**
287
+ * Listens for events on this task.
288
+ *
289
+ * @returns If only the event argument is passed, returns a function you can use to add callbacks.
290
+ * Otherwise returns a function you can call to unregister the callbacks.
291
+ */
292
+ on(
293
+ event: TaskEvent,
294
+ nextOrObserver?:
295
+ | StorageObserver<UploadTaskSnapshot>
296
+ | null
297
+ | ((snapshot: UploadTaskSnapshot) => unknown),
298
+ error?: ((error: NativeFirebaseError) => unknown) | null,
299
+ complete?: CompleteFn | null,
300
+ ): Unsubscribe | Subscribe<UploadTaskSnapshot>;
301
+
302
+ /**
303
+ * Pauses a currently running task. Has no effect on a paused or failed task.
304
+ * @returns True if the operation took effect, false if ignored.
305
+ */
306
+ pause(): Promise<boolean>;
307
+
308
+ /**
309
+ * Resumes a paused task. Has no effect on a currently running or failed task.
310
+ * @returns True if the operation took effect, false if ignored.
311
+ */
312
+ resume(): Promise<boolean>;
313
+
314
+ /**
315
+ * A snapshot of the current task state.
316
+ */
317
+ snapshot: UploadTaskSnapshot;
318
+
319
+ /**
320
+ * This object behaves like a Promise, and resolves with its snapshot data when the upload completes.
321
+ */
322
+ then(
323
+ onFulfilled?: ((snapshot: UploadTaskSnapshot) => unknown) | null,
324
+ onRejected?: ((error: NativeFirebaseError) => unknown) | null,
325
+ ): Promise<unknown>;
326
+ }
327
+
328
+ /**
329
+ * Holds data about the current state of the upload task.
330
+ * @public
331
+ */
332
+ export interface UploadTaskSnapshot {
333
+ /**
334
+ * The number of bytes that have been successfully uploaded so far.
335
+ */
336
+ bytesTransferred: number;
337
+
338
+ /**
339
+ * Before the upload completes, contains the metadata sent to the server.
340
+ * After the upload completes, contains the metadata sent back from the server.
341
+ */
342
+ metadata: FullMetadata;
343
+
344
+ /**
345
+ * The reference that spawned this snapshot's upload task.
346
+ */
347
+ ref: StorageReference;
348
+
349
+ /**
350
+ * The current state of the task.
351
+ */
352
+ state: TaskState;
353
+
354
+ /**
355
+ * The task of which this is a snapshot.
356
+ */
357
+ task: UploadTask;
358
+
359
+ /**
360
+ * The total number of bytes to be uploaded.
361
+ */
362
+ totalBytes: number;
363
+ }
364
+
365
+ /**
366
+ * Result returned from a non-resumable upload.
367
+ * @public
368
+ */
369
+ export interface UploadResult {
370
+ /**
371
+ * Contains the metadata sent back from the server.
372
+ */
373
+ readonly metadata: FullMetadata;
374
+
375
+ /**
376
+ * The reference that spawned this upload.
377
+ */
378
+ readonly ref: StorageReference;
379
+ }
380
+
381
+ export type Subscribe<T> = (
382
+ nextOrObserver?: StorageObserver<T> | null | NextFn<T>,
383
+ error?: ((error: NativeFirebaseError) => unknown) | null,
384
+ complete?: CompleteFn | null,
385
+ ) => Unsubscribe;
386
+
387
+ /**
388
+ * Snapshot of a storage task (upload or download).
389
+ */
390
+ export interface TaskSnapshot extends UploadTaskSnapshot {
391
+ /**
392
+ * If the state is `error`, returns a JavaScript error of the current task snapshot.
393
+ */
394
+ error?: NativeFirebaseError;
395
+ }
396
+
397
+ /**
398
+ * Result of a completed task.
399
+ */
400
+ export type TaskResult = UploadResult;
401
+
402
+ /**
403
+ * Observer object for task state changes.
404
+ */
405
+ export type TaskSnapshotObserver = StorageObserver<TaskSnapshot>;
406
+
407
+ /**
408
+ * Storage task for uploads or downloads.
409
+ */
410
+ export type Task = UploadTask;
411
+
412
+ /**
413
+ * Options for connecting to the storage emulator (web only).
414
+ */
415
+ export interface EmulatorMockTokenOptions {
416
+ mockUserToken?: string | null;
417
+ }
@@ -17,6 +17,9 @@
17
17
 
18
18
  import { isNull, isObject, isString } from '@react-native-firebase/app/dist/module/common';
19
19
  import { NativeFirebaseError } from '@react-native-firebase/app/dist/module/internal';
20
+ import type { SettableMetadata, UploadMetadata } from './types/storage';
21
+ import type { StorageInternal } from './types/internal';
22
+ import type { NativeErrorUserInfo } from '@react-native-firebase/app/dist/module/types/internal';
20
23
 
21
24
  const SETTABLE_FIELDS = [
22
25
  'cacheControl',
@@ -25,21 +28,39 @@ const SETTABLE_FIELDS = [
25
28
  'contentLanguage',
26
29
  'contentType',
27
30
  'customMetadata',
28
- 'md5hash',
29
- ];
30
-
31
- export async function handleStorageEvent(storageInstance, event) {
31
+ 'md5Hash',
32
+ ] as const;
33
+
34
+ const LEGACY_MD5_HASH_FIELD = 'md5hash';
35
+ const MD5_HASH_FIELD = 'md5Hash';
36
+
37
+ export async function handleStorageEvent(
38
+ storageInstance: StorageInternal,
39
+ event: {
40
+ taskId: string;
41
+ eventName: string;
42
+ body?: { error?: NativeErrorUserInfo };
43
+ },
44
+ ): Promise<void> {
32
45
  const { taskId, eventName } = event;
33
46
  const body = event.body || {};
34
47
 
35
48
  if (body.error) {
36
- body.error = await NativeFirebaseError.fromEvent(body.error, storageInstance._config.namespace);
49
+ // Convert NativeErrorUserInfo to NativeFirebaseError instance
50
+ const nativeError = NativeFirebaseError.fromEvent(
51
+ body.error,
52
+ storageInstance._config.namespace,
53
+ );
54
+ // Assign NativeFirebaseError (Error instance) to body.error for consumers
55
+ // Type assertion needed because body.error is typed as NativeErrorUserInfo in input,
56
+ // but consumers expect Error instance
57
+ (body as { error?: Error }).error = nativeError;
37
58
  }
38
59
 
39
60
  storageInstance.emitter.emit(storageInstance.eventNameForApp(taskId, eventName), body);
40
61
  }
41
62
 
42
- export function getHttpUrlParts(url) {
63
+ export function getHttpUrlParts(url: string): { bucket: string; path: string } | null {
43
64
  const decoded = decodeURIComponent(url);
44
65
  const parts = decoded.match(/\/b\/(.*)\/o\/([a-zA-Z0-9./\-_]+)(.*)/);
45
66
 
@@ -47,10 +68,10 @@ export function getHttpUrlParts(url) {
47
68
  return null;
48
69
  }
49
70
 
50
- return { bucket: `gs://${parts[1]}`, path: parts[2] };
71
+ return { bucket: `gs://${parts[1]}`, path: parts[2]! };
51
72
  }
52
73
 
53
- export function getGsUrlParts(url) {
74
+ export function getGsUrlParts(url: string): { bucket: string; path: string } {
54
75
  const bucket = url.substring(0, url.indexOf('/', 5)) || url;
55
76
  const path =
56
77
  (url.indexOf('/', 5) > -1 ? url.substring(url.indexOf('/', 5) + 1, url.length) : '/') || '/';
@@ -58,31 +79,49 @@ export function getGsUrlParts(url) {
58
79
  return { bucket, path };
59
80
  }
60
81
 
61
- export function validateMetadata(metadata, update = true) {
82
+ export function validateMetadata(
83
+ metadata: SettableMetadata | UploadMetadata,
84
+ update = true,
85
+ ): SettableMetadata | UploadMetadata {
62
86
  if (!isObject(metadata)) {
63
87
  throw new Error('firebase.storage.SettableMetadata must be an object value if provided.');
64
88
  }
65
89
 
66
90
  const metadataEntries = Object.entries(metadata);
91
+ const validatedMetadata: Record<string, unknown> = {};
92
+ let hasLegacyMd5Hash = false;
93
+ let hasMd5Hash = false;
67
94
 
68
95
  for (let i = 0; i < metadataEntries.length; i++) {
69
- const [key, value] = metadataEntries[i];
96
+ const entry = metadataEntries[i];
97
+ if (!entry) continue;
98
+ const [key, value] = entry;
99
+ const normalizedKey = key === LEGACY_MD5_HASH_FIELD ? MD5_HASH_FIELD : key;
100
+
101
+ if (key === LEGACY_MD5_HASH_FIELD) {
102
+ hasLegacyMd5Hash = true;
103
+ }
104
+
105
+ if (key === MD5_HASH_FIELD) {
106
+ hasMd5Hash = true;
107
+ }
108
+
70
109
  // validate keys
71
- if (!SETTABLE_FIELDS.includes(key)) {
110
+ if (!SETTABLE_FIELDS.includes(normalizedKey as (typeof SETTABLE_FIELDS)[number])) {
72
111
  throw new Error(
73
112
  `firebase.storage.SettableMetadata unknown property '${key}' provided for metadata.`,
74
113
  );
75
114
  }
76
115
 
77
116
  // md5 is only allowed on put, not on update
78
- if (key === 'md5hash' && update === true) {
117
+ if (normalizedKey === MD5_HASH_FIELD && update === true) {
79
118
  throw new Error(
80
- `firebase.storage.SettableMetadata md5hash may only be set on upload, not on updateMetadata`,
119
+ `firebase.storage.SettableMetadata ${MD5_HASH_FIELD} may only be set on upload, not on updateMetadata`,
81
120
  );
82
121
  }
83
122
 
84
123
  // validate values
85
- if (key !== 'customMetadata') {
124
+ if (normalizedKey !== 'customMetadata') {
86
125
  if (!isString(value) && !isNull(value)) {
87
126
  throw new Error(
88
127
  `firebase.storage.SettableMetadata invalid property '${key}' should be a string or null value.`,
@@ -93,7 +132,15 @@ export function validateMetadata(metadata, update = true) {
93
132
  'firebase.storage.SettableMetadata.customMetadata must be an object of keys and string values or null value.',
94
133
  );
95
134
  }
135
+
136
+ validatedMetadata[normalizedKey] = value;
137
+ }
138
+
139
+ if (hasLegacyMd5Hash && hasMd5Hash) {
140
+ throw new Error(
141
+ "firebase.storage.SettableMetadata cannot contain both 'md5Hash' and legacy 'md5hash' properties.",
142
+ );
96
143
  }
97
144
 
98
- return metadata;
145
+ return validatedMetadata as SettableMetadata | UploadMetadata;
99
146
  }
package/lib/version.ts ADDED
@@ -0,0 +1,2 @@
1
+ // Generated by genversion.
2
+ export const version = '25.0.1';
@@ -0,0 +1,3 @@
1
+ // No-op for android.
2
+ const RNFBStorageModule = {};
3
+ export default RNFBStorageModule;
@@ -0,0 +1,3 @@
1
+ // Re-export the main module
2
+ const RNFBStorageModule = {};
3
+ export default RNFBStorageModule;