create-pika-minigame 1.1.0 → 1.3.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 CHANGED
@@ -103,42 +103,33 @@ function patchPodfile(projectDir) {
103
103
 
104
104
  let content = fs.readFileSync(podfilePath, 'utf8');
105
105
 
106
- // Add fmt fix to post_install
106
+ // Add fmt auto-patch to post_install
107
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'
108
+ # Fix fmt consteval issue with newer Xcode (auto-patch)
109
+ fmt_base_h = File.join(__dir__, 'Pods/fmt/include/fmt/base.h')
110
+ if File.exist?(fmt_base_h)
111
+ content = File.read(fmt_base_h)
112
+ patched = content.gsub(
113
+ /#elif defined\\(__apple_build_version__\\) && __apple_build_version__ < \\d+L/,
114
+ '#elif defined(__apple_build_version__)'
115
+ )
116
+ if content != patched
117
+ File.write(fmt_base_h, patched)
118
+ Pod::UI.puts "Patched fmt/base.h for Xcode compatibility".green
113
119
  end
114
120
  end`;
115
121
 
116
- // Insert before the last 'end' in post_install
122
+ // Insert after react_native_post_install
117
123
  if (content.includes('react_native_post_install')) {
118
124
  content = content.replace(
119
125
  /(react_native_post_install\([^)]+\))/,
120
126
  `$1\n${fmtFix}`
121
127
  );
122
128
  fs.writeFileSync(podfilePath, content);
123
- log.success('Patched Podfile with fmt fix');
129
+ log.success('Patched Podfile with auto fmt fix');
124
130
  }
125
131
  }
126
132
 
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
133
 
143
134
  function main() {
144
135
  const args = process.argv.slice(2);
@@ -225,7 +216,6 @@ ${colors.reset}
225
216
  // Step 3: Patch Podfile for fmt compatibility
226
217
  log.step(3, 'Patching for Xcode compatibility...');
227
218
  patchPodfile(targetDir);
228
- createPostInstallScript(targetDir);
229
219
 
230
220
  // Step 4: Update package.json with additional dependencies
231
221
  log.step(4, 'Updating package.json...');
@@ -240,11 +230,7 @@ ${colors.reset}
240
230
  'react-native-safe-area-context': '4.12.0',
241
231
  };
242
232
 
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
- };
233
+ // No additional scripts needed - fmt fix is automatic in Podfile
248
234
 
249
235
  fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
250
236
 
@@ -258,7 +244,6 @@ ${colors.bright}Next steps:${colors.reset}
258
244
  ${colors.cyan}cd ${projectName}${colors.reset}
259
245
  ${colors.cyan}npm install --legacy-peer-deps${colors.reset}
260
246
  ${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
247
  ${colors.cyan}npm run ios${colors.reset}
263
248
 
264
249
  ${colors.bright}Available commands:${colors.reset}
@@ -271,7 +256,6 @@ ${colors.bright}Project structure:${colors.reset}
271
256
 
272
257
  src/ Game source code (edit this!)
273
258
  dev/ Development helpers (MockHost)
274
- scripts/ Build scripts
275
259
 
276
260
  Happy coding! ${colors.yellow}🎮${colors.reset}
277
261
  `);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-pika-minigame",
3
- "version": "1.1.0",
3
+ "version": "1.3.0",
4
4
  "description": "CLI to scaffold Pika mini-game projects (bare React Native 0.77)",
5
5
  "author": "Pika Team",
6
6
  "license": "MIT",
@@ -8,12 +8,9 @@ Pika Mini-Game built with React Native 0.77
8
8
  # Install dependencies
9
9
  npm install --legacy-peer-deps
10
10
 
11
- # iOS setup
11
+ # iOS setup (auto-patches Xcode compatibility)
12
12
  cd ios && pod install && cd ..
13
13
 
14
- # Fix Xcode compatibility (IMPORTANT!)
15
- ./scripts/fix-fmt.sh
16
-
17
14
  # Run
18
15
  npm run ios
19
16
  ```
@@ -142,8 +139,9 @@ const App: React.FC<GameProps> = ({ host }) => {
142
139
 
143
140
  ### Xcode fmt errors
144
141
 
142
+ Re-run pod install (it auto-patches):
145
143
  ```bash
146
- ./scripts/fix-fmt.sh
144
+ cd ios && rm -rf Pods Podfile.lock && pod install && cd ..
147
145
  # Then in Xcode: Cmd+Shift+K (Clean), Cmd+R (Run)
