vite_react 0.1.5 → 0.1.8

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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/v0/component_generator.rb +33 -0
  3. data/lib/generators/v0/install_generator.rb +0 -0
  4. data/lib/generators/vite_react/devise/devise.rb +16 -0
  5. data/lib/generators/vite_react/migration/migration.rb +3 -6
  6. data/lib/generators/vite_react/model_validation/model_validation_generator.rb +6 -6
  7. data/lib/generators/vite_react/scaffold/scaffold_generator.rb +69 -36
  8. data/lib/generators/vite_react/scaffold/templates/_form.html.erb.tt +43 -0
  9. data/lib/generators/vite_react/scaffold/templates/edit.html.erb.tt +12 -0
  10. data/lib/generators/vite_react/scaffold/templates/index.html.erb.tt +31 -0
  11. data/lib/generators/vite_react/scaffold/templates/new.html.erb.tt +11 -0
  12. data/lib/generators/vite_react/scaffold/templates/partial.html.erb.tt +16 -0
  13. data/lib/generators/vite_react/scaffold/templates/show.html.erb.tt +20 -0
  14. data/lib/generators/vite_react/stripe/stripe.rb +10 -0
  15. data/lib/install/App.tsx +3 -3
  16. data/lib/install/AppSSR.tsx +41 -0
  17. data/lib/install/Procfile.dev +6 -0
  18. data/lib/install/application.css +89 -60
  19. data/lib/install/application.jsx +15 -0
  20. data/lib/install/index.html.erb +1 -1
  21. data/lib/install/opentelemetry.rb.tt +10 -0
  22. data/lib/install/postcss.config.mjs +5 -0
  23. data/lib/install/ssr.ts +70 -0
  24. data/lib/install/tailwind.config.js +46 -46
  25. data/lib/install/tsconfig.app.json +1 -1
  26. data/lib/install/tsconfig.node.json +5 -1
  27. data/lib/install/{vite.config.js → vite.config.ts} +8 -0
  28. data/lib/install/vite_react.rb +55 -56
  29. data/lib/tasks/install.rake +0 -5
  30. data/lib/vite_react/configuration.rb +15 -0
  31. data/lib/vite_react/engine.rb +16 -0
  32. data/lib/vite_react/node_manager.rb +39 -0
  33. data/lib/vite_react/railtie.rb +112 -10
  34. data/lib/vite_react/version.rb +1 -1
  35. data/lib/vite_react.rb +9 -0
  36. metadata +23 -4
  37. /data/lib/{install/eslint.config.js → generators/devise/tailwind/tailwind_generator.rb} +0 -0
@@ -0,0 +1,39 @@
1
+ module ViteReact
2
+ module NodeServerManager
3
+ class << self
4
+ def start!
5
+ return if @started
6
+ @started = true
7
+
8
+ node_executable = ViteReact.config.node_path ||
9
+ `which bun`.strip
10
+ unless node_executable && !node_executable.empty?
11
+ Rails.logger.error("Node executable not found. SSR functionality disabled.")
12
+ return
13
+ end
14
+
15
+ server_script = File.expand_path("/node/ssr-server.ts", __FILE__)
16
+ port = ViteReact.config.node_server_port
17
+ command = "#{node_executable} #{server_script} --expirimental-strip-types --port=#{port}"
18
+ Rails.logger.info("Starting vite_react_ssr Node server with: #{command}")
19
+
20
+ @pid = Process.spawn(command, out: "/dev/null", err: "/dev/null")
21
+ Rails.logger.info("vite_react_ssr Node server started with pid: #{@pid}")
22
+
23
+ sleep 1
24
+
25
+ at_exit { stop! }
26
+ rescue => e
27
+ Rails.logger.error("Failed to start vite_react_ssr Node server: #{e.message}")
28
+ end
29
+
30
+ def stop!
31
+ return unless @pid
32
+ Rails.logger.info("Stopping vite_react_ssr Node server (pid: #{@pid})")
33
+ Process.kill("TERM", @pid)
34
+ rescue => e
35
+ Rails.logger.error("Error stopping vite_react_ssr Node server: #{e.message}")
36
+ end
37
+ end
38
+ end
39
+ end
@@ -1,28 +1,130 @@
1
1
  require "rails"
2
2
  require "rails/railtie"
3
- require "rails/generators"
4
- require "rails/generators/rails/scaffold/scaffold_generator"
5
3
 
4
+ require "net/http"
5
+ require "json"
6
+ require "securerandom"
6
7
 
