shakapacker 9.3.0.beta.1 → 9.3.0.beta.2
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.
- checksums.yaml +4 -4
 - data/.github/workflows/eslint-validation.yml +46 -0
 - data/ESLINT_TECHNICAL_DEBT.md +160 -0
 - data/Gemfile.lock +1 -1
 - data/docs/common-upgrades.md +80 -0
 - data/docs/v9_upgrade.md +90 -8
 - data/eslint.config.js +123 -7
 - data/lib/shakapacker/runner.rb +24 -1
 - data/lib/shakapacker/version.rb +1 -1
 - data/package/configExporter/cli.ts +11 -15
 - data/package/configExporter/fileWriter.ts +12 -12
 - data/package-lock.json +2 -2
 - data/package.json +1 -1
 - data/test/configExporter/buildValidator.test.js +31 -28
 - data/test/package/configExporter.test.js +4 -8
 - metadata +4 -2
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: d196f7ff4fd6270c0a4739f62ed17ee202eef663222018dc0b031b7dfb8ec015
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: cb645bae3cb677c7b7f7e35164d99b779dfb92d7d6a975204ac0fcae71b56f40
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: ee177b62cc41abd5fbd460d34f8f8dfe387385152cc683aed5034fe3fd67050043dd3cd2fe32f09f06735ff28a4e71ec6f1f4f945e6ea582dbba06e0883dbb1d
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: dcb85543ec034ede52cf91ed5e36ab5a987e8fb485d54c857fd1762f133252a827d760ac92dd36b9973897e30c3ab1d89f64bacd5761ffe6815b75c990c2c2f9
         
     | 
| 
         @@ -0,0 +1,46 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            name: ESLint Validation
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            on:
         
     | 
| 
      
 4 
     | 
    
         
            +
              pull_request:
         
     | 
| 
      
 5 
     | 
    
         
            +
                paths:
         
     | 
| 
      
 6 
     | 
    
         
            +
                  - "eslint.config.js"
         
     | 
| 
      
 7 
     | 
    
         
            +
                  - "package.json"
         
     | 
| 
      
 8 
     | 
    
         
            +
                  - "package/**/*.js"
         
     | 
| 
      
 9 
     | 
    
         
            +
                  - "test/**/*.js"
         
     | 
| 
      
 10 
     | 
    
         
            +
                  - ".github/workflows/eslint-validation.yml"
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            jobs:
         
     | 
| 
      
 13 
     | 
    
         
            +
              validate:
         
     | 
| 
      
 14 
     | 
    
         
            +
                runs-on: ubuntu-latest
         
     | 
| 
      
 15 
     | 
    
         
            +
                steps:
         
     | 
| 
      
 16 
     | 
    
         
            +
                  - uses: actions/checkout@v4
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  - name: Setup Node
         
     | 
| 
      
 19 
     | 
    
         
            +
                    uses: actions/setup-node@v4
         
     | 
| 
      
 20 
     | 
    
         
            +
                    with:
         
     | 
| 
      
 21 
     | 
    
         
            +
                      node-version: "20"
         
     | 
| 
      
 22 
     | 
    
         
            +
                      cache: "yarn"
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                  - name: Install dependencies
         
     | 
| 
      
 25 
     | 
    
         
            +
                    run: yarn install --frozen-lockfile
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  - name: Validate ESLint config
         
     | 
| 
      
 28 
     | 
    
         
            +
                    run: |
         
     | 
| 
      
 29 
     | 
    
         
            +
                      echo "Validating ESLint configuration..."
         
     | 
| 
      
 30 
     | 
    
         
            +
                      node -e "const config = require('./eslint.config.js'); console.log('✓ Config is valid with', config.length, 'rule sets')"
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                  - name: Run ESLint
         
     | 
| 
      
 33 
     | 
    
         
            +
                    run: |
         
     | 
| 
      
 34 
     | 
    
         
            +
                      echo "Running ESLint on allowed files..."
         
     | 
| 
      
 35 
     | 
    
         
            +
                      yarn eslint . --max-warnings 5
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                  - name: Check warning count
         
     | 
| 
      
 38 
     | 
    
         
            +
                    run: |
         
     | 
| 
      
 39 
     | 
    
         
            +
                      echo "Checking warning count..."
         
     | 
| 
      
 40 
     | 
    
         
            +
                      WARNING_COUNT=$(yarn eslint . 2>&1 | grep -E "^✖.*warning" | grep -oE "[0-9]+ warning" | cut -d' ' -f1)
         
     | 
| 
      
 41 
     | 
    
         
            +
                      echo "Current warning count: $WARNING_COUNT"
         
     | 
| 
      
 42 
     | 
    
         
            +
                      if [ "$WARNING_COUNT" -gt "5" ]; then
         
     | 
| 
      
 43 
     | 
    
         
            +
                        echo "❌ Too many warnings: $WARNING_COUNT (max allowed: 5)"
         
     | 
| 
      
 44 
     | 
    
         
            +
                        exit 1
         
     | 
| 
      
 45 
     | 
    
         
            +
                      fi
         
     | 
| 
      
 46 
     | 
    
         
            +
                      echo "✓ Warning count is acceptable"
         
     | 
| 
         @@ -0,0 +1,160 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # ESLint Technical Debt Documentation
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            This document tracks the ESLint errors currently suppressed in the codebase and outlines the plan to address them.
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            ## Current Approach
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            **As of 2025-10-14**: All TypeScript files in `package/` directory are temporarily excluded from linting via the ignore pattern `package/**/*.ts` in `eslint.config.js`. This allows the project to adopt ESLint configuration without requiring immediate fixes to all existing issues.
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            **Latest Update**: Fixed all `class-methods-use-this` violations by converting FileWriter methods to static methods (4 violations resolved).
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            ## Current Linting Status
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            **Files currently linted** (`test/**/*.js`, `scripts/*.js`):
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            - ✅ **0 errors** (CI passing)
         
     | 
