Skip to content

Commit 7424d53

Browse files
committed
Improve Inertia initializers
1 parent 0401abb commit 7424d53

File tree

18 files changed

+168
-69
lines changed

18 files changed

+168
-69
lines changed

.github/workflows/generators.yml

+15-6
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,23 @@ jobs:
1818
test:
1919
runs-on: ubuntu-latest
2020
strategy:
21+
fail-fast: false
2122
matrix:
22-
framework: [react, vue, svelte4, svelte]
23+
framework: [react vue svelte svelte4]
2324
typescript: [true, false]
2425
tailwind: [true, false]
2526
ruby: ['3.3']
2627
node: ['22']
28+
inertia_version: ['1.2.0', '1.3.0-beta.2', '2.0.0-beta.2']
29+
exclude:
30+
# 1.2.0 does not support typescript
31+
- typescript: true
32+
inertia_version: '1.2.0'
33+
# 1.2.0 doesn't support Svelte 5
34+
- framework: svelte
35+
inertia_version: '1.2.0'
2736

28-
name: ${{ matrix.framework }} (TS:${{ matrix.typescript }}, TW:${{ matrix.tailwind }})
37+
name: ${{ matrix.framework }} (TS:${{ matrix.typescript }}, TW:${{ matrix.tailwind }}, Inertia:${{ matrix.inertia_version }})
2938

3039
steps:
3140
- uses: actions/checkout@v4
@@ -48,7 +57,7 @@ jobs:
4857
tmp/bundle_cache
4958
tmp/npm_cache
5059
~/.npm
51-
key: ${{ runner.os }}-deps-${{ matrix.framework }}-${{ hashFiles('**/Gemfile.lock') }}-${{ github.sha }}
60+
key: ${{ runner.os }}-deps-${{ matrix.framework }}-${{ matrix.inertia_version }}-${{ hashFiles('**/Gemfile.lock') }}-${{ github.sha }}
5261
restore-keys: |
5362
${{ runner.os }}-deps-${{ matrix.framework }}-
5463
${{ runner.os }}-deps-
@@ -60,13 +69,13 @@ jobs:
6069
run: |
6170
ts_flag=${{ matrix.typescript && '--typescript' || '--no-typescript' }}
6271
tw_flag=${{ matrix.tailwind && '--tailwind' || '--no-tailwind' }}
63-
bin/generate_scaffold_example --framework=${{ matrix.framework }} $ts_flag $tw_flag
72+
bin/generate_scaffold_example --framework=${{ matrix.framework }} --inertia-version=${{ matrix.inertia_version }} $ts_flag $tw_flag
6473
6574
- name: Upload test artifacts
6675
if: failure()
67-
uses: actions/upload-artifact@v3
76+
uses: actions/upload-artifact@v4
6877
with:
69-
name: test-output-${{ matrix.framework }}-ts${{ matrix.typescript }}-tw${{ matrix.tailwind }}
78+
name: test-output-${{ matrix.framework }}-ts${{ matrix.typescript }}-tw${{ matrix.tailwind }}-v${{ matrix.inertia_version }}
7079
path: |
7180
tmp/scaffold_example/log
7281
tmp/scaffold_example/tmp/screenshots

bin/generate_scaffold_example

+20-13
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,17 @@ OptionParser.new do |opts|
2626
opts.on('--[no-]tailwind', 'Enable/disable Tailwind') do |t|
2727
options[:tailwind] = t
2828
end
29+
30+
opts.on('--inertia-version VERSION', 'Specify Inertia version') do |v|
31+
options[:inertia_version] = v
32+
end
2933
end.parse!
3034

3135
# Build generator args string
3236
generator_args = "--framework=#{options[:framework]}"
3337
generator_args += ' --typescript' if options[:typescript]
34-
generator_args += ' --install-vite'
35-
generator_args += ' --install-tailwind' if options[:tailwind]
38+
generator_args += ' --tailwind' if options[:tailwind]
39+
generator_args += " --inertia-version=#{options[:inertia_version]}" if options[:inertia_version]
3640

3741
# Setup paths relative to project root
3842
project_root = File.expand_path('..', __dir__)
@@ -57,25 +61,28 @@ system("rails new #{app_dir} -J")
5761
# Install and configure with caching
5862
Dir.chdir(app_dir) do
5963
# Configure bundler to use cache in project root
60-
system("bundle config set --local path '#{gem_cache}'")
64+
system("bundle config set --local path '#{gem_cache}'", exception: true)
6165

6266
# Configure npm to use cache in project root
63-
system("npm config set cache '#{npm_cache}'")
67+
system("npm config set cache '#{npm_cache}'", exception: true)
6468