148
146
  ```
149
147
 
@@ -9,6 +9,19 @@ import { HostBridge, PronunciationResult } from '../src/types';
9
9
 
10
10
  // Simulate recording state
11
11
  let isRecording = false;
12
+ let recordingStartTime = 0;
13
+
14
+ // Configure mock behavior (edit these for testing)
15
+ const MOCK_CONFIG = {
16
+ // Set to a number (0-100) to always return this score, or null for random
17
+ fixedScore: null as number | null,
18
+ // Minimum recording time in ms (like real API)
19
+ minRecordingMs: 700,
20
+ // Simulate network delay range [min, max] ms
21
+ networkDelay: [800, 1300] as [number, number],
22
+ // Chance to throw error (0-1), set > 0 to test error handling
23
+ errorChance: 0,
24
+ };
12
25
 
13
26
  /**
14
27
  * Generate a random score for testing different UI states.
@@ -43,41 +56,56 @@ export const mockHost: HostBridge = {
43
56
  }
44
57
  console.log('[MockHost] 🎤 Recording started...');
45
58
  isRecording = true;
59
+ recordingStartTime = Date.now();
46
60
  // Simulate recording initialization delay
47
61
  await delay(100);
48
62
  },
49
63
 
50
- stopAndCheck: async (targetWord: string): Promise<PronunciationResult> => {
64
+ stopAndCheck: async (targetText: string): Promise<PronunciationResult> => {
51
65
  if (!isRecording) {
52
66
  console.warn('[MockHost] Not recording');
53
67
  throw new Error('Not recording');
54
68
  }
55
69
 
56
- console.log(`[MockHost] 🛑 Recording stopped. Checking: "${targetWord}"`);
70
+ const elapsed = Date.now() - recordingStartTime;
71
+ console.log(`[MockHost] 🛑 Recording stopped (${elapsed}ms). Checking: "${targetText}"`);
57
72
  isRecording = false;
58
73
 
59
- // Simulate processing delay (like API call)
60
- await delay(800 + Math.random() * 500);
74
+ // Check minimum recording time (like real API)
75
+ if (elapsed < MOCK_CONFIG.minRecordingMs) {
76
+ throw new Error('Giữ nút lâu hơn (1–2 giây) rồi nói to, rõ nhé.');
77
+ }
61
78
 
62
- // Generate mock result
63
- const wordScore = randomScore(50, 100);
64
- const letters = generateLetterScores(targetWord);
65
- const totalScore = Math.round(
66
- letters.reduce((sum, l) => sum + l.score, 0) / letters.length
79
+ // Simulate random errors for testing
80
+ if (MOCK_CONFIG.errorChance > 0 && Math.random() < MOCK_CONFIG.errorChance) {
81
+ throw new Error('Chưa nghe rõ, thử lại nhé');
82
+ }
83
+
84
+ // Simulate network delay
85
+ const [minDelay, maxDelay] = MOCK_CONFIG.networkDelay;
86
+ await delay(minDelay + Math.random() * (maxDelay - minDelay));
87
+
88
+ // Split into words (real API does this)
89
+ const wordList = targetText.trim().split(/\s+/);
90
+
91
+ // Generate scores for each word
92
+ const words = wordList.map((word) => {
93
+ const letters = generateLetterScores(word);
94
+ // Use fixed score if configured, otherwise use average of letters
95
+ const wordScore = MOCK_CONFIG.fixedScore ?? Math.round(
96
+ letters.reduce((sum, l) => sum + l.score, 0) / letters.length
97
+ );
98
+ return { word, score: wordScore, letters };
99
+ });
100
+
101
+ // Total score is average of all words
102
+ const totalScore = MOCK_CONFIG.fixedScore ?? Math.round(
103
+ words.reduce((sum, w) => sum + w.score, 0) / words.length
67
104
  );
68
105
 
69
- console.log(`[MockHost] ✅ Score: ${totalScore}`);
70
-
71
- return {
72
- totalScore,
73
- words: [
74
- {
75
- word: targetWord,
76
- score: wordScore,
77
- letters,
78
- },
79
- ],
80
- };
106
+ console.log(`[MockHost] ✅ Score: ${totalScore} (${words.length} word${words.length > 1 ? 's' : ''})`);
107
+
108
+ return { totalScore, words };
81
109
  },
82
110
 
83
111
  cancel: async () => {