Class: Archipelago::Generators::Install::ReactGenerator

Inherits:
Rails::Generators::Base
  • Object
show all
Defined in:
lib/generators/archipelago/install/react/react_generator.rb

Instance Method Summary collapse

Instance Method Details

#configure_scope_registryObject



131
132
133
# File 'lib/generators/archipelago/install/react/react_generator.rb', line 131

def configure_scope_registry
  ensure_scope_registry_in_npmrc
end

#create_archipelago_entryObject



125
126
127
128
129
# File 'lib/generators/archipelago/install/react/react_generator.rb', line 125

def create_archipelago_entry
  extension = @use_typescript ? "tsx" : "jsx"
  @entry_relative_path = "app/javascript/archipelago/entry.#{extension}"
  template "entry.js.tt", @entry_relative_path
end

#detect_stackObject



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/generators/archipelago/install/react/react_generator.rb', line 58

def detect_stack
  @detected_bundler = detect_bundler
  @detected_typescript = detect_typescript?
  @detected_package_manager = detect_package_manager
  @detected_local_monorepo_path = detect_local_monorepo_path

  @bundler = options[:bundler] == "auto" ? @detected_bundler : options[:bundler].to_sym
  @use_typescript = case options[:typescript]
  when "true"
    true
  when "false"
    false
  else
    @detected_typescript
  end
  @should_install = options[:install]
  @package_manager = options[:package_manager] == "auto" ? @detected_package_manager : options[:package_manager]
  @local_monorepo_path = options[:local_monorepo_path] || @detected_local_monorepo_path
  @auto_registry = options[:auto_registry]
  @lazy_registry = options[:lazy_registry]
end

#ensure_supported_stackObject

Raises:

  • (Thor::Error)


114
115
116
117
118
119
120
121
122
123
# File 'lib/generators/archipelago/install/react/react_generator.rb', line 114

def ensure_supported_stack
  if @bundler == :vite
    say_status :info, "Vite detected. Generating React entry; wire it into your Vite entrypoints.", :blue
    return
  end

  return if @bundler == :esbuild

  raise Thor::Error, "Could not detect JS bundler. Pass --bundler=esbuild or --bundler=vite."
end

#install_packagesObject



165
166
167
168
169
170
171
172
173
174
175
# File 'lib/generators/archipelago/install/react/react_generator.rb', line 165

def install_packages
  return unless @should_install
  return unless path_exists?("package.json")

  if @local_monorepo_path
    run "#{resolved_package_manager} add react react-dom #{archipelago_client_package}"
    run "#{resolved_package_manager} add #{archipelago_react_package}"
  else
    run "#{resolved_package_manager} add #{packages_for_install.join(' ')}"
  end
end

#interactive_preferencesObject



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/generators/archipelago/install/react/react_generator.rb', line 80

def interactive_preferences
  unless interactive_mode?
    if options[:interactive]
      say_status :info, "Interactive prompts skipped (non-TTY). Using detected/default options.", :yellow
    end
    return
  end

  say_status :info, "Interactive Archipelago React setup", :blue

  bundler_default = @bundler == :unknown ? "esbuild" : @bundler.to_s
  @bundler = ask_choice("Bundler", %w[esbuild vite], default: bundler_default).to_sym
  @use_typescript = ask_yes_no("Use TypeScript for island entry files?", default: @use_typescript)
  if @bundler == :esbuild
    @auto_registry = ask_yes_no(
      "Enable esbuild auto-registry for islands (no manual component map)?",
      default: @auto_registry
    )
  else
    @auto_registry = false
  end
  @should_install = ask_yes_no("Install frontend npm packages now?", default: @should_install)

  if @should_install
    @package_manager = ask_choice(
      "Package manager",
      %w[yarn npm pnpm bun],
      default: @package_manager
    )
  end

  @local_monorepo_path = prompt_for_local_monorepo_path(@local_monorepo_path)
end


177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/generators/archipelago/install/react/react_generator.rb', line 177

def print_next_steps
  say ""
  say "Archipelago React frontend scaffolding created:"
  say "  #{@entry_relative_path}"
  say ""
  unless @should_install
    say "Install packages:"
    say "  #{resolved_package_manager} add #{packages_for_install.join(' ')}"
  end
  say "Scoped registry configured in .npmrc for @archipelago-js -> npmjs.org."
  say ""
  if @bundler == :esbuild && @auto_registry
    say "Islands in app/javascript/islands/**/* are auto-registered before esbuild runs."
    say "Manual refresh command: #{script_run_command('archipelago:registry')}"
  else
    say "Register each island component in app/javascript/archipelago/entry.* under `registry`."
  end
  say "If streaming is needed, assign an ActionCable consumer to `window.Archipelago.cable`."
end

#setup_esbuild_auto_registryObject



135
136
137
138
139
140
141
142
# File 'lib/generators/archipelago/install/react/react_generator.rb', line 135

def setup_esbuild_auto_registry
  return unless @bundler == :esbuild
  return unless @auto_registry

  template "generate_registry.mjs.tt", "app/javascript/archipelago/generate_registry.mjs"
  create_file registry_relative_path, initial_registry_source
  wire_esbuild_package_scripts
end

#setup_lazy_registryObject



144
145
146
147
148
149
# File 'lib/generators/archipelago/install/react/react_generator.rb', line 144

def setup_lazy_registry
  return unless @lazy_registry
  return if @bundler == :esbuild && @auto_registry

  create_file registry_relative_path, lazy_registry_source
end

#wire_esbuild_entryObject



151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/generators/archipelago/install/react/react_generator.rb', line 151

def wire_esbuild_entry
  return unless @bundler == :esbuild

  app_entry = preferred_application_entry
  if app_entry.nil?
    say_status :info, "No app/javascript/application.(js|ts) file found. Import manually:", :yellow
    say "  import \"./archipelago/entry\""
    return
  end

  import_line = 'import "./archipelago/entry"'
  append_to_file app_entry, "\n#{import_line}\n" unless File.read(path_for(app_entry)).include?(import_line)
end