inertia_rails 3.15.0 → 3.16.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.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +7 -0
  3. data/lib/generators/inertia/install/helpers.rb +9 -0
  4. data/lib/generators/inertia/install/install_generator.rb +11 -26
  5. data/lib/generators/inertia/install/templates/inertia_controller.rb +3 -1
  6. data/lib/generators/inertia/install/templates/react/types/globals.d.ts +2 -1
  7. data/lib/generators/inertia/install/templates/react/types/index.ts +2 -4
  8. data/lib/generators/inertia/install/templates/svelte/types/globals.d.ts +2 -1
  9. data/lib/generators/inertia/install/templates/svelte/types/index.ts +2 -4
  10. data/lib/generators/inertia/install/templates/vue/types/globals.d.ts +2 -1
  11. data/lib/generators/inertia/install/templates/vue/types/index.ts +2 -4
  12. data/lib/generators/inertia/scaffold_controller/templates/controller.rb.tt +0 -4
  13. data/lib/generators/inertia_templates/scaffold/templates/react/index.jsx.tt +4 -2
  14. data/lib/generators/inertia_templates/scaffold/templates/react/index.tsx.tt +4 -3
  15. data/lib/generators/inertia_templates/scaffold/templates/react/show.jsx.tt +4 -2
  16. data/lib/generators/inertia_templates/scaffold/templates/react/show.tsx.tt +4 -3
  17. data/lib/generators/inertia_templates/scaffold/templates/svelte/index.svelte.tt +4 -4
  18. data/lib/generators/inertia_templates/scaffold/templates/svelte/index.ts.svelte.tt +4 -5
  19. data/lib/generators/inertia_templates/scaffold/templates/svelte/show.svelte.tt +4 -4
  20. data/lib/generators/inertia_templates/scaffold/templates/svelte/show.ts.svelte.tt +4 -5
  21. data/lib/generators/inertia_templates/scaffold/templates/vue/index.ts.vue.tt +3 -3
  22. data/lib/generators/inertia_templates/scaffold/templates/vue/index.vue.tt +3 -2
  23. data/lib/generators/inertia_templates/scaffold/templates/vue/show.ts.vue.tt +3 -3
  24. data/lib/generators/inertia_templates/scaffold/templates/vue/show.vue.tt +3 -2
  25. data/lib/generators/inertia_tw_templates/scaffold/templates/react/edit.jsx.tt +4 -4
  26. data/lib/generators/inertia_tw_templates/scaffold/templates/react/edit.tsx.tt +4 -4
  27. data/lib/generators/inertia_tw_templates/scaffold/templates/react/index.jsx.tt +4 -2
  28. data/lib/generators/inertia_tw_templates/scaffold/templates/react/index.tsx.tt +4 -3
  29. data/lib/generators/inertia_tw_templates/scaffold/templates/react/show.jsx.tt +4 -2
  30. data/lib/generators/inertia_tw_templates/scaffold/templates/react/show.tsx.tt +4 -3
  31. data/lib/generators/inertia_tw_templates/scaffold/templates/svelte/index.svelte.tt +4 -4
  32. data/lib/generators/inertia_tw_templates/scaffold/templates/svelte/index.ts.svelte.tt +4 -5
  33. data/lib/generators/inertia_tw_templates/scaffold/templates/svelte/show.svelte.tt +4 -4
  34. data/lib/generators/inertia_tw_templates/scaffold/templates/svelte/show.ts.svelte.tt +4 -5
  35. data/lib/generators/inertia_tw_templates/scaffold/templates/vue/index.ts.vue.tt +3 -3
  36. data/lib/generators/inertia_tw_templates/scaffold/templates/vue/index.vue.tt +3 -2
  37. data/lib/generators/inertia_tw_templates/scaffold/templates/vue/show.ts.vue.tt +3 -3
  38. data/lib/generators/inertia_tw_templates/scaffold/templates/vue/show.vue.tt +3 -2
  39. data/lib/inertia_rails/configuration.rb +4 -0
  40. data/lib/inertia_rails/controller.rb +12 -1
  41. data/lib/inertia_rails/engine.rb +6 -0
  42. data/lib/inertia_rails/flash_extension.rb +63 -0
  43. data/lib/inertia_rails/generators/helper.rb +0 -8
  44. data/lib/inertia_rails/inertia_rails.rb +2 -2
  45. data/lib/inertia_rails/middleware.rb +1 -1
  46. data/lib/inertia_rails/renderer.rb +3 -0
  47. data/lib/inertia_rails/version.rb +1 -1
  48. data/lib/patches/debug_exceptions.rb +8 -4
  49. metadata +3 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2460d1f62147b4360786f5caba3ed7525d0539da9b61acc65dd9c93f925d7e7b
4
- data.tar.gz: 741b89dd90fbf8b2fe212ef48ddd1e723ef69d9d13ffa5c35a3cc61d82443743
3
+ metadata.gz: dde0b293a9be9f560b828392e23a40cfb5ecb72f6c912e48660660640c211c9a
4
+ data.tar.gz: f72cce31fc538e2985f0be5c938c603ecfaeb03d0b6bafc682d32049c05f514f
5
5
  SHA512:
