inertia_rails 3.14.0 → 3.15.0
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/CHANGELOG.md +6 -0
- data/app/views/inertia.html.erb +1 -1
- data/lib/generators/inertia/install/templates/initializer.rb +1 -0
- data/lib/generators/inertia/install/templates/react/InertiaExample.tsx +1 -1
- data/lib/generators/inertia/install/templates/react/inertia.jsx +1 -0
- data/lib/generators/inertia/install/templates/react/inertia.tsx +1 -0
- data/lib/generators/inertia/install/templates/svelte/inertia.ts +1 -0
- data/lib/generators/inertia/install/templates/vue/InertiaExample.ts.vue +1 -1
- data/lib/generators/inertia/install/templates/vue/inertia.ts +1 -0
- data/lib/inertia_rails/base_prop.rb +1 -1
- data/lib/inertia_rails/configuration.rb +6 -0
- data/lib/inertia_rails/defer_prop.rb +1 -0
- data/lib/inertia_rails/helper.rb +14 -0
- data/lib/inertia_rails/inertia_rails.rb +8 -2
- data/lib/inertia_rails/merge_prop.rb +1 -0
- data/lib/inertia_rails/once_prop.rb +12 -0
- data/lib/inertia_rails/optional_prop.rb +1 -0
- data/lib/inertia_rails/prop_onceable.rb +39 -0
- data/lib/inertia_rails/renderer.rb +52 -13
- data/lib/inertia_rails/version.rb +1 -1
- 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: 2460d1f62147b4360786f5caba3ed7525d0539da9b61acc65dd9c93f925d7e7b
|
|
4
|
+
data.tar.gz: 741b89dd90fbf8b2fe212ef48ddd1e723ef69d9d13ffa5c35a3cc61d82443743
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 06a2bca60142ca5d450b4640fe6fe4df5000b15da57b8830c7993563d827b6d9abec3c3cf036d6ca33cf931a745e40ca81a52706598293e0e619bc4ed5bcb207
|
|
7
|
+
data.tar.gz: ee907ff350208d0e415aac873cc38b971d9a5fc8964b96dc502d031acd2af6ac5f6ab848163c2e56e60e3b855a1a7c95dc52fda1abbda5e1959a96cb00b068ac
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
5
5
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [3.15.0] - 2025-12-11
|
|
8
|
+
|
|
9
|
+
* Support for rendering initial page data in a script tag (@skryukov)
|
|
10
|
+
* Once props support (@skryukov)
|
|
11
|
+
* Fix file references in TypeScript templates (@bigmasonwang)
|
|
12
|
+
|
|
7
13
|
## [3.14.0] - 2025-11-27
|
|
8
14
|
|
|
9
15
|
Lots of quality of life improvements!
|
data/app/views/inertia.html.erb
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
<%= inertia_root(page: page) %>
|
|
@@ -34,7 +34,7 @@ export default function InertiaExample(
|
|
|
34
34
|
<div className={cs.footer}>
|
|
35
35
|
<div className={cs.card}>
|
|
36
36
|
<p>
|
|
37
|
-
Edit <code><%= js_destination_path %>/pages/inertia_example/index.
|
|
37
|
+
Edit <code><%= js_destination_path %>/pages/inertia_example/index.tsx</code> and save to test <abbr title="Hot Module Replacement">HMR</abbr>.
|
|
38
38
|
</p>
|
|
39
39
|
</div>
|
|
40
40
|
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
<div class="footer">
|
|
18
18
|
<div class="card">
|
|
19
19
|
<p>
|
|
20
|
-
Edit <code><%= js_destination_path %>/pages/inertia_example/index.
|
|
20
|
+
Edit <code><%= js_destination_path %>/pages/inertia_example/index.vue</code> and save to test <abbr title="Hot Module Replacement">HMR</abbr>.
|
|
21
21
|
</p>
|
|
22
22
|
</div>
|
|
23
23
|
|
|
@@ -34,6 +34,12 @@ module InertiaRails
|
|
|
34
34
|
|
|
35
35
|
# Whether to include empty `errors` hash to the props when no errors are present.
|
|
36
36
|
always_include_errors_hash: nil,
|
|
37
|
+
|
|
38
|
+
# Whether to use `<script>` element for initial page rendering instead of the `data-page` attribute.
|
|
39
|
+
use_script_element_for_initial_page: false,
|
|
40
|
+
|
|
41
|
+
# DOM id to use for the root Inertia.js element.
|
|
42
|
+
root_dom_id: 'app',
|
|
37
43
|
}.freeze
|
|
38
44
|
|
|
39
45
|
OPTION_NAMES = DEFAULTS.keys.freeze
|
data/lib/inertia_rails/helper.rb
CHANGED
|
@@ -32,5 +32,19 @@ module InertiaRails
|
|
|
32
32
|
|
|
33
33
|
safe_join(meta_tags, "\n")
|
|
34
34
|
end
|
|
35
|
+
|
|
36
|
+
def inertia_root(id: nil, page: inertia_page)
|
|
37
|
+
config = controller.send(:inertia_configuration)
|
|
38
|
+
id ||= config.root_dom_id
|
|
39
|
+
|
|
40
|
+
if config.use_script_element_for_initial_page
|
|
41
|
+
safe_join([
|
|
42
|
+
tag.script(page.to_json.html_safe, 'data-page': id, type: 'application/json'),
|
|
43
|
+
tag.div(id: id)
|
|
44
|
+
], "\n")
|
|
45
|
+
else
|
|
46
|
+
tag.div(id: id, 'data-page': page.to_json)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
35
49
|
end
|
|
36
50
|
end
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'inertia_rails/prop_onceable'
|
|
3
4
|
require 'inertia_rails/prop_mergeable'
|
|
4
5
|
require 'inertia_rails/base_prop'
|
|
5
6
|
require 'inertia_rails/ignore_on_first_load_prop'
|
|
@@ -8,6 +9,7 @@ require 'inertia_rails/lazy_prop'
|
|
|
8
9
|
require 'inertia_rails/optional_prop'
|
|
9
10
|
require 'inertia_rails/defer_prop'
|
|
10
11
|
require 'inertia_rails/merge_prop'
|
|
12
|
+
require 'inertia_rails/once_prop'
|
|
11
13
|
require 'inertia_rails/scroll_prop'
|
|
12
14
|
require 'inertia_rails/configuration'
|
|
13
15
|
require 'inertia_rails/meta_tag'
|
|
@@ -36,6 +38,10 @@ module InertiaRails
|
|
|
36
38
|
AlwaysProp.new(&block)
|
|
37
39
|
end
|
|
38
40
|
|
|
41
|
+
def once(...)
|
|
42
|
+
OnceProp.new(...)
|
|
43
|
+
end
|
|
44
|
+
|
|
39
45
|
def merge(...)
|
|
40
46
|
MergeProp.new(...)
|
|
41
47
|
end
|
|
@@ -44,8 +50,8 @@ module InertiaRails
|
|
|
44
50
|
MergeProp.new(deep_merge: true, match_on: match_on, &block)
|
|
45
51
|
end
|
|
46
52
|
|
|
47
|
-
def defer(
|
|
48
|
-
DeferProp.new(
|
|
53
|
+
def defer(...)
|
|
54
|
+
DeferProp.new(...)
|
|
49
55
|
end
|
|
50
56
|
|
|
51
57
|
def scroll(metadata = nil, **options, &block)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module InertiaRails
|
|
4
|
+
module PropOnceable
|
|
5
|
+
attr_reader :once_key, :once_expires_in
|
|
6
|
+
|
|
7
|
+
def initialize(**props, &block)
|
|
8
|
+
@once = props.fetch(:once, false)
|
|
9
|
+
@once_key = props[:key]
|
|
10
|
+
@once_expires_in = props[:expires_in]
|
|
11
|
+
@fresh = props.fetch(:fresh, false)
|
|
12
|
+
|
|
13
|
+
super
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def once?
|
|
17
|
+
@once
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def fresh?
|
|
21
|
+
@fresh
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def expires_at
|
|
25
|
+
return nil unless @once_expires_in
|
|
26
|
+
|
|
27
|
+
timestamp = case @once_expires_in
|
|
28
|
+
when ActiveSupport::Duration
|
|
29
|
+
(Time.current + @once_expires_in).to_f
|
|
30
|
+
when Numeric
|
|
31
|
+
Time.current.to_f + @once_expires_in
|
|
32
|
+
else
|
|
33
|
+
raise ArgumentError, "Invalid `expires_in` value: #{@once_expires_in.inspect}"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
(timestamp * 1000).to_i
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -48,7 +48,7 @@ module InertiaRails
|
|
|
48
48
|
else
|
|
49
49
|
"#{@response.headers['Vary']}, X-Inertia"
|
|
50
50
|
end
|
|
51
|
-
if @request.
|
|
51
|
+
if @request.inertia?
|
|
52
52
|
@response.set_header('X-Inertia', 'true')
|
|
53
53
|
@render_method.call json: page.to_json, status: @response.status, content_type: Mime[:json]
|
|
54
54
|
else
|
|
@@ -97,15 +97,17 @@ module InertiaRails
|
|
|
97
97
|
def computed_props
|
|
98
98
|
# rubocop:disable Style/MultilineBlockChain
|
|
99
99
|
@props
|
|
100
|
-
.tap do |merged_props|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
100
|
+
.tap do |merged_props|
|
|
101
|
+
# Always keep errors in the props
|
|
102
|
+
if merged_props.key?(:errors) && !merged_props[:errors].is_a?(BaseProp)
|
|
103
|
+
errors = merged_props[:errors]
|
|
104
|
+
merged_props[:errors] = InertiaRails.always { errors }
|
|
105
105
|
end
|
|
106
|
+
end
|
|
106
107
|
.then { |props| deep_transform_props(props) } # Internal hydration/filtering
|
|
107
108
|
.then { |props| @configuration.prop_transformer(props: props) } # Apply user-defined prop transformer
|
|
108
|
-
.tap do |props|
|
|
109
|
+
.tap do |props|
|
|
110
|
+
# Add meta tags last (never transformed)
|
|
109
111
|
props[:_inertia_meta] = meta_tags if meta_tags.present?
|
|
110
112
|
end
|
|
111
113
|
# rubocop:enable Style/MultilineBlockChain
|
|
@@ -128,6 +130,9 @@ module InertiaRails
|
|
|
128
130
|
@page[:scrollProps] = scroll_props if scroll_props.present?
|
|
129
131
|
@page.merge!(resolve_merge_props)
|
|
130
132
|
|
|
133
|
+
once_props = resolve_once_props
|
|
134
|
+
@page[:onceProps] = once_props if once_props.present?
|
|
135
|
+
|
|
131
136
|
@page
|
|
132
137
|
end
|
|
133
138
|
|
|
@@ -173,6 +178,17 @@ module InertiaRails
|
|
|
173
178
|
}.delete_if { |_, v| v.blank? }
|
|
174
179
|
end
|
|
175
180
|
|
|
181
|
+
def resolve_once_props
|
|
182
|
+
@props.each_with_object({}) do |(key, prop), result|
|
|
183
|
+
next unless prop.try(:once?)
|
|
184
|
+
next if excluded_by_partial_request?([key.to_s])
|
|
185
|
+
|
|
186
|
+
once_key = (prop.once_key || key).to_s
|
|
187
|
+
|
|
188
|
+
result[once_key] = { prop: key.to_s, expiresAt: prop.expires_at }.compact
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
|
|
176
192
|
def resolve_match_on_props
|
|
177
193
|
all_merge_props.filter_map do |key, prop|
|
|
178
194
|
prop.match_on.map! { |ms| "#{key}.#{ms}" } if prop.match_on.present?
|
|
@@ -251,6 +267,10 @@ module InertiaRails
|
|
|
251
267
|
@partial_except_keys ||= (@request.headers['X-Inertia-Partial-Except'] || '').split(',').compact_blank!
|
|
252
268
|
end
|
|
253
269
|
|
|
270
|
+
def except_once_keys
|
|
271
|
+
@except_once_keys ||= (@request.headers['X-Inertia-Except-Once-Props'] || '').split(',').compact_blank!
|
|
272
|
+
end
|
|
273
|
+
|
|
254
274
|
def rendering_partial_component?
|
|
255
275
|
@request.headers['X-Inertia-Partial-Component'] == @component
|
|
256
276
|
end
|
|
@@ -265,12 +285,8 @@ module InertiaRails
|
|
|
265
285
|
|
|
266
286
|
def keep_prop?(prop, path)
|
|
267
287
|
return true if prop.is_a?(AlwaysProp)
|
|
268
|
-
|
|
269
|
-
if
|
|
270
|
-
path_with_prefixes = path_prefixes(path)
|
|
271
|
-
return false if excluded_by_only_partial_keys?(path_with_prefixes)
|
|
272
|
-
return false if excluded_by_except_partial_keys?(path_with_prefixes)
|
|
273
|
-
end
|
|
288
|
+
return false if excluded_by_once_cache?(prop, path)
|
|
289
|
+
return false if excluded_by_partial_request?(path)
|
|
274
290
|
|
|
275
291
|
# Precedence: Evaluate IgnoreOnFirstLoadProp only after partial keys have been checked
|
|
276
292
|
return false if prop.is_a?(IgnoreOnFirstLoadProp) && !rendering_partial_component?
|
|
@@ -278,6 +294,29 @@ module InertiaRails
|
|
|
278
294
|
true
|
|
279
295
|
end
|
|
280
296
|
|
|
297
|
+
def excluded_by_once_cache?(prop, path)
|
|
298
|
+
return false unless prop.try(:once?)
|
|
299
|
+
return false if prop.try(:fresh?)
|
|
300
|
+
return false if explicitly_requested?(path)
|
|
301
|
+
|
|
302
|
+
once_key = (prop.once_key || path.join('.')).to_s
|
|
303
|
+
except_once_keys.include?(once_key)
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
def explicitly_requested?(path)
|
|
307
|
+
return false unless rendering_partial_component? && partial_keys.present?
|
|
308
|
+
|
|
309
|
+
path_with_prefixes = path_prefixes(path)
|
|
310
|
+
(path_with_prefixes & partial_keys).any?
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
def excluded_by_partial_request?(path)
|
|
314
|
+
return false unless rendering_partial_component? && (partial_keys.present? || partial_except_keys.present?)
|
|
315
|
+
|
|
316
|
+
path_with_prefixes = path_prefixes(path)
|
|
317
|
+
excluded_by_only_partial_keys?(path_with_prefixes) || excluded_by_except_partial_keys?(path_with_prefixes)
|
|
318
|
+
end
|
|
319
|
+
|
|
281
320
|
def path_prefixes(parts)
|
|
282
321
|
(0...parts.length).map do |i|
|
|
283
322
|
parts[0..i].join('.')
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: inertia_rails
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.15.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Brian Knoles
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
- Eugene Granovsky
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2025-
|
|
12
|
+
date: 2025-12-12 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: railties
|
|
@@ -200,8 +200,10 @@ files:
|
|
|
200
200
|
- lib/inertia_rails/meta_tag.rb
|
|
201
201
|
- lib/inertia_rails/meta_tag_builder.rb
|
|
202
202
|
- lib/inertia_rails/middleware.rb
|
|
203
|
+
- lib/inertia_rails/once_prop.rb
|
|
203
204
|
- lib/inertia_rails/optional_prop.rb
|
|
204
205
|
- lib/inertia_rails/prop_mergeable.rb
|
|
206
|
+
- lib/inertia_rails/prop_onceable.rb
|
|
205
207
|
- lib/inertia_rails/renderer.rb
|
|
206
208
|
- lib/inertia_rails/rspec.rb
|
|
207
209
|
- lib/inertia_rails/scroll_metadata.rb
|