|
4 | 4 | require "json" |
5 | 5 | require_relative "generator_helper" |
6 | 6 | require_relative "generator_messages" |
| 7 | +require_relative "js_dependency_manager" |
7 | 8 |
|
8 | 9 | module ReactOnRails |
9 | 10 | module Generators |
10 | 11 | # rubocop:disable Metrics/ClassLength |
11 | 12 | class InstallGenerator < Rails::Generators::Base |
12 | 13 | include GeneratorHelper |
| 14 | + include JsDependencyManager |
13 | 15 |
|
14 | 16 | # fetch USAGE file for details generator description |
15 | 17 | source_root(File.expand_path(__dir__)) |
@@ -113,10 +115,7 @@ def invoke_generators |
113 | 115 | end |
114 | 116 |
|
115 | 117 | def setup_react_dependencies |
116 | | - @added_dependencies_to_package_json ||= false |
117 | | - @ran_direct_installs ||= false |
118 | | - add_js_dependencies |
119 | | - install_js_dependencies if @added_dependencies_to_package_json && !@ran_direct_installs |
| 118 | + setup_js_dependencies |
120 | 119 | end |
121 | 120 |
|
122 | 121 | # NOTE: other requirements for existing files such as .gitignore or application. |
@@ -376,11 +375,17 @@ def install_typescript_dependencies |
376 | 375 | ] |
377 | 376 |
|
378 | 377 | # Try using GeneratorHelper first (package manager agnostic) |
379 | | - return if add_npm_dependencies(typescript_packages, dev: true) |
| 378 | + if add_npm_dependencies(typescript_packages, dev: true) |
| 379 | + @added_dependencies_to_package_json = true |
| 380 | + return |
| 381 | + end |
380 | 382 |
|
381 | 383 | # Fallback to npm if GeneratorHelper fails |
382 | 384 | success = system("npm", "install", "--save-dev", *typescript_packages) |
383 | | - return if success |
| 385 | + if success |
| 386 | + @ran_direct_installs = true |
| 387 | + return |
| 388 | + end |
384 | 389 |
|
385 | 390 | warning = <<~MSG.strip |
386 | 391 | ⚠️ Failed to install TypeScript dependencies automatically. |
@@ -450,159 +455,6 @@ def create_typescript_config |
450 | 455 | puts Rainbow("✅ Created tsconfig.json").green |
451 | 456 | end |
452 | 457 |
|
453 | | - def add_js_dependencies |
454 | | - add_react_on_rails_package |
455 | | - add_react_dependencies |
456 | | - add_css_dependencies |
457 | | - add_rspack_dependencies if options.rspack? |
458 | | - add_dev_dependencies |
459 | | - end |
460 | | - |
461 | | - def add_react_on_rails_package |
462 | | - major_minor_patch_only = /\A\d+\.\d+\.\d+\z/ |
463 | | - |
464 | | - # Try to use package_json gem first, fall back to direct npm commands |
465 | | - react_on_rails_pkg = if ReactOnRails::VERSION.match?(major_minor_patch_only) |
466 | | - ["react-on-rails@#{ReactOnRails::VERSION}"] |
467 | | - else |
468 | | - puts "Adding the latest react-on-rails NPM module. " \ |
469 | | - "Double check this is correct in package.json" |
470 | | - ["react-on-rails"] |
471 | | - end |
472 | | - |
473 | | - puts "Installing React on Rails package..." |
474 | | - if add_npm_dependencies(react_on_rails_pkg) |
475 | | - @added_dependencies_to_package_json = true |
476 | | - return |
477 | | - end |
478 | | - |
479 | | - puts "Using direct npm commands as fallback" |
480 | | - success = system("npm", "install", *react_on_rails_pkg) |
481 | | - @ran_direct_installs = true if success |
482 | | - handle_npm_failure("react-on-rails package", react_on_rails_pkg) unless success |
483 | | - end |
484 | | - |
485 | | - def add_react_dependencies |
486 | | - puts "Installing React dependencies..." |
487 | | - react_deps = %w[ |
488 | | - react |
489 | | - react-dom |
490 | | - @babel/preset-react |
491 | | - prop-types |
492 | | - babel-plugin-transform-react-remove-prop-types |
493 | | - babel-plugin-macros |
494 | | - ] |
495 | | - if add_npm_dependencies(react_deps) |
496 | | - @added_dependencies_to_package_json = true |
497 | | - return |
498 | | - end |
499 | | - |
500 | | - success = system("npm", "install", *react_deps) |
501 | | - @ran_direct_installs = true if success |
502 | | - handle_npm_failure("React dependencies", react_deps) unless success |
503 | | - end |
504 | | - |
505 | | - def add_css_dependencies |
506 | | - puts "Installing CSS handling dependencies..." |
507 | | - css_deps = %w[ |
508 | | - css-loader |
509 | | - css-minimizer-webpack-plugin |
510 | | - mini-css-extract-plugin |
511 | | - style-loader |
512 | | - ] |
513 | | - if add_npm_dependencies(css_deps) |
514 | | - @added_dependencies_to_package_json = true |
515 | | - return |
516 | | - end |
517 | | - |
518 | | - success = system("npm", "install", *css_deps) |
519 | | - @ran_direct_installs = true if success |
520 | | - handle_npm_failure("CSS dependencies", css_deps) unless success |
521 | | - end |
522 | | - |
523 | | - def add_rspack_dependencies |
524 | | - puts "Installing Rspack core dependencies..." |
525 | | - rspack_deps = %w[ |
526 | | - @rspack/core |
527 | | - rspack-manifest-plugin |
528 | | - ] |
529 | | - if add_npm_dependencies(rspack_deps) |
530 | | - @added_dependencies_to_package_json = true |
531 | | - return |
532 | | - end |
533 | | - |
534 | | - success = system("npm", "install", *rspack_deps) |
535 | | - @ran_direct_installs = true if success |
536 | | - handle_npm_failure("Rspack dependencies", rspack_deps) unless success |
537 | | - end |
538 | | - |
539 | | - def add_dev_dependencies |
540 | | - puts "Installing development dependencies..." |
541 | | - dev_deps = if options.rspack? |
542 | | - %w[ |
543 | | - @rspack/cli |
544 | | - @rspack/plugin-react-refresh |
545 | | - react-refresh |
546 | | - ] |
547 | | - else |
548 | | - %w[ |
549 | | - @pmmmwh/react-refresh-webpack-plugin |
550 | | - react-refresh |
551 | | - ] |
552 | | - end |
553 | | - if add_npm_dependencies(dev_deps, dev: true) |
554 | | - @added_dependencies_to_package_json = true |
555 | | - return |
556 | | - end |
557 | | - |
558 | | - success = system("npm", "install", "--save-dev", *dev_deps) |
559 | | - @ran_direct_installs = true if success |
560 | | - handle_npm_failure("development dependencies", dev_deps, dev: true) unless success |
561 | | - end |
562 | | - |
563 | | - def install_js_dependencies |
564 | | - # Detect which package manager to use |
565 | | - success = if File.exist?(File.join(destination_root, "yarn.lock")) |
566 | | - system("yarn", "install") |
567 | | - elsif File.exist?(File.join(destination_root, "pnpm-lock.yaml")) |
568 | | - system("pnpm", "install") |
569 | | - elsif File.exist?(File.join(destination_root, "package-lock.json")) || |
570 | | - File.exist?(File.join(destination_root, "package.json")) |
571 | | - # Use npm for package-lock.json or as default fallback |
572 | | - system("npm", "install") |
573 | | - else |
574 | | - true # No package manager detected, skip |
575 | | - end |
576 | | - |
577 | | - unless success |
578 | | - GeneratorMessages.add_warning(<<~MSG.strip) |
579 | | - ⚠️ JavaScript dependencies installation failed. |
580 | | -
|
581 | | - This could be due to network issues or missing package manager. |
582 | | - You can install dependencies manually later by running: |
583 | | - • npm install (if using npm) |
584 | | - • yarn install (if using yarn) |
585 | | - • pnpm install (if using pnpm) |
586 | | - MSG |
587 | | - end |
588 | | - |
589 | | - success |
590 | | - end |
591 | | - |
592 | | - def handle_npm_failure(dependency_type, packages, dev: false) |
593 | | - install_command = dev ? "npm install --save-dev" : "npm install" |
594 | | - GeneratorMessages.add_warning(<<~MSG.strip) |
595 | | - ⚠️ Failed to install #{dependency_type}. |
596 | | -
|
597 | | - The following packages could not be installed automatically: |
598 | | - #{packages.map { |pkg| " • #{pkg}" }.join("\n")} |
599 | | -
|
600 | | - This could be due to network issues or missing package manager. |
601 | | - You can install them manually later by running: |
602 | | - #{install_command} #{packages.join(' ')} |
603 | | - MSG |
604 | | - end |
605 | | - |
606 | 458 | # Removed: Shakapacker auto-installation logic (now explicit dependency) |
607 | 459 |
|
608 | 460 | # Removed: Shakapacker 8+ is now required as explicit dependency |
|
0 commit comments