6
- metadata.gz: 06a2bca60142ca5d450b4640fe6fe4df5000b15da57b8830c7993563d827b6d9abec3c3cf036d6ca33cf931a745e40ca81a52706598293e0e619bc4ed5bcb207
7
- data.tar.gz: ee907ff350208d0e415aac873cc38b971d9a5fc8964b96dc502d031acd2af6ac5f6ab848163c2e56e60e3b855a1a7c95dc52fda1abbda5e1959a96cb00b068ac
6
+ metadata.gz: b4b064f174ceb0122be41945f045234d7caba21327bc750b9dd9bae49f5c14b17839a707e463b34f9ccaf0646f93f55b71d76fd22b1d31a11a6e12c324ed9afe
7
+ data.tar.gz: b38aa3f36e089e46a1f4d827ef32f9e1e12234e5490490cdc179cf90200bb2c6a7b7cbc66492d83df2a7d990b955ccf5e641f8718808a0391c1342ffa5256e1d
data/CHANGELOG.md CHANGED
@@ -4,6 +4,13 @@ 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.16.0] - 2025-12-30
8
+
9
+ * Fix optional once props (@skryukov)
10
+ * Support for new Flash API in Inertia.js page object (@skryukov)
11
+ * Generator improvements (@skryukov)
12
+ * Fix debug exceptions patch for Rails 8.2 (@crobbo)
13
+
7
14
  ## [3.15.0] - 2025-12-11
8
15
 
9
16
  * Support for rendering initial page data in a script tag (@skryukov)
@@ -31,6 +31,15 @@ module Inertia
31
31
  File.join(destination_root, *relative_path)
32
32
  end
33
33
 
34
+ def update_package_json
35
+ package_json_path = file_path('package.json')
36
+ package_json = JSON.parse(File.read(package_json_path))
37
+
38
+ yield package_json
39
+
40
+ File.write(package_json_path, "#{JSON.pretty_generate(package_json)}\n")
41
+ end
42
+
34
43
  # Interactivity Helpers
35
44
  def ask(*)
36
45
  unless options[:interactive]
@@ -49,11 +49,6 @@ module Inertia
49
49
  def install
50
50
  say "Installing Inertia's Rails adapter"
51
51
 
52
- if inertia_resolved_version.version == '0'
53
- say_error "Could not find the Inertia.js package version #{options[:inertia_version]}.", :red
54
- exit(false)
55
- end
56
-
57
52
  install_vite unless ruby_vite_installed?
58
53
 
59
54
  install_typescript if typescript?
@@ -137,14 +132,6 @@ module Inertia
137
132
 
138
133
  def install_typescript
139
134
  say 'Adding TypeScript support'
140
- if svelte? && inertia_resolved_version.release < Gem::Version.new('1.3.0')
141
- say 'WARNING: @inertiajs/svelte < 1.3.0 does not support TypeScript ' \
142
- "(resolved version: #{inertia_resolved_version}).",
143
- :yellow
144
- say 'Skipping TypeScript support for @inertiajs/svelte', :yellow
145
- @typescript = false
146
- return
147
- end
148
135
 
149
136
  add_dependencies(*FRAMEWORKS[framework]['packages_ts'])
150
137
 
@@ -165,12 +152,16 @@ module Inertia
165
152
  end
166
153
 
167
154
  say 'Adding TypeScript check scripts to package.json'
168
- if svelte?
169
- run 'npm pkg set scripts.check="svelte-check --tsconfig ./tsconfig.json && tsc -p tsconfig.node.json"'
170
- elsif react?
171
- run 'npm pkg set scripts.check="tsc -p tsconfig.app.json && tsc -p tsconfig.node.json"'
172
- elsif vue?
173
- run 'npm pkg set scripts.check="vue-tsc -p tsconfig.app.json && tsc -p tsconfig.node.json"'
155
+ update_package_json do |package_json|
156
+ package_json['scripts'] ||= {}
157
+ package_json['scripts']['check'] =
158
+ if svelte?
159
+ 'svelte-check --tsconfig ./tsconfig.json && tsc -p tsconfig.node.json'
160
+ elsif react?
161
+ 'tsc -p tsconfig.app.json && tsc -p tsconfig.node.json'
162
+ elsif vue?
163
+ 'vue-tsc -p tsconfig.app.json && tsc -p tsconfig.node.json'
164
+ end
174
165
  end
175
166
  end
176
167
 
@@ -225,6 +216,7 @@ module Inertia
225
216
  end
226
217
  if (capture = run('bundle exec vite install', capture: !verbose?))
227
218
  rename_application_js_to_ts if typescript?
219
+ run('bundle binstub vite_ruby', capture: !verbose?) if File.exist?(file_path('bin/vite'))
228
220
  say 'Vite Rails successfully installed', :green
229
221
  else
230
222
  say capture
@@ -325,13 +317,6 @@ module Inertia
325
317
  "#{tag} #{filename}"
326
318
  end
327
319
 
328
- def inertia_resolved_version
329
- package = "@inertiajs/core@#{options[:inertia_version]}"
330
- @inertia_resolved_version ||= Gem::Version.new(
331
- `npm show #{package} version --json | tail -n2 | head -n1 | tr -d '", '`.strip
332
- )
333
- end
334
-
335
320
  def verbose?
336
321
  options[:verbose]
337
322
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class InertiaController < ApplicationController
4
- inertia_share flash: -> { flash.to_hash }
4
+ # Share data with all Inertia responses
5
+ # see https://inertia-rails.dev/guide/shared-data
6
+ # inertia_share user: -> { Current.user&.as_json(only: [:id, :name, :email]) }
5
7
  end
