├── .husky ├── .npmignore ├── pre-commit └── commit-msg ├── example ├── android │ ├── app │ │ ├── src │ │ │ ├── main │ │ │ │ ├── res │ │ │ │ │ ├── values-night │ │ │ │ │ │ └── colors.xml │ │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ ├── ic_launcher_round.png │ │ │ │ │ │ └── ic_launcher_foreground.png │ │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ ├── ic_launcher_round.png │ │ │ │ │ │ └── ic_launcher_foreground.png │ │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ ├── ic_launcher_round.png │ │ │ │ │ │ └── ic_launcher_foreground.png │ │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ ├── ic_launcher_round.png │ │ │ │ │ │ └── ic_launcher_foreground.png │ │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ ├── ic_launcher_round.png │ │ │ │ │ │ └── ic_launcher_foreground.png │ │ │ │ │ ├── drawable-hdpi │ │ │ │ │ │ └── splashscreen_image.png │ │ │ │ │ ├── drawable-mdpi │ │ │ │ │ │ └── splashscreen_image.png │ │ │ │ │ ├── drawable-xhdpi │ │ │ │ │ │ └── splashscreen_image.png │ │ │ │ │ ├── drawable-xxhdpi │ │ │ │ │ │ └── splashscreen_image.png │ │ │ │ │ ├── drawable │ │ │ │ │ │ ├── splashscreen.xml │ │ │ │ │ │ └── rn_edit_text_material.xml │ │ │ │ │ ├── drawable-xxxhdpi │ │ │ │ │ │ └── splashscreen_image.png │ │ │ │ │ ├── values │ │ │ │ │ │ ├── colors.xml │ │ │ │ │ │ ├── strings.xml │ │ │ │ │ │ └── styles.xml │ │ │ │ │ └── mipmap-anydpi-v26 │ │ │ │ │ │ ├── ic_launcher.xml │ │ │ │ │ │ └── ic_launcher_round.xml │ │ │ │ ├── jni │ │ │ │ │ ├── MainApplicationModuleProvider.h │ │ │ │ │ ├── OnLoad.cpp │ │ │ │ │ ├── MainApplicationModuleProvider.cpp │ │ │ │ │ ├── MainComponentsRegistry.h │ │ │ │ │ ├── MainApplicationTurboModuleManagerDelegate.h │ │ │ │ │ ├── MainApplicationTurboModuleManagerDelegate.cpp │ │ │ │ │ ├── Android.mk │ │ │ │ │ └── MainComponentsRegistry.cpp │ │ │ │ ├── java │ │ │ │ │ └── com │ │ │ │ │ │ └── skillnation │ │ │ │ │ │ └── examplernfbhooks │ │ │ │ │ │ ├── newarchitecture │ │ │ │ │ │ ├── components │ │ │ │ │ │ │ └── MainComponentsRegistry.java │ │ │ │ │ │ ├── modules │ │ │ │ │ │ │ └── MainApplicationTurboModuleManagerDelegate.java │ │ │ │ │ │ └── MainApplicationReactNativeHost.java │ │ │ │ │ │ ├── MainActivity.java │ │ │ │ │ │ └── MainApplication.java │ │ │ │ └── AndroidManifest.xml │ │ │ └── debug │ │ │ │ ├── AndroidManifest.xml │ │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── skillnation │ │ │ │ └── examplernfbhooks │ │ │ │ └── ReactNativeFlipper.java │ │ ├── debug.keystore │ │ ├── proguard-rules.pro │ │ ├── build_defs.bzl │ │ └── BUCK │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── .gitignore │ ├── settings.gradle │ ├── gradle.properties │ ├── build.gradle │ ├── gradlew.bat │ └── gradlew ├── ios │ ├── Podfile.properties.json │ ├── example │ │ ├── Images.xcassets │ │ │ ├── Contents.json │ │ │ ├── SplashScreen.imageset │ │ │ │ ├── image.png │ │ │ │ └── Contents.json │ │ │ ├── AppIcon.appiconset │ │ │ │ ├── App-Icon-20x20@1x.png │ │ │ │ ├── App-Icon-20x20@2x.png │ │ │ │ ├── App-Icon-20x20@3x.png │ │ │ │ ├── App-Icon-29x29@1x.png │ │ │ │ ├── App-Icon-29x29@2x.png │ │ │ │ ├── App-Icon-29x29@3x.png │ │ │ │ ├── App-Icon-40x40@1x.png │ │ │ │ ├── App-Icon-40x40@2x.png │ │ │ │ ├── App-Icon-40x40@3x.png │ │ │ │ ├── App-Icon-60x60@2x.png │ │ │ │ ├── App-Icon-60x60@3x.png │ │ │ │ ├── App-Icon-76x76@1x.png │ │ │ │ ├── App-Icon-76x76@2x.png │ │ │ │ ├── ItunesArtwork@2x.png │ │ │ │ ├── App-Icon-83.5x83.5@2x.png │ │ │ │ └── Contents.json │ │ │ └── SplashScreenBackground.imageset │ │ │ │ ├── image.png │ │ │ │ └── Contents.json │ │ ├── noop-file.swift │ │ ├── AppDelegate.h │ │ ├── main.m │ │ ├── example.entitlements │ │ ├── Supporting │ │ │ └── Expo.plist │ │ ├── Info.plist │ │ ├── SplashScreen.storyboard │ │ └── AppDelegate.mm │ ├── example.xcworkspace │ │ └── contents.xcworkspacedata │ ├── .gitignore │ ├── Podfile │ └── example.xcodeproj │ │ └── xcshareddata │ │ └── xcschemes │ │ └── example.xcscheme ├── src │ ├── types.ts │ ├── Basic_useCollectionData.tsx │ ├── Basic_useDocumentData.tsx │ ├── Basic_useCollectionDataOnce.tsx │ ├── Basic_useDocumentDataOnce.tsx │ ├── Basic_useCollection.tsx │ ├── Basic_useCollectionOnce.tsx │ ├── Basic_useDocument.tsx │ ├── Basic_useDocumentOnce.tsx │ ├── ChangeQuery_useDocumentData.tsx │ ├── ChangeQuery_useDocumentDataOnce.tsx │ ├── ChangeQuery_useCollectionData.tsx │ └── components │ │ └── BasicScreen.tsx ├── assets │ ├── icon.png │ ├── favicon.png │ ├── splash.png │ └── adaptive-icon.png ├── .expo-shared │ └── assets.json ├── README.md ├── tsconfig.json ├── index.js ├── babel.config.js ├── app.json ├── .gitignore ├── metro.config.js ├── package.json └── App.tsx ├── .gitattributes ├── tsconfig.build.json ├── src ├── storage │ ├── index.ts │ └── useDownloadURL.ts ├── index.ts ├── util │ ├── index.ts │ ├── types.ts │ ├── refHooks.ts │ └── useLoadingValue.ts ├── database │ ├── index.ts │ ├── types.ts │ ├── helpers │ │ ├── index.ts │ │ └── useListReducer.ts │ ├── useObject.ts │ └── useList.ts ├── auth │ ├── index.ts │ ├── types.ts │ ├── useAuthState.ts │ ├── useSignInWithEmailAndPassword.ts │ └── useCreateUserWithEmailAndPassword.ts └── firestore │ ├── index.ts │ ├── helpers │ └── index.ts │ ├── useInternal.ts │ ├── useInternalOnce.ts │ ├── useCollection.ts │ ├── useDocument.ts │ └── types.ts ├── babel.config.js ├── .yarnrc ├── auth └── package.json ├── storage └── package.json ├── database └── package.json ├── firestore └── package.json ├── .editorconfig ├── tsconfig.json ├── scripts └── bootstrap.js ├── .gitignore ├── docs ├── storage.md ├── auth.md └── database.md ├── .circleci └── config.yml ├── README.md ├── package.json ├── CONTRIBUTING.md └── LICENSE /.husky/.npmignore: -------------------------------------------------------------------------------- 1 | _ 2 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values-night/colors.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/ios/Podfile.properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo.jsEngine": "jsc" 3 | } 4 | -------------------------------------------------------------------------------- /example/src/types.ts: -------------------------------------------------------------------------------- 1 | export type Product = { 2 | name: string; 3 | }; 4 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text 2 | # specific for windows script files 3 | *.bat text eol=crlf -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "extends": "./tsconfig", 4 | "exclude": ["example"] 5 | } 6 | -------------------------------------------------------------------------------- /src/storage/index.ts: -------------------------------------------------------------------------------- 1 | export { default as useDownloadURL, DownloadURLHook } from './useDownloadURL'; 2 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | yarn lint && yarn typescript 5 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:metro-react-native-babel-preset'], 3 | }; 4 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | yarn commitlint -E HUSKY_GIT_PARAMS 5 | -------------------------------------------------------------------------------- /example/assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/assets/icon.png -------------------------------------------------------------------------------- /example/assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/assets/favicon.png -------------------------------------------------------------------------------- /example/assets/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/assets/splash.png -------------------------------------------------------------------------------- /.yarnrc: -------------------------------------------------------------------------------- 1 | # Override Yarn command so we can automatically setup the repo on running `yarn` 2 | 3 | yarn-path "scripts/bootstrap.js" 4 | -------------------------------------------------------------------------------- /example/assets/adaptive-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/assets/adaptive-icon.png -------------------------------------------------------------------------------- /example/ios/example/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "expo" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './auth'; 2 | export * from './storage'; 3 | export * from './database'; 4 | export * from './firestore'; 5 | -------------------------------------------------------------------------------- /example/android/app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/android/app/debug.keystore -------------------------------------------------------------------------------- /example/ios/example/noop-file.swift: -------------------------------------------------------------------------------- 1 | // 2 | // @generated 3 | // A blank Swift file must be created for native modules with Swift files to work correctly. 4 | // 5 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/.expo-shared/assets.json: -------------------------------------------------------------------------------- 1 | { 2 | "12bb71342c6255bbf50437ec8f4441c083f47cdb74bd89160c15e4f43e52a1cb": true, 3 | "40b842e832070c58deac6aa9e08fa459302ee3f9da492c7e77d93d2fbf4a56fd": true 4 | } 5 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /src/util/index.ts: -------------------------------------------------------------------------------- 1 | export { default as useLoadingValue } from './useLoadingValue'; 2 | export * from './refHooks'; 3 | 4 | export type LoadingHook = [T | undefined, boolean, E | undefined]; 5 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/ios/example/Images.xcassets/SplashScreen.imageset/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/ios/example/Images.xcassets/SplashScreen.imageset/image.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable-hdpi/splashscreen_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/android/app/src/main/res/drawable-hdpi/splashscreen_image.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable-mdpi/splashscreen_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/android/app/src/main/res/drawable-mdpi/splashscreen_image.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable-xhdpi/splashscreen_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/android/app/src/main/res/drawable-xhdpi/splashscreen_image.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable-xxhdpi/splashscreen_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/android/app/src/main/res/drawable-xxhdpi/splashscreen_image.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/splashscreen.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable-xxxhdpi/splashscreen_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/android/app/src/main/res/drawable-xxxhdpi/splashscreen_image.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-20x20@1x.png -------------------------------------------------------------------------------- /example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-20x20@2x.png -------------------------------------------------------------------------------- /example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-20x20@3x.png -------------------------------------------------------------------------------- /example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-29x29@1x.png -------------------------------------------------------------------------------- /example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-29x29@2x.png -------------------------------------------------------------------------------- /example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-29x29@3x.png -------------------------------------------------------------------------------- /example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-40x40@1x.png -------------------------------------------------------------------------------- /example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-40x40@2x.png -------------------------------------------------------------------------------- /example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-40x40@3x.png -------------------------------------------------------------------------------- /example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-60x60@2x.png -------------------------------------------------------------------------------- /example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-60x60@3x.png -------------------------------------------------------------------------------- /example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-76x76@1x.png -------------------------------------------------------------------------------- /example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-76x76@2x.png -------------------------------------------------------------------------------- /example/ios/example/Images.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/ios/example/Images.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png -------------------------------------------------------------------------------- /auth/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-firebase-hooks/auth", 3 | "main": "../lib/commonjs/auth/index.js", 4 | "module": "../lib/module/auth/index.js", 5 | "typings": "../lib/typescript/auth/index.d.ts" 6 | } 7 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # Example app 2 | 3 | ## Running the example app 4 | 5 | You need to connect the app to a firebase project with firestore configured. 6 | For that, place your `google-services.json` and `GoogleService-` 7 | -------------------------------------------------------------------------------- /example/ios/example/Images.xcassets/SplashScreenBackground.imageset/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/ios/example/Images.xcassets/SplashScreenBackground.imageset/image.png -------------------------------------------------------------------------------- /example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannojg/react-native-firebase-hooks/HEAD/example/ios/example/Images.xcassets/AppIcon.appiconset/App-Icon-83.5x83.5@2x.png -------------------------------------------------------------------------------- /example/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "expo/tsconfig.base", 3 | "compilerOptions": { 4 | "strict": true, 5 | "paths": { 6 | "@skillnation/react-native-firebase-hooks/*": ["../src/*"] 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /storage/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-firebase-hooks/storage", 3 | "main": "../lib/commonjs/storage/index.js", 4 | "module": "../lib/module/storage/index.js", 5 | "typings": "../lib/typescript/storage/index.d.ts" 6 | } 7 | -------------------------------------------------------------------------------- /database/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-firebase-hooks/database", 3 | "main": "../lib/commonjs/database/index.js", 4 | "module": "../lib/module/database/index.js", 5 | "typings": "../lib/typescript/database/index.d.ts" 6 | } 7 | -------------------------------------------------------------------------------- /firestore/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-firebase-hooks/firestore", 3 | "main": "../lib/commonjs/firestore/index.js", 4 | "module": "../lib/module/firestore/index.js", 5 | "typings": "../lib/typescript/firestore/index.d.ts" 6 | } 7 | -------------------------------------------------------------------------------- /example/ios/example/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | 5 | #import 6 | 7 | @interface AppDelegate : EXAppDelegateWrapper 8 | 9 | @end 10 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /example/ios/example/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char * argv[]) { 6 | @autoreleasepool { 7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 8 | } 9 | } 10 | 11 | -------------------------------------------------------------------------------- /src/database/index.ts: -------------------------------------------------------------------------------- 1 | export { useList, useListKeys, useListVals } from './useList'; 2 | export { useObject, useObjectVal } from './useObject'; 3 | export { 4 | ListHook, 5 | ListKeysHook, 6 | ListValsHook, 7 | ObjectHook, 8 | ObjectValHook, 9 | } from './types'; 10 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | #ffffff 3 | #FFFFFF 4 | #023c69 5 | #ffffff 6 | -------------------------------------------------------------------------------- /example/android/.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Android/IntelliJ 6 | # 7 | build/ 8 | .idea 9 | .gradle 10 | local.properties 11 | *.iml 12 | *.hprof 13 | 14 | # BUCK 15 | buck-out/ 16 | \.buckd/ 17 | *.keystore 18 | !debug.keystore 19 | 20 | # Bundle artifacts 21 | *.jsbundle 22 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | example 3 | contain 4 | false 5 | -------------------------------------------------------------------------------- /example/ios/example/example.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | aps-environment 6 | development 7 | 8 | -------------------------------------------------------------------------------- /example/ios/example.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/auth/index.ts: -------------------------------------------------------------------------------- 1 | export { default as useAuthState, AuthStateHook } from './useAuthState'; 2 | export { default as useSignInWithEmailAndPassword } from './useSignInWithEmailAndPassword'; 3 | export { default as useCreateUserWithEmailAndPassword } from './useCreateUserWithEmailAndPassword'; 4 | 5 | export { EmailAndPasswordActionHook } from './types'; 6 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | 9 | indent_style = space 10 | indent_size = 2 11 | 12 | end_of_line = lf 13 | charset = utf-8 14 | trim_trailing_whitespace = true 15 | insert_final_newline = true 16 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/index.js: -------------------------------------------------------------------------------- 1 | import 'react-native-gesture-handler'; 2 | import { registerRootComponent } from 'expo'; 3 | 4 | import App from './App'; 5 | 6 | // registerRootComponent calls AppRegistry.registerComponent('main', () => App); 7 | // It also ensures that whether you load the app in Expo Go or in a native build, 8 | // the environment is set up appropriately 9 | registerRootComponent(App); 10 | -------------------------------------------------------------------------------- /src/util/types.ts: -------------------------------------------------------------------------------- 1 | import type { firebase } from '@react-native-firebase/auth'; 2 | import type { FirebaseAuthTypes } from '@react-native-firebase/auth'; 3 | import type { ReactNativeFirebase } from '@react-native-firebase/app'; 4 | 5 | export type FirebaseModuleAuth = typeof firebase.auth; 6 | export type AuthError = FirebaseAuthTypes.NativeFirebaseAuthError; 7 | export type FirebaseError = ReactNativeFirebase.NativeFirebaseError; 8 | -------------------------------------------------------------------------------- /src/firestore/index.ts: -------------------------------------------------------------------------------- 1 | export { 2 | useCollection, 3 | useCollectionOnce, 4 | useCollectionData, 5 | useCollectionDataOnce, 6 | } from './useCollection'; 7 | export { 8 | useDocument, 9 | useDocumentData, 10 | useDocumentOnce, 11 | useDocumentDataOnce, 12 | } from './useDocument'; 13 | export { 14 | CollectionHook, 15 | CollectionDataHook, 16 | DocumentHook, 17 | DocumentDataHook, 18 | } from './types'; 19 | -------------------------------------------------------------------------------- /example/ios/example/Images.xcassets/SplashScreen.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images": [ 3 | { 4 | "idiom": "universal", 5 | "filename": "image.png", 6 | "scale": "1x" 7 | }, 8 | { 9 | "idiom": "universal", 10 | "scale": "2x" 11 | }, 12 | { 13 | "idiom": "universal", 14 | "scale": "3x" 15 | } 16 | ], 17 | "info": { 18 | "version": 1, 19 | "author": "expo" 20 | } 21 | } -------------------------------------------------------------------------------- /example/android/app/src/main/jni/MainApplicationModuleProvider.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | namespace facebook { 9 | namespace react { 10 | 11 | std::shared_ptr MainApplicationModuleProvider( 12 | const std::string moduleName, 13 | const JavaTurboModule::InitParams ¶ms); 14 | 15 | } // namespace react 16 | } // namespace facebook 17 | -------------------------------------------------------------------------------- /example/ios/.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | project.xcworkspace 24 | 25 | # Bundle artifacts 26 | *.jsbundle 27 | 28 | # CocoaPods 29 | /Pods/ 30 | -------------------------------------------------------------------------------- /example/ios/example/Images.xcassets/SplashScreenBackground.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images": [ 3 | { 4 | "idiom": "universal", 5 | "filename": "image.png", 6 | "scale": "1x" 7 | }, 8 | { 9 | "idiom": "universal", 10 | "scale": "2x" 11 | }, 12 | { 13 | "idiom": "universal", 14 | "scale": "3x" 15 | } 16 | ], 17 | "info": { 18 | "version": 1, 19 | "author": "expo" 20 | } 21 | } -------------------------------------------------------------------------------- /example/android/app/src/main/jni/OnLoad.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "MainApplicationTurboModuleManagerDelegate.h" 3 | #include "MainComponentsRegistry.h" 4 | 5 | JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) { 6 | return facebook::jni::initialize(vm, [] { 7 | facebook::react::MainApplicationTurboModuleManagerDelegate:: 8 | registerNatives(); 9 | facebook::react::MainComponentsRegistry::registerNatives(); 10 | }); 11 | } 12 | -------------------------------------------------------------------------------- /example/src/Basic_useCollectionData.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { useCollectionData } from '@skillnation/react-native-firebase-hooks/firestore'; 3 | import { Product } from './types'; 4 | import { BasicScreen } from './components/BasicScreen'; 5 | import firestore from '@react-native-firebase/firestore'; 6 | 7 | export const Basic_useCollectionData: React.FC = () => { 8 | const hookData = useCollectionData( 9 | firestore().collection('products') 10 | ); 11 | 12 | return ; 13 | }; 14 | -------------------------------------------------------------------------------- /example/src/Basic_useDocumentData.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { useDocumentData } from '@skillnation/react-native-firebase-hooks/firestore'; 3 | import { Product } from './types'; 4 | import { BasicScreen } from './components/BasicScreen'; 5 | import firestore from '@react-native-firebase/firestore'; 6 | 7 | export const Basic_useDocumentData: React.FC = () => { 8 | const hookData = useDocumentData( 9 | firestore().collection('products').doc('productA') 10 | ); 11 | 12 | return ; 13 | }; 14 | -------------------------------------------------------------------------------- /example/babel.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const pak = require('../package.json'); 3 | 4 | module.exports = function (api) { 5 | api.cache(true); 6 | return { 7 | presets: ['babel-preset-expo'], 8 | plugins: [ 9 | [ 10 | 'module-resolver', 11 | { 12 | extensions: ['.tsx', '.ts', '.js', '.json'], 13 | alias: { 14 | [pak.name]: path.join(__dirname, '..', pak.source), 15 | }, 16 | }, 17 | ], 18 | 'react-native-reanimated/plugin', 19 | ], 20 | }; 21 | }; 22 | -------------------------------------------------------------------------------- /src/auth/types.ts: -------------------------------------------------------------------------------- 1 | import type { FirebaseAuthTypes } from '@react-native-firebase/auth'; 2 | 3 | export type AuthActionHook = [ 4 | (email: string, password: string) => Promise, 5 | T | undefined, 6 | boolean, 7 | E | undefined 8 | ]; 9 | export type CreateUserOptions = { 10 | emailVerificationOptions?: FirebaseAuthTypes.ActionCodeSettings; 11 | sendEmailVerification?: boolean; 12 | }; 13 | export type EmailAndPasswordActionHook = AuthActionHook< 14 | FirebaseAuthTypes.UserCredential, 15 | FirebaseAuthTypes.NativeFirebaseAuthError 16 | >; 17 | -------------------------------------------------------------------------------- /example/src/Basic_useCollectionDataOnce.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import type { Product } from './types'; 3 | import { BasicScreen } from './components/BasicScreen'; 4 | import firestore from '@react-native-firebase/firestore'; 5 | import { useCollectionDataOnce } from '@skillnation/react-native-firebase-hooks/firestore'; 6 | 7 | export const Basic_useCollectionDataOnce: React.FC = () => { 8 | const hookData = useCollectionDataOnce( 9 | firestore().collection('products') 10 | ); 11 | 12 | return ; 13 | }; 14 | -------------------------------------------------------------------------------- /example/src/Basic_useDocumentDataOnce.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { useDocumentDataOnce } from '@skillnation/react-native-firebase-hooks/firestore'; 3 | import type { Product } from './types'; 4 | import { BasicScreen } from './components/BasicScreen'; 5 | import firestore from '@react-native-firebase/firestore'; 6 | 7 | export const Basic_useDocumentDataOnce: React.FC = () => { 8 | const hookData = useDocumentDataOnce( 9 | firestore().collection('products').doc('productA') 10 | ); 11 | 12 | return ; 13 | }; 14 | -------------------------------------------------------------------------------- /example/ios/example/Supporting/Expo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | EXUpdatesCheckOnLaunch 6 | ALWAYS 7 | EXUpdatesEnabled 8 | 9 | EXUpdatesLaunchWaitMs 10 | 0 11 | EXUpdatesSDKVersion 12 | 45.0.0 13 | EXUpdatesURL 14 | https://exp.host/@skillnation/example 15 | 16 | -------------------------------------------------------------------------------- /example/android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # react-native-reanimated 11 | -keep class com.swmansion.reanimated.** { *; } 12 | -keep class com.facebook.react.turbomodule.** { *; } 13 | 14 | # Add any project specific keep options here: 15 | -------------------------------------------------------------------------------- /example/src/Basic_useCollection.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { useCollection } from '@skillnation/react-native-firebase-hooks/firestore'; 3 | import { Product } from './types'; 4 | import { BasicScreen } from './components/BasicScreen'; 5 | import firestore from '@react-native-firebase/firestore'; 6 | 7 | export const Basic_useCollection: React.FC = () => { 8 | const hookData = useCollection(firestore().collection('products')); 9 | 10 | return ( 11 | ({ 14 | size: d.size, 15 | empty: d.empty, 16 | })} 17 | /> 18 | ); 19 | }; 20 | -------------------------------------------------------------------------------- /example/src/Basic_useCollectionOnce.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import type { Product } from './types'; 3 | import { BasicScreen } from './components/BasicScreen'; 4 | import firestore from '@react-native-firebase/firestore'; 5 | import { useCollectionOnce } from '@skillnation/react-native-firebase-hooks/firestore'; 6 | 7 | export const Basic_useCollectionOnce: React.FC = () => { 8 | const hookData = useCollectionOnce( 9 | firestore().collection('products') 10 | ); 11 | 12 | return ( 13 | ({ 16 | size: d.size, 17 | empty: d.empty, 18 | })} 19 | /> 20 | ); 21 | }; 22 | -------------------------------------------------------------------------------- /example/android/app/build_defs.bzl: -------------------------------------------------------------------------------- 1 | """Helper definitions to glob .aar and .jar targets""" 2 | 3 | def create_aar_targets(aarfiles): 4 | for aarfile in aarfiles: 5 | name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")] 6 | lib_deps.append(":" + name) 7 | android_prebuilt_aar( 8 | name = name, 9 | aar = aarfile, 10 | ) 11 | 12 | def create_jar_targets(jarfiles): 13 | for jarfile in jarfiles: 14 | name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")] 15 | lib_deps.append(":" + name) 16 | prebuilt_jar( 17 | name = name, 18 | binary_jar = jarfile, 19 | ) 20 | -------------------------------------------------------------------------------- /example/src/Basic_useDocument.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { useDocument } from '@skillnation/react-native-firebase-hooks/firestore'; 3 | import { Product } from './types'; 4 | import { BasicScreen } from './components/BasicScreen'; 5 | import firestore from '@react-native-firebase/firestore'; 6 | 7 | export const Basic_useDocument: React.FC = () => { 8 | const hookData = useDocument( 9 | firestore().collection('products').doc('productA') 10 | ); 11 | 12 | return ( 13 | ({ 16 | ...d.data(), 17 | id: d.id, 18 | path: d.ref.path, 19 | })} 20 | /> 21 | ); 22 | }; 23 | -------------------------------------------------------------------------------- /example/src/Basic_useDocumentOnce.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { useDocumentOnce } from '@skillnation/react-native-firebase-hooks/firestore'; 3 | import { Product } from './types'; 4 | import { BasicScreen } from './components/BasicScreen'; 5 | import firestore from '@react-native-firebase/firestore'; 6 | 7 | export const Basic_useDocumentOnce: React.FC = () => { 8 | const hookData = useDocumentOnce( 9 | firestore().collection('products').doc('productA') 10 | ); 11 | 12 | return ( 13 | ({ 16 | ...d.data(), 17 | id: d.id, 18 | path: d.ref.path, 19 | })} 20 | /> 21 | ); 22 | }; 23 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": "./", 4 | "allowUnreachableCode": false, 5 | "allowUnusedLabels": false, 6 | "esModuleInterop": true, 7 | "importsNotUsedAsValues": "error", 8 | "forceConsistentCasingInFileNames": true, 9 | "jsx": "react", 10 | "lib": ["esnext"], 11 | "module": "esnext", 12 | "moduleResolution": "node", 13 | "noFallthroughCasesInSwitch": true, 14 | "noImplicitReturns": true, 15 | "noImplicitUseStrict": false, 16 | "noStrictGenericChecks": false, 17 | "noUnusedLocals": true, 18 | "noUnusedParameters": true, 19 | "resolveJsonModule": true, 20 | "skipLibCheck": true, 21 | "strict": true, 22 | "target": "esnext" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/auth/useAuthState.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useMemo } from 'react'; 2 | import { LoadingHook, useLoadingValue } from '../util'; 3 | import type { FirebaseAuthTypes } from '@react-native-firebase/auth'; 4 | import type { FirebaseModuleAuth } from '../util/types'; 5 | 6 | export type AuthStateHook = LoadingHook; 7 | 8 | export default (auth: FirebaseModuleAuth): AuthStateHook => { 9 | const { error, loading, setValue, value } = useLoadingValue< 10 | FirebaseAuthTypes.User | null, 11 | Error 12 | >(() => auth().currentUser); 13 | 14 | useEffect(() => { 15 | return auth().onAuthStateChanged({ 16 | next: setValue, 17 | }); 18 | }, [auth, setValue]); 19 | 20 | return useMemo( 21 | () => [value, loading, error], 22 | [error, loading, value] 23 | ); 24 | }; 25 | -------------------------------------------------------------------------------- /example/src/ChangeQuery_useDocumentData.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Button } from 'react-native'; 3 | import { useDocumentData } from '@skillnation/react-native-firebase-hooks/firestore'; 4 | import firestore from '@react-native-firebase/firestore'; 5 | import type { Product } from './types'; 6 | import { BasicScreen } from './components/BasicScreen'; 7 | 8 | export const ChangeQuery_useDocumentData = () => { 9 | const [documentPath, setDocumentPath] = React.useState('invalid/doc'); 10 | 11 | const hookData = useDocumentData(firestore().doc(documentPath), { 12 | snapshotListenOptions: { includeMetadataChanges: true }, 13 | }); 14 | 15 | return ( 16 | 17 | 74 | 75 | ); 76 | } 77 | return ; 78 | }; 79 | ``` 80 | 81 | ### useCreateUserWithEmailAndPassword 82 | 83 | ```js 84 | const [ 85 | createUserWithEmailAndPassword, 86 | user, 87 | loading, 88 | error, 89 | ] = useCreateUserWithEmailAndPassword(auth); 90 | ``` 91 | 92 | Create a user with email and password. Wraps the underlying `firebase.auth().createUserWithEmailAndPassword` method and provides additional `loading` and `error` information. 93 | 94 | The `useCreateUserWithEmailAndPassword` hook takes the following parameters: 95 | 96 | - `auth`: `auth.Auth` instance for the app you would like to monitor 97 | - `options`: (optional) `Object` with the following parameters: 98 | - `emailVerificationOptions`: (optional) `auth.ActionCodeSettings` to customise the email verification 99 | - `sendEmailVerification`: (optional) `boolean` to trigger sending of an email verification after the user has been created 100 | 101 | Returns: 102 | 103 | - `createUserWithEmailAndPassword(email: string, password: string)`: a function you can call to start the registration 104 | - `user`: The `User` if the user was created or `undefined` if not 105 | - `loading`: A `boolean` to indicate whether the the user creation is processing 106 | - `error`: Any `Error` returned by Firebase when trying to create the user, or `undefined` if there is no error 107 | 108 | #### Full Example 109 | 110 | ```jsx 111 | import { useCreateUserWithEmailAndPassword } from 'react-firebase-hooks/auth'; 112 | 113 | const SignIn = () => { 114 | const [email, setEmail] = useState(''); 115 | const [password, setPassword] = useState(''); 116 | const [ 117 | createUserWithEmailAndPassword, 118 | user, 119 | loading, 120 | error, 121 | ] = useCreateUserWithEmailAndPassword(auth); 122 | 123 | if (error) { 124 | return ( 125 |
126 |

Error: {error.message}

127 |
128 | ); 129 | } 130 | if (loading) { 131 | return

Loading...

; 132 | } 133 | if (user) { 134 | return ( 135 |
136 |

Registered User: {user.email}

137 |
138 | ); 139 | } 140 | return ( 141 |
142 | setEmail(e.target.value)} 146 | /> 147 | setPassword(e.target.value)} 151 | /> 152 | 155 |
156 | ); 157 | }; 158 | ``` 159 | 160 | ### useSignInWithEmailAndPassword 161 | 162 | ```js 163 | const [ 164 | signInWithEmailAndPassword, 165 | user, 166 | loading, 167 | error, 168 | ] = useSignInWithEmailAndPassword(auth); 169 | ``` 170 | 171 | Login a user with email and password. Wraps the underlying `auth.signInWithEmailAndPassword` method and provides additional `loading` and `error` information. 172 | 173 | The `useSignInWithEmailAndPassword` hook takes the following parameters: 174 | 175 | - `auth`: `Auth` instance for the app you would like to monitor 176 | 177 | Returns: 178 | 179 | - `signInWithEmailAndPassword(email: string, password: string)`: a function you can call to start the login 180 | - `user`: The `auth.User` if the user was logged in or `undefined` if not 181 | - `loading`: A `boolean` to indicate whether the the user login is processing 182 | - `error`: Any `Error` returned by Firebase when trying to login the user, or `undefined` if there is no error 183 | 184 | #### Full Example 185 | 186 | ```jsx 187 | import { useSignInWithEmailAndPassword } from 'react-firebase-hooks/auth'; 188 | 189 | const SignIn = () => { 190 | const [email, setEmail] = useState(''); 191 | const [password, setPassword] = useState(''); 192 | const [ 193 | signInWithEmailAndPassword, 194 | user, 195 | loading, 196 | error, 197 | ] = useSignInWithEmailAndPassword(auth); 198 | 199 | if (error) { 200 | return ( 201 |
202 |

Error: {error.message}

203 |
204 | ); 205 | } 206 | if (loading) { 207 | return

Loading...

; 208 | } 209 | if (user) { 210 | return ( 211 |
212 |

Signed In User: {user.email}

213 |
214 | ); 215 | } 216 | return ( 217 |
218 | setEmail(e.target.value)} 222 | /> 223 | setPassword(e.target.value)} 227 | /> 228 | 231 |
232 | ); 233 | }; 234 | ``` 235 | -------------------------------------------------------------------------------- /example/android/gradlew: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Copyright © 2015-2021 the original authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | # 21 | # Gradle start up script for POSIX generated by Gradle. 22 | # 23 | # Important for running: 24 | # 25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is 26 | # noncompliant, but you have some other compliant shell such as ksh or 27 | # bash, then to run this script, type that shell name before the whole 28 | # command line, like: 29 | # 30 | # ksh Gradle 31 | # 32 | # Busybox and similar reduced shells will NOT work, because this script 33 | # requires all of these POSIX shell features: 34 | # * functions; 35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», 36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»; 37 | # * compound commands having a testable exit status, especially «case»; 38 | # * various built-in commands including «command», «set», and «ulimit». 39 | # 40 | # Important for patching: 41 | # 42 | # (2) This script targets any POSIX shell, so it avoids extensions provided 43 | # by Bash, Ksh, etc; in particular arrays are avoided. 44 | # 45 | # The "traditional" practice of packing multiple parameters into a 46 | # space-separated string is a well documented source of bugs and security 47 | # problems, so this is (mostly) avoided, by progressively accumulating 48 | # options in "$@", and eventually passing that to Java. 49 | # 50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, 51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; 52 | # see the in-line comments for details. 53 | # 54 | # There are tweaks for specific operating systems such as AIX, CygWin, 55 | # Darwin, MinGW, and NonStop. 56 | # 57 | # (3) This script is generated from the Groovy template 58 | # https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt 59 | # within the Gradle project. 60 | # 61 | # You can find Gradle at https://github.com/gradle/gradle/. 62 | # 63 | ############################################################################## 64 | 65 | # Attempt to set APP_HOME 66 | 67 | # Resolve links: $0 may be a link 68 | app_path=$0 69 | 70 | # Need this for daisy-chained symlinks. 71 | while 72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path 73 | [ -h "$app_path" ] 74 | do 75 | ls=$( ls -ld "$app_path" ) 76 | link=${ls#*' -> '} 77 | case $link in #( 78 | /*) app_path=$link ;; #( 79 | *) app_path=$APP_HOME$link ;; 80 | esac 81 | done 82 | 83 | APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit 84 | 85 | APP_NAME="Gradle" 86 | APP_BASE_NAME=${0##*/} 87 | 88 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 89 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 90 | 91 | # Use the maximum available, or set MAX_FD != -1 to use that value. 92 | MAX_FD=maximum 93 | 94 | warn () { 95 | echo "$*" 96 | } >&2 97 | 98 | die () { 99 | echo 100 | echo "$*" 101 | echo 102 | exit 1 103 | } >&2 104 | 105 | # OS specific support (must be 'true' or 'false'). 106 | cygwin=false 107 | msys=false 108 | darwin=false 109 | nonstop=false 110 | case "$( uname )" in #( 111 | CYGWIN* ) cygwin=true ;; #( 112 | Darwin* ) darwin=true ;; #( 113 | MSYS* | MINGW* ) msys=true ;; #( 114 | NONSTOP* ) nonstop=true ;; 115 | esac 116 | 117 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 118 | 119 | 120 | # Determine the Java command to use to start the JVM. 121 | if [ -n "$JAVA_HOME" ] ; then 122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 123 | # IBM's JDK on AIX uses strange locations for the executables 124 | JAVACMD=$JAVA_HOME/jre/sh/java 125 | else 126 | JAVACMD=$JAVA_HOME/bin/java 127 | fi 128 | if [ ! -x "$JAVACMD" ] ; then 129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 130 | 131 | Please set the JAVA_HOME variable in your environment to match the 132 | location of your Java installation." 133 | fi 134 | else 135 | JAVACMD=java 136 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 137 | 138 | Please set the JAVA_HOME variable in your environment to match the 139 | location of your Java installation." 140 | fi 141 | 142 | # Increase the maximum file descriptors if we can. 143 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then 144 | case $MAX_FD in #( 145 | max*) 146 | MAX_FD=$( ulimit -H -n ) || 147 | warn "Could not query maximum file descriptor limit" 148 | esac 149 | case $MAX_FD in #( 150 | '' | soft) :;; #( 151 | *) 152 | ulimit -n "$MAX_FD" || 153 | warn "Could not set maximum file descriptor limit to $MAX_FD" 154 | esac 155 | fi 156 | 157 | # Collect all arguments for the java command, stacking in reverse order: 158 | # * args from the command line 159 | # * the main class name 160 | # * -classpath 161 | # * -D...appname settings 162 | # * --module-path (only if needed) 163 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. 164 | 165 | # For Cygwin or MSYS, switch paths to Windows format before running java 166 | if "$cygwin" || "$msys" ; then 167 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) 168 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) 169 | 170 | JAVACMD=$( cygpath --unix "$JAVACMD" ) 171 | 172 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 173 | for arg do 174 | if 175 | case $arg in #( 176 | -*) false ;; # don't mess with options #( 177 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath 178 | [ -e "$t" ] ;; #( 179 | *) false ;; 180 | esac 181 | then 182 | arg=$( cygpath --path --ignore --mixed "$arg" ) 183 | fi 184 | # Roll the args list around exactly as many times as the number of 185 | # args, so each arg winds up back in the position where it started, but 186 | # possibly modified. 187 | # 188 | # NB: a `for` loop captures its iteration list before it begins, so 189 | # changing the positional parameters here affects neither the number of 190 | # iterations, nor the values presented in `arg`. 191 | shift # remove old arg 192 | set -- "$@" "$arg" # push replacement arg 193 | done 194 | fi 195 | 196 | # Collect all arguments for the java command; 197 | # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of 198 | # shell script including quotes and variable substitutions, so put them in 199 | # double quotes to make sure that they get re-expanded; and 200 | # * put everything else in single quotes, so that it's not re-expanded. 201 | 202 | set -- \ 203 | "-Dorg.gradle.appname=$APP_BASE_NAME" \ 204 | -classpath "$CLASSPATH" \ 205 | org.gradle.wrapper.GradleWrapperMain \ 206 | "$@" 207 | 208 | # Use "xargs" to parse quoted args. 209 | # 210 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. 211 | # 212 | # In Bash we could simply go: 213 | # 214 | # readarray ARGS < <( xargs -n1 <<<"$var" ) && 215 | # set -- "${ARGS[@]}" "$@" 216 | # 217 | # but POSIX shell has neither arrays nor command substitution, so instead we 218 | # post-process each arg (as a line of input to sed) to backslash-escape any 219 | # character that might be a shell metacharacter, then use eval to reverse 220 | # that process (while maintaining the separation between arguments), and wrap 221 | # the whole thing up as a single "set" statement. 222 | # 223 | # This will of course break if any of these variables contains a newline or 224 | # an unmatched quote. 225 | # 226 | 227 | eval "set -- $( 228 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | 229 | xargs -n1 | 230 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | 231 | tr '\n' ' ' 232 | )" '"$@"' 233 | 234 | exec "$JAVACMD" "$@" 235 | -------------------------------------------------------------------------------- /docs/database.md: -------------------------------------------------------------------------------- 1 | # React Firebase Hooks - Realtime Database 2 | 3 | React Firebase Hooks provides convenience listeners for lists and values stored within the 4 | Firebase Realtime Database. The hooks wrap around the `onX(...)` method. 5 | 6 | In addition to returning the list or value, the hooks provide an `error` and `loading` property 7 | to give a complete lifecycle for loading and listening to the Realtime Database. 8 | 9 | All hooks can be imported from `react-firebase-hooks/database`, e.g. 10 | 11 | ```js 12 | import { useList } from 'react-firebase-hooks/database'; 13 | ``` 14 | 15 | List of Realtime Database hooks: 16 | 17 | - [React Firebase Hooks - Realtime Database](#react-firebase-hooks---realtime-database) 18 | - [useList](#uselist) 19 | - [Full Example](#full-example) 20 | - [useListKeys](#uselistkeys) 21 | - [useListVals](#uselistvals) 22 | - [useObject](#useobject) 23 | - [Full Example](#full-example-1) 24 | - [useObjectVal](#useobjectval) 25 | - [Transforming data](#transforming-data) 26 | - [Full Example](#full-example-2) 27 | 28 | Additional functionality: 29 | 30 | - [Transforming data](#transforming-data) 31 | 32 | ### useList 33 | 34 | ```js 35 | const [snapshots, loading, error] = useList(reference); 36 | ``` 37 | 38 | Retrieve and monitor a list value in the Firebase Realtime Database. 39 | 40 | The `useList` hook takes the following parameters: 41 | 42 | - `reference`: (optional) `database.Reference` for the data you would like to load 43 | 44 | Returns: 45 | 46 | - `snapshots`: an array of `database.DataSnapshot`, or `undefined` if no reference is supplied 47 | - `loading`: a `boolean` to indicate if the data is still being loaded 48 | - `error`: Any `Error` returned by Firebase when trying to load the data, or `undefined` if there is no error 49 | 50 | #### Full Example 51 | 52 | ```js 53 | import { ref, getDatabase } from 'firebase/database'; 54 | import { useList } from 'react-firebase-hooks/database'; 55 | 56 | const database = getDatabase(firebaseApp); 57 | 58 | const DatabaseList = () => { 59 | const [snapshots, loading, error] = useList(ref(database, 'list')); 60 | 61 | return ( 62 |
63 |

64 | {error && Error: {error}} 65 | {loading && List: Loading...} 66 | {!loading && snapshots && ( 67 | 68 | 69 | List:{' '} 70 | {snapshots.map((v) => ( 71 | {v.val()}, 72 | ))} 73 | 74 | 75 | )} 76 |

77 |
78 | ); 79 | }; 80 | ``` 81 | 82 | ### useListKeys 83 | 84 | ```js 85 | const [keys, loading, error] = useListKeys(reference); 86 | ``` 87 | 88 | As `useList`, but this hooks extracts the `database.DataSnapshot.key` values, rather than the the `database.DataSnapshot`s themselves. 89 | 90 | The `useListKeys` hook takes the following parameters: 91 | 92 | - `reference`: (optional) `database.Reference` for the data you would like to load 93 | 94 | Returns: 95 | 96 | - `keys`: an array of `string`, or `undefined` if no reference is supplied 97 | - `loading`: a `boolean` to indicate if the data is still being loaded 98 | - `error`: Any `Error` returned by Firebase when trying to load the data, or `undefined` if there is no error 99 | 100 | ### useListVals 101 | 102 | ```js 103 | const [values, loading, error] = useListVals (reference, options); 104 | ``` 105 | 106 | As `useList`, but this hook extracts a typed list of the `database.DataSnapshot.val()` values, rather than the the 107 | `database.DataSnapshot`s themselves. 108 | 109 | The `useListVals` hook takes the following parameters: 110 | 111 | - `reference`: (optional) `database.Reference` for the data you would like to load 112 | - `options`: (optional) `Object` with the following parameters: 113 | - `keyField`: (optional) `string` field name that should be populated with the `database.DataSnapshot.id` property in the returned values. 114 | - `refField`: (optional) `string` field name that should be populated with the `database.DataSnapshot.ref` property. 115 | - `transform`: (optional) a function that receives the raw `database.DataSnapshot.val()` for each item in the list to allow manual transformation of the data where required by the application. See [`Transforming data`](#transforming-data) below. 116 | 117 | Returns: 118 | 119 | - `values`: an array of `T`, or `undefined` if no reference is supplied 120 | - `loading`: a `boolean` to indicate if the data is still being loaded 121 | - `error`: Any `Error` returned by Firebase when trying to load the data, or `undefined` if there is no error 122 | 123 | ### useObject 124 | 125 | ```js 126 | const [snapshot, loading, error] = useObject(reference); 127 | ``` 128 | 129 | Retrieve and monitor an object or primitive value in the Firebase Realtime Database. 130 | 131 | The `useObject` hook takes the following parameters: 132 | 133 | - `reference`: (optional) `database.Reference` for the data you would like to load 134 | 135 | Returns: 136 | 137 | - `snapshot`: a `database.DataSnapshot`, or `undefined` if no reference is supplied 138 | - `loading`: a `boolean` to indicate if the data is still being loaded 139 | - `error`: Any `Error` returned by Firebase when trying to load the data, or `undefined` if there is no error 140 | 141 | #### Full Example 142 | 143 | ```js 144 | import { ref, getDatabase } from 'firebase/database'; 145 | import { useObject } from 'react-firebase-hooks/database'; 146 | 147 | const database = getDatabase(firebaseApp); 148 | 149 | const DatabaseValue = () => { 150 | const [snapshot, loading, error] = useObject(ref(database, 'value')); 151 | 152 | return ( 153 |
154 |

155 | {error && Error: {error}} 156 | {loading && Value: Loading...} 157 | {snapshot && Value: {snapshot.val()}} 158 |

159 |
160 | ); 161 | }; 162 | ``` 163 | 164 | ### useObjectVal 165 | 166 | ```js 167 | const [value, loading, error] = useObjectVal (reference, options); 168 | ``` 169 | 170 | As `useObject`, but this hook returns the typed contents of `database.DataSnapshot.val()`, rather than the the 171 | `database.DataSnapshot` itself. 172 | 173 | The `useObjectVal` hook takes the following parameters: 174 | 175 | - `reference`: (optional) `database.Reference` for the data you would like to load 176 | - `options`: (optional) `Object` with the following parameters: 177 | - `keyField`: (optional) `string` field name that should be populated with the `database.DataSnapshot.key` property in the returned value. 178 | - `refField`: (optional) `string` field name that should be populated with the `database.DataSnapshot.ref` property. 179 | - `transform`: (optional) a function that receives the raw `database.DataSnapshot.val()` to allow manual transformation of the data where required by the application. See [`Transforming data`](#transforming-data) below. 180 | 181 | Returns: 182 | 183 | - `value`: a `T`, or `undefined` if no reference is supplied 184 | - `loading`: a `boolean` to indicate if the data is still being loaded 185 | - `error`: Any `FirebaseError` returned by Firebase when trying to load the data, or `undefined` if there is no error 186 | 187 | ## Transforming data 188 | 189 | Firebase allows a restricted number of data types in the Realtime Database, which may not be flexible enough for your application. Both `useListVals` and `useObjectVal` support an optional `transform` function which allows the transformation of the underlying Firebase data into whatever format the application require, e.g. a `Date` type. 190 | 191 | ```js 192 | transform?: (val: any) => T; 193 | ``` 194 | 195 | The `transform` function is passed a single row of a data, so will be called once when used with `useObjectVal` and multiple times, when used with `useListVals`. 196 | 197 | The `transform` function will not receive the `key` or `ref` values referenced in the properties named in the `keyField` or `refField` options, nor it is expected to produce them. Either or both, if specified, will be merged afterwards. 198 | 199 | If the `transform` function is defined within your React component, it is recomended that you memoize the function to prevent unnecessry renders. 200 | 201 | #### Full Example 202 | 203 | ```js 204 | type SaleType = { 205 | idSale: string, 206 | date: Date, // <== it is declared as type Date which Firebase does not support. 207 | // ...Other fields 208 | }; 209 | const options = { 210 | keyField: 'idSale', 211 | transform: (val) => ({ 212 | ...val, 213 | date: new Date(val.date), 214 | }), 215 | }; 216 | export const useSale: ( 217 | idSale: string 218 | ) => [SaleType | undefined, boolean, any] = (idSale) => 219 | useObjectVal < SaleType > (database.ref(`sales/${idSale}`), options); 220 | export const useSales: () => [SaleType[] | undefined, boolean, any] = () => 221 | useListVals < SaleType > (database.ref('sales'), options); 222 | ``` 223 | 224 | The `transform` function might be used for various purposes: 225 | 226 | ```js 227 | transform: ({ firstName, lastName, someBool, ...val }) => ({ 228 | // Merge in default values, declared elsewhere: 229 | ...defaultValues, 230 | // Override them with the actual values 231 | ...val, 232 | // Create new fields from existing values 233 | fullName: `${firstName} ${lastName}`, 234 | // Ensure a field is a proper boolean instead of truish or falsy: 235 | someBool: !!someBool, 236 | // Same goes for any other poorly represented data type 237 | }); 238 | ``` 239 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | We want this community to be friendly and respectful to each other. Please follow it in all your interactions with the project. 4 | 5 | ## Development workflow 6 | 7 | To get started with the project, run `yarn` in the root directory to install the required dependencies for each package: 8 | 9 | ```sh 10 | yarn 11 | ``` 12 | 13 | > While it's possible to use [`npm`](https://github.com/npm/cli), the tooling is built around [`yarn`](https://classic.yarnpkg.com/), so you'll have an easier time if you use `yarn` for development. 14 | 15 | While developing, you can run the [example app](/example/) to test your changes. Any changes you make in your library's JavaScript code will be reflected in the example app without a rebuild. If you change any native code, then you'll need to rebuild the example app. 16 | 17 | To start the packager: 18 | 19 | ```sh 20 | yarn example start 21 | ``` 22 | 23 | To run the example app on Android: 24 | 25 | ```sh 26 | yarn example android 27 | ``` 28 | 29 | To run the example app on iOS: 30 | 31 | ```sh 32 | yarn example ios 33 | ``` 34 | 35 | To run the example app on Web: 36 | 37 | ```sh 38 | yarn example web 39 | ``` 40 | 41 | Make sure your code passes TypeScript and ESLint. Run the following to verify: 42 | 43 | ```sh 44 | yarn typescript 45 | yarn lint 46 | ``` 47 | 48 | To fix formatting errors, run the following: 49 | 50 | ```sh 51 | yarn lint --fix 52 | ``` 53 | 54 | Remember to add tests for your change if possible. Run the unit tests by: 55 | 56 | ```sh 57 | yarn test 58 | ``` 59 | 60 | ### Commit message convention 61 | 62 | We follow the [conventional commits specification](https://www.conventionalcommits.org/en) for our commit messages: 63 | 64 | - `fix`: bug fixes, e.g. fix crash due to deprecated method. 65 | - `feat`: new features, e.g. add new method to the module. 66 | - `refactor`: code refactor, e.g. migrate from class components to hooks. 67 | - `docs`: changes into documentation, e.g. add usage example for the module.. 68 | - `test`: adding or updating tests, e.g. add integration tests using detox. 69 | - `chore`: tooling changes, e.g. change CI config. 70 | 71 | Our pre-commit hooks verify that your commit message matches this format when committing. 72 | 73 | ### Linting and tests 74 | 75 | [ESLint](https://eslint.org/), [Prettier](https://prettier.io/), [TypeScript](https://www.typescriptlang.org/) 76 | 77 | We use [TypeScript](https://www.typescriptlang.org/) for type checking, [ESLint](https://eslint.org/) with [Prettier](https://prettier.io/) for linting and formatting the code, and [Jest](https://jestjs.io/) for testing. 78 | 79 | Our pre-commit hooks verify that the linter and tests pass when committing. 80 | 81 | ### Publishing to npm 82 | 83 | We use [release-it](https://github.com/release-it/release-it) to make it easier to publish new versions. It handles common tasks like bumping version based on semver, creating tags and releases etc. 84 | 85 | To publish new versions, run the following: 86 | 87 | ```sh 88 | yarn release 89 | ``` 90 | 91 | ### Scripts 92 | 93 | The `package.json` file contains various scripts for common tasks: 94 | 95 | - `yarn bootstrap`: setup project by installing all dependencies and pods. 96 | - `yarn typescript`: type-check files with TypeScript. 97 | - `yarn lint`: lint files with ESLint. 98 | - `yarn test`: run unit tests with Jest. 99 | - `yarn example start`: start the Metro server for the example app. 100 | - `yarn example android`: run the example app on Android. 101 | - `yarn example ios`: run the example app on iOS. 102 | 103 | ### Sending a pull request 104 | 105 | > **Working on your first pull request?** You can learn how from this _free_ series: [How to Contribute to an Open Source Project on GitHub](https://app.egghead.io/playlists/how-to-contribute-to-an-open-source-project-on-github). 106 | 107 | When you're sending a pull request: 108 | 109 | - Prefer small pull requests focused on one change. 110 | - Verify that linters and tests are passing. 111 | - Review the documentation to make sure it looks good. 112 | - Follow the pull request template when opening a pull request. 113 | - For pull requests that change the API or implementation, discuss with maintainers first by opening an issue. 114 | 115 | ## Code of Conduct 116 | 117 | ### Our Pledge 118 | 119 | We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. 120 | 121 | We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. 122 | 123 | ### Our Standards 124 | 125 | Examples of behavior that contributes to a positive environment for our community include: 126 | 127 | - Demonstrating empathy and kindness toward other people 128 | - Being respectful of differing opinions, viewpoints, and experiences 129 | - Giving and gracefully accepting constructive feedback 130 | - Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience 131 | - Focusing on what is best not just for us as individuals, but for the overall community 132 | 133 | Examples of unacceptable behavior include: 134 | 135 | - The use of sexualized language or imagery, and sexual attention or 136 | advances of any kind 137 | - Trolling, insulting or derogatory comments, and personal or political attacks 138 | - Public or private harassment 139 | - Publishing others' private information, such as a physical or email 140 | address, without their explicit permission 141 | - Other conduct which could reasonably be considered inappropriate in a 142 | professional setting 143 | 144 | ### Enforcement Responsibilities 145 | 146 | Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful. 147 | 148 | Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate. 149 | 150 | ### Scope 151 | 152 | This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. 153 | 154 | ### Enforcement 155 | 156 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at [INSERT CONTACT METHOD]. All complaints will be reviewed and investigated promptly and fairly. 157 | 158 | All community leaders are obligated to respect the privacy and security of the reporter of any incident. 159 | 160 | ### Enforcement Guidelines 161 | 162 | Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct: 163 | 164 | #### 1. Correction 165 | 166 | **Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community. 167 | 168 | **Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested. 169 | 170 | #### 2. Warning 171 | 172 | **Community Impact**: A violation through a single incident or series of actions. 173 | 174 | **Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban. 175 | 176 | #### 3. Temporary Ban 177 | 178 | **Community Impact**: A serious violation of community standards, including sustained inappropriate behavior. 179 | 180 | **Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban. 181 | 182 | #### 4. Permanent Ban 183 | 184 | **Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. 185 | 186 | **Consequence**: A permanent ban from any sort of public interaction within the community. 187 | 188 | ### Attribution 189 | 190 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0, 191 | available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 192 | 193 | Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity). 194 | 195 | [homepage]: https://www.contributor-covenant.org 196 | 197 | For answers to common questions about this code of conduct, see the FAQ at 198 | https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations. 199 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright 2021 SkillNation B.V. 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | --------------------------------------------------------------------------------