- 
                Notifications
    You must be signed in to change notification settings 
- Fork 272
refactor hash by js side #514
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
a31e749
              2e93541
              b5db66c
              15c4710
              0a6118f
              ad4baa4
              684aa50
              8a3fd02
              File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,184 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const crypto = require('crypto'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const fs = require('fs'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const path = require('path'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const PROJECT_ROOT = path.resolve(__dirname, '../../..'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log(`[Bundle Metadata] Project root: ${PROJECT_ROOT}`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| function calculateContentHash(bundleCode) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const hash = crypto.createHash('sha256'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| hash.update(bundleCode, 'utf8'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return hash.digest('hex'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| function generateMetadataInjection(contentHash) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return `// Auto-injected bundle metadata by Metro plugin | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var __BUNDLE_METADATA__ = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| contentHash: '${contentHash}' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| `; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| function generateMetadataComment(contentHash) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return `\n//# BUNDLE_METADATA ${JSON.stringify({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| contentHash | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| })}`; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| function setupSingleHermesc(hermescPath, locationName) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const hermescDir = path.dirname(hermescPath); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const backupHermescPath = path.join(hermescDir, '_hermesc'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const wrapperSourcePath = path.join(__dirname, 'hermesc-wrapper.js'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (fs.existsSync(backupHermescPath)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log(`⏭️ [Hermesc Setup] ${locationName} already configured, skipping...`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!fs.existsSync(hermescPath)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log(`ℹ️ [Hermesc Setup] ${locationName} hermesc not found at: ${hermescPath}`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!fs.existsSync(wrapperSourcePath)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.error(`❌ [Hermesc Setup] Wrapper script not found at: ${wrapperSourcePath}`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log(`🔧 [Hermesc Setup] Setting up hermesc wrapper for ${locationName}...`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fs.renameSync(hermescPath, backupHermescPath); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log(`✅ [Hermesc Setup] ${locationName}: Renamed hermesc -> _hermesc`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const shellScript = `#!/bin/bash | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Hermesc wrapper script - auto-generated | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # This script calls the Node.js wrapper which handles post-processing | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| WRAPPER_SCRIPT="${wrapperSourcePath}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| find_node() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if command -v node >/dev/null 2>&1; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| command -v node | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local NODE_PATHS=( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "/usr/local/bin/node" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "/opt/homebrew/bin/node" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "$HOME/.nvm/versions/node/$(ls -t "$HOME/.nvm/versions/node" 2>/dev/null | head -1)/bin/node" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "/usr/bin/node" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for node_path in "\${NODE_PATHS[@]}"; do | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [ -x "$node_path" ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "$node_path" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| done | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "Error: node executable not found" >&2 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "Please ensure Node.js is installed and accessible" >&2 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| NODE_BIN=$(find_node) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exec "$NODE_BIN" "$WRAPPER_SCRIPT" "$@" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| `; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 
      Comment on lines
    
      +53
     to 
      +87
    
   There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shell wrapper must pass the hermesc directory to the Node wrapper Export HERMESC_DIR so hermesc-wrapper can spawn the correct local _hermesc (Pods vs node_modules, Linux). -    const shellScript = `#!/bin/bash
+    const shellScript = `#!/bin/bash
 # Hermesc wrapper script - auto-generated
 # This script calls the Node.js wrapper which handles post-processing
 
 SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
 WRAPPER_SCRIPT="${wrapperSourcePath}"
@@
 NODE_BIN=$(find_node)
-exec "$NODE_BIN" "$WRAPPER_SCRIPT" "$@"
+export HERMESC_DIR="$SCRIPT_DIR"
+exec "$NODE_BIN" "$WRAPPER_SCRIPT" "$@"
 `;📝 Committable suggestion
 
        Suggested change
       
 🤖 Prompt for AI Agents | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fs.writeFileSync(hermescPath, shellScript, { mode: 0o755 }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log(`✅ [Hermesc Setup] ${locationName}: Created hermesc wrapper shell script`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log(`🎉 [Hermesc Setup] ${locationName} configured successfully!`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log(`📋 [Hermesc Setup] ${locationName} details:`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log(` - Original: ${backupHermescPath}`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log(` - Wrapper: ${hermescPath}`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log(` - Handler: ${wrapperSourcePath}`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.error(`❌ [Hermesc Setup] Failed to setup hermesc wrapper for ${locationName}:`, error); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (fs.existsSync(backupHermescPath) && !fs.existsSync(hermescPath)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fs.renameSync(backupHermescPath, hermescPath); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log(`🔄 [Hermesc Setup] ${locationName}: Rolled back changes`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (rollbackError) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.error(`❌ [Hermesc Setup] ${locationName}: Rollback failed:`, rollbackError); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| function setupHermescWrapper() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const wrapperSourcePath = path.join(__dirname, 'hermesc-wrapper.js'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!fs.existsSync(wrapperSourcePath)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.error(`❌ [Hermesc Setup] Wrapper script not found at: ${wrapperSourcePath}`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fs.chmodSync(wrapperSourcePath, 0o755); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.error('❌ [Hermesc Setup] Failed to set execute permissions on wrapper:', error); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log('🔧 [Hermesc Setup] Starting hermesc wrapper setup...'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const hermescLocations = [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| path: path.join(PROJECT_ROOT, 'node_modules/react-native/sdks/hermesc/osx-bin/hermesc'), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name: 'Node Modules' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| path: path.join(PROJECT_ROOT, 'ios/Pods/hermes-engine/destroot/bin/hermesc'), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name: 'iOS Pods' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let successCount = 0; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let totalProcessed = 0; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (const location of hermescLocations) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const success = setupSingleHermesc(location.path, location.name); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (success) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| successCount++; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| totalProcessed++; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log(`\n📊 [Hermesc Setup] Summary: ${successCount}/${totalProcessed} locations configured successfully`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| function metadataSerializer(entryPoint, preModules, graph, options) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setupHermescWrapper(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const baseJSBundle = require('metro/src/DeltaBundler/Serializers/baseJSBundle'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const bundleToString = require('metro/src/lib/bundleToString'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const bundle = baseJSBundle(entryPoint, preModules, graph, options); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const { code: bundleCode } = bundleToString(bundle); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const contentHash = calculateContentHash(bundleCode); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const metadataInjection = generateMetadataInjection(contentHash); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const metadataComment = generateMetadataComment(contentHash); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const hashFilePath = path.join(PROJECT_ROOT, 'bundle-hash.json'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const hashData = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| contentHash, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| timestamp: new Date().toISOString(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fs.writeFileSync(hashFilePath, JSON.stringify(hashData, null, 2)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log(`✅ [Metro] Saved hash to: ${hashFilePath}`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log(`🔐 [Metro] Hash: ${contentHash.slice(0, 16)}...`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.error('❌ [Metro] Failed to save hash file:', error); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return bundleCode + metadataInjection + metadataComment; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| module.exports = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| metadataSerializer, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,97 @@ | ||||||||||
| #!/usr/bin/env node | ||||||||||
|  | ||||||||||
| const { spawn } = require('child_process'); | ||||||||||
| const path = require('path'); | ||||||||||
| const fs = require('fs'); | ||||||||||
| const PROJECT_ROOT = path.resolve(__dirname, '../../..'); | ||||||||||
| const realHermescPath = path.join(PROJECT_ROOT, 'node_modules/react-native/sdks/hermesc/osx-bin/_hermesc'); | ||||||||||
| const args = process.argv.slice(2); | ||||||||||
| 
      Comment on lines
    
      +7
     to 
      +8
    
   There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Blocker: wrapper hard-codes a single macOS hermesc path; breaks for iOS Pods/Linux and mismatches the wrapped location Derive the real hermesc from the invoking hermesc dir (exported by the shell wrapper) and fall back to known locations. Without this, invocations from Pods or Linux fail or compile with the wrong binary. Apply: -const realHermescPath = path.join(PROJECT_ROOT, 'node_modules/react-native/sdks/hermesc/osx-bin/_hermesc');
+function resolveRealHermescPath() {
+  const candidates = [];
+  if (process.env.HERMESC_DIR) {
+    candidates.push(path.join(process.env.HERMESC_DIR, '_hermesc'));
+  }
+  candidates.push(
+    path.join(PROJECT_ROOT, 'node_modules/react-native/sdks/hermesc/osx-bin/_hermesc'),
+    path.join(PROJECT_ROOT, 'node_modules/react-native/sdks/hermesc/linux64-bin/_hermesc'),
+    path.join(PROJECT_ROOT, 'ios/Pods/hermes-engine/destroot/bin/_hermesc'),
+  );
+  return candidates.find(p => fs.existsSync(p));
+}
+const realHermescPath = resolveRealHermescPath();
+if (!realHermescPath) {
+  console.error('[Hermesc Wrapper] ❌ Could not locate _hermesc (set HERMESC_DIR or install Hermes).');
+  process.exit(1);
+}
+console.log(`[Hermesc Wrapper] Using hermesc: ${realHermescPath}`);
 | ||||||||||
|  | ||||||||||
| console.log(`[Hermesc Wrapper] Executing Hermes compilation...`); | ||||||||||
| console.log(`[Hermesc Wrapper] Args:`, args.join(' ')); | ||||||||||
|  | ||||||||||
| const isCompileOperation = args.includes('-emit-binary'); | ||||||||||
| let outputFile = null; | ||||||||||
|  | ||||||||||
| const outIndex = args.indexOf('-out'); | ||||||||||
| if (outIndex !== -1 && outIndex + 1 < args.length) { | ||||||||||
| outputFile = args[outIndex + 1]; | ||||||||||
| } | ||||||||||
|  | ||||||||||
| const hermesc = spawn(realHermescPath, args, { | ||||||||||
| stdio: 'inherit', | ||||||||||
| env: process.env | ||||||||||
| }); | ||||||||||
|  | ||||||||||
| hermesc.on('error', (error) => { | ||||||||||
| console.error(`[Hermesc Wrapper] ❌ Failed to start hermesc:`, error); | ||||||||||
| process.exit(1); | ||||||||||
| }); | ||||||||||
|  | ||||||||||
| hermesc.on('close', (code) => { | ||||||||||
| console.log(`[Hermesc Wrapper] Hermes compilation completed with code: ${code}`); | ||||||||||
|  | ||||||||||
| if (code === 0 && isCompileOperation && outputFile) { | ||||||||||
| console.log(`[Hermesc Wrapper] 🔄 Post-processing HBC file: ${outputFile}`); | ||||||||||
|  | ||||||||||
| setTimeout(() => { | ||||||||||
| processHBCFile(outputFile); | ||||||||||
| }, 500); | ||||||||||
| 
      Comment on lines
    
      +37
     to 
      +39
    
   There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major Remove the 500ms setTimeout workaround. The arbitrary delay suggests a race condition or file system synchronization issue that should be resolved properly rather than masked with a timeout. This is brittle and may fail under load or on slower systems. Consider one of these approaches: Option 1: Synchronous waiting (if hermesc writes are buffered) -    setTimeout(() => {
-      processHBCFile(outputFile);
-    }, 500);
+    processHBCFile(outputFile);Option 2: Polling with retry (if writes are truly async) -    setTimeout(() => {
-      processHBCFile(outputFile);
-    }, 500);
+    waitForFileStable(outputFile, (err) => {
+      if (err) {
+        console.error(`[Hermesc Wrapper] ❌ Output file not ready:`, err);
+        process.exit(1);
+      }
+      processHBCFile(outputFile);
+    });
+
+function waitForFileStable(filePath, callback, maxRetries = 10, delay = 100) {
+  let lastSize = -1;
+  let retries = 0;
+  
+  const check = () => {
+    try {
+      const stats = fs.statSync(filePath);
+      if (stats.size === lastSize) {
+        callback(null);
+      } else {
+        lastSize = stats.size;
+        retries++;
+        if (retries >= maxRetries) {
+          callback(new Error('File not stable'));
+        } else {
+          setTimeout(check, delay);
+        }
+      }
+    } catch (err) {
+      callback(err);
+    }
+  };
+  check();
+}📝 Committable suggestion
 
        Suggested change
       
 🤖 Prompt for AI Agents | ||||||||||
| } else { | ||||||||||
| process.exit(code); | ||||||||||
| } | ||||||||||
| }); | ||||||||||
|  | ||||||||||
| function processHBCFile(hbcFilePath) { | ||||||||||
| const hashFilePath = path.join(PROJECT_ROOT, 'bundle-hash.json'); | ||||||||||
| There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chainVerify bundle-hash.json is in .gitignore. The  🏁 Script executed: #!/bin/bash
# Verify bundle-hash.json is ignored
if [ -f .gitignore ]; then
  if grep -q "bundle-hash\.json" .gitignore; then
    echo "✅ bundle-hash.json is in .gitignore"
  else
    echo "❌ bundle-hash.json is NOT in .gitignore"
  fi
else
  echo "⚠️  No .gitignore file found at repository root"
fi
# Show .gitignore contents for context
echo -e "\n=== Current .gitignore ==="
cat .gitignore 2>/dev/null || echo "File not found"Length of output: 932 🏁 Script executed: #!/bin/bash
# Check for nested .gitignore files that might ignore bundle-hash.json
echo "=== Searching for nested .gitignore files ==="
find . -name ".gitignore" -type f 2>/dev/null | head -20
# Search for bundle-hash.json references in codebase
echo -e "\n=== References to bundle-hash.json ==="
rg "bundle-hash\.json" --type-list | head -5
rg "bundle-hash" -n -B2 -A2 2>/dev/null || echo "No additional references found"Length of output: 1539 🏁 Script executed: #!/bin/bash
# Examine context around bundle-hash.json usage in hermesc-wrapper.js
echo "=== hermesc-wrapper.js context (lines 40-60) ==="
sed -n '40,60p' git/scripts/hermesc-wrapper.js
echo -e "\n=== bundle-metadata-plugin.js context (lines 160-175) ==="
sed -n '160,175p' git/scripts/bundle-metadata-plugin.jsLength of output: 262 🏁 Script executed: #!/bin/bash
# Examine context around bundle-hash.json usage - corrected paths
echo "=== hermesc-wrapper.js context (lines 40-60) ==="
sed -n '40,60p' scripts/hermesc-wrapper.js 2>/dev/null || echo "File not found at scripts/hermesc-wrapper.js"
echo -e "\n=== bundle-metadata-plugin.js context (lines 160-175) ==="
sed -n '160,175p' scripts/bundle-metadata-plugin.js 2>/dev/null || echo "File not found"
# Also try finding the files
echo -e "\n=== Locating files ==="
find . -name "hermesc-wrapper.js" -o -name "bundle-metadata-plugin.js" 2>/dev/null | head -10Length of output: 1495 Add  The file is a runtime-generated artifact created by  Action: Add  🤖 Prompt for AI Agents | ||||||||||
|  | ||||||||||
| if (!fs.existsSync(hashFilePath)) { | ||||||||||
| console.warn(`[Hermesc Wrapper] ⚠️ Hash file not found: ${hashFilePath}`); | ||||||||||
| console.warn(`[Hermesc Wrapper] Skipping metadata injection.`); | ||||||||||
| process.exit(0); | ||||||||||
| return; | ||||||||||
| } | ||||||||||
|  | ||||||||||
| if (!fs.existsSync(hbcFilePath)) { | ||||||||||
| console.warn(`[Hermesc Wrapper] ⚠️ HBC file not found: ${hbcFilePath}`); | ||||||||||
| console.warn(`[Hermesc Wrapper] Skipping metadata injection.`); | ||||||||||
| process.exit(0); | ||||||||||
| return; | ||||||||||
| } | ||||||||||
|  | ||||||||||
| try { | ||||||||||
| const hashData = JSON.parse(fs.readFileSync(hashFilePath, 'utf8')); | ||||||||||
| const { contentHash } = hashData; | ||||||||||
|  | ||||||||||
| console.log(`[Hermesc Wrapper] 📝 Injecting metadata into HBC...`); | ||||||||||
| console.log(`[Hermesc Wrapper] Hash: ${contentHash.slice(0, 16)}...`); | ||||||||||
|  | ||||||||||
| const hbcBuffer = fs.readFileSync(hbcFilePath); | ||||||||||
|  | ||||||||||
| const metadata = { contentHash }; | ||||||||||
| const metadataJson = JSON.stringify(metadata); | ||||||||||
|  | ||||||||||
| const MAGIC = Buffer.from('RNUPDATE', 'utf8'); | ||||||||||
| const jsonBuffer = Buffer.from(metadataJson, 'utf8'); | ||||||||||
| const lengthBuffer = Buffer.alloc(4); | ||||||||||
| lengthBuffer.writeUInt32LE(jsonBuffer.length); | ||||||||||
|  | ||||||||||
| const finalBuffer = Buffer.concat([ | ||||||||||
| hbcBuffer, | ||||||||||
| MAGIC, | ||||||||||
| jsonBuffer, | ||||||||||
| lengthBuffer, | ||||||||||
| MAGIC, | ||||||||||
| ]); | ||||||||||
|  | ||||||||||
| fs.writeFileSync(hbcFilePath, finalBuffer); | ||||||||||
| 
      Comment on lines
    
      +62
     to 
      +87
    
   There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Make metadata appends idempotent and guard against missing/invalid hash Repeated runs currently re-append RNUPDATE blocks and bloat the HBC. Also, slice() on an undefined hash can throw.    try {
-    const hashData = JSON.parse(fs.readFileSync(hashFilePath, 'utf8'));
-    const { contentHash } = hashData;
+    const hashData = JSON.parse(fs.readFileSync(hashFilePath, 'utf8'));
+    const { contentHash } = hashData || {};
+    if (typeof contentHash !== 'string' || !contentHash.length) {
+      console.warn('[Hermesc Wrapper] ⚠️  Invalid contentHash in bundle-hash.json; skipping.');
+      process.exit(0);
+      return;
+    }
@@
-    const hbcBuffer = fs.readFileSync(hbcFilePath);
+    let hbcBuffer = fs.readFileSync(hbcFilePath);
@@
-    const finalBuffer = Buffer.concat([
-      hbcBuffer,
+    // Strip existing RNUPDATE footer if present (idempotent)
+    function stripRNUpdateFooter(buf, MAGIC) {
+      const m = MAGIC.length;
+      if (buf.length < (m * 2 + 4)) return { base: buf, stripped: false };
+      const endMagicStart = buf.length - m;
+      if (!buf.slice(endMagicStart).equals(MAGIC)) return { base: buf, stripped: false };
+      const lenStart = endMagicStart - 4;
+      if (lenStart < 0) return { base: buf, stripped: false };
+      const jsonLen = buf.readUInt32LE(lenStart);
+      const startMagicStart = lenStart - jsonLen - m;
+      if (startMagicStart < 0) return { base: buf, stripped: false };
+      if (!buf.slice(startMagicStart, startMagicStart + m).equals(MAGIC)) return { base: buf, stripped: false };
+      return { base: buf.slice(0, startMagicStart), stripped: true };
+    }
+    const { base: baseBuffer } = stripRNUpdateFooter(hbcBuffer, MAGIC);
+
+    const finalBuffer = Buffer.concat([
+      baseBuffer,
       MAGIC,
       jsonBuffer,
       lengthBuffer,
       MAGIC,
     ]); | ||||||||||
|  | ||||||||||
| console.log(`[Hermesc Wrapper] ✅ Successfully injected metadata into: ${hbcFilePath}`); | ||||||||||
| console.log(`[Hermesc Wrapper] 🧹 Cleaning up hash file...`); | ||||||||||
|  | ||||||||||
| process.exit(0); | ||||||||||
| 
      Comment on lines
    
      +89
     to 
      +92
    
   There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Misleading log: no cleanup actually happens Either remove the message or implement opt-in cleanup. Recommend removing to avoid confusion. -    console.log(`[Hermesc Wrapper] 🧹 Cleaning up hash file...`);🤖 Prompt for AI Agents | ||||||||||
| } catch (error) { | ||||||||||
| console.error(`[Hermesc Wrapper] ❌ Failed to process HBC file:`, error); | ||||||||||
| process.exit(1); | ||||||||||
| } | ||||||||||
| } | ||||||||||
| 
      Comment on lines
    
      +45
     to 
      +97
    
   There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Race condition: parallel builds will corrupt bundle-hash.json. If multiple hermesc processes compile in parallel (common in multi-platform or multi-architecture builds), they will all attempt to read/write the same  
 Consider one of these solutions: Option 1: Use per-output hash files -  const hashFilePath = path.join(PROJECT_ROOT, 'bundle-hash.json');
+  const hashFilePath = hbcFilePath.replace(/\.hbc$/, '.hash.json');Then update  Option 2: Add process locking Option 3: Pass hash via environment variable -  const hashFilePath = path.join(PROJECT_ROOT, 'bundle-hash.json');
-  if (!fs.existsSync(hashFilePath)) {
-    console.warn(`[Hermesc Wrapper] ⚠️  Hash file not found: ${hashFilePath}`);
+  const contentHash = process.env.RNUPDATE_CONTENT_HASH;
+  if (!contentHash) {
+    console.warn(`[Hermesc Wrapper] ⚠️  RNUPDATE_CONTENT_HASH not set`);
     console.warn(`[Hermesc Wrapper] Skipping metadata injection.`);
     process.exit(0);
-    return;
   }
 | ||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Symlink/permissions-safe swap when wrapping hermesc
Pods binaries can be symlinks; rename may fail or break subsequent installs. Prefer copy+rename fallback and detect symlinks before swapping.
try { console.log(`🔧 [Hermesc Setup] Setting up hermesc wrapper for ${locationName}...`); - fs.renameSync(hermescPath, backupHermescPath); + const stat = fs.lstatSync(hermescPath); + if (stat.isSymbolicLink()) { + // Preserve original target, copy real file as _hermesc and replace link with wrapper + const real = fs.realpathSync(hermescPath); + fs.copyFileSync(real, backupHermescPath); + fs.unlinkSync(hermescPath); + } else { + fs.renameSync(hermescPath, backupHermescPath); + } console.log(`✅ [Hermesc Setup] ${locationName}: Renamed hermesc -> _hermesc`);📝 Committable suggestion
🤖 Prompt for AI Agents