@rebasepro/client-firebase 0.0.1-canary.4d4fb3e
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 +21 -0
- package/README.md +4 -0
- package/dist/components/FirebaseLoginView.d.ts +72 -0
- package/dist/components/RebaseFirebaseApp.d.ts +19 -0
- package/dist/components/RebaseFirebaseAppProps.d.ts +144 -0
- package/dist/components/index.d.ts +3 -0
- package/dist/components/social_icons.d.ts +6 -0
- package/dist/hooks/index.d.ts +7 -0
- package/dist/hooks/useAppCheck.d.ts +20 -0
- package/dist/hooks/useFirebaseAuthController.d.ts +15 -0
- package/dist/hooks/useFirebaseRealTimeDBDelegate.d.ts +5 -0
- package/dist/hooks/useFirebaseStorageSource.d.ts +14 -0
- package/dist/hooks/useFirestoreDriver.d.ts +56 -0
- package/dist/hooks/useInitialiseFirebase.d.ts +34 -0
- package/dist/hooks/useRecaptcha.d.ts +8 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.es.js +2757 -0
- package/dist/index.es.js.map +1 -0
- package/dist/index.umd.js +2743 -0
- package/dist/index.umd.js.map +1 -0
- package/dist/social_icons.d.ts +6 -0
- package/dist/types/appcheck.d.ts +10 -0
- package/dist/types/auth.d.ts +41 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/text_search.d.ts +39 -0
- package/dist/utils/algolia.d.ts +9 -0
- package/dist/utils/collections_firestore.d.ts +5 -0
- package/dist/utils/database.d.ts +2 -0
- package/dist/utils/index.d.ts +7 -0
- package/dist/utils/local_text_search_controller.d.ts +2 -0
- package/dist/utils/pinecone.d.ts +24 -0
- package/dist/utils/rebase_search_controller.d.ts +73 -0
- package/dist/utils/text_search_controller.d.ts +13 -0
- package/package.json +61 -0
- package/src/components/FirebaseLoginView.tsx +703 -0
- package/src/components/RebaseFirebaseApp.tsx +275 -0
- package/src/components/RebaseFirebaseAppProps.tsx +180 -0
- package/src/components/index.ts +3 -0
- package/src/components/social_icons.tsx +135 -0
- package/src/hooks/index.ts +7 -0
- package/src/hooks/useAppCheck.ts +101 -0
- package/src/hooks/useFirebaseAuthController.ts +334 -0
- package/src/hooks/useFirebaseRealTimeDBDelegate.ts +269 -0
- package/src/hooks/useFirebaseStorageSource.ts +208 -0
- package/src/hooks/useFirestoreDriver.ts +778 -0
- package/src/hooks/useInitialiseFirebase.ts +132 -0
- package/src/hooks/useRecaptcha.tsx +28 -0
- package/src/index.ts +4 -0
- package/src/social_icons.tsx +135 -0
- package/src/types/appcheck.ts +11 -0
- package/src/types/auth.tsx +74 -0
- package/src/types/index.ts +3 -0
- package/src/types/text_search.ts +42 -0
- package/src/utils/algolia.ts +27 -0
- package/src/utils/collections_firestore.ts +149 -0
- package/src/utils/database.ts +39 -0
- package/src/utils/index.ts +7 -0
- package/src/utils/local_text_search_controller.ts +143 -0
- package/src/utils/pinecone.ts +75 -0
- package/src/utils/rebase_search_controller.ts +356 -0
- package/src/utils/text_search_controller.ts +34 -0
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { FirebaseApp } from "@firebase/app";
|
|
2
|
+
import {
|
|
3
|
+
deleteObject,
|
|
4
|
+
getDownloadURL,
|
|
5
|
+
getMetadata,
|
|
6
|
+
getStorage,
|
|
7
|
+
list,
|
|
8
|
+
ref,
|
|
9
|
+
uploadBytesResumable
|
|
10
|
+
} from "@firebase/storage";
|
|
11
|
+
import { DownloadConfig, DownloadMetadata, StorageListResult, StorageSource, UploadFileProps } from "@rebasepro/types";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @group Firebase
|
|
15
|
+
*/
|
|
16
|
+
export interface FirebaseStorageSourceProps {
|
|
17
|
+
firebaseApp?: FirebaseApp
|
|
18
|
+
bucketUrl?: string
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Use this hook to build an {@link StorageSource} based on Firebase storage
|
|
23
|
+
* @group Firebase
|
|
24
|
+
*/
|
|
25
|
+
export function useFirebaseStorageSource({
|
|
26
|
+
firebaseApp,
|
|
27
|
+
bucketUrl
|
|
28
|
+
}: FirebaseStorageSourceProps): StorageSource {
|
|
29
|
+
const projectId = firebaseApp?.options?.projectId;
|
|
30
|
+
const urlsCache: Record<string, DownloadConfig> = {};
|
|
31
|
+
return {
|
|
32
|
+
uploadFile({
|
|
33
|
+
file,
|
|
34
|
+
fileName,
|
|
35
|
+
path,
|
|
36
|
+
metadata,
|
|
37
|
+
bucket
|
|
38
|
+
}: UploadFileProps)
|
|
39
|
+
: Promise<any> {
|
|
40
|
+
try {
|
|
41
|
+
if (!firebaseApp) throw Error("useFirebaseStorageSource Firebase not initialised");
|
|
42
|
+
const storageBucketUrl = bucket ?? bucketUrl;
|
|
43
|
+
const storage = getStorage(firebaseApp, storageBucketUrl);
|
|
44
|
+
if (!storage) throw Error("useFirebaseStorageSource Firebase not initialised");
|
|
45
|
+
const usedFilename = fileName ?? file.name;
|
|
46
|
+
|
|
47
|
+
const storageRef = ref(storage, `${path}/${usedFilename}`);
|
|
48
|
+
const uploadTask = uploadBytesResumable(storageRef, file, metadata);
|
|
49
|
+
|
|
50
|
+
return new Promise((resolve, reject) => {
|
|
51
|
+
let lastProgress = 0;
|
|
52
|
+
let timeoutId: NodeJS.Timeout | null = null;
|
|
53
|
+
|
|
54
|
+
const clearTimeoutIfExists = () => {
|
|
55
|
+
if (timeoutId) {
|
|
56
|
+
clearTimeout(timeoutId);
|
|
57
|
+
timeoutId = null;
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const setProgressTimeout = () => {
|
|
62
|
+
clearTimeoutIfExists();
|
|
63
|
+
timeoutId = setTimeout(() => {
|
|
64
|
+
uploadTask.cancel();
|
|
65
|
+
reject(new Error("Upload failed - This is likely a CORS configuration issue. " +
|
|
66
|
+
"Make sure Firebase Storage is enabled in your project: " + `https://console.firebase.google.com/u/0/project/${projectId}/storage` + ". " +
|
|
67
|
+
"If it is, check Firebase Storage CORS settings."));
|
|
68
|
+
}, 5000);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
setProgressTimeout();
|
|
72
|
+
|
|
73
|
+
uploadTask.on("state_changed",
|
|
74
|
+
(snapshot) => {
|
|
75
|
+
const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
|
|
76
|
+
|
|
77
|
+
if (progress > lastProgress) {
|
|
78
|
+
lastProgress = progress;
|
|
79
|
+
setProgressTimeout();
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
(error) => {
|
|
83
|
+
clearTimeoutIfExists();
|
|
84
|
+
console.error("Firebase Storage upload error:", error);
|
|
85
|
+
|
|
86
|
+
let errorMessage = "Unknown upload error";
|
|
87
|
+
|
|
88
|
+
if (error?.message) {
|
|
89
|
+
errorMessage = error.message;
|
|
90
|
+
} else if (typeof error === "string") {
|
|
91
|
+
errorMessage = error;
|
|
92
|
+
} else if (error?.code) {
|
|
93
|
+
errorMessage = error.code;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (error?.code === "storage/unauthorized") {
|
|
97
|
+
reject(new Error("Unauthorized: Check Firebase Storage security rules"));
|
|
98
|
+
} else if (error?.code === "storage/canceled") {
|
|
99
|
+
reject(new Error("Upload canceled"));
|
|
100
|
+
} else if (error?.code === "storage/unknown" || !error?.code) {
|
|
101
|
+
reject(new Error("Upload failed - Check Firebase Storage CORS configuration or network connection"));
|
|
102
|
+
} else if (errorMessage.toLowerCase().includes("network")) {
|
|
103
|
+
reject(new Error("Network error: Check your internet connection"));
|
|
104
|
+
} else {
|
|
105
|
+
const newError = Object.assign(new Error(errorMessage), { code: error?.code });
|
|
106
|
+
reject(newError);
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
() => {
|
|
110
|
+
clearTimeoutIfExists();
|
|
111
|
+
const fullPath = uploadTask.snapshot.ref.fullPath;
|
|
112
|
+
const bucketName = uploadTask.snapshot.ref.bucket;
|
|
113
|
+
resolve({
|
|
114
|
+
path: fullPath,
|
|
115
|
+
bucket: bucketName,
|
|
116
|
+
storageUrl: `gs://${bucketName}/${fullPath}`
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
);
|
|
120
|
+
});
|
|
121
|
+
} catch (error) {
|
|
122
|
+
return Promise.reject(error);
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
|
|
126
|
+
async getFile(path: string, bucket?: string): Promise<File | null> {
|
|
127
|
+
try {
|
|
128
|
+
if (!firebaseApp) throw Error("useFirebaseStorageSource Firebase not initialised");
|
|
129
|
+
const storageBucketUrl = bucket ?? bucketUrl;
|
|
130
|
+
const storage = getStorage(firebaseApp, storageBucketUrl);
|
|
131
|
+
if (!storage) throw Error("useFirebaseStorageSource Firebase not initialised");
|
|
132
|
+
const fileRef = ref(storage, path);
|
|
133
|
+
const url = await getDownloadURL(fileRef);
|
|
134
|
+
const response = await fetch(url);
|
|
135
|
+
const blob = await response.blob();
|
|
136
|
+
return new File([blob], path);
|
|
137
|
+
} catch (e: any) {
|
|
138
|
+
if (e?.code === "storage/object-not-found") return null;
|
|
139
|
+
throw e;
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
|
|
143
|
+
async getDownloadURL(storagePathOrUrl: string, bucket?: string): Promise<DownloadConfig> {
|
|
144
|
+
if (!firebaseApp) throw Error("useFirebaseStorageSource Firebase not initialised");
|
|
145
|
+
|
|
146
|
+
// Support fully-qualified gs:// URLs
|
|
147
|
+
let resolvedPathOrUrl = storagePathOrUrl;
|
|
148
|
+
let resolvedBucket = bucket;
|
|
149
|
+
if (storagePathOrUrl.startsWith("gs://")) {
|
|
150
|
+
// Format: gs://<bucket>/<path>
|
|
151
|
+
const withoutProtocol = storagePathOrUrl.substring("gs://".length);
|
|
152
|
+
const firstSlash = withoutProtocol.indexOf("/");
|
|
153
|
+
if (firstSlash > 0) {
|
|
154
|
+
resolvedBucket = withoutProtocol.substring(0, firstSlash);
|
|
155
|
+
resolvedPathOrUrl = withoutProtocol.substring(firstSlash + 1);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const storageBucketUrl = resolvedBucket ?? bucketUrl;
|
|
160
|
+
const storage = getStorage(firebaseApp, storageBucketUrl);
|
|
161
|
+
if (!storage) throw Error("useFirebaseStorageSource Firebase not initialised");
|
|
162
|
+
|
|
163
|
+
if (urlsCache[storagePathOrUrl])
|
|
164
|
+
return urlsCache[storagePathOrUrl];
|
|
165
|
+
try {
|
|
166
|
+
const fileRef = ref(storage, resolvedPathOrUrl);
|
|
167
|
+
const [url, metadata] = await Promise.all([getDownloadURL(fileRef), getMetadata(fileRef)]);
|
|
168
|
+
const result: DownloadConfig = {
|
|
169
|
+
url,
|
|
170
|
+
metadata: metadata as DownloadMetadata
|
|
171
|
+
}
|
|
172
|
+
urlsCache[storagePathOrUrl] = result;
|
|
173
|
+
return result;
|
|
174
|
+
} catch (e: any) {
|
|
175
|
+
if (e?.code === "storage/object-not-found") return {
|
|
176
|
+
url: null,
|
|
177
|
+
fileNotFound: true
|
|
178
|
+
};
|
|
179
|
+
throw e;
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
|
|
183
|
+
async list(path: string, options?: {
|
|
184
|
+
bucket?: string,
|
|
185
|
+
maxResults?: number,
|
|
186
|
+
pageToken?: string
|
|
187
|
+
}): Promise<StorageListResult> {
|
|
188
|
+
if (!firebaseApp) throw Error("useFirebaseStorageSource Firebase not initialised");
|
|
189
|
+
const storageBucketUrl = options?.bucket ?? bucketUrl;
|
|
190
|
+
const storage = getStorage(firebaseApp, storageBucketUrl);
|
|
191
|
+
if (!storage) throw Error("useFirebaseStorageSource Firebase not initialised");
|
|
192
|
+
const folderRef = ref(storage, path);
|
|
193
|
+
return await list(folderRef, {
|
|
194
|
+
maxResults: options?.maxResults,
|
|
195
|
+
pageToken: options?.pageToken
|
|
196
|
+
});
|
|
197
|
+
},
|
|
198
|
+
|
|
199
|
+
async deleteFile(path: string, bucket?: string): Promise<void> {
|
|
200
|
+
if (!firebaseApp) throw Error("useFirebaseStorageSource Firebase not initialised");
|
|
201
|
+
const storageBucketUrl = bucket ?? bucketUrl;
|
|
202
|
+
const storage = getStorage(firebaseApp, storageBucketUrl);
|
|
203
|
+
if (!storage) throw Error("useFirebaseStorageSource Firebase not initialised");
|
|
204
|
+
const fileRef = ref(storage, path);
|
|
205
|
+
return deleteObject(fileRef);
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
}
|