create-pika-minigame 1.0.0 → 1.1.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/bin/cli.js +127 -36
- package/package.json +2 -2
- package/templates/README.md +53 -77
- package/templates/app.json.template +1 -11
- package/templates/metro.config.js +15 -0
package/bin/cli.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const path = require('path');
|
|
5
|
+
const { execSync, spawn } = require('child_process');
|
|
5
6
|
|
|
6
7
|
// Colors for terminal output
|
|
7
8
|
const colors = {
|
|
@@ -35,13 +36,12 @@ ${colors.bright}Options:${colors.reset}
|
|
|
35
36
|
${colors.bright}Examples:${colors.reset}
|
|
36
37
|
npx create-pika-minigame my-awesome-game
|
|
37
38
|
npx create-pika-minigame pronunciation-game
|
|
38
|
-
npx create-pika-minigame quiz-game
|
|
39
39
|
|
|
40
40
|
${colors.bright}After creation:${colors.reset}
|
|
41
41
|
cd <project-name>
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
npm install
|
|
43
|
+
cd ios && pod install && cd ..
|
|
44
|
+
npm run ios # Run on iOS simulator
|
|
45
45
|
`);
|
|
46
46
|
}
|
|
47
47
|
|
|
@@ -50,13 +50,6 @@ function showVersion() {
|
|
|
50
50
|
console.log(pkg.version);
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
function toKebabCase(str) {
|
|
54
|
-
return str
|
|
55
|
-
.replace(/([a-z])([A-Z])/g, '$1-$2')
|
|
56
|
-
.replace(/[\s_]+/g, '-')
|
|
57
|
-
.toLowerCase();
|
|
58
|
-
}
|
|
59
|
-
|
|
60
53
|
function toPascalCase(str) {
|
|
61
54
|
return str
|
|
62
55
|
.split(/[-_\s]+/)
|
|
@@ -64,11 +57,13 @@ function toPascalCase(str) {
|
|
|
64
57
|
.join('');
|
|
65
58
|
}
|
|
66
59
|
|
|
67
|
-
function
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
60
|
+
function runCommand(command, cwd = process.cwd()) {
|
|
61
|
+
try {
|
|
62
|
+
execSync(command, { cwd, stdio: 'inherit' });
|
|
63
|
+
return true;
|
|
64
|
+
} catch (error) {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
72
67
|
}
|
|
73
68
|
|
|
74
69
|
function copyDir(src, dest, replacements = {}) {
|
|
@@ -98,10 +93,56 @@ function copyDir(src, dest, replacements = {}) {
|
|
|
98
93
|
}
|
|
99
94
|
}
|
|
100
95
|
|
|
96
|
+
function patchPodfile(projectDir) {
|
|
97
|
+
const podfilePath = path.join(projectDir, 'ios', 'Podfile');
|
|
98
|
+
|
|
99
|
+
if (!fs.existsSync(podfilePath)) {
|
|
100
|
+
log.warn('Podfile not found, skipping patch');
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
let content = fs.readFileSync(podfilePath, 'utf8');
|
|
105
|
+
|
|
106
|
+
// Add fmt fix to post_install
|
|
107
|
+
const fmtFix = `
|
|
108
|
+
# Fix fmt library compatibility with newer Xcode
|
|
109
|
+
installer.pods_project.targets.each do |target|
|
|
110
|
+
target.build_configurations.each do |config|
|
|
111
|
+
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)']
|
|
112
|
+
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'FMT_USE_CONSTEVAL=0'
|
|
113
|
+
end
|
|
114
|
+
end`;
|
|
115
|
+
|
|
116
|
+
// Insert before the last 'end' in post_install
|
|
117
|
+
if (content.includes('react_native_post_install')) {
|
|
118
|
+
content = content.replace(
|
|
119
|
+
/(react_native_post_install\([^)]+\))/,
|
|
120
|
+
`$1\n${fmtFix}`
|
|
121
|
+
);
|
|
122
|
+
fs.writeFileSync(podfilePath, content);
|
|
123
|
+
log.success('Patched Podfile with fmt fix');
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function createPostInstallScript(projectDir) {
|
|
128
|
+
const scriptContent = `#!/bin/bash
|
|
129
|
+
# Fix fmt consteval issue for Xcode compatibility
|
|
130
|
+
FMT_BASE_H="ios/Pods/fmt/include/fmt/base.h"
|
|
131
|
+
if [ -f "$FMT_BASE_H" ]; then
|
|
132
|
+
sed -i '' 's/__apple_build_version__ < 14000029L/__apple_build_version__/' "$FMT_BASE_H"
|
|
133
|
+
echo "Patched fmt base.h for Xcode compatibility"
|
|
134
|
+
fi
|
|
135
|
+
`;
|
|
136
|
+
|
|
137
|
+
const scriptPath = path.join(projectDir, 'scripts', 'fix-fmt.sh');
|
|
138
|
+
fs.mkdirSync(path.join(projectDir, 'scripts'), { recursive: true });
|
|
139
|
+
fs.writeFileSync(scriptPath, scriptContent);
|
|
140
|
+
fs.chmodSync(scriptPath, '755');
|
|
141
|
+
}
|
|
142
|
+
|
|
101
143
|
function main() {
|
|
102
144
|
const args = process.argv.slice(2);
|
|
103
145
|
|
|
104
|
-
// Handle flags
|
|
105
146
|
if (args.includes('--help') || args.includes('-h') || args.length === 0) {
|
|
106
147
|
showHelp();
|
|
107
148
|
process.exit(0);
|
|
@@ -127,6 +168,7 @@ function main() {
|
|
|
127
168
|
}
|
|
128
169
|
|
|
129
170
|
const targetDir = path.resolve(process.cwd(), projectName);
|
|
171
|
+
const pascalName = toPascalCase(projectName);
|
|
130
172
|
|
|
131
173
|
if (fs.existsSync(targetDir)) {
|
|
132
174
|
log.error(`Directory "${projectName}" already exists.`);
|
|
@@ -143,44 +185,93 @@ ${colors.bright}${colors.cyan}
|
|
|
143
185
|
${colors.reset}
|
|
144
186
|
`);
|
|
145
187
|
|
|
146
|
-
log.info(`Creating a new Pika mini-game
|
|
188
|
+
log.info(`Creating a new Pika mini-game: ${colors.bright}${pascalName}${colors.reset}`);
|
|
147
189
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
190
|
+
// Step 1: Create React Native project
|
|
191
|
+
log.step(1, 'Creating React Native 0.77 project...');
|
|
192
|
+
|
|
193
|
+
const initSuccess = runCommand(
|
|
194
|
+
`npx @react-native-community/cli init ${pascalName} --version 0.77.0 --directory "${projectName}" --skip-install`,
|
|
195
|
+
process.cwd()
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
if (!initSuccess) {
|
|
199
|
+
log.error('Failed to create React Native project');
|
|
200
|
+
process.exit(1);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Step 2: Copy Pika mini-game source files
|
|
204
|
+
log.step(2, 'Adding Pika mini-game template files...');
|
|
205
|
+
|
|
206
|
+
const templatesDir = path.join(__dirname, '..', 'templates');
|
|
207
|
+
const srcTemplateDir = path.join(templatesDir, 'src');
|
|
208
|
+
const devTemplateDir = path.join(templatesDir, 'dev');
|
|
151
209
|
|
|
152
210
|
const replacements = {
|
|
153
211
|
PROJECT_NAME: projectName,
|
|
154
|
-
PROJECT_NAME_KEBAB: kebabName,
|
|
155
212
|
PROJECT_NAME_PASCAL: pascalName,
|
|
156
|
-
PROJECT_NAME_SNAKE: snakeName,
|
|
157
|
-
YEAR: new Date().getFullYear().toString(),
|
|
158
213
|
};
|
|
159
214
|
|
|
160
|
-
|
|
215
|
+
// Copy src folder
|
|
216
|
+
if (fs.existsSync(srcTemplateDir)) {
|
|
217
|
+
copyDir(srcTemplateDir, path.join(targetDir, 'src'), replacements);
|
|
218
|
+
}
|
|
161
219
|
|
|
162
|
-
|
|
163
|
-
|
|
220
|
+
// Copy dev folder
|
|
221
|
+
if (fs.existsSync(devTemplateDir)) {
|
|
222
|
+
copyDir(devTemplateDir, path.join(targetDir, 'dev'), replacements);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Step 3: Patch Podfile for fmt compatibility
|
|
226
|
+
log.step(3, 'Patching for Xcode compatibility...');
|
|
227
|
+
patchPodfile(targetDir);
|
|
228
|
+
createPostInstallScript(targetDir);
|
|
164
229
|
|
|
165
|
-
|
|
230
|
+
// Step 4: Update package.json with additional dependencies
|
|
231
|
+
log.step(4, 'Updating package.json...');
|
|
232
|
+
|
|
233
|
+
const pkgPath = path.join(targetDir, 'package.json');
|
|
234
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
235
|
+
|
|
236
|
+
pkg.dependencies = {
|
|
237
|
+
...pkg.dependencies,
|
|
238
|
+
'react-native-gesture-handler': '~2.20.0',
|
|
239
|
+
'react-native-reanimated': '~3.16.0',
|
|
240
|
+
'react-native-safe-area-context': '4.12.0',
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
pkg.scripts = {
|
|
244
|
+
...pkg.scripts,
|
|
245
|
+
'fix-fmt': './scripts/fix-fmt.sh',
|
|
246
|
+
'postinstall:ios': 'cd ios && pod install && cd .. && npm run fix-fmt',
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
|
|
250
|
+
|
|
251
|
+
log.step(5, 'Project created successfully!');
|
|
166
252
|
|
|
167
253
|
console.log(`
|
|
168
|
-
${colors.green}Success!${colors.reset} Created ${colors.bright}${
|
|
254
|
+
${colors.green}Success!${colors.reset} Created ${colors.bright}${pascalName}${colors.reset} at ${targetDir}
|
|
169
255
|
|
|
170
256
|
${colors.bright}Next steps:${colors.reset}
|
|
171
257
|
|
|
172
258
|
${colors.cyan}cd ${projectName}${colors.reset}
|
|
173
|
-
${colors.cyan}
|
|
259
|
+
${colors.cyan}npm install --legacy-peer-deps${colors.reset}
|
|
260
|
+
${colors.cyan}cd ios && pod install && cd ..${colors.reset}
|
|
261
|
+
${colors.cyan}./scripts/fix-fmt.sh${colors.reset} ${colors.yellow}# Fix Xcode compatibility${colors.reset}
|
|
262
|
+
${colors.cyan}npm run ios${colors.reset}
|
|
174
263
|
|
|
175
264
|
${colors.bright}Available commands:${colors.reset}
|
|
176
265
|
|
|
177
|
-
${colors.cyan}
|
|
178
|
-
${colors.cyan}
|
|
179
|
-
${colors.cyan}
|
|
180
|
-
|
|
266
|
+
${colors.cyan}npm run ios${colors.reset} Run on iOS simulator
|
|
267
|
+
${colors.cyan}npm run android${colors.reset} Run on Android emulator
|
|
268
|
+
${colors.cyan}npm start${colors.reset} Start Metro bundler
|
|
269
|
+
|
|
270
|
+
${colors.bright}Project structure:${colors.reset}
|
|
181
271
|
|
|
182
|
-
|
|
183
|
-
|
|
272
|
+
src/ Game source code (edit this!)
|
|
273
|
+
dev/ Development helpers (MockHost)
|
|
274
|
+
scripts/ Build scripts
|
|
184
275
|
|
|
185
276
|
Happy coding! ${colors.yellow}🎮${colors.reset}
|
|
186
277
|
`);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-pika-minigame",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "CLI to scaffold Pika mini-game projects
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "CLI to scaffold Pika mini-game projects (bare React Native 0.77)",
|
|
5
5
|
"author": "Pika Team",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"bin": {
|
package/templates/README.md
CHANGED
|
@@ -1,25 +1,27 @@
|
|
|
1
1
|
# {{PROJECT_NAME_PASCAL}}
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Pika Mini-Game built with React Native 0.77
|
|
4
4
|
|
|
5
5
|
## Quick Start
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
8
|
# Install dependencies
|
|
9
|
-
|
|
9
|
+
npm install --legacy-peer-deps
|
|
10
10
|
|
|
11
|
-
#
|
|
12
|
-
|
|
11
|
+
# iOS setup
|
|
12
|
+
cd ios && pod install && cd ..
|
|
13
13
|
|
|
14
|
-
#
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
# Fix Xcode compatibility (IMPORTANT!)
|
|
15
|
+
./scripts/fix-fmt.sh
|
|
16
|
+
|
|
17
|
+
# Run
|
|
18
|
+
npm run ios
|
|
17
19
|
```
|
|
18
20
|
|
|
19
21
|
## Project Structure
|
|
20
22
|
|
|
21
23
|
```
|
|
22
|
-
{{
|
|
24
|
+
{{PROJECT_NAME}}/
|
|
23
25
|
├── src/ # Your game source code
|
|
24
26
|
│ ├── App.tsx # Main entry component
|
|
25
27
|
│ ├── tokens.ts # Design system tokens
|
|
@@ -30,26 +32,34 @@ yarn build:android
|
|
|
30
32
|
│ ├── TopBar.tsx
|
|
31
33
|
│ └── Spinner.tsx
|
|
32
34
|
│
|
|
33
|
-
├── dev/ #
|
|
34
|
-
│ ├── index.js # Dev entry point
|
|
35
|
-
│ ├── DevApp.tsx # Wrapper with mock host
|
|
35
|
+
├── dev/ # Development helpers
|
|
36
36
|
│ └── MockHost.ts # Mock native capabilities
|
|
37
37
|
│
|
|
38
|
-
├──
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
├── scripts/ # Build scripts
|
|
39
|
+
│ └── fix-fmt.sh # Xcode compatibility fix
|
|
40
|
+
│
|
|
41
|
+
├── ios/ # iOS native code
|
|
42
|
+
├── android/ # Android native code
|
|
41
43
|
└── package.json
|
|
42
44
|
```
|
|
43
45
|
|
|
44
46
|
## Development
|
|
45
47
|
|
|
46
|
-
### Running
|
|
48
|
+
### Running on iOS
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# Terminal 1: Start Metro
|
|
52
|
+
npm start
|
|
53
|
+
|
|
54
|
+
# Terminal 2: Run app
|
|
55
|
+
npm run ios
|
|
56
|
+
```
|
|
47
57
|
|
|
48
|
-
|
|
58
|
+
### Running on Android
|
|
49
59
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
60
|
+
```bash
|
|
61
|
+
npm run android
|
|
62
|
+
```
|
|
53
63
|
|
|
54
64
|
### Mock Host
|
|
55
65
|
|
|
@@ -58,7 +68,7 @@ Edit `dev/MockHost.ts` to customize mock behavior:
|
|
|
58
68
|
```typescript
|
|
59
69
|
// Return specific scores for testing
|
|
60
70
|
stopAndCheck: async (word) => ({
|
|
61
|
-
totalScore: 95,
|
|
71
|
+
totalScore: 95,
|
|
62
72
|
words: [{ word, score: 95, letters: [...] }]
|
|
63
73
|
})
|
|
64
74
|
|
|
@@ -66,9 +76,6 @@ stopAndCheck: async (word) => ({
|
|
|
66
76
|
startRecording: async () => {
|
|
67
77
|
throw new Error('Microphone permission denied');
|
|
68
78
|
}
|
|
69
|
-
|
|
70
|
-
// Add delays for loading state testing
|
|
71
|
-
await delay(3000);
|
|
72
79
|
```
|
|
73
80
|
|
|
74
81
|
## Design System
|
|
@@ -82,13 +89,13 @@ import { color, semantic, space, radius, typography } from './tokens';
|
|
|
82
89
|
|
|
83
90
|
const styles = StyleSheet.create({
|
|
84
91
|
container: {
|
|
85
|
-
backgroundColor: semantic.bg,
|
|
86
|
-
padding: space[4],
|
|
87
|
-
borderRadius: radius.lg,
|
|
92
|
+
backgroundColor: semantic.bg,
|
|
93
|
+
padding: space[4],
|
|
94
|
+
borderRadius: radius.lg,
|
|
88
95
|
},
|
|
89
96
|
title: {
|
|
90
|
-
color: semantic.text,
|
|
91
|
-
fontSize: typography.title1.size,
|
|
97
|
+
color: semantic.text,
|
|
98
|
+
fontSize: typography.title1.size,
|
|
92
99
|
fontWeight: typography.title1.fontWeight,
|
|
93
100
|
},
|
|
94
101
|
});
|
|
@@ -101,18 +108,9 @@ Pre-built components in `src/components/`:
|
|
|
101
108
|
```typescript
|
|
102
109
|
import { Button, Card, TopBar, Spinner } from './components';
|
|
103
110
|
|
|
104
|
-
// Button variants: primary, secondary, danger, ghost
|
|
105
111
|
<Button label="Start" variant="primary" size="lg" onPress={...} />
|
|
106
|
-
|
|
107
|
-
// Card with press interaction
|
|
108
|
-
<Card onPress={...}>
|
|
109
|
-
<Text>Tap me</Text>
|
|
110
|
-
</Card>
|
|
111
|
-
|
|
112
|
-
// TopBar with back/close buttons
|
|
112
|
+
<Card onPress={...}><Text>Tap me</Text></Card>
|
|
113
113
|
<TopBar left="back" onLeftPress={goBack} title="Game" />
|
|
114
|
-
|
|
115
|
-
// Loading spinner
|
|
116
114
|
<Spinner size="lg" color={color.cyan[400]} />
|
|
117
115
|
```
|
|
118
116
|
|
|
@@ -130,67 +128,45 @@ interface HostBridge {
|
|
|
130
128
|
}
|
|
131
129
|
```
|
|
132
130
|
|
|
133
|
-
Usage
|
|
131
|
+
Usage:
|
|
134
132
|
|
|
135
133
|
```typescript
|
|
136
134
|
const App: React.FC<GameProps> = ({ host }) => {
|
|
137
135
|
const startRecording = async () => {
|
|
138
136
|
await host?.pronunciation.startRecording();
|
|
139
137
|
};
|
|
140
|
-
|
|
141
|
-
const checkPronunciation = async (word: string) => {
|
|
142
|
-
const result = await host?.pronunciation.stopAndCheck(word);
|
|
143
|
-
console.log('Score:', result.totalScore);
|
|
144
|
-
};
|
|
145
138
|
};
|
|
146
139
|
```
|
|
147
140
|
|
|
148
|
-
##
|
|
141
|
+
## Troubleshooting
|
|
149
142
|
|
|
150
|
-
###
|
|
143
|
+
### Xcode fmt errors
|
|
151
144
|
|
|
152
145
|
```bash
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
# Android
|
|
157
|
-
yarn build:android
|
|
146
|
+
./scripts/fix-fmt.sh
|
|
147
|
+
# Then in Xcode: Cmd+Shift+K (Clean), Cmd+R (Run)
|
|
158
148
|
```
|
|
159
149
|
|
|
160
|
-
###
|
|
150
|
+
### Metro port in use
|
|
161
151
|
|
|
162
152
|
```bash
|
|
163
|
-
|
|
153
|
+
lsof -ti:8081 | xargs kill -9
|
|
154
|
+
npm start
|
|
164
155
|
```
|
|
165
156
|
|
|
166
|
-
###
|
|
157
|
+
### Pod install fails
|
|
167
158
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
"deploy:ios": "MF_PUBLIC_PATH=https://your-cdn.com/games/{{PROJECT_NAME_KEBAB}}/ yarn build:ios && <your-deploy-command>"
|
|
174
|
-
}
|
|
175
|
-
}
|
|
159
|
+
```bash
|
|
160
|
+
cd ios
|
|
161
|
+
rm -rf Pods Podfile.lock
|
|
162
|
+
pod install
|
|
163
|
+
cd ..
|
|
176
164
|
```
|
|
177
165
|
|
|
178
166
|
## Integration with Pika App
|
|
179
167
|
|
|
180
|
-
Once
|
|
181
|
-
|
|
182
|
-
```typescript
|
|
183
|
-
// In the host app
|
|
184
|
-
const game = await loadRemote('{{PROJECT_NAME_SNAKE}}/App');
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
## Tips
|
|
188
|
-
|
|
189
|
-
1. **Test on real devices** - Mock host simulates behavior, but test on device for real performance
|
|
190
|
-
2. **Keep it fast** - Mini-games should load instantly; minimize bundle size
|
|
191
|
-
3. **Handle errors** - Always check if `host` is defined before using
|
|
192
|
-
4. **Dark theme** - Default tokens are dark-themed for immersive game feel
|
|
168
|
+
Once ready, this mini-game can be loaded via Module Federation in the main Pika app.
|
|
193
169
|
|
|
194
|
-
|
|
170
|
+
---
|
|
195
171
|
|
|
196
|
-
|
|
172
|
+
Created with `create-pika-minigame` v1.1.0
|
|
@@ -4,11 +4,8 @@
|
|
|
4
4
|
"slug": "{{PROJECT_NAME_KEBAB}}",
|
|
5
5
|
"version": "1.0.0",
|
|
6
6
|
"orientation": "portrait",
|
|
7
|
-
"icon": "./assets/icon.png",
|
|
8
7
|
"userInterfaceStyle": "dark",
|
|
9
8
|
"splash": {
|
|
10
|
-
"image": "./assets/splash.png",
|
|
11
|
-
"resizeMode": "contain",
|
|
12
9
|
"backgroundColor": "#0B0B0B"
|
|
13
10
|
},
|
|
14
11
|
"ios": {
|
|
@@ -16,14 +13,7 @@
|
|
|
16
13
|
"bundleIdentifier": "com.pika.minigame.{{PROJECT_NAME_KEBAB}}"
|
|
17
14
|
},
|
|
18
15
|
"android": {
|
|
19
|
-
"adaptiveIcon": {
|
|
20
|
-
"foregroundImage": "./assets/adaptive-icon.png",
|
|
21
|
-
"backgroundColor": "#0B0B0B"
|
|
22
|
-
},
|
|
23
16
|
"package": "com.pika.minigame.{{PROJECT_NAME_SNAKE}}"
|
|
24
|
-
}
|
|
25
|
-
"plugins": [
|
|
26
|
-
"expo-router"
|
|
27
|
-
]
|
|
17
|
+
}
|
|
28
18
|
}
|
|
29
19
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const { getDefaultConfig } = require('expo/metro-config');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
const projectRoot = __dirname;
|
|
5
|
+
|
|
6
|
+
const config = getDefaultConfig(projectRoot);
|
|
7
|
+
|
|
8
|
+
// Isolate this project - don't resolve from parent directories
|
|
9
|
+
config.watchFolders = [projectRoot];
|
|
10
|
+
config.resolver.nodeModulesPaths = [path.resolve(projectRoot, 'node_modules')];
|
|
11
|
+
|
|
12
|
+
// Disable looking up in parent directories
|
|
13
|
+
config.resolver.disableHierarchicalLookup = true;
|
|
14
|
+
|
|
15
|
+
module.exports = config;
|