|
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__)) |
@@ -83,10 +85,7 @@ def invoke_generators |
83 | 85 | end |
84 | 86 |
|
85 | 87 | def setup_react_dependencies |
86 | | - @added_dependencies_to_package_json ||= false |
87 | | - @ran_direct_installs ||= false |
88 | | - add_js_dependencies |
89 | | - install_js_dependencies if @added_dependencies_to_package_json && !@ran_direct_installs |
| 88 | + setup_js_dependencies |
90 | 89 | end |
91 | 90 |
|
92 | 91 | # NOTE: other requirements for existing files such as .gitignore or application. |
@@ -346,11 +345,17 @@ def install_typescript_dependencies |
346 | 345 | ] |
347 | 346 |
|
348 | 347 | # Try using GeneratorHelper first (package manager agnostic) |
349 | | - return if add_npm_dependencies(typescript_packages, dev: true) |
| 348 | + if add_npm_dependencies(typescript_packages, dev: true) |
| 349 | + @added_dependencies_to_package_json = true |
| 350 | + return |
| 351 | + end |
350 | 352 |
|
351 | 353 | # Fallback to npm if GeneratorHelper fails |
352 | 354 | success = system("npm", "install", "--save-dev", *typescript_packages) |
353 | | - return if success |
| 355 | + if success |
| 356 | + @ran_direct_installs = true |
| 357 | + return |
| 358 | + end |
354 | 359 |
|
355 | 360 | warning = <<~MSG.strip |
356 | 361 | ⚠️ Failed to install TypeScript dependencies automatically. |
@@ -420,134 +425,6 @@ def create_typescript_config |
420 | 425 | puts Rainbow("✅ Created tsconfig.json").green |
421 | 426 | end |
422 | 427 |
|
423 | | - def add_js_dependencies |
424 | | - add_react_on_rails_package |
425 | | - add_react_dependencies |
426 | | - add_css_dependencies |
427 | | - add_dev_dependencies |
428 | | - end |
429 | | - |
430 | | - def add_react_on_rails_package |
431 | | - major_minor_patch_only = /\A\d+\.\d+\.\d+\z/ |
432 | | - |
433 | | - # Try to use package_json gem first, fall back to direct npm commands |
434 | | - react_on_rails_pkg = if ReactOnRails::VERSION.match?(major_minor_patch_only) |
435 | | - ["react-on-rails@#{ReactOnRails::VERSION}"] |
436 | | - else |
437 | | - puts "Adding the latest react-on-rails NPM module. " \ |
438 | | - "Double check this is correct in package.json" |
439 | | - ["react-on-rails"] |
440 | | - end |
441 | | - |
442 | | - puts "Installing React on Rails package..." |
443 | | - if add_npm_dependencies(react_on_rails_pkg) |
444 | | - @added_dependencies_to_package_json = true |
445 | | - return |
446 | | - end |
447 | | - |
448 | | - puts "Using direct npm commands as fallback" |
449 | | - success = system("npm", "install", *react_on_rails_pkg) |
450 | | - @ran_direct_installs = true if success |
451 | | - handle_npm_failure("react-on-rails package", react_on_rails_pkg) unless success |
452 | | - end |
453 | | - |
454 | | - def add_react_dependencies |
455 | | - puts "Installing React dependencies..." |
456 | | - react_deps = %w[ |
457 | | - react |
458 | | - react-dom |
459 | | - @babel/preset-react |
460 | | - prop-types |
461 | | - babel-plugin-transform-react-remove-prop-types |
462 | | - babel-plugin-macros |
463 | | - ] |
464 | | - if add_npm_dependencies(react_deps) |
465 | | - @added_dependencies_to_package_json = true |
466 | | - return |
467 | | - end |
468 | | - |
469 | | - success = system("npm", "install", *react_deps) |
470 | | - @ran_direct_installs = true if success |
471 | | - handle_npm_failure("React dependencies", react_deps) unless success |
472 | | - end |
473 | | - |
474 | | - def add_css_dependencies |
475 | | - puts "Installing CSS handling dependencies..." |
476 | | - css_deps = %w[ |
477 | | - css-loader |
478 | | - css-minimizer-webpack-plugin |
479 | | - mini-css-extract-plugin |
480 | | - style-loader |
481 | | - ] |
482 | | - if add_npm_dependencies(css_deps) |
483 | | - @added_dependencies_to_package_json = true |
484 | | - return |
485 | | - end |
486 | | - |
487 | | - success = system("npm", "install", *css_deps) |
488 | | - @ran_direct_installs = true if success |
489 | | - handle_npm_failure("CSS dependencies", css_deps) unless success |
490 | | - end |
491 | | - |
492 | | - def add_dev_dependencies |
493 | | - puts "Installing development dependencies..." |
494 | | - dev_deps = %w[ |
495 | | - @pmmmwh/react-refresh-webpack-plugin |
496 | | - react-refresh |
497 | | - ] |
498 | | - if add_npm_dependencies(dev_deps, dev: true) |
499 | | - @added_dependencies_to_package_json = true |
500 | | - return |
501 | | - end |
502 | | - |
503 | | - success = system("npm", "install", "--save-dev", *dev_deps) |
504 | | - @ran_direct_installs = true if success |
505 | | - handle_npm_failure("development dependencies", dev_deps, dev: true) unless success |
506 | | - end |
507 | | - |
508 | | - def install_js_dependencies |
509 | | - # Detect which package manager to use |
510 | | - success = if File.exist?(File.join(destination_root, "yarn.lock")) |
511 | | - system("yarn", "install") |
512 | | - elsif File.exist?(File.join(destination_root, "pnpm-lock.yaml")) |
513 | | - system("pnpm", "install") |
514 | | - elsif File.exist?(File.join(destination_root, "package-lock.json")) || |
515 | | - File.exist?(File.join(destination_root, "package.json")) |
516 | | - # Use npm for package-lock.json or as default fallback |
517 | | - system("npm", "install") |
518 | | - else |
519 | | - true # No package manager detected, skip |
520 | | - end |
521 | | - |
522 | | - unless success |
523 | | - GeneratorMessages.add_warning(<<~MSG.strip) |
524 | | - ⚠️ JavaScript dependencies installation failed. |
525 | | -
|
526 | | - This could be due to network issues or missing package manager. |
527 | | - You can install dependencies manually later by running: |
528 | | - • npm install (if using npm) |
529 | | - • yarn install (if using yarn) |
530 | | - • pnpm install (if using pnpm) |
531 | | - MSG |
532 | | - end |
533 | | - |
534 | | - success |
535 | | - end |
536 | | - |
537 | | - def handle_npm_failure(dependency_type, packages, dev: false) |
538 | | - install_command = dev ? "npm install --save-dev" : "npm install" |
539 | | - GeneratorMessages.add_warning(<<~MSG.strip) |
540 | | - ⚠️ Failed to install #{dependency_type}. |
541 | | -
|
542 | | - The following packages could not be installed automatically: |
543 | | - #{packages.map { |pkg| " • #{pkg}" }.join("\n")} |
544 | | -
|
545 | | - This could be due to network issues or missing package manager. |
546 | | - You can install them manually later by running: |
547 | | - #{install_command} #{packages.join(' ')} |
548 | | - MSG |
549 | | - end |
550 | | - |
551 | 428 | # Removed: Shakapacker auto-installation logic (now explicit dependency) |
552 | 429 |
|
553 | 430 | # Removed: Shakapacker 8+ is now required as explicit dependency |
|
0 commit comments