7
8
  module ViteReact
8
- module ScaffoldGenerator
9
- extend ActiveSupport::Concern
10
- included do
11
- hook_for :scaffold, in: nil, default: true, type: :boolean
9
+ module ReactComponentHelper
10
+ # Usage:
11
+ # <%== react_component("MyComponent", props: { name: "Alice" }) %>
12
+ # for client‑side hydration, and:
13
+ #
14
+ # <%== react_component("MyComponent", props: { name: "Alice" }) do %>
15
+ # <div>Extra ERB content</div>
16
+ # <% end %>
17
+ #
18
+ # for SSR via renderToPipeableStream.
19
+ def react_component(name, props: {}, ssr: false, &block)
20
+ if block_given? or ssr
21
+ # SERVER‑SIDE RENDERING: capture block content
22
+ children_html = capture(&block)
23
+ # Merge in the children as a prop for your React component
24
+ props_with_children = props.merge(children: children_html)
25
+ ssr_html = render_react_component_ssr(name, props_with_children)
26
+ ssr_html
27
+ else
28
+ # CLIENT‑SIDE RENDERING: output a placeholder div with data attributes
29
+ placeholder_id = "react-component-#{SecureRandom.hex(8)}"
30
+ content_tag(:div, "",
31
+ id: placeholder_id,
32
+ data: { react_component: name, props: props.to_json })
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def render_react_component_ssr(name, props)
39
+ port = 4000 # ViteReact.config.node_server_port || 4000
40
+ uri = URI("http://localhost:#{port}/render")
41
+ http = Net::HTTP.new(uri.host, uri.port)
42
+ req = Net::HTTP::Post.new(uri, "Content-Type" => "application/json")
43
+ req.body = { component: name, props: props }.to_json
44
+
45
+ res = http.request(req)
46
+ if res.is_a?(Net::HTTPSuccess)
47
+ res.body.html_safe
48
+ else
49
+ Rails.logger.error("SSR Error: #{res.code} #{res.body}")
50
+ "Error rendering component"
51
+ end
52
+ rescue => e
53
+ Rails.logger.error("SSR Exception: #{e.message}")
54
+ "Error rendering component"
12
55
  end
13
56
  end
14
57
  end
15
58
 
16
59
 
17
-
18
60
  module ViteReact
19
61
  class Railtie < ::Rails::Railtie
62
+ initializer "vite_react.action_view" do
63
+ ActiveSupport.on_load(:action_view) do
64
+ include ViteReact::ReactComponentHelper
65
+ end
66
+ end
20
67
  rake_tasks do
21
68
  load "tasks/install.rake"
22
69
  end
23
- generators do |app|
24
- Rails::Generators.configure! app.config.generators
25
- Rails::Generators::ScaffoldGenerator.include ViteReact::ScaffoldGenerator
70
+ end
71
+ end
72
+
73
+
74
+ module ViteReact
75
+ module ReactComponentHelper
76
+ # Renders a React component with extended options.
77
+ #
78
+ # Options:
79
+ # - i18n: if true, merge current locale translations from Rails I18n YAML into props under :i18n.
80
+ # - filename: if provided, used to determine the component file path on the Node server.
81
+ #
82
+ # Example usage:
83
+ # <%== react_component("MyComponent", file_name="CustomFile", props: { name: "Alice" }, options: { i18n: true }) %>
84
+ def react_component(name, file_name: nil, props: {}, options: {}, &block)
85
+ # Process options BEFORE any other logic.
86
+ if options[:i18n]
87
+ # Fetch only translations for the current locale from the YAML files.
88
+ translations = I18n.backend.send(:translations)[I18n.locale] || {}
89
+ props[:i18n] = translations
90
+ end
91
+ filename = name if file_name.nil?
92
+ if block_given?
93
+ # SERVER‑SIDE RENDERING: capture block content as children.
94
+ children_html = capture(&block)
95
+ props_with_children = props.merge(children: children_html)
96
+ ssr_html = render_react_component_ssr(name, props_with_children, filename)
97
+ ssr_html
98
+ else
99
+ # CLIENT‑SIDE RENDERING: output a placeholder div with data attributes.
100
+ placeholder_id = "react-component-#{SecureRandom.hex(8)}"
101
+ data_attributes = { react_component: name, props: props.to_json }
102
+ data_attributes[:filename] = filename if filename
103
+ content_tag(:div, "", id: placeholder_id, data: data_attributes)
104
+ end
105
+ end
106
+
107
+ private
108
+
109
+ def render_react_component_ssr(name, props, filename = nil)
110
+ port = 4000 # Alternatively, use ViteReact.config.node_server_port || 4000
111
+ uri = URI("http://localhost:#{port}/render")
112
+ http = Net::HTTP.new(uri.host, uri.port)
113
+ req = Net::HTTP::Post.new(uri, "Content-Type" => "application/json")
114
+ payload = { component: name, props: props }
115
+ payload[:filename] = filename if filename
116
+ req.body = payload.to_json
117
+
118
+ res = http.request(req)
119
+ if res.is_a?(Net::HTTPSuccess)
120
+ res.body.html_safe
121
+ else
122
+ Rails.logger.error("SSR Error: #{res.code} #{res.body}")
123
+ "Error rendering component"
124
+ end
125
+ rescue => e
126
+ Rails.logger.error("SSR Exception: #{e.message}")
127
+ "Error rendering component"
26
128
  end
