inertia_rails 3.5.0 → 3.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +20 -0
  3. data/LICENSE.txt +1 -1
  4. data/README.md +11 -6
  5. data/lib/generators/inertia/install/install_generator.rb +5 -8
  6. data/lib/generators/inertia/install/templates/react/InertiaExample.tsx +1 -1
  7. data/lib/generators/inertia/install/templates/react/inertia.ts +3 -3
  8. data/lib/generators/inertia/install/templates/svelte/InertiaExample.svelte +1 -1
  9. data/lib/generators/inertia/install/templates/svelte/InertiaExample.ts.svelte +1 -1
  10. data/lib/generators/inertia/install/templates/svelte/inertia.js +3 -3
  11. data/lib/generators/inertia/install/templates/svelte/inertia.ts.tt +4 -4
  12. data/lib/generators/inertia/install/templates/svelte4/InertiaExample.svelte +1 -1
  13. data/lib/generators/inertia/install/templates/svelte4/InertiaExample.ts.svelte +1 -1
  14. data/lib/generators/inertia/install/templates/svelte4/inertia.js +3 -3
  15. data/lib/generators/inertia/install/templates/svelte4/inertia.ts.tt +4 -4
  16. data/lib/generators/inertia/install/templates/tailwind/application.css +3 -12
  17. data/lib/generators/inertia/install/templates/vue/InertiaExample.ts.vue +1 -1
  18. data/lib/generators/inertia/install/templates/vue/InertiaExample.vue +1 -1
  19. data/lib/generators/inertia/install/templates/vue/inertia.ts +3 -3
  20. data/lib/inertia_rails/configuration.rb +3 -0
  21. data/lib/inertia_rails/controller.rb +8 -3
  22. data/lib/inertia_rails/defer_prop.rb +21 -0
  23. data/lib/inertia_rails/generators/helper.rb +9 -7
  24. data/lib/inertia_rails/ignore_on_first_load_prop.rb +6 -0
  25. data/lib/inertia_rails/inertia_rails.rb +16 -0
  26. data/lib/inertia_rails/lazy_prop.rb +5 -1
  27. data/lib/inertia_rails/merge_prop.rb +14 -0
  28. data/lib/inertia_rails/middleware.rb +7 -2
  29. data/lib/inertia_rails/optional_prop.rb +6 -0
  30. data/lib/inertia_rails/renderer.rb +39 -7
  31. data/lib/inertia_rails/rspec.rb +5 -6
  32. data/lib/inertia_rails/version.rb +1 -1
  33. data/lib/inertia_rails.rb +2 -0
  34. metadata +7 -8
  35. data/lib/generators/inertia/install/templates/tailwind/postcss.config.js +0 -6
  36. data/lib/generators/inertia/install/templates/tailwind/tailwind.config.js.tt +0 -18
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ef66baa0e1a57eca72a52421858b7d0f1cc27e6bd0bbf09f53d2c6440b677b94
4
- data.tar.gz: 832a854fc9e749a365d3745521d256834eb778693e256cdda2321253eda47332
3
+ metadata.gz: 9d06f57228ce3ff3b4dba1d2b7bdf99deaa110c8b85c474c106baa989dd1bf8c
4
+ data.tar.gz: ec01c88da7419b8dbf1cc1243eced6fd38c10a7fba1c21d75def08ae1516cf01
5
5
  SHA512:
6
- metadata.gz: 1dc4a22fe2d2fd31fc1284030f2cc64f292cdc1224b15e37e2370d4f5b081c6240f6ed3340f827ccb9c0ad0b0022acdd51001ca3585c404ca1033b93b2503666
7
- data.tar.gz: 9becf43df35016ef9659f0055439b599c88d0a422eec1d6728bbf22b2393cb16bd5b177b697044651a9c79c51be332d5a9564969b6773f0815fada77d6408fae
6
+ metadata.gz: 6506c7ae154865ed78172e6f6bc2f28ff09cc8ee00faf25cb9d687f53143c9cbe7e105dbc297c028ceb29189070e63ba5484ecdf4c7217115b2d46b090389321
7
+ data.tar.gz: 7891ba539d642509920d1ab0d17c7c79e6bfbb1399c93c1c298a1ed20367b5a758352c644fc2794ea2309053a452643d807a26a1167b67a93e68febeabe9170e
data/CHANGELOG.md CHANGED
@@ -4,6 +4,26 @@ 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.6.1] - 2025-02-04
8
+
9
+ * Install generator tweaks @skryukov
10
+ * Performance improvement for oj serialization users @alexspeller
11
+ * Doc updates @youyoumu
12
+ * Doc updates @pedroaugustoramalhoduarte
13
+ * Tailwind v4 support in install generators @arandilopez
14
+ * Various CI fixes @bknoles / @skryukov
15
+
16
+ ## [3.6.0] - 2024-12-13
17
+
18
+ Support for the v2.0 Inertia.js release! It's a minor bump because there are no breaking changes!
19
+
20
+ Kudos to @skryukov and @PedroAugustoRamalhoDuarte for driving the features in this release!
21
+
22
+ * InertiaRails.defer for deferred props
23
+ * History encryption
24
+ * InertiaRails.merge for merge props
25
+ * InertiaRails.optional props (replaces lazy props in v2.0, InertiaRails.lazy now has a deprecation warning)
26
+
7
27
  ## [3.5.0] - 2024-11-29