6569
# Install dependencies
66-
system('bundle add inertia_rails --path ../../')
67-
system('bundle add bcrypt')
68-
system('bin/rails active_storage:install')
70+
system('bundle add inertia_rails --path ../../', exception: true)
71+
system('bundle add bcrypt', exception: true)
72+
system('bin/rails active_storage:install', exception: true)
6973

7074
# Run install generator with configured options
71-
system("bin/rails g inertia:install --no-interactive --force #{generator_args}")
75+
system("bin/rails g inertia:install --no-interactive --force --vite #{generator_args} --verbose", exception: true)
7276

7377
# Generate a scaffold
74-
system('bin/rails g inertia:scaffold user name email admin:boolean password:digest avatar:attachment')
75-
system('bin/rails g inertia:scaffold post content:text published_at:date gallery:attachments')
76-
system('bin/rails db:migrate')
78+
system('bin/rails g inertia:scaffold user name email admin:boolean password:digest avatar:attachment', exception: true)
79+
system('bin/rails g inertia:scaffold post content:text published_at:date gallery:attachments', exception: true)
80+
system('bin/rails db:migrate', exception: true)
7781

7882
# Run tests
79-
system('bin/rails test')
80-
system('bin/rails test:system')
83+
system('bin/rails test', exception: true)
84+
system('bin/rails test:system', exception: true)
85+
86+
# Lint code
87+
system('npm run check', exception: true) if options[:typescript]
8188
end

docs/cookbook/integrating-shadcn-ui.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ If you're starting fresh, create a new Rails application with Inertia (or skip t
1414
rails new -JA shadcn-inertia-rails
1515
cd shadcn-inertia-rails
1616

17-
rails generate inertia:install `--framework=react --typescript --install-vite --install-tailwind --no-interactive`
17+
rails generate inertia:install `--framework=react --typescript --vite --tailwind --no-interactive`
1818
Installing Inertia's Rails adapter
1919
...
2020
```
@@ -25,7 +25,7 @@ Installing Inertia's Rails adapter
2525
rails new -JA shadcn-inertia-rails
2626
cd shadcn-inertia-rails
2727
28-
rails generate inertia:install --framework=react --install-vite --install-tailwind --no-interactive
28+
rails generate inertia:install --framework=react --vite --tailwind --no-interactive
2929
Installing Inertia's Rails adapter
3030
...
3131
```

lib/generators/inertia/install/install_generator.rb

+11-6
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,10 @@ class InstallGenerator < Rails::Generators::Base
3434
class_option :interactive, type: :boolean, default: true,
3535
desc: 'Whether to prompt for optional installations'
3636

37-
class_option :install_tailwind, type: :boolean, default: false,
38-
desc: 'Whether to install Tailwind CSS'
39-
class_option :install_vite, type: :boolean, default: false,
40-
desc: 'Whether to install Vite Ruby'
37+
class_option :tailwind, type: :boolean, default: false,
38+
desc: 'Whether to install Tailwind CSS'
39+
class_option :vite, type: :boolean, default: false,
40+
desc: 'Whether to install Vite Ruby'
4141
class_option :example_page, type: :boolean, default: true,
4242
desc: 'Whether to add an example Inertia page'
4343

@@ -127,6 +127,11 @@ def install_typescript
127127
end
128128

129129
add_dependencies(*FRAMEWORKS[framework]['packages_ts'])
130+
131+
say 'Copying adding scripts to package.json'
132+
run 'npm pkg set scripts.check="svelte-check --tsconfig ./tsconfig.json && tsc -p tsconfig.node.json"' if svelte?
133+
run 'npm pkg set scripts.check="vue-tsc -p tsconfig.app.json && tsc -p tsconfig.node.json"' if framework == 'vue'
134+
run 'npm pkg set scripts.check="tsc -p tsconfig.app.json && tsc -p tsconfig.node.json"' if framework == 'react'
130135
end
131136

132137
def install_example_page
@@ -236,13 +241,13 @@ def vite_config_path
236241
def install_vite?
237242
return @install_vite if defined?(@install_vite)
238243

239-
@install_vite = options[:install_vite] || yes?('Would you like to install Vite Ruby? (y/n)', :green)
244+
@install_vite = options[:vite] || yes?('Would you like to install Vite Ruby? (y/n)', :green)
240245
end
241246

242247
def install_tailwind?
243248
return @install_tailwind if defined?(@install_tailwind)
244249

245-
@install_tailwind = options[:install_tailwind] || yes?('Would you like to install Tailwind CSS? (y/n)', :green)
250+
@install_tailwind = options[:tailwind] || yes?('Would you like to install Tailwind CSS? (y/n)', :green)
246251
end
247252

248253
def typescript?

lib/generators/inertia/install/templates/react/inertia.js

