Skip to content

Commit

Permalink
Refactor: trying to centralise all firebase types,
Browse files Browse the repository at this point in the history
Which should make upgrading firebase easier
  • Loading branch information
benwinding committed Jan 24, 2022
1 parent 2d79271 commit af3b2ab
Show file tree
Hide file tree
Showing 36 changed files with 377 additions and 237 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,14 @@
"microbundle": "^0.12.4",
"ts-jest": "^25",
"tslint": "^5.16.0",
"typescript": "^4.1.x"
"typescript": "4.5.5"
},
"homepage": "https://github.com/benwinding/react-admin-firebase",
"email": "[email protected]",
"license": "MIT",
"scripts": {
"build": "rm -rf dist && microbundle",
"tsc-test": "tsc -p ./tsconfig.spec.json",
"watch": "microbundle watch",
"start-demo": "gulp start-demo",
"start-emulator": "yarn firebase emulators:start --only firestore",
Expand Down
4 changes: 2 additions & 2 deletions src/misc/document-parser.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { QueryDocumentSnapshot } from '@firebase/firestore-types';
import { FireStoreDocumentSnapshot, FireStoreQueryDocumentSnapshot } from './firebase-models';
import { parseAllDatesDoc } from './timestamp-parser';

export const parseFireStoreDocument = (doc: QueryDocumentSnapshot) => {
export const parseFireStoreDocument = (doc: FireStoreQueryDocumentSnapshot) => {
const data = doc.data();
parseAllDatesDoc(data);
// React Admin requires an id field on every document,
Expand Down
5 changes: 1 addition & 4 deletions src/misc/file-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,8 @@ export const recursivelyMapStorageUrls = async (
if (isAlreadyUploaded) {
return fieldValue;
}
let ref: firebase.storage.Reference = null as any;
try {
ref = fireWrapper.storage().ref(fieldValue.src);
const src = await ref.getDownloadURL();
const src = await fireWrapper.getStorageDownloadUrl(fieldValue.src);
return {
...fieldValue,
src
Expand All @@ -88,7 +86,6 @@ export const recursivelyMapStorageUrls = async (
logError(`Error when getting download URL`, {
error,
fieldValue,
ref
});
return fieldValue;
}
Expand Down
32 changes: 32 additions & 0 deletions src/misc/firebase-models.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import {
DocumentSnapshot,
Query,
QueryDocumentSnapshot,
OrderByDirection
} from '@firebase/firestore-types';

export type FireUser = firebase.User;
export type FireApp = firebase.app.App;

export type FireStorage = firebase.storage.Storage;
export type FireStorageReference = firebase.storage.Reference;
export type FireUploadTaskSnapshot = firebase.storage.UploadTaskSnapshot;
export type FireUploadTask = firebase.storage.UploadTask;
export type FireStoragePutFileResult = {
task: FireUploadTask,
taskResult: Promise<FireUploadTaskSnapshot>,
downloadUrl: Promise<string>,
}

export type FireAuth = firebase.auth.Auth;
export type FireAuthUserCredentials = firebase.auth.UserCredential;

export type FireStore = firebase.firestore.Firestore;
export type FireStoreBatch = firebase.firestore.WriteBatch;
export type FireStoreTimeStamp = firebase.firestore.FieldValue;
export type FireStoreDocumentRef = firebase.firestore.DocumentReference;
export type FireStoreDocumentSnapshot = DocumentSnapshot;
export type FireStoreCollectionRef = firebase.firestore.CollectionReference;
export type FireStoreQueryDocumentSnapshot = QueryDocumentSnapshot;
export type FireStoreQuery = Query;
export type FireStoreQueryOrder = OrderByDirection;
7 changes: 3 additions & 4 deletions src/misc/messageTypes.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
// Firebase types
import { CollectionReference } from "@firebase/firestore-types";
import { FireStoreCollectionRef } from "./firebase-models";
import { GetListParams } from "./react-admin-models";

// PARAMETERS
export namespace messageTypes {
export type IParamsGetList = GetListParams;

export type CollectionQueryType = (
arg0: CollectionReference
) => CollectionReference;
arg0: FireStoreCollectionRef
) => FireStoreCollectionRef;

export interface IParamsGetOne {
id: string;
Expand Down
10 changes: 6 additions & 4 deletions src/misc/objectFlatten.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
type SearchValue = {} | number | string | boolean | null;

export interface SearchObj {
searchField: string;
searchValue: number | string | boolean | null;
searchValue: SearchValue;
}
export function getFieldReferences(
fieldName: string,
value: {} | number | string | boolean | null
value: {} | SearchValue
): SearchObj[] {
const isFalsy = !value;
const isSimple = isFalsy ||
Expand All @@ -16,11 +18,11 @@ export function getFieldReferences(
return [
{
searchField: fieldName,
searchValue: value as number | string | boolean | null,
searchValue: value as SearchValue,
},
];
}
const tree = {} as any;
const tree = {} as Record<string, SearchValue>;
tree[fieldName] = value;
return objectFlatten(tree);
}
Expand Down
51 changes: 11 additions & 40 deletions src/providers/AuthProvider.ts
Original file line number Diff line number Diff line change
@@ -1,53 +1,34 @@
import { messageTypes } from './../misc/messageTypes';
import firebase from 'firebase/app';
import 'firebase/auth';
import { FirebaseAuth, User } from '@firebase/auth-types';
import { log, retrieveStatusTxt, logWarn, logger } from '../misc';
import { RAFirebaseOptions } from './options';
import { FirebaseWrapper } from './database/firebase/FirebaseWrapper';
import {
AuthProvider as RaAuthProvider,
UserIdentity,
} from '../misc/react-admin-models';
import { IFirebaseWrapper } from './database';
import { FireUser } from 'misc/firebase-models';

class AuthClient {
private auth: FirebaseAuth;
private fireWrapper: IFirebaseWrapper;

constructor(firebaseConfig: {}, optionsInput?: RAFirebaseOptions) {
const options = optionsInput || {};
log('Auth Client: initializing...', { firebaseConfig, options });
const fireWrapper = new FirebaseWrapper();
fireWrapper.init(firebaseConfig, options);
this.auth = fireWrapper.auth();
this.fireWrapper = new FirebaseWrapper(options, firebaseConfig);
options.persistence && this.setPersistence(options.persistence);
}

setPersistence(persistenceInput: 'session' | 'local' | 'none') {
let persistenceResolved: string;
switch (persistenceInput) {
case 'local':
persistenceResolved = firebase.auth.Auth.Persistence.LOCAL;
break;
case 'none':
persistenceResolved = firebase.auth.Auth.Persistence.NONE;
break;
case 'session':
default:
persistenceResolved = firebase.auth.Auth.Persistence.SESSION;
break;
}
log('setPersistence', { persistenceInput, persistenceResolved });
this.auth
.setPersistence(persistenceResolved)
.catch((error) => console.error(error));
return this.fireWrapper.authSetPersistence(persistenceInput);
}

public async HandleAuthLogin(params: { username: string; password: string }) {
const { username, password } = params;

if (username && password) {
try {
const user = await this.auth.signInWithEmailAndPassword(
const user = await this.fireWrapper.authSigninEmailPassword(
username,
password
);
Expand All @@ -63,7 +44,7 @@ class AuthClient {
}

public HandleAuthLogout() {
return this.auth.signOut();
return this.fireWrapper.authSignOut();
}

public HandleAuthError(errorHttp: messageTypes.HttpErrorType) {
Expand All @@ -78,22 +59,12 @@ class AuthClient {
return Promise.reject();
}

public async HandleAuthCheck(): Promise<void> {
return this.getUserLogin() as any; // Prevents breaking change
public async HandleAuthCheck(): Promise<any> {
return this.getUserLogin();
}

public getUserLogin(): Promise<User> {
return new Promise((resolve, reject) => {
if (this.auth.currentUser) return resolve(this.auth.currentUser);
const unsubscribe = this.auth.onAuthStateChanged((user) => {
unsubscribe();
if (user) {
resolve(user);
} else {
reject();
}
});
});
public getUserLogin(): Promise<FireUser> {
return this.fireWrapper.authGetUserLoggedIn();
}

public async HandleGetPermissions() {
Expand Down
7 changes: 3 additions & 4 deletions src/providers/DataProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
import * as ra from "../misc/react-admin-models";
import { RAFirebaseOptions } from "./options";
import { FirebaseWrapper } from "./database/firebase/FirebaseWrapper";
import { FireApp } from "./database/firebase/IFirebaseWrapper";
import { FireApp } from "../misc/firebase-models";
import { FireClient } from "./database/FireClient";
import { GetList, GetMany, GetManyReference, GetOne } from "./queries";
import { Create, Delete, DeleteMany, Update, UpdateMany } from "./commands";
Expand All @@ -34,16 +34,15 @@ export function DataProvider(
options
});

const fireWrapper = new FirebaseWrapper();
fireWrapper.init(firebaseConfig, optionsInput);
const fireWrapper = new FirebaseWrapper(optionsInput, firebaseConfig);

async function run<T>(cb: () => Promise<T>) {
let res: any;
try {
res = await cb();
return res;
} catch (error) {
const errorMsg = error.toString();
const errorMsg = ((error as any) || '').toString();
const code = retrieveStatusCode(errorMsg);
const errorObj = { status: code, message: errorMsg, json: res };
logError("DataProvider:", error, { errorMsg, code, errorObj });
Expand Down
2 changes: 1 addition & 1 deletion src/providers/commands/Create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export async function Create<T extends ra.Record>(
},
};
}
const newId = fireWrapper.db().collection("collections").doc().id;
const newId = fireWrapper.dbMakeNewId();
const data = await client.parseDataAndUpload(r, newId, params.data);
const docObj = { ...data };
client.checkRemoveIdField(docObj, newId);
Expand Down
2 changes: 1 addition & 1 deletion src/providers/commands/Delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export async function Delete<T extends ra.Record>(
const id = params.id + "";
await r.collection.doc(id).delete();
} catch (error) {
throw new Error(error);
throw new Error(error as any);
}
return {
data: params.previousData as T,
Expand Down
8 changes: 3 additions & 5 deletions src/providers/commands/DeleteMany.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ import { log } from "../../misc";
import * as ra from "../../misc/react-admin-models";
import { DeleteManySoft } from "./DeleteMany.Soft";

type DocumentRef = firebase.firestore.DocumentReference<any>;

export async function DeleteMany(
resourceName: string,
params: ra.DeleteManyParams,
Expand All @@ -17,17 +15,17 @@ export async function DeleteMany(
const r = await rm.TryGetResource(resourceName);
log("DeleteMany", { resourceName, resource: r, params });
const returnData: ra.Identifier[] = [];
const batch = fireWrapper.db().batch();
const batch = fireWrapper.dbCreateBatch();
for (const id of params.ids) {
const idStr = id + '';
const docToDelete = r.collection.doc(idStr) as DocumentRef;
const docToDelete = r.collection.doc(idStr);
batch.delete(docToDelete);
returnData.push(id);
}
try {
await batch.commit();
} catch (error) {
throw new Error(error)
throw new Error(error as any)
}
return { data: returnData };
}
14 changes: 4 additions & 10 deletions src/providers/database/FireClient.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { set } from "lodash";
import { set, get } from "lodash";
import {
AddCreatedByFields,
AddUpdatedByFields,
Expand All @@ -14,9 +14,6 @@ import { IResource, ResourceManager } from "./ResourceManager";

export class FireClient {
public rm: ResourceManager;
public db() {
return this.fireWrapper.db();
}

constructor(
public fireWrapper: IFirebaseWrapper,
Expand Down Expand Up @@ -78,20 +75,17 @@ export class FireClient {
rawFile: any
): Promise<string | undefined> {
log("saveFile() saving file...", { storagePath, rawFile });
const task = this.fireWrapper.storage().ref(storagePath).put(rawFile);
try {
const taskResult: firebase.storage.UploadTaskSnapshot = await new Promise(
(res, rej) => task.then(res).catch(rej)
);
const getDownloadURL = await taskResult.ref.getDownloadURL();
const { taskResult, downloadUrl } = this.fireWrapper.putFile(storagePath, rawFile);
const getDownloadURL = await downloadUrl;
log("saveFile() saved file", {
storagePath,
taskResult,
getDownloadURL,
});
return this.options.relativeFilePaths ? storagePath : getDownloadURL;
} catch (storageError) {
if (storageError.code === "storage/unknown") {
if (get(storageError, 'code') === "storage/unknown") {
logError(
'saveFile() error saving file, No bucket found! Try clicking "Get Started" in firebase -> storage',
{ storageError }
Expand Down
Loading

0 comments on commit af3b2ab

Please sign in to comment.