8
28
 
9
29
  * Add Algolia search for docs (#151, @skryukov)
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2019 TODO: Bellawatt
3
+ Copyright (c) 2025 Bellawatt
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -188,15 +188,12 @@ end
188
188
  }
189
189
  ```
190
190
 
191
- ### Lazy Props
191
+ ### Optional Props
192
192
 
193
- On the front end, Inertia supports the concept of "partial reloads" where only the props requested are returned by the server. Sometimes, you may want to use this flow to avoid processing a particularly slow prop on the intial load. In this case, you can use Lazy props. Lazy props aren't evaluated unless they're specifically requested by name in a partial reload.
193
+ On the frontend, Inertia supports the concept of "partial reloads" where only the props requested are returned by the server. Sometimes, you may want to use this flow to avoid processing a particularly slow prop on the initial load. In this case, you can use Optional props. Optional props aren't evaluated unless they're specifically requested by name in a partial reload.
194
194
 
195
195
  ```ruby
196
- inertia_share some_data: InertiaRails.lazy(lambda { some_very_slow_method })
197
-
198
- # Using a Ruby block syntax
199
- inertia_share some_data: InertiaRails.lazy { some_very_slow_method }
196
+ inertia_share some_data: InertiaRails.optional { some_very_slow_method }
200
197
  ```
201
198
 
202
199
  ### Routing
@@ -269,6 +266,14 @@ end
269
266
 
270
267
  __Default__: `false`
271
268
 
269
+ #### `encrypt_history`
270
+
271
+ When enabled, you instruct Inertia to encrypt your app's history, it uses
272
+ the browser's built-in [`crypto` api](https://developer.mozilla.org/en-US/docs/Web/API/Crypto)
273
+ to encrypt the current page's data before pushing it to the history state.
274
+
275
+ __Default__: `false`
276
+
272
277
  #### `ssr_enabled` _(experimental)_
273
278
 
274
279
  Whether to use a JavaScript server to pre-render your JavaScript pages,
@@ -78,8 +78,7 @@ module Inertia
78
78
  template 'initializer.rb', file_path('config/initializers/inertia_rails.rb')
79
79
 
80
80
  say 'Installing Inertia npm packages'
81
- add_dependencies(*FRAMEWORKS[framework]['packages'])
82
- add_dependencies(inertia_package)
81
+ add_dependencies(inertia_package, *FRAMEWORKS[framework]['packages'])
83
82
 
84
83
  unless File.read(vite_config_path).include?(FRAMEWORKS[framework]['vite_plugin_import'])
85
84
  say "Adding Vite plugin for #{framework}"
@@ -152,11 +151,9 @@ module Inertia
152
151
 
153
152
  def install_tailwind
154
153
  say 'Installing Tailwind CSS'
155
- add_dependencies(%w[tailwindcss postcss autoprefixer @tailwindcss/forms @tailwindcss/typography
156
- @tailwindcss/container-queries])
157
-
158
- template 'tailwind/tailwind.config.js', file_path('tailwind.config.js')
159
- copy_file 'tailwind/postcss.config.js', file_path('postcss.config.js')
154
+ add_dependencies(%w[tailwindcss @tailwindcss/vite @tailwindcss/forms @tailwindcss/typography])
155
+ prepend_file vite_config_path, "import tailwindcss from '@tailwindcss/vite'\n"
156
+ insert_into_file vite_config_path, "\n tailwindcss(),", after: 'plugins: ['
160
157
  copy_file 'tailwind/application.css', js_file_path('entrypoints/application.css')
161
158
 
162
159
  if application_layout.exist?
@@ -266,7 +263,7 @@ module Inertia
266
263
 
267
264
  def inertia_resolved_version
268
265
  @inertia_resolved_version ||= Gem::Version.new(
269
- `npm show @inertiajs/core@#{options[:inertia_version]} version`.strip
266
+ `npm show @inertiajs/core@#{options[:inertia_version]} version --json | tail -n2 | head -n1 | tr -d '", '`.strip
270
267
  )
271
268
  end
