-
Notifications
You must be signed in to change notification settings - Fork 932
WIP: RxFire #933
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WIP: RxFire #933
Changes from 18 commits
300a1a6
cc5f15e
af4a601
1676c7b
5661262
3cdc3d7
28c3a11
a7a49f6
9d9769c
da2cfb7
cec2d57
f4ea936
4503a55
3d1a53a
ddc24aa
4cb0a99
76a1124
065729c
e87d98a
85c9da4
8887b51
ee8915d
07fb713
97ce638
5831f83
dca768f
22d6f13
fb759b4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/rxfire*.js | ||
/rxfire*.map | ||
/rxfire*.gz | ||
/rxfire*.tgz | ||
|
||
# generated declaration files | ||
auth/index.d.ts | ||
firestore/collection/index.d.ts | ||
firestore/document/index.d.ts | ||
firestore/fromRef.d.ts | ||
firestore/index.d.ts | ||
functions/index.d.ts | ||
index.d.ts | ||
storage/index.d.ts | ||
test/index.d.ts | ||
test/firestore.test.d.ts |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
/** | ||
* Copyright 2018 Google Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
import { auth, User } from 'firebase/app'; | ||
import { Observable, from, of } from 'rxjs'; | ||
import { switchMap } from 'rxjs/operators'; | ||
|
||
/** | ||
* Create an observable of authentication state. The observer is only | ||
* triggered on sign-in or sign-out. | ||
* @param auth firebase.auth.Auth | ||
*/ | ||
export function authState(auth: auth.Auth): Observable<User> { | ||
return new Observable(subscriber => { | ||
const unsubscribe = auth.onAuthStateChanged(subscriber); | ||
return { unsubscribe }; | ||
}); | ||
} | ||
|
||
/** | ||
* Create an observable of user state. The observer is triggered for sign-in, | ||
* sign-out, and token refresh events | ||
* @param auth firebase.auth.Auth | ||
*/ | ||
export function user(auth: auth.Auth): Observable<User> { | ||
return new Observable(subscriber => { | ||
const unsubscribe = auth.onIdTokenChanged(subscriber); | ||
return { unsubscribe }; | ||
}); | ||
} | ||
|
||
/** | ||
* Create an observable of idToken state. The observer is triggered for sign-in, | ||
* sign-out, and token refresh events | ||
* @param auth firebase.auth.Auth | ||
*/ | ||
export function idToken(auth: auth.Auth) { | ||
return user(auth).pipe( | ||
switchMap(user => (user ? from(user.getIdToken()) : of(null))) | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"name": "rxfire/auth", | ||
"main": "dist/index.cjs.js", | ||
"module": "dist/index.esm.js" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
/** | ||
* Copyright 2018 Google Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
import { firestore } from 'firebase/app'; | ||
import { fromCollectionRef } from '../fromRef'; | ||
import { Observable } from 'rxjs'; | ||
import { map, filter, scan } from 'rxjs/operators'; | ||
|
||
const ALL_EVENTS: firestore.DocumentChangeType[] = [ | ||
'added', | ||
'modified', | ||
'removed' | ||
]; | ||
|
||
/** | ||
* Create an operator that determines if a the stream of document changes | ||
* are specified by the event filter. If the document change type is not | ||
* in specified events array, it will not be emitted. | ||
*/ | ||
const filterEvents = (events?: firestore.DocumentChangeType[]) => | ||
filter((changes: firestore.DocumentChange[]) => { | ||
let hasChange = false; | ||
changes.forEach(change => { | ||
if (events.indexOf(change.type) >= 0) { | ||
hasChange = true; | ||
} | ||
}); | ||
return hasChange; | ||
}); | ||
|
||
/** | ||
* Create an operator that filters out empty changes. We provide the | ||
* ability to filter on events, which means all changes can be filtered out. | ||
* This creates an empty array and would be incorrect to emit. | ||
*/ | ||
const filterEmpty = filter( | ||
(changes: firestore.DocumentChange[]) => changes.length > 0 | ||
); | ||
|
||
/** | ||
* Creates a new sorted array from a new change. | ||
* @param combined | ||
* @param change | ||
*/ | ||
function processIndividualChange( | ||
combined: firestore.DocumentChange[], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's be more descriptive of what this actually is in this name (i.e. the full array of changes and a single change to process) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed. |
||
change: firestore.DocumentChange | ||
): firestore.DocumentChange[] { | ||
switch (change.type) { | ||
case 'added': | ||
if ( | ||
combined[change.newIndex] && | ||
combined[change.newIndex].doc.id == change.doc.id | ||
) { | ||
// Not sure why the duplicates are getting fired | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This comment seems like a good opportunity for some more explanation There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||
} else { | ||
combined.splice(change.newIndex, 0, change); | ||
} | ||
break; | ||
case 'modified': | ||
// When an item changes position we first remove it | ||
// and then add it's new position | ||
if (change.oldIndex !== change.newIndex) { | ||
combined.splice(change.oldIndex, 1); | ||
combined.splice(change.newIndex, 0, change); | ||
} else { | ||
combined.splice(change.newIndex, 1, change); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is just a more difficult way of saying: combined[change.newIndex] = change; Can we swap it out and add a comment? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||
} | ||
break; | ||
case 'removed': | ||
combined.splice(change.oldIndex, 1); | ||
break; | ||
} | ||
return combined; | ||
} | ||
|
||
/** | ||
* Combines the total result set from the current set of changes from an incoming set | ||
* of changes. | ||
* @param current | ||
* @param changes | ||
* @param events | ||
*/ | ||
function processDocumentChanges( | ||
current: firestore.DocumentChange[], | ||
changes: firestore.DocumentChange[], | ||
events: firestore.DocumentChangeType[] = ALL_EVENTS | ||
) { | ||
changes.forEach(change => { | ||
// skip unwanted change types | ||
if (events.indexOf(change.type) > -1) { | ||
current = processIndividualChange(current, change); | ||
} | ||
}); | ||
return current; | ||
} | ||
|
||
/** | ||
* Return a stream of document changes on a query. These results are not in sort order but in | ||
* order of occurence. | ||
* @param query | ||
*/ | ||
export function docChanges( | ||
query: firestore.Query, | ||
events: firestore.DocumentChangeType[] = ALL_EVENTS | ||
) { | ||
return fromCollectionRef(query).pipe( | ||
map(snapshot => snapshot.docChanges()), | ||
filterEvents(events), | ||
filterEmpty | ||
); | ||
} | ||
|
||
/** | ||
* Return a stream of document snapshots on a query. These results are in sort order. | ||
* @param query | ||
*/ | ||
export function collection(query: firestore.Query) { | ||
return fromCollectionRef(query).pipe(map(changes => changes.docs)); | ||
} | ||
|
||
/** | ||
* Return a stream of document changes on a query. These results are in sort order. | ||
* @param query | ||
*/ | ||
export function sortedChanges( | ||
query: firestore.Query, | ||
events?: firestore.DocumentChangeType[] | ||
) { | ||
return docChanges(query, events).pipe( | ||
scan( | ||
( | ||
current: firestore.DocumentChange[], | ||
changes: firestore.DocumentChange[] | ||
) => processDocumentChanges(current, changes, events), | ||
[] | ||
) | ||
); | ||
} | ||
|
||
/** | ||
* Create a stream of changes as they occur it time. This method is similar | ||
* to stateChanges() but it collects each event in an array over time. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it's now |
||
*/ | ||
export function auditTrail( | ||
query: firestore.Query, | ||
events?: firestore.DocumentChangeType[] | ||
): Observable<firestore.DocumentChange[]> { | ||
return docChanges(query, events).pipe( | ||
scan((current, action) => [...current, ...action], []) | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
/** | ||
* Copyright 2018 Google Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
import { firestore } from 'firebase/app'; | ||
import { Observable } from 'rxjs'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You don't use this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||
import { fromDocRef } from '../fromRef'; | ||
|
||
export function doc(ref: firestore.DocumentReference) { | ||
return fromDocRef(ref); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
/** | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In this file we reference a whole bunch of generics that need upstream counterparts (specifically for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. action item for SDK |
||
* Copyright 2018 Google Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
import { firestore } from 'firebase/app'; | ||
import { Observable } from 'rxjs'; | ||
|
||
function _fromRef(ref: any): Observable<any> { | ||
return new Observable(subscriber => { | ||
const unsubscribe = ref.onSnapshot(subscriber); | ||
return { unsubscribe }; | ||
}); | ||
} | ||
|
||
export function fromRef(ref: firestore.DocumentReference | firestore.Query) { | ||
return _fromRef(ref); | ||
} | ||
|
||
export function fromDocRef( | ||
ref: firestore.DocumentReference | ||
): Observable<firestore.DocumentSnapshot> { | ||
return fromRef(ref); | ||
} | ||
|
||
export function fromCollectionRef<T>( | ||
ref: firestore.Query | ||
): Observable<firestore.QuerySnapshot> { | ||
return fromRef(ref); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
/** | ||
* Copyright 2018 Google Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
export * from './collection'; | ||
export * from './document'; | ||
export * from './fromRef'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"name": "rxfire/firestore", | ||
"main": "dist/index.cjs.js", | ||
"module": "dist/index.esm.js" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
/** | ||
* Copyright 2018 Google Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
import { functions } from 'firebase/app'; | ||
import { Observable, from } from 'rxjs'; | ||
import { map } from 'rxjs/operators'; | ||
|
||
export function httpsCallable<T = any, R = any>( | ||
functions: functions.Functions, | ||
name: string | ||
) { | ||
const callable = functions.httpsCallable(name); | ||
return (data: T) => { | ||
return from(callable(data)).pipe(map(r => r.data as R)); | ||
}; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"name": "rxfire/functions", | ||
"main": "dist/index.cjs.js", | ||
"module": "dist/index.esm.js" | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could be really inefficient as it'll exhaust the full list irregardless of the ability to early return, swap this for a for-loop?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or even some?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed