ignite-parse-auth-kit 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTRIBUTING.md +0 -0
- package/LICENSE +21 -0
- package/README.md +492 -0
- package/app/app.tsx +116 -0
- package/app/components/AlertTongle.tsx +105 -0
- package/app/components/AutoImage.tsx +89 -0
- package/app/components/Button.tsx +248 -0
- package/app/components/Card.tsx +314 -0
- package/app/components/EmptyState.tsx +248 -0
- package/app/components/Header.tsx +332 -0
- package/app/components/Icon.tsx +140 -0
- package/app/components/ListItem.tsx +243 -0
- package/app/components/ListView.tsx +42 -0
- package/app/components/Screen.tsx +305 -0
- package/app/components/Text.test.tsx +23 -0
- package/app/components/Text.tsx +116 -0
- package/app/components/TextField.tsx +292 -0
- package/app/components/Toggle/Checkbox.tsx +123 -0
- package/app/components/Toggle/Radio.tsx +106 -0
- package/app/components/Toggle/Switch.tsx +264 -0
- package/app/components/Toggle/Toggle.tsx +285 -0
- package/app/components/index copy.ts +15 -0
- package/app/components/index.ts +18 -0
- package/app/config/config.base.ts +26 -0
- package/app/config/config.dev.ts +10 -0
- package/app/config/config.prod.ts +10 -0
- package/app/config/index.ts +28 -0
- package/app/context/AuthContext.tsx +14 -0
- package/app/context/EpisodeContext.tsx +136 -0
- package/app/context/auth/AuthProvider.tsx +340 -0
- package/app/context/auth/hooks.ts +29 -0
- package/app/context/auth/index.ts +38 -0
- package/app/context/auth/reducer.ts +68 -0
- package/app/context/auth/services.ts +394 -0
- package/app/context/auth/types.ts +99 -0
- package/app/context/auth/validation.ts +45 -0
- package/app/devtools/ReactotronClient.ts +9 -0
- package/app/devtools/ReactotronClient.web.ts +12 -0
- package/app/devtools/ReactotronConfig.ts +139 -0
- package/app/i18n/ar.ts +126 -0
- package/app/i18n/demo-ar.ts +464 -0
- package/app/i18n/demo-en.ts +462 -0
- package/app/i18n/demo-es.ts +469 -0
- package/app/i18n/demo-fr.ts +471 -0
- package/app/i18n/demo-hi.ts +468 -0
- package/app/i18n/demo-ja.ts +464 -0
- package/app/i18n/demo-ko.ts +457 -0
- package/app/i18n/en.ts +146 -0
- package/app/i18n/es.ts +132 -0
- package/app/i18n/fr.ts +132 -0
- package/app/i18n/hi.ts +131 -0
- package/app/i18n/index.ts +86 -0
- package/app/i18n/ja.ts +130 -0
- package/app/i18n/ko.ts +129 -0
- package/app/i18n/translate.ts +33 -0
- package/app/lib/Parse/index.ts +2 -0
- package/app/lib/Parse/parse.ts +62 -0
- package/app/navigators/AppNavigator.tsx +145 -0
- package/app/navigators/DemoNavigator.tsx +137 -0
- package/app/navigators/navigationUtilities.ts +208 -0
- package/app/screens/ChooseAuthScreen.tsx +224 -0
- package/app/screens/DemoCommunityScreen.tsx +141 -0
- package/app/screens/DemoDebugScreen.tsx +192 -0
- package/app/screens/DemoPodcastListScreen.tsx +387 -0
- package/app/screens/DemoShowroomScreen/DemoDivider.tsx +66 -0
- package/app/screens/DemoShowroomScreen/DemoShowroomScreen.tsx +313 -0
- package/app/screens/DemoShowroomScreen/DemoUseCase.tsx +52 -0
- package/app/screens/DemoShowroomScreen/DrawerIconButton.tsx +120 -0
- package/app/screens/DemoShowroomScreen/SectionListWithKeyboardAwareScrollView.tsx +59 -0
- package/app/screens/DemoShowroomScreen/demos/DemoAutoImage.tsx +230 -0
- package/app/screens/DemoShowroomScreen/demos/DemoButton.tsx +234 -0
- package/app/screens/DemoShowroomScreen/demos/DemoCard.tsx +181 -0
- package/app/screens/DemoShowroomScreen/demos/DemoEmptyState.tsx +78 -0
- package/app/screens/DemoShowroomScreen/demos/DemoHeader.tsx +151 -0
- package/app/screens/DemoShowroomScreen/demos/DemoIcon.tsx +115 -0
- package/app/screens/DemoShowroomScreen/demos/DemoListItem.tsx +218 -0
- package/app/screens/DemoShowroomScreen/demos/DemoText.tsx +144 -0
- package/app/screens/DemoShowroomScreen/demos/DemoTextField.tsx +233 -0
- package/app/screens/DemoShowroomScreen/demos/DemoToggle.tsx +354 -0
- package/app/screens/DemoShowroomScreen/demos/index.ts +12 -0
- package/app/screens/ErrorScreen/ErrorBoundary.tsx +76 -0
- package/app/screens/ErrorScreen/ErrorDetails.tsx +98 -0
- package/app/screens/ForgetPasswordScreen.tsx +180 -0
- package/app/screens/LoginScreen.tsx +260 -0
- package/app/screens/RegisterScreen.tsx +395 -0
- package/app/screens/WelcomeScreen.tsx +114 -0
- package/app/services/api/apiProblem.test.ts +73 -0
- package/app/services/api/apiProblem.ts +74 -0
- package/app/services/api/index.ts +91 -0
- package/app/services/api/types.ts +50 -0
- package/app/theme/colors.ts +85 -0
- package/app/theme/colorsDark.ts +50 -0
- package/app/theme/context.tsx +145 -0
- package/app/theme/context.utils.ts +25 -0
- package/app/theme/spacing.ts +14 -0
- package/app/theme/spacingDark.ts +14 -0
- package/app/theme/styles.ts +24 -0
- package/app/theme/theme.ts +23 -0
- package/app/theme/timing.ts +6 -0
- package/app/theme/types.ts +64 -0
- package/app/theme/typography.ts +71 -0
- package/app/utils/crashReporting.ts +62 -0
- package/app/utils/delay.ts +6 -0
- package/app/utils/formatDate.ts +49 -0
- package/app/utils/gestureHandler.native.ts +3 -0
- package/app/utils/gestureHandler.ts +6 -0
- package/app/utils/hasValidStringProp.ts +11 -0
- package/app/utils/openLinkInBrowser.ts +8 -0
- package/app/utils/storage/index.ts +82 -0
- package/app/utils/storage/storage.test.ts +61 -0
- package/app/utils/useHeader.tsx +37 -0
- package/app/utils/useIsMounted.ts +18 -0
- package/app/utils/useSafeAreaInsetsStyle.ts +46 -0
- package/app.config.ts +39 -0
- package/app.json +67 -0
- package/assets/icons/back.png +0 -0
- package/assets/icons/back@2x.png +0 -0
- package/assets/icons/back@3x.png +0 -0
- package/assets/icons/bell.png +0 -0
- package/assets/icons/bell@2x.png +0 -0
- package/assets/icons/bell@3x.png +0 -0
- package/assets/icons/caretLeft.png +0 -0
- package/assets/icons/caretLeft@2x.png +0 -0
- package/assets/icons/caretLeft@3x.png +0 -0
- package/assets/icons/caretRight.png +0 -0
- package/assets/icons/caretRight@2x.png +0 -0
- package/assets/icons/caretRight@3x.png +0 -0
- package/assets/icons/check.png +0 -0
- package/assets/icons/check@2x.png +0 -0
- package/assets/icons/check@3x.png +0 -0
- package/assets/icons/demo/clap.png +0 -0
- package/assets/icons/demo/clap@2x.png +0 -0
- package/assets/icons/demo/clap@3x.png +0 -0
- package/assets/icons/demo/community.png +0 -0
- package/assets/icons/demo/community@2x.png +0 -0
- package/assets/icons/demo/community@3x.png +0 -0
- package/assets/icons/demo/components.png +0 -0
- package/assets/icons/demo/components@2x.png +0 -0
- package/assets/icons/demo/components@3x.png +0 -0
- package/assets/icons/demo/debug.png +0 -0
- package/assets/icons/demo/debug@2x.png +0 -0
- package/assets/icons/demo/debug@3x.png +0 -0
- package/assets/icons/demo/github.png +0 -0
- package/assets/icons/demo/github@2x.png +0 -0
- package/assets/icons/demo/github@3x.png +0 -0
- package/assets/icons/demo/heart.png +0 -0
- package/assets/icons/demo/heart@2x.png +0 -0
- package/assets/icons/demo/heart@3x.png +0 -0
- package/assets/icons/demo/pin.png +0 -0
- package/assets/icons/demo/pin@2x.png +0 -0
- package/assets/icons/demo/pin@3x.png +0 -0
- package/assets/icons/demo/podcast.png +0 -0
- package/assets/icons/demo/podcast@2x.png +0 -0
- package/assets/icons/demo/podcast@3x.png +0 -0
- package/assets/icons/demo/slack.png +0 -0
- package/assets/icons/demo/slack@2x.png +0 -0
- package/assets/icons/demo/slack@3x.png +0 -0
- package/assets/icons/google.png +0 -0
- package/assets/icons/hidden.png +0 -0
- package/assets/icons/hidden@2x.png +0 -0
- package/assets/icons/hidden@3x.png +0 -0
- package/assets/icons/ladybug.png +0 -0
- package/assets/icons/ladybug@2x.png +0 -0
- package/assets/icons/ladybug@3x.png +0 -0
- package/assets/icons/lock.png +0 -0
- package/assets/icons/lock@2x.png +0 -0
- package/assets/icons/lock@3x.png +0 -0
- package/assets/icons/menu.png +0 -0
- package/assets/icons/menu@2x.png +0 -0
- package/assets/icons/menu@3x.png +0 -0
- package/assets/icons/more.png +0 -0
- package/assets/icons/more@2x.png +0 -0
- package/assets/icons/more@3x.png +0 -0
- package/assets/icons/settings.png +0 -0
- package/assets/icons/settings@2x.png +0 -0
- package/assets/icons/settings@3x.png +0 -0
- package/assets/icons/view.png +0 -0
- package/assets/icons/view@2x.png +0 -0
- package/assets/icons/view@3x.png +0 -0
- package/assets/icons/x.png +0 -0
- package/assets/icons/x@2x.png +0 -0
- package/assets/icons/x@3x.png +0 -0
- package/assets/images/app-icon-all.png +0 -0
- package/assets/images/app-icon-android-adaptive-background.png +0 -0
- package/assets/images/app-icon-android-adaptive-foreground.png +0 -0
- package/assets/images/app-icon-android-legacy.png +0 -0
- package/assets/images/app-icon-ios.png +0 -0
- package/assets/images/app-icon-web-favicon.png +0 -0
- package/assets/images/demo/cr-logo.png +0 -0
- package/assets/images/demo/cr-logo@2x.png +0 -0
- package/assets/images/demo/cr-logo@3x.png +0 -0
- package/assets/images/demo/rnl-logo.png +0 -0
- package/assets/images/demo/rnl-logo@2x.png +0 -0
- package/assets/images/demo/rnl-logo@3x.png +0 -0
- package/assets/images/demo/rnn-logo.png +0 -0
- package/assets/images/demo/rnn-logo@2x.png +0 -0
- package/assets/images/demo/rnn-logo@3x.png +0 -0
- package/assets/images/demo/rnr-image-1.png +0 -0
- package/assets/images/demo/rnr-image-1@2x.png +0 -0
- package/assets/images/demo/rnr-image-1@3x.png +0 -0
- package/assets/images/demo/rnr-image-2.png +0 -0
- package/assets/images/demo/rnr-image-2@2x.png +0 -0
- package/assets/images/demo/rnr-image-2@3x.png +0 -0
- package/assets/images/demo/rnr-image-3.png +0 -0
- package/assets/images/demo/rnr-image-3@2x.png +0 -0
- package/assets/images/demo/rnr-image-3@3x.png +0 -0
- package/assets/images/demo/rnr-logo.png +0 -0
- package/assets/images/demo/rnr-logo@2x.png +0 -0
- package/assets/images/demo/rnr-logo@3x.png +0 -0
- package/assets/images/logo.png +0 -0
- package/assets/images/logo@2x.png +0 -0
- package/assets/images/logo@3x.png +0 -0
- package/assets/images/sad-face.png +0 -0
- package/assets/images/sad-face@2x.png +0 -0
- package/assets/images/sad-face@3x.png +0 -0
- package/assets/images/welcome-face.png +0 -0
- package/assets/images/welcome-face@2x.png +0 -0
- package/assets/images/welcome-face@3x.png +0 -0
- package/babel.config.js +7 -0
- package/bin/cli.js +196 -0
- package/ignite/templates/app-icon/android-adaptive-background.png +0 -0
- package/ignite/templates/app-icon/android-adaptive-foreground.png +0 -0
- package/ignite/templates/app-icon/android-legacy.png +0 -0
- package/ignite/templates/app-icon/ios-universal.png +0 -0
- package/ignite/templates/component/NAME.tsx.ejs +39 -0
- package/ignite/templates/navigator/NAMENavigator.tsx.ejs +18 -0
- package/ignite/templates/screen/NAMEScreen.tsx.ejs +29 -0
- package/ignite/templates/splash-screen/logo.png +0 -0
- package/index.tsx +9 -0
- package/jest.config.js +5 -0
- package/metro.config.js +31 -0
- package/package.json +166 -0
- package/plugins/withSplashScreen.ts +69 -0
- package/src/app/_layout.tsx +58 -0
- package/src/app/index.tsx +5 -0
- package/test/i18n.test.ts +75 -0
- package/test/mockFile.ts +6 -0
- package/test/setup.ts +58 -0
- package/test/test-tsconfig.json +8 -0
- package/tsconfig.json +52 -0
- package/types/lib.es5.d.ts +25 -0
package/CONTRIBUTING.md
ADDED
|
File without changes
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Kwaku Ansah
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,492 @@
|
|
|
1
|
+
# Ignite Parse Auth Kit
|
|
2
|
+
|
|
3
|
+
A comprehensive React Native (Expo) template powered by Ignite CLI and Parse Server, providing production-ready authentication solutions including email/password authentication, Google Sign-In integration, session persistence, and password reset functionality.
|
|
4
|
+
|
|
5
|
+
[](https://github.com/neweracy/IgniteParseAuthKit/actions)
|
|
6
|
+
[](https://codecov.io/gh/neweracy/IgniteParseAuthKit)
|
|
7
|
+
[](https://www.npmjs.com/package/ignite-parse-auth-kit)
|
|
8
|
+
[](LICENSE)
|
|
9
|
+
[](CONTRIBUTING.md)
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Table of Contents
|
|
14
|
+
|
|
15
|
+
- [Features](#features)
|
|
16
|
+
- [Quick Start](#quick-start)
|
|
17
|
+
- [Installation via npm](#installation-via-npm)
|
|
18
|
+
- [Usage Guide](#usage-guide)
|
|
19
|
+
- [Configuration](#configuration)
|
|
20
|
+
- [Project Structure](#project-structure)
|
|
21
|
+
- [Development](#development)
|
|
22
|
+
- [Contributing](#contributing)
|
|
23
|
+
- [License](#license)
|
|
24
|
+
- [Support & Contact](#support--contact)
|
|
25
|
+
- [Changelog](#changelog)
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Features
|
|
30
|
+
|
|
31
|
+
### Authentication & Security
|
|
32
|
+
|
|
33
|
+
- **Email/Password Authentication** - Complete signup and login flow with real-time validation
|
|
34
|
+
- **Google Sign-In Integration** - Seamless OAuth via Expo AuthSession
|
|
35
|
+
- **Password Reset** - Built-in password recovery using Parse Server
|
|
36
|
+
- **Session Persistence** - Fast session restore using MMKV storage
|
|
37
|
+
- **Server Health Monitoring** - Pre-flight checks before authentication actions
|
|
38
|
+
|
|
39
|
+
### Developer Experience
|
|
40
|
+
|
|
41
|
+
- **React Native + Expo** - Cross-platform development with modern tooling
|
|
42
|
+
- **TypeScript Support** - Fully typed AuthContext and API responses
|
|
43
|
+
- **Path Aliases** - Clean imports with `@/...` syntax
|
|
44
|
+
- **Offline-First Ready** - Parse local datastore enabled for offline capabilities
|
|
45
|
+
- **Production Ready** - Comprehensive error handling and loading states
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Quick Start
|
|
50
|
+
|
|
51
|
+
### Installation via npm (Recommended)
|
|
52
|
+
|
|
53
|
+
The easiest way to create a new project is using npx:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# Create a new project
|
|
57
|
+
npx ignite-parse-auth-kit my-app
|
|
58
|
+
|
|
59
|
+
# Navigate to the project
|
|
60
|
+
cd my-app
|
|
61
|
+
|
|
62
|
+
# Start developing
|
|
63
|
+
npx expo start
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
#### CLI Options
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
# Skip automatic dependency installation
|
|
70
|
+
npx ignite-parse-auth-kit my-app --skip-install
|
|
71
|
+
|
|
72
|
+
# Use npm instead of yarn
|
|
73
|
+
npx ignite-parse-auth-kit my-app --use-npm
|
|
74
|
+
|
|
75
|
+
# Use bun instead of yarn
|
|
76
|
+
npx ignite-parse-auth-kit my-app --use-bun
|
|
77
|
+
|
|
78
|
+
# Specify a custom directory
|
|
79
|
+
npx ignite-parse-auth-kit my-app --directory ./projects
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Alternative Installation Methods
|
|
83
|
+
|
|
84
|
+
#### Using GitHub Template
|
|
85
|
+
|
|
86
|
+
1. **Use this template**
|
|
87
|
+
- Click the "Use this template" button on GitHub
|
|
88
|
+
- Or visit: `https://github.com/neweracy/IgniteParseAuthKit/generate`
|
|
89
|
+
- Create your new repository from this template
|
|
90
|
+
|
|
91
|
+
2. **Clone your new repository**
|
|
92
|
+
```bash
|
|
93
|
+
git clone https://github.com/your-username/your-new-repo-name.git
|
|
94
|
+
cd your-new-repo-name
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
3. **Install dependencies**
|
|
98
|
+
```bash
|
|
99
|
+
yarn install
|
|
100
|
+
# or
|
|
101
|
+
npm install
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
4. **Configure environment variables**
|
|
105
|
+
```bash
|
|
106
|
+
# Edit app/config/config.dev.ts with your Parse Server configuration
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
5. **Start the development server**
|
|
110
|
+
```bash
|
|
111
|
+
npx expo start
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
6. **Launch on device/simulator**
|
|
115
|
+
- Press `i` for iOS Simulator
|
|
116
|
+
- Press `a` for Android Emulator
|
|
117
|
+
- Scan QR code with Expo Go for physical device testing
|
|
118
|
+
|
|
119
|
+
### Prerequisites
|
|
120
|
+
|
|
121
|
+
Ensure you have the following installed on your development machine:
|
|
122
|
+
|
|
123
|
+
- **Node.js** LTS (v18 or higher)
|
|
124
|
+
- **Package Manager** - Yarn, npm, or bun
|
|
125
|
+
- **Expo CLI** - Comes with npx (no global install needed)
|
|
126
|
+
- **Mobile Development Environment**:
|
|
127
|
+
- **iOS**: Xcode (macOS only)
|
|
128
|
+
- **Android**: Android Studio
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Usage Guide
|
|
133
|
+
|
|
134
|
+
### Authentication Methods
|
|
135
|
+
|
|
136
|
+
The AuthContext provides a comprehensive API for handling all authentication scenarios:
|
|
137
|
+
|
|
138
|
+
### Code Examples
|
|
139
|
+
|
|
140
|
+
#### Email/Password Login
|
|
141
|
+
|
|
142
|
+
```tsx
|
|
143
|
+
import { useAuth } from '@/context/AuthContext'
|
|
144
|
+
|
|
145
|
+
export function LoginScreen() {
|
|
146
|
+
const { setAuthEmail, setAuthPassword, login, isLoading, error } = useAuth()
|
|
147
|
+
|
|
148
|
+
const handleLogin = async () => {
|
|
149
|
+
setAuthEmail('user@example.com')
|
|
150
|
+
setAuthPassword('password123')
|
|
151
|
+
|
|
152
|
+
const result = await login()
|
|
153
|
+
if (!result.success) {
|
|
154
|
+
console.error('Login failed:', result.error)
|
|
155
|
+
} else {
|
|
156
|
+
console.log('Login successful!')
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return (
|
|
161
|
+
<View>
|
|
162
|
+
{/* Your login form UI here */}
|
|
163
|
+
<Button title="Login" onPress={handleLogin} disabled={isLoading} />
|
|
164
|
+
{error && <Text style={{ color: 'red' }}>{error}</Text>}
|
|
165
|
+
</View>
|
|
166
|
+
)
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
#### User Registration
|
|
171
|
+
|
|
172
|
+
```tsx
|
|
173
|
+
import { useAuth } from '@/context/AuthContext'
|
|
174
|
+
|
|
175
|
+
export function RegisterScreen() {
|
|
176
|
+
const { setAuthEmail, setAuthPassword, signUp, isLoading, error } = useAuth()
|
|
177
|
+
|
|
178
|
+
const handleSignUp = async () => {
|
|
179
|
+
setAuthEmail('newuser@example.com')
|
|
180
|
+
setAuthPassword('securePassword123')
|
|
181
|
+
|
|
182
|
+
const result = await signUp('unique_username')
|
|
183
|
+
if (result.success) {
|
|
184
|
+
console.log('Account created successfully!')
|
|
185
|
+
} else {
|
|
186
|
+
console.error('Registration failed:', result.error)
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return (
|
|
191
|
+
<View>
|
|
192
|
+
{/* Your registration form UI here */}
|
|
193
|
+
<Button title="Sign Up" onPress={handleSignUp} disabled={isLoading} />
|
|
194
|
+
{error && <Text style={{ color: 'red' }}>{error}</Text>}
|
|
195
|
+
</View>
|
|
196
|
+
)
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
#### Password Reset
|
|
201
|
+
|
|
202
|
+
```tsx
|
|
203
|
+
import { useAuth } from '@/context/AuthContext'
|
|
204
|
+
|
|
205
|
+
export function PasswordResetScreen() {
|
|
206
|
+
const { requestPasswordReset } = useAuth()
|
|
207
|
+
const [email, setEmail] = useState('')
|
|
208
|
+
|
|
209
|
+
const handlePasswordReset = async () => {
|
|
210
|
+
const result = await requestPasswordReset(email)
|
|
211
|
+
if (result.success) {
|
|
212
|
+
Alert.alert('Success', result.message || 'Password reset email sent!')
|
|
213
|
+
} else {
|
|
214
|
+
Alert.alert('Error', result.error || 'Failed to send reset email')
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return (
|
|
219
|
+
<View>
|
|
220
|
+
<TextInput
|
|
221
|
+
value={email}
|
|
222
|
+
onChangeText={setEmail}
|
|
223
|
+
placeholder="Enter your email"
|
|
224
|
+
keyboardType="email-address"
|
|
225
|
+
/>
|
|
226
|
+
<Button title="Reset Password" onPress={handlePasswordReset} />
|
|
227
|
+
</View>
|
|
228
|
+
)
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
#### Google Sign-In
|
|
233
|
+
|
|
234
|
+
```tsx
|
|
235
|
+
import { useAuth } from '@/context/AuthContext'
|
|
236
|
+
|
|
237
|
+
export function GoogleSignInScreen() {
|
|
238
|
+
const { googleSignIn } = useAuth()
|
|
239
|
+
|
|
240
|
+
const handleGoogleSignIn = async () => {
|
|
241
|
+
try {
|
|
242
|
+
// You'll need to implement getGoogleAuthResponse using Expo AuthSession
|
|
243
|
+
const googleResponse = await getGoogleAuthResponse()
|
|
244
|
+
|
|
245
|
+
const result = await googleSignIn(googleResponse)
|
|
246
|
+
if (result.success) {
|
|
247
|
+
console.log('Google sign-in successful!')
|
|
248
|
+
} else {
|
|
249
|
+
console.error('Google sign-in failed:', result.error)
|
|
250
|
+
}
|
|
251
|
+
} catch (error) {
|
|
252
|
+
console.error('Google sign-in error:', error)
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
return (
|
|
257
|
+
<View>
|
|
258
|
+
<Button title="Sign in with Google" onPress={handleGoogleSignIn} />
|
|
259
|
+
</View>
|
|
260
|
+
)
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
#### Server Health Check
|
|
265
|
+
|
|
266
|
+
```tsx
|
|
267
|
+
import { useAuth } from '@/context/AuthContext'
|
|
268
|
+
import { useEffect } from 'react'
|
|
269
|
+
|
|
270
|
+
export function ServerStatusComponent() {
|
|
271
|
+
const { checkServerStatus } = useAuth()
|
|
272
|
+
|
|
273
|
+
useEffect(() => {
|
|
274
|
+
const verifyServerConnection = async () => {
|
|
275
|
+
const status = await checkServerStatus()
|
|
276
|
+
|
|
277
|
+
if (status.isRunning) {
|
|
278
|
+
console.log('✅ Parse Server is running')
|
|
279
|
+
} else {
|
|
280
|
+
console.error('❌ Server unavailable:', status.message)
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
verifyServerConnection()
|
|
285
|
+
}, [checkServerStatus])
|
|
286
|
+
|
|
287
|
+
return null
|
|
288
|
+
}
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
---
|
|
292
|
+
|
|
293
|
+
## Configuration
|
|
294
|
+
|
|
295
|
+
### Environment Variables
|
|
296
|
+
|
|
297
|
+
Create a `.env` file in your project root with the following required variables:
|
|
298
|
+
|
|
299
|
+
```env
|
|
300
|
+
# Parse Server Configuration (Required)
|
|
301
|
+
EXPO_PUBLIC_SERVER_URL=https://your-parse-server.herokuapp.com/parse
|
|
302
|
+
EXPO_PUBLIC_APP_ID=your_unique_app_identifier
|
|
303
|
+
EXPO_PUBLIC_JAVASCRIPT_KEY=your_javascript_key
|
|
304
|
+
|
|
305
|
+
# Optional: Google Sign-In Configuration
|
|
306
|
+
GOOGLE_CLIENT_ID=your-google-oauth-client-id
|
|
307
|
+
|
|
308
|
+
# Optional: Development Settings
|
|
309
|
+
NODE_ENV=development
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
> **⚠️ Security Note**: Never commit sensitive keys to version control. Use Expo's secure environment variable handling for production deployments.
|
|
313
|
+
|
|
314
|
+
### TypeScript Configuration
|
|
315
|
+
|
|
316
|
+
The template includes pre-configured path aliases for clean imports:
|
|
317
|
+
|
|
318
|
+
**tsconfig.json**
|
|
319
|
+
```json
|
|
320
|
+
{
|
|
321
|
+
"compilerOptions": {
|
|
322
|
+
"baseUrl": ".",
|
|
323
|
+
"paths": {
|
|
324
|
+
"@/*": ["app/*"],
|
|
325
|
+
"@/components/*": ["app/components/*"],
|
|
326
|
+
"@/context/*": ["app/context/*"],
|
|
327
|
+
"@/lib/*": ["app/lib/*"]
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
**babel.config.js**
|
|
334
|
+
```javascript
|
|
335
|
+
module.exports = function (api) {
|
|
336
|
+
api.cache(true)
|
|
337
|
+
|
|
338
|
+
return {
|
|
339
|
+
presets: ['babel-preset-expo'],
|
|
340
|
+
plugins: [
|
|
341
|
+
[
|
|
342
|
+
'module-resolver',
|
|
343
|
+
{
|
|
344
|
+
root: ['./'],
|
|
345
|
+
alias: {
|
|
346
|
+
'@': './app',
|
|
347
|
+
},
|
|
348
|
+
extensions: ['.ts', '.tsx', '.js', '.jsx', '.json'],
|
|
349
|
+
},
|
|
350
|
+
],
|
|
351
|
+
],
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
### Parse Server Setup
|
|
357
|
+
|
|
358
|
+
The Parse SDK is initialized in `app/lib/Parse/parse.ts` with the following configuration:
|
|
359
|
+
|
|
360
|
+
- **AsyncStorage Integration** - For React Native compatibility
|
|
361
|
+
- **Local Datastore** - Enabled for offline-first capabilities
|
|
362
|
+
- **Runtime Validation** - Environment variables are validated on app start
|
|
363
|
+
- **Error Handling** - Comprehensive error boundaries for Parse operations
|
|
364
|
+
|
|
365
|
+
---
|
|
366
|
+
|
|
367
|
+
## Project Structure
|
|
368
|
+
|
|
369
|
+
```text
|
|
370
|
+
ignite-parse-auth-kit/
|
|
371
|
+
├── app/ # Main application directory
|
|
372
|
+
│ ├── components/ # Reusable UI components
|
|
373
|
+
│ ├── context/ # React Context providers
|
|
374
|
+
│ │ └── AuthContext.tsx # Central authentication state
|
|
375
|
+
│ ├── lib/ # Core libraries and utilities
|
|
376
|
+
│ │ ├── Parse/
|
|
377
|
+
│ │ │ └── parse.ts # Parse SDK initialization
|
|
378
|
+
│ │ └── utils/
|
|
379
|
+
│ │ ├── validation.ts # Form validation helpers
|
|
380
|
+
│ │ └── storage.ts # MMKV storage wrapper
|
|
381
|
+
│ ├── screens/ # Application screens
|
|
382
|
+
│ │ ├── LoginScreen.tsx # Email/password login
|
|
383
|
+
│ │ ├── RegisterScreen.tsx # User registration
|
|
384
|
+
│ │ ├── ForgotPasswordScreen.tsx # Password recovery
|
|
385
|
+
│ │ └── DashboardScreen.tsx # Protected route example
|
|
386
|
+
│ ├── navigators/ # Navigation configuration
|
|
387
|
+
│ │ ├── AuthNavigator.tsx # Authentication flow
|
|
388
|
+
│ │ ├── AppNavigator.tsx # Main app navigation
|
|
389
|
+
│ │ └── types.ts # Navigation type definitions
|
|
390
|
+
│ └── types/ # TypeScript type definitions
|
|
391
|
+
│ ├── auth.ts # Authentication types
|
|
392
|
+
│ └── api.ts # API response types
|
|
393
|
+
├── assets/ # Static assets (images, fonts)
|
|
394
|
+
├── .env.example # Environment variables template
|
|
395
|
+
├── app.json # Expo configuration
|
|
396
|
+
├── package.json # Dependencies and scripts
|
|
397
|
+
└── README.md # This file
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
---
|
|
401
|
+
|
|
402
|
+
## Development
|
|
403
|
+
|
|
404
|
+
### Available Scripts
|
|
405
|
+
|
|
406
|
+
```bash
|
|
407
|
+
# Start development server
|
|
408
|
+
npm start
|
|
409
|
+
|
|
410
|
+
# Start with cache cleared
|
|
411
|
+
npm run start:clear
|
|
412
|
+
|
|
413
|
+
# Run on iOS simulator
|
|
414
|
+
npm run ios
|
|
415
|
+
|
|
416
|
+
# Run on Android emulator
|
|
417
|
+
npm run android
|
|
418
|
+
|
|
419
|
+
# Run tests
|
|
420
|
+
npm test
|
|
421
|
+
|
|
422
|
+
# Type checking
|
|
423
|
+
npm run type-check
|
|
424
|
+
|
|
425
|
+
# Linting
|
|
426
|
+
npm run lint
|
|
427
|
+
|
|
428
|
+
# Build for production
|
|
429
|
+
npm run build
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
### Development Workflow
|
|
433
|
+
|
|
434
|
+
1. **Feature Development** - Create feature branches from `main`
|
|
435
|
+
2. **Testing** - Run tests and manual testing on both platforms
|
|
436
|
+
3. **Code Quality** - Ensure TypeScript compliance and linting passes
|
|
437
|
+
4. **Documentation** - Update relevant documentation for new features
|
|
438
|
+
|
|
439
|
+
---
|
|
440
|
+
|
|
441
|
+
## Contributing
|
|
442
|
+
|
|
443
|
+
We welcome contributions from the community! Here's how you can help:
|
|
444
|
+
|
|
445
|
+
### Getting Started
|
|
446
|
+
|
|
447
|
+
1. **Use this template** to create your own repository
|
|
448
|
+
2. **Clone** your new repository locally
|
|
449
|
+
3. **Create** a feature branch: `git checkout -b feat/your-feature-name`
|
|
450
|
+
4. **Make** your changes and improvements
|
|
451
|
+
5. **Test** thoroughly on both iOS and Android
|
|
452
|
+
6. **Submit** a pull request to the original template repository
|
|
453
|
+
|
|
454
|
+
### Contribution Guidelines
|
|
455
|
+
|
|
456
|
+
- Follow [Conventional Commits](https://www.conventionalcommits.org/) format
|
|
457
|
+
- Include tests for new features
|
|
458
|
+
- Update documentation for API changes
|
|
459
|
+
- Keep PRs focused and atomic
|
|
460
|
+
- Ensure all CI checks pass
|
|
461
|
+
|
|
462
|
+
### Commit Message Format
|
|
463
|
+
```
|
|
464
|
+
type(scope): description
|
|
465
|
+
|
|
466
|
+
feat(auth): add biometric authentication support
|
|
467
|
+
fix(login): resolve session persistence issue
|
|
468
|
+
docs(readme): update installation instructions
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
---
|
|
472
|
+
|
|
473
|
+
## License
|
|
474
|
+
|
|
475
|
+
This project is licensed under the **MIT License**. See the [LICENSE](LICENSE) file for complete details.
|
|
476
|
+
|
|
477
|
+
```
|
|
478
|
+
MIT License - Copyright (c) 2024 Ignite Parse Auth Kit
|
|
479
|
+
|
|
480
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
481
|
+
of this software and associated documentation files...
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
---
|
|
485
|
+
|
|
486
|
+
## Support & Contact
|
|
487
|
+
|
|
488
|
+
### Getting Help
|
|
489
|
+
|
|
490
|
+
- **Bug Reports**: [GitHub Issues](https://github.com/your-org/ignite-parse-auth-kit/issues)
|
|
491
|
+
- **Feature Requests**: [GitHub Discussions](https://github.com/your-org/ignite-parse-auth-kit/discussions)
|
|
492
|
+
- **Documentation**: [Wiki](https://github.com/your-org/ignite-parse-auth-kit/wiki)
|
package/app/app.tsx
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/* eslint-disable import/first */
|
|
2
|
+
/**
|
|
3
|
+
* Welcome to the main entry point of the app. In this file, we'll
|
|
4
|
+
* be kicking off our app.
|
|
5
|
+
*
|
|
6
|
+
* Most of this file is boilerplate and you shouldn't need to modify
|
|
7
|
+
* it very often. But take some time to look through and understand
|
|
8
|
+
* what is going on here.
|
|
9
|
+
*
|
|
10
|
+
* The app navigation resides in ./app/navigators, so head over there
|
|
11
|
+
* if you're interested in adding screens and navigators.
|
|
12
|
+
*/
|
|
13
|
+
if (__DEV__) {
|
|
14
|
+
// Load Reactotron in development only.
|
|
15
|
+
// Note that you must be using metro's `inlineRequires` for this to work.
|
|
16
|
+
// If you turn it off in metro.config.js, you'll have to manually import it.
|
|
17
|
+
require("./devtools/ReactotronConfig.ts")
|
|
18
|
+
}
|
|
19
|
+
import "./utils/gestureHandler"
|
|
20
|
+
|
|
21
|
+
import { useEffect, useState } from "react"
|
|
22
|
+
import { useFonts } from "expo-font"
|
|
23
|
+
import * as Linking from "expo-linking"
|
|
24
|
+
import { KeyboardProvider } from "react-native-keyboard-controller"
|
|
25
|
+
import { initialWindowMetrics, SafeAreaProvider } from "react-native-safe-area-context"
|
|
26
|
+
|
|
27
|
+
import { AuthProvider } from "./context/AuthContext" // @demo remove-current-line
|
|
28
|
+
import { initI18n } from "./i18n"
|
|
29
|
+
import { AppNavigator } from "./navigators/AppNavigator"
|
|
30
|
+
import { useNavigationPersistence } from "./navigators/navigationUtilities"
|
|
31
|
+
import { ThemeProvider } from "./theme/context"
|
|
32
|
+
import { customFontsToLoad } from "./theme/typography"
|
|
33
|
+
import { loadDateFnsLocale } from "./utils/formatDate"
|
|
34
|
+
import 'react-native-get-random-values';
|
|
35
|
+
import * as storage from "./utils/storage"
|
|
36
|
+
|
|
37
|
+
export const NAVIGATION_PERSISTENCE_KEY = "NAVIGATION_STATE"
|
|
38
|
+
|
|
39
|
+
// Web linking configuration
|
|
40
|
+
const prefix = Linking.createURL("/")
|
|
41
|
+
const config = {
|
|
42
|
+
screens: {
|
|
43
|
+
Login: {
|
|
44
|
+
path: "",
|
|
45
|
+
},
|
|
46
|
+
Welcome: "welcome",
|
|
47
|
+
Demo: {
|
|
48
|
+
screens: {
|
|
49
|
+
DemoShowroom: {
|
|
50
|
+
path: "showroom/:queryIndex?/:itemIndex?",
|
|
51
|
+
},
|
|
52
|
+
DemoDebug: "debug",
|
|
53
|
+
DemoPodcastList: "podcast",
|
|
54
|
+
DemoCommunity: "community",
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* This is the root component of our app.
|
|
62
|
+
* @param {AppProps} props - The props for the `App` component.
|
|
63
|
+
* @returns {JSX.Element} The rendered `App` component.
|
|
64
|
+
*/
|
|
65
|
+
export function App() {
|
|
66
|
+
const {
|
|
67
|
+
initialNavigationState,
|
|
68
|
+
onNavigationStateChange,
|
|
69
|
+
isRestored: isNavigationStateRestored,
|
|
70
|
+
} = useNavigationPersistence(storage, NAVIGATION_PERSISTENCE_KEY)
|
|
71
|
+
|
|
72
|
+
const [areFontsLoaded, fontLoadError] = useFonts(customFontsToLoad)
|
|
73
|
+
const [isI18nInitialized, setIsI18nInitialized] = useState(false)
|
|
74
|
+
|
|
75
|
+
useEffect(() => {
|
|
76
|
+
initI18n()
|
|
77
|
+
.then(() => setIsI18nInitialized(true))
|
|
78
|
+
.then(() => loadDateFnsLocale())
|
|
79
|
+
}, [])
|
|
80
|
+
|
|
81
|
+
// Before we show the app, we have to wait for our state to be ready.
|
|
82
|
+
// In the meantime, don't render anything. This will be the background
|
|
83
|
+
// color set in native by rootView's background color.
|
|
84
|
+
// In iOS: application:didFinishLaunchingWithOptions:
|
|
85
|
+
// In Android: https://stackoverflow.com/a/45838109/204044
|
|
86
|
+
// You can replace with your own loading component if you wish.
|
|
87
|
+
if (!isNavigationStateRestored || !isI18nInitialized || (!areFontsLoaded && !fontLoadError)) {
|
|
88
|
+
return null
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const linking = {
|
|
92
|
+
prefixes: [prefix],
|
|
93
|
+
config,
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// otherwise, we're ready to render the app
|
|
97
|
+
return (
|
|
98
|
+
<SafeAreaProvider initialMetrics={initialWindowMetrics}>
|
|
99
|
+
<KeyboardProvider>
|
|
100
|
+
{/* @demo remove-block-start */}
|
|
101
|
+
<AuthProvider>
|
|
102
|
+
{/* @demo remove-block-end */}
|
|
103
|
+
<ThemeProvider>
|
|
104
|
+
<AppNavigator
|
|
105
|
+
linking={linking}
|
|
106
|
+
initialState={initialNavigationState}
|
|
107
|
+
onStateChange={onNavigationStateChange}
|
|
108
|
+
/>
|
|
109
|
+
</ThemeProvider>
|
|
110
|
+
{/* @demo remove-block-start */}
|
|
111
|
+
</AuthProvider>
|
|
112
|
+
{/* @demo remove-block-end */}
|
|
113
|
+
</KeyboardProvider>
|
|
114
|
+
</SafeAreaProvider>
|
|
115
|
+
)
|
|
116
|
+
}
|