272
269
 
@@ -18,7 +18,7 @@ export default function InertiaExample({ name }: { name: string }) {
18
18
  <h1 className={cs.h1}>Hello {name}!</h1>
19
19
 
20
20
  <div>
21
- <a href="https://inertia-rails.netlify.app" target="_blank">
21
+ <a href="https://inertia-rails.dev" target="_blank">
22
22
  <img className={cs.logo} src={inertiaSvg} alt="Inertia logo" />
23
23
  </a>
24
24
  <a href="https://vite-ruby.netlify.app" target="_blank">
@@ -10,13 +10,13 @@ type ResolvedComponent = {
10
10
 
11
11
  createInertiaApp({
12
12
  // Set default page title
13
- // see https://inertia-rails.netlify.app/guide/title-and-meta
13
+ // see https://inertia-rails.dev/guide/title-and-meta
14
14
  //
15
15
  // title: title => title ? `${title} - App` : 'App',
16
16
 
17
17
  // Disable progress bar
18
18
  //
19
- // see https://inertia-rails.netlify.app/guide/progress-indicators
19
+ // see https://inertia-rails.dev/guide/progress-indicators
20
20
  // progress: false,
21
21
 
22
22
  resolve: (name) => {
@@ -30,7 +30,7 @@ createInertiaApp({
30
30
 
31
31
  // To use a default layout, import the Layout component
32
32
  // and use the following line.
33
- // see https://inertia-rails.netlify.app/guide/pages#default-layouts
33
+ // see https://inertia-rails.dev/guide/pages#default-layouts
34
34
  //
35
35
  // page.default.layout ||= (page) => createElement(Layout, null, page)
36
36
 
@@ -16,7 +16,7 @@
16
16
  <h1>Hello {name}!</h1>
17
17
 
18
18
  <div>
19
- <a href="https://inertia-rails.netlify.app" target="_blank">
19
+ <a href="https://inertia-rails.dev" target="_blank">
20
20
  <img class="logo" src={inertiaSvg} alt="Inertia logo" />
21
21
  </a>
22
22
  <a href="https://vite-ruby.netlify.app" target="_blank">
@@ -16,7 +16,7 @@
16
16
  <h1>Hello {name}!</h1>
17
17
 
18
18
  <div>
19
- <a href="https://inertia-rails.netlify.app" target="_blank">
19
+ <a href="https://inertia-rails.dev" target="_blank">
20
20
  <img class="logo" src={inertiaSvg} alt="Inertia logo" />
21
21
  </a>
22
22
  <a href="https://vite-ruby.netlify.app" target="_blank">
@@ -3,13 +3,13 @@ import { mount } from 'svelte';
3
3
 
4
4
  createInertiaApp({
5
5
  // Set default page title
6
- // see https://inertia-rails.netlify.app/guide/title-and-meta
6
+ // see https://inertia-rails.dev/guide/title-and-meta
7
7
  //
8
8
  // title: title => title ? `${title} - App` : 'App',
9
9
 
10
10
  // Disable progress bar
11
11
  //
12
- // see https://inertia-rails.netlify.app/guide/progress-indicators
12
+ // see https://inertia-rails.dev/guide/progress-indicators
13
13
  // progress: false,
14
14
 
15
15
  resolve: (name) => {
@@ -23,7 +23,7 @@ createInertiaApp({
23
23
 
24
24
  // To use a default layout, import the Layout component
25
25
  // and use the following line.
26
- // see https://inertia-rails.netlify.app/guide/pages#default-layouts
26
+ // see https://inertia-rails.dev/guide/pages#default-layouts
27
27
  //
28
28
  // return { default: page.default, layout: page.layout || Layout }
29
29
 
@@ -3,13 +3,13 @@ import { mount } from 'svelte'
3
3
 
4
4
  createInertiaApp({
5
5
  // Set default page title
6
- // see https://inertia-rails.netlify.app/guide/title-and-meta
6
+ // see https://inertia-rails.dev/guide/title-and-meta
7
7
  //
8
8
  // title: title => title ? `${title} - App` : 'App',
9
9
 
10
10
  // Disable progress bar
11
11
  //
12
- // see https://inertia-rails.netlify.app/guide/progress-indicators
12
+ // see https://inertia-rails.dev/guide/progress-indicators
13
13
  // progress: false,
14
14
 
15
15
  resolve: (name) => {
@@ -23,7 +23,7 @@ createInertiaApp({
23
23
 
24
24
  // To use a default layout, import the Layout component
25
25
  // and use the following line.
26
- // see https://inertia-rails.netlify.app/guide/pages#default-layouts
26
+ // see https://inertia-rails.dev/guide/pages#default-layouts
27
27
  //
28
28
  // return { default: page.default, layout: page.layout || Layout }
29
29
 
@@ -32,7 +32,7 @@ createInertiaApp({
32
32
 
33
33
  setup({ el, App, props }) {
34
34
  if (el) {
35
- <%= " // @ts-expect-error 1.3.0 beta contains types mismatch\n" if inertia_resolved_version == Gem::Version.new('1.3.0-beta.2') -%>
35
+ <%= " // @ts-expect-error 1.3.0 contains types mismatch\n" if inertia_resolved_version.release == Gem::Version.new('1.3.0') -%>
36
36
  mount(App, { target: el, props })
37
37
  } else {
38
38
  console.error(
@@ -20,7 +20,7 @@
20
20
  <h1>Hello {name}!</h1>
21
21
 
22
22
  <div>
23
- <a href="https://inertia-rails.netlify.app" target="_blank">
23
+ <a href="https://inertia-rails.dev/" target="_blank">
24
24
  <img class="logo" src={inertiaSvg} alt="Inertia logo" />
25
25
  </a>
26
26
  <a href="https://vite-ruby.netlify.app" target="_blank">
@@ -20,7 +20,7 @@
20
20
  <h1>Hello {name}!</h1>
21
21
 
22
22
  <div>
23
- <a href="https://inertia-rails.netlify.app" target="_blank">
23
+ <a href="https://inertia-rails.dev" target="_blank">
24
24
  <img class="logo" src={inertiaSvg} alt="Inertia logo" />
25
25
  </a>
26
26
  <a href="https://vite-ruby.netlify.app" target="_blank">
@@ -2,13 +2,13 @@ import { createInertiaApp } from '@inertiajs/svelte'
2
2
 
3
3
  createInertiaApp({
4
4
  // Set default page title
5
- // see https://inertia-rails.netlify.app/guide/title-and-meta
5
+ // see https://inertia-rails.dev/guide/title-and-meta
6
6
  //
7
7
  // title: title => title ? `${title} - App` : 'App',
8
8
 
9
9
  // Disable progress bar
10
10
  //
11
- // see https://inertia-rails.netlify.app/guide/progress-indicators
11
+ // see https://inertia-rails.dev/guide/progress-indicators
12
12
  // progress: false,
13
13
 
14
14
  resolve: (name) => {
@@ -22,7 +22,7 @@ createInertiaApp({
22
22
 
23
23
  // To use a default layout, import the Layout component
24
24
  // and use the following lines.
25
- // see https://inertia-rails.netlify.app/guide/pages#default-layouts
25
+ // see https://inertia-rails.dev/guide/pages#default-layouts
26
26
  //
27
27
  // return { default: page.default, layout: page.layout || Layout }
28
28
 
@@ -2,13 +2,13 @@ import { createInertiaApp, type ResolvedComponent } from '@inertiajs/svelte'
2
2
 
3
3
  createInertiaApp({
4
4
  // Set default page title
5
- // see https://inertia-rails.netlify.app/guide/title-and-meta
5
+ // see https://inertia-rails.dev/guide/title-and-meta
6
6
  //
7
7
  // title: title => title ? `${title} - App` : 'App',
8
8
 
9
9
  // Disable progress bar
10
10
  //
11
- // see https://inertia-rails.netlify.app/guide/progress-indicators
11
+ // see https://inertia-rails.dev/guide/progress-indicators
12
12
  // progress: false,
13
13
 
14
14
  resolve: (name) => {
@@ -22,7 +22,7 @@ createInertiaApp({
22
22
 
23
23
  // To use a default layout, import the Layout component
24
24
  // and use the following line.
25
- // see https://inertia-rails.netlify.app/guide/pages#default-layouts
25
+ // see https://inertia-rails.dev/guide/pages#default-layouts
26
26
  //
27
27
  // return { default: page.default, layout: page.layout || Layout }
28
28
 
@@ -31,7 +31,7 @@ createInertiaApp({
31
31
 
32
32
  setup({ el, App, props }) {
33
33
  if (el) {
34
- <%= "// @ts-expect-error 1.3.0 beta contains types mismatch\n" if inertia_resolved_version == Gem::Version.new('1.3.0-beta.2') -%>
34
+ <%= "// @ts-expect-error 1.3.0 beta contains types mismatch\n" if inertia_resolved_version.release == Gem::Version.new('1.3.0') -%>
35
35
  new App({ target: el, props })
36
36
  } else {
37
37
  console.error(
@@ -1,13 +1,4 @@
1
- @tailwind base;
2
- @tailwind components;
3
- @tailwind utilities;
1
+ @import "tailwindcss";
4
2
 
5
- /*
6
-
7
- @layer components {
8
- .btn-primary {
9
- @apply py-2 px-4 bg-blue-200;
10
- }
11
- }
12
-
13
- */
3
+ @plugin "@tailwindcss/typography";
4
+ @plugin "@tailwindcss/forms";
@@ -5,7 +5,7 @@
5
5
  <h1 class="h1">Hello {{ name }}!</h1>
6
6
 
7
7
  <div>
8
- <a href="https://inertia-rails.netlify.app" target="_blank">
8
+ <a href="https://inertia-rails.dev" target="_blank">
9
9
  <img class="logo" :src="inertiaSvg" alt="Inertia logo" />
10
10
  </a>
11
11
  <a href="https://vite-ruby.netlify.app" target="_blank">
@@ -5,7 +5,7 @@
5
5
  <h1 class="h1">Hello {{ name }}!</h1>
6
6
 
7
7
  <div>
8
- <a href="https://inertia-rails.netlify.app" target="_blank">
8
+ <a href="https://inertia-rails.dev" target="_blank">
9
9
  <img class="logo" :src="inertiaSvg" alt="Inertia logo" />
10
10
  </a>
11
11
  <a href="https://vite-ruby.netlify.app" target="_blank">
@@ -3,13 +3,13 @@ import { createApp, DefineComponent, h } from 'vue'
3
3
 
4
4
  createInertiaApp({
5
5
  // Set default page title
6
- // see https://inertia-rails.netlify.app/guide/title-and-meta
6
+ // see https://inertia-rails.dev/guide/title-and-meta
7
7
  //
8
8
  // title: title => title ? `${title} - App` : 'App',
9
9
 
10
10
  // Disable progress bar
11
11
  //
12
- // see https://inertia-rails.netlify.app/guide/progress-indicators
12
+ // see https://inertia-rails.dev/guide/progress-indicators
13
13
  // progress: false,
14
14
 
15
15
  resolve: (name) => {
@@ -20,7 +20,7 @@ createInertiaApp({
20
20
 
21
21
  // To use a default layout, import the Layout component
22
22
  // and use the following lines.
23
- // see https://inertia-rails.netlify.app/guide/pages#default-layouts
23
+ // see https://inertia-rails.dev/guide/pages#default-layouts
24
24
  //
25
25
  // const page = pages[`../pages/${name}.vue`]
26
26
  // page.default.layout = page.default.layout || Layout
@@ -16,6 +16,9 @@ module InertiaRails
16
16
  # controller configuration.
17
17
  layout: true,
18
18
 
19
+ # Whether to encrypt the history state in the client.
20
+ encrypt_history: false,
21
+
19
22
  # SSR options.
20
23
  ssr_enabled: false,
21
24
  ssr_url: 'http://localhost:13714',
@@ -123,7 +123,7 @@ module InertiaRails
123
123
  end
124
124
 
125
125
  def redirect_to(options = {}, response_options = {})
126
- capture_inertia_errors(response_options)
126
+ capture_inertia_session_options(response_options)
127
127
  super
128
128
  end
129
129
 
@@ -155,8 +155,10 @@ module InertiaRails
155
155
  head :conflict
156
156
  end
157
157
 
158
- def capture_inertia_errors(options)
159
- if (inertia_errors = options.dig(:inertia, :errors))
158
+ def capture_inertia_session_options(options)
159
+ return unless (inertia = options[:inertia])
160
+
161
+ if (inertia_errors = inertia[:errors])
160
162
  if inertia_errors.respond_to?(:to_hash)
161
163
  session[:inertia_errors] = inertia_errors.to_hash
162
164
  else
@@ -165,7 +167,10 @@ module InertiaRails
165
167
  )
166
168
  session[:inertia_errors] = inertia_errors
167
169
  end
170
+
168
171
  end
172
+
173
+ session[:inertia_clear_history] = inertia[:clear_history] if inertia[:clear_history]
169
174
  end
170
175
  end
171
176
  end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module InertiaRails
4
+ class DeferProp < IgnoreOnFirstLoadProp
5
+ DEFAULT_GROUP = 'default'
6
+
7
+ attr_reader :group
8
+
9
+ def initialize(group: nil, merge: nil, &block)
10
+ super(&block)
11
+
12
+ @group = group || DEFAULT_GROUP
13
+ @merge = merge
14
+ @block = block
15
+ end
16
+
17
+ def merge?
18
+ @merge
19
+ end
20
+ end
21
+ end
@@ -4,14 +4,16 @@ module InertiaRails
4
4
  module Generators
5
5
  module Helper
6
6
  class << self
7
- def guess_the_default_framework
8
- package = Rails.root.join('package.json').read
9
- case package
10
- when %r{@inertiajs/react}
7
+ def guess_the_default_framework(package_json_path = Rails.root.join('package.json'))
8
+ package_json = JSON.parse(package_json_path.read)
9
+ dependencies = package_json['dependencies'] || {}
10
+
11
+ if dependencies['@inertiajs/react']
11
12
  'react'
12
- when %r{@inertiajs/svelte}
13
- package.match?(/"svelte": "\^5/) ? 'svelte' : 'svelte4'
14
- when %r{@inertiajs/vue3}
13
+ elsif dependencies['@inertiajs/svelte']
14
+ version = dependencies['svelte'].gsub(/[\^~]/, '') # Remove ^ or ~ from version
15
+ version.start_with?('5') ? 'svelte' : 'svelte4'
16
+ elsif dependencies['@inertiajs/vue3']
15
17
  'vue'
16
18
  else
17
19
  Thor::Shell::Basic.new.say_error 'Could not determine the Inertia.js framework you are using.'
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module InertiaRails
4
+ class IgnoreOnFirstLoadProp < BaseProp
5
+ end
6
+ end
@@ -1,6 +1,10 @@
1
1
  require 'inertia_rails/base_prop'
2
+ require 'inertia_rails/ignore_on_first_load_prop'
2
3
  require 'inertia_rails/always_prop'
3
4
  require 'inertia_rails/lazy_prop'
5
+ require 'inertia_rails/optional_prop'
6
+ require 'inertia_rails/defer_prop'
7
+ require 'inertia_rails/merge_prop'
4
8
  require 'inertia_rails/configuration'
5
9
 
6
10
  module InertiaRails
@@ -19,8 +23,20 @@ module InertiaRails
19
23
  LazyProp.new(value, &block)
20
24
  end
21
25
 
26
+ def optional(&block)
27
+ OptionalProp.new(&block)
28
+ end
29
+
22
30
  def always(&block)
23
31
  AlwaysProp.new(&block)
24
32
  end
33
+
34
+ def merge(&block)
35
+ MergeProp.new(&block)
36
+ end
37
+
38
+ def defer(group: nil, merge: nil, &block)
39
+ DeferProp.new(group: group, merge: merge, &block)
40
+ end
25
41
  end
26
42
  end
@@ -1,10 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module InertiaRails
4
- class LazyProp < BaseProp
4
+ class LazyProp < IgnoreOnFirstLoadProp
5
5
  def initialize(value = nil, &block)
6
6
  raise ArgumentError, 'You must provide either a value or a block, not both' if value && block
7
7
 
8
+ InertiaRails.deprecator.warn(
9
+ '`lazy` is deprecated and will be removed in InertiaRails 4.0, use `optional` instead.'
10
+ )
11
+
8
12
  @value = value
9
13
  @block = block
10
14
  end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module InertiaRails
4
+ class MergeProp < BaseProp
5
+ def initialize(*)
6
+ super
7
+ @merge = true
8
+ end
9
+
10
+ def merge?
11
+ @merge
12
+ end
13
+ end
14
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module InertiaRails
2
4
  class Middleware
3
5
  def initialize(app)
@@ -20,7 +22,10 @@ module InertiaRails
20
22
  request = ActionDispatch::Request.new(@env)
21
23
 
22
24
  # Inertia errors are added to the session via redirect_to
23
- request.session.delete(:inertia_errors) unless keep_inertia_errors?(status)
25
+ unless keep_inertia_session_options?(status)
26
+ request.session.delete(:inertia_errors)
27
+ request.session.delete(:inertia_clear_history)
28
+ end
24
29
 
25
30
  status = 303 if inertia_non_post_redirect?(status)
26
31
 
@@ -29,7 +34,7 @@ module InertiaRails
29
34
 
30
35
  private
31
36
 
32
- def keep_inertia_errors?(status)
37
+ def keep_inertia_session_options?(status)
33
38
  redirect_status?(status) || stale_inertia_request?
34
39
  end
35
40
 
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module InertiaRails
4
+ class OptionalProp < IgnoreOnFirstLoadProp
5
+ end
6
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'net/http'
4
4
  require 'json'
5
- require_relative "inertia_rails"
5
+ require_relative 'inertia_rails'
6
6
 
7
7
  module InertiaRails
8
8
  class Renderer
@@ -15,9 +15,11 @@ module InertiaRails
15
15
  :controller,
16
16
  :props,
17
17
  :view_data,
18
+ :encrypt_history,
19
+ :clear_history
18
20
  )
19
21
 
20
- def initialize(component, controller, request, response, render_method, props: nil, view_data: nil, deep_merge: nil)
22
+ def initialize(component, controller, request, response, render_method, props: nil, view_data: nil, deep_merge: nil, encrypt_history: nil, clear_history: nil)
21
23
  @controller = controller
22
24
  @configuration = controller.__send__(:inertia_configuration)
23
25
  @component = resolve_component(component)
@@ -27,6 +29,8 @@ module InertiaRails
27
29
  @props = props || controller.__send__(:inertia_view_assigns)
28
30
  @view_data = view_data || {}
29
31
  @deep_merge = !deep_merge.nil? ? deep_merge : configuration.deep_merge_shared_data
32
+ @encrypt_history = !encrypt_history.nil? ? encrypt_history : configuration.encrypt_history
33
+ @clear_history = clear_history || controller.session[:inertia_clear_history] || false
30
34
  end
31
35
 
32
36
  def render
@@ -37,7 +41,7 @@ module InertiaRails
37
41
  end
38
42
  if @request.headers['X-Inertia']
39
43
  @response.set_header('X-Inertia', 'true')
40
- @render_method.call json: page, status: @response.status, content_type: Mime[:json]
44
+ @render_method.call json: page.to_json, status: @response.status, content_type: Mime[:json]
41
45
  else
42
46
  return render_ssr if configuration.ssr_enabled rescue nil
43
47
  @render_method.call template: 'inertia', layout: layout, locals: view_data.merge(page: page)
@@ -96,12 +100,22 @@ module InertiaRails
96
100
  end
97
101
 
98
102
  def page
99
- {
103
+ default_page = {
100
104
  component: component,
101
105
  props: computed_props,
102
106
  url: @request.original_fullpath,
103
107
  version: configuration.version,
108
+ encryptHistory: encrypt_history,
109
+ clearHistory: clear_history,
104
110
  }
111
+
112
+ deferred_props = deferred_props_keys
113
+ default_page[:deferredProps] = deferred_props if deferred_props.present?
114
+
115
+ merge_props = merge_props_keys
116
+ default_page[:mergeProps] = merge_props if merge_props.present?
117
+
118
+ default_page
105
119
  end
106
120
 
107
121
  def deep_transform_props(props, parent_path = [], &block)
@@ -120,8 +134,26 @@ module InertiaRails
120
134
  end
121
135
  end
122
136
 
137
+ def deferred_props_keys
138
+ return if rendering_partial_component?
139
+
140
+ @props.each_with_object({}) do |(key, prop), result|
141
+ (result[prop.group] ||= []) << key if prop.is_a?(DeferProp)
142
+ end
143
+ end
144
+
145
+ def merge_props_keys
146
+ @props.each_with_object([]) do |(key, prop), result|
147
+ result << key if prop.try(:merge?) && reset_keys.exclude?(key)
148
+ end
149
+ end
150
+
123
151
  def partial_keys
124
- (@request.headers['X-Inertia-Partial-Data'] || '').split(',').compact
152
+ @partial_keys ||= (@request.headers['X-Inertia-Partial-Data'] || '').split(',').compact
153
+ end
154
+
155
+ def reset_keys
156
+ (@request.headers['X-Inertia-Reset'] || '').split(',').compact.map(&:to_sym)
125
157
  end
126
158
 
127
159
  def partial_except_keys
@@ -147,8 +179,8 @@ module InertiaRails
147
179
  return false if excluded_by_except_partial_keys?(path_with_prefixes)
148
180
  end
149
181
 
150
- # Precedence: Evaluate LazyProp only after partial keys have been checked
151
- return false if prop.is_a?(LazyProp) && !rendering_partial_component?
182
+ # Precedence: Evaluate IgnoreOnFirstLoadProp only after partial keys have been checked
183
+ return false if prop.is_a?(IgnoreOnFirstLoadProp) && !rendering_partial_component?
152
184
 
153
185
  true
154
186
  end
@@ -32,8 +32,9 @@ module InertiaRails
32
32
  else
33
33
  # Sequential Inertia request
34
34
  @view_data = {}
35
- @props = params[:json][:props]
36
- @component = params[:json][:component]
35
+ json = JSON.parse(params[:json])
36
+ @props = json["props"]
37
+ @component = json["component"]
37
38
  end
38
39
  end
39
40
  end
@@ -81,8 +82,7 @@ end
81
82
 
82
83
  RSpec::Matchers.define :have_exact_props do |expected_props|
83
84
  match do |inertia|
84
- # Computed props have symbolized keys.
85
- expect(inertia.props).to eq expected_props.deep_symbolize_keys
85
+ expect(inertia.props).to eq expected_props
86
86
  end
87
87
 
88
88
  failure_message do |inertia|
@@ -92,8 +92,7 @@ end
92
92
 
93
93
  RSpec::Matchers.define :include_props do |expected_props|
94
94
  match do |inertia|
95
- # Computed props have symbolized keys.
96
- expect(inertia.props).to include expected_props.deep_symbolize_keys
95
+ expect(inertia.props).to include expected_props
97
96
  end
98
97
 
99
98
  failure_message do |inertia|
@@ -1,3 +1,3 @@
1
1
  module InertiaRails
2
- VERSION = "3.5.0"
2
+ VERSION = "3.6.1"
3
3
  end
data/lib/inertia_rails.rb CHANGED
@@ -16,6 +16,8 @@ ActionController::Renderers.add :inertia do |component, options|
16
16
  props: options[:props],
17
17
  view_data: options[:view_data],
18
18
  deep_merge: options[:deep_merge],
19
+ encrypt_history: options[:encrypt_history],
20
+ clear_history: options[:clear_history],
19
21
  ).render
20
22
  end
21
23
 
metadata CHANGED
@@ -1,16 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inertia_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.5.0
4
+ version: 3.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Knoles
8
8
  - Brandon Shar
9
9
  - Eugene Granovsky
10
- autorequire:
11
10
  bindir: bin
12
11
  cert_chain: []
13
- date: 2024-11-29 00:00:00.000000000 Z
12
+ date: 2025-02-05 00:00:00.000000000 Z
14
13
  dependencies:
15
14
  - !ruby/object:Gem::Dependency
16
15
  name: railties
@@ -81,8 +80,6 @@ files:
81
80
  - lib/generators/inertia/install/templates/svelte4/tsconfig.node.json
82
81
  - lib/generators/inertia/install/templates/svelte4/vite-env.d.ts
83
82
  - lib/generators/inertia/install/templates/tailwind/application.css
84
- - lib/generators/inertia/install/templates/tailwind/postcss.config.js
85
- - lib/generators/inertia/install/templates/tailwind/tailwind.config.js.tt
86
83
  - lib/generators/inertia/install/templates/vue/InertiaExample.ts.vue
87
84
  - lib/generators/inertia/install/templates/vue/InertiaExample.vue
88
85
  - lib/generators/inertia/install/templates/vue/inertia.js
@@ -218,14 +215,18 @@ files:
218
215
  - lib/inertia_rails/base_prop.rb
219
216
  - lib/inertia_rails/configuration.rb
220
217
  - lib/inertia_rails/controller.rb
218
+ - lib/inertia_rails/defer_prop.rb
221
219
  - lib/inertia_rails/engine.rb
222
220
  - lib/inertia_rails/generators/controller_template_base.rb
223
221
  - lib/inertia_rails/generators/helper.rb
224
222
  - lib/inertia_rails/generators/scaffold_template_base.rb
225
223
  - lib/inertia_rails/helper.rb
224
+ - lib/inertia_rails/ignore_on_first_load_prop.rb
226
225
  - lib/inertia_rails/inertia_rails.rb
227
226
  - lib/inertia_rails/lazy_prop.rb
227
+ - lib/inertia_rails/merge_prop.rb
228
228
  - lib/inertia_rails/middleware.rb
229
+ - lib/inertia_rails/optional_prop.rb
229
230
  - lib/inertia_rails/renderer.rb
230
231
  - lib/inertia_rails/rspec.rb
231
232
  - lib/inertia_rails/version.rb
@@ -246,7 +247,6 @@ metadata:
246
247
  homepage_uri: https://github.com/inertiajs/inertia-rails
247
248
  source_code_uri: https://github.com/inertiajs/inertia-rails
248
249
  rubygems_mfa_required: 'true'
249
- post_install_message:
250
250
  rdoc_options: []
251
251
  require_paths:
252
252
  - lib
@@ -261,8 +261,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
261
261
  - !ruby/object:Gem::Version
262
262
  version: '0'
263
263
  requirements: []
264
- rubygems_version: 3.5.22
265
- signing_key:
264
+ rubygems_version: 3.6.2
266
265
  specification_version: 4
267
266
  summary: Inertia.js adapter for Rails
268
267
  test_files: []
@@ -1,6 +0,0 @@
1
- export default {
2
- plugins: {
3
- tailwindcss: {},
4
- autoprefixer: {},
5
- },
6
- }
@@ -1,18 +0,0 @@
1
- /** @type {import('tailwindcss').Config} */
2
-
3
- module.exports = {
4
- content: [
5
- './public/*.html',
6
- './app/helpers/**/*.rb',
7
- './<%= js_destination_path %>/**/*.{js,ts,jsx,tsx,vue,svelte}',
8
- './app/views/**/*.{erb,haml,html,slim}'
9
- ],
10
- theme: {
11
- extend: {},
12
- },
13
- plugins: [
14
- require('@tailwindcss/forms'),
15
- require('@tailwindcss/typography'),
16
- require('@tailwindcss/container-queries'),
17
- ]
18
- }