create-100x-mobile 0.4.11 → 0.5.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/dist/cli.js +2 -1
- package/dist/commands/new/args.js +25 -0
- package/dist/commands/new/scaffold.js +18 -8
- package/dist/commands/new/steps.js +160 -33
- package/dist/commands/new.js +160 -41
- package/dist/templates/cloudflare/alchemyRun.js +122 -0
- package/dist/templates/cloudflare/cloudflareStorage.js +108 -0
- package/dist/templates/cloudflare/instantCloudflareLib.js +42 -0
- package/dist/templates/cloudflare/worker.js +762 -0
- package/dist/templates/cloudflare/workerMigration.js +18 -0
- package/dist/templates/cloudflare/workerTsconfig.js +20 -0
- package/dist/templates/config/appJson.js +5 -3
- package/dist/templates/config/envExample.js +31 -1
- package/dist/templates/config/packageJson.js +45 -8
- package/dist/templates/config/readme.js +149 -1
- package/dist/templates/config/tsconfig.js +1 -0
- package/dist/templates/instant/magic/authLayout.js +122 -0
- package/dist/templates/instant/magic/rootLayout.js +24 -0
- package/dist/templates/instant/magic/settingsScreen.js +282 -0
- package/dist/templates/instant/magic/signIn.js +346 -0
- package/dist/templates/instant/magic/tabsLayout.js +143 -0
- package/package.json +4 -3
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.workerMigrationTemplate = workerMigrationTemplate;
|
|
4
|
+
function workerMigrationTemplate() {
|
|
5
|
+
return `CREATE TABLE IF NOT EXISTS uploads (
|
|
6
|
+
id TEXT PRIMARY KEY,
|
|
7
|
+
object_key TEXT NOT NULL UNIQUE,
|
|
8
|
+
owner_id TEXT NOT NULL,
|
|
9
|
+
file_name TEXT NOT NULL,
|
|
10
|
+
content_type TEXT NOT NULL,
|
|
11
|
+
size INTEGER NOT NULL,
|
|
12
|
+
created_at TEXT NOT NULL
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
CREATE INDEX IF NOT EXISTS uploads_owner_id_created_at_idx
|
|
16
|
+
ON uploads (owner_id, created_at DESC);
|
|
17
|
+
`;
|
|
18
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.workerTsconfigTemplate = workerTsconfigTemplate;
|
|
4
|
+
function workerTsconfigTemplate() {
|
|
5
|
+
const config = {
|
|
6
|
+
compilerOptions: {
|
|
7
|
+
target: "ES2022",
|
|
8
|
+
module: "ESNext",
|
|
9
|
+
moduleResolution: "Bundler",
|
|
10
|
+
lib: ["ES2022"],
|
|
11
|
+
types: ["@cloudflare/workers-types", "node"],
|
|
12
|
+
strict: true,
|
|
13
|
+
noEmit: true,
|
|
14
|
+
allowImportingTsExtensions: true,
|
|
15
|
+
skipLibCheck: true,
|
|
16
|
+
},
|
|
17
|
+
include: ["src/**/*.ts", "../alchemy.run.ts"],
|
|
18
|
+
};
|
|
19
|
+
return JSON.stringify(config, null, 2) + "\n";
|
|
20
|
+
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.appJsonTemplate = appJsonTemplate;
|
|
4
|
-
function appJsonTemplate(appName, backend) {
|
|
5
|
-
const plugins = backend === "
|
|
6
|
-
|
|
4
|
+
function appJsonTemplate(appName, backend, instantAuthMode = "clerk") {
|
|
5
|
+
const plugins = backend === "instantdb" &&
|
|
6
|
+
(instantAuthMode === "magic-code" ||
|
|
7
|
+
instantAuthMode === "magic-code-cloudflare")
|
|
8
|
+
? ["expo-router", "expo-font"]
|
|
7
9
|
: ["expo-router", "expo-font", "expo-web-browser", "expo-secure-store"];
|
|
8
10
|
const config = {
|
|
9
11
|
expo: {
|
|
@@ -1,8 +1,38 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.envExampleTemplate = envExampleTemplate;
|
|
4
|
-
function envExampleTemplate(backend) {
|
|
4
|
+
function envExampleTemplate(backend, instantAuthMode = "clerk") {
|
|
5
5
|
if (backend === "instantdb") {
|
|
6
|
+
if (instantAuthMode === "magic-code-cloudflare") {
|
|
7
|
+
return `# InstantDB
|
|
8
|
+
EXPO_PUBLIC_INSTANT_APP_ID=
|
|
9
|
+
|
|
10
|
+
# Cloudflare Worker storage API
|
|
11
|
+
# Set this after running: bun run cloudflare:deploy
|
|
12
|
+
EXPO_PUBLIC_STORAGE_WORKER_URL=
|
|
13
|
+
|
|
14
|
+
# Alchemy reads this while deploying Cloudflare storage.
|
|
15
|
+
# INSTANT_ADMIN_TOKEN stays server-side and is bound only to the Worker.
|
|
16
|
+
# You can also use EXPO_PUBLIC_INSTANT_APP_ID as the app id for local development.
|
|
17
|
+
INSTANT_APP_ID=
|
|
18
|
+
INSTANT_ADMIN_TOKEN=
|
|
19
|
+
|
|
20
|
+
# Comma-separated origins allowed by the storage Worker for web builds.
|
|
21
|
+
# Native mobile requests do not use browser CORS, but web uploads do.
|
|
22
|
+
ALLOWED_ORIGINS=http://localhost:3000,http://localhost:8080,http://localhost:8081,http://localhost:19006
|
|
23
|
+
|
|
24
|
+
# Storage Worker policy. Values are read by Alchemy and bound to the Worker.
|
|
25
|
+
MAX_UPLOAD_BYTES=26214400
|
|
26
|
+
USER_STORAGE_LIMIT_BYTES=524288000
|
|
27
|
+
DAILY_UPLOAD_LIMIT=100
|
|
28
|
+
ALLOWED_CONTENT_TYPES=image/jpeg,image/png,image/webp,application/pdf,text/plain
|
|
29
|
+
`;
|
|
30
|
+
}
|
|
31
|
+
if (instantAuthMode === "magic-code") {
|
|
32
|
+
return `# InstantDB
|
|
33
|
+
EXPO_PUBLIC_INSTANT_APP_ID=
|
|
34
|
+
`;
|
|
35
|
+
}
|
|
6
36
|
return `# InstantDB
|
|
7
37
|
EXPO_PUBLIC_INSTANT_APP_ID=
|
|
8
38
|
EXPO_PUBLIC_INSTANT_CLERK_CLIENT_NAME=clerk
|
|
@@ -1,19 +1,54 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.packageJsonTemplate = packageJsonTemplate;
|
|
4
|
-
function
|
|
4
|
+
function isCloudflareInstantAuthMode(instantAuthMode) {
|
|
5
|
+
return instantAuthMode === "magic-code-cloudflare";
|
|
6
|
+
}
|
|
7
|
+
function isMagicCodeInstantAuthMode(instantAuthMode) {
|
|
8
|
+
return (instantAuthMode === "magic-code" ||
|
|
9
|
+
instantAuthMode === "magic-code-cloudflare");
|
|
10
|
+
}
|
|
11
|
+
function packageJsonTemplate(appName, expoVersion = "latest", backend = "convex", instantAuthMode = "clerk") {
|
|
5
12
|
const backendDependencies = backend === "instantdb"
|
|
6
|
-
?
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
? isMagicCodeInstantAuthMode(instantAuthMode)
|
|
14
|
+
? {
|
|
15
|
+
...(isCloudflareInstantAuthMode(instantAuthMode)
|
|
16
|
+
? { "@instantdb/admin": "^1.0.15" }
|
|
17
|
+
: {}),
|
|
18
|
+
"@instantdb/react-native": "^0.20.0",
|
|
19
|
+
"@react-native-async-storage/async-storage": "^2.2.0",
|
|
20
|
+
"@react-native-community/netinfo": "^11.4.1",
|
|
21
|
+
"react-native-get-random-values": "^1.11.0",
|
|
22
|
+
}
|
|
23
|
+
: {
|
|
24
|
+
"@clerk/clerk-expo": "^2.14.24",
|
|
25
|
+
"@instantdb/react-native": "^0.20.0",
|
|
26
|
+
"@react-native-async-storage/async-storage": "^2.2.0",
|
|
27
|
+
"@react-native-community/netinfo": "^11.4.1",
|
|
28
|
+
"react-native-get-random-values": "^1.11.0",
|
|
29
|
+
}
|
|
13
30
|
: {
|
|
14
31
|
"@clerk/clerk-expo": "^2.14.24",
|
|
15
32
|
convex: "^1.26.1",
|
|
16
33
|
};
|
|
34
|
+
const cloudflareScripts = isCloudflareInstantAuthMode(instantAuthMode)
|
|
35
|
+
? {
|
|
36
|
+
"cloudflare:configure": "alchemy configure",
|
|
37
|
+
"cloudflare:login": "alchemy login",
|
|
38
|
+
"cloudflare:dev": "alchemy dev",
|
|
39
|
+
"cloudflare:deploy": "alchemy deploy",
|
|
40
|
+
"cloudflare:destroy": "alchemy destroy",
|
|
41
|
+
"typecheck:worker": "tsc --noEmit -p worker/tsconfig.json",
|
|
42
|
+
}
|
|
43
|
+
: {};
|
|
44
|
+
const cloudflareDevDependencies = isCloudflareInstantAuthMode(instantAuthMode)
|
|
45
|
+
? {
|
|
46
|
+
"@cloudflare/workers-types": "^4.20260424.1",
|
|
47
|
+
"@types/node": "^22.0.0",
|
|
48
|
+
alchemy: "^0.93.0",
|
|
49
|
+
wrangler: "^4.85.0",
|
|
50
|
+
}
|
|
51
|
+
: {};
|
|
17
52
|
const pkg = {
|
|
18
53
|
name: appName,
|
|
19
54
|
main: "expo-router/entry",
|
|
@@ -24,6 +59,7 @@ function packageJsonTemplate(appName, expoVersion = "latest", backend = "convex"
|
|
|
24
59
|
"build:web": "expo export --platform web",
|
|
25
60
|
lint: "expo lint",
|
|
26
61
|
format: "prettier --write .",
|
|
62
|
+
...cloudflareScripts,
|
|
27
63
|
},
|
|
28
64
|
dependencies: {
|
|
29
65
|
"@react-navigation/bottom-tabs": "^7.3.10",
|
|
@@ -39,6 +75,7 @@ function packageJsonTemplate(appName, expoVersion = "latest", backend = "convex"
|
|
|
39
75
|
"eslint-config-expo": "~10.0.0",
|
|
40
76
|
prettier: "^3.4.2",
|
|
41
77
|
typescript: "~5.9.2",
|
|
78
|
+
...cloudflareDevDependencies,
|
|
42
79
|
},
|
|
43
80
|
};
|
|
44
81
|
return JSON.stringify(pkg, null, 2) + "\n";
|
|
@@ -1,8 +1,156 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.readmeTemplate = readmeTemplate;
|
|
4
|
-
function readmeTemplate(projectName, backend) {
|
|
4
|
+
function readmeTemplate(projectName, backend, instantAuthMode = "clerk") {
|
|
5
5
|
if (backend === "instantdb") {
|
|
6
|
+
if (instantAuthMode === "magic-code-cloudflare") {
|
|
7
|
+
return `# ${projectName}
|
|
8
|
+
|
|
9
|
+
A mobile app built with **Expo**, **InstantDB magic code auth**, and **Cloudflare storage managed by Alchemy**.
|
|
10
|
+
|
|
11
|
+
## Tech Stack
|
|
12
|
+
|
|
13
|
+
- **[Expo](https://expo.dev)** — React Native framework
|
|
14
|
+
- **[InstantDB](https://instantdb.com)** — Real-time backend, auth, and sync
|
|
15
|
+
- **[Cloudflare Workers](https://developers.cloudflare.com/workers/)** — Storage API
|
|
16
|
+
- **[Cloudflare R2](https://developers.cloudflare.com/r2/)** — Object storage
|
|
17
|
+
- **[Cloudflare D1](https://developers.cloudflare.com/d1/)** — Upload metadata database
|
|
18
|
+
- **[Alchemy](https://alchemy.run)** — TypeScript infrastructure for Cloudflare resources
|
|
19
|
+
- **[Expo Router](https://docs.expo.dev/router/introduction/)** — File-based navigation
|
|
20
|
+
|
|
21
|
+
## Getting Started
|
|
22
|
+
|
|
23
|
+
\`\`\`bash
|
|
24
|
+
# Install dependencies
|
|
25
|
+
bun install
|
|
26
|
+
|
|
27
|
+
# Add your Instant app id
|
|
28
|
+
cp .env.example .env.local
|
|
29
|
+
|
|
30
|
+
# Start Expo
|
|
31
|
+
bunx expo start
|
|
32
|
+
\`\`\`
|
|
33
|
+
|
|
34
|
+
Set this in \`.env.local\`:
|
|
35
|
+
- \`EXPO_PUBLIC_INSTANT_APP_ID\`
|
|
36
|
+
- \`EXPO_PUBLIC_STORAGE_WORKER_URL\` after Cloudflare deploy
|
|
37
|
+
- \`INSTANT_APP_ID\` for Alchemy Cloudflare deploys; this can match \`EXPO_PUBLIC_INSTANT_APP_ID\`
|
|
38
|
+
- \`INSTANT_ADMIN_TOKEN\` for the Worker-only InstantDB metadata sync
|
|
39
|
+
- \`ALLOWED_ORIGINS\` with your production web origins before deploy
|
|
40
|
+
- \`MAX_UPLOAD_BYTES\`, \`USER_STORAGE_LIMIT_BYTES\`, \`DAILY_UPLOAD_LIMIT\`, and \`ALLOWED_CONTENT_TYPES\` for Worker policy
|
|
41
|
+
|
|
42
|
+
You can create an Instant app id via:
|
|
43
|
+
|
|
44
|
+
\`\`\`bash
|
|
45
|
+
npx instant-cli init-without-files --title ${projectName}
|
|
46
|
+
\`\`\`
|
|
47
|
+
|
|
48
|
+
## Cloudflare Storage
|
|
49
|
+
|
|
50
|
+
This template uses Cloudflare Workers, R2, and D1 only. It does not use Durable Objects, Queues, Workflows, Cron Triggers, or other paid-plan Workers features.
|
|
51
|
+
|
|
52
|
+
\`\`\`bash
|
|
53
|
+
bun run cloudflare:configure
|
|
54
|
+
bun run cloudflare:login
|
|
55
|
+
bun run cloudflare:deploy
|
|
56
|
+
\`\`\`
|
|
57
|
+
|
|
58
|
+
After deploy, copy the printed \`storageWorkerUrl\` into \`.env.local\` as \`EXPO_PUBLIC_STORAGE_WORKER_URL\`.
|
|
59
|
+
|
|
60
|
+
The storage flow is:
|
|
61
|
+
1. App sends the InstantDB refresh token to the Cloudflare Worker as a Bearer token.
|
|
62
|
+
2. Worker verifies the token with \`@instantdb/admin\`.
|
|
63
|
+
3. Worker derives the object owner from the verified InstantDB user.
|
|
64
|
+
4. Worker stores the object in R2.
|
|
65
|
+
5. Worker records metadata in D1.
|
|
66
|
+
6. Worker syncs the canonical metadata to InstantDB with the admin SDK.
|
|
67
|
+
7. App reads the realtime metadata from InstantDB.
|
|
68
|
+
|
|
69
|
+
Production hardening included in the starter:
|
|
70
|
+
- InstantDB token verification for upload, read, download, and delete routes
|
|
71
|
+
- Worker-owned InstantDB metadata writes using \`INSTANT_ADMIN_TOKEN\`
|
|
72
|
+
- Owner checks before reading, downloading, or deleting stored objects
|
|
73
|
+
- Configurable CORS allowlist through \`ALLOWED_ORIGINS\`
|
|
74
|
+
- Configurable content-type allowlist
|
|
75
|
+
- Streaming upload size enforcement
|
|
76
|
+
- Per-user storage quota and daily upload limit backed by D1 metadata
|
|
77
|
+
- Private Worker-served downloads; the R2 bucket is not exposed publicly
|
|
78
|
+
|
|
79
|
+
## Scripts
|
|
80
|
+
|
|
81
|
+
| Command | Description |
|
|
82
|
+
|---------|-------------|
|
|
83
|
+
| \`bun run dev\` | Start Expo dev server |
|
|
84
|
+
| \`bun run lint\` | Run ESLint |
|
|
85
|
+
| \`bun run format\` | Format code with Prettier |
|
|
86
|
+
| \`bun run cloudflare:configure\` | Configure Alchemy Cloudflare credentials |
|
|
87
|
+
| \`bun run cloudflare:login\` | Login to Cloudflare through Alchemy |
|
|
88
|
+
| \`bun run cloudflare:dev\` | Run the Cloudflare Worker locally |
|
|
89
|
+
| \`bun run cloudflare:deploy\` | Deploy Worker, R2, and D1 with Alchemy |
|
|
90
|
+
| \`bun run typecheck:worker\` | Type-check the Worker template |
|
|
91
|
+
|
|
92
|
+
## Learn More
|
|
93
|
+
|
|
94
|
+
- [Expo Docs](https://docs.expo.dev)
|
|
95
|
+
- [InstantDB Docs](https://instantdb.com/docs)
|
|
96
|
+
- [Magic Code Auth](https://instantdb.com/docs/auth/magic-codes)
|
|
97
|
+
- [Alchemy Docs](https://alchemy.run/getting-started)
|
|
98
|
+
- [Cloudflare Workers Docs](https://developers.cloudflare.com/workers/)
|
|
99
|
+
`;
|
|
100
|
+
}
|
|
101
|
+
if (instantAuthMode === "magic-code") {
|
|
102
|
+
return `# ${projectName}
|
|
103
|
+
|
|
104
|
+
A mobile app built with **Expo**, **InstantDB**, and **magic code auth**.
|
|
105
|
+
|
|
106
|
+
## Tech Stack
|
|
107
|
+
|
|
108
|
+
- **[Expo](https://expo.dev)** — React Native framework
|
|
109
|
+
- **[InstantDB](https://instantdb.com)** — Real-time backend, auth, and sync
|
|
110
|
+
- **[Expo Router](https://docs.expo.dev/router/introduction/)** — File-based navigation
|
|
111
|
+
|
|
112
|
+
## Getting Started
|
|
113
|
+
|
|
114
|
+
\`\`\`bash
|
|
115
|
+
# Install dependencies
|
|
116
|
+
bun install
|
|
117
|
+
|
|
118
|
+
# Add your Instant app id
|
|
119
|
+
cp .env.example .env.local
|
|
120
|
+
|
|
121
|
+
# Start Expo
|
|
122
|
+
bunx expo start
|
|
123
|
+
\`\`\`
|
|
124
|
+
|
|
125
|
+
Set this in \`.env.local\`:
|
|
126
|
+
- \`EXPO_PUBLIC_INSTANT_APP_ID\`
|
|
127
|
+
|
|
128
|
+
You can create an Instant app id via:
|
|
129
|
+
|
|
130
|
+
\`\`\`bash
|
|
131
|
+
npx instant-cli init-without-files --title ${projectName}
|
|
132
|
+
\`\`\`
|
|
133
|
+
|
|
134
|
+
InstantDB magic code auth setup:
|
|
135
|
+
1. Enter your email in the sign-in screen.
|
|
136
|
+
2. Instant sends a login code to that address.
|
|
137
|
+
3. Paste the code to sign in.
|
|
138
|
+
|
|
139
|
+
## Scripts
|
|
140
|
+
|
|
141
|
+
| Command | Description |
|
|
142
|
+
|---------|-------------|
|
|
143
|
+
| \`bun run dev\` | Start Expo dev server |
|
|
144
|
+
| \`bun run lint\` | Run ESLint |
|
|
145
|
+
| \`bun run format\` | Format code with Prettier |
|
|
146
|
+
|
|
147
|
+
## Learn More
|
|
148
|
+
|
|
149
|
+
- [Expo Docs](https://docs.expo.dev)
|
|
150
|
+
- [InstantDB Docs](https://instantdb.com/docs)
|
|
151
|
+
- [Magic Code Auth](https://instantdb.com/docs/auth/magic-codes)
|
|
152
|
+
`;
|
|
153
|
+
}
|
|
6
154
|
return `# ${projectName}
|
|
7
155
|
|
|
8
156
|
A mobile app built with **Expo**, **InstantDB**, and **Clerk**.
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.magicAuthLayoutTemplate = magicAuthLayoutTemplate;
|
|
4
|
+
function magicAuthLayoutTemplate() {
|
|
5
|
+
return `import { Redirect, Stack } from "expo-router";
|
|
6
|
+
import { ActivityIndicator, StyleSheet, Text, View } from "react-native";
|
|
7
|
+
import { instantDb } from "@/lib/instant";
|
|
8
|
+
|
|
9
|
+
function SetupRequired() {
|
|
10
|
+
return (
|
|
11
|
+
<View style={styles.setupContainer}>
|
|
12
|
+
<View style={styles.setupCard}>
|
|
13
|
+
<Text style={styles.setupTitle}>Setup Required</Text>
|
|
14
|
+
<Text style={styles.setupText}>
|
|
15
|
+
Add EXPO_PUBLIC_INSTANT_APP_ID to your .env.local file.
|
|
16
|
+
</Text>
|
|
17
|
+
<Text style={styles.setupStep}>
|
|
18
|
+
You can create an app id with:\n
|
|
19
|
+
npx instant-cli init-without-files --title my-app
|
|
20
|
+
</Text>
|
|
21
|
+
</View>
|
|
22
|
+
</View>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function AuthenticatedAuthLayout({
|
|
27
|
+
db,
|
|
28
|
+
}: {
|
|
29
|
+
db: NonNullable<typeof instantDb>;
|
|
30
|
+
}) {
|
|
31
|
+
const { isLoading, user, error } = db.useAuth();
|
|
32
|
+
|
|
33
|
+
if (isLoading) {
|
|
34
|
+
return (
|
|
35
|
+
<View style={styles.loadingContainer}>
|
|
36
|
+
<ActivityIndicator size="large" color="#4B5563" />
|
|
37
|
+
</View>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (error) {
|
|
42
|
+
return (
|
|
43
|
+
<View style={styles.setupContainer}>
|
|
44
|
+
<View style={styles.setupCard}>
|
|
45
|
+
<Text style={styles.setupTitle}>Authentication Error</Text>
|
|
46
|
+
<Text style={styles.setupText}>{error.message}</Text>
|
|
47
|
+
</View>
|
|
48
|
+
</View>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (user) {
|
|
53
|
+
return <Redirect href="/" />;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<Stack screenOptions={{ headerShown: false }}>
|
|
58
|
+
<Stack.Screen name="sign-in" />
|
|
59
|
+
</Stack>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export default function AuthLayout() {
|
|
64
|
+
if (!instantDb) {
|
|
65
|
+
return <SetupRequired />;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return <AuthenticatedAuthLayout db={instantDb} />;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const styles = StyleSheet.create({
|
|
72
|
+
setupContainer: {
|
|
73
|
+
flex: 1,
|
|
74
|
+
backgroundColor: "#f5f5f5",
|
|
75
|
+
justifyContent: "center",
|
|
76
|
+
alignItems: "center",
|
|
77
|
+
padding: 20,
|
|
78
|
+
},
|
|
79
|
+
setupCard: {
|
|
80
|
+
backgroundColor: "#fff",
|
|
81
|
+
borderRadius: 12,
|
|
82
|
+
padding: 24,
|
|
83
|
+
maxWidth: 420,
|
|
84
|
+
width: "100%",
|
|
85
|
+
shadowColor: "#000",
|
|
86
|
+
shadowOffset: { width: 0, height: 2 },
|
|
87
|
+
shadowOpacity: 0.1,
|
|
88
|
+
shadowRadius: 8,
|
|
89
|
+
elevation: 3,
|
|
90
|
+
},
|
|
91
|
+
setupTitle: {
|
|
92
|
+
fontSize: 24,
|
|
93
|
+
fontWeight: "700",
|
|
94
|
+
color: "#333",
|
|
95
|
+
marginBottom: 16,
|
|
96
|
+
textAlign: "center",
|
|
97
|
+
},
|
|
98
|
+
setupText: {
|
|
99
|
+
fontSize: 16,
|
|
100
|
+
color: "#666",
|
|
101
|
+
marginBottom: 12,
|
|
102
|
+
lineHeight: 22,
|
|
103
|
+
textAlign: "center",
|
|
104
|
+
},
|
|
105
|
+
setupStep: {
|
|
106
|
+
fontSize: 14,
|
|
107
|
+
color: "#888",
|
|
108
|
+
marginTop: 16,
|
|
109
|
+
padding: 16,
|
|
110
|
+
backgroundColor: "#f8f9fa",
|
|
111
|
+
borderRadius: 8,
|
|
112
|
+
lineHeight: 20,
|
|
113
|
+
},
|
|
114
|
+
loadingContainer: {
|
|
115
|
+
flex: 1,
|
|
116
|
+
alignItems: "center",
|
|
117
|
+
justifyContent: "center",
|
|
118
|
+
backgroundColor: "#FFFFFF",
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
`;
|
|
122
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.magicRootLayoutTemplate = magicRootLayoutTemplate;
|
|
4
|
+
function magicRootLayoutTemplate() {
|
|
5
|
+
return `import { Stack } from "expo-router";
|
|
6
|
+
import { StatusBar } from "expo-status-bar";
|
|
7
|
+
import { useFrameworkReady } from "@/hooks/useFrameworkReady";
|
|
8
|
+
|
|
9
|
+
export default function RootLayout() {
|
|
10
|
+
useFrameworkReady();
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<>
|
|
14
|
+
<Stack screenOptions={{ headerShown: false }}>
|
|
15
|
+
<Stack.Screen name="(tabs)" />
|
|
16
|
+
<Stack.Screen name="(auth)" />
|
|
17
|
+
<Stack.Screen name="+not-found" />
|
|
18
|
+
</Stack>
|
|
19
|
+
<StatusBar style="auto" />
|
|
20
|
+
</>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
`;
|
|
24
|
+
}
|