| 
      
 16 
     | 
    
         
            +
            - ⚠️ **3 warnings** (acceptable, won't block CI)
         
     | 
| 
      
 17 
     | 
    
         
            +
              - 1x unused eslint-disable directive in `scripts/remove-use-strict.js`
         
     | 
| 
      
 18 
     | 
    
         
            +
              - 2x jest/no-disabled-tests in test files (expected for conditional test skipping)
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            **TypeScript files** (currently ignored via `package/**/*.ts`):
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            - **Estimated suppressed errors: ~172** (from sample analysis)
         
     | 
| 
      
 23 
     | 
    
         
            +
              - TypeScript type-safety issues: ~114 (66%)
         
     | 
| 
      
 24 
     | 
    
         
            +
              - Style/convention issues: ~58 (34%)
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
            **Target**: Reduce suppressed errors by 50% within Q1 2025
         
     | 
| 
      
 27 
     | 
    
         
            +
            **Last Updated**: 2025-10-14
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
            ## Priority Matrix
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
            | Category                             | Impact | Effort | Priority | Count |
         
     | 
| 
      
 32 
     | 
    
         
            +
            | ------------------------------------ | ------ | ------ | -------- | ----- |
         
     | 
| 
      
 33 
     | 
    
         
            +
            | `@typescript-eslint/no-explicit-any` | High   | High   | P1       | 22    |
         
     | 
| 
      
 34 
     | 
    
         
            +
            | `@typescript-eslint/no-unsafe-*`     | High   | High   | P1       | 85    |
         
     | 
| 
      
 35 
     | 
    
         
            +
            | `config.ts` type safety              | High   | Medium | P1       | 7     |
         
     | 
| 
      
 36 
     | 
    
         
            +
            | `no-param-reassign`                  | Medium | Low    | P2       | 7     |
         
     | 
| 
      
 37 
     | 
    
         
            +
            | `class-methods-use-this`             | Low    | Low    | P3       | 0     |
         
     | 
| 
      
 38 
     | 
    
         
            +
            | `no-nested-ternary`                  | Low    | Low    | P3       | 3     |
         
     | 
| 
      
 39 
     | 
    
         
            +
            | `import/prefer-default-export`       | Low    | Medium | P3       | 9     |
         
     | 
| 
      
 40 
     | 
    
         
            +
            | `global-require`                     | Medium | High   | P2       | 3     |
         
     | 
| 
      
 41 
     | 
    
         
            +
            | Other style issues                   | Low    | Low    | P3       | 31    |
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
            ## Categories of Suppressed Errors
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
            ### 1. TypeScript Type Safety (Requires Major Refactoring)
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
            #### `@typescript-eslint/no-explicit-any` (22 instances)
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
            **Files affected:** `configExporter/`, `config.ts`, `utils/`
         
     | 
| 
      
 50 
     | 
    
         
            +
            **Why suppressed:** These require careful type definitions and potentially breaking API changes
         
     | 
| 
      
 51 
     | 
    
         
            +
            **Fix strategy:** Create proper type definitions for configuration objects and YAML parsing
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
            #### `@typescript-eslint/no-unsafe-*` (85 instances)
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
            - `no-unsafe-assignment`: 47 instances
         
     | 
| 
      
 56 
     | 
    
         
            +
            - `no-unsafe-member-access`: 20 instances
         
     | 
| 
      
 57 
     | 
    
         
            +
            - `no-unsafe-call`: 8 instances
         
     | 
| 
      
 58 
     | 
    
         
            +
            - `no-unsafe-return`: 8 instances
         
     | 
| 
      
 59 
     | 
    
         
            +
            - `no-unsafe-argument`: 7 instances
         
     | 
| 
      
 60 
     | 
    
         
            +
              **Why suppressed:** These stem from `any` types and dynamic property access
         
     | 
| 
      
 61 
     | 
    
         
            +
              **Fix strategy:** Requires comprehensive type refactoring alongside `no-explicit-any` fixes
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
            ### 2. Module System (Potential Breaking Changes)
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
            #### `global-require` (3 instances)
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
            **Files affected:** `configExporter/cli.ts`
         
     | 
| 
      
 68 
     | 
    
         
            +
            **Why suppressed:** Dynamic require calls are needed for conditional module loading
         
     | 
| 
      
 69 
     | 
    
         
            +
            **Fix strategy:** Would require converting to ES modules with dynamic imports
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
            #### `import/prefer-default-export` (9 instances)
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
            **Files affected:** Multiple single-export modules
         
     | 
| 
      
 74 
     | 
    
         
            +
            **Why suppressed:** Adding default exports alongside named exports could break consumers
         
     | 
| 
      
 75 
     | 
    
         
            +
            **Fix strategy:** Can be fixed non-breaking by adding default exports that match named exports
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
            ### 3. Code Style (Can Be Fixed)
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
            #### `class-methods-use-this` (0 instances)
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
            ✅ **FIXED** - All FileWriter methods that didn't use instance state have been converted to static methods
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
            #### `no-nested-ternary` (3 instances)
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
            **Fix strategy:** Refactor to if-else statements
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
            #### `no-param-reassign` (7 instances)
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
            **Files affected:** `configExporter/cli.ts`
         
     | 
| 
      
 90 
     | 
    
         
            +
            **Why suppressed:** Common pattern for option objects
         
     | 
| 
      
 91 
     | 
    
         
            +
            **Fix strategy:** Create new objects instead of mutating parameters
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
            #### `no-underscore-dangle` (2 instances)
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
            **Fix strategy:** Rename variables or add exceptions for Node internals
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
            ### 4. Control Flow
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
            #### `no-await-in-loop` (1 instance)
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
            **Fix strategy:** Use `Promise.all()` for parallel execution
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
            #### `no-continue` (1 instance)
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
            **Fix strategy:** Refactor loop logic
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
      
 107 
     | 
    
         
            +
            ## Recommended Approach
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
            ### Phase 1: Non-Breaking Fixes
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
            ✅ Completed:
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
            - Fixed `no-use-before-define` by reordering functions
         
     | 
| 
      
 114 
     | 
    
         
            +
            - Fixed redundant type constituents with `string & {}` pattern
         
     | 
| 
      
 115 
     | 
    
         
            +
            - Added proper type annotations for `requireOrError` calls
         
     | 
| 
      
 116 
     | 
    
         
            +
            - Configured appropriate global rule disables (`no-console`, `no-restricted-syntax`)
         
     | 
| 
      
 117 
     | 
    
         
            +
            - ✅ **Fixed `class-methods-use-this`** - Converted FileWriter methods to static methods
         
     | 
| 
      
 118 
     | 
    
         
            +
             
     | 
| 
      
 119 
     | 
    
         
            +
            🔧 Could still fix (low risk):
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
      
 121 
     | 
    
         
            +
            - `no-nested-ternary` - Refactor conditionals
         
     | 
| 
      
 122 
     | 
    
         
            +
            - `no-useless-escape` - Remove unnecessary escapes
         
     | 
| 
      
 123 
     | 
    
         
            +
            - Unused variables - Remove or prefix with underscore
         
     | 
| 
      
 124 
     | 
    
         
            +
             
     | 
| 
      
 125 
     | 
    
         
            +
            ### Phase 2: Follow-up PRs (Non-Breaking)
         
     | 
| 
      
 126 
     | 
    
         
            +
             
     | 
| 
      
 127 
     | 
    
         
            +
            - Systematic type safety improvements file by file
         
     | 
| 
      
 128 
     | 
    
         
            +
            - Add explicit type definitions for configuration objects
         
     | 
| 
      
 129 
     | 
    
         
            +
            - Replace `any` with `unknown` where possible
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
            ### Phase 3: Future Major Version (Breaking Changes)
         
     | 
| 
      
 132 
     | 
    
         
            +
             
     | 
| 
      
 133 
     | 
    
         
            +
            - Convert `export =` to `export default`
         
     | 
| 
      
 134 
     | 
    
         
            +
            - Convert `require()` to ES6 imports
         
     | 
| 
      
 135 
     | 
    
         
            +
            - Full TypeScript strict mode compliance
         
     | 
| 
      
 136 
     | 
    
         
            +
            - Provide codemod for automatic migration
         
     | 
| 
      
 137 
     | 
    
         
            +
             
     | 
| 
      
 138 
     | 
    
         
            +
            ## Configuration Strategy
         
     | 
| 
      
 139 
     | 
    
         
            +
             
     | 
| 
      
 140 
     | 
    
         
            +
            The current approach uses file-specific overrides to suppress errors in affected files while maintaining strict checking elsewhere. This allows:
         
     | 
| 
      
 141 
     | 
    
         
            +
             
     | 
| 
      
 142 
     | 
    
         
            +
            1. New code to follow strict standards
         
     | 
| 
      
 143 
     | 
    
         
            +
            2. Gradual refactoring of existing code
         
     | 
| 
      
 144 
     | 
    
         
            +
            3. Clear visibility of technical debt
         
     | 
| 
      
 145 
     | 
    
         
            +
             
     | 
| 
      
 146 
     | 
    
         
            +
            ## Issue Tracking
         
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
      
 148 
     | 
    
         
            +
            GitHub issues should be created for each category:
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
            1. [ ] Issue: Type safety refactoring for configExporter module
         
     | 
| 
      
 151 
     | 
    
         
            +
            2. [ ] Issue: Type safety for dynamic config loading
         
     | 
| 
      
 152 
     | 
    
         
            +
            3. [ ] Issue: Convert class methods to static where appropriate
         
     | 
| 
      
 153 
     | 
    
         
            +
            4. [ ] Issue: Module system modernization (ES6 modules)
         
     | 
| 
      
 154 
     | 
    
         
            +
            5. [ ] Issue: Create codemod for breaking changes migration
         
     | 
| 
      
 155 
     | 
    
         
            +
             
     | 
| 
      
 156 
     | 
    
         
            +
            ## Notes
         
     | 
| 
      
 157 
     | 
    
         
            +
             
     | 
| 
      
 158 
     | 
    
         
            +
            - All suppressed errors are documented in `eslint.config.js` with TODO comments
         
     | 
| 
      
 159 
     | 
    
         
            +
            - The suppressions are scoped to specific files to prevent spreading technical debt
         
     | 
| 
      
 160 
     | 
    
         
            +
            - New code should not add to these suppressions
         
     | 
    
        data/Gemfile.lock
    CHANGED
    
    
    
        data/docs/common-upgrades.md
    CHANGED
    
    | 
         @@ -6,6 +6,7 @@ This document provides step-by-step instructions for the most common upgrade sce 
     | 
|
| 
       6 
6 
     | 
    
         | 
| 
       7 
7 
     | 
    
         
             
            ## Table of Contents
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
      
 9 
     | 
    
         
            +
            - [Upgrading Shakapacker](#upgrading-shakapacker)
         
     | 
| 
       9 
10 
     | 
    
         
             
            - [Migrating Package Managers](#migrating-package-managers)
         
     | 
| 
       10 
11 
     | 
    
         
             
              - [Yarn to npm](#yarn-to-npm)
         
     | 
| 
       11 
12 
     | 
    
         
             
              - [npm to Yarn](#npm-to-yarn)
         
     | 
| 
         @@ -15,6 +16,85 @@ This document provides step-by-step instructions for the most common upgrade sce 
     | 
|
| 
       15 
16 
     | 
    
         | 
| 
       16 
17 
     | 
    
         
             
            ---
         
     | 
| 
       17 
18 
     | 
    
         | 
| 
      
 19 
     | 
    
         
            +
            ## Upgrading Shakapacker
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
            > **⚠️ Important:** Shakapacker is both a Ruby gem AND an npm package. **You must update BOTH** when upgrading.
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            Shakapacker consists of two components that must be updated together:
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            1. **Ruby gem** - provides Rails integration and view helpers
         
     | 
| 
      
 26 
     | 
    
         
            +
            2. **npm package** - provides webpack/rspack configuration and build tools
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
            ### Upgrade Steps
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
            #### 1. Update `Gemfile`
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 33 
     | 
    
         
            +
            gem "shakapacker", "9.3.0"  # or the version you want to upgrade to
         
     | 
| 
      
 34 
     | 
    
         
            +
            ```
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
            **Pre-release versions:** Ruby gems use dot notation (e.g., `"9.3.0.beta.1"`)
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
            #### 2. Update `package.json`
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
            ```json
         
     | 
| 
      
 41 
     | 
    
         
            +
            {
         
     | 
| 
      
 42 
     | 
    
         
            +
              "dependencies": {
         
     | 
| 
      
 43 
     | 
    
         
            +
                "shakapacker": "9.3.0"
         
     | 
| 
      
 44 
     | 
    
         
            +
              }
         
     | 
| 
      
 45 
     | 
    
         
            +
            }
         
     | 
| 
      
 46 
     | 
    
         
            +
            ```
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
            **Pre-release versions:** npm uses hyphen notation (e.g., `"9.3.0-beta.1"`)
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
            #### 3. Run bundler and package manager
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
            ```bash
         
     | 
| 
      
 53 
     | 
    
         
            +
            bundle update shakapacker
         
     | 
| 
      
 54 
     | 
    
         
            +
            yarn install  # or npm install, pnpm install, bun install
         
     | 
| 
      
 55 
     | 
    
         
            +
            ```
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
            #### 4. Test your build
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
            ```bash
         
     | 
| 
      
 60 
     | 
    
         
            +
            bin/shakapacker
         
     | 
| 
      
 61 
     | 
    
         
            +
            bin/shakapacker-dev-server
         
     | 
| 
      
 62 
     | 
    
         
            +
            ```
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
            ### Why Both Must Be Updated
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
            - **Mismatched versions can cause build failures** - The Ruby gem expects specific configuration formats from the npm package
         
     | 
| 
      
 67 
     | 
    
         
            +
            - **Feature compatibility** - New features in the gem require corresponding npm package updates
         
     | 
| 
      
 68 
     | 
    
         
            +
            - **Bug fixes** - Fixes often span both Ruby and JavaScript code
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
            ### Version Format Differences
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
            Note that pre-release versions use different formats:
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
            | Component    | Stable Version | Pre-release Version |
         
     | 
| 
      
 75 
     | 
    
         
            +
            | ------------ | -------------- | ------------------- |
         
     | 
| 
      
 76 
     | 
    
         
            +
            | Gemfile      | `"9.3.0"`      | `"9.3.0.beta.1"`    |
         
     | 
| 
      
 77 
     | 
    
         
            +
            | package.json | `"9.3.0"`      | `"9.3.0-beta.1"`    |
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
            ### Finding the Latest Version
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
            - **Ruby gem:** Check [RubyGems.org](https://rubygems.org/gems/shakapacker)
         
     | 
| 
      
 82 
     | 
    
         
            +
            - **npm package:** Check [npmjs.com](https://www.npmjs.com/package/shakapacker)
         
     | 
| 
      
 83 
     | 
    
         
            +
            - **Releases:** See [GitHub Releases](https://github.com/shakacode/shakapacker/releases)
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
            ### Major Version Upgrades
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
            For major version upgrades, always consult the version-specific upgrade guides for breaking changes and new features:
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
            - [V9 Upgrade Guide](./v9_upgrade.md) - Upgrading from v8 to v9 (includes CSS Modules changes, SWC defaults, and more)
         
     | 
| 
      
 90 
     | 
    
         
            +
            - [V8 Upgrade Guide](./v8_upgrade.md) - Upgrading from v7 to v8
         
     | 
| 
      
 91 
     | 
    
         
            +
            - [V7 Upgrade Guide](./v7_upgrade.md) - Upgrading from v6 to v7
         
     | 
| 
      
 92 
     | 
    
         
            +
            - [V6 Upgrade Guide](./v6_upgrade.md) - Upgrading from v5 to v6
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
            > **💡 Note:** Major version upgrades may include breaking changes. The steps above cover the basic gem/package updates that apply to all versions, but you should always review the version-specific guide for additional migration steps.
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
            ---
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
       18 
98 
     | 
    
         
             
            ## Migrating Package Managers
         
     | 
| 
       19 
99 
     | 
    
         | 
| 
       20 
100 
     | 
    
         
             
            ### Yarn to npm
         
     | 
    
        data/docs/v9_upgrade.md
    CHANGED
    
    | 
         @@ -4,6 +4,15 @@ This guide outlines new features, breaking changes, and migration steps for upgr 
     | 
|
| 
       4 
4 
     | 
    
         | 
| 
       5 
5 
     | 
    
         
             
            **📖 For detailed configuration options, see the [Configuration Guide](./configuration.md)**
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
      
 7 
     | 
    
         
            +
            > **⚠️ Important:** Shakapacker is both a Ruby gem AND an npm package. **You must update BOTH**:
         
     | 
| 
      
 8 
     | 
    
         
            +
            >
         
     | 
| 
      
 9 
     | 
    
         
            +
            > - Update the version in `Gemfile`
         
     | 
| 
      
 10 
     | 
    
         
            +
            > - Update the version in `package.json`
         
     | 
| 
      
 11 
     | 
    
         
            +
            > - Run `bundle update shakapacker`
         
     | 
| 
      
 12 
     | 
    
         
            +
            > - Run your package manager install command (`yarn install`, `npm install`, or `pnpm install`)
         
     | 
| 
      
 13 
     | 
    
         
            +
            >
         
     | 
| 
      
 14 
     | 
    
         
            +
            > See [Migration Steps](#migration-steps) below for detailed instructions including version format differences and testing.
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
       7 
16 
     | 
    
         
             
            > **⚠️ Important for v9.1.0 Users:** If you're upgrading to v9.1.0 or later, please note the [SWC Configuration Breaking Change](#swc-loose-mode-breaking-change-v910) below. This affects users who previously configured SWC in v9.0.0.
         
     | 
| 
       8 
17 
     | 
    
         | 
| 
       9 
18 
     | 
    
         
             
            ## New Features
         
     | 
| 
         @@ -264,15 +273,49 @@ You won't get warnings about missing Babel, Rspack, or esbuild packages. 
     | 
|
| 
       264 
273 
     | 
    
         | 
| 
       265 
274 
     | 
    
         
             
            ## Migration Steps
         
     | 
| 
       266 
275 
     | 
    
         | 
| 
       267 
     | 
    
         
            -
             
     | 
| 
      
 276 
     | 
    
         
            +
            > **💡 Tip:** For general upgrade instructions applicable to all Shakapacker versions, see [Upgrading Shakapacker](./common-upgrades.md#upgrading-shakapacker) in the Common Upgrades guide.
         
     | 
| 
      
 277 
     | 
    
         
            +
             
     | 
| 
      
 278 
     | 
    
         
            +
            ### Step 1: Update Gemfile
         
     | 
| 
      
 279 
     | 
    
         
            +
             
     | 
| 
      
 280 
     | 
    
         
            +
            Update the shakapacker version in your `Gemfile`:
         
     | 
| 
      
 281 
     | 
    
         
            +
             
     | 
| 
      
 282 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 283 
     | 
    
         
            +
            # Gemfile
         
     | 
| 
      
 284 
     | 
    
         
            +
            gem "shakapacker", "9.3.0"  # or latest version
         
     | 
| 
      
 285 
     | 
    
         
            +
            ```
         
     | 
| 
      
 286 
     | 
    
         
            +
             
     | 
| 
      
 287 
     | 
    
         
            +
            **Note:** Ruby gems use dot notation for pre-release versions (e.g., `9.3.0.beta.1`), while npm uses hyphen notation (e.g., `9.3.0-beta.1`). See [Version Format Differences](#version-format-differences) below.
         
     | 
| 
      
 288 
     | 
    
         
            +
             
     | 
| 
      
 289 
     | 
    
         
            +
            ### Step 2: Update package.json
         
     | 
| 
      
 290 
     | 
    
         
            +
             
     | 
| 
      
 291 
     | 
    
         
            +
            Update the shakapacker version in your `package.json`:
         
     | 
| 
      
 292 
     | 
    
         
            +
             
     | 
| 
      
 293 
     | 
    
         
            +
            ```json
         
     | 
| 
      
 294 
     | 
    
         
            +
            {
         
     | 
| 
      
 295 
     | 
    
         
            +
              "dependencies": {
         
     | 
| 
      
 296 
     | 
    
         
            +
                "shakapacker": "9.3.0"
         
     | 
| 
      
 297 
     | 
    
         
            +
              }
         
     | 
| 
      
 298 
     | 
    
         
            +
            }
         
     | 
| 
      
 299 
     | 
    
         
            +
            ```
         
     | 
| 
      
 300 
     | 
    
         
            +
             
     | 
| 
      
 301 
     | 
    
         
            +
            **Note:** For pre-release versions, npm uses hyphen notation (e.g., `"shakapacker": "9.3.0-beta.1"`).
         
     | 
| 
      
 302 
     | 
    
         
            +
             
     | 
| 
      
 303 
     | 
    
         
            +
            ### Step 3: Install Updates
         
     | 
| 
      
 304 
     | 
    
         
            +
             
     | 
| 
      
 305 
     | 
    
         
            +
            Run both bundler and your package manager:
         
     | 
| 
       268 
306 
     | 
    
         | 
| 
       269 
307 
     | 
    
         
             
            ```bash
         
     | 
| 
       270 
     | 
    
         
            -
             
     | 
| 
       271 
     | 
    
         
            -
             
     | 
| 
       272 
     | 
    
         
            -
             
     | 
| 
      
 308 
     | 
    
         
            +
            # Update Ruby gem
         
     | 
| 
      
 309 
     | 
    
         
            +
            bundle update shakapacker
         
     | 
| 
      
 310 
     | 
    
         
            +
             
     | 
| 
      
 311 
     | 
    
         
            +
            # Update npm package (choose one based on your package manager)
         
     | 
| 
      
 312 
     | 
    
         
            +
            yarn install      # if using Yarn
         
     | 
| 
      
 313 
     | 
    
         
            +
            npm install       # if using npm
         
     | 
| 
      
 314 
     | 
    
         
            +
            pnpm install      # if using pnpm
         
     | 
| 
      
 315 
     | 
    
         
            +
            bun install       # if using Bun
         
     | 
| 
       273 
316 
     | 
    
         
             
            ```
         
     | 
| 
       274 
317 
     | 
    
         | 
| 
       275 
     | 
    
         
            -
            ### Step  
     | 
| 
      
 318 
     | 
    
         
            +
            ### Step 4: Update CSS Module Imports
         
     | 
| 
       276 
319 
     | 
    
         | 
| 
       277 
320 
     | 
    
         
             
            #### For each CSS module import:
         
     | 
| 
       278 
321 
     | 
    
         | 
| 
         @@ -299,7 +342,7 @@ declare module "*.module.css" { 
     | 
|
| 
       299 
342 
     | 
    
         
             
            }
         
     | 
| 
       300 
343 
     | 
    
         
             
            ```
         
     | 
| 
       301 
344 
     | 
    
         | 
| 
       302 
     | 
    
         
            -
            ### Step  
     | 
| 
      
 345 
     | 
    
         
            +
            ### Step 5: Handle Kebab-Case Class Names
         
     | 
| 
       303 
346 
     | 
    
         | 
| 
       304 
347 
     | 
    
         
             
            v9 automatically converts kebab-case to camelCase with `exportLocalsConvention: 'camelCaseOnly'`:
         
     | 
| 
       305 
348 
     | 
    
         | 
| 
         @@ -340,7 +383,7 @@ const buttonClass = styles['my-button']; 
     | 
|
| 
       340 
383 
     | 
    
         | 
| 
       341 
384 
     | 
    
         
             
            **Note:** With `'camelCaseOnly'` (default) or `'dashesOnly'`, only one version is exported. If you need both the original and camelCase versions, you would need to use `'camelCase'` instead, but this requires `namedExport: false` (v8 behavior). See the [CSS Modules Export Mode documentation](./css-modules-export-mode.md) for details on reverting to v8 behavior.
         
     | 
| 
       342 
385 
     | 
    
         | 
| 
       343 
     | 
    
         
            -
            ### Step  
     | 
| 
      
 386 
     | 
    
         
            +
            ### Step 6: Update Configuration Files
         
     | 
| 
       344 
387 
     | 
    
         | 
| 
       345 
388 
     | 
    
         
             
            If you have `webpack_loader` in your configuration:
         
     | 
| 
       346 
389 
     | 
    
         | 
| 
         @@ -353,7 +396,7 @@ If you have `webpack_loader` in your configuration: 
     | 
|
| 
       353 
396 
     | 
    
         
             
            javascript_transpiler: "babel"
         
     | 
| 
       354 
397 
     | 
    
         
             
            ```
         
     | 
| 
       355 
398 
     | 
    
         | 
| 
       356 
     | 
    
         
            -
            ### Step  
     | 
| 
      
 399 
     | 
    
         
            +
            ### Step 7: Run Tests
         
     | 
| 
       357 
400 
     | 
    
         | 
| 
       358 
401 
     | 
    
         
             
            ```bash
         
     | 
| 
       359 
402 
     | 
    
         
             
            # Run your test suite
         
     | 
| 
         @@ -366,6 +409,45 @@ bin/shakapacker 
     | 
|
| 
       366 
409 
     | 
    
         
             
            bin/shakapacker-dev-server
         
     | 
| 
       367 
410 
     | 
    
         
             
            ```
         
     | 
| 
       368 
411 
     | 
    
         | 
| 
      
 412 
     | 
    
         
            +
            ## Version Format Differences
         
     | 
| 
      
 413 
     | 
    
         
            +
             
     | 
| 
      
 414 
     | 
    
         
            +
            Shakapacker version numbers differ between the Ruby gem and npm package for pre-release versions:
         
     | 
| 
      
 415 
     | 
    
         
            +
             
     | 
| 
      
 416 
     | 
    
         
            +
            | Version Type | Ruby Gem (Gemfile) | npm Package (package.json) |
         
     | 
| 
      
 417 
     | 
    
         
            +
            | ------------ | ------------------ | -------------------------- |
         
     | 
| 
      
 418 
     | 
    
         
            +
            | Stable       | `"9.3.0"`          | `"9.3.0"`                  |
         
     | 
| 
      
 419 
     | 
    
         
            +
            | Pre-release  | `"9.3.0.beta.1"`   | `"9.3.0-beta.1"`           |
         
     | 
| 
      
 420 
     | 
    
         
            +
             
     | 
| 
      
 421 
     | 
    
         
            +
            **Examples:**
         
     | 
| 
      
 422 
     | 
    
         
            +
             
     | 
| 
      
 423 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 424 
     | 
    
         
            +
            # Gemfile - uses dots for pre-release versions
         
     | 
| 
      
 425 
     | 
    
         
            +
            gem "shakapacker", "9.3.0"         # stable
         
     | 
| 
      
 426 
     | 
    
         
            +
            gem "shakapacker", "9.3.0.beta.1"  # pre-release
         
     | 
| 
      
 427 
     | 
    
         
            +
            ```
         
     | 
| 
      
 428 
     | 
    
         
            +
             
     | 
| 
      
 429 
     | 
    
         
            +
            Stable version in package.json:
         
     | 
| 
      
 430 
     | 
    
         
            +
             
     | 
| 
      
 431 
     | 
    
         
            +
            ```json
         
     | 
| 
      
 432 
     | 
    
         
            +
            {
         
     | 
| 
      
 433 
     | 
    
         
            +
              "dependencies": {
         
     | 
| 
      
 434 
     | 
    
         
            +
                "shakapacker": "9.3.0"
         
     | 
| 
      
 435 
     | 
    
         
            +
              }
         
     | 
| 
      
 436 
     | 
    
         
            +
            }
         
     | 
| 
      
 437 
     | 
    
         
            +
            ```
         
     | 
| 
      
 438 
     | 
    
         
            +
             
     | 
| 
      
 439 
     | 
    
         
            +
            Pre-release version in package.json:
         
     | 
| 
      
 440 
     | 
    
         
            +
             
     | 
| 
      
 441 
     | 
    
         
            +
            ```json
         
     | 
| 
      
 442 
     | 
    
         
            +
            {
         
     | 
| 
      
 443 
     | 
    
         
            +
              "dependencies": {
         
     | 
| 
      
 444 
     | 
    
         
            +
                "shakapacker": "9.3.0-beta.1"
         
     | 
| 
      
 445 
     | 
    
         
            +
              }
         
     | 
| 
      
 446 
     | 
    
         
            +
            }
         
     | 
| 
      
 447 
     | 
    
         
            +
            ```
         
     | 
| 
      
 448 
     | 
    
         
            +
             
     | 
| 
      
 449 
     | 
    
         
            +
            This is due to different versioning conventions between RubyGems (which uses dots) and npm (which follows semantic versioning with hyphens for pre-release identifiers).
         
     | 
| 
      
 450 
     | 
    
         
            +
             
     | 
| 
       369 
451 
     | 
    
         
             
            ## Troubleshooting
         
     | 
| 
       370 
452 
     | 
    
         | 
| 
       371 
453 
     | 
    
         
             
            ### CSS Classes Not Applying
         
     | 
    
        data/eslint.config.js
    CHANGED
    
    | 
         @@ -14,11 +14,16 @@ module.exports = [ 
     | 
|
| 
       14 
14 
     | 
    
         
             
              // Global ignores (replaces .eslintignore)
         
     | 
| 
       15 
15 
     | 
    
         
             
              {
         
     | 
| 
       16 
16 
     | 
    
         
             
                ignores: [
         
     | 
| 
       17 
     | 
    
         
            -
                  "lib/**",
         
     | 
| 
       18 
     | 
    
         
            -
                  "**/node_modules/**",
         
     | 
| 
       19 
     | 
    
         
            -
                  "vendor/**",
         
     | 
| 
       20 
     | 
    
         
            -
                  "spec/**",
         
     | 
| 
       21 
     | 
    
         
            -
                  "package 
     | 
| 
      
 17 
     | 
    
         
            +
                  "lib/**", // Ruby files, not JavaScript
         
     | 
| 
      
 18 
     | 
    
         
            +
                  "**/node_modules/**", // Third-party dependencies
         
     | 
| 
      
 19 
     | 
    
         
            +
                  "vendor/**", // Vendored dependencies
         
     | 
| 
      
 20 
     | 
    
         
            +
                  "spec/**", // Ruby specs, not JavaScript
         
     | 
| 
      
 21 
     | 
    
         
            +
                  "package/**/*.js", // Generated/compiled JavaScript from TypeScript
         
     | 
| 
      
 22 
     | 
    
         
            +
                  "package/**/*.d.ts", // Generated TypeScript declaration files
         
     | 
| 
      
 23 
     | 
    
         
            +
                  // Temporarily ignore TypeScript files until technical debt is resolved
         
     | 
| 
      
 24 
     | 
    
         
            +
                  // See ESLINT_TECHNICAL_DEBT.md for tracking
         
     | 
| 
      
 25 
     | 
    
         
            +
                  // TODO: Remove this once ESLint issues are fixed (tracked in #723)
         
     | 
| 
      
 26 
     | 
    
         
            +
                  "package/**/*.ts"
         
     | 
| 
       22 
27 
     | 
    
         
             
                ]
         
     | 
| 
       23 
28 
     | 
    
         
             
              },
         
     | 
| 
       24 
29 
     | 
    
         | 
| 
         @@ -52,7 +57,11 @@ module.exports = [ 
     | 
|
| 
       52 
57 
     | 
    
         
             
                  "import/no-extraneous-dependencies": "off",
         
     | 
| 
       53 
58 
     | 
    
         
             
                  // TypeScript handles extensions, not needed for JS imports
         
     | 
| 
       54 
59 
     | 
    
         
             
                  "import/extensions": "off",
         
     | 
| 
       55 
     | 
    
         
            -
                  indent: ["error", 2]
         
     | 
| 
      
 60 
     | 
    
         
            +
                  indent: ["error", 2],
         
     | 
| 
      
 61 
     | 
    
         
            +
                  // Allow for...of loops - modern JS syntax, won't pollute client code
         
     | 
| 
      
 62 
     | 
    
         
            +
                  "no-restricted-syntax": "off",
         
     | 
| 
      
 63 
     | 
    
         
            +
                  // Allow console statements - used for debugging/logging throughout
         
     | 
| 
      
 64 
     | 
    
         
            +
                  "no-console": "off"
         
     | 
| 
       56 
65 
     | 
    
         
             
                },
         
     | 
| 
       57 
66 
     | 
    
         
             
                settings: {
         
     | 
| 
       58 
67 
     | 
    
         
             
                  react: {
         
     | 
| 
         @@ -131,7 +140,114 @@ module.exports = [ 
     | 
|
| 
       131 
140 
     | 
    
         
             
                  // Strict: no 'any' types allowed - use 'unknown' or specific types instead
         
     | 
| 
       132 
141 
     | 
    
         
             
                  "@typescript-eslint/no-explicit-any": "error",
         
     | 
| 
       133 
142 
     | 
    
         
             
                  // Allow implicit return types - TypeScript can infer them
         
     | 
| 
       134 
     | 
    
         
            -
                  "@typescript-eslint/explicit-module-boundary-types": "off"
         
     | 
| 
      
 143 
     | 
    
         
            +
                  "@typescript-eslint/explicit-module-boundary-types": "off",
         
     | 
| 
      
 144 
     | 
    
         
            +
                  // Disable no-undef for TypeScript - TypeScript compiler handles this
         
     | 
| 
      
 145 
     | 
    
         
            +
                  // This prevents false positives for ambient types like NodeJS.ProcessEnv
         
     | 
| 
      
 146 
     | 
    
         
            +
                  "no-undef": "off"
         
     | 
| 
      
 147 
     | 
    
         
            +
                }
         
     | 
| 
      
 148 
     | 
    
         
            +
              },
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
              // Temporary overrides for files with remaining errors
         
     | 
| 
      
 151 
     | 
    
         
            +
              // See ESLINT_TECHNICAL_DEBT.md for detailed documentation
         
     | 
| 
      
 152 
     | 
    
         
            +
              //
         
     | 
| 
      
 153 
     | 
    
         
            +
              // These overrides suppress ~172 errors that require either:
         
     | 
| 
      
 154 
     | 
    
         
            +
              // 1. Major type refactoring (any/unsafe-* rules)
         
     | 
| 
      
 155 
     | 
    
         
            +
              // 2. Potential breaking changes (module system)
         
     | 
| 
      
 156 
     | 
    
         
            +
              // 3. Significant code restructuring
         
     | 
| 
      
 157 
     | 
    
         
            +
              //
         
     | 
| 
      
 158 
     | 
    
         
            +
              // GitHub Issues tracking this technical debt:
         
     | 
| 
      
 159 
     | 
    
         
            +
              // - #707: TypeScript: Refactor configExporter module for type safety
         
     | 
| 
      
 160 
     | 
    
         
            +
              // - #708: Module System: Modernize to ES6 modules with codemod
         
     | 
| 
      
 161 
     | 
    
         
            +
              // - #709: Code Style: Fix remaining ESLint style issues
         
     | 
| 
      
 162 
     | 
    
         
            +
              {
         
     | 
| 
      
 163 
     | 
    
         
            +
                // Consolidated override for package/config.ts and package/babel/preset.ts
         
     | 
| 
      
 164 
     | 
    
         
            +
                // Combines rules from both previous override blocks to avoid duplication
         
     | 
| 
      
 165 
     | 
    
         
            +
                files: ["package/babel/preset.ts", "package/config.ts"],
         
     | 
| 
      
 166 
     | 
    
         
            +
                rules: {
         
     | 
| 
      
 167 
     | 
    
         
            +
                  // From first override block
         
     | 
| 
      
 168 
     | 
    
         
            +
                  "@typescript-eslint/no-require-imports": "off",
         
     | 
| 
      
 169 
     | 
    
         
            +
                  "@typescript-eslint/no-unused-vars": "off",
         
     | 
| 
      
 170 
     | 
    
         
            +
                  "@typescript-eslint/no-unsafe-call": "off",
         
     | 
| 
      
 171 
     | 
    
         
            +
                  "import/order": "off",
         
     | 
| 
      
 172 
     | 
    
         
            +
                  "import/newline-after-import": "off",
         
     | 
| 
      
 173 
     | 
    
         
            +
                  "import/first": "off",
         
     | 
| 
      
 174 
     | 
    
         
            +
                  // Additional rules that were in the second override for config.ts
         
     | 
| 
      
 175 
     | 
    
         
            +
                  "@typescript-eslint/no-unsafe-assignment": "off",
         
     | 
| 
      
 176 
     | 
    
         
            +
                  "@typescript-eslint/no-unsafe-member-access": "off",
         
     | 
| 
      
 177 
     | 
    
         
            +
                  "@typescript-eslint/no-unsafe-argument": "off",
         
     | 
| 
      
 178 
     | 
    
         
            +
                  "@typescript-eslint/no-explicit-any": "off",
         
     | 
| 
      
 179 
     | 
    
         
            +
                  "no-useless-escape": "off",
         
     | 
| 
      
 180 
     | 
    
         
            +
                  "no-continue": "off",
         
     | 
| 
      
 181 
     | 
    
         
            +
                  "no-nested-ternary": "off"
         
     | 
| 
      
 182 
     | 
    
         
            +
                }
         
     | 
| 
      
 183 
     | 
    
         
            +
              },
         
     | 
| 
      
 184 
     | 
    
         
            +
              {
         
     | 
| 
      
 185 
     | 
    
         
            +
                files: ["package/configExporter/**/*.ts"],
         
     | 
| 
      
 186 
     | 
    
         
            +
                rules: {
         
     | 
| 
      
 187 
     | 
    
         
            +
                  "@typescript-eslint/no-explicit-any": "off",
         
     | 
| 
      
 188 
     | 
    
         
            +
                  "@typescript-eslint/no-unsafe-assignment": "off",
         
     | 
| 
      
 189 
     | 
    
         
            +
                  "@typescript-eslint/no-unsafe-member-access": "off",
         
     | 
| 
      
 190 
     | 
    
         
            +
                  "@typescript-eslint/no-unsafe-call": "off",
         
     | 
| 
      
 191 
     | 
    
         
            +
                  "@typescript-eslint/no-unsafe-return": "off",
         
     | 
| 
      
 192 
     | 
    
         
            +
                  "@typescript-eslint/no-unsafe-argument": "off",
         
     | 
| 
      
 193 
     | 
    
         
            +
                  "@typescript-eslint/no-unsafe-function-type": "off",
         
     | 
| 
      
 194 
     | 
    
         
            +
                  "@typescript-eslint/no-unused-vars": "off",
         
     | 
| 
      
 195 
     | 
    
         
            +
                  "@typescript-eslint/require-await": "off",
         
     | 
| 
      
 196 
     | 
    
         
            +
                  "no-param-reassign": "off",
         
     | 
| 
      
 197 
     | 
    
         
            +
                  "no-await-in-loop": "off",
         
     | 
| 
      
 198 
     | 
    
         
            +
                  "no-nested-ternary": "off",
         
     | 
| 
      
 199 
     | 
    
         
            +
                  "import/prefer-default-export": "off",
         
     | 
| 
      
 200 
     | 
    
         
            +
                  "global-require": "off",
         
     | 
| 
      
 201 
     | 
    
         
            +
                  "no-underscore-dangle": "off"
         
     | 
| 
      
 202 
     | 
    
         
            +
                }
         
     | 
| 
      
 203 
     | 
    
         
            +
              },
         
     | 
| 
      
 204 
     | 
    
         
            +
              {
         
     | 
| 
      
 205 
     | 
    
         
            +
                // Remaining utils files (removed package/config.ts from this block)
         
     | 
| 
      
 206 
     | 
    
         
            +
                files: [
         
     | 
| 
      
 207 
     | 
    
         
            +
                  "package/utils/inliningCss.ts",
         
     | 
| 
      
 208 
     | 
    
         
            +
                  "package/utils/errorCodes.ts",
         
     | 
| 
      
 209 
     | 
    
         
            +
                  "package/utils/errorHelpers.ts",
         
     | 
| 
      
 210 
     | 
    
         
            +
                  "package/utils/pathValidation.ts"
         
     | 
| 
      
 211 
     | 
    
         
            +
                ],
         
     | 
| 
      
 212 
     | 
    
         
            +
                rules: {
         
     | 
| 
      
 213 
     | 
    
         
            +
                  "@typescript-eslint/no-unsafe-assignment": "off",
         
     | 
| 
      
 214 
     | 
    
         
            +
                  "@typescript-eslint/no-unsafe-member-access": "off",
         
     | 
| 
      
 215 
     | 
    
         
            +
                  "@typescript-eslint/no-unsafe-argument": "off",
         
     | 
| 
      
 216 
     | 
    
         
            +
                  "@typescript-eslint/no-explicit-any": "off",
         
     | 
| 
      
 217 
     | 
    
         
            +
                  "no-useless-escape": "off",
         
     | 
| 
      
 218 
     | 
    
         
            +
                  "no-continue": "off",
         
     | 
| 
      
 219 
     | 
    
         
            +
                  "no-nested-ternary": "off"
         
     | 
| 
      
 220 
     | 
    
         
            +
                }
         
     | 
| 
      
 221 
     | 
    
         
            +
              },
         
     | 
| 
      
 222 
     | 
    
         
            +
              {
         
     | 
| 
      
 223 
     | 
    
         
            +
                files: ["package/plugins/**/*.ts", "package/optimization/**/*.ts"],
         
     | 
| 
      
 224 
     | 
    
         
            +
                rules: {
         
     | 
| 
      
 225 
     | 
    
         
            +
                  "@typescript-eslint/no-unsafe-assignment": "off",
         
     | 
| 
      
 226 
     | 
    
         
            +
                  "@typescript-eslint/no-unsafe-call": "off",
         
     | 
| 
      
 227 
     | 
    
         
            +
                  "@typescript-eslint/no-redundant-type-constituents": "off",
         
     | 
| 
      
 228 
     | 
    
         
            +
                  "import/prefer-default-export": "off"
         
     | 
| 
      
 229 
     | 
    
         
            +
                }
         
     | 
| 
      
 230 
     | 
    
         
            +
              },
         
     | 
| 
      
 231 
     | 
    
         
            +
              {
         
     | 
| 
      
 232 
     | 
    
         
            +
                files: [
         
     | 
| 
      
 233 
     | 
    
         
            +
                  "package/environments/**/*.ts",
         
     | 
| 
      
 234 
     | 
    
         
            +
                  "package/index.ts",
         
     | 
| 
      
 235 
     | 
    
         
            +
                  "package/rspack/index.ts",
         
     | 
| 
      
 236 
     | 
    
         
            +
                  "package/rules/**/*.ts",
         
     | 
| 
      
 237 
     | 
    
         
            +
                  "package/swc/index.ts",
         
     | 
| 
      
 238 
     | 
    
         
            +
                  "package/esbuild/index.ts",
         
     | 
| 
      
 239 
     | 
    
         
            +
                  "package/dev_server.ts",
         
     | 
| 
      
 240 
     | 
    
         
            +
                  "package/env.ts"
         
     | 
| 
      
 241 
     | 
    
         
            +
                ],
         
     | 
| 
      
 242 
     | 
    
         
            +
                rules: {
         
     | 
| 
      
 243 
     | 
    
         
            +
                  "@typescript-eslint/no-unsafe-assignment": "off",
         
     | 
| 
      
 244 
     | 
    
         
            +
                  "@typescript-eslint/no-unsafe-call": "off",
         
     | 
| 
      
 245 
     | 
    
         
            +
                  "@typescript-eslint/no-unsafe-return": "off",
         
     | 
| 
      
 246 
     | 
    
         
            +
                  "@typescript-eslint/no-redundant-type-constituents": "off",
         
     | 
| 
      
 247 
     | 
    
         
            +
                  "@typescript-eslint/no-unused-vars": "off",
         
     | 
| 
      
 248 
     | 
    
         
            +
                  "@typescript-eslint/no-unsafe-function-type": "off",
         
     | 
| 
      
 249 
     | 
    
         
            +
                  "import/prefer-default-export": "off",
         
     | 
| 
      
 250 
     | 
    
         
            +
                  "no-underscore-dangle": "off"
         
     | 
| 
       135 
251 
     | 
    
         
             
                }
         
     | 
| 
       136 
252 
     | 
    
         
             
              },
         
     | 
| 
       137 
253 
     | 
    
         | 
    
        data/lib/shakapacker/runner.rb
    CHANGED
    
    | 
         @@ -379,7 +379,7 @@ module Shakapacker 
     | 
|
| 
       379 
379 
     | 
    
         
             
                      return rspack_path
         
     | 
| 
       380 
380 
     | 
    
         
             
                    end
         
     | 
| 
       381 
381 
     | 
    
         | 
| 
       382 
     | 
    
         
            -
                    # Fallback to webpack config  
     | 
| 
      
 382 
     | 
    
         
            +
                    # Fallback to webpack config in the configured directory
         
     | 
| 
       383 
383 
     | 
    
         
             
                    webpack_paths = %w[ts js].map do |ext|
         
     | 
| 
       384 
384 
     | 
    
         
             
                      File.join(@app_path, config_dir, "webpack.config.#{ext}")
         
     | 
| 
       385 
385 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -393,6 +393,29 @@ module Shakapacker 
     | 
|
| 
       393 
393 
     | 
    
         
             
                      return webpack_path
         
     | 
| 
       394 
394 
     | 
    
         
             
                    end
         
     | 
| 
       395 
395 
     | 
    
         | 
| 
      
 396 
     | 
    
         
            +
                    # Backward compatibility: Check config/webpack/ if we were looking in config/rspack/
         
     | 
| 
      
 397 
     | 
    
         
            +
                    # This supports upgrades from versions where rspack used config/webpack/
         
     | 
| 
      
 398 
     | 
    
         
            +
                    if config_dir == "config/rspack"
         
     | 
| 
      
 399 
     | 
    
         
            +
                      webpack_dir_paths = %w[ts js].map do |ext|
         
     | 
| 
      
 400 
     | 
    
         
            +
                        File.join(@app_path, "config/webpack", "webpack.config.#{ext}")
         
     | 
| 
      
 401 
     | 
    
         
            +
                      end
         
     | 
| 
      
 402 
     | 
    
         
            +
             
     | 
| 
      
 403 
     | 
    
         
            +
                      puts "[Shakapacker] Checking config/webpack/ for backward compatibility..."
         
     | 
| 
      
 404 
     | 
    
         
            +
                      webpack_dir_path = webpack_dir_paths.find { |f| File.exist?(f) }
         
     | 
| 
      
 405 
     | 
    
         
            +
                      if webpack_dir_path
         
     | 
| 
      
 406 
     | 
    
         
            +
                        $stderr.puts "⚠️  DEPRECATION WARNING: Found webpack config in config/webpack/ but assets_bundler is set to 'rspack'."
         
     | 
| 
      
 407 
     | 
    
         
            +
                        $stderr.puts "   For rspack, configs should be in config/rspack/ directory."
         
     | 
| 
      
 408 
     | 
    
         
            +
                        $stderr.puts "   "
         
     | 
| 
      
 409 
     | 
    
         
            +
                        $stderr.puts "   To fix this, either:"
         
     | 
| 
      
 410 
     | 
    
         
            +
                        $stderr.puts "   1. Move your config: mv config/webpack config/rspack"
         
     | 
| 
      
 411 
     | 
    
         
            +
                        $stderr.puts "   2. Set assets_bundler_config_path in config/shakapacker.yml:"
         
     | 
| 
      
 412 
     | 
    
         
            +
                        $stderr.puts "      assets_bundler_config_path: config/webpack"
         
     | 
| 
      
 413 
     | 
    
         
            +
                        $stderr.puts "   "
         
     | 
| 
      
 414 
     | 
    
         
            +
                        $stderr.puts "   Using: #{webpack_dir_path}"
         
     | 
| 
      
 415 
     | 
    
         
            +
                        return webpack_dir_path
         
     | 
| 
      
 416 
     | 
    
         
            +
                      end
         
     | 
| 
      
 417 
     | 
    
         
            +
                    end
         
     | 
| 
      
 418 
     | 
    
         
            +
             
     | 
| 
       396 
419 
     | 
    
         
             
                    # No config found
         
     | 
| 
       397 
420 
     | 
    
         
             
                    print_config_not_found_error("rspack", rspack_paths.last, config_dir)
         
     | 
| 
       398 
421 
     | 
    
         
             
                    exit(1)
         
     | 
    
        data/lib/shakapacker/version.rb
    CHANGED
    
    
| 
         @@ -592,7 +592,6 @@ async function runAllBuildsCommand(options: ExportOptions): Promise<number> { 
     | 
|
| 
       592 
592 
     | 
    
         
             
                  `\n📦 Exporting ${buildNames.length} builds from config file...\n`
         
     | 
| 
       593 
593 
     | 
    
         
             
                )
         
     | 
| 
       594 
594 
     | 
    
         | 
| 
       595 
     | 
    
         
            -
                const fileWriter = new FileWriter()
         
     | 
| 
       596 
595 
     | 
    
         
             
                const targetDir = options.saveDir! // Set by applyDefaults
         
     | 
| 
       597 
596 
     | 
    
         
             
                const createdFiles: string[] = []
         
     | 
| 
       598 
597 
     | 
    
         | 
| 
         @@ -610,7 +609,7 @@ async function runAllBuildsCommand(options: ExportOptions): Promise<number> { 
     | 
|
| 
       610 
609 
     | 
    
         | 
| 
       611 
610 
     | 
    
         
             
                  for (const { config: cfg, metadata } of configs) {
         
     | 
| 
       612 
611 
     | 
    
         
             
                    const output = formatConfig(cfg, metadata, options, appRoot)
         
     | 
| 
       613 
     | 
    
         
            -
                    const filename =  
     | 
| 
      
 612 
     | 
    
         
            +
                    const filename = FileWriter.generateFilename(
         
     | 
| 
       614 
613 
     | 
    
         
             
                      metadata.bundler,
         
     | 
| 
       615 
614 
     | 
    
         
             
                      metadata.environment,
         
     | 
| 
       616 
615 
     | 
    
         
             
                      metadata.configType,
         
     | 
| 
         @@ -619,7 +618,7 @@ async function runAllBuildsCommand(options: ExportOptions): Promise<number> { 
     | 
|
| 
       619 
618 
     | 
    
         
             
                    )
         
     | 
| 
       620 
619 
     | 
    
         | 
| 
       621 
620 
     | 
    
         
             
                    const fullPath = resolve(targetDir, filename)
         
     | 
| 
       622 
     | 
    
         
            -
                     
     | 
| 
      
 621 
     | 
    
         
            +
                    FileWriter.writeSingleFile(fullPath, output)
         
     | 
| 
       623 
622 
     | 
    
         
             
                    createdFiles.push(fullPath)
         
     | 
| 
       624 
623 
     | 
    
         
             
                  }
         
     | 
| 
       625 
624 
     | 
    
         
             
                }
         
     | 
| 
         @@ -659,7 +658,6 @@ async function runDoctorMode( 
     | 
|
| 
       659 
658 
     | 
    
         
             
                console.log("🔍 Config Exporter - Doctor Mode")
         
     | 
| 
       660 
659 
     | 
    
         
             
                console.log("=".repeat(80))
         
     | 
| 
       661 
660 
     | 
    
         | 
| 
       662 
     | 
    
         
            -
                const fileWriter = new FileWriter()
         
     | 
| 
       663 
661 
     | 
    
         
             
                const targetDir = options.saveDir! // Set by applyDefaults
         
     | 
| 
       664 
662 
     | 
    
         | 
| 
       665 
663 
     | 
    
         
             
                const createdFiles: string[] = []
         
     | 
| 
         @@ -693,7 +691,7 @@ async function runDoctorMode( 
     | 
|
| 
       693 
691 
     | 
    
         | 
| 
       694 
692 
     | 
    
         
             
                        for (const { config, metadata } of configs) {
         
     | 
| 
       695 
693 
     | 
    
         
             
                          const output = formatConfig(config, metadata, options, appRoot)
         
     | 
| 
       696 
     | 
    
         
            -
                          const filename =  
     | 
| 
      
 694 
     | 
    
         
            +
                          const filename = FileWriter.generateFilename(
         
     | 
| 
       697 
695 
     | 
    
         
             
                            metadata.bundler,
         
     | 
| 
       698 
696 
     | 
    
         
             
                            metadata.environment,
         
     | 
| 
       699 
697 
     | 
    
         
             
                            metadata.configType,
         
     | 
| 
         @@ -701,7 +699,7 @@ async function runDoctorMode( 
     | 
|
| 
       701 
699 
     | 
    
         
             
                            metadata.buildName
         
     | 
| 
       702 
700 
     | 
    
         
             
                          )
         
     | 
| 
       703 
701 
     | 
    
         
             
                          const fullPath = resolve(targetDir, filename)
         
     | 
| 
       704 
     | 
    
         
            -
                           
     | 
| 
      
 702 
     | 
    
         
            +
                          FileWriter.writeSingleFile(fullPath, output)
         
     | 
| 
       705 
703 
     | 
    
         
             
                          createdFiles.push(fullPath)
         
     | 
| 
       706 
704 
     | 
    
         
             
                        }
         
     | 
| 
       707 
705 
     | 
    
         
             
                      }
         
     | 
| 
         @@ -761,7 +759,7 @@ async function runDoctorMode( 
     | 
|
| 
       761 
759 
     | 
    
         
             
                       * - Filename uses "client" type and "development-hmr" build name to
         
     | 
| 
       762 
760 
     | 
    
         
             
                       *   distinguish it from regular development client bundle
         
     | 
| 
       763 
761 
     | 
    
         
             
                       */
         
     | 
| 
       764 
     | 
    
         
            -
                      filename =  
     | 
| 
      
 762 
     | 
    
         
            +
                      filename = FileWriter.generateFilename(
         
     | 
| 
       765 
763 
     | 
    
         
             
                        metadata.bundler,
         
     | 
| 
       766 
764 
     | 
    
         
             
                        metadata.environment,
         
     | 
| 
       767 
765 
     | 
    
         
             
                        "client",
         
     | 
| 
         @@ -769,7 +767,7 @@ async function runDoctorMode( 
     | 
|
| 
       769 
767 
     | 
    
         
             
                        "development-hmr"
         
     | 
| 
       770 
768 
     | 
    
         
             
                      )
         
     | 
| 
       771 
769 
     | 
    
         
             
                    } else {
         
     | 
| 
       772 
     | 
    
         
            -
                      filename =  
     | 
| 
      
 770 
     | 
    
         
            +
                      filename = FileWriter.generateFilename(
         
     | 
| 
       773 
771 
     | 
    
         
             
                        metadata.bundler,
         
     | 
| 
       774 
772 
     | 
    
         
             
                        metadata.environment,
         
     | 
| 
       775 
773 
     | 
    
         
             
                        metadata.configType,
         
     | 
| 
         @@ -780,7 +778,7 @@ async function runDoctorMode( 
     | 
|
| 
       780 
778 
     | 
    
         | 
| 
       781 
779 
     | 
    
         
             
                    const fullPath = resolve(targetDir, filename)
         
     | 
| 
       782 
780 
     | 
    
         
             
                    const fileOutput: FileOutput = { filename, content: output, metadata }
         
     | 
| 
       783 
     | 
    
         
            -
                     
     | 
| 
      
 781 
     | 
    
         
            +
                    FileWriter.writeSingleFile(fullPath, output)
         
     | 
| 
       784 
782 
     | 
    
         
             
                    createdFiles.push(fullPath)
         
     | 
| 
       785 
783 
     | 
    
         
             
                  }
         
     | 
| 
       786 
784 
     | 
    
         
             
                }
         
     | 
| 
         @@ -834,7 +832,6 @@ async function runSaveMode( 
     | 
|
| 
       834 
832 
     | 
    
         
             
              const env = options.env || "development"
         
     | 
| 
       835 
833 
     | 
    
         
             
              console.log(`[Config Exporter] Exporting ${env} configs`)
         
     | 
| 
       836 
834 
     | 
    
         | 
| 
       837 
     | 
    
         
            -
              const fileWriter = new FileWriter()
         
     | 
| 
       838 
835 
     | 
    
         
             
              const targetDir = options.saveDir! // Set by applyDefaults
         
     | 
| 
       839 
836 
     | 
    
         
             
              const configs = await loadConfigsForEnv(options.env, options, appRoot)
         
     | 
| 
       840 
837 
     | 
    
         
             
              const createdFiles: string[] = []
         
     | 
| 
         @@ -852,13 +849,13 @@ async function runSaveMode( 
     | 
|
| 
       852 
849 
     | 
    
         
             
                  appRoot
         
     | 
| 
       853 
850 
     | 
    
         
             
                )
         
     | 
| 
       854 
851 
     | 
    
         
             
                const fullPath = resolve(options.output)
         
     | 
| 
       855 
     | 
    
         
            -
                 
     | 
| 
      
 852 
     | 
    
         
            +
                FileWriter.writeSingleFile(fullPath, output)
         
     | 
| 
       856 
853 
     | 
    
         
             
                createdFiles.push(fullPath)
         
     | 
| 
       857 
854 
     | 
    
         
             
              } else {
         
     | 
| 
       858 
855 
     | 
    
         
             
                // Multi-file output (one per config)
         
     | 
| 
       859 
856 
     | 
    
         
             
                for (const { config, metadata } of configs) {
         
     | 
| 
       860 
857 
     | 
    
         
             
                  const output = formatConfig(config, metadata, options, appRoot)
         
     | 
| 
       861 
     | 
    
         
            -
                  const filename =  
     | 
| 
      
 858 
     | 
    
         
            +
                  const filename = FileWriter.generateFilename(
         
     | 
| 
       862 
859 
     | 
    
         
             
                    metadata.bundler,
         
     | 
| 
       863 
860 
     | 
    
         
             
                    metadata.environment,
         
     | 
| 
       864 
861 
     | 
    
         
             
                    metadata.configType,
         
     | 
| 
         @@ -866,7 +863,7 @@ async function runSaveMode( 
     | 
|
| 
       866 
863 
     | 
    
         
             
                    metadata.buildName
         
     | 
| 
       867 
864 
     | 
    
         
             
                  )
         
     | 
| 
       868 
865 
     | 
    
         
             
                  const fullPath = resolve(targetDir, filename)
         
     | 
| 
       869 
     | 
    
         
            -
                   
     | 
| 
      
 866 
     | 
    
         
            +
                  FileWriter.writeSingleFile(fullPath, output)
         
     | 
| 
       870 
867 
     | 
    
         
             
                  createdFiles.push(fullPath)
         
     | 
| 
       871 
868 
     | 
    
         
             
                }
         
     | 
| 
       872 
869 
     | 
    
         
             
              }
         
     | 
| 
         @@ -906,9 +903,8 @@ async function runSingleFileMode( 
     | 
|
| 
       906 
903 
     | 
    
         
             
              const config = combined.length === 1 ? combined[0] : combined
         
     | 
| 
       907 
904 
     | 
    
         
             
              const output = formatConfig(config, metadata, options, appRoot)
         
     | 
| 
       908 
905 
     | 
    
         | 
| 
       909 
     | 
    
         
            -
              const fileWriter = new FileWriter()
         
     | 
| 
       910 
906 
     | 
    
         
             
              const filePath = resolve(process.cwd(), options.output!)
         
     | 
| 
       911 
     | 
    
         
            -
               
     | 
| 
      
 907 
     | 
    
         
            +
              FileWriter.writeSingleFile(filePath, output)
         
     | 
| 
       912 
908 
     | 
    
         
             
            }
         
     | 
| 
       913 
909 
     | 
    
         | 
| 
       914 
910 
     | 
    
         
             
            async function loadConfigsForEnv(
         
     | 
| 
         @@ -11,16 +11,16 @@ export class FileWriter { 
     | 
|
| 
       11 
11 
     | 
    
         
             
              /**
         
     | 
| 
       12 
12 
     | 
    
         
             
               * Write multiple config files (one per config in array)
         
     | 
| 
       13 
13 
     | 
    
         
             
               */
         
     | 
| 
       14 
     | 
    
         
            -
              writeMultipleFiles(outputs: FileOutput[], targetDir: string): void {
         
     | 
| 
      
 14 
     | 
    
         
            +
              static writeMultipleFiles(outputs: FileOutput[], targetDir: string): void {
         
     | 
| 
       15 
15 
     | 
    
         
             
                // Ensure directory exists
         
     | 
| 
       16 
     | 
    
         
            -
                 
     | 
| 
      
 16 
     | 
    
         
            +
                FileWriter.ensureDirectory(targetDir)
         
     | 
| 
       17 
17 
     | 
    
         | 
| 
       18 
18 
     | 
    
         
             
                // Write each file
         
     | 
| 
       19 
19 
     | 
    
         
             
                outputs.forEach((output) => {
         
     | 
| 
       20 
20 
     | 
    
         
             
                  const safeName = basename(output.filename)
         
     | 
| 
       21 
21 
     | 
    
         
             
                  const filePath = resolve(targetDir, safeName)
         
     | 
| 
       22 
     | 
    
         
            -
                   
     | 
| 
       23 
     | 
    
         
            -
                   
     | 
| 
      
 22 
     | 
    
         
            +
                  FileWriter.validateOutputPath(filePath)
         
     | 
| 
      
 23 
     | 
    
         
            +
                  FileWriter.writeFile(filePath, output.content)
         
     | 
| 
       24 
24 
     | 
    
         
             
                  console.log(`[Config Exporter] Created: ${filePath}`)
         
     | 
| 
       25 
25 
     | 
    
         
             
                })
         
     | 
| 
       26 
26 
     | 
    
         | 
| 
         @@ -32,13 +32,13 @@ export class FileWriter { 
     | 
|
| 
       32 
32 
     | 
    
         
             
              /**
         
     | 
| 
       33 
33 
     | 
    
         
             
               * Write a single file
         
     | 
| 
       34 
34 
     | 
    
         
             
               */
         
     | 
| 
       35 
     | 
    
         
            -
              writeSingleFile(filePath: string, content: string): void {
         
     | 
| 
      
 35 
     | 
    
         
            +
              static writeSingleFile(filePath: string, content: string): void {
         
     | 
| 
       36 
36 
     | 
    
         
             
                // Ensure parent directory exists
         
     | 
| 
       37 
37 
     | 
    
         
             
                const dir = dirname(filePath)
         
     | 
| 
       38 
     | 
    
         
            -
                 
     | 
| 
      
 38 
     | 
    
         
            +
                FileWriter.ensureDirectory(dir)
         
     | 
| 
       39 
39 
     | 
    
         | 
| 
       40 
     | 
    
         
            -
                 
     | 
| 
       41 
     | 
    
         
            -
                 
     | 
| 
      
 40 
     | 
    
         
            +
                FileWriter.validateOutputPath(filePath)
         
     | 
| 
      
 41 
     | 
    
         
            +
                FileWriter.writeFile(filePath, content)
         
     | 
| 
       42 
42 
     | 
    
         
             
                console.log(`[Config Exporter] Created: ${filePath}`)
         
     | 
| 
       43 
43 
     | 
    
         
             
              }
         
     | 
| 
       44 
44 
     | 
    
         | 
| 
         @@ -54,7 +54,7 @@ export class FileWriter { 
     | 
|
| 
       54 
54 
     | 
    
         
             
               *   webpack-dev-client.yaml (with build name)
         
     | 
| 
       55 
55 
     | 
    
         
             
               *   rspack-cypress-dev-server.yaml (with build name)
         
     | 
| 
       56 
56 
     | 
    
         
             
               */
         
     | 
| 
       57 
     | 
    
         
            -
              generateFilename(
         
     | 
| 
      
 57 
     | 
    
         
            +
              static generateFilename(
         
     | 
| 
       58 
58 
     | 
    
         
             
                bundler: string,
         
     | 
| 
       59 
59 
     | 
    
         
             
                env: string,
         
     | 
| 
       60 
60 
     | 
    
         
             
                configType: "client" | "server" | "all" | "client-hmr",
         
     | 
| 
         @@ -66,11 +66,11 @@ export class FileWriter { 
     | 
|
| 
       66 
66 
     | 
    
         
             
                return `${bundler}-${name}-${configType}.${ext}`
         
     | 
| 
       67 
67 
     | 
    
         
             
              }
         
     | 
| 
       68 
68 
     | 
    
         | 
| 
       69 
     | 
    
         
            -
              private writeFile(filePath: string, content: string): void {
         
     | 
| 
      
 69 
     | 
    
         
            +
              private static writeFile(filePath: string, content: string): void {
         
     | 
| 
       70 
70 
     | 
    
         
             
                writeFileSync(filePath, content, "utf8")
         
     | 
| 
       71 
71 
     | 
    
         
             
              }
         
     | 
| 
       72 
72 
     | 
    
         | 
| 
       73 
     | 
    
         
            -
              private ensureDirectory(dir: string): void {
         
     | 
| 
      
 73 
     | 
    
         
            +
              private static ensureDirectory(dir: string): void {
         
     | 
| 
       74 
74 
     | 
    
         
             
                if (!existsSync(dir)) {
         
     | 
| 
       75 
75 
     | 
    
         
             
                  mkdirSync(dir, { recursive: true })
         
     | 
| 
       76 
76 
     | 
    
         
             
                }
         
     | 
| 
         @@ -79,7 +79,7 @@ export class FileWriter { 
     | 
|
| 
       79 
79 
     | 
    
         
             
              /**
         
     | 
| 
       80 
80 
     | 
    
         
             
               * Validate output path and warn if writing outside cwd
         
     | 
| 
       81 
81 
     | 
    
         
             
               */
         
     | 
| 
       82 
     | 
    
         
            -
              validateOutputPath(outputPath: string): void {
         
     | 
| 
      
 82 
     | 
    
         
            +
              private static validateOutputPath(outputPath: string): void {
         
     | 
| 
       83 
83 
     | 
    
         
             
                const absPath = resolve(outputPath)
         
     | 
| 
       84 
84 
     | 
    
         
             
                const cwd = process.cwd()
         
     | 
| 
       85 
85 
     | 
    
         | 
    
        data/package-lock.json
    CHANGED
    
    | 
         @@ -1,12 +1,12 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            {
         
     | 
| 
       2 
2 
     | 
    
         
             
              "name": "shakapacker",
         
     | 
| 
       3 
     | 
    
         
            -
              "version": "9.3.0-beta. 
     | 
| 
      
 3 
     | 
    
         
            +
              "version": "9.3.0-beta.2",
         
     | 
| 
       4 
4 
     | 
    
         
             
              "lockfileVersion": 3,
         
     | 
| 
       5 
5 
     | 
    
         
             
              "requires": true,
         
     | 
| 
       6 
6 
     | 
    
         
             
              "packages": {
         
     | 
| 
       7 
7 
     | 
    
         
             
                "": {
         
     | 
| 
       8 
8 
     | 
    
         
             
                  "name": "shakapacker",
         
     | 
| 
       9 
     | 
    
         
            -
                  "version": "9.3.0-beta. 
     | 
| 
      
 9 
     | 
    
         
            +
                  "version": "9.3.0-beta.2",
         
     | 
| 
       10 
10 
     | 
    
         
             
                  "license": "MIT",
         
     | 
| 
       11 
11 
     | 
    
         
             
                  "dependencies": {
         
     | 
| 
       12 
12 
     | 
    
         
             
                    "js-yaml": "^4.1.0",
         
     | 
    
        data/package.json
    CHANGED
    
    
| 
         @@ -154,41 +154,44 @@ describe("BuildValidator", () => { 
     | 
|
| 
       154 
154 
     | 
    
         
             
                  writeFileSync(configPath, "module.exports = {}")
         
     | 
| 
       155 
155 
     | 
    
         | 
| 
       156 
156 
     | 
    
         
             
                  const originalPath = process.env.PATH
         
     | 
| 
       157 
     | 
    
         
            -
                  process.env.PATH = "/test/path"
         
     | 
| 
       158 
157 
     | 
    
         | 
| 
       159 
     | 
    
         
            -
                   
     | 
| 
       160 
     | 
    
         
            -
                     
     | 
| 
       161 
     | 
    
         
            -
             
     | 
| 
       162 
     | 
    
         
            -
                     
     | 
| 
       163 
     | 
    
         
            -
             
     | 
| 
       164 
     | 
    
         
            -
             
     | 
| 
       165 
     | 
    
         
            -
             
     | 
| 
       166 
     | 
    
         
            -
             
     | 
| 
      
 158 
     | 
    
         
            +
                  try {
         
     | 
| 
      
 159 
     | 
    
         
            +
                    process.env.PATH = "/test/path"
         
     | 
| 
      
 160 
     | 
    
         
            +
             
     | 
| 
      
 161 
     | 
    
         
            +
                    const mockChild = {
         
     | 
| 
      
 162 
     | 
    
         
            +
                      stdout: { on: jest.fn(), removeAllListeners: jest.fn() },
         
     | 
| 
      
 163 
     | 
    
         
            +
                      stderr: { on: jest.fn(), removeAllListeners: jest.fn() },
         
     | 
| 
      
 164 
     | 
    
         
            +
                      on: jest.fn(),
         
     | 
| 
      
 165 
     | 
    
         
            +
                      once: jest.fn(),
         
     | 
| 
      
 166 
     | 
    
         
            +
                      kill: jest.fn(),
         
     | 
| 
      
 167 
     | 
    
         
            +
                      removeAllListeners: jest.fn()
         
     | 
| 
      
 168 
     | 
    
         
            +
                    }
         
     | 
| 
       167 
169 
     | 
    
         | 
| 
       168 
     | 
    
         
            -
             
     | 
| 
      
 170 
     | 
    
         
            +
                    mockSpawn.mockReturnValue(mockChild)
         
     | 
| 
       169 
171 
     | 
    
         | 
| 
       170 
     | 
    
         
            -
             
     | 
| 
       171 
     | 
    
         
            -
             
     | 
| 
       172 
     | 
    
         
            -
             
     | 
| 
       173 
     | 
    
         
            -
             
     | 
| 
       174 
     | 
    
         
            -
             
     | 
| 
       175 
     | 
    
         
            -
             
     | 
| 
       176 
     | 
    
         
            -
             
     | 
| 
       177 
     | 
    
         
            -
             
     | 
| 
       178 
     | 
    
         
            -
                  const validationPromise = validator.validateBuild(build, testDir)
         
     | 
| 
      
 172 
     | 
    
         
            +
                    const build = {
         
     | 
| 
      
 173 
     | 
    
         
            +
                      name: "test",
         
     | 
| 
      
 174 
     | 
    
         
            +
                      bundler: "webpack",
         
     | 
| 
      
 175 
     | 
    
         
            +
                      environment: { NODE_ENV: "production" },
         
     | 
| 
      
 176 
     | 
    
         
            +
                      configFile: configPath,
         
     | 
| 
      
 177 
     | 
    
         
            +
                      outputs: ["client"]
         
     | 
| 
      
 178 
     | 
    
         
            +
                    }
         
     | 
| 
       179 
179 
     | 
    
         | 
| 
       180 
     | 
    
         
            -
             
     | 
| 
       181 
     | 
    
         
            -
                    ([event]) => event === "exit"
         
     | 
| 
       182 
     | 
    
         
            -
                  )[1]
         
     | 
| 
       183 
     | 
    
         
            -
                  exitHandler(0)
         
     | 
| 
      
 180 
     | 
    
         
            +
                    const validationPromise = validator.validateBuild(build, testDir)
         
     | 
| 
       184 
181 
     | 
    
         | 
| 
       185 
     | 
    
         
            -
             
     | 
| 
      
 182 
     | 
    
         
            +
                    const exitHandler = mockChild.on.mock.calls.find(
         
     | 
| 
      
 183 
     | 
    
         
            +
                      ([event]) => event === "exit"
         
     | 
| 
      
 184 
     | 
    
         
            +
                    )[1]
         
     | 
| 
      
 185 
     | 
    
         
            +
                    exitHandler(0)
         
     | 
| 
       186 
186 
     | 
    
         | 
| 
       187 
     | 
    
         
            -
             
     | 
| 
       188 
     | 
    
         
            -
                  const { env } = spawnCall[2]
         
     | 
| 
       189 
     | 
    
         
            -
                  expect(env.PATH).toBe("/test/path")
         
     | 
| 
      
 187 
     | 
    
         
            +
                    await validationPromise
         
     | 
| 
       190 
188 
     | 
    
         | 
| 
       191 
     | 
    
         
            -
             
     | 
| 
      
 189 
     | 
    
         
            +
                    const spawnCall = mockSpawn.mock.calls[0]
         
     | 
| 
      
 190 
     | 
    
         
            +
                    const { env } = spawnCall[2]
         
     | 
| 
      
 191 
     | 
    
         
            +
                    expect(env.PATH).toBe("/test/path")
         
     | 
| 
      
 192 
     | 
    
         
            +
                  } finally {
         
     | 
| 
      
 193 
     | 
    
         
            +
                    process.env.PATH = originalPath
         
     | 
| 
      
 194 
     | 
    
         
            +
                  }
         
     | 
| 
       192 
195 
     | 
    
         
             
                })
         
     | 
| 
       193 
196 
     | 
    
         
             
              })
         
     | 
| 
       194 
197 
     | 
    
         | 
| 
         @@ -17,8 +17,7 @@ describe("configExporter", () => { 
     | 
|
| 
       17 
17 
     | 
    
         
             
              describe("fileWriter", () => {
         
     | 
| 
       18 
18 
     | 
    
         
             
                test("generates correct filename for client config", () => {
         
     | 
| 
       19 
19 
     | 
    
         
             
                  const { FileWriter } = require("../../package/configExporter/fileWriter")
         
     | 
| 
       20 
     | 
    
         
            -
                  const  
     | 
| 
       21 
     | 
    
         
            -
                  const filename = writer.generateFilename(
         
     | 
| 
      
 20 
     | 
    
         
            +
                  const filename = FileWriter.generateFilename(
         
     | 
| 
       22 
21 
     | 
    
         
             
                    "webpack",
         
     | 
| 
       23 
22 
     | 
    
         
             
                    "development",
         
     | 
| 
       24 
23 
     | 
    
         
             
                    "client",
         
     | 
| 
         @@ -29,8 +28,7 @@ describe("configExporter", () => { 
     | 
|
| 
       29 
28 
     | 
    
         | 
| 
       30 
29 
     | 
    
         
             
                test("generates correct filename for server config", () => {
         
     | 
| 
       31 
30 
     | 
    
         
             
                  const { FileWriter } = require("../../package/configExporter/fileWriter")
         
     | 
| 
       32 
     | 
    
         
            -
                  const  
     | 
| 
       33 
     | 
    
         
            -
                  const filename = writer.generateFilename(
         
     | 
| 
      
 31 
     | 
    
         
            +
                  const filename = FileWriter.generateFilename(
         
     | 
| 
       34 
32 
     | 
    
         
             
                    "webpack",
         
     | 
| 
       35 
33 
     | 
    
         
             
                    "production",
         
     | 
| 
       36 
34 
     | 
    
         
             
                    "server",
         
     | 
| 
         @@ -41,8 +39,7 @@ describe("configExporter", () => { 
     | 
|
| 
       41 
39 
     | 
    
         | 
| 
       42 
40 
     | 
    
         
             
                test("generates correct filename for client-hmr config", () => {
         
     | 
| 
       43 
41 
     | 
    
         
             
                  const { FileWriter } = require("../../package/configExporter/fileWriter")
         
     | 
| 
       44 
     | 
    
         
            -
                  const  
     | 
| 
       45 
     | 
    
         
            -
                  const filename = writer.generateFilename(
         
     | 
| 
      
 42 
     | 
    
         
            +
                  const filename = FileWriter.generateFilename(
         
     | 
| 
       46 
43 
     | 
    
         
             
                    "webpack",
         
     | 
| 
       47 
44 
     | 
    
         
             
                    "development",
         
     | 
| 
       48 
45 
     | 
    
         
             
                    "client-hmr",
         
     | 
| 
         @@ -53,8 +50,7 @@ describe("configExporter", () => { 
     | 
|
| 
       53 
50 
     | 
    
         | 
| 
       54 
51 
     | 
    
         
             
                test("generates correct filename for json format", () => {
         
     | 
| 
       55 
52 
     | 
    
         
             
                  const { FileWriter } = require("../../package/configExporter/fileWriter")
         
     | 
| 
       56 
     | 
    
         
            -
                  const  
     | 
| 
       57 
     | 
    
         
            -
                  const filename = writer.generateFilename(
         
     | 
| 
      
 53 
     | 
    
         
            +
                  const filename = FileWriter.generateFilename(
         
     | 
| 
       58 
54 
     | 
    
         
             
                    "rspack",
         
     | 
| 
       59 
55 
     | 
    
         
             
                    "production",
         
     | 
| 
       60 
56 
     | 
    
         
             
                    "client",
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: shakapacker
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 9.3.0.beta. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 9.3.0.beta.2
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - David Heinemeier Hansson
         
     | 
| 
         @@ -141,6 +141,7 @@ files: 
     | 
|
| 
       141 
141 
     | 
    
         
             
            - ".github/workflows/claude-code-review.yml"
         
     | 
| 
       142 
142 
     | 
    
         
             
            - ".github/workflows/claude.yml"
         
     | 
| 
       143 
143 
     | 
    
         
             
            - ".github/workflows/dummy.yml"
         
     | 
| 
      
 144 
     | 
    
         
            +
            - ".github/workflows/eslint-validation.yml"
         
     | 
| 
       144 
145 
     | 
    
         
             
            - ".github/workflows/generator.yml"
         
     | 
| 
       145 
146 
     | 
    
         
             
            - ".github/workflows/node.yml"
         
     | 
| 
       146 
147 
     | 
    
         
             
            - ".github/workflows/ruby.yml"
         
     | 
| 
         @@ -156,6 +157,7 @@ files: 
     | 
|
| 
       156 
157 
     | 
    
         
             
            - CHANGELOG.md
         
     | 
| 
       157 
158 
     | 
    
         
             
            - CLAUDE.md
         
     | 
| 
       158 
159 
     | 
    
         
             
            - CONTRIBUTING.md
         
     | 
| 
      
 160 
     | 
    
         
            +
            - ESLINT_TECHNICAL_DEBT.md
         
     | 
| 
       159 
161 
     | 
    
         
             
            - Gemfile
         
     | 
| 
       160 
162 
     | 
    
         
             
            - Gemfile.development_dependencies
         
     | 
| 
       161 
163 
     | 
    
         
             
            - Gemfile.lock
         
     | 
| 
         @@ -378,7 +380,7 @@ homepage: https://github.com/shakacode/shakapacker 
     | 
|
| 
       378 
380 
     | 
    
         
             
            licenses:
         
     | 
| 
       379 
381 
     | 
    
         
             
            - MIT
         
     | 
| 
       380 
382 
     | 
    
         
             
            metadata:
         
     | 
| 
       381 
     | 
    
         
            -
              source_code_uri: https://github.com/shakacode/shakapacker/tree/v9.3.0.beta. 
     | 
| 
      
 383 
     | 
    
         
            +
              source_code_uri: https://github.com/shakacode/shakapacker/tree/v9.3.0.beta.2
         
     | 
| 
       382 
384 
     | 
    
         
             
            rdoc_options: []
         
     | 
| 
       383 
385 
     | 
    
         
             
            require_paths:
         
     | 
| 
       384 
386 
     | 
    
         
             
            - lib
         
     |