create-pika-minigame 2.6.1 → 2.6.3

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
@@ -291,7 +291,26 @@ ${colors.reset}
291
291
 
292
292
  fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
293
293
 
294
- log.step(5, 'Project created successfully!');
294
+ // Step 5: Update .gitignore for Vercel
295
+ log.step(5, 'Updating .gitignore...');
296
+ const gitignorePath = path.join(targetDir, '.gitignore');
297
+ if (fs.existsSync(gitignorePath)) {
298
+ let gitignore = fs.readFileSync(gitignorePath, 'utf8');
299
+ if (!gitignore.includes('.vercel-prod-url')) {
300
+ gitignore += `
301
+ # Vercel
302
+ .vercel
303
+ .vercel-prod-url
304
+
305
+ # Build outputs
306
+ build/
307
+ `;
308
+ fs.writeFileSync(gitignorePath, gitignore);
309
+ log.success('Updated .gitignore');
310
+ }
311
+ }
312
+
313
+ log.step(6, 'Project created successfully!');
295
314
 
296
315
  console.log(`
297
316
  ${colors.green}Success!${colors.reset} Created ${colors.bright}${pascalName}${colors.reset} at ${targetDir}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-pika-minigame",
3
- "version": "2.6.1",
3
+ "version": "2.6.3",
4
4
  "description": "CLI to scaffold Pika mini-game projects (bare React Native 0.77)",
5
5
  "author": "Pika Team",
6
6
  "license": "MIT",
@@ -13,6 +13,10 @@ let recordingStartTime = 0;
13
13
 
14
14
  // Configure mock behavior (edit these for testing)
15
15
  const MOCK_CONFIG = {
16
+ // Mock access token for API calls (replace with real token for testing)
17
+ accessToken: '__DEV_TOKEN__',
18
+ // Mock user ID
19
+ userId: 'dev-user-123',
16
20
  // Set to a number (0-100) to always return this score, or null for random
17
21
  fixedScore: null as number | null,
18
22
  // Minimum recording time in ms (like real API)
@@ -48,6 +52,16 @@ const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
48
52
  * Edit these to test different scenarios.
49
53
  */
50
54
  export const mockHost: HostBridge = {
55
+ auth: {
56
+ getAccessToken: () => {
57
+ console.log('[MockHost] getAccessToken called');
58
+ return MOCK_CONFIG.accessToken;
59
+ },
60
+ getUserId: () => {
61
+ console.log('[MockHost] getUserId called');
62
+ return MOCK_CONFIG.userId;
63
+ },
64
+ },
51
65
  pronunciation: {
52
66
  startRecording: async () => {
53
67
  if (isRecording) {
@@ -128,6 +142,7 @@ export const mockHost: HostBridge = {
128
142
  * Mock host that always fails - useful for testing error states.
129
143
  */
130
144
  export const mockHostWithErrors: HostBridge = {
145
+ auth: mockHost.auth,
131
146
  pronunciation: {
132
147
  startRecording: async () => {
133
148
  throw new Error('Microphone permission denied');
@@ -143,6 +158,7 @@ export const mockHostWithErrors: HostBridge = {
143
158
  * Mock host with slow responses - useful for testing loading states.
144
159
  */
145
160
  export const mockHostSlow: HostBridge = {
161
+ auth: mockHost.auth,
146
162
  pronunciation: {
147
163
  startRecording: async () => {
148
164
  await delay(2000);
@@ -8,17 +8,16 @@ set -e
8
8
  # Usage:
9
9
  # ./scripts/deploy-vercel.sh [--prod]
10
10
  #
11
- # Environment variables:
12
- # VERCEL_PROD_URL - Production URL (e.g., https://my-game.vercel.app)
13
- # Required for --prod to set correct publicPath
11
+ # First deploy creates a new Vercel project and saves the production URL.
12
+ # Subsequent deploys use the saved URL automatically.
13
+ #
14
+ # To reset and create a new Vercel project:
15
+ # rm -rf .vercel .vercel-prod-url && ./scripts/deploy-vercel.sh --prod
14
16
  #
15
17
  # Prerequisites:
16
18
  # - Vercel CLI: npm i -g vercel
17
19
  # - Logged in: vercel login
18
20
  #
19
- # Example:
20
- # VERCEL_PROD_URL=https://deploy-pink-mu.vercel.app ./scripts/deploy-vercel.sh --prod
21
- #
22
21
  # =============================================================================
23
22
 
24
23
  # Colors
@@ -41,16 +40,23 @@ fi
41
40
 
42
41
  # Parse arguments
43
42
  PROD_FLAG=""
43
+ PROD_URL_FILE=".vercel-prod-url"
44
+
44
45
  if [[ "$1" == "--prod" ]]; then
45
46
  PROD_FLAG="--prod"
46
47
  log_info "Deploying to PRODUCTION"
47
48
 
48
- # Check for VERCEL_PROD_URL
49
+ # Check for saved production URL (project-local)
50
+ if [[ -f "$PROD_URL_FILE" ]]; then
51
+ SAVED_PROD_URL=$(cat "$PROD_URL_FILE" | tr -d '[:space:]')
52
+ if [[ -n "$SAVED_PROD_URL" ]]; then
53
+ log_info "Using saved production URL: $SAVED_PROD_URL"
54
+ VERCEL_PROD_URL="$SAVED_PROD_URL"
55
+ fi
56
+ fi
57
+
49
58
  if [[ -z "$VERCEL_PROD_URL" ]]; then
50
- log_warn "VERCEL_PROD_URL not set. Will try to auto-detect, but may not work correctly."
51
- log_warn "For reliable deploys, set: VERCEL_PROD_URL=https://your-project.vercel.app"
52
- else
53
- log_info "Production URL: $VERCEL_PROD_URL"
59
+ log_info "No saved production URL found. Will detect after first deploy."
54
60
  fi
55
61
  else
56
62
  log_info "Deploying to PREVIEW (add --prod for production)"
@@ -129,9 +135,11 @@ cat > "$BUILD_DIR/index.html" << EOF
129
135
  </html>
130
136
  EOF
131
137
 
132
- # Create vercel.json for proper routing
138
+ # Create vercel.json with project name for proper routing
139
+ # Using project name ensures each game gets its own Vercel project
133
140
  cat > "$BUILD_DIR/vercel.json" << EOF
134
141
  {
142
+ "name": "${PROJECT_NAME}",
135
143
  "headers": [
136
144
  {
137
145
  "source": "/(.*)",
@@ -168,11 +176,12 @@ fi
168
176
  # For production, use VERCEL_PROD_URL if set, otherwise try to auto-detect
169
177
  if [[ "$PROD_FLAG" == "--prod" ]]; then
170
178
  if [[ -n "$VERCEL_PROD_URL" ]]; then
171
- # Use the explicitly set production URL
179
+ # Use the saved/provided production URL
172
180
  DEPLOY_URL="$VERCEL_PROD_URL"
173
- log_info "Using provided production URL: $DEPLOY_URL"
181
+ log_info "Using production URL: $DEPLOY_URL"
174
182
  else
175
- log_info "Trying to detect production alias..."
183
+ log_info "Detecting production alias from Vercel..."
184
+
176
185
  # Try to get alias from the deployed URL
177
186
  PROD_DOMAIN=$(vercel inspect "$DEPLOY_URL" --json 2>/dev/null | node -e "
178
187
  const data = JSON.parse(require('fs').readFileSync('/dev/stdin', 'utf8'));
@@ -186,8 +195,13 @@ if [[ "$PROD_FLAG" == "--prod" ]]; then
186
195
  DEPLOY_URL="https://$PROD_DOMAIN"
187
196
  log_info "Detected production alias: $DEPLOY_URL"
188
197
  else
189
- log_warn "Could not detect production alias, using deployment URL: $DEPLOY_URL"
198
+ # Use the deployment URL as-is (first deploy)
199
+ log_info "Using deployment URL as production URL: $DEPLOY_URL"
190
200
  fi
201
+
202
+ # Save for future deploys
203
+ echo "$DEPLOY_URL" > "$PROD_URL_FILE"
204
+ log_success "Saved production URL to $PROD_URL_FILE"
191
205
  fi
192
206
  fi
193
207
 
@@ -1,8 +1,9 @@
1
- import React, { useState, useCallback } from 'react';
1
+ import React, { useState, useCallback, useEffect } from 'react';
2
2
  import { View, Text, StyleSheet } from 'react-native';
3
3
  import { TopBar, Button, Card } from './components';
4
4
  import { semantic, space, typography, color, radius } from './tokens';
5
5
  import { GameProps, Screen } from './types';
6
+ import { getAccessToken, getUserId } from './hooks/useHostBridge';
6
7
 
7
8
  /**
8
9
  * {{PROJECT_NAME_PASCAL}} - Main App Component
@@ -16,6 +17,18 @@ const App: React.FC<GameProps> = ({ onExit, onGameOver, host }) => {
16
17
  const [screen, setScreen] = useState<Screen>('home');
17
18
  const [score, setScore] = useState(0);
18
19
 
20
+ // Example: Get access token from host (falls back to mock in dev mode)
21
+ const accessToken = getAccessToken(host);
22
+ const userId = getUserId(host);
23
+
24
+ // Example: Use token for API calls
25
+ useEffect(() => {
26
+ if (__DEV__) {
27
+ console.log('[Game] Access Token:', accessToken ? `${accessToken.substring(0, 20)}...` : 'none');
28
+ console.log('[Game] User ID:', userId);
29
+ }
30
+ }, [accessToken, userId]);
31
+
19
32
  const handleStartGame = useCallback(() => {
20
33
  setScreen('game');
21
34
  setScore(0);
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Hook to access host bridge (auth, pronunciation, etc.)
3
+ * Falls back to mock values when running standalone (not in host app)
4
+ */
5
+
6
+ export interface HostAuth {
7
+ getAccessToken: () => string;
8
+ getUserId: () => string | null;
9
+ }
10
+
11
+ export interface HostBridge {
12
+ auth: HostAuth;
13
+ pronunciation?: {
14
+ startRecording: () => Promise<void>;
15
+ stopAndCheck: (target: string) => Promise<any>;
16
+ cancel: () => Promise<void>;
17
+ };
18
+ }
19
+
20
+ export interface GameBridgeProps {
21
+ onExit: () => void;
22
+ onGameOver?: (result: { score: number }) => void;
23
+ host: HostBridge;
24
+ }
25
+
26
+ // Mock token for standalone development - replace with your test token
27
+ const MOCK_ACCESS_TOKEN = '__DEV_TOKEN__';
28
+ const MOCK_USER_ID = 'dev-user-123';
29
+
30
+ /**
31
+ * Create a mock host bridge for standalone development
32
+ */
33
+ export function createMockHostBridge(): HostBridge {
34
+ return {
35
+ auth: {
36
+ getAccessToken: () => MOCK_ACCESS_TOKEN,
37
+ getUserId: () => MOCK_USER_ID,
38
+ },
39
+ pronunciation: {
40
+ startRecording: async () => {
41
+ console.log('[MockHost] startRecording');
42
+ },
43
+ stopAndCheck: async (target: string) => {
44
+ console.log('[MockHost] stopAndCheck:', target);
45
+ return { totalScore: 85, words: [] };
46
+ },
47
+ cancel: async () => {
48
+ console.log('[MockHost] cancel');
49
+ },
50
+ },
51
+ };
52
+ }
53
+
54
+ /**
55
+ * Get access token from host bridge
56
+ * @param host - Host bridge from props (undefined when running standalone)
57
+ * @returns Access token string
58
+ */
59
+ export function getAccessToken(host?: HostBridge): string {
60
+ if (host?.auth?.getAccessToken) {
61
+ return host.auth.getAccessToken();
62
+ }
63
+ // Fallback for standalone development
64
+ console.warn('[useHostBridge] No host bridge, using mock token');
65
+ return MOCK_ACCESS_TOKEN;
66
+ }
67
+
68
+ /**
69
+ * Get user ID from host bridge
70
+ * @param host - Host bridge from props (undefined when running standalone)
71
+ * @returns User ID or null
72
+ */
73
+ export function getUserId(host?: HostBridge): string | null {
74
+ if (host?.auth?.getUserId) {
75
+ return host.auth.getUserId();
76
+ }
77
+ return MOCK_USER_ID;
78
+ }
@@ -18,6 +18,13 @@ export interface PronunciationResult {
18
18
  * In dev mode, this is mocked by MockHost.
19
19
  */
20
20
  export interface HostBridge {
21
+ /** Auth info from host app */
22
+ auth: {
23
+ /** Get current access token (empty if not logged in) */
24
+ getAccessToken: () => string;
25
+ /** Get current user ID (null if not logged in) */
26
+ getUserId: () => string | null;
27
+ };
21
28
  pronunciation: {
22
29
  startRecording: () => Promise<void>;
23
30
  stopAndCheck: (target: string) => Promise<PronunciationResult>;