+15-6
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,29 @@ createInertiaApp({
1515

1616
resolve: (name) => {
1717
const pages = import.meta.glob('../pages/**/*.jsx', { eager: true })
18-
return pages[`../pages/${name}.jsx`]
18+
const page = pages[`../pages/${name}.jsx`]
19+
if (!page) {
20+
console.error(`Missing Inertia page component: '${name}.jsx'`)
21+
}
1922

2023
// To use a default layout, import the Layout component
2124
// and use the following lines.
2225
// see https://inertia-rails.netlify.app/guide/pages#default-layouts
2326
//
24-
// const page = pages[`../pages/${name}.jsx`]
2527
// page.default.layout ||= (page) => createElement(Layout, null, page)
26-
// return page
28+
29+
return page
2730
},
2831

2932
setup({ el, App, props }) {
30-
const root = createRoot(el)
31-
32-
root.render(createElement(App, props))
33+
if (el) {
34+
createRoot(el).render(createElement(App, props))
35+
} else {
36+
console.error(
37+
'Missing root element.\n\n' +
38+
'If you see this error, it probably means you load Inertia.js on non-Inertia pages.\n' +
39+
'Consider moving <%%= vite_javascript_tag "inertia" %> to the Inertia-specific layout instead.'
40+
)
41+
}
3342
},
3443
})

lib/generators/inertia/install/templates/react/inertia.ts

+18-9
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,30 @@ createInertiaApp({
1616
// progress: false,
1717

1818
resolve: (name) => {
19-
const pages = import.meta.glob<ResolvedComponent>('../pages/**/*.tsx', { eager: true })
20-
return pages[`../pages/${name}.tsx`]
19+
const pages = import.meta.glob<ResolvedComponent>('../pages/**/*.tsx', {eager: true})
20+
const page = pages[`../pages/${name}.tsx`]
21+
if (!page) {
22+
console.error(`Missing Inertia page component: '${name}.tsx'`)
23+
}
2124

2225
// To use a default layout, import the Layout component
23-
// and use the following lines.
26+
// and use the following line.
2427
// see https://inertia-rails.netlify.app/guide/pages#default-layouts
2528
//
26-
// const page = pages[`../pages/${name}.tsx`]
2729
// page.default.layout ||= (page) => createElement(Layout, null, page)
28-
// return page
29-
},
3030

31-
setup({ el, App, props }) {
32-
const root = createRoot(el)
31+
return page
32+
},
3333

34-
root.render(createElement(App, props))
34+
setup({el, App, props}) {
35+
if (el) {
36+
createRoot(el).render(createElement(App, props))
37+
} else {
38+
console.error(
39+
'Missing root element.\n\n' +
40+
'If you see this error, it probably means you load Inertia.js on non-Inertia pages.\n' +
41+
'Consider moving <%%= vite_typescript_tag "inertia" %> to the Inertia-specific layout instead.'
42+
)
43+
}
3544
},
3645
})

lib/generators/inertia/install/templates/svelte/inertia.js

+16-4
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,29 @@ createInertiaApp({
1414

1515
resolve: (name) => {
1616
const pages = import.meta.glob('../pages/**/*.svelte', { eager: true })
17-
return pages[`../pages/${name}.svelte`]
17+
const page = pages[`../pages/${name}.svelte`]
18+
if (!page) {
19+
console.error(`Missing Inertia page component: '${name}.svelte'`)
20+
}
1821

1922
// To use a default layout, import the Layout component
20-
// and use the following lines.
23+
// and use the following line.
2124
// see https://inertia-rails.netlify.app/guide/pages#default-layouts
2225
//
23-
// const page = pages[`../pages/${name}.svelte`]
2426
// return { default: page.default, layout: page.layout || Layout }
27+
28+
return page
2529
},
2630

2731
setup({ el, App, props }) {
28-
mount(App, { target: el, props })
32+
if (el) {
33+
mount(App, { target: el, props })
34+
} else {
35+
console.error(
36+
'Missing root element.\n\n' +
37+
'If you see this error, it probably means you load Inertia.js on non-Inertia pages.\n' +
38+
'Consider moving <%%= vite_javascript_tag "inertia" %> to the Inertia-specific layout instead.'
39+
)
40+
}
2941
},
3042
})

lib/generators/inertia/install/templates/svelte/inertia.ts