27
129
  end
28
130
  end
@@ -1,3 +1,3 @@
1
1
  module ViteReact
2
- VERSION = "0.1.5"
2
+ VERSION = "0.1.8"
3
3
  end
data/lib/vite_react.rb CHANGED
@@ -1,5 +1,14 @@
1
1
  require "vite_react/version"
2
2
  require "vite_react/railtie"
3
+ require "vite_react/engine"
4
+
3
5
 
4
6
  module ViteReact
7
+ def self.config
8
+ @config ||= Configuration.new
9
+ end
10
+
11
+ def self.configure
12
+ yield(config)
13
+ end
5
14
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vite_react
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - lsproule
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-01-16 00:00:00.000000000 Z
10
+ date: 2025-03-15 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: rails
@@ -104,26 +104,45 @@ files:
104
104
  - MIT-LICENSE
105
105
  - README.md
106
106
  - Rakefile
107
+ - lib/generators/devise/tailwind/tailwind_generator.rb
107
108
  - lib/generators/ui/component/component_generator.rb
108
109
  - lib/generators/ui/component/templates/component.tsx.erb
109
110
  - lib/generators/ui/register/register_generator.rb
111
+ - lib/generators/v0/component_generator.rb
112
+ - lib/generators/v0/install_generator.rb
113
+ - lib/generators/vite_react/devise/devise.rb
110
114
  - lib/generators/vite_react/migration/migration.rb
111
115
  - lib/generators/vite_react/model_validation/model_validation_generator.rb
112
116
  - lib/generators/vite_react/scaffold/scaffold_generator.rb
117
+ - lib/generators/vite_react/scaffold/templates/_form.html.erb.tt
118
+ - lib/generators/vite_react/scaffold/templates/edit.html.erb.tt
119
+ - lib/generators/vite_react/scaffold/templates/index.html.erb.tt
120
+ - lib/generators/vite_react/scaffold/templates/new.html.erb.tt
121
+ - lib/generators/vite_react/scaffold/templates/partial.html.erb.tt
122
+ - lib/generators/vite_react/scaffold/templates/show.html.erb.tt
123
+ - lib/generators/vite_react/stripe/stripe.rb
113
124
  - lib/install/App.tsx
125
+ - lib/install/AppSSR.tsx
126
+ - lib/install/Procfile.dev
114
127
  - lib/install/application.css
128
+ - lib/install/application.jsx
115
129
  - lib/install/components.json
116
- - lib/install/eslint.config.js
117
130
  - lib/install/index.html.erb
131
+ - lib/install/opentelemetry.rb.tt
132
+ - lib/install/postcss.config.mjs
133
+ - lib/install/ssr.ts
118
134
  - lib/install/tailwind.config.js
119
135
  - lib/install/tsconfig.app.json
120
136
  - lib/install/tsconfig.json
121
137
  - lib/install/tsconfig.node.json
122
138
  - lib/install/utils.ts
123
- - lib/install/vite.config.js
139
+ - lib/install/vite.config.ts
124
140
  - lib/install/vite_react.rb
125
141
  - lib/tasks/install.rake
126
142
  - lib/vite_react.rb
143
+ - lib/vite_react/configuration.rb
144
+ - lib/vite_react/engine.rb
145
+ - lib/vite_react/node_manager.rb
127
146
  - lib/vite_react/railtie.rb
128
147
  - lib/vite_react/version.rb
129
148
  homepage: https://docs.lucassproule.com