@@ -1,8 +1,9 @@
1
- import type { SharedProps } from '@/types'
1
+ import type { FlashData, SharedProps } from '@/types'
2
2
 
3
3
  declare module '@inertiajs/core' {
4
4
  export interface InertiaConfig {
5
5
  sharedPageProps: SharedProps
6
+ flashDataType: FlashData
6
7
  errorValueType: string[]
7
8
  }
8
9
  }
@@ -1,8 +1,6 @@
1
- export type Flash = {
1
+ export type FlashData = {
2
2
  notice?: string
3
3
  alert?: string
4
4
  }
5
5
 
6
- export type SharedProps = {
7
- flash: Flash
8
- }
6
+ export type SharedProps = {}
@@ -1,8 +1,9 @@
1
- import type { SharedProps } from '@/types'
1
+ import type { FlashData, SharedProps } from '@/types'
2
2
 
3
3
  declare module '@inertiajs/core' {
4
4
  export interface InertiaConfig {
5
5
  sharedPageProps: SharedProps
6
+ flashDataType: FlashData
6
7
  errorValueType: string[]
7
8
  }
8
9
  }
@@ -1,8 +1,6 @@
1
- export type Flash = {
1
+ export type FlashData = {
2
2
  notice?: string
3
3
  alert?: string
4
4
  }
5
5
 
6
- export type SharedProps = {
7
- flash: Flash
8
- }
6
+ export type SharedProps = {}
@@ -1,8 +1,9 @@
1
- import type { SharedProps } from '@/types'
1
+ import type { FlashData, SharedProps } from '@/types'
2
2
 
3
3
  declare module '@inertiajs/core' {
4
4
  export interface InertiaConfig {
5
5
  sharedPageProps: SharedProps
6
+ flashDataType: FlashData
6
7
  errorValueType: string[]
7
8
  }
8
9
  }
@@ -1,8 +1,6 @@
1
- export type Flash = {
1
+ export type FlashData = {
2
2
  notice?: string
3
3
  alert?: string
4
4
  }
5
5
 
6
- export type SharedProps = {
7
- flash: Flash
8
- }
6
+ export type SharedProps = {}
@@ -5,10 +5,6 @@ class <%= controller_class_name %>Controller < <%= parent_controller %>
5
5
  <% if regular_class_path.any? -%>
6
6
  wrap_parameters :<%= singular_table_name %>
7
7
 
8
- <% end -%>
9
- <% if parent_controller != 'InertiaController' -%>
10
- inertia_share flash: -> { flash.to_hash }
11
-
12
8
  <% end -%>
13
9
  # GET <%= route_url %>
14
10
  def index
@@ -1,7 +1,9 @@
1
- import { Head, Link } from '@inertiajs/react'
1
+ import { Head, Link, usePage } from '@inertiajs/react'
2
2
  import <%= inertia_component_name %> from './<%= singular_name %>'
3
3
 
4
- export default function Index({ <%= plural_table_name %>, flash }) {
4
+ export default function Index({ <%= plural_table_name %> }) {
5
+ const { flash } = usePage()
6
+
5
7
  return (
6
8
  <>
7
9
  <Head title="<%= human_name.pluralize %>" />
@@ -1,13 +1,14 @@
1
- import { Head, Link } from '@inertiajs/react'
1
+ import { Head, Link, usePage } from '@inertiajs/react'
2
2
  import <%= inertia_component_name %> from './<%= singular_name %>'
3
3
  import { <%= inertia_model_type %> } from './types'
4
4
 
5
5
  interface IndexProps {
6
6
  <%= plural_table_name %>: <%= inertia_model_type %>[]
7
- flash: { notice?: string }
8
7
  }
9
8
 
10
- export default function Index({ <%= plural_table_name %>, flash }: IndexProps) {
9
+ export default function Index({ <%= plural_table_name %> }: IndexProps) {
10
+ const { flash } = usePage()
11
+
11
12
  return (
12
13
  <>
13
14
  <Head title="<%= human_name.pluralize %>" />
@@ -1,7 +1,9 @@
1
- import { Head, Link } from '@inertiajs/react'
1
+ import { Head, Link, usePage } from '@inertiajs/react'
2
2
  import <%= inertia_component_name %> from './<%= singular_name %>'
3
3
 
4
- export default function Show({ <%= singular_table_name %>, flash }) {
4
+ export default function Show({ <%= singular_table_name %> }) {
5
+ const { flash } = usePage()
6
+
5
7
  return (
6
8
  <>
7
9
  <Head title={`<%= human_name %> #${<%= singular_table_name %>.id}`} />
@@ -1,13 +1,14 @@
1
- import { Head, Link } from '@inertiajs/react'
1
+ import { Head, Link, usePage } from '@inertiajs/react'
2
2
  import <%= inertia_component_name %> from './<%= singular_name %>'
3
3
  import { <%= inertia_model_type %> } from './types'
4
4
 
5
5
  interface ShowProps {
6
6
  <%= singular_table_name %>: <%= inertia_model_type %>
7
- flash: { notice?: string }
8
7
  }
9
8
 
10
- export default function Show({ <%= singular_table_name %>, flash }: ShowProps) {
9
+ export default function Show({ <%= singular_table_name %> }: ShowProps) {
10
+ const { flash } = usePage()
11
+
11
12
  return (
12
13
  <>
13
14
  <Head title={`<%= human_name %> #${<%= singular_table_name %>.id}`} />
@@ -1,16 +1,16 @@
1
1
  <script>
2
- import { Link } from '@inertiajs/svelte'
2
+ import { Link, page } from '@inertiajs/svelte'
3
3
  import <%= inertia_component_name %> from './<%= singular_name %>.svelte'
4
4
 
5
- let { <%= plural_table_name %>, flash } = $props()
5
+ let { <%= plural_table_name %> } = $props()
6
6
  </script>
7
7
 
8
8
  <svelte:head>
9
9
  <title><%= human_name.pluralize %></title>
10
10
  </svelte:head>
11
11
 
12
- {#if flash.notice}
13
- <p class="notice">{flash.notice}</p>
12
+ {#if $page.flash.notice}
13
+ <p class="notice">{$page.flash.notice}</p>
14
14
  {/if}
15
15
 
16
16
  <h1><%= human_name.pluralize %></h1>
@@ -1,11 +1,10 @@
1
1
  <script lang="ts">
2
- import { Link } from '@inertiajs/svelte'
2
+ import { Link, page } from '@inertiajs/svelte'
3
3
  import <%= inertia_component_name %> from './<%= singular_name %>.svelte'
4
4
  import type { <%= inertia_model_type %> } from './types'
5
5
 
6
- let { <%= plural_table_name %>, flash } = $props<{
6
+ let { <%= plural_table_name %> } = $props<{
7
7
  <%= plural_table_name %>: <%= inertia_model_type %>[]
8
- flash: { notice?: string }
9
8
  }>()
10
9
  </script>
11
10
 
@@ -13,8 +12,8 @@
13
12
  <title><%= human_name.pluralize %></title>
14
13
  </svelte:head>
15
14
 
16
- {#if flash.notice}
17
- <p class="notice">{flash.notice}</p>
15
+ {#if $page.flash.notice}
16
+ <p class="notice">{$page.flash.notice}</p>
18
17
  {/if}
19
18
 
20
19
  <h1><%= human_name.pluralize %></h1>
@@ -1,16 +1,16 @@
1
1
  <script>
2
- import { Link } from '@inertiajs/svelte'
2
+ import { Link, page } from '@inertiajs/svelte'
3
3
  import <%= inertia_component_name %> from './<%= singular_name %>.svelte'
4
4
 
5
- let { <%= singular_table_name %>, flash } = $props()
5
+ let { <%= singular_table_name %> } = $props()
6
6
  </script>
7
7
 
8
8
  <svelte:head>
9
9
  <title><%= human_name %> #{<%= singular_table_name %>.id}</title>
10
10
  </svelte:head>
11
11
 
12
- {#if flash.notice}
13
- <p class="notice">{flash.notice}</p>
12
+ {#if $page.flash.notice}
13
+ <p class="notice">{$page.flash.notice}</p>
14
14
  {/if}
15
15
 
16
16
  <h1><%= human_name %> #{<%= singular_table_name %>.id}</h1>
@@ -1,11 +1,10 @@
1
1
  <script lang="ts">
2
- import { Link } from '@inertiajs/svelte'
2
+ import { Link, page } from '@inertiajs/svelte'
3
3
  import <%= inertia_component_name %> from './<%= singular_name %>.svelte'
4
4
  import type { <%= inertia_model_type %> } from './types'
5
5
 
6
- let { <%= singular_table_name %>, flash } = $props<{
6
+ let { <%= singular_table_name %> } = $props<{
7
7
  <%= singular_table_name %>: <%= inertia_model_type %>
8
- flash: { notice?: string }
9
8
  }>()
10
9
  </script>
11
10
 
@@ -13,8 +12,8 @@
13
12
  <title><%= human_name %> #{<%= singular_table_name %>.id}</title>
14
13
  </svelte:head>
15
14
 
16
- {#if flash.notice}
17
- <p class="notice">{flash.notice}</p>
15
+ {#if $page.flash.notice}
16
+ <p class="notice">{$page.flash.notice}</p>
18
17
  {/if}
19
18
 
20
19
  <h1><%= human_name %> #{<%= singular_table_name %>.id}</h1>
@@ -18,14 +18,14 @@
18
18
  </template>
19
19
 
20
20
  <script setup lang="ts">
21
- import { Head, Link } from '@inertiajs/vue3'
21
+ import { Head, Link, usePage } from '@inertiajs/vue3'
22
22
  import <%= inertia_component_name %> from './<%= singular_name %>.vue'
23
23
  import { <%= inertia_model_type %> } from './types'
24
24
 
25
- const { <%= plural_table_name %>, flash } = defineProps<{
25
+ defineProps<{
26
26
  <%= plural_table_name %>: <%= inertia_model_type %>[]
27
- flash: { notice?: string }
28
27
  }>()
28
+ const { flash } = usePage()
29
29
  </script>
30
30
 
31
31
  <style scoped>
@@ -18,10 +18,11 @@
18
18
  </template>
19
19
 
20
20
  <script setup>
21
- import { Head, Link } from '@inertiajs/vue3'
21
+ import { Head, Link, usePage } from '@inertiajs/vue3'
22
22
  import <%= inertia_component_name %> from './<%= singular_name %>.vue'
23
23
 
24
- const { <%= plural_table_name %>, flash } = defineProps(['<%= plural_table_name %>', 'flash'])
24
+ defineProps(['<%= plural_table_name %>'])
25
+ const { flash } = usePage()
25
26
  </script>
26
27
 
27
28
  <style scoped>
@@ -24,14 +24,14 @@
24
24
  </template>
25
25
 
26
26
  <script setup lang="ts">
27
- import { Head, Link } from '@inertiajs/vue3'
27
+ import { Head, Link, usePage } from '@inertiajs/vue3'
28
28
  import <%= inertia_component_name %> from './<%= singular_name %>.vue'
29
29
  import { <%= inertia_model_type %> } from './types'
30
30
 
31
- const { <%= singular_table_name %>, flash } = defineProps<{
31
+ defineProps<{
32
32
  <%= singular_table_name %>: <%= inertia_model_type %>
33
- flash: { notice?: string }
34
33
  }>()
34
+ const { flash } = usePage()
35
35
  </script>
36
36
 
37
37
  <style scoped>
@@ -24,10 +24,11 @@
24
24
  </template>
25
25
 
26
26
  <script setup>
27
- import { Head, Link } from '@inertiajs/vue3'
27
+ import { Head, Link, usePage } from '@inertiajs/vue3'
28
28
  import <%= inertia_component_name %> from './<%= singular_name %>.vue'
29
29
 
30
- const { <%= singular_table_name %>, flash } = defineProps(['<%= singular_table_name %>', 'flash'])
30
+ defineProps(['<%= singular_table_name %>'])
31
+ const { flash } = usePage()
31
32
  </script>
32
33
 
33
34
  <style scoped>
@@ -11,12 +11,12 @@ export default function Edit({ <%= singular_table_name %> }) {
11
11
 
12
12
  <Form
13
13
  <%= singular_table_name %>={<%= singular_table_name %>}
14
- action={`<%= js_resource_path %>`}
14
+ action={`<%= js_resource_path %>`}
15
15
  <% if attributes.any?(&:attachments?) -%>
16
- method="post"
17
- headers={{ 'X-HTTP-METHOD-OVERRIDE': 'patch' }}
16
+ method="post"
17
+ headers={{ 'X-HTTP-METHOD-OVERRIDE': 'patch' }}
18
18
  <% else -%>
19
- method="patch"
19
+ method="patch"
20
20
  <% end -%>
21
21
  submitText="Update <%= human_name %>"
22
22
  />
@@ -16,12 +16,12 @@ export default function Edit({ <%= singular_table_name %> }: EditProps) {
16
16
 
17
17
  <Form
18
18
  <%= singular_table_name %>={<%= singular_table_name %>}
19
- action={`<%= js_resource_path %>`}
19
+ action={`<%= js_resource_path %>`}
20
20
  <% if attributes.any?(&:attachments?) -%>
21
- method="post"
22
- headers={{ 'X-HTTP-METHOD-OVERRIDE': 'patch' }}
21
+ method="post"
22
+ headers={{ 'X-HTTP-METHOD-OVERRIDE': 'patch' }}
23
23
  <% else -%>
24
- method="patch"
24
+ method="patch"
25
25
  <% end -%>
26
26
  submitText="Update <%= human_name %>"
27
27
  />
@@ -1,8 +1,10 @@
1
- import { Head, Link } from '@inertiajs/react'
1
+ import { Head, Link, usePage } from '@inertiajs/react'
2
2
  import { Fragment } from 'react'
3
3
  import <%= inertia_component_name %> from './<%= singular_name %>'
4
4
 
5
- export default function Index({ <%= plural_table_name %>, flash }) {
5
+ export default function Index({ <%= plural_table_name %> }) {
6
+ const { flash } = usePage()
7
+
6
8
  return (
7
9
  <>
8
10
  <Head title="<%= human_name.pluralize %>" />
@@ -1,14 +1,15 @@
1
- import { Head, Link } from '@inertiajs/react'
1
+ import { Head, Link, usePage } from '@inertiajs/react'
2
2
  import { Fragment } from 'react'
3
3
  import <%= inertia_component_name %> from './<%= singular_name %>'
4
4
  import { <%= inertia_model_type %> } from './types'
5
5
 
6
6
  interface IndexProps {
7
7
  <%= plural_table_name %>: <%= inertia_model_type %>[]
8
- flash: { notice?: string }
9
8
  }
10
9
 
11
- export default function Index({ <%= plural_table_name %>, flash }: IndexProps) {
10
+ export default function Index({ <%= plural_table_name %> }: IndexProps) {
11
+ const { flash } = usePage()
12
+
12
13
  return (
13
14
  <>
14
15
  <Head title="<%= human_name.pluralize %>" />
@@ -1,7 +1,9 @@
1
- import { Head, Link } from '@inertiajs/react'
1
+ import { Head, Link, usePage } from '@inertiajs/react'
2
2
  import <%= inertia_component_name %> from './<%= singular_name %>'
3
3
 
4
- export default function Show({ <%= singular_table_name %>, flash }) {
4
+ export default function Show({ <%= singular_table_name %> }) {
5
+ const { flash } = usePage()
6
+
5
7
  return (
6
8
  <>
7
9
  <Head title={`<%= human_name %> #${<%= singular_table_name %>.id}`} />
@@ -1,13 +1,14 @@
1
- import { Head, Link } from '@inertiajs/react'
1
+ import { Head, Link, usePage } from '@inertiajs/react'
2
2
  import <%= inertia_component_name %> from './<%= singular_name %>'
3
3
  import { <%= inertia_model_type %> } from './types'
4
4
 
5
5
  interface ShowProps {
6
6
  <%= singular_table_name %>: <%= inertia_model_type %>
7
- flash: { notice?: string }
8
7
  }
9
8
 
10
- export default function Show({ <%= singular_table_name %>, flash }: ShowProps) {
9
+ export default function Show({ <%= singular_table_name %> }: ShowProps) {
10
+ const { flash } = usePage()
11
+
11
12
  return (
12
13
  <>
13
14
  <Head title={`<%= human_name %> #${<%= singular_table_name %>.id}`} />
@@ -1,8 +1,8 @@
1
1
  <script>
2
- import { Link } from '@inertiajs/svelte'
2
+ import { Link, page } from '@inertiajs/svelte'
3
3
  import <%= inertia_component_name %> from './<%= singular_name %>.svelte'
4
4
 
5
- let { <%= plural_table_name %>, flash } = $props()
5
+ let { <%= plural_table_name %> } = $props()
6
6
  </script>
7
7
 
8
8
  <svelte:head>
@@ -10,9 +10,9 @@
10
10
  </svelte:head>
11
11
 
12
12
  <div class="mx-auto md:w-2/3 w-full px-8 pt-8">
13
- {#if flash.notice}
13
+ {#if $page.flash.notice}
14
14
  <p class="py-2 px-3 bg-green-50 mb-5 text-green-500 font-medium rounded-lg inline-block">
15
- {flash.notice}
15
+ {$page.flash.notice}
16
16
  </p>
17
17
  {/if}
18
18
 
@@ -1,11 +1,10 @@
1
1
  <script lang="ts">
2
- import { Link } from '@inertiajs/svelte'
2
+ import { Link, page } from '@inertiajs/svelte'
3
3
  import <%= inertia_component_name %> from './<%= singular_name %>.svelte'
4
4
  import type { <%= inertia_model_type %> } from './types'
5
5
 
6
- let { <%= plural_table_name %>, flash } = $props<{
6
+ let { <%= plural_table_name %> } = $props<{
7
7
  <%= plural_table_name %>: <%= inertia_model_type %>[]
8
- flash: { notice?: string }
9
8
  }>()
10
9
  </script>
11
10
 
@@ -14,9 +13,9 @@
14
13
  </svelte:head>
15
14
 
16
15
  <div class="mx-auto md:w-2/3 w-full px-8 pt-8">
17
- {#if flash.notice}
16
+ {#if $page.flash.notice}
18
17
  <p class="py-2 px-3 bg-green-50 mb-5 text-green-500 font-medium rounded-lg inline-block">
19
- {flash.notice}
18
+ {$page.flash.notice}
20
19
  </p>
21
20
  {/if}
22
21
 
@@ -1,8 +1,8 @@
1
1
  <script>
2
- import { Link } from '@inertiajs/svelte'
2
+ import { Link, page } from '@inertiajs/svelte'
3
3
  import <%= inertia_component_name %> from './<%= singular_name %>.svelte'
4
4
 
5
- let { <%= singular_table_name %>, flash } = $props()
5
+ let { <%= singular_table_name %> } = $props()
6
6
  </script>
7
7
 
8
8
  <svelte:head>
@@ -11,9 +11,9 @@
11
11
 
12
12
  <div class="mx-auto md:w-2/3 w-full px-8 pt-8">
13
13
  <div class="mx-auto">
14
- {#if flash.notice}
14
+ {#if $page.flash.notice}
15
15
  <p class="py-2 px-3 bg-green-50 mb-5 text-green-500 font-medium rounded-lg inline-block">
16
- {flash.notice}
16
+ {$page.flash.notice}
17
17
  </p>
18
18
  {/if}
19
19
 
@@ -1,11 +1,10 @@
1
1
  <script lang="ts">
2
- import { Link } from '@inertiajs/svelte'
2
+ import { Link, page } from '@inertiajs/svelte'
3
3
  import <%= inertia_component_name %> from './<%= singular_name %>.svelte'
4
4
  import type { <%= inertia_model_type %> } from './types'
5
5
 
6
- let { <%= singular_table_name %>, flash } = $props<{
6
+ let { <%= singular_table_name %> } = $props<{
7
7
  <%= singular_table_name %>: <%= inertia_model_type %>
8
- flash: { notice?: string }
9
8
  }>()
10
9
  </script>
11
10
 
@@ -15,9 +14,9 @@
15
14
 
16
15
  <div class="mx-auto md:w-2/3 w-full px-8 pt-8">
17
16
  <div class="mx-auto">
18
- {#if flash.notice}
17
+ {#if $page.flash.notice}
19
18
  <p class="py-2 px-3 bg-green-50 mb-5 text-green-500 font-medium rounded-lg inline-block">
20
- {flash.notice}
19
+ {$page.flash.notice}
21
20
  </p>
22
21
  {/if}
23
22
 
@@ -36,12 +36,12 @@
36
36
  </template>
37
37
 
38
38
  <script setup lang="ts">
39
- import { Head, Link } from '@inertiajs/vue3'
39
+ import { Head, Link, usePage } from '@inertiajs/vue3'
40
40
  import <%= inertia_component_name %> from './<%= singular_name %>.vue'
41
41
  import { <%= inertia_model_type %> } from './types'
42
42
 
43
- const { <%= plural_table_name %>, flash } = defineProps<{
43
+ defineProps<{
44
44
  <%= plural_table_name %>: <%= inertia_model_type %>[]
45
- flash: { notice?: string }
46
45
  }>()
46
+ const { flash } = usePage()
47
47
  </script>
@@ -36,8 +36,9 @@
36
36
  </template>
37
37
 
38
38
  <script setup>
39
- import { Head, Link } from '@inertiajs/vue3'
39
+ import { Head, Link, usePage } from '@inertiajs/vue3'
40
40
  import <%= inertia_component_name %> from './<%= singular_name %>.vue'
41
41
 
42
- const { <%= plural_table_name %>, flash } = defineProps(['<%= plural_table_name %>', 'flash'])
42
+ defineProps(['<%= plural_table_name %>'])
43
+ const { flash } = usePage()
43
44
  </script>
@@ -42,12 +42,12 @@
42
42
  </template>
43
43
 
44
44
  <script setup lang="ts">
45
- import { Head, Link } from '@inertiajs/vue3'
45
+ import { Head, Link, usePage } from '@inertiajs/vue3'
46
46
  import <%= inertia_component_name %> from './<%= singular_name %>.vue'
47
47
  import { <%= inertia_model_type %> } from './types'
48
48
 
49
- const { <%= singular_table_name %>, flash } = defineProps<{
49
+ defineProps<{
50
50
  <%= singular_table_name %>: <%= inertia_model_type %>
51
- flash: { notice?: string }
52
51
  }>()
52
+ const { flash } = usePage()
53
53
  </script>
@@ -42,8 +42,9 @@
42
42
  </template>
43
43
 
44
44
  <script setup>
45
- import { Head, Link } from '@inertiajs/vue3'
45
+ import { Head, Link, usePage } from '@inertiajs/vue3'
46
46
  import <%= inertia_component_name %> from './<%= singular_name %>.vue'
47
47
 
48
- const { <%= singular_table_name %>, flash } = defineProps(['<%= singular_table_name %>', 'flash'])
48
+ defineProps(['<%= singular_table_name %>'])
49
+ const { flash } = usePage()
49
50
  </script>
@@ -40,6 +40,10 @@ module InertiaRails
40
40
 
41
41
  # DOM id to use for the root Inertia.js element.
42
42
  root_dom_id: 'app',
43
+
44
+ # Flash keys from Rails flash to expose to frontend.
45
+ # Set to nil to disable Rails flash integration (use only flash.inertia).
46
+ flash_keys: %i[notice alert].freeze,
43
47
  }.freeze
44
48
 
45
49
  OPTION_NAMES = DEFAULTS.keys.freeze
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'inertia_rails'
4
+ require_relative 'flash_extension'
4
5
  require_relative 'helper'
5
6
  require_relative 'action_filter'
6
7
  require_relative 'meta_tag_builder'
@@ -180,6 +181,17 @@ module InertiaRails
180
181
  head :conflict
181
182
  end
182
183
 
184
+ def inertia_collect_flash_data
185
+ flash_data = flash.to_hash
186
+
187
+ allowed_keys = inertia_configuration.flash_keys
188
+ result = allowed_keys ? flash_data.slice(*allowed_keys.map(&:to_s)) : {}
189
+
190
+ result.merge!(flash_data['inertia'].transform_keys(&:to_s)) if flash_data['inertia'].is_a?(Hash)
191
+
192
+ result.symbolize_keys
193
+ end
194
+
183
195
  def capture_inertia_session_options(options)
184
196
  return unless (inertia = options[:inertia])
185
197
 
@@ -192,7 +204,6 @@ module InertiaRails
192
204
  )
193
205
  session[:inertia_errors] = inertia_errors
194
206
  end
195
-
196
207
  end
197
208
 
198
209
  session[:inertia_clear_history] = inertia[:clear_history] if inertia[:clear_history]
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative 'middleware'
4
4
  require_relative 'controller'
5
+ require_relative 'flash_extension'
5
6
 
6
7
  module InertiaRails
7
8
  class Engine < ::Rails::Engine
@@ -14,5 +15,10 @@ module InertiaRails
14
15
  include ::InertiaRails::Controller
15
16
  end
16
17
  end
18
+
19
+ initializer 'inertia_rails.flash_extension' do
20
+ ActionDispatch::Flash::FlashHash.prepend ::InertiaRails::FlashExtension
21
+ ActionDispatch::Flash::FlashNow.prepend ::InertiaRails::FlashExtension
22
+ end
17
23
  end
18
24
  end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module InertiaRails
4
+ # Provides a scoped interface for Inertia flash data within Rails' flash.
5
+ # Uses native hash storage: flash[:inertia] = { key: value }
6
+ # Tracks .now keys separately in @inertia_now_keys for session filtering.
7
+ module FlashExtension
8
+ INERTIA_KEY = 'inertia'
9
+
10
+ def inertia
11
+ @inertia ||= InertiaFlashScope.new(self)
12
+ end
13
+
14
+ # Keys set via flash.now.inertia that should not persist to session
15
+ def inertia_now_keys
16
+ @inertia_now_keys ||= Set.new
17
+ end
18
+
19
+ # Clear .now tracking when user explicitly keeps :inertia or all flash
20
+ def keep(key = nil)
21
+ @inertia_now_keys&.clear if key.nil? || key.to_s == INERTIA_KEY
22
+ super
23
+ end
24
+
25
+ # Override to filter .now keys from nested inertia hash before session persistence
26
+ def to_session_value
27
+ inertia_hash = self[INERTIA_KEY]
28
+ if inertia_hash.is_a?(Hash) && @inertia_now_keys&.any?
29
+ @inertia_now_keys.each { |k| inertia_hash.delete(k.to_s) }
30
+ delete(INERTIA_KEY) if inertia_hash.empty?
31
+ end
32
+
33
+ super
34
+ end
35
+
36
+ class InertiaFlashScope
37
+ def initialize(flash_or_now)
38
+ if flash_or_now.respond_to?(:flash)
39
+ @flash = flash_or_now.flash
40
+ @now = true
41
+ else
42
+ @flash = flash_or_now
43
+ @now = false
44
+ end
45
+ end
46
+
47
+ def []=(key, value)
48
+ @flash[INERTIA_KEY] ||= {}
49
+ @flash[INERTIA_KEY][key.to_s] = value
50
+ @flash.inertia_now_keys.add(key.to_s) if @now
51
+ end
52
+
53
+ def [](key)
54
+ @flash[INERTIA_KEY]&.[](key.to_s)
55
+ end
56
+
57
+ def to_hash
58
+ @flash[INERTIA_KEY]&.dup || {}
59
+ end
60
+ alias to_h to_hash
61
+ end
62
+ end
63
+ end
@@ -87,14 +87,6 @@ module InertiaRails
87
87
  route_url
88
88
  end
89
89
 
90
- def inertia_js_version
91
- @inertia_js_version ||= Gem::Version.new(
92
- JSON.parse(`npm ls @inertiajs/core --json`).then do |json|
93
- json['dependencies'].values.first['version']
94
- end
95
- )
96
- end
97
-
98
90
  def ts_type(attribute)
99
91
  case attribute.type
100
92
  when :float, :decimal, :integer
@@ -30,8 +30,8 @@ module InertiaRails
30
30
  LazyProp.new(value, &block)
31
31
  end
32
32
 
33
- def optional(&block)
34
- OptionalProp.new(&block)
33
+ def optional(...)
34
+ OptionalProp.new(...)
35
35
  end
36
36
 
37
37
  def always(&block)
@@ -21,7 +21,7 @@ module InertiaRails
21
21
  status, headers, body = @app.call(@env)
22
22
  request = ActionDispatch::Request.new(@env)
23
23
 
24
- # Inertia errors are added to the session via redirect_to
24
+ # Inertia session data is added via redirect_to
25
25
  unless keep_inertia_session_options?(status)
26
26
  request.session.delete(:inertia_errors)
27
27
  request.session.delete(:inertia_clear_history)
@@ -125,6 +125,9 @@ module InertiaRails
125
125
  clearHistory: @clear_history,
126
126
  }
127
127
 
128
+ flash_data = @controller.__send__(:inertia_collect_flash_data)
129
+ @page[:flash] = flash_data if flash_data.present?
130
+
128
131
  deferred_props = deferred_props_keys
129
132
  @page[:deferredProps] = deferred_props if deferred_props.present?
130
133
  @page[:scrollProps] = scroll_props if scroll_props.present?
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module InertiaRails
4
- VERSION = '3.15.0'
4
+ VERSION = '3.16.0'
5
5
  end
@@ -5,18 +5,22 @@
5
5
  # The original source needs to be patched, so that Inertia requests are
6
6
  # NOT responded with plain text, but with HTML.
7
7
  #
8
- # Original source (unchanged since Rails 5.1):
9
- # https://github.com/rails/rails/blob/5-1-stable/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
8
+ # Original source:
10
9
  # https://github.com/rails/rails/blob/8-0-stable/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
10
+ # https://github.com/rails/rails/blob/main/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
11
11
  #
12
12
 
13
13
  module InertiaRails
14
14
  module InertiaDebugExceptions
15
- def render_for_browser_request(request, wrapper)
15
+ # Rails 8.2+ passes content_type as third argument
16
+ def render_for_browser_request(request, wrapper, content_type = nil)
16
17
  template = create_template(request, wrapper)
17
18
  file = "rescues/#{wrapper.rescue_template}"
18
19
 
19
- if request.xhr? && !request.headers['X-Inertia'] # <<<< this line is changed only
20
+ if content_type == Mime[:md]
21
+ body = template.render(template: file, layout: false, formats: [:text])
22
+ format = 'text/markdown'
23
+ elsif request.xhr? && !request.headers['X-Inertia']
20
24
  body = template.render(template: file, layout: false, formats: [:text])
21
25
  format = 'text/plain'
22
26
  else
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.15.0
4
+ version: 3.16.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-12 00:00:00.000000000 Z
12
+ date: 2025-12-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: railties
@@ -189,6 +189,7 @@ files:
189
189
  - lib/inertia_rails/controller.rb
190
190
  - lib/inertia_rails/defer_prop.rb
191
191
  - lib/inertia_rails/engine.rb
192
+ - lib/inertia_rails/flash_extension.rb
192
193
  - lib/inertia_rails/generators/controller_template_base.rb
193
194
  - lib/inertia_rails/generators/helper.rb
194
195
  - lib/inertia_rails/generators/scaffold_template_base.rb