+17-4
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,30 @@ createInertiaApp({
1414

1515
resolve: (name) => {
1616
const pages = import.meta.glob<ResolvedComponent>('../pages/**/*.svelte', { eager: true })
17-
return pages[`../pages/${name}.svelte`]
17+
const page = pages[`../pages/${name}.svelte`]
18+
if (!page) {
19+
console.error(`Missing Inertia page component: '${name}.svelte'`)
20+
}
1821

1922
// To use a default layout, import the Layout component
20-
// and use the following lines.
23+
// and use the following line.
2124
// see https://inertia-rails.netlify.app/guide/pages#default-layouts
2225
//
23-
// const page = pages[`../pages/${name}.svelte`]
2426
// return { default: page.default, layout: page.layout || Layout }
27+
28+
return page
2529
},
2630

2731
setup({ el, App, props }) {
28-
mount(App, { target: el, props })
32+
if (el) {
33+
<%= '// @ts-expect-error 1.3.0 beta contains types mismatch' if inertia_resolved_version == Gem::Version.new('1.3.0-beta.2') -%>
34+
mount(App, { target: el, props })
35+
} else {
36+
console.error(
37+
'Missing root element.\n\n' +
38+
'If you see this error, it probably means you load Inertia.js on non-Inertia pages.\n' +
39+
'Consider moving <%%= vite_typescript_tag "inertia" %> to the Inertia-specific layout instead.'
40+
)
41+
}
2942
},
3043
})

lib/generators/inertia/install/templates/svelte4/inertia.js

+15-3
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,29 @@ createInertiaApp({
1313

1414
resolve: (name) => {
1515
const pages = import.meta.glob('../pages/**/*.svelte', { eager: true })
16-
return pages[`../pages/${name}.svelte`]
16+
const page = pages[`../pages/${name}.svelte`]
17+
if (!page) {
18+
console.error(`Missing Inertia page component: '${name}.svelte'`)
19+
}
1720

1821
// To use a default layout, import the Layout component
1922
// and use the following lines.
2023
// see https://inertia-rails.netlify.app/guide/pages#default-layouts
2124
//
22-
// const page = pages[`../pages/${name}.svelte`]
2325
// return { default: page.default, layout: page.layout || Layout }
26+
27+
return page
2428
},
2529

2630
setup({ el, App, props }) {
27-
new App({ target: el, props })
31+
if (el) {
32+
new App({ target: el, props })
33+
} else {
34+
console.error(
35+
'Missing root element.\n\n' +
36+
'If you see this error, it probably means you load Inertia.js on non-Inertia pages.\n' +
37+
'Consider moving <%%= vite_javascript_tag "inertia" %> to the Inertia-specific layout instead.'
38+
)
39+
}
2840
},
2941
})

lib/generators/inertia/install/templates/svelte4/inertia.ts

+16-4
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,29 @@ createInertiaApp({
1313

1414
resolve: (name) => {
1515
const pages = import.meta.glob<ResolvedComponent>('../pages/**/*.svelte', { eager: true })
16-
return pages[`../pages/${name}.svelte`]
16+
const page = pages[`../pages/${name}.svelte`]
17+
if (!page) {
18+
console.error(`Missing Inertia page component: '${name}.svelte'`)
19+
}
1720

1821
// To use a default layout, import the Layout component
19-
// and use the following lines.
22+
// and use the following line.
2023
// see https://inertia-rails.netlify.app/guide/pages#default-layouts
2124
//
22-
// const page = pages[`../pages/${name}.svelte`]
2325
// return { default: page.default, layout: page.layout || Layout }
26+
27+
return page
2428
},
2529

2630
setup({ el, App, props }) {
27-
new App({ target: el, props })
31+
if (el) {
32+
new App({ target: el, props })
33+
} else {
34+
console.error(
35+
'Missing root element.\n\n' +
36+
'If you see this error, it probably means you load Inertia.js on non-Inertia pages.\n' +
37+
'Consider moving <%%= vite_javascript_tag "inertia" %> to the Inertia-specific layout instead.'
38+
)
39+
}
2840
},
2941
})

lib/generators/inertia_templates/scaffold/templates/react/Form.tsx.tt

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import { FormEvent } from 'react'
2-
import { useForm, InertiaFormProps } from '@inertiajs/react'
2+
import { useForm <%= ', InertiaFormProps' if inertia_resolved_version.release >= Gem::Version.new('2.0.0') %>} from '@inertiajs/react'
33
import { <%= inertia_model_type %>, <%= inertia_model_form_type %> } from './types'
4-
4+
<% if inertia_resolved_version.release < Gem::Version.new('2.0.0') %>
5+
// Temporary fix for InertiaFormProps not being exported from @inertiajs/react
6+
type InertiaFormProps<TForm extends Record<string, any>> = ReturnType<typeof useForm<TForm>>
7+
<% end %>
58
interface FormProps {
69
<%= singular_table_name %>: <%= inertia_model_type %>
710
onSubmit: (form: InertiaFormProps<<%= inertia_model_form_type %>>) => void

0 commit comments

Comments
 (0)