@donotdev/cli 0.0.13 → 0.0.15
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/dependencies-matrix.json +357 -89
- package/dist/bin/commands/agent-setup.d.ts +6 -0
- package/dist/bin/commands/agent-setup.d.ts.map +1 -0
- package/dist/bin/commands/agent-setup.js +629 -0
- package/dist/bin/commands/agent-setup.js.map +1 -0
- package/dist/bin/commands/build.js +131 -50
- package/dist/bin/commands/bump.js +137 -49
- package/dist/bin/commands/cacheout.js +50 -21
- package/dist/bin/commands/create-app.js +270 -261
- package/dist/bin/commands/create-project.js +418 -197
- package/dist/bin/commands/deploy.js +1752 -712
- package/dist/bin/commands/dev.js +151 -35
- package/dist/bin/commands/emu.js +228 -70
- package/dist/bin/commands/format.js +50 -21
- package/dist/bin/commands/lint.js +50 -21
- package/dist/bin/commands/preview.js +155 -35
- package/dist/bin/commands/supabase-setup.d.ts +6 -0
- package/dist/bin/commands/supabase-setup.d.ts.map +1 -0
- package/dist/bin/commands/supabase-setup.js +7 -0
- package/dist/bin/commands/supabase-setup.js.map +1 -0
- package/dist/bin/commands/sync-secrets.js +224 -46
- package/dist/bin/commands/type-check.d.ts +14 -0
- package/dist/bin/commands/type-check.d.ts.map +1 -0
- package/dist/bin/commands/type-check.js +314 -0
- package/dist/bin/commands/type-check.js.map +1 -0
- package/dist/bin/commands/wai.js +7399 -11
- package/dist/bin/dndev.js +27 -2
- package/dist/bin/donotdev.js +27 -2
- package/dist/index.js +3960 -2996
- package/package.json +2 -2
- package/templates/app-demo/src/App.tsx.example +1 -0
- package/templates/app-demo/src/pages/FullPage.tsx.example +2 -2
- package/templates/app-demo/src/pages/components/DemoLayout.tsx.example +2 -2
- package/templates/app-demo/src/themes.css.example +5 -12
- package/templates/app-expo/.env.example +64 -0
- package/templates/app-expo/.expo/README.md.example +5 -0
- package/templates/app-expo/.gitignore.example +36 -0
- package/templates/app-expo/README.md.example +58 -0
- package/templates/app-expo/app/.gitkeep +2 -0
- package/templates/app-expo/app/_layout.tsx.example +41 -0
- package/templates/app-expo/app/form.tsx.example +52 -0
- package/templates/app-expo/app/index.tsx.example +89 -0
- package/templates/app-expo/app/list.tsx.example +32 -0
- package/templates/app-expo/app/profile.tsx.example +76 -0
- package/templates/app-expo/app/signin.tsx.example +53 -0
- package/templates/app-expo/app.json.example +39 -0
- package/templates/app-expo/babel.config.js.example +10 -0
- package/templates/app-expo/eas.json.example +20 -0
- package/templates/app-expo/expo-env.d.ts.example +4 -0
- package/templates/app-expo/metro.config.js.example +20 -0
- package/templates/app-expo/service-account-key.json.example +12 -0
- package/templates/app-expo/tsconfig.json.example +19 -0
- package/templates/app-next/.env.example +4 -33
- package/templates/app-next/src/app/ClientLayout.tsx.example +2 -0
- package/templates/app-next/src/app/layout.tsx.example +7 -6
- package/templates/app-next/src/globals.css.example +2 -11
- package/templates/app-next/src/pages/HomePage.tsx.example +1 -1
- package/templates/app-next/src/themes.css.example +10 -13
- package/templates/app-vite/.env.example +3 -32
- package/templates/app-vite/index.html.example +2 -24
- package/templates/app-vite/src/App.tsx.example +2 -0
- package/templates/app-vite/src/globals.css.example +2 -12
- package/templates/app-vite/src/pages/FormPageExample.tsx.example +1 -2
- package/templates/app-vite/src/pages/HomePage.tsx.example +1 -1
- package/templates/app-vite/src/themes.css.example +109 -79
- package/templates/app-vite/vercel.json.example +11 -0
- package/templates/functions-firebase/build.mjs.example +2 -72
- package/templates/functions-firebase/functions-firebase/.env.example.example +23 -25
- package/templates/functions-firebase/functions-firebase/build.mjs.example +2 -72
- package/templates/functions-firebase/functions-firebase/tsconfig.json.example +1 -1
- package/templates/functions-supabase/supabase/functions/cancel-subscription/index.ts.example +7 -0
- package/templates/functions-supabase/supabase/functions/change-plan/index.ts.example +11 -0
- package/templates/functions-supabase/supabase/functions/create-checkout-session/index.ts.example +11 -0
- package/templates/functions-supabase/supabase/functions/create-customer-portal/index.ts.example +7 -0
- package/templates/functions-supabase/supabase/functions/crud/index.ts.example +16 -0
- package/templates/functions-supabase/supabase/functions/delete-account/index.ts.example +7 -0
- package/templates/functions-supabase/supabase/functions/get-custom-claims/index.ts.example +7 -0
- package/templates/functions-supabase/supabase/functions/get-user-auth-status/index.ts.example +7 -0
- package/templates/functions-supabase/supabase/functions/refresh-subscription-status/index.ts.example +7 -0
- package/templates/functions-supabase/supabase/functions/remove-custom-claims/index.ts.example +7 -0
- package/templates/functions-supabase/supabase/functions/set-custom-claims/index.ts.example +7 -0
- package/templates/functions-supabase/supabase/migrations/20250101000000_idempotency.sql +24 -0
- package/templates/functions-supabase/supabase/migrations/20250101000001_rate_limits.sql +22 -0
- package/templates/functions-supabase/supabase/migrations/20250101000002_cleanup_jobs.sql +28 -0
- package/templates/functions-supabase/supabase/migrations/20250101000003_operation_metrics.sql +28 -0
- package/templates/functions-vercel/functions-vercel/tsconfig.json.example +1 -1
- package/templates/functions-vercel/functions-vercel/vercel.json.example +1 -1
- package/templates/functions-vercel/vercel.json.example +1 -1
- package/templates/github/github/workflows/firebase-deploy.yml.example +1 -1
- package/templates/github/workflows/firebase-deploy.yml.example +1 -1
- package/templates/overlay-firebase/env.fragment.example +34 -0
- package/templates/overlay-firebase/env.fragment.expo.example +34 -0
- package/templates/overlay-firebase/env.fragment.nextjs.example +34 -0
- package/templates/overlay-firebase/src/config/providers.expo.ts.example +49 -0
- package/templates/overlay-firebase/src/config/providers.ts.example +23 -0
- package/templates/overlay-supabase/env.fragment.example +7 -0
- package/templates/overlay-supabase/env.fragment.expo.example +7 -0
- package/templates/overlay-supabase/env.fragment.nextjs.example +7 -0
- package/templates/overlay-supabase/src/config/providers.expo.ts.example +35 -0
- package/templates/overlay-supabase/src/config/providers.ts.example +33 -0
- package/templates/overlay-supabase/vercel.headers.example +23 -0
- package/templates/overlay-supabase/vercel.json.example +22 -0
- package/templates/overlay-vercel/env.fragment.example +34 -0
- package/templates/overlay-vercel/env.fragment.nextjs.example +34 -0
- package/templates/overlay-vercel/src/config/providers.ts.example +24 -0
- package/templates/root-consumer/.claude/agents/architect.md.example +2 -310
- package/templates/root-consumer/.claude/agents/builder.md.example +2 -326
- package/templates/root-consumer/.claude/agents/coder.md.example +2 -83
- package/templates/root-consumer/.claude/agents/extractor.md.example +2 -231
- package/templates/root-consumer/.claude/agents/polisher.md.example +2 -132
- package/templates/root-consumer/.claude/agents/prompt-engineer.md.example +2 -81
- package/templates/root-consumer/.claude/commands/brainstorm.md.example +1 -1
- package/templates/root-consumer/.claude/commands/build.md.example +1 -1
- package/templates/root-consumer/.claude/commands/design.md.example +1 -1
- package/templates/root-consumer/.claude/commands/grill.md.example +30 -0
- package/templates/root-consumer/.claude/commands/polish.md.example +1 -1
- package/templates/root-consumer/.claude/commands/techdebt.md.example +28 -0
- package/templates/root-consumer/.clinerules.example +1 -0
- package/templates/root-consumer/.cursor/rules/no-docs.mdc.example +15 -0
- package/templates/root-consumer/.cursorrules.example +1 -0
- package/templates/root-consumer/.dndev/args.json.example +6 -0
- package/templates/root-consumer/.gemini/settings.json.example +2 -2
- package/templates/root-consumer/.github/copilot-instructions.md.example +1 -0
- package/templates/root-consumer/.windsurfrules.example +1 -0
- package/templates/root-consumer/AI.md.example +25 -108
- package/templates/root-consumer/CLAUDE.md.example +1 -128
- package/templates/root-consumer/CONVENTIONS.md.example +1 -0
- package/templates/root-consumer/GEMINI.md.example +1 -0
- package/templates/root-consumer/firebase.json.example +1 -1
- package/templates/root-consumer/guides/dndev/AGENT_START_HERE.md.example +54 -0
- package/templates/root-consumer/guides/dndev/COMPONENTS_ADV.md.example +0 -18
- package/templates/root-consumer/guides/dndev/COMPONENTS_UI.md.example +1 -1
- package/templates/root-consumer/guides/dndev/ENV_SETUP.md.example +99 -30
- package/templates/root-consumer/guides/dndev/GOTCHAS.md.example +186 -0
- package/templates/root-consumer/guides/dndev/INDEX.md.example +4 -1
- package/templates/root-consumer/guides/dndev/SETUP_CRUD.md.example +143 -12
- package/templates/root-consumer/guides/dndev/SETUP_FIREBASE.md.example +9 -3
- package/templates/root-consumer/guides/dndev/SETUP_FUNCTIONS.md.example +12 -7
- package/templates/root-consumer/guides/dndev/SETUP_SOC2.md.example +234 -0
- package/templates/root-consumer/guides/dndev/SETUP_SUPABASE.md.example +124 -0
- package/templates/root-consumer/guides/dndev/SETUP_THEMES.md.example +6 -2
- package/templates/root-consumer/guides/dndev/SETUP_VERCEL.md.example +176 -0
- package/templates/root-consumer/guides/dndev/USE_ROUTING.md.example +5 -9
- package/templates/root-consumer/guides/dndev/essences_reference.css.example +174 -0
- package/templates/root-consumer/guides/wai-way/agents/builder.md.example +10 -0
- package/templates/root-consumer/guides/wai-way/agents/extractor.md.example +25 -5
- package/templates/root-consumer/guides/wai-way/agents/polisher.md.example +13 -2
- package/templates/root-consumer/guides/wai-way/blueprints/0_brainstorm.md.example +2 -2
- package/templates/root-consumer/guides/wai-way/blueprints/1_scaffold.md.example +47 -11
- package/templates/root-consumer/guides/wai-way/blueprints/3_compose.md.example +15 -4
- package/templates/root-consumer/guides/wai-way/spec_template.md.example +7 -6
- package/templates/app-payload/.env.example +0 -28
- package/templates/app-payload/README.md.example +0 -233
- package/templates/app-payload/collections/Company.ts.example +0 -125
- package/templates/app-payload/collections/Hero.ts.example +0 -62
- package/templates/app-payload/collections/Media.ts.example +0 -41
- package/templates/app-payload/collections/Products.ts.example +0 -115
- package/templates/app-payload/collections/Services.ts.example +0 -104
- package/templates/app-payload/collections/Testimonials.ts.example +0 -92
- package/templates/app-payload/collections/Users.ts.example +0 -35
- package/templates/app-payload/src/server.ts.example +0 -79
- package/templates/app-payload/tsconfig.json.example +0 -24
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@donotdev/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.15",
|
|
4
4
|
"description": "Command-line interface for DoNotDev Framework",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"type-check": "tsc --noEmit"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@clack/prompts": "^1.0.
|
|
36
|
+
"@clack/prompts": "^1.0.1",
|
|
37
37
|
"commander": "^14.0.3",
|
|
38
38
|
"fast-glob": "^3.3.3"
|
|
39
39
|
},
|
|
@@ -34,7 +34,7 @@ export default function FullPage() {
|
|
|
34
34
|
areas={\`"header header header"
|
|
35
35
|
"main main sidebar"
|
|
36
36
|
"footer footer footer"\`}
|
|
37
|
-
|
|
37
|
+
cols="1fr 3fr 1fr"
|
|
38
38
|
gap="none"
|
|
39
39
|
>
|
|
40
40
|
{/* Children */}
|
|
@@ -45,7 +45,7 @@ export default function FullPage() {
|
|
|
45
45
|
areas={`"header header header"
|
|
46
46
|
"main main sidebar"
|
|
47
47
|
"footer footer footer"`}
|
|
48
|
-
|
|
48
|
+
cols="1fr 3fr 1fr"
|
|
49
49
|
gap="none"
|
|
50
50
|
>
|
|
51
51
|
<GridArea as="header" name="header">
|
|
@@ -140,7 +140,7 @@ export function DemoLayout({
|
|
|
140
140
|
return (
|
|
141
141
|
<Grid
|
|
142
142
|
className="dndev-h-screen dndev-w-full dndev-overflow-hidden"
|
|
143
|
-
|
|
143
|
+
cols={isLaptop ? '280px 1fr' : '1fr'}
|
|
144
144
|
areas={isLaptop ? 'sidebar main' : 'main'}
|
|
145
145
|
gap="none"
|
|
146
146
|
>
|
|
@@ -163,7 +163,7 @@ export function DemoLayout({
|
|
|
163
163
|
<Stack className="dndev-h-full" gap="none">
|
|
164
164
|
{/* Header */}
|
|
165
165
|
<Grid
|
|
166
|
-
|
|
166
|
+
cols="1fr auto 1fr"
|
|
167
167
|
align="center"
|
|
168
168
|
style={{
|
|
169
169
|
padding: 'var(--gap-sm) var(--gap-md)',
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/themes.css — SSOT for essence and theme variables. Default = SaaS. Optional .brutalist / .luxury: set class on <html>.
|
|
3
|
+
*/
|
|
1
4
|
/* src/themes.css */
|
|
2
5
|
|
|
3
6
|
/* ===========================
|
|
@@ -114,18 +117,8 @@
|
|
|
114
117
|
--warning-foreground: #09090b;
|
|
115
118
|
}
|
|
116
119
|
|
|
120
|
+
/* Optional essences: .brutalist, .luxury — see guides/dndev/essences_reference.css. They do not apply by default. */
|
|
121
|
+
|
|
117
122
|
/* ===========================
|
|
118
123
|
CUSTOM THEMES
|
|
119
|
-
Add your brand themes below
|
|
120
124
|
=========================== */
|
|
121
|
-
|
|
122
|
-
/* Example:
|
|
123
|
-
:root.brand {
|
|
124
|
-
--theme-icon: 'Zap';
|
|
125
|
-
--theme-label: 'Brand';
|
|
126
|
-
--theme-is-dark: 0;
|
|
127
|
-
--background: #your-color;
|
|
128
|
-
--foreground: #your-color;
|
|
129
|
-
...
|
|
130
|
-
}
|
|
131
|
-
*/
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# DoNotDev Framework Environment Variables
|
|
3
|
+
# =============================================================================
|
|
4
|
+
# Copy this file to .env and update with your values
|
|
5
|
+
|
|
6
|
+
# =============================================================================
|
|
7
|
+
# DoNotDev License Key
|
|
8
|
+
# =============================================================================
|
|
9
|
+
# Get your license key from: https://donotdev.com/pricing
|
|
10
|
+
# Removes watermark and enables all features
|
|
11
|
+
EXPO_PUBLIC_DONOTDEV_LICENSE_KEY=dndev_your_key_here
|
|
12
|
+
|
|
13
|
+
# =============================================================================
|
|
14
|
+
# Authentication & OAuth Providers
|
|
15
|
+
# =============================================================================
|
|
16
|
+
# Comma-separated list of enabled auth providers
|
|
17
|
+
# Available: github (required for framework), google, facebook, discord, twitter, microsoft, spotify, linkedin, reddit, twitch, yahoo, apple
|
|
18
|
+
# Uncomment when Firebase is configured
|
|
19
|
+
# EXPO_PUBLIC_AUTH_PARTNERS=github
|
|
20
|
+
|
|
21
|
+
# Comma-separated list of enabled OAuth partners for API access
|
|
22
|
+
# Available: google, github, facebook, discord, twitter, microsoft, spotify, linkedin, reddit, twitch, yahoo, apple
|
|
23
|
+
# EXPO_PUBLIC_OAUTH_PARTNERS=google,spotify
|
|
24
|
+
|
|
25
|
+
# Individual OAuth client IDs (only needed for OAuth partners)
|
|
26
|
+
# EXPO_PUBLIC_GOOGLE_CLIENT_ID=your_google_client_id
|
|
27
|
+
# EXPO_PUBLIC_GITHUB_CLIENT_ID=your_github_client_id
|
|
28
|
+
# EXPO_PUBLIC_SPOTIFY_CLIENT_ID=your_spotify_client_id
|
|
29
|
+
|
|
30
|
+
# =============================================================================
|
|
31
|
+
# Firebase Configuration
|
|
32
|
+
# =============================================================================
|
|
33
|
+
# Get these values from your Firebase project settings
|
|
34
|
+
# Run `dndev firebase:setup` to auto-populate, or copy from Firebase Console
|
|
35
|
+
EXPO_PUBLIC_FIREBASE_API_KEY=
|
|
36
|
+
EXPO_PUBLIC_FIREBASE_PROJECT_ID=
|
|
37
|
+
EXPO_PUBLIC_FIREBASE_AUTH_DOMAIN=
|
|
38
|
+
EXPO_PUBLIC_FIREBASE_STORAGE_BUCKET=
|
|
39
|
+
EXPO_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=
|
|
40
|
+
EXPO_PUBLIC_FIREBASE_APP_ID=
|
|
41
|
+
EXPO_PUBLIC_FIREBASE_MEASUREMENT_ID=
|
|
42
|
+
EXPO_PUBLIC_FIREBASE_FUNCTIONS_REGION=
|
|
43
|
+
|
|
44
|
+
# =============================================================================
|
|
45
|
+
# Firebase Emulator (Development only)
|
|
46
|
+
# =============================================================================
|
|
47
|
+
# Set to true to use Firebase emulators instead of production services
|
|
48
|
+
EXPO_PUBLIC_USE_FIREBASE_EMULATOR=false
|
|
49
|
+
EXPO_PUBLIC_FIREBASE_EMULATOR_HOST=localhost
|
|
50
|
+
EXPO_PUBLIC_FIREBASE_EMULATOR_PORT=9099
|
|
51
|
+
EXPO_PUBLIC_FIREBASE_AUTH_EMULATOR_HOST=http://localhost:9099
|
|
52
|
+
EXPO_PUBLIC_FIREBASE_FIRESTORE_EMULATOR_HOST=localhost:8080
|
|
53
|
+
EXPO_PUBLIC_FIREBASE_FUNCTIONS_EMULATOR_PORT=5001
|
|
54
|
+
|
|
55
|
+
# =============================================================================
|
|
56
|
+
# Stripe Configuration (if using billing)
|
|
57
|
+
# =============================================================================
|
|
58
|
+
EXPO_PUBLIC_STRIPE_PUBLISHABLE_KEY=
|
|
59
|
+
|
|
60
|
+
# =============================================================================
|
|
61
|
+
# Sentry (optional - auto-enabled if SENTRY_DSN is set)
|
|
62
|
+
# =============================================================================
|
|
63
|
+
# Framework automatically initializes Sentry if this variable is set
|
|
64
|
+
EXPO_PUBLIC_SENTRY_DSN=
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Expo
|
|
2
|
+
.expo/
|
|
3
|
+
dist/
|
|
4
|
+
web-build/
|
|
5
|
+
|
|
6
|
+
# Native
|
|
7
|
+
*.orig.*
|
|
8
|
+
*.jks
|
|
9
|
+
*.p8
|
|
10
|
+
*.p12
|
|
11
|
+
*.key
|
|
12
|
+
*.mobileprovision
|
|
13
|
+
|
|
14
|
+
# Metro
|
|
15
|
+
.metro-health-check*
|
|
16
|
+
|
|
17
|
+
# Debug
|
|
18
|
+
npm-debug.*
|
|
19
|
+
yarn-debug.*
|
|
20
|
+
yarn-error.*
|
|
21
|
+
|
|
22
|
+
# macOS
|
|
23
|
+
.DS_Store
|
|
24
|
+
*.pem
|
|
25
|
+
|
|
26
|
+
# Local env files
|
|
27
|
+
.env*.local
|
|
28
|
+
|
|
29
|
+
# Typescript
|
|
30
|
+
*.tsbuildinfo
|
|
31
|
+
|
|
32
|
+
# EAS
|
|
33
|
+
.eas/
|
|
34
|
+
|
|
35
|
+
# Temporary files
|
|
36
|
+
*.log
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# {{appName}}
|
|
2
|
+
|
|
3
|
+
Mobile app built with DoNotDev Framework and Expo.
|
|
4
|
+
|
|
5
|
+
## Getting Started
|
|
6
|
+
|
|
7
|
+
### Prerequisites
|
|
8
|
+
|
|
9
|
+
- Node.js 20+ and Bun 1.3+
|
|
10
|
+
- Expo Go app on your phone (for development)
|
|
11
|
+
- Firebase project (run `dndev firebase:setup`)
|
|
12
|
+
|
|
13
|
+
### Development
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Install dependencies
|
|
17
|
+
bun install
|
|
18
|
+
|
|
19
|
+
# Start development server
|
|
20
|
+
bun dev
|
|
21
|
+
# or
|
|
22
|
+
npx expo start
|
|
23
|
+
|
|
24
|
+
# Scan QR code with Expo Go app on your phone
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Building
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# Install EAS CLI
|
|
31
|
+
npm install -g eas-cli
|
|
32
|
+
|
|
33
|
+
# Login
|
|
34
|
+
eas login
|
|
35
|
+
|
|
36
|
+
# Build for iOS
|
|
37
|
+
eas build --platform ios
|
|
38
|
+
|
|
39
|
+
# Build for Android
|
|
40
|
+
eas build --platform android
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Project Structure
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
app/ # Expo Router pages (file-based routing)
|
|
47
|
+
_layout.tsx # Root layout
|
|
48
|
+
index.tsx # Home page (/)
|
|
49
|
+
src/ # Source files (components, config, etc.)
|
|
50
|
+
app.json # Expo configuration
|
|
51
|
+
eas.json # EAS Build configuration
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Documentation
|
|
55
|
+
|
|
56
|
+
- [Expo Router Docs](https://docs.expo.dev/router/introduction/)
|
|
57
|
+
- [DoNotDev Expo Package](../../../docs/development/EXPO_QUICK_START.md)
|
|
58
|
+
- [WAI-WAY Guide](../../guides/wai-way/WAI_WAY_CLI.md.example)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Root Layout
|
|
3
|
+
* @description Root layout component for Expo Router with DoNotDev providers
|
|
4
|
+
*
|
|
5
|
+
* @version 0.0.1
|
|
6
|
+
* @since 0.0.1
|
|
7
|
+
* @author AMBROISE PARK Consulting
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import '../src/config/providers'; // configures CRUD/auth/storage at module load
|
|
11
|
+
import { Stack } from 'expo-router';
|
|
12
|
+
import { ExpoAppProviders } from '@donotdev/expo';
|
|
13
|
+
import { useAuth } from '@donotdev/auth';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Inner layout — rendered inside ExpoAppProviders so useAuth() has context.
|
|
17
|
+
*/
|
|
18
|
+
function AppStack() {
|
|
19
|
+
const { user } = useAuth();
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<Stack
|
|
23
|
+
screenOptions={{
|
|
24
|
+
headerShown: false,
|
|
25
|
+
}}
|
|
26
|
+
/>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Root layout component
|
|
32
|
+
* Wraps the entire app with DoNotDev providers and Expo Router Stack.
|
|
33
|
+
* useAuth() must be called inside ExpoAppProviders, not above it.
|
|
34
|
+
*/
|
|
35
|
+
export default function RootLayout() {
|
|
36
|
+
return (
|
|
37
|
+
<ExpoAppProviders>
|
|
38
|
+
<AppStack />
|
|
39
|
+
</ExpoAppProviders>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview CRUD Form Example
|
|
3
|
+
* @description FormRenderer example page — create / edit (use with expo-router dynamic routes)
|
|
4
|
+
* Suggested file locations: app/[entity]/new.tsx or app/[entity]/[id]/edit.tsx
|
|
5
|
+
*
|
|
6
|
+
* @version 0.0.1
|
|
7
|
+
* @since 0.0.1
|
|
8
|
+
* @author AMBROISE PARK Consulting
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { useState } from 'react';
|
|
12
|
+
import { Alert } from 'react-native';
|
|
13
|
+
import { SafeAreaView } from 'react-native-safe-area-context';
|
|
14
|
+
import { useLocalSearchParams, useRouter } from 'expo-router';
|
|
15
|
+
|
|
16
|
+
import { EntityFormRenderer, Stack, Text } from '@donotdev/expo';
|
|
17
|
+
import { useCrud } from '@donotdev/crud';
|
|
18
|
+
|
|
19
|
+
// import { productEntity } from '../entities/Product';
|
|
20
|
+
const productEntity = null as any; // replace with your entity
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Form page component — create or edit a single record
|
|
24
|
+
*/
|
|
25
|
+
export default function FormPage() {
|
|
26
|
+
const router = useRouter();
|
|
27
|
+
const { id } = useLocalSearchParams<{ id?: string }>();
|
|
28
|
+
const { add, update } = useCrud(productEntity);
|
|
29
|
+
const [submitting, setSubmitting] = useState(false);
|
|
30
|
+
|
|
31
|
+
const handleSubmit = async (data: unknown) => {
|
|
32
|
+
setSubmitting(true);
|
|
33
|
+
try {
|
|
34
|
+
if (id) await update(id as string, data as any);
|
|
35
|
+
else await add(data as any);
|
|
36
|
+
router.back();
|
|
37
|
+
} catch (err) {
|
|
38
|
+
Alert.alert('Error', err instanceof Error ? err.message : 'Failed to save.');
|
|
39
|
+
} finally {
|
|
40
|
+
setSubmitting(false);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<SafeAreaView style={{ flex: 1 }}>
|
|
46
|
+
<Stack spacing={16} style={{ flex: 1, padding: 16 }}>
|
|
47
|
+
<Text level="h2">{id ? 'Edit' : 'Create'}</Text>
|
|
48
|
+
<EntityFormRenderer entity={productEntity} entityId={id} onSubmit={handleSubmit} />
|
|
49
|
+
</Stack>
|
|
50
|
+
</SafeAreaView>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Home Page
|
|
3
|
+
* @description Welcome page for {{appName}}
|
|
4
|
+
*
|
|
5
|
+
* @version 0.0.1
|
|
6
|
+
* @since 0.0.1
|
|
7
|
+
* @author AMBROISE PARK Consulting
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { View, StyleSheet } from 'react-native';
|
|
11
|
+
import { Text, Card, Stack, Button } from '@donotdev/expo';
|
|
12
|
+
import { useNavigate } from '@donotdev/expo';
|
|
13
|
+
import { useAuth } from '@donotdev/auth';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Home page component
|
|
17
|
+
*/
|
|
18
|
+
export default function HomePage() {
|
|
19
|
+
const navigate = useNavigate();
|
|
20
|
+
const { user } = useAuth();
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<View style={styles.container}>
|
|
24
|
+
<Stack spacing={24} style={styles.content}>
|
|
25
|
+
<Text level="h1">Welcome to {{appName}}</Text>
|
|
26
|
+
|
|
27
|
+
<Card title="Getting Started">
|
|
28
|
+
<Text level="body">
|
|
29
|
+
Your Expo app is running! Follow these steps to get started:
|
|
30
|
+
</Text>
|
|
31
|
+
|
|
32
|
+
<Stack spacing={16} style={styles.steps}>
|
|
33
|
+
<View>
|
|
34
|
+
<Text level="h3">1. Backend Setup</Text>
|
|
35
|
+
<Text level="small">
|
|
36
|
+
Run: dndev setup
|
|
37
|
+
</Text>
|
|
38
|
+
</View>
|
|
39
|
+
|
|
40
|
+
<View>
|
|
41
|
+
<Text level="h3">2. Configure Environment</Text>
|
|
42
|
+
<Text level="small">
|
|
43
|
+
Update .env with your Firebase credentials
|
|
44
|
+
</Text>
|
|
45
|
+
</View>
|
|
46
|
+
|
|
47
|
+
<View>
|
|
48
|
+
<Text level="h3">3. Start Building</Text>
|
|
49
|
+
<Text level="small">
|
|
50
|
+
Use WAI-WAY to build your app features
|
|
51
|
+
</Text>
|
|
52
|
+
</View>
|
|
53
|
+
</Stack>
|
|
54
|
+
</Card>
|
|
55
|
+
|
|
56
|
+
{user ? (
|
|
57
|
+
<Card title="You're Signed In">
|
|
58
|
+
<Text level="body">Welcome, {user.email}!</Text>
|
|
59
|
+
<Button onPress={() => navigate('/profile')}>
|
|
60
|
+
Go to Profile
|
|
61
|
+
</Button>
|
|
62
|
+
</Card>
|
|
63
|
+
) : (
|
|
64
|
+
<Card title="Authentication">
|
|
65
|
+
<Text level="body">Sign in to get started</Text>
|
|
66
|
+
<Button onPress={() => navigate('/signin')}>
|
|
67
|
+
Sign In
|
|
68
|
+
</Button>
|
|
69
|
+
</Card>
|
|
70
|
+
)}
|
|
71
|
+
</Stack>
|
|
72
|
+
</View>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const styles = StyleSheet.create({
|
|
77
|
+
container: {
|
|
78
|
+
flex: 1,
|
|
79
|
+
padding: 16,
|
|
80
|
+
},
|
|
81
|
+
content: {
|
|
82
|
+
maxWidth: 600,
|
|
83
|
+
width: '100%',
|
|
84
|
+
alignSelf: 'center',
|
|
85
|
+
},
|
|
86
|
+
steps: {
|
|
87
|
+
marginTop: 16,
|
|
88
|
+
},
|
|
89
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview CRUD List Example
|
|
3
|
+
* @description EntityCardList example page — copy & rename (e.g. products.tsx, customers.tsx)
|
|
4
|
+
*
|
|
5
|
+
* @version 0.0.1
|
|
6
|
+
* @since 0.0.1
|
|
7
|
+
* @author AMBROISE PARK Consulting
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { SafeAreaView } from 'react-native-safe-area-context';
|
|
11
|
+
|
|
12
|
+
import { EntityCardList, Stack, Text } from '@donotdev/expo';
|
|
13
|
+
import { useAuth } from '@donotdev/auth';
|
|
14
|
+
|
|
15
|
+
// import { productEntity } from '../entities/Product';
|
|
16
|
+
const productEntity = null as any; // replace with your entity
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* List page component — shows all records for an entity
|
|
20
|
+
*/
|
|
21
|
+
export default function ListPage() {
|
|
22
|
+
const { user } = useAuth();
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<SafeAreaView style={{ flex: 1 }}>
|
|
26
|
+
<Stack spacing={16} style={{ flex: 1, padding: 16 }}>
|
|
27
|
+
<Text level="h2">Products</Text>
|
|
28
|
+
<EntityCardList entity={productEntity} userRole={user?.role} />
|
|
29
|
+
</Stack>
|
|
30
|
+
</SafeAreaView>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Profile Page
|
|
3
|
+
* @description User profile page for {{appName}}
|
|
4
|
+
*
|
|
5
|
+
* @version 0.0.1
|
|
6
|
+
* @since 0.0.1
|
|
7
|
+
* @author AMBROISE PARK Consulting
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { View, StyleSheet } from 'react-native';
|
|
11
|
+
import { Text, Card, Stack, Button } from '@donotdev/expo';
|
|
12
|
+
import { useAuth } from '@donotdev/auth';
|
|
13
|
+
import { useNavigate } from '@donotdev/expo';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Profile page component
|
|
17
|
+
*/
|
|
18
|
+
export default function ProfilePage() {
|
|
19
|
+
const { user, signOut } = useAuth();
|
|
20
|
+
const navigate = useNavigate();
|
|
21
|
+
|
|
22
|
+
if (!user) {
|
|
23
|
+
navigate('/signin');
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const handleSignOut = async () => {
|
|
28
|
+
await signOut();
|
|
29
|
+
navigate('/');
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<View style={styles.container}>
|
|
34
|
+
<Stack spacing={24} style={styles.content}>
|
|
35
|
+
<Text level="h1">Profile</Text>
|
|
36
|
+
|
|
37
|
+
<Card title="Account Information">
|
|
38
|
+
<Stack spacing={12}>
|
|
39
|
+
<View>
|
|
40
|
+
<Text level="small" style={styles.label}>Email</Text>
|
|
41
|
+
<Text level="body">{user.email}</Text>
|
|
42
|
+
</View>
|
|
43
|
+
|
|
44
|
+
{user.displayName && (
|
|
45
|
+
<View>
|
|
46
|
+
<Text level="small" style={styles.label}>Display Name</Text>
|
|
47
|
+
<Text level="body">{user.displayName}</Text>
|
|
48
|
+
</View>
|
|
49
|
+
)}
|
|
50
|
+
</Stack>
|
|
51
|
+
</Card>
|
|
52
|
+
|
|
53
|
+
<Button onPress={handleSignOut} variant="destructive">
|
|
54
|
+
Sign Out
|
|
55
|
+
</Button>
|
|
56
|
+
</Stack>
|
|
57
|
+
</View>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const styles = StyleSheet.create({
|
|
62
|
+
container: {
|
|
63
|
+
flex: 1,
|
|
64
|
+
backgroundColor: '#fff',
|
|
65
|
+
padding: 16,
|
|
66
|
+
},
|
|
67
|
+
content: {
|
|
68
|
+
maxWidth: 600,
|
|
69
|
+
width: '100%',
|
|
70
|
+
alignSelf: 'center',
|
|
71
|
+
},
|
|
72
|
+
label: {
|
|
73
|
+
opacity: 0.7,
|
|
74
|
+
marginBottom: 4,
|
|
75
|
+
},
|
|
76
|
+
});
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Sign In Page
|
|
3
|
+
* @description Authentication page for {{appName}}
|
|
4
|
+
*
|
|
5
|
+
* @version 0.0.1
|
|
6
|
+
* @since 0.0.1
|
|
7
|
+
* @author AMBROISE PARK Consulting
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { View, StyleSheet } from 'react-native';
|
|
11
|
+
import { Text, Card, Stack, Button } from '@donotdev/expo';
|
|
12
|
+
import { MultipleAuthProviders } from '@donotdev/expo';
|
|
13
|
+
import { useNavigate } from '@donotdev/expo';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Sign in page component
|
|
17
|
+
*/
|
|
18
|
+
export default function SignInPage() {
|
|
19
|
+
const navigate = useNavigate();
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<View style={styles.container}>
|
|
23
|
+
<Stack spacing={24} style={styles.content}>
|
|
24
|
+
<Text level="h1">Sign In</Text>
|
|
25
|
+
|
|
26
|
+
<Card title="Welcome Back">
|
|
27
|
+
<MultipleAuthProviders
|
|
28
|
+
onSuccess={() => {
|
|
29
|
+
navigate('/');
|
|
30
|
+
}}
|
|
31
|
+
/>
|
|
32
|
+
</Card>
|
|
33
|
+
|
|
34
|
+
<Button onPress={() => navigate('/')} variant="outline">
|
|
35
|
+
Back to Home
|
|
36
|
+
</Button>
|
|
37
|
+
</Stack>
|
|
38
|
+
</View>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const styles = StyleSheet.create({
|
|
43
|
+
container: {
|
|
44
|
+
flex: 1,
|
|
45
|
+
backgroundColor: '#fff',
|
|
46
|
+
padding: 16,
|
|
47
|
+
},
|
|
48
|
+
content: {
|
|
49
|
+
maxWidth: 400,
|
|
50
|
+
width: '100%',
|
|
51
|
+
alignSelf: 'center',
|
|
52
|
+
},
|
|
53
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"expo": {
|
|
3
|
+
"name": "{{appName}}",
|
|
4
|
+
"slug": "{{appName}}",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"orientation": "portrait",
|
|
7
|
+
"icon": "./assets/icon.png",
|
|
8
|
+
"userInterfaceStyle": "automatic",
|
|
9
|
+
"splash": {
|
|
10
|
+
"image": "./assets/splash.png",
|
|
11
|
+
"resizeMode": "contain",
|
|
12
|
+
"backgroundColor": "#ffffff"
|
|
13
|
+
},
|
|
14
|
+
"assetBundlePatterns": [
|
|
15
|
+
"**/*"
|
|
16
|
+
],
|
|
17
|
+
"ios": {
|
|
18
|
+
"supportsTablet": true,
|
|
19
|
+
"bundleIdentifier": "com.{{appName}}.{{appName}}"
|
|
20
|
+
},
|
|
21
|
+
"android": {
|
|
22
|
+
"adaptiveIcon": {
|
|
23
|
+
"foregroundImage": "./assets/adaptive-icon.png",
|
|
24
|
+
"backgroundColor": "#ffffff"
|
|
25
|
+
},
|
|
26
|
+
"package": "com.{{appName}}.{{appName}}"
|
|
27
|
+
},
|
|
28
|
+
"web": {
|
|
29
|
+
"favicon": "./assets/favicon.png"
|
|
30
|
+
},
|
|
31
|
+
"scheme": "{{appName}}",
|
|
32
|
+
"plugins": [
|
|
33
|
+
"expo-router"
|
|
34
|
+
],
|
|
35
|
+
"experiments": {
|
|
36
|
+
"typedRoutes": true
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cli": {
|
|
3
|
+
"version": ">= 5.0.0"
|
|
4
|
+
},
|
|
5
|
+
"build": {
|
|
6
|
+
"development": {
|
|
7
|
+
"developmentClient": true,
|
|
8
|
+
"distribution": "internal"
|
|
9
|
+
},
|
|
10
|
+
"preview": {
|
|
11
|
+
"distribution": "internal"
|
|
12
|
+
},
|
|
13
|
+
"production": {
|
|
14
|
+
"autoIncrement": true
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"submit": {
|
|
18
|
+
"production": {}
|
|
19
|
+
}
|
|
20
|
+
}
|