From 8097c2ee14ae67553a7804ec8086ba2060b8cbe9 Mon Sep 17 00:00:00 2001
From: Svyatoslav Kryukov
Date: Mon, 11 Nov 2024 11:43:31 +0300
Subject: [PATCH 01/11] Upstream generators
---
.github/workflows/push.yml | 21 +-
.rubocop.yml | 15 +
.rubocop_todo.yml | 631 ++++++++++++++++++
Gemfile | 26 +-
Rakefile | 12 +-
docs/guide/responses.md | 12 +-
docs/guide/server-side-setup.md | 5 +-
inertia_rails.gemspec | 37 +-
.../controller/controller_generator.rb | 18 +
.../controller/templates/controller.rb.tt | 10 +
lib/generators/inertia/install/frameworks.yml | 98 +++
lib/generators/inertia/install/helpers.rb | 51 ++
.../inertia/install/install_generator.rb | 286 ++++++++
.../inertia/install/js_package_manager.rb | 50 ++
.../install/templates/assets/inertia.svg | 1 +
.../install/templates/assets/react.svg | 1 +
.../install/templates/assets/svelte.svg | 1 +
.../install/templates/assets/vite_ruby.svg | 1 +
.../inertia/install/templates/assets/vue.svg | 1 +
.../install/templates}/controller.rb | 4 +-
lib/generators/inertia/install/templates/dev | 23 +
.../inertia/install/templates/initializer.rb | 6 +
.../templates/react/InertiaExample.jsx | 60 ++
.../templates/react/InertiaExample.module.css | 80 +++
.../templates/react/InertiaExample.tsx | 60 ++
.../install/templates/react/inertia.js | 34 +
.../install/templates/react/inertia.ts | 36 +
.../install/templates/react/tsconfig.app.json | 27 +
.../install/templates/react/tsconfig.json | 11 +
.../templates/react/tsconfig.node.json | 13 +
.../install/templates/react/vite-env.d.ts | 1 +
.../templates/svelte/InertiaExample.svelte | 112 ++++
.../templates/svelte/InertiaExample.ts.svelte | 112 ++++
.../install/templates/svelte/inertia.js | 30 +
.../install/templates/svelte/inertia.ts | 30 +
.../install/templates/svelte/svelte.config.js | 7 +
.../install/templates/svelte/tsconfig.json | 21 +
.../templates/svelte/tsconfig.node.json | 12 +
.../install/templates/svelte/vite-env.d.ts | 2 +
.../templates/svelte4/InertiaExample.svelte | 116 ++++
.../svelte4/InertiaExample.ts.svelte | 116 ++++
.../install/templates/svelte4/inertia.js | 29 +
.../install/templates/svelte4/inertia.ts | 29 +
.../templates/svelte4/svelte.config.js | 7 +
.../install/templates/svelte4/tsconfig.json | 21 +
.../templates/svelte4/tsconfig.node.json | 12 +
.../install/templates/svelte4/vite-env.d.ts | 2 +
.../templates/tailwind/application.css | 13 +
.../templates/tailwind/postcss.config.js | 6 +
.../templates/tailwind/tailwind.config.js.tt | 18 +
.../templates/vue/InertiaExample.ts.vue | 117 ++++
.../install/templates/vue/InertiaExample.vue | 117 ++++
.../inertia/install/templates/vue/inertia.js | 33 +
.../inertia/install/templates/vue/inertia.ts | 33 +
.../install/templates/vue/tsconfig.app.json | 24 +
.../install/templates/vue/tsconfig.json | 11 +
.../install/templates/vue/tsconfig.node.json | 22 +
.../install/templates/vue/vite-env.d.ts | 1 +
.../inertia/scaffold/scaffold_generator.rb | 16 +
.../scaffold_controller_generator.rb | 60 ++
.../templates/controller.rb.tt | 100 +++
.../install/react/InertiaExample.jsx | 9 -
.../inertia_rails/install/react/inertia.jsx | 17 -
.../install/svelte/InertiaExample.svelte | 11 -
.../inertia_rails/install/svelte/inertia.js | 14 -
.../install/vue/InertiaExample.vue | 11 -
.../inertia_rails/install/vue/inertia.js | 20 -
.../inertia_rails/install_generator.rb | 84 ---
.../controller/controller_generator.rb | 12 +
.../controller/templates/react/view.jsx.tt | 8 +
.../templates/svelte/view.svelte.tt | 2 +
.../templates/svelte4/view.svelte.tt | 2 +
.../controller/templates/vue/view.vue.tt | 4 +
.../scaffold/scaffold_generator.rb | 12 +
.../scaffold/templates/react/Edit.jsx.tt | 35 +
.../scaffold/templates/react/Form.jsx.tt | 111 +++
.../scaffold/templates/react/Index.jsx.tt | 26 +
.../scaffold/templates/react/New.jsx.tt | 27 +
.../scaffold/templates/react/One.jsx.tt | 26 +
.../scaffold/templates/react/Show.jsx.tt | 39 ++
.../scaffold/templates/svelte/Edit.svelte.tt | 36 +
.../scaffold/templates/svelte/Form.svelte.tt | 98 +++
.../scaffold/templates/svelte/Index.svelte.tt | 35 +
.../scaffold/templates/svelte/New.svelte.tt | 29 +
.../scaffold/templates/svelte/One.svelte.tt | 28 +
.../scaffold/templates/svelte/Show.svelte.tt | 41 ++
.../scaffold/templates/svelte4/Edit.svelte.tt | 37 +
.../scaffold/templates/svelte4/Form.svelte.tt | 96 +++
.../templates/svelte4/Index.svelte.tt | 36 +
.../scaffold/templates/svelte4/New.svelte.tt | 30 +
.../scaffold/templates/svelte4/One.svelte.tt | 28 +
.../scaffold/templates/svelte4/Show.svelte.tt | 46 ++
.../scaffold/templates/vue/Edit.vue.tt | 36 +
.../scaffold/templates/vue/Form.vue.tt | 94 +++
.../scaffold/templates/vue/Index.vue.tt | 31 +
.../scaffold/templates/vue/New.vue.tt | 29 +
.../scaffold/templates/vue/One.vue.tt | 26 +
.../scaffold/templates/vue/Show.vue.tt | 44 ++
.../controller/controller_generator.rb | 12 +
.../controller/templates/react/view.jsx.tt | 8 +
.../templates/svelte/view.svelte.tt | 2 +
.../templates/svelte4/view.svelte.tt | 2 +
.../controller/templates/vue/view.vue.tt | 4 +
.../scaffold/scaffold_generator.rb | 12 +
.../scaffold/templates/react/Edit.jsx.tt | 42 ++
.../scaffold/templates/react/Form.jsx.tt | 122 ++++
.../scaffold/templates/react/Index.jsx.tt | 43 ++
.../scaffold/templates/react/New.jsx.tt | 30 +
.../scaffold/templates/react/One.jsx.tt | 26 +
.../scaffold/templates/react/Show.jsx.tt | 54 ++
.../scaffold/templates/svelte/Edit.svelte.tt | 44 ++
.../scaffold/templates/svelte/Form.svelte.tt | 119 ++++
.../scaffold/templates/svelte/Index.svelte.tt | 42 ++
.../scaffold/templates/svelte/New.svelte.tt | 32 +
.../scaffold/templates/svelte/One.svelte.tt | 28 +
.../scaffold/templates/svelte/Show.svelte.tt | 57 ++
.../scaffold/templates/svelte4/Edit.svelte.tt | 45 ++
.../scaffold/templates/svelte4/Form.svelte.tt | 120 ++++
.../templates/svelte4/Index.svelte.tt | 43 ++
.../scaffold/templates/svelte4/New.svelte.tt | 33 +
.../scaffold/templates/svelte4/One.svelte.tt | 28 +
.../scaffold/templates/svelte4/Show.svelte.tt | 58 ++
.../scaffold/templates/vue/Edit.vue.tt | 44 ++
.../scaffold/templates/vue/Form.vue.tt | 127 ++++
.../scaffold/templates/vue/Index.vue.tt | 43 ++
.../scaffold/templates/vue/New.vue.tt | 32 +
.../scaffold/templates/vue/One.vue.tt | 26 +
.../scaffold/templates/vue/Show.vue.tt | 56 ++
lib/inertia_rails/configuration.rb | 2 +-
.../generators/controller_template_base.rb | 56 ++
lib/inertia_rails/generators/helper.rb | 89 +++
.../generators/scaffold_template_base.rb | 36 +
spec/fixtures/install_generator/dummy/Gemfile | 3 +
.../app/views/layouts/application.html.erb | 13 +
.../install_generator/dummy/config/routes.rb | 5 +
.../app/views/layouts/application.html.erb | 16 +
.../with_vite/config/vite.json | 1 +
.../install_generator/with_vite/package.json | 1 +
.../with_vite/vite.config.ts | 8 +
.../install/install_generator_spec.rb | 314 +++++++++
140 files changed, 5800 insertions(+), 209 deletions(-)
create mode 100644 .rubocop.yml
create mode 100644 .rubocop_todo.yml
create mode 100644 lib/generators/inertia/controller/controller_generator.rb
create mode 100644 lib/generators/inertia/controller/templates/controller.rb.tt
create mode 100644 lib/generators/inertia/install/frameworks.yml
create mode 100644 lib/generators/inertia/install/helpers.rb
create mode 100644 lib/generators/inertia/install/install_generator.rb
create mode 100644 lib/generators/inertia/install/js_package_manager.rb
create mode 100644 lib/generators/inertia/install/templates/assets/inertia.svg
create mode 100644 lib/generators/inertia/install/templates/assets/react.svg
create mode 100644 lib/generators/inertia/install/templates/assets/svelte.svg
create mode 100644 lib/generators/inertia/install/templates/assets/vite_ruby.svg
create mode 100644 lib/generators/inertia/install/templates/assets/vue.svg
rename lib/generators/{inertia_rails/install => inertia/install/templates}/controller.rb (64%)
create mode 100644 lib/generators/inertia/install/templates/dev
create mode 100644 lib/generators/inertia/install/templates/initializer.rb
create mode 100644 lib/generators/inertia/install/templates/react/InertiaExample.jsx
create mode 100644 lib/generators/inertia/install/templates/react/InertiaExample.module.css
create mode 100644 lib/generators/inertia/install/templates/react/InertiaExample.tsx
create mode 100644 lib/generators/inertia/install/templates/react/inertia.js
create mode 100644 lib/generators/inertia/install/templates/react/inertia.ts
create mode 100644 lib/generators/inertia/install/templates/react/tsconfig.app.json
create mode 100644 lib/generators/inertia/install/templates/react/tsconfig.json
create mode 100644 lib/generators/inertia/install/templates/react/tsconfig.node.json
create mode 100644 lib/generators/inertia/install/templates/react/vite-env.d.ts
create mode 100644 lib/generators/inertia/install/templates/svelte/InertiaExample.svelte
create mode 100644 lib/generators/inertia/install/templates/svelte/InertiaExample.ts.svelte
create mode 100644 lib/generators/inertia/install/templates/svelte/inertia.js
create mode 100644 lib/generators/inertia/install/templates/svelte/inertia.ts
create mode 100644 lib/generators/inertia/install/templates/svelte/svelte.config.js
create mode 100644 lib/generators/inertia/install/templates/svelte/tsconfig.json
create mode 100644 lib/generators/inertia/install/templates/svelte/tsconfig.node.json
create mode 100644 lib/generators/inertia/install/templates/svelte/vite-env.d.ts
create mode 100644 lib/generators/inertia/install/templates/svelte4/InertiaExample.svelte
create mode 100644 lib/generators/inertia/install/templates/svelte4/InertiaExample.ts.svelte
create mode 100644 lib/generators/inertia/install/templates/svelte4/inertia.js
create mode 100644 lib/generators/inertia/install/templates/svelte4/inertia.ts
create mode 100644 lib/generators/inertia/install/templates/svelte4/svelte.config.js
create mode 100644 lib/generators/inertia/install/templates/svelte4/tsconfig.json
create mode 100644 lib/generators/inertia/install/templates/svelte4/tsconfig.node.json
create mode 100644 lib/generators/inertia/install/templates/svelte4/vite-env.d.ts
create mode 100644 lib/generators/inertia/install/templates/tailwind/application.css
create mode 100644 lib/generators/inertia/install/templates/tailwind/postcss.config.js
create mode 100644 lib/generators/inertia/install/templates/tailwind/tailwind.config.js.tt
create mode 100644 lib/generators/inertia/install/templates/vue/InertiaExample.ts.vue
create mode 100644 lib/generators/inertia/install/templates/vue/InertiaExample.vue
create mode 100644 lib/generators/inertia/install/templates/vue/inertia.js
create mode 100644 lib/generators/inertia/install/templates/vue/inertia.ts
create mode 100644 lib/generators/inertia/install/templates/vue/tsconfig.app.json
create mode 100644 lib/generators/inertia/install/templates/vue/tsconfig.json
create mode 100644 lib/generators/inertia/install/templates/vue/tsconfig.node.json
create mode 100644 lib/generators/inertia/install/templates/vue/vite-env.d.ts
create mode 100644 lib/generators/inertia/scaffold/scaffold_generator.rb
create mode 100644 lib/generators/inertia/scaffold_controller/scaffold_controller_generator.rb
create mode 100644 lib/generators/inertia/scaffold_controller/templates/controller.rb.tt
delete mode 100644 lib/generators/inertia_rails/install/react/InertiaExample.jsx
delete mode 100644 lib/generators/inertia_rails/install/react/inertia.jsx
delete mode 100644 lib/generators/inertia_rails/install/svelte/InertiaExample.svelte
delete mode 100644 lib/generators/inertia_rails/install/svelte/inertia.js
delete mode 100644 lib/generators/inertia_rails/install/vue/InertiaExample.vue
delete mode 100644 lib/generators/inertia_rails/install/vue/inertia.js
delete mode 100644 lib/generators/inertia_rails/install_generator.rb
create mode 100644 lib/generators/inertia_templates/controller/controller_generator.rb
create mode 100644 lib/generators/inertia_templates/controller/templates/react/view.jsx.tt
create mode 100644 lib/generators/inertia_templates/controller/templates/svelte/view.svelte.tt
create mode 100644 lib/generators/inertia_templates/controller/templates/svelte4/view.svelte.tt
create mode 100644 lib/generators/inertia_templates/controller/templates/vue/view.vue.tt
create mode 100644 lib/generators/inertia_templates/scaffold/scaffold_generator.rb
create mode 100644 lib/generators/inertia_templates/scaffold/templates/react/Edit.jsx.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/react/Form.jsx.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/react/Index.jsx.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/react/New.jsx.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/react/One.jsx.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/react/Show.jsx.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/svelte/Edit.svelte.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/svelte/Form.svelte.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/svelte/Index.svelte.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/svelte/New.svelte.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/svelte/One.svelte.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/svelte/Show.svelte.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/svelte4/Edit.svelte.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/svelte4/Form.svelte.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/svelte4/Index.svelte.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/svelte4/New.svelte.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/svelte4/One.svelte.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/svelte4/Show.svelte.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/vue/Edit.vue.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/vue/Form.vue.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/vue/Index.vue.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/vue/New.vue.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/vue/One.vue.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/vue/Show.vue.tt
create mode 100644 lib/generators/inertia_tw_templates/controller/controller_generator.rb
create mode 100644 lib/generators/inertia_tw_templates/controller/templates/react/view.jsx.tt
create mode 100644 lib/generators/inertia_tw_templates/controller/templates/svelte/view.svelte.tt
create mode 100644 lib/generators/inertia_tw_templates/controller/templates/svelte4/view.svelte.tt
create mode 100644 lib/generators/inertia_tw_templates/controller/templates/vue/view.vue.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/scaffold_generator.rb
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/react/Edit.jsx.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/react/Form.jsx.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/react/Index.jsx.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/react/New.jsx.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/react/One.jsx.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/react/Show.jsx.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/svelte/Edit.svelte.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/svelte/Form.svelte.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/svelte/Index.svelte.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/svelte/New.svelte.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/svelte/One.svelte.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/svelte/Show.svelte.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/svelte4/Edit.svelte.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/svelte4/Form.svelte.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/svelte4/Index.svelte.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/svelte4/New.svelte.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/svelte4/One.svelte.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/svelte4/Show.svelte.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/vue/Edit.vue.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/vue/Form.vue.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/vue/Index.vue.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/vue/New.vue.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/vue/One.vue.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/vue/Show.vue.tt
create mode 100644 lib/inertia_rails/generators/controller_template_base.rb
create mode 100644 lib/inertia_rails/generators/helper.rb
create mode 100644 lib/inertia_rails/generators/scaffold_template_base.rb
create mode 100644 spec/fixtures/install_generator/dummy/Gemfile
create mode 100644 spec/fixtures/install_generator/dummy/app/views/layouts/application.html.erb
create mode 100644 spec/fixtures/install_generator/dummy/config/routes.rb
create mode 100644 spec/fixtures/install_generator/with_vite/app/views/layouts/application.html.erb
create mode 100644 spec/fixtures/install_generator/with_vite/config/vite.json
create mode 100644 spec/fixtures/install_generator/with_vite/package.json
create mode 100644 spec/fixtures/install_generator/with_vite/vite.config.ts
create mode 100644 spec/generators/install/install_generator_spec.rb
diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml
index 1384c27a..2e8d8a25 100644
--- a/.github/workflows/push.yml
+++ b/.github/workflows/push.yml
@@ -15,6 +15,20 @@ on:
- '**.md'
jobs:
+ lint:
+ runs-on: ubuntu-latest
+ name: Linter
+ steps:
+ - uses: actions/checkout@v4
+ - name: Set up Ruby
+ uses: ruby/setup-ruby@v1
+ with:
+ ruby-version: "3.3"
+ bundler: latest
+ bundler-cache: true
+ - name: Run RuboCop
+ run: bundle exec rubocop
+
test:
strategy:
fail-fast: false
@@ -31,6 +45,11 @@ jobs:
- name: Setup System
run: sudo apt-get install libsqlite3-dev
+ - name: Set up Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: 22.x
+
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
@@ -40,6 +59,6 @@ jobs:
RAILS_VERSION: ${{ matrix.rails }}
- name: Run tests
- run: bundle exec rake
+ run: bundle exec rspec
env:
RAILS_VERSION: ${{ matrix.rails }}
diff --git a/.rubocop.yml b/.rubocop.yml
new file mode 100644
index 00000000..bb580f41
--- /dev/null
+++ b/.rubocop.yml
@@ -0,0 +1,15 @@
+inherit_from: .rubocop_todo.yml
+
+AllCops:
+ TargetRubyVersion: 3.0
+ NewCops: enable
+ SuggestExtensions: false
+
+Metrics:
+ Enabled: false
+
+Style/Documentation:
+ Enabled: false
+
+Style/TrailingCommaInHashLiteral:
+ EnforcedStyleForMultiline: consistent_comma
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
new file mode 100644
index 00000000..99d08152
--- /dev/null
+++ b/.rubocop_todo.yml
@@ -0,0 +1,631 @@
+# This configuration was generated by
+# `rubocop --auto-gen-config --exclude-limit 10000`
+# on 2024-11-11 08:39:28 UTC using RuboCop version 1.68.0.
+# The point is for the user to remove these configuration records
+# one by one as the offenses are removed from the code base.
+# Note that changes in the inspected code, or installation of new
+# versions of RuboCop, may require this file to be generated again.
+
+# Offense count: 1
+# This cop supports safe autocorrection (--autocorrect).
+# Configuration parameters: EnforcedStyle, IndentationWidth.
+# SupportedStyles: outdent, indent
+Layout/AccessModifierIndentation:
+ Exclude:
+ - 'lib/inertia_rails/configuration.rb'
+
+# Offense count: 2
+# This cop supports safe autocorrection (--autocorrect).
+# Configuration parameters: EnforcedStyle, IndentationWidth.
+# SupportedStyles: with_first_argument, with_fixed_indentation
+Layout/ArgumentAlignment:
+ Exclude:
+ - 'bin/console'
+ - 'spec/inertia/response_spec.rb'
+
+# Offense count: 5
+# This cop supports safe autocorrection (--autocorrect).
+Layout/BlockEndNewline:
+ Exclude:
+ - 'spec/inertia/rendering_spec.rb'
+
+# Offense count: 2
+# This cop supports safe autocorrection (--autocorrect).
+# Configuration parameters: AllowForAlignment.
+Layout/CommentIndentation:
+ Exclude:
+ - 'lib/inertia_rails/rspec.rb'
+
+# Offense count: 2
+# This cop supports safe autocorrection (--autocorrect).
+Layout/EmptyLineAfterGuardClause:
+ Exclude:
+ - 'lib/inertia_rails/configuration.rb'
+ - 'lib/inertia_rails/controller.rb'
+
+# Offense count: 1
+# This cop supports safe autocorrection (--autocorrect).
+Layout/EmptyLineAfterMagicComment:
+ Exclude:
+ - 'lib/inertia_rails/action_filter.rb'
+
+# Offense count: 1
+# This cop supports safe autocorrection (--autocorrect).
+# Configuration parameters: EnforcedStyle.
+# SupportedStyles: empty_lines, no_empty_lines
+Layout/EmptyLinesAroundBlockBody:
+ Exclude:
+ - 'spec/inertia/rails_mimic_spec.rb'
+
+# Offense count: 3
+# This cop supports safe autocorrection (--autocorrect).
+# Configuration parameters: AllowForAlignment, AllowBeforeTrailingComments, ForceEqualSignAlignment.
+Layout/ExtraSpacing:
+ Exclude:
+ - 'lib/inertia_rails/controller.rb'
+ - 'spec/inertia/request_spec.rb'
+ - 'spec/inertia/response_spec.rb'
+
+# Offense count: 1
+# This cop supports safe autocorrection (--autocorrect).
+# Configuration parameters: EnforcedStyle, IndentationWidth.
+# SupportedStyles: consistent, consistent_relative_to_receiver, special_for_inner_method_call, special_for_inner_method_call_in_parentheses
+Layout/FirstArgumentIndentation:
+ Exclude:
+ - 'spec/inertia/ssr_spec.rb'
+
+# Offense count: 2
+# This cop supports safe autocorrection (--autocorrect).
+# Configuration parameters: IndentationWidth.
+# SupportedStyles: special_inside_parentheses, consistent, align_braces
+Layout/FirstHashElementIndentation:
+ EnforcedStyle: consistent
+
+# Offense count: 1
+# This cop supports safe autocorrection (--autocorrect).
+# Configuration parameters: Width, AllowedPatterns.
+Layout/IndentationWidth:
+ Exclude:
+ - 'spec/inertia/configuration_spec.rb'
+
+# Offense count: 5
+# This cop supports safe autocorrection (--autocorrect).
+Layout/MultilineBlockLayout:
+ Exclude:
+ - 'spec/inertia/rendering_spec.rb'
+
+# Offense count: 4
+# This cop supports safe autocorrection (--autocorrect).
+# Configuration parameters: EnforcedStyle, IndentationWidth.
+# SupportedStyles: aligned, indented, indented_relative_to_receiver
+Layout/MultilineMethodCallIndentation:
+ Exclude:
+ - 'spec/inertia/ssr_spec.rb'
+
+# Offense count: 7
+# This cop supports safe autocorrection (--autocorrect).
+# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces.
+# SupportedStyles: space, no_space
+# SupportedStylesForEmptyBraces: space, no_space
+Layout/SpaceBeforeBlockBraces:
+ Exclude:
+ - 'spec/dummy/app/controllers/inertia_render_test_controller.rb'
+ - 'spec/inertia/error_sharing_spec.rb'
+ - 'spec/inertia/request_spec.rb'
+
+# Offense count: 4
+# This cop supports safe autocorrection (--autocorrect).
+# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBrackets.
+# SupportedStyles: space, no_space, compact
+# SupportedStylesForEmptyBrackets: space, no_space
+Layout/SpaceInsideArrayLiteralBrackets:
+ Exclude:
+ - 'spec/dummy/app/controllers/inertia_test_controller.rb'
+ - 'spec/dummy/config/environments/production.rb'
+
+# Offense count: 22
+# This cop supports safe autocorrection (--autocorrect).
+# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces, SpaceBeforeBlockParameters.
+# SupportedStyles: space, no_space
+# SupportedStylesForEmptyBraces: space, no_space
+Layout/SpaceInsideBlockBraces:
+ Exclude:
+ - 'lib/inertia_rails/renderer.rb'
+ - 'spec/inertia/configuration_spec.rb'
+ - 'spec/inertia/error_sharing_spec.rb'
+ - 'spec/inertia/rendering_spec.rb'
+ - 'spec/inertia/request_spec.rb'
+
+# Offense count: 130
+# This cop supports safe autocorrection (--autocorrect).
+# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces.
+# SupportedStyles: space, no_space, compact
+# SupportedStylesForEmptyBraces: space, no_space
+Layout/SpaceInsideHashLiteralBraces:
+ Exclude:
+ - 'lib/inertia_rails/controller.rb'
+ - 'lib/inertia_rails/middleware.rb'
+ - 'lib/patches/mapper.rb'
+ - 'spec/dummy/app/controllers/inertia_conditional_sharing_controller.rb'
+ - 'spec/dummy/app/controllers/inertia_share_test_controller.rb'
+ - 'spec/inertia/conditional_sharing_spec.rb'
+ - 'spec/inertia/configuration_spec.rb'
+ - 'spec/inertia/middleware_spec.rb'
+ - 'spec/inertia/rails_mimic_spec.rb'
+ - 'spec/inertia/rendering_spec.rb'
+ - 'spec/inertia/request_spec.rb'
+ - 'spec/inertia/rspec_helper_spec.rb'
+ - 'spec/inertia/sharing_spec.rb'
+ - 'spec/inertia/ssr_spec.rb'
+
+# Offense count: 2
+# This cop supports safe autocorrection (--autocorrect).
+# Configuration parameters: EnforcedStyle.
+# SupportedStyles: final_newline, final_blank_line
+Layout/TrailingEmptyLines:
+ Exclude:
+ - 'lib/tasks/inertia_rails.rake'
+ - 'spec/inertia/rails_mimic_spec.rb'
+
+# Offense count: 12
+# This cop supports safe autocorrection (--autocorrect).
+# Configuration parameters: AllowInHeredoc.
+Layout/TrailingWhitespace:
+ Exclude:
+ - 'lib/inertia_rails/rspec.rb'
+ - 'spec/dummy/app/controllers/inertia_render_test_controller.rb'
+ - 'spec/dummy/config/environments/test.rb'
+
+# Offense count: 1
+# Configuration parameters: AllowComments.
+Lint/EmptyClass:
+ Exclude:
+ - 'spec/dummy/app/controllers/inertia_responders_test_controller.rb'
+
+# Offense count: 1
+# Configuration parameters: AllowedParentClasses.
+Lint/MissingSuper:
+ Exclude:
+ - 'lib/inertia_rails/lazy_prop.rb'
+
+# Offense count: 1
+# This cop supports unsafe autocorrection (--autocorrect-all).
+# Configuration parameters: AllowedImplicitNamespaces.
+# AllowedImplicitNamespaces: Gem
+Lint/RaiseException:
+ Exclude:
+ - 'spec/dummy/app/controllers/inertia_multithreaded_share_controller.rb'
+
+# Offense count: 1
+# This cop supports safe autocorrection (--autocorrect).
+# Configuration parameters: EnforcedStyle.
+# SupportedStyles: strict, consistent
+Lint/SymbolConversion:
+ Exclude:
+ - 'spec/inertia/rails_mimic_spec.rb'
+
+# Offense count: 1
+# Configuration parameters: AllowKeywordBlockArguments.
+Lint/UnderscorePrefixedVariableName:
+ Exclude:
+ - 'lib/inertia_rails/renderer.rb'
+
+# Offense count: 1
+# This cop supports safe autocorrection (--autocorrect).
+# Configuration parameters: AutoCorrect, AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods.
+Lint/UnusedMethodArgument:
+ Exclude:
+ - 'lib/patches/mapper.rb'
+
+# Offense count: 1
+Naming/AccessorMethodName:
+ Exclude:
+ - 'lib/inertia_rails/rspec.rb'
+
+# Offense count: 2
+# Configuration parameters: ExpectMatchingDefinition, CheckDefinitionPathHierarchy, CheckDefinitionPathHierarchyRoots, Regex, IgnoreExecutableScripts, AllowedAcronyms.
+# CheckDefinitionPathHierarchyRoots: lib, spec, test, src
+# AllowedAcronyms: CLI, DSL, ACL, API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS
+Naming/FileName:
+ Exclude:
+ - 'Rakefile.rb'
+ - 'lib/patches/debug_exceptions/patch-5-0.rb'
+ - 'lib/patches/debug_exceptions/patch-5-1.rb'
+
+# Offense count: 2
+# Configuration parameters: EnforcedStyle, CheckMethodNames, CheckSymbols, AllowedIdentifiers, AllowedPatterns.
+# SupportedStyles: snake_case, normalcase, non_integer
+# AllowedIdentifiers: capture3, iso8601, rfc1123_date, rfc822, rfc2822, rfc3339, x86_64
+Naming/VariableNumber:
+ Exclude:
+ - 'spec/dummy/app/controllers/inertia_test_controller.rb'
+
+# Offense count: 21
+# This cop supports safe autocorrection (--autocorrect).
+# Configuration parameters: EnforcedStyle, ProceduralMethods, FunctionalMethods, AllowedMethods, AllowedPatterns, AllowBracesOnProceduralOneLiners, BracesRequiredMethods.
+# SupportedStyles: line_count_based, semantic, braces_for_chaining, always_braces
+# ProceduralMethods: benchmark, bm, bmbm, create, each_with_object, measure, new, realtime, tap, with_object
+# FunctionalMethods: let, let!, subject, watch
+# AllowedMethods: lambda, proc, it
+Style/BlockDelimiters:
+ Exclude:
+ - 'lib/inertia_rails/configuration.rb'
+ - 'lib/inertia_rails/controller.rb'
+ - 'spec/inertia/action_filter_spec.rb'
+ - 'spec/inertia/conditional_sharing_spec.rb'
+ - 'spec/inertia/configuration_spec.rb'
+ - 'spec/inertia/rendering_spec.rb'
+ - 'spec/inertia/request_spec.rb'
+ - 'spec/inertia/rspec_helper_spec.rb'
+ - 'spec/inertia/sharing_spec.rb'
+
+# Offense count: 1
+# This cop supports unsafe autocorrection (--autocorrect-all).
+# Configuration parameters: EnforcedStyle.
+# SupportedStyles: nested, compact
+Style/ClassAndModuleChildren:
+ Exclude:
+ - 'lib/inertia_rails/helper.rb'
+
+# Offense count: 2
+# This cop supports safe autocorrection (--autocorrect).
+Style/ColonMethodCall:
+ Exclude:
+ - 'spec/inertia/error_sharing_spec.rb'
+ - 'spec/inertia/rendering_spec.rb'
+
+# Offense count: 1
+# This cop supports safe autocorrection (--autocorrect).
+# Configuration parameters: EnforcedStyle, SingleLineConditionsOnly, IncludeTernaryExpressions.
+# SupportedStyles: assign_to_condition, assign_inside_condition
+Style/ConditionalAssignment:
+ Exclude:
+ - 'lib/inertia_rails/renderer.rb'
+
+# Offense count: 1
+# This cop supports safe autocorrection (--autocorrect).
+# Configuration parameters: AutoCorrect, EnforcedStyle, AllowComments.
+# SupportedStyles: empty, nil, both
+Style/EmptyElse:
+ Exclude:
+ - 'lib/patches/debug_exceptions.rb'
+
+# Offense count: 3
+# This cop supports safe autocorrection (--autocorrect).
+Style/EmptyLiteral:
+ Exclude:
+ - 'spec/inertia/request_spec.rb'
+
+# Offense count: 2
+# This cop supports safe autocorrection (--autocorrect).
+# Configuration parameters: AutoCorrect, EnforcedStyle.
+# SupportedStyles: compact, expanded
+Style/EmptyMethod:
+ Exclude:
+ - 'spec/dummy/app/controllers/transformed_inertia_rails_mimic_controller.rb'
+ - 'spec/inertia/rspec_helper_spec.rb'
+
+# Offense count: 1
+# This cop supports safe autocorrection (--autocorrect).
+Style/ExpandPathArguments:
+ Exclude:
+ - 'spec/rails_helper.rb'
+
+# Offense count: 74
+# This cop supports unsafe autocorrection (--autocorrect-all).
+# Configuration parameters: EnforcedStyle.
+# SupportedStyles: always, always_true, never
+Style/FrozenStringLiteralComment:
+ Exclude:
+ - 'app/controllers/inertia_rails/static_controller.rb'
+ - 'bin/console'
+ - 'lib/inertia_rails.rb'
+ - 'lib/inertia_rails/controller.rb'
+ - 'lib/inertia_rails/engine.rb'
+ - 'lib/inertia_rails/helper.rb'
+ - 'lib/inertia_rails/inertia_rails.rb'
+ - 'lib/inertia_rails/middleware.rb'
+ - 'lib/inertia_rails/rspec.rb'
+ - 'lib/inertia_rails/version.rb'
+ - 'lib/patches/better_errors.rb'
+ - 'lib/patches/debug_exceptions.rb'
+ - 'lib/patches/debug_exceptions/patch-5-0.rb'
+ - 'lib/patches/debug_exceptions/patch-5-1.rb'
+ - 'lib/patches/mapper.rb'
+ - 'lib/patches/request.rb'
+ - 'lib/tasks/inertia_rails.rake'
+ - 'spec/dummy/Rakefile'
+ - 'spec/dummy/app/controllers/application_controller.rb'
+ - 'spec/dummy/app/controllers/inertia_child_share_test_controller.rb'
+ - 'spec/dummy/app/controllers/inertia_conditional_sharing_controller.rb'
+ - 'spec/dummy/app/controllers/inertia_config_test_controller.rb'
+ - 'spec/dummy/app/controllers/inertia_lambda_shared_props_controller.rb'
+ - 'spec/dummy/app/controllers/inertia_merge_instance_props_controller.rb'
+ - 'spec/dummy/app/controllers/inertia_merge_shared_controller.rb'
+ - 'spec/dummy/app/controllers/inertia_multithreaded_share_controller.rb'
+ - 'spec/dummy/app/controllers/inertia_rails_mimic_controller.rb'
+ - 'spec/dummy/app/controllers/inertia_render_test_controller.rb'
+ - 'spec/dummy/app/controllers/inertia_responders_test_controller.rb'
+ - 'spec/dummy/app/controllers/inertia_session_continuity_test_controller.rb'
+ - 'spec/dummy/app/controllers/inertia_share_test_controller.rb'
+ - 'spec/dummy/app/controllers/inertia_test_controller.rb'
+ - 'spec/dummy/app/controllers/transformed_inertia_rails_mimic_controller.rb'
+ - 'spec/dummy/app/helpers/application_helper.rb'
+ - 'spec/dummy/bin/rails'
+ - 'spec/dummy/bin/rake'
+ - 'spec/dummy/bin/setup'
+ - 'spec/dummy/config.ru'
+ - 'spec/dummy/config/application.rb'
+ - 'spec/dummy/config/boot.rb'
+ - 'spec/dummy/config/environment.rb'
+ - 'spec/dummy/config/environments/development.rb'
+ - 'spec/dummy/config/environments/production.rb'
+ - 'spec/dummy/config/environments/test.rb'
+ - 'spec/dummy/config/initializers/application_controller_renderer.rb'
+ - 'spec/dummy/config/initializers/backtrace_silencers.rb'
+ - 'spec/dummy/config/initializers/content_security_policy.rb'
+ - 'spec/dummy/config/initializers/cookies_serializer.rb'
+ - 'spec/dummy/config/initializers/filter_parameter_logging.rb'
+ - 'spec/dummy/config/initializers/inflections.rb'
+ - 'spec/dummy/config/initializers/mime_types.rb'
+ - 'spec/dummy/config/initializers/wrap_parameters.rb'
+ - 'spec/dummy/config/puma.rb'
+ - 'spec/dummy/config/routes.rb'
+ - 'spec/dummy/config/spring.rb'
+ - 'spec/inertia/action_filter_spec.rb'
+ - 'spec/inertia/always_prop_spec.rb'
+ - 'spec/inertia/base_prop_spec.rb'
+ - 'spec/inertia/conditional_sharing_spec.rb'
+ - 'spec/inertia/configuration_spec.rb'
+ - 'spec/inertia/error_sharing_spec.rb'
+ - 'spec/inertia/lazy_prop_spec.rb'
+ - 'spec/inertia/middleware_spec.rb'
+ - 'spec/inertia/rails_mimic_spec.rb'
+ - 'spec/inertia/rendering_spec.rb'
+ - 'spec/inertia/request_spec.rb'
+ - 'spec/inertia/response_spec.rb'
+ - 'spec/inertia/rspec_helper_spec.rb'
+ - 'spec/inertia/sharing_spec.rb'
+ - 'spec/inertia/ssr_spec.rb'
+ - 'spec/rails_helper.rb'
+ - 'spec/spec_helper.rb'
+ - 'spec/support/helper_module.rb'
+ - 'spec/support/shared_examples.rb'
+
+# Offense count: 1
+# This cop supports unsafe autocorrection (--autocorrect-all).
+Style/GlobalStdStream:
+ Exclude:
+ - 'spec/dummy/config/environments/production.rb'
+
+# Offense count: 2
+# Configuration parameters: AllowedVariables.
+Style/GlobalVars:
+ Exclude:
+ - 'spec/inertia/rspec_helper_spec.rb'
+
+# Offense count: 1
+# This cop supports safe autocorrection (--autocorrect).
+# Configuration parameters: MinBodyLength, AllowConsecutiveConditionals.
+Style/GuardClause:
+ Exclude:
+ - 'lib/inertia_rails/configuration.rb'
+
+# Offense count: 1
+# This cop supports safe autocorrection (--autocorrect).
+# Configuration parameters: EnforcedStyle, EnforcedShorthandSyntax, UseHashRocketsWithSymbolValues, PreferHashRocketsForNonAlnumEndingSymbols.
+# SupportedStyles: ruby19, hash_rockets, no_mixed_keys, ruby19_no_mixed_keys
+# SupportedShorthandSyntax: always, never, either, consistent, either_consistent
+Style/HashSyntax:
+ Exclude:
+ - 'lib/tasks/inertia_rails.rake'
+
+# Offense count: 3
+# This cop supports safe autocorrection (--autocorrect).
+Style/IfUnlessModifier:
+ Exclude:
+ - 'lib/inertia_rails/configuration.rb'
+ - 'lib/inertia_rails/controller.rb'
+ - 'spec/dummy/config/environments/test.rb'
+
+# Offense count: 2
+# This cop supports safe autocorrection (--autocorrect).
+Style/IfUnlessModifierOfIfUnless:
+ Exclude:
+ - 'lib/inertia_rails/controller.rb'
+
+# Offense count: 1
+# This cop supports safe autocorrection (--autocorrect).
+Style/KeywordArgumentsMerging:
+ Exclude:
+ - 'lib/inertia_rails/configuration.rb'
+
+# Offense count: 2
+# This cop supports safe autocorrection (--autocorrect).
+# Configuration parameters: EnforcedStyle.
+# SupportedStyles: line_count_dependent, lambda, literal
+Style/Lambda:
+ Exclude:
+ - 'spec/dummy/app/controllers/inertia_lambda_shared_props_controller.rb'
+ - 'spec/dummy/app/controllers/transformed_inertia_rails_mimic_controller.rb'
+
+# Offense count: 1
+# This cop supports unsafe autocorrection (--autocorrect-all).
+Style/MapToSet:
+ Exclude:
+ - 'lib/inertia_rails/action_filter.rb'
+
+# Offense count: 1
+# This cop supports safe autocorrection (--autocorrect).
+Style/MultilineIfModifier:
+ Exclude:
+ - 'lib/inertia_rails/configuration.rb'
+
+# Offense count: 1
+# This cop supports unsafe autocorrection (--autocorrect-all).
+# Configuration parameters: EnforcedStyle.
+# SupportedStyles: literals, strict
+Style/MutableConstant:
+ Exclude:
+ - 'lib/inertia_rails/version.rb'
+
+# Offense count: 1
+# This cop supports safe autocorrection (--autocorrect).
+Style/NegatedIfElseCondition:
+ Exclude:
+ - 'lib/inertia_rails/renderer.rb'
+
+# Offense count: 2
+# This cop supports safe autocorrection (--autocorrect).
+Style/NestedModifier:
+ Exclude:
+ - 'lib/inertia_rails/controller.rb'
+
+# Offense count: 1
+Style/OpenStructUse:
+ Exclude:
+ - 'spec/inertia/ssr_spec.rb'
+
+# Offense count: 2
+# This cop supports safe autocorrection (--autocorrect).
+Style/RedundantBegin:
+ Exclude:
+ - 'spec/inertia/rspec_helper_spec.rb'
+
+# Offense count: 5
+# This cop supports safe autocorrection (--autocorrect).
+Style/RedundantConstantBase:
+ Exclude:
+ - 'lib/inertia_rails/rspec.rb'
+ - 'spec/dummy/config/environments/production.rb'
+ - 'spec/inertia/rspec_helper_spec.rb'
+
+# Offense count: 2
+# This cop supports unsafe autocorrection (--autocorrect-all).
+# Configuration parameters: SafeForConstants.
+Style/RedundantFetchBlock:
+ Exclude:
+ - 'spec/dummy/config/puma.rb'
+
+# Offense count: 1
+# This cop supports safe autocorrection (--autocorrect).
+# Configuration parameters: AllowMultipleReturnValues.
+Style/RedundantReturn:
+ Exclude:
+ - 'spec/dummy/app/controllers/inertia_session_continuity_test_controller.rb'
+
+# Offense count: 1
+# This cop supports safe autocorrection (--autocorrect).
+Style/RescueModifier:
+ Exclude:
+ - 'lib/inertia_rails/renderer.rb'
+
+# Offense count: 1
+# This cop supports safe autocorrection (--autocorrect).
+# Configuration parameters: AllowIfMethodIsEmpty.
+Style/SingleLineMethods:
+ Exclude:
+ - 'spec/dummy/app/controllers/inertia_test_controller.rb'
+
+# Offense count: 2
+# This cop supports safe autocorrection (--autocorrect).
+# Configuration parameters: AllowModifier.
+Style/SoleNestedConditional:
+ Exclude:
+ - 'lib/inertia_rails/controller.rb'
+
+# Offense count: 90
+# This cop supports safe autocorrection (--autocorrect).
+# Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline.
+# SupportedStyles: single_quotes, double_quotes
+Style/StringLiterals:
+ Exclude:
+ - 'bin/console'
+ - 'lib/inertia_rails/controller.rb'
+ - 'lib/inertia_rails/engine.rb'
+ - 'lib/inertia_rails/helper.rb'
+ - 'lib/inertia_rails/middleware.rb'
+ - 'lib/inertia_rails/renderer.rb'
+ - 'lib/inertia_rails/rspec.rb'
+ - 'lib/inertia_rails/version.rb'
+ - 'lib/patches/better_errors.rb'
+ - 'lib/patches/debug_exceptions/patch-5-0.rb'
+ - 'lib/patches/debug_exceptions/patch-5-1.rb'
+ - 'lib/tasks/inertia_rails.rake'
+ - 'spec/dummy/app/controllers/inertia_conditional_sharing_controller.rb'
+ - 'spec/dummy/app/controllers/inertia_config_test_controller.rb'
+ - 'spec/dummy/app/controllers/inertia_lambda_shared_props_controller.rb'
+ - 'spec/dummy/app/controllers/inertia_rails_mimic_controller.rb'
+ - 'spec/dummy/app/controllers/inertia_render_test_controller.rb'
+ - 'spec/dummy/config/application.rb'
+ - 'spec/dummy/config/environments/production.rb'
+ - 'spec/dummy/config/puma.rb'
+ - 'spec/dummy/config/routes.rb'
+ - 'spec/dummy/config/spring.rb'
+ - 'spec/inertia/conditional_sharing_spec.rb'
+ - 'spec/inertia/configuration_spec.rb'
+ - 'spec/inertia/rendering_spec.rb'
+ - 'spec/inertia/response_spec.rb'
+ - 'spec/inertia/rspec_helper_spec.rb'
+ - 'spec/rails_helper.rb'
+ - 'spec/spec_helper.rb'
+
+# Offense count: 1
+# This cop supports safe autocorrection (--autocorrect).
+# Configuration parameters: EnforcedStyle.
+# SupportedStyles: single_quotes, double_quotes
+Style/StringLiteralsInInterpolation:
+ Exclude:
+ - 'lib/inertia_rails/renderer.rb'
+
+# Offense count: 2
+# This cop supports safe autocorrection (--autocorrect).
+# Configuration parameters: .
+# SupportedStyles: percent, brackets
+Style/SymbolArray:
+ EnforcedStyle: percent
+ MinSize: 3
+
+# Offense count: 11
+# This cop supports safe autocorrection (--autocorrect).
+# Configuration parameters: EnforcedStyleForMultiline.
+# SupportedStylesForMultiline: comma, consistent_comma, no_comma
+Style/TrailingCommaInArguments:
+ Exclude:
+ - 'lib/inertia_rails.rb'
+ - 'lib/inertia_rails/renderer.rb'
+ - 'spec/dummy/app/controllers/inertia_config_test_controller.rb'
+ - 'spec/dummy/app/controllers/inertia_rails_mimic_controller.rb'
+ - 'spec/inertia/configuration_spec.rb'
+ - 'spec/inertia/rendering_spec.rb'
+
+# Offense count: 17
+# This cop supports safe autocorrection (--autocorrect).
+# Configuration parameters: EnforcedStyleForMultiline.
+# SupportedStylesForMultiline: comma, consistent_comma, no_comma
+Style/TrailingCommaInHashLiteral:
+ Exclude:
+ - 'lib/inertia_rails/rspec.rb'
+ - 'spec/dummy/app/controllers/inertia_lambda_shared_props_controller.rb'
+ - 'spec/dummy/app/controllers/inertia_merge_instance_props_controller.rb'
+ - 'spec/dummy/app/controllers/inertia_merge_shared_controller.rb'
+ - 'spec/dummy/app/controllers/inertia_render_test_controller.rb'
+ - 'spec/dummy/config/environments/development.rb'
+ - 'spec/dummy/config/environments/test.rb'
+ - 'spec/inertia/response_spec.rb'
+ - 'spec/inertia/rspec_helper_spec.rb'
+
+# Offense count: 1
+# This cop supports safe autocorrection (--autocorrect).
+# Configuration parameters: WordRegex.
+# SupportedStyles: percent, brackets
+Style/WordArray:
+ EnforcedStyle: percent
+ MinSize: 4
+
+# Offense count: 16
+# This cop supports safe autocorrection (--autocorrect).
+# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns.
+# URISchemes: http, https
+Layout/LineLength:
+ Max: 290
diff --git a/Gemfile b/Gemfile
index d5cb00b8..e1b35728 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,15 +1,19 @@
-source "https://rubygems.org"
+# frozen_string_literal: true
-# Specify your gem's dependencies in inertia-rails.gemspec
+source 'https://rubygems.org'
+
+# Specify your gem's dependencies in inertia_rails.gemspec
gemspec
-version = ENV["RAILS_VERSION"] || "7.2"
-gem "rails", "~> #{version}.0"
+version = ENV['RAILS_VERSION'] || '7.2'
+gem 'rails', "~> #{version}.0"
-gem "bundler", "~> 2.0"
-gem "rake", "~> 13.0"
-gem "rspec-rails", "~> 6.0"
-gem "rails-controller-testing"
-gem "sqlite3"
-gem "responders"
-gem "debug"
+gem 'bundler', '~> 2.0'
+gem 'debug'
+gem 'generator_spec', '~> 0.10'
+gem 'rails-controller-testing'
+gem 'rake', '~> 13.0'
+gem 'responders'
+gem 'rspec-rails', '~> 6.0'
+gem 'rubocop', '~> 1.21'
+gem 'sqlite3'
diff --git a/Rakefile b/Rakefile
index b7e9ed54..49647511 100644
--- a/Rakefile
+++ b/Rakefile
@@ -1,6 +1,12 @@
-require "bundler/gem_tasks"
-require "rspec/core/rake_task"
+# frozen_string_literal: true
+
+require 'bundler/gem_tasks'
+require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new(:spec)
-task :default => :spec
+require 'rubocop/rake_task'
+
+RuboCop::RakeTask.new
+
+task default: %i[spec rubocop]
diff --git a/docs/guide/responses.md b/docs/guide/responses.md
index c67d2d75..99e93154 100644
--- a/docs/guide/responses.md
+++ b/docs/guide/responses.md
@@ -125,7 +125,7 @@ You can then access this variable like a regular local variable.
## Rails generators
-Gem `inertia_rails-contrib` provides a number of generators to help you get started with Inertia in your Rails application. You can generate controllers or use scaffolds to create a new resource with Inertia responses.
+Inertia Rails provides a number of generators to help you get started with Inertia in your Rails application. You can generate controllers or use scaffolds to create a new resource with Inertia responses.
### Scaffold generator
@@ -168,7 +168,7 @@ $ bin/rails generate inertia:scaffold Post title:string body:text
#### Tailwind CSS integration
-Gem `inertia_rails-contrib` tries to detect the presence of Tailwind CSS in the application and generate the templates accordingly. If you want to specify templates type, use the `--inertia-templates` option:
+Inertia Rails tries to detect the presence of Tailwind CSS in the application and generate the templates accordingly. If you want to specify templates type, use the `--inertia-templates` option:
- `inertia_templates` - default
- `inertia_tw_templates` - Tailwind CSS
@@ -213,10 +213,10 @@ export default function <%= @action.camelize %>() {
You can find the default templates in the gem's source code:
-- [Default controller generator templates](https://github.com/skryukov/inertia_rails-contrib/tree/main/lib/generators/inertia_templates/controller/templates)
-- [Default scaffold generator templates](https://github.com/skryukov/inertia_rails-contrib/tree/main/lib/generators/inertia_templates/scaffold/templates)
-- [Tailwind controller generator templates](https://github.com/skryukov/inertia_rails-contrib/tree/main/lib/generators/inertia_tw_templates/controller/templates)
-- [Tailwind scaffold generator templates](https://github.com/skryukov/inertia_rails-contrib/tree/main/lib/generators/inertia_tw_templates/scaffold/templates)
+- [Default controller generator templates](https://github.com/inertiajs/inertia-rails/tree/master/lib/generators/inertia_templates/controller/templates)
+- [Default scaffold generator templates](https://github.com/inertiajs/inertia-rails/tree/master/lib/generators/inertia_templates/scaffold/templates)
+- [Tailwind controller generator templates](https://github.com/inertiajs/inertia-rails/tree/master/lib/generators/inertia_tw_templates/controller/templates)
+- [Tailwind scaffold generator templates](https://github.com/inertiajs/inertia-rails/tree/master/lib/generators/inertia_tw_templates/scaffold/templates)
> [!TIP]
> You can also replace the whole generator with your own implementation. See the [Rails documentation](https://guides.rubyonrails.org/generators.html#overriding-rails-generators) for more information.
diff --git a/docs/guide/server-side-setup.md b/docs/guide/server-side-setup.md
index b29c35b7..7351c6ef 100644
--- a/docs/guide/server-side-setup.md
+++ b/docs/guide/server-side-setup.md
@@ -15,12 +15,11 @@ bundle add inertia_rails
## Rails generator
-If you plan to use Vite as your frontend build tool, you can use the `inertia_rails-contrib` gem to install and set up Inertia in a Rails application. It automatically detects if the [Vite Rails](https://vite-ruby.netlify.app/guide/rails.html) gem is installed and will attempt to install it if not present.
+If you plan to use Vite as your frontend build tool, you can use the built-in generator to install and set up Inertia in a Rails application. It automatically detects if the [Vite Rails](https://vite-ruby.netlify.app/guide/rails.html) gem is installed and will attempt to install it if not present.
To install and setup Inertia in a Rails application, execute the following command in the terminal:
```bash
-bundle add inertia_rails-contrib
bin/rails generate inertia:install
```
@@ -38,7 +37,7 @@ This command will:
> To use TypeScript with Svelte, you need to install `@inertiajs/svelte` version `1.3.0-beta.2` or higher. You can use the `--inertia-version` option to specify the version.
> [!NOTE]
-> The `inertia_rails-contrib` gem doesn't include [Rails scaffold generators](/guide/responses#rails-generators) for TypeScript yet.
+> The built-in generator doesn't include [Rails scaffold generators](/guide/responses#rails-generators) for TypeScript yet.
Example output:
diff --git a/inertia_rails.gemspec b/inertia_rails.gemspec
index cb63ade9..5277b65a 100644
--- a/inertia_rails.gemspec
+++ b/inertia_rails.gemspec
@@ -1,29 +1,32 @@
# frozen_string_literal: true
-require_relative "lib/inertia_rails/version"
+require_relative 'lib/inertia_rails/version'
Gem::Specification.new do |spec|
- spec.name = "inertia_rails"
+ spec.name = 'inertia_rails'
spec.version = InertiaRails::VERSION
- spec.authors = ["Brian Knoles", "Brandon Shar", "Eugene Granovsky"]
- spec.email = ["brian@bellawatt.com", "brandon@bellawatt.com", "eugene@bellawatt.com"]
+ spec.authors = ['Brian Knoles', 'Brandon Shar', 'Eugene Granovsky']
+ spec.email = ['brian@bellawatt.com', 'brandon@bellawatt.com', 'eugene@bellawatt.com']
- spec.summary = "Inertia.js adapter for Rails"
- spec.description = "Quickly build modern single-page React, Vue and Svelte apps using classic server-side routing and controllers."
- spec.homepage = "https://github.com/inertiajs/inertia-rails"
- spec.license = "MIT"
+ spec.summary = 'Inertia.js adapter for Rails'
+ spec.description = 'Quickly build modern single-page React, Vue and Svelte apps ' \
+ 'using classic server-side routing and controllers.'
+ spec.homepage = 'https://github.com/inertiajs/inertia-rails'
+ spec.license = 'MIT'
+
+ spec.required_ruby_version = '>= 3.0'
spec.metadata = {
- "bug_tracker_uri" => "#{spec.homepage}/issues",
- "changelog_uri" => "#{spec.homepage}/blob/master/CHANGELOG.md",
- "documentation_uri" => "#{spec.homepage}/blob/master/README.md",
- "homepage_uri" => spec.homepage,
- "source_code_uri" => spec.homepage,
- "rubygems_mfa_required" => "true"
+ 'bug_tracker_uri' => "#{spec.homepage}/issues",
+ 'changelog_uri' => "#{spec.homepage}/blob/master/CHANGELOG.md",
+ 'documentation_uri' => "#{spec.homepage}/blob/master/README.md",
+ 'homepage_uri' => spec.homepage,
+ 'source_code_uri' => spec.homepage,
+ 'rubygems_mfa_required' => 'true',
}
- spec.files = Dir["{app,lib}/**/*", "CHANGELOG.md", "LICENSE.txt", "README.md"]
- spec.require_paths = ["lib"]
+ spec.files = Dir['{app,lib}/**/*', 'CHANGELOG.md', 'LICENSE.txt', 'README.md']
+ spec.require_paths = ['lib']
- spec.add_runtime_dependency "railties", '>= 6'
+ spec.add_dependency 'railties', '>= 6'
end
diff --git a/lib/generators/inertia/controller/controller_generator.rb b/lib/generators/inertia/controller/controller_generator.rb
new file mode 100644
index 00000000..9356b2a5
--- /dev/null
+++ b/lib/generators/inertia/controller/controller_generator.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+require 'rails/generators/rails/controller/controller_generator'
+require 'inertia_rails/generators/helper'
+
+module Inertia
+ module Generators
+ class ControllerGenerator < Rails::Generators::ControllerGenerator
+ include InertiaRails::Generators::Helper
+
+ source_root File.expand_path('./templates', __dir__)
+
+ remove_hook_for :template_engine
+
+ hook_for :inertia_templates, required: true, default: InertiaRails::Generators::Helper.guess_inertia_template
+ end
+ end
+end
diff --git a/lib/generators/inertia/controller/templates/controller.rb.tt b/lib/generators/inertia/controller/templates/controller.rb.tt
new file mode 100644
index 00000000..53eb0eb4
--- /dev/null
+++ b/lib/generators/inertia/controller/templates/controller.rb.tt
@@ -0,0 +1,10 @@
+<% module_namespacing do -%>
+class <%= class_name %>Controller < <%= parent_class_name.classify %>
+<% actions.each do |action| -%>
+ def <%= action %>
+ render inertia: '<%= "#{inertia_base_path}/#{action.camelize}" %>'
+ end
+<%= "\n" unless action == actions.last -%>
+<% end -%>
+end
+<% end -%>
diff --git a/lib/generators/inertia/install/frameworks.yml b/lib/generators/inertia/install/frameworks.yml
new file mode 100644
index 00000000..6a11dc64
--- /dev/null
+++ b/lib/generators/inertia/install/frameworks.yml
@@ -0,0 +1,98 @@
+react:
+ inertia_package: "@inertiajs/react"
+ packages:
+ - "@vitejs/plugin-react"
+ - "react"
+ - "react-dom"
+ packages_ts:
+ - "@types/react"
+ - "@types/react-dom"
+ - "typescript"
+ vite_plugin_import: "import react from '@vitejs/plugin-react'"
+ vite_plugin_call: "react()"
+ copy_files_ts:
+ "InertiaExample.tsx": "%{js_destination_path}/pages/InertiaExample.tsx"
+ "tsconfig.json": "tsconfig.json"
+ "tsconfig.app.json": "tsconfig.app.json"
+ "tsconfig.node.json": "tsconfig.node.json"
+ "vite-env.d.ts": "%{js_destination_path}/vite-env.d.ts"
+ copy_files_js:
+ "InertiaExample.jsx": "%{js_destination_path}/pages/InertiaExample.jsx"
+ copy_files:
+ "InertiaExample.module.css": "%{js_destination_path}/pages/InertiaExample.module.css"
+ "../assets/react.svg": "%{js_destination_path}/assets/react.svg"
+ "../assets/inertia.svg": "%{js_destination_path}/assets/inertia.svg"
+ "../assets/vite_ruby.svg": "%{js_destination_path}/assets/vite_ruby.svg"
+
+vue:
+ inertia_package: "@inertiajs/vue3"
+ packages:
+ - "vue"
+ - "@vitejs/plugin-vue"
+ packages_ts:
+ - "typescript"
+ - "vue-tsc"
+ vite_plugin_import: "import vue from '@vitejs/plugin-vue'"
+ vite_plugin_call: "vue()"
+ copy_files:
+ "../assets/vue.svg": "%{js_destination_path}/assets/vue.svg"
+ "../assets/inertia.svg": "%{js_destination_path}/assets/inertia.svg"
+ "../assets/vite_ruby.svg": "%{js_destination_path}/assets/vite_ruby.svg"
+ copy_files_ts:
+ "InertiaExample.ts.vue": "%{js_destination_path}/pages/InertiaExample.vue"
+ "tsconfig.json": "tsconfig.json"
+ "tsconfig.app.json": "tsconfig.app.json"
+ "tsconfig.node.json": "tsconfig.node.json"
+ "vite-env.d.ts": "%{js_destination_path}/vite-env.d.ts"
+ copy_files_js:
+ "InertiaExample.vue": "%{js_destination_path}/pages/InertiaExample.vue"
+
+svelte4:
+ inertia_package: "@inertiajs/svelte"
+ packages:
+ - "svelte@4"
+ - "@sveltejs/vite-plugin-svelte@3"
+ packages_ts:
+ - "@tsconfig/svelte@4"
+ - "svelte-check"
+ - "typescript"
+ - "tslib"
+ vite_plugin_import: "import { svelte } from '@sveltejs/vite-plugin-svelte'"
+ vite_plugin_call: "svelte()"
+ copy_files_ts:
+ "InertiaExample.ts.svelte": "%{js_destination_path}/pages/InertiaExample.svelte"
+ "tsconfig.json": "tsconfig.json"
+ "tsconfig.node.json": "tsconfig.node.json"
+ "vite-env.d.ts": "%{js_destination_path}/vite-env.d.ts"
+ copy_files_js:
+ "InertiaExample.svelte": "%{js_destination_path}/pages/InertiaExample.svelte"
+ copy_files:
+ "svelte.config.js": "svelte.config.js"
+ "../assets/svelte.svg": "%{js_destination_path}/assets/svelte.svg"
+ "../assets/inertia.svg": "%{js_destination_path}/assets/inertia.svg"
+ "../assets/vite_ruby.svg": "%{js_destination_path}/assets/vite_ruby.svg"
+
+svelte:
+ inertia_package: "@inertiajs/svelte"
+ packages:
+ - "svelte@5"
+ - "@sveltejs/vite-plugin-svelte@4"
+ packages_ts:
+ - "@tsconfig/svelte@5"
+ - "svelte-check"
+ - "typescript"
+ - "tslib"
+ vite_plugin_import: "import { svelte } from '@sveltejs/vite-plugin-svelte'"
+ vite_plugin_call: "svelte()"
+ copy_files_ts:
+ "InertiaExample.ts.svelte": "%{js_destination_path}/pages/InertiaExample.svelte"
+ "tsconfig.json": "tsconfig.json"
+ "tsconfig.node.json": "tsconfig.node.json"
+ "vite-env.d.ts": "%{js_destination_path}/vite-env.d.ts"
+ copy_files_js:
+ "InertiaExample.svelte": "%{js_destination_path}/pages/InertiaExample.svelte"
+ copy_files:
+ "svelte.config.js": "svelte.config.js"
+ "../assets/svelte.svg": "%{js_destination_path}/assets/svelte.svg"
+ "../assets/inertia.svg": "%{js_destination_path}/assets/inertia.svg"
+ "../assets/vite_ruby.svg": "%{js_destination_path}/assets/vite_ruby.svg"
diff --git a/lib/generators/inertia/install/helpers.rb b/lib/generators/inertia/install/helpers.rb
new file mode 100644
index 00000000..f21f2e57
--- /dev/null
+++ b/lib/generators/inertia/install/helpers.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+module Inertia
+ module Generators
+ module Helpers
+ ### FS Helpers
+ def js_destination_path
+ return ViteRuby.config.source_code_dir if defined?(ViteRuby)
+
+ if file?('config/vite.json')
+ source_code_dir = JSON.parse(File.read(file_path('config/vite.json'))).dig('all', 'sourceCodeDir')
+ return source_code_dir if source_code_dir
+ end
+
+ 'app/frontend'
+ end
+
+ def js_destination_root
+ file_path(js_destination_path)
+ end
+
+ def js_file_path(*relative_path)
+ File.join(js_destination_root, *relative_path)
+ end
+
+ def file?(*relative_path)
+ File.file?(file_path(*relative_path))
+ end
+
+ def file_path(*relative_path)
+ File.join(destination_root, *relative_path)
+ end
+
+ # Interactivity Helpers
+ def ask(*)
+ unless options[:interactive]
+ say_error 'Specify all options when running the generator non-interactively.', :red
+ exit(1)
+ end
+
+ super
+ end
+
+ def yes?(*)
+ return false unless options[:interactive]
+
+ super
+ end
+ end
+ end
+end
diff --git a/lib/generators/inertia/install/install_generator.rb b/lib/generators/inertia/install/install_generator.rb
new file mode 100644
index 00000000..5a1a0c90
--- /dev/null
+++ b/lib/generators/inertia/install/install_generator.rb
@@ -0,0 +1,286 @@
+# frozen_string_literal: true
+
+require 'yaml'
+require 'rails/generators'
+require 'rails/generators/base'
+
+require_relative 'helpers'
+require_relative 'js_package_manager'
+
+module Inertia
+ module Generators
+ class InstallGenerator < Rails::Generators::Base
+ include Helpers
+
+ FRAMEWORKS = YAML.load_file(File.expand_path('./frameworks.yml', __dir__))
+
+ source_root File.expand_path('./templates', __dir__)
+
+ class_option :framework, type: :string,
+ desc: 'The framework you want to use with Inertia',
+ enum: FRAMEWORKS.keys,
+ default: nil
+
+ class_option :inertia_version, type: :string, default: 'latest',
+ desc: 'The version of Inertia.js to install'
+
+ class_option :typescript, type: :boolean, default: false,
+ desc: 'Whether to use TypeScript'
+
+ class_option :package_manager, type: :string, default: nil,
+ enum: JSPackageManager.package_managers,
+ desc: "The package manager you want to use to install Inertia's npm packages"
+
+ class_option :interactive, type: :boolean, default: true,
+ desc: 'Whether to prompt for optional installations'
+
+ class_option :install_tailwind, type: :boolean, default: false,
+ desc: 'Whether to install Tailwind CSS'
+ class_option :install_vite, type: :boolean, default: false,
+ desc: 'Whether to install Vite Ruby'
+ class_option :example_page, type: :boolean, default: true,
+ desc: 'Whether to add an example Inertia page'
+
+ class_option :verbose, type: :boolean, default: false,
+ desc: 'Run the generator in verbose mode'
+
+ remove_class_option :skip_namespace, :skip_collision_check
+
+ def install
+ say "Installing Inertia's Rails adapter"
+
+ if inertia_resolved_version.version == '0'
+ say_error "Could not find the Inertia.js package version #{options[:inertia_version]}.", :red
+ exit(false)
+ end
+
+ install_vite unless ruby_vite_installed?
+
+ install_typescript if typescript?
+
+ install_tailwind if install_tailwind?
+
+ install_inertia
+
+ install_example_page if options[:example_page]
+
+ say 'Copying bin/dev'
+ copy_file "#{__dir__}/templates/dev", 'bin/dev'
+ chmod 'bin/dev', 0o755, verbose: verbose?
+
+ say "Inertia's Rails adapter successfully installed", :green
+ end
+
+ private
+
+ def install_inertia
+ say "Adding Inertia's Rails adapter initializer"
+ template 'initializer.rb', file_path('config/initializers/inertia_rails.rb')
+
+ say 'Installing Inertia npm packages'
+ add_dependencies(*FRAMEWORKS[framework]['packages'])
+ add_dependencies(inertia_package)
+
+ unless File.read(vite_config_path).include?(FRAMEWORKS[framework]['vite_plugin_import'])
+ say "Adding Vite plugin for #{framework}"
+ insert_into_file vite_config_path, "\n #{FRAMEWORKS[framework]['vite_plugin_call']},", after: 'plugins: ['
+ prepend_file vite_config_path, "#{FRAMEWORKS[framework]['vite_plugin_import']}\n"
+ end
+
+ say "Copying #{inertia_entrypoint} entrypoint"
+ template "#{framework}/#{inertia_entrypoint}", js_file_path("entrypoints/#{inertia_entrypoint}")
+
+ if application_layout.exist?
+ say "Adding #{inertia_entrypoint} script tag to the application layout"
+ headers = <<-ERB
+ <%= #{vite_tag} "inertia" %>
+ <%= inertia_headers %>
+ ERB
+ insert_into_file application_layout.to_s, headers, after: "<%= vite_client_tag %>\n"
+
+ if framework == 'react' && !application_layout.read.include?('vite_react_refresh_tag')
+ say 'Adding Vite React Refresh tag to the application layout'
+ insert_into_file application_layout.to_s, "<%= vite_react_refresh_tag %>\n ",
+ before: '<%= vite_client_tag %>'
+ end
+
+ gsub_file application_layout.to_s, //, '' unless svelte?
+ else
+ say_error 'Could not find the application layout file. Please add the following tags manually:', :red
+ say_error '- ...'
+ say_error '+ ...'
+ say_error '+ <%= inertia_headers %>'
+ say_error '+ <%= vite_react_refresh_tag %>' if framework == 'react'
+ say_error "+ <%= #{vite_tag} \"inertia\" %>"
+ end
+ end
+
+ def install_typescript
+ say 'Adding TypeScript support'
+ if svelte? && inertia_resolved_version.release < Gem::Version.new('1.3.0')
+ say 'WARNING: @inertiajs/svelte < 1.3.0 does not support TypeScript ' \
+ "(resolved version: #{inertia_resolved_version}).",
+ :yellow
+ say 'Skipping TypeScript support for @inertiajs/svelte', :yellow
+ @typescript = false
+ return
+ end
+
+ add_dependencies(*FRAMEWORKS[framework]['packages_ts'])
+ end
+
+ def install_example_page
+ say 'Copying example Inertia controller'
+ template 'controller.rb', file_path('app/controllers/inertia_example_controller.rb')
+
+ say 'Adding a route for the example Inertia controller'
+ route "get 'inertia-example', to: 'inertia_example#index'"
+
+ say 'Copying page assets'
+ copy_files = FRAMEWORKS[framework]['copy_files'].merge(
+ FRAMEWORKS[framework]["copy_files_#{typescript? ? 'ts' : 'js'}"]
+ )
+ copy_files.each do |source, destination|
+ template "#{framework}/#{source}", file_path(format(destination, js_destination_path: js_destination_path))
+ end
+ end
+
+ def install_tailwind
+ say 'Installing Tailwind CSS'
+ add_dependencies(%w[tailwindcss postcss autoprefixer @tailwindcss/forms @tailwindcss/typography
+ @tailwindcss/container-queries])
+
+ template 'tailwind/tailwind.config.js', file_path('tailwind.config.js')
+ copy_file 'tailwind/postcss.config.js', file_path('postcss.config.js')
+ copy_file 'tailwind/application.css', js_file_path('entrypoints/application.css')
+
+ if application_layout.exist?
+ say 'Adding Tailwind CSS to the application layout'
+ insert_into_file application_layout.to_s, "<%= vite_stylesheet_tag \"application\" %>\n ",
+ before: '<%= vite_client_tag %>'
+ else
+ say_error 'Could not find the application layout file. Please add the following tags manually:', :red
+ say_error '+ <%= vite_stylesheet_tag "application" %>' if install_tailwind?
+ end
+ end
+
+ def install_vite
+ unless install_vite?
+ say_error 'This generator only supports Ruby on Rails with Vite.', :red
+ exit(false)
+ end
+
+ in_root do
+ Bundler.with_original_env do
+ if (capture = run('bundle add vite_rails', capture: !verbose?))
+ say 'Vite Rails gem successfully installed', :green
+ else
+ say capture
+ say_error 'Failed to install Vite Rails gem', :red
+ exit(false)
+ end
+ if (capture = run('bundle exec vite install', capture: !verbose?))
+ say 'Vite Rails successfully installed', :green
+ else
+ say capture
+ say_error 'Failed to install Vite Rails', :red
+ exit(false)
+ end
+ end
+ end
+ end
+
+ def ruby_vite_installed?
+ return true if package_manager.present? && ruby_vite?
+
+ if !package_manager.present?
+ say_status 'Could not find a package.json file to install Inertia to.', nil
+ elsif gem_installed?('webpacker') || gem_installed?('shakapacker')
+ say 'Webpacker or Shakapacker is installed.', :yellow
+ say 'Vite Ruby can work alongside Webpacker or Shakapacker, but it might cause issues.', :yellow
+ say 'Please see the Vite Ruby documentation for the migration guide:', :yellow
+ say 'https://vite-ruby.netlify.app/guide/migration.html#webpacker-%F0%9F%93%A6', :yellow
+ else
+ say_status 'Could not find a Vite configuration files ' \
+ '(`config/vite.json` & `vite.config.{ts,js,mjs,cjs,mts,cts}`).',
+ nil
+ end
+ false
+ end
+
+ def gem_installed?(name)
+ regex = /^[^#]*gem\s+['"]#{name}['"]/
+ File.read(file_path('Gemfile')).match?(regex)
+ end
+
+ def application_layout
+ @application_layout ||= Pathname.new(file_path('app/views/layouts/application.html.erb'))
+ end
+
+ def ruby_vite?
+ file?('config/vite.json') && vite_config_path
+ end
+
+ def package_manager
+ @package_manager ||= JSPackageManager.new(self)
+ end
+
+ def add_dependencies(*packages)
+ package_manager.add_dependencies(*packages)
+ end
+
+ def vite_config_path
+ @vite_config_path ||= Dir.glob(file_path('vite.config.{ts,js,mjs,cjs,mts,cts}')).first
+ end
+
+ def install_vite?
+ return @install_vite if defined?(@install_vite)
+
+ @install_vite = options[:install_vite] || yes?('Would you like to install Vite Ruby? (y/n)', :green)
+ end
+
+ def install_tailwind?
+ return @install_tailwind if defined?(@install_tailwind)
+
+ @install_tailwind = options[:install_tailwind] || yes?('Would you like to install Tailwind CSS? (y/n)', :green)
+ end
+
+ def typescript?
+ return @typescript if defined?(@typescript)
+
+ @typescript = options[:typescript] || yes?('Would you like to use TypeScript? (y/n)', :green)
+ end
+
+ def inertia_entrypoint
+ "inertia.#{typescript? ? 'ts' : 'js'}"
+ end
+
+ def vite_tag
+ typescript? ? 'vite_typescript_tag' : 'vite_javascript_tag'
+ end
+
+ def inertia_resolved_version
+ @inertia_resolved_version ||= Gem::Version.new(
+ `npm show @inertiajs/core@#{options[:inertia_version]} version`.strip
+ )
+ end
+
+ def verbose?
+ options[:verbose]
+ end
+
+ def svelte?
+ framework.start_with? 'svelte'
+ end
+
+ def inertia_package
+ "#{FRAMEWORKS[framework]['inertia_package']}@#{options[:inertia_version]}"
+ end
+
+ def framework
+ @framework ||= options[:framework] || ask('What framework do you want to use with Inertia?', :green,
+ limited_to: FRAMEWORKS.keys, default: 'react')
+ end
+ end
+ end
+end
diff --git a/lib/generators/inertia/install/js_package_manager.rb b/lib/generators/inertia/install/js_package_manager.rb
new file mode 100644
index 00000000..24b0f1a6
--- /dev/null
+++ b/lib/generators/inertia/install/js_package_manager.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+module Inertia
+ module Generators
+ class JSPackageManager
+ def self.package_managers
+ %w[npm yarn bun pnpm]
+ end
+
+ def initialize(generator)
+ @generator = generator
+ end
+
+ def present?
+ package_manager.present?
+ end
+
+ def add_dependencies(*dependencies)
+ options = @generator.options[:verbose] ? '' : ' --silent'
+ @generator.in_root do
+ @generator.run "#{package_manager} add #{dependencies.join(' ')}#{options}"
+ end
+ end
+
+ private
+
+ def package_manager
+ @package_manager ||= @generator.options[:package_manager] || detect_package_manager
+ end
+
+ def detect_package_manager
+ return nil unless file?('package.json')
+
+ if file?('package-lock.json')
+ 'npm'
+ elsif file?('bun.lockb')
+ 'bun'
+ elsif file?('pnpm-lock.yaml')
+ 'pnpm'
+ else
+ 'yarn'
+ end
+ end
+
+ def file?(*relative_path)
+ @generator.file?(*relative_path)
+ end
+ end
+ end
+end
diff --git a/lib/generators/inertia/install/templates/assets/inertia.svg b/lib/generators/inertia/install/templates/assets/inertia.svg
new file mode 100644
index 00000000..61ec585c
--- /dev/null
+++ b/lib/generators/inertia/install/templates/assets/inertia.svg
@@ -0,0 +1 @@
+
diff --git a/lib/generators/inertia/install/templates/assets/react.svg b/lib/generators/inertia/install/templates/assets/react.svg
new file mode 100644
index 00000000..ae3e3f22
--- /dev/null
+++ b/lib/generators/inertia/install/templates/assets/react.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/lib/generators/inertia/install/templates/assets/svelte.svg b/lib/generators/inertia/install/templates/assets/svelte.svg
new file mode 100644
index 00000000..dc9a29c1
--- /dev/null
+++ b/lib/generators/inertia/install/templates/assets/svelte.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/lib/generators/inertia/install/templates/assets/vite_ruby.svg b/lib/generators/inertia/install/templates/assets/vite_ruby.svg
new file mode 100644
index 00000000..c4d42701
--- /dev/null
+++ b/lib/generators/inertia/install/templates/assets/vite_ruby.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/lib/generators/inertia/install/templates/assets/vue.svg b/lib/generators/inertia/install/templates/assets/vue.svg
new file mode 100644
index 00000000..36a27ab2
--- /dev/null
+++ b/lib/generators/inertia/install/templates/assets/vue.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/lib/generators/inertia_rails/install/controller.rb b/lib/generators/inertia/install/templates/controller.rb
similarity index 64%
rename from lib/generators/inertia_rails/install/controller.rb
rename to lib/generators/inertia/install/templates/controller.rb
index 57d8d638..0c95ffe9 100644
--- a/lib/generators/inertia_rails/install/controller.rb
+++ b/lib/generators/inertia/install/templates/controller.rb
@@ -1,7 +1,9 @@
+# frozen_string_literal: true
+
class InertiaExampleController < ApplicationController
def index
render inertia: 'InertiaExample', props: {
- name: 'World',
+ name: params.fetch(:name, 'World'),
}
end
end
diff --git a/lib/generators/inertia/install/templates/dev b/lib/generators/inertia/install/templates/dev
new file mode 100644
index 00000000..ef33f02c
--- /dev/null
+++ b/lib/generators/inertia/install/templates/dev
@@ -0,0 +1,23 @@
+#!/usr/bin/env sh
+
+export PORT="${PORT:-3000}"
+
+if command -v overmind 1> /dev/null 2>&1
+then
+ overmind start -f Procfile.dev "$@"
+ exit $?
+fi
+
+if command -v hivemind 1> /dev/null 2>&1
+then
+ echo "Hivemind is installed. Running the application with Hivemind..."
+ exec hivemind Procfile.dev "$@"
+ exit $?
+fi
+
+if gem list --no-installed --exact --silent foreman; then
+ echo "Installing foreman..."
+ gem install foreman
+fi
+
+foreman start -f Procfile.dev "$@"
diff --git a/lib/generators/inertia/install/templates/initializer.rb b/lib/generators/inertia/install/templates/initializer.rb
new file mode 100644
index 00000000..4e3b52e5
--- /dev/null
+++ b/lib/generators/inertia/install/templates/initializer.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+
+InertiaRails.configure do |config|
+ config.ssr_enabled = ViteRuby.config.ssr_build_enabled
+ config.version = ViteRuby.digest
+end
diff --git a/lib/generators/inertia/install/templates/react/InertiaExample.jsx b/lib/generators/inertia/install/templates/react/InertiaExample.jsx
new file mode 100644
index 00000000..f159ccf2
--- /dev/null
+++ b/lib/generators/inertia/install/templates/react/InertiaExample.jsx
@@ -0,0 +1,60 @@
+import { Head } from '@inertiajs/react'
+import { useState } from 'react'
+
+import reactSvg from '/assets/react.svg'
+import inertiaSvg from '/assets/inertia.svg'
+import viteRubySvg from '/assets/vite_ruby.svg'
+
+import cs from './InertiaExample.module.css'
+
+export default function InertiaExample({ name }) {
+ const [count, setCount] = useState(0)
+
+ return (
+ <>
+
+
+
+
Hello {name}!
+
+
+
+
Inertia + Vite Ruby + React
+
+
+
+
+ Edit app/frontend/pages/InertiaExample.jsx
and save to
+ test HMR
+
+
+
+ Click on the Inertia, Vite Ruby, and React logos to learn more
+
+
+ >
+ )
+}
diff --git a/lib/generators/inertia/install/templates/react/InertiaExample.module.css b/lib/generators/inertia/install/templates/react/InertiaExample.module.css
new file mode 100644
index 00000000..dea73ca3
--- /dev/null
+++ b/lib/generators/inertia/install/templates/react/InertiaExample.module.css
@@ -0,0 +1,80 @@
+.root {
+ font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
+ line-height: 1.5;
+ font-weight: 400;
+ color: #213547;
+ background-color: #ffffff;
+ max-width: 1280px;
+ margin: 0 auto;
+ padding: 2rem;
+ text-align: center;
+}
+
+.h1 {
+ font-size: 3.2em;
+ line-height: 1.1;
+}
+
+.h2 {
+ font-size: 2.6em;
+ line-height: 1.1;
+}
+
+.button {
+ border-radius: 8px;
+ border: 1px solid transparent;
+ padding: 0.6em 1.2em;
+ font-size: 1em;
+ font-weight: 500;
+ font-family: inherit;
+ background-color: #f9f9f9;
+ cursor: pointer;
+ transition: border-color 0.25s;
+}
+.button:hover {
+ border-color: #646cff;
+}
+.button:focus,
+.button:focus-visible {
+ outline: 4px auto -webkit-focus-ring-color;
+}
+
+.logo {
+ display: inline-block;
+ height: 6em;
+ padding: 1.5em;
+ will-change: filter;
+ transition: filter 300ms;
+}
+.logo:hover {
+ filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.vite:hover {
+ filter: drop-shadow(0 0 2em #e4023baa);
+}
+.logo.react:hover {
+ filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+ from {
+ transform: rotate(0deg);
+ }
+ to {
+ transform: rotate(360deg);
+ }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+ .logo.react {
+ animation: logo-spin infinite 20s linear;
+ }
+}
+
+.card {
+ padding: 2em;
+}
+
+.read-the-docs {
+ color: #888;
+}
diff --git a/lib/generators/inertia/install/templates/react/InertiaExample.tsx b/lib/generators/inertia/install/templates/react/InertiaExample.tsx
new file mode 100644
index 00000000..8937b077
--- /dev/null
+++ b/lib/generators/inertia/install/templates/react/InertiaExample.tsx
@@ -0,0 +1,60 @@
+import { Head } from '@inertiajs/react'
+import { useState } from 'react'
+
+import reactSvg from '/assets/react.svg'
+import inertiaSvg from '/assets/inertia.svg'
+import viteRubySvg from '/assets/vite_ruby.svg'
+
+import cs from './InertiaExample.module.css'
+
+export default function InertiaExample({ name }: { name: string }) {
+ const [count, setCount] = useState(0)
+
+ return (
+ <>
+
+
+
+
Hello {name}!
+
+
+
+
Inertia + Vite Ruby + React
+
+
+
+
+ Edit app/frontend/pages/InertiaExample.jsx
and save to
+ test HMR
+
+
+
+ Click on the Inertia, Vite Ruby, and React logos to learn more
+
+
+ >
+ )
+}
diff --git a/lib/generators/inertia/install/templates/react/inertia.js b/lib/generators/inertia/install/templates/react/inertia.js
new file mode 100644
index 00000000..f00cad69
--- /dev/null
+++ b/lib/generators/inertia/install/templates/react/inertia.js
@@ -0,0 +1,34 @@
+import { createInertiaApp } from '@inertiajs/react'
+import { createElement } from 'react'
+import { createRoot } from 'react-dom/client'
+
+createInertiaApp({
+ // Set default page title
+ // see https://inertia-rails.netlify.app/guide/title-and-meta
+ //
+ // title: title => title ? `${title} - App` : 'App',
+
+ // Disable progress bar
+ //
+ // see https://inertia-rails.netlify.app/guide/progress-indicators
+ // progress: false,
+
+ resolve: (name) => {
+ const pages = import.meta.glob('../pages/**/*.jsx', { eager: true })
+ return pages[`../pages/${name}.jsx`]
+
+ // To use a default layout, import the Layout component
+ // and use the following lines.
+ // see https://inertia-rails.netlify.app/guide/pages#default-layouts
+ //
+ // const page = pages[`../pages/${name}.jsx`]
+ // page.default.layout ||= (page) => createElement(Layout, null, page)
+ // return page
+ },
+
+ setup({ el, App, props }) {
+ const root = createRoot(el)
+
+ root.render(createElement(App, props))
+ },
+})
diff --git a/lib/generators/inertia/install/templates/react/inertia.ts b/lib/generators/inertia/install/templates/react/inertia.ts
new file mode 100644
index 00000000..4ef3a280
--- /dev/null
+++ b/lib/generators/inertia/install/templates/react/inertia.ts
@@ -0,0 +1,36 @@
+import { createInertiaApp } from '@inertiajs/react'
+import { createElement, ReactNode } from 'react'
+import { createRoot } from 'react-dom/client'
+
+type ResolvedComponent = { default: ReactNode, layout?: (page: ReactNode) => ReactNode }
+
+createInertiaApp({
+ // Set default page title
+ // see https://inertia-rails.netlify.app/guide/title-and-meta
+ //
+ // title: title => title ? `${title} - App` : 'App',
+
+ // Disable progress bar
+ //
+ // see https://inertia-rails.netlify.app/guide/progress-indicators
+ // progress: false,
+
+ resolve: (name) => {
+ const pages = import.meta.glob('../pages/**/*.tsx', { eager: true })
+ return pages[`../pages/${name}.tsx`]
+
+ // To use a default layout, import the Layout component
+ // and use the following lines.
+ // see https://inertia-rails.netlify.app/guide/pages#default-layouts
+ //
+ // const page = pages[`../pages/${name}.tsx`]
+ // page.default.layout ||= (page) => createElement(Layout, null, page)
+ // return page
+ },
+
+ setup({ el, App, props }) {
+ const root = createRoot(el)
+
+ root.render(createElement(App, props))
+ },
+})
diff --git a/lib/generators/inertia/install/templates/react/tsconfig.app.json b/lib/generators/inertia/install/templates/react/tsconfig.app.json
new file mode 100644
index 00000000..ff1c5b10
--- /dev/null
+++ b/lib/generators/inertia/install/templates/react/tsconfig.app.json
@@ -0,0 +1,27 @@
+{
+ "compilerOptions": {
+ "composite": true,
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
+ "target": "ES2020",
+ "useDefineForClassFields": true,
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+ "jsx": "react-jsx",
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true,
+ },
+ "include": ["<%= js_destination_path %>"]
+}
diff --git a/lib/generators/inertia/install/templates/react/tsconfig.json b/lib/generators/inertia/install/templates/react/tsconfig.json
new file mode 100644
index 00000000..ea9d0cd8
--- /dev/null
+++ b/lib/generators/inertia/install/templates/react/tsconfig.json
@@ -0,0 +1,11 @@
+{
+ "files": [],
+ "references": [
+ {
+ "path": "./tsconfig.app.json"
+ },
+ {
+ "path": "./tsconfig.node.json"
+ }
+ ]
+}
diff --git a/lib/generators/inertia/install/templates/react/tsconfig.node.json b/lib/generators/inertia/install/templates/react/tsconfig.node.json
new file mode 100644
index 00000000..3afdd6e3
--- /dev/null
+++ b/lib/generators/inertia/install/templates/react/tsconfig.node.json
@@ -0,0 +1,13 @@
+{
+ "compilerOptions": {
+ "composite": true,
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
+ "skipLibCheck": true,
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "allowSyntheticDefaultImports": true,
+ "strict": true,
+ "noEmit": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/lib/generators/inertia/install/templates/react/vite-env.d.ts b/lib/generators/inertia/install/templates/react/vite-env.d.ts
new file mode 100644
index 00000000..11f02fe2
--- /dev/null
+++ b/lib/generators/inertia/install/templates/react/vite-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/lib/generators/inertia/install/templates/svelte/InertiaExample.svelte b/lib/generators/inertia/install/templates/svelte/InertiaExample.svelte
new file mode 100644
index 00000000..4c6d2942
--- /dev/null
+++ b/lib/generators/inertia/install/templates/svelte/InertiaExample.svelte
@@ -0,0 +1,112 @@
+
+
+
+ Inertia + Vite Ruby + Svelte Example
+
+
+
+
Hello {name}!
+
+
+
+
Inertia + Vite Ruby + Svelte
+
+
+
+
+ Edit app/frontend/pages/InertiaExample.svelte
and save to test
+ HMR
+
+
+
+ Click on the Inertia, Vite Ruby, and Svelte logos to learn more
+
+
+
+
diff --git a/lib/generators/inertia/install/templates/svelte/InertiaExample.ts.svelte b/lib/generators/inertia/install/templates/svelte/InertiaExample.ts.svelte
new file mode 100644
index 00000000..0ed1c7df
--- /dev/null
+++ b/lib/generators/inertia/install/templates/svelte/InertiaExample.ts.svelte
@@ -0,0 +1,112 @@
+
+
+
+ Inertia + Vite Ruby + Svelte Example
+
+
+
+
Hello {name}!
+
+
+
+
Inertia + Vite Ruby + Svelte
+
+
+
+
+ Edit app/frontend/pages/InertiaExample.svelte
and save to test
+ HMR
+
+
+
+ Click on the Inertia, Vite Ruby, and Svelte logos to learn more
+
+
+
+
diff --git a/lib/generators/inertia/install/templates/svelte/inertia.js b/lib/generators/inertia/install/templates/svelte/inertia.js
new file mode 100644
index 00000000..1ea6c22f
--- /dev/null
+++ b/lib/generators/inertia/install/templates/svelte/inertia.js
@@ -0,0 +1,30 @@
+import { createInertiaApp } from '@inertiajs/svelte'
+import { mount } from 'svelte';
+
+createInertiaApp({
+ // Set default page title
+ // see https://inertia-rails.netlify.app/guide/title-and-meta
+ //
+ // title: title => title ? `${title} - App` : 'App',
+
+ // Disable progress bar
+ //
+ // see https://inertia-rails.netlify.app/guide/progress-indicators
+ // progress: false,
+
+ resolve: (name) => {
+ const pages = import.meta.glob('../pages/**/*.svelte', { eager: true })
+ return pages[`../pages/${name}.svelte`]
+
+ // To use a default layout, import the Layout component
+ // and use the following lines.
+ // see https://inertia-rails.netlify.app/guide/pages#default-layouts
+ //
+ // const page = pages[`../pages/${name}.svelte`]
+ // return { default: page.default, layout: page.layout || Layout }
+ },
+
+ setup({ el, App, props }) {
+ mount(App, { target: el, props })
+ },
+})
diff --git a/lib/generators/inertia/install/templates/svelte/inertia.ts b/lib/generators/inertia/install/templates/svelte/inertia.ts
new file mode 100644
index 00000000..d6d55cd6
--- /dev/null
+++ b/lib/generators/inertia/install/templates/svelte/inertia.ts
@@ -0,0 +1,30 @@
+import { createInertiaApp, type ResolvedComponent } from '@inertiajs/svelte'
+import { mount } from 'svelte'
+
+createInertiaApp({
+ // Set default page title
+ // see https://inertia-rails.netlify.app/guide/title-and-meta
+ //
+ // title: title => title ? `${title} - App` : 'App',
+
+ // Disable progress bar
+ //
+ // see https://inertia-rails.netlify.app/guide/progress-indicators
+ // progress: false,
+
+ resolve: (name) => {
+ const pages = import.meta.glob('../pages/**/*.svelte', { eager: true })
+ return pages[`../pages/${name}.svelte`]
+
+ // To use a default layout, import the Layout component
+ // and use the following lines.
+ // see https://inertia-rails.netlify.app/guide/pages#default-layouts
+ //
+ // const page = pages[`../pages/${name}.svelte`]
+ // return { default: page.default, layout: page.layout || Layout }
+ },
+
+ setup({ el, App, props }) {
+ mount(App, { target: el, props })
+ },
+})
diff --git a/lib/generators/inertia/install/templates/svelte/svelte.config.js b/lib/generators/inertia/install/templates/svelte/svelte.config.js
new file mode 100644
index 00000000..b0683fd2
--- /dev/null
+++ b/lib/generators/inertia/install/templates/svelte/svelte.config.js
@@ -0,0 +1,7 @@
+import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'
+
+export default {
+ // Consult https://svelte.dev/docs#compile-time-svelte-preprocess
+ // for more information about preprocessors
+ preprocess: vitePreprocess(),
+}
diff --git a/lib/generators/inertia/install/templates/svelte/tsconfig.json b/lib/generators/inertia/install/templates/svelte/tsconfig.json
new file mode 100644
index 00000000..acbc1cdf
--- /dev/null
+++ b/lib/generators/inertia/install/templates/svelte/tsconfig.json
@@ -0,0 +1,21 @@
+{
+ "extends": "@tsconfig/svelte/tsconfig.json",
+ "compilerOptions": {
+ "target": "ESNext",
+ "useDefineForClassFields": true,
+ "module": "ESNext",
+ "resolveJsonModule": true,
+ /**
+ * Typecheck JS in `.svelte` and `.js` files by default.
+ * Disable checkJs if you'd like to use dynamic types in JS.
+ * Note that setting allowJs false does not prevent the use
+ * of JS in `.svelte` files.
+ */
+ "allowJs": true,
+ "checkJs": true,
+ "isolatedModules": true,
+ "moduleDetection": "force",
+ },
+ "include": ["<%= js_destination_path %>/**/*.ts", "<%= js_destination_path %>/**/*.js", "<%= js_destination_path %>/**/*.svelte"],
+ "references": [{ "path": "./tsconfig.node.json" }]
+}
diff --git a/lib/generators/inertia/install/templates/svelte/tsconfig.node.json b/lib/generators/inertia/install/templates/svelte/tsconfig.node.json
new file mode 100644
index 00000000..3126cd74
--- /dev/null
+++ b/lib/generators/inertia/install/templates/svelte/tsconfig.node.json
@@ -0,0 +1,12 @@
+{
+ "compilerOptions": {
+ "composite": true,
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
+ "skipLibCheck": true,
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "strict": true,
+ "noEmit": true,
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/lib/generators/inertia/install/templates/svelte/vite-env.d.ts b/lib/generators/inertia/install/templates/svelte/vite-env.d.ts
new file mode 100644
index 00000000..4078e747
--- /dev/null
+++ b/lib/generators/inertia/install/templates/svelte/vite-env.d.ts
@@ -0,0 +1,2 @@
+///
+///
diff --git a/lib/generators/inertia/install/templates/svelte4/InertiaExample.svelte b/lib/generators/inertia/install/templates/svelte4/InertiaExample.svelte
new file mode 100644
index 00000000..96785fe5
--- /dev/null
+++ b/lib/generators/inertia/install/templates/svelte4/InertiaExample.svelte
@@ -0,0 +1,116 @@
+
+
+
+ Inertia + Vite Ruby + Svelte Example
+
+
+
+
Hello {name}!
+
+
+
+
Inertia + Vite Ruby + Svelte
+
+
+
+
+ Edit app/frontend/pages/InertiaExample.svelte
and save to test
+ HMR
+
+
+
+ Click on the Inertia, Vite Ruby, and Svelte logos to learn more
+
+
+
+
diff --git a/lib/generators/inertia/install/templates/svelte4/InertiaExample.ts.svelte b/lib/generators/inertia/install/templates/svelte4/InertiaExample.ts.svelte
new file mode 100644
index 00000000..b0d42e3a
--- /dev/null
+++ b/lib/generators/inertia/install/templates/svelte4/InertiaExample.ts.svelte
@@ -0,0 +1,116 @@
+
+
+
+ Inertia + Vite Ruby + Svelte Example
+
+
+
+
Hello {name}!
+
+
+
+
Inertia + Vite Ruby + Svelte
+
+
+
+
+ Edit app/frontend/pages/InertiaExample.svelte
and save to test
+ HMR
+
+
+
+ Click on the Inertia, Vite Ruby, and Svelte logos to learn more
+
+
+
+
diff --git a/lib/generators/inertia/install/templates/svelte4/inertia.js b/lib/generators/inertia/install/templates/svelte4/inertia.js
new file mode 100644
index 00000000..7c288a6e
--- /dev/null
+++ b/lib/generators/inertia/install/templates/svelte4/inertia.js
@@ -0,0 +1,29 @@
+import { createInertiaApp } from '@inertiajs/svelte'
+
+createInertiaApp({
+ // Set default page title
+ // see https://inertia-rails.netlify.app/guide/title-and-meta
+ //
+ // title: title => title ? `${title} - App` : 'App',
+
+ // Disable progress bar
+ //
+ // see https://inertia-rails.netlify.app/guide/progress-indicators
+ // progress: false,
+
+ resolve: (name) => {
+ const pages = import.meta.glob('../pages/**/*.svelte', { eager: true })
+ return pages[`../pages/${name}.svelte`]
+
+ // To use a default layout, import the Layout component
+ // and use the following lines.
+ // see https://inertia-rails.netlify.app/guide/pages#default-layouts
+ //
+ // const page = pages[`../pages/${name}.svelte`]
+ // return { default: page.default, layout: page.layout || Layout }
+ },
+
+ setup({ el, App, props }) {
+ new App({ target: el, props })
+ },
+})
diff --git a/lib/generators/inertia/install/templates/svelte4/inertia.ts b/lib/generators/inertia/install/templates/svelte4/inertia.ts
new file mode 100644
index 00000000..a4a75495
--- /dev/null
+++ b/lib/generators/inertia/install/templates/svelte4/inertia.ts
@@ -0,0 +1,29 @@
+import { createInertiaApp, type ResolvedComponent } from '@inertiajs/svelte'
+
+createInertiaApp({
+ // Set default page title
+ // see https://inertia-rails.netlify.app/guide/title-and-meta
+ //
+ // title: title => title ? `${title} - App` : 'App',
+
+ // Disable progress bar
+ //
+ // see https://inertia-rails.netlify.app/guide/progress-indicators
+ // progress: false,
+
+ resolve: (name) => {
+ const pages = import.meta.glob('../pages/**/*.svelte', { eager: true })
+ return pages[`../pages/${name}.svelte`]
+
+ // To use a default layout, import the Layout component
+ // and use the following lines.
+ // see https://inertia-rails.netlify.app/guide/pages#default-layouts
+ //
+ // const page = pages[`../pages/${name}.svelte`]
+ // return { default: page.default, layout: page.layout || Layout }
+ },
+
+ setup({ el, App, props }) {
+ new App({ target: el, props })
+ },
+})
diff --git a/lib/generators/inertia/install/templates/svelte4/svelte.config.js b/lib/generators/inertia/install/templates/svelte4/svelte.config.js
new file mode 100644
index 00000000..b0683fd2
--- /dev/null
+++ b/lib/generators/inertia/install/templates/svelte4/svelte.config.js
@@ -0,0 +1,7 @@
+import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'
+
+export default {
+ // Consult https://svelte.dev/docs#compile-time-svelte-preprocess
+ // for more information about preprocessors
+ preprocess: vitePreprocess(),
+}
diff --git a/lib/generators/inertia/install/templates/svelte4/tsconfig.json b/lib/generators/inertia/install/templates/svelte4/tsconfig.json
new file mode 100644
index 00000000..acbc1cdf
--- /dev/null
+++ b/lib/generators/inertia/install/templates/svelte4/tsconfig.json
@@ -0,0 +1,21 @@
+{
+ "extends": "@tsconfig/svelte/tsconfig.json",
+ "compilerOptions": {
+ "target": "ESNext",
+ "useDefineForClassFields": true,
+ "module": "ESNext",
+ "resolveJsonModule": true,
+ /**
+ * Typecheck JS in `.svelte` and `.js` files by default.
+ * Disable checkJs if you'd like to use dynamic types in JS.
+ * Note that setting allowJs false does not prevent the use
+ * of JS in `.svelte` files.
+ */
+ "allowJs": true,
+ "checkJs": true,
+ "isolatedModules": true,
+ "moduleDetection": "force",
+ },
+ "include": ["<%= js_destination_path %>/**/*.ts", "<%= js_destination_path %>/**/*.js", "<%= js_destination_path %>/**/*.svelte"],
+ "references": [{ "path": "./tsconfig.node.json" }]
+}
diff --git a/lib/generators/inertia/install/templates/svelte4/tsconfig.node.json b/lib/generators/inertia/install/templates/svelte4/tsconfig.node.json
new file mode 100644
index 00000000..3126cd74
--- /dev/null
+++ b/lib/generators/inertia/install/templates/svelte4/tsconfig.node.json
@@ -0,0 +1,12 @@
+{
+ "compilerOptions": {
+ "composite": true,
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
+ "skipLibCheck": true,
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "strict": true,
+ "noEmit": true,
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/lib/generators/inertia/install/templates/svelte4/vite-env.d.ts b/lib/generators/inertia/install/templates/svelte4/vite-env.d.ts
new file mode 100644
index 00000000..4078e747
--- /dev/null
+++ b/lib/generators/inertia/install/templates/svelte4/vite-env.d.ts
@@ -0,0 +1,2 @@
+///
+///
diff --git a/lib/generators/inertia/install/templates/tailwind/application.css b/lib/generators/inertia/install/templates/tailwind/application.css
new file mode 100644
index 00000000..8666d2f3
--- /dev/null
+++ b/lib/generators/inertia/install/templates/tailwind/application.css
@@ -0,0 +1,13 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+/*
+
+@layer components {
+ .btn-primary {
+ @apply py-2 px-4 bg-blue-200;
+ }
+}
+
+*/
diff --git a/lib/generators/inertia/install/templates/tailwind/postcss.config.js b/lib/generators/inertia/install/templates/tailwind/postcss.config.js
new file mode 100644
index 00000000..2e7af2b7
--- /dev/null
+++ b/lib/generators/inertia/install/templates/tailwind/postcss.config.js
@@ -0,0 +1,6 @@
+export default {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+}
diff --git a/lib/generators/inertia/install/templates/tailwind/tailwind.config.js.tt b/lib/generators/inertia/install/templates/tailwind/tailwind.config.js.tt
new file mode 100644
index 00000000..dae93715
--- /dev/null
+++ b/lib/generators/inertia/install/templates/tailwind/tailwind.config.js.tt
@@ -0,0 +1,18 @@
+/** @type {import('tailwindcss').Config} */
+
+module.exports = {
+ content: [
+ './public/*.html',
+ './app/helpers/**/*.rb',
+ './<%= js_destination_path %>/**/*.{js,ts,jsx,tsx,vue,svelte}',
+ './app/views/**/*.{erb,haml,html,slim}'
+ ],
+ theme: {
+ extend: {},
+ },
+ plugins: [
+ require('@tailwindcss/forms'),
+ require('@tailwindcss/typography'),
+ require('@tailwindcss/container-queries'),
+ ]
+}
diff --git a/lib/generators/inertia/install/templates/vue/InertiaExample.ts.vue b/lib/generators/inertia/install/templates/vue/InertiaExample.ts.vue
new file mode 100644
index 00000000..42392ac4
--- /dev/null
+++ b/lib/generators/inertia/install/templates/vue/InertiaExample.ts.vue
@@ -0,0 +1,117 @@
+
+
+
+
+
Hello {{ name }}!
+
+
+
+
Inertia + Vite Ruby + Vue
+
+
+
+
+ Edit app/frontend/pages/InertiaExample.vue
and save to test
+ HMR
+
+
+
+ Click on the Inertia, Vite Ruby, and Vue logos to learn more
+
+
+
+
+
+
+
diff --git a/lib/generators/inertia/install/templates/vue/InertiaExample.vue b/lib/generators/inertia/install/templates/vue/InertiaExample.vue
new file mode 100644
index 00000000..06d00c5d
--- /dev/null
+++ b/lib/generators/inertia/install/templates/vue/InertiaExample.vue
@@ -0,0 +1,117 @@
+
+
+
+
+
Hello {{ name }}!
+
+
+
+
Inertia + Vite Ruby + Vue
+
+
+
+
+ Edit app/frontend/pages/InertiaExample.vue
and save to test
+ HMR
+
+
+
+ Click on the Inertia, Vite Ruby, and Vue logos to learn more
+
+
+
+
+
+
+
diff --git a/lib/generators/inertia/install/templates/vue/inertia.js b/lib/generators/inertia/install/templates/vue/inertia.js
new file mode 100644
index 00000000..5e72d481
--- /dev/null
+++ b/lib/generators/inertia/install/templates/vue/inertia.js
@@ -0,0 +1,33 @@
+import { createInertiaApp } from '@inertiajs/vue3'
+import { createApp, h } from 'vue'
+
+createInertiaApp({
+ // Set default page title
+ // see https://inertia-rails.netlify.app/guide/title-and-meta
+ //
+ // title: title => title ? `${title} - App` : 'App',
+
+ // Disable progress bar
+ //
+ // see https://inertia-rails.netlify.app/guide/progress-indicators
+ // progress: false,
+
+ resolve: (name) => {
+ const pages = import.meta.glob('../pages/**/*.vue', { eager: true })
+ return pages[`../pages/${name}.vue`]
+
+ // To use a default layout, import the Layout component
+ // and use the following lines.
+ // see https://inertia-rails.netlify.app/guide/pages#default-layouts
+ //
+ // const page = pages[`../pages/${name}.vue`]
+ // page.default.layout = page.default.layout || Layout
+ // return page
+ },
+
+ setup({ el, App, props, plugin }) {
+ createApp({ render: () => h(App, props) })
+ .use(plugin)
+ .mount(el)
+ },
+})
diff --git a/lib/generators/inertia/install/templates/vue/inertia.ts b/lib/generators/inertia/install/templates/vue/inertia.ts
new file mode 100644
index 00000000..b4c62d63
--- /dev/null
+++ b/lib/generators/inertia/install/templates/vue/inertia.ts
@@ -0,0 +1,33 @@
+import { createInertiaApp } from '@inertiajs/vue3'
+import {createApp, DefineComponent, h} from 'vue'
+
+createInertiaApp({
+ // Set default page title
+ // see https://inertia-rails.netlify.app/guide/title-and-meta
+ //
+ // title: title => title ? `${title} - App` : 'App',
+
+ // Disable progress bar
+ //
+ // see https://inertia-rails.netlify.app/guide/progress-indicators
+ // progress: false,
+
+ resolve: (name) => {
+ const pages = import.meta.glob('../pages/**/*.vue', { eager: true })
+ return pages[`../pages/${name}.vue`]
+
+ // To use a default layout, import the Layout component
+ // and use the following lines.
+ // see https://inertia-rails.netlify.app/guide/pages#default-layouts
+ //
+ // const page = pages[`../pages/${name}.vue`]
+ // page.default.layout = page.default.layout || Layout
+ // return page
+ },
+
+ setup({ el, App, props, plugin }) {
+ createApp({ render: () => h(App, props) })
+ .use(plugin)
+ .mount(el)
+ },
+})
diff --git a/lib/generators/inertia/install/templates/vue/tsconfig.app.json b/lib/generators/inertia/install/templates/vue/tsconfig.app.json
new file mode 100644
index 00000000..dc7d6ca1
--- /dev/null
+++ b/lib/generators/inertia/install/templates/vue/tsconfig.app.json
@@ -0,0 +1,24 @@
+{
+ "compilerOptions": {
+ "target": "ES2020",
+ "useDefineForClassFields": true,
+ "module": "ESNext",
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "isolatedModules": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+ "jsx": "preserve",
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true
+ },
+ "include": ["<%= js_destination_path %>/**/*.ts", "<%= js_destination_path %>/**/*.tsx", "<%= js_destination_path %>/**/*.vue"]
+}
diff --git a/lib/generators/inertia/install/templates/vue/tsconfig.json b/lib/generators/inertia/install/templates/vue/tsconfig.json
new file mode 100644
index 00000000..ea9d0cd8
--- /dev/null
+++ b/lib/generators/inertia/install/templates/vue/tsconfig.json
@@ -0,0 +1,11 @@
+{
+ "files": [],
+ "references": [
+ {
+ "path": "./tsconfig.app.json"
+ },
+ {
+ "path": "./tsconfig.node.json"
+ }
+ ]
+}
diff --git a/lib/generators/inertia/install/templates/vue/tsconfig.node.json b/lib/generators/inertia/install/templates/vue/tsconfig.node.json
new file mode 100644
index 00000000..0d3d7144
--- /dev/null
+++ b/lib/generators/inertia/install/templates/vue/tsconfig.node.json
@@ -0,0 +1,22 @@
+{
+ "compilerOptions": {
+ "target": "ES2022",
+ "lib": ["ES2023"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "isolatedModules": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/lib/generators/inertia/install/templates/vue/vite-env.d.ts b/lib/generators/inertia/install/templates/vue/vite-env.d.ts
new file mode 100644
index 00000000..11f02fe2
--- /dev/null
+++ b/lib/generators/inertia/install/templates/vue/vite-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/lib/generators/inertia/scaffold/scaffold_generator.rb b/lib/generators/inertia/scaffold/scaffold_generator.rb
new file mode 100644
index 00000000..6717e92c
--- /dev/null
+++ b/lib/generators/inertia/scaffold/scaffold_generator.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require 'rails/generators/rails/resource/resource_generator'
+
+module Inertia
+ module Generators
+ class ScaffoldGenerator < Rails::Generators::ResourceGenerator # :nodoc:
+ remove_hook_for :resource_controller
+ remove_class_option :actions
+
+ class_option :resource_route, type: :boolean
+
+ hook_for :scaffold_controller, required: true
+ end
+ end
+end
diff --git a/lib/generators/inertia/scaffold_controller/scaffold_controller_generator.rb b/lib/generators/inertia/scaffold_controller/scaffold_controller_generator.rb
new file mode 100644
index 00000000..86d22041
--- /dev/null
+++ b/lib/generators/inertia/scaffold_controller/scaffold_controller_generator.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+require 'rails/generators/resource_helpers'
+require 'inertia_rails/generators/helper'
+
+module Inertia
+ module Generators
+ # This class is a modified copy of Rails::Generators::ScaffoldControllerGenerator.
+ # We don't use inheritance because some gems (i.e. jsbuilder) monkey-patch it.
+ class ScaffoldControllerGenerator < Rails::Generators::NamedBase
+ include InertiaRails::Generators::Helper
+ include Rails::Generators::ResourceHelpers
+
+ source_root File.expand_path('./templates', __dir__)
+
+ check_class_collision suffix: 'Controller'
+
+ class_option :helper, type: :boolean
+ class_option :orm, banner: 'NAME', type: :string, required: true,
+ desc: 'ORM to generate the controller for'
+
+ class_option :skip_routes, type: :boolean, desc: "Don't add routes to config/routes.rb."
+
+ argument :attributes, type: :array, default: [], banner: 'field:type field:type'
+
+ def create_controller_files
+ template 'controller.rb',
+ File.join('app/controllers', controller_class_path, "#{controller_file_name}_controller.rb")
+ end
+
+ hook_for :inertia_templates, as: :scaffold, required: true,
+ default: InertiaRails::Generators::Helper.guess_inertia_template
+
+ hook_for :resource_route, in: :rails, required: true do |route|
+ invoke route unless options.skip_routes?
+ end
+
+ hook_for :test_framework, in: :rails, as: :scaffold
+
+ # Invoke the helper using the controller name (pluralized)
+ hook_for :helper, in: :rails, as: :scaffold do |invoked|
+ invoke invoked, [controller_name]
+ end
+
+ private
+
+ def permitted_params
+ attachments, others = attributes_names.partition { |name| attachments?(name) }
+ params = others.map { |name| ":#{name}" }
+ params += attachments.map { |name| "#{name}: []" }
+ params.join(', ')
+ end
+
+ def attachments?(name)
+ attribute = attributes.find { |attr| attr.name == name }
+ attribute&.attachments?
+ end
+ end
+ end
+end
diff --git a/lib/generators/inertia/scaffold_controller/templates/controller.rb.tt b/lib/generators/inertia/scaffold_controller/templates/controller.rb.tt
new file mode 100644
index 00000000..03e9a49f
--- /dev/null
+++ b/lib/generators/inertia/scaffold_controller/templates/controller.rb.tt
@@ -0,0 +1,100 @@
+<% module_namespacing do -%>
+class <%= controller_class_name %>Controller < ApplicationController
+ before_action :set_<%= singular_table_name %>, only: %i[ show edit update destroy ]
+
+<% if regular_class_path.any? -%>
+ wrap_parameters :<%= singular_table_name %>
+
+<% end -%>
+ inertia_share flash: -> { flash.to_hash }
+
+ # GET <%= route_url %>
+ def index
+ @<%= plural_table_name %> = <%= orm_class.all(class_name) %>
+ render inertia: '<%= "#{inertia_base_path}/Index" %>', props: {
+ <%= plural_table_name %>: @<%= plural_table_name %>.map do |<%= singular_table_name %>|
+ <%= "serialize_#{singular_table_name}" %>(<%= singular_table_name %>)
+ end
+ }
+ end
+
+ # GET <%= route_url %>/1
+ def show
+ render inertia: '<%= "#{inertia_base_path}/Show" %>', props: {
+ <%= singular_table_name %>: <%= "serialize_#{singular_table_name}" %>(@<%= singular_table_name %>)
+ }
+ end
+
+ # GET <%= route_url %>/new
+ def new
+ @<%= singular_table_name %> = <%= orm_class.build(class_name) %>
+ render inertia: '<%= "#{inertia_base_path}/New" %>', props: {
+ <%= singular_table_name %>: <%= "serialize_#{singular_table_name}" %>(@<%= singular_table_name %>)
+ }
+ end
+
+ # GET <%= route_url %>/1/edit
+ def edit
+ render inertia: '<%= "#{inertia_base_path}/Edit" %>', props: {
+ <%= singular_table_name %>: <%= "serialize_#{singular_table_name}" %>(@<%= singular_table_name %>)
+ }
+ end
+
+ # POST <%= route_url %>
+ def create
+ @<%= singular_table_name %> = <%= orm_class.build(class_name, "#{singular_table_name}_params") %>
+
+ if @<%= orm_instance.save %>
+ redirect_to <%= redirect_resource_name %>, notice: <%= %("#{human_name} was successfully created.") %>
+ else
+ redirect_to <%= new_helper %>, inertia: { errors: @<%= singular_table_name %>.errors }
+ end
+ end
+
+ # PATCH/PUT <%= route_url %>/1
+ def update
+ if @<%= orm_instance.update("#{singular_table_name}_params") %>
+ redirect_to <%= redirect_resource_name %>, notice: <%= %("#{human_name} was successfully updated.") %>
+ else
+ redirect_to <%= edit_helper %>, inertia: { errors: @<%= singular_table_name %>.errors }
+ end
+ end
+
+ # DELETE <%= route_url %>/1
+ def destroy
+ @<%= orm_instance.destroy %>
+ redirect_to <%= index_helper %>_url, notice: <%= %("#{human_name} was successfully destroyed.") %>
+ end
+
+ private
+ # Use callbacks to share common setup or constraints between actions.
+ def set_<%= singular_table_name %>
+ @<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %>
+ end
+
+ # Only allow a list of trusted parameters through.
+ def <%= "#{singular_table_name}_params" %>
+ <%- if attributes_names.empty? -%>
+ params.fetch(:<%= singular_table_name %>, {})
+ <%- else -%>
+ params.require(:<%= singular_table_name %>).permit(<%= permitted_params %>)
+ <%- end -%>
+ end
+
+ def <%= "serialize_#{singular_table_name}" %>(<%= singular_table_name %>)
+ <%= singular_table_name %>.as_json(only: [
+ <%= attributes_to_serialize.map { |attribute| ":#{attribute}" }.join(", ") %>
+ ])<%- if attributes.any?(&:attachment?) || attributes.any?(&:attachments?) -%>.tap do |hash|
+ <%- attributes.filter(&:attachment?).map do |attribute| -%>
+ hash["<%= attribute.column_name %>"] = {filename: <%= singular_table_name %>.<%= attribute.column_name %>.filename, url: url_for(<%= singular_table_name %>.<%= attribute.column_name %>)} if <%= singular_table_name %>.<%= attribute.column_name %>.attached?
+ <%- end -%>
+ <%- attributes.filter(&:attachments?).map do |attribute| -%>
+ hash["<%= attribute.column_name %>"] =
+ <%= singular_table_name %>.<%= attribute.column_name %>.flat_map do |file|
+ {filename: file.filename.to_s, url: url_for(file)}
+ end
+ <%- end -%>
+ end<% end %>
+ end
+end
+<% end -%>
diff --git a/lib/generators/inertia_rails/install/react/InertiaExample.jsx b/lib/generators/inertia_rails/install/react/InertiaExample.jsx
deleted file mode 100644
index ab8aeeb9..00000000
--- a/lib/generators/inertia_rails/install/react/InertiaExample.jsx
+++ /dev/null
@@ -1,9 +0,0 @@
-import React from 'react';
-
-const InertiaExample = ({name}) => (
- <>
- Hello {name}!
- >
-);
-
-export default InertiaExample;
diff --git a/lib/generators/inertia_rails/install/react/inertia.jsx b/lib/generators/inertia_rails/install/react/inertia.jsx
deleted file mode 100644
index b1def90d..00000000
--- a/lib/generators/inertia_rails/install/react/inertia.jsx
+++ /dev/null
@@ -1,17 +0,0 @@
-import { App } from '@inertiajs/inertia-react';
-import React from 'react';
-import { render } from 'react-dom';
-import { InertiaProgress } from '@inertiajs/progress';
-
-document.addEventListener('DOMContentLoaded', () => {
- InertiaProgress.init();
- const el = document.getElementById('app')
-
- render(
- require(`../Pages/${name}`).default}
- />,
- el
- )
-});
diff --git a/lib/generators/inertia_rails/install/svelte/InertiaExample.svelte b/lib/generators/inertia_rails/install/svelte/InertiaExample.svelte
deleted file mode 100644
index 4a2caef8..00000000
--- a/lib/generators/inertia_rails/install/svelte/InertiaExample.svelte
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
- Hello {name}!
-
\ No newline at end of file
diff --git a/lib/generators/inertia_rails/install/svelte/inertia.js b/lib/generators/inertia_rails/install/svelte/inertia.js
deleted file mode 100644
index 7310e20a..00000000
--- a/lib/generators/inertia_rails/install/svelte/inertia.js
+++ /dev/null
@@ -1,14 +0,0 @@
-import { createInertiaApp } from '@inertiajs/inertia-svelte'
-import { InertiaProgress } from '@inertiajs/progress'
-
-document.addEventListener('DOMContentLoaded', () => {
- InertiaProgress.init()
-
- createInertiaApp({
- id: 'app',
- resolve: name => import(`../Pages/${name}.svelte`),
- setup({ el, App, props }) {
- new App({ target: el, props })
- },
- })
-})
diff --git a/lib/generators/inertia_rails/install/vue/InertiaExample.vue b/lib/generators/inertia_rails/install/vue/InertiaExample.vue
deleted file mode 100644
index a52dfd01..00000000
--- a/lib/generators/inertia_rails/install/vue/InertiaExample.vue
+++ /dev/null
@@ -1,11 +0,0 @@
-
- Hello {{name}}!
-
-
-
diff --git a/lib/generators/inertia_rails/install/vue/inertia.js b/lib/generators/inertia_rails/install/vue/inertia.js
deleted file mode 100644
index bb692d9a..00000000
--- a/lib/generators/inertia_rails/install/vue/inertia.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import Vue from 'vue'
-
-import { app, plugin } from '@inertiajs/inertia-vue'
-import { InertiaProgress } from '@inertiajs/progress'
-
-document.addEventListener('DOMContentLoaded', () => {
- InertiaProgress.init();
- const el = document.getElementById('app')
-
- Vue.use(plugin)
-
- new Vue({
- render: h => h(app, {
- props: {
- initialPage: JSON.parse(el.dataset.page),
- resolveComponent: name => require(`../Pages/${name}`).default,
- },
- }),
- }).$mount(el)
-})
diff --git a/lib/generators/inertia_rails/install_generator.rb b/lib/generators/inertia_rails/install_generator.rb
deleted file mode 100644
index 2ddc8221..00000000
--- a/lib/generators/inertia_rails/install_generator.rb
+++ /dev/null
@@ -1,84 +0,0 @@
-module InertiaRails
- class InstallGenerator < Rails::Generators::Base
- source_root File.expand_path('./install', __dir__)
- class_option :front_end, type: :string, default: 'react'
-
- FRONT_END_INSTALLERS = [
- 'react',
- 'vue',
- 'svelte',
- ]
-
- def install
- exit! unless installable?
-
- install_base!
-
- send "install_#{options[:front_end]}!"
-
- say "You're all set! Run rails s and checkout localhost:3000/inertia-example", :green
- end
-
- protected
-
- def installable?
- unless run("./bin/rails webpacker:verify_install")
- say "Sorry, you need to have webpacker installed for inertia_rails default setup.", :red
- return false
- end
-
- unless options[:front_end].in? FRONT_END_INSTALLERS
- say "Sorry, there is no generator for #{options[:front_end]}!\n\n", :red
- say "If you are a #{options[:front_end]} developer, please help us improve inertia_rails by contributing an installer.\n\n"
- say "https://github.com/inertiajs/inertia-rails/\n\n"
-
- return false
- end
-
- true
- end
-
- def install_base!
- say "Adding inertia pack tag to application layout", :blue
- insert_into_file Rails.root.join("app/views/layouts/application.html.erb").to_s, after: "<%= javascript_pack_tag 'application' %>\n" do
- "\t\t<%= javascript_pack_tag 'inertia' %>\n"
- end
-
- say "Installing inertia client packages", :blue
- run "yarn add @inertiajs/inertia @inertiajs/progress"
-
- say "Copying example files", :blue
- template "controller.rb", Rails.root.join("app/controllers/inertia_example_controller.rb").to_s
-
- say "Adding a route for the example inertia controller...", :blue
- route "get 'inertia-example', to: 'inertia_example#index'"
- end
-
- def install_react!
- say "Creating a React page component...", :blue
- run 'yarn add @inertiajs/inertia-react'
- template "react/InertiaExample.jsx", Rails.root.join("app/javascript/Pages/InertiaExample.js").to_s
- say "Copying inertia.jsx into webpacker's packs folder...", :blue
- template "react/inertia.jsx", Rails.root.join("app/javascript/packs/inertia.jsx").to_s
- say "done!", :green
- end
-
- def install_vue!
- say "Creating a Vue page component...", :blue
- run 'yarn add @inertiajs/inertia-vue'
- template "vue/InertiaExample.vue", Rails.root.join("app/javascript/Pages/InertiaExample.vue").to_s
- say "Copying inertia.js into webpacker's packs folder...", :blue
- template "vue/inertia.js", Rails.root.join("app/javascript/packs/inertia.js").to_s
- say "done!", :green
- end
-
- def install_svelte!
- say "Creating a Svelte page component...", :blue
- run 'yarn add @inertiajs/inertia-svelte'
- template "svelte/InertiaExample.svelte", Rails.root.join("app/javascript/Pages/InertiaExample.svelte").to_s
- say "Copying inertia.js into webpacker's packs folder...", :blue
- template "svelte/inertia.js", Rails.root.join("app/javascript/packs/inertia.js").to_s
- say "done!", :green
- end
- end
-end
diff --git a/lib/generators/inertia_templates/controller/controller_generator.rb b/lib/generators/inertia_templates/controller/controller_generator.rb
new file mode 100644
index 00000000..0b4608c6
--- /dev/null
+++ b/lib/generators/inertia_templates/controller/controller_generator.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+require 'inertia_rails/generators/controller_template_base'
+
+module InertiaTemplates
+ module Generators
+ class ControllerGenerator < InertiaRails::Generators::ControllerTemplateBase
+ hide!
+ source_root File.expand_path('./templates', __dir__)
+ end
+ end
+end
diff --git a/lib/generators/inertia_templates/controller/templates/react/view.jsx.tt b/lib/generators/inertia_templates/controller/templates/react/view.jsx.tt
new file mode 100644
index 00000000..799ea4c5
--- /dev/null
+++ b/lib/generators/inertia_templates/controller/templates/react/view.jsx.tt
@@ -0,0 +1,8 @@
+export default function <%= @action.camelize %>() {
+ return (
+ <>
+ <%= class_name %>#<%= @action %>
+ Find me in <%= @path %>
+ >
+ );
+}
diff --git a/lib/generators/inertia_templates/controller/templates/svelte/view.svelte.tt b/lib/generators/inertia_templates/controller/templates/svelte/view.svelte.tt
new file mode 100644
index 00000000..cd54d13d
--- /dev/null
+++ b/lib/generators/inertia_templates/controller/templates/svelte/view.svelte.tt
@@ -0,0 +1,2 @@
+<%= class_name %>#<%= @action %>
+Find me in <%= @path %>
diff --git a/lib/generators/inertia_templates/controller/templates/svelte4/view.svelte.tt b/lib/generators/inertia_templates/controller/templates/svelte4/view.svelte.tt
new file mode 100644
index 00000000..cd54d13d
--- /dev/null
+++ b/lib/generators/inertia_templates/controller/templates/svelte4/view.svelte.tt
@@ -0,0 +1,2 @@
+<%= class_name %>#<%= @action %>
+Find me in <%= @path %>
diff --git a/lib/generators/inertia_templates/controller/templates/vue/view.vue.tt b/lib/generators/inertia_templates/controller/templates/vue/view.vue.tt
new file mode 100644
index 00000000..14e2f96d
--- /dev/null
+++ b/lib/generators/inertia_templates/controller/templates/vue/view.vue.tt
@@ -0,0 +1,4 @@
+
+ <%= class_name %>#<%= @action %>
+ Find me in <%= @path %>
+
diff --git a/lib/generators/inertia_templates/scaffold/scaffold_generator.rb b/lib/generators/inertia_templates/scaffold/scaffold_generator.rb
new file mode 100644
index 00000000..b7674f0f
--- /dev/null
+++ b/lib/generators/inertia_templates/scaffold/scaffold_generator.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+require 'inertia_rails/generators/scaffold_template_base'
+
+module InertiaTemplates
+ module Generators
+ class ScaffoldGenerator < InertiaRails::Generators::ScaffoldTemplateBase
+ hide!
+ source_root File.expand_path('./templates', __dir__)
+ end
+ end
+end
diff --git a/lib/generators/inertia_templates/scaffold/templates/react/Edit.jsx.tt b/lib/generators/inertia_templates/scaffold/templates/react/Edit.jsx.tt
new file mode 100644
index 00000000..faf0c3b5
--- /dev/null
+++ b/lib/generators/inertia_templates/scaffold/templates/react/Edit.jsx.tt
@@ -0,0 +1,35 @@
+import { Link, Head } from '@inertiajs/react'
+import Form from './Form'
+
+export default function Edit({ <%= singular_table_name %> }) {
+ return (
+ <>
+
+
+ Editing <%= human_name.downcase %>
+
+
+ )
+}
diff --git a/lib/generators/inertia_templates/scaffold/templates/react/Index.jsx.tt b/lib/generators/inertia_templates/scaffold/templates/react/Index.jsx.tt
new file mode 100644
index 00000000..924961b8
--- /dev/null
+++ b/lib/generators/inertia_templates/scaffold/templates/react/Index.jsx.tt
@@ -0,0 +1,26 @@
+import { Link, Head } from '@inertiajs/react'
+import <%= inertia_component_name %> from './<%= inertia_component_name %>'
+
+export default function Index({ <%= plural_table_name %>, flash }) {
+ return (
+ <>
+
+
+ {flash.notice && {flash.notice}
}
+
+ <%= human_name.pluralize %>
+
+ {<%= plural_table_name %>.map((<%= singular_table_name %>) => (
+
.id}>
+ <<%= inertia_component_name %> <%= singular_table_name %>={<%= singular_table_name %>} />
+
+ `}>Show this <%= human_name.downcase %>
+
+
+ ))}
+
+
+ New <%= human_name.downcase %>
+ >
+ )
+}
diff --git a/lib/generators/inertia_templates/scaffold/templates/react/New.jsx.tt b/lib/generators/inertia_templates/scaffold/templates/react/New.jsx.tt
new file mode 100644
index 00000000..10c7e01e
--- /dev/null
+++ b/lib/generators/inertia_templates/scaffold/templates/react/New.jsx.tt
@@ -0,0 +1,27 @@
+import { Link, Head } from '@inertiajs/react'
+import Form from './Form'
+
+export default function New({ <%= singular_table_name %> }) {
+ return (
+ <>
+
+
+ New <%= human_name.downcase %>
+
+
+
+
diff --git a/lib/generators/inertia_templates/scaffold/templates/svelte/Index.svelte.tt b/lib/generators/inertia_templates/scaffold/templates/svelte/Index.svelte.tt
new file mode 100644
index 00000000..e8a7e7dd
--- /dev/null
+++ b/lib/generators/inertia_templates/scaffold/templates/svelte/Index.svelte.tt
@@ -0,0 +1,35 @@
+
+
+
+ <%= human_name.pluralize %>
+
+
+{#if flash.notice}
+ {flash.notice}
+{/if}
+
+<%= human_name.pluralize %>
+
+
+ {#each <%= plural_table_name %> as <%= singular_table_name %> (<%= singular_table_name %>.id)}
+
+ <<%= inertia_component_name %> {<%= singular_table_name %>} />
+
+ `}>Show this <%= human_name.downcase %>
+
+
+ {/each}
+
+
+New <%= human_name.downcase %>
+
+
diff --git a/lib/generators/inertia_templates/scaffold/templates/svelte/New.svelte.tt b/lib/generators/inertia_templates/scaffold/templates/svelte/New.svelte.tt
new file mode 100644
index 00000000..d46b4656
--- /dev/null
+++ b/lib/generators/inertia_templates/scaffold/templates/svelte/New.svelte.tt
@@ -0,0 +1,29 @@
+
+
+
+ New <%= human_name.downcase %>
+
+
+New <%= human_name.downcase %>
+
+
+
+
diff --git a/lib/generators/inertia_templates/scaffold/templates/svelte4/Index.svelte.tt b/lib/generators/inertia_templates/scaffold/templates/svelte4/Index.svelte.tt
new file mode 100644
index 00000000..7164c7b7
--- /dev/null
+++ b/lib/generators/inertia_templates/scaffold/templates/svelte4/Index.svelte.tt
@@ -0,0 +1,36 @@
+
+
+
+ <%= human_name.pluralize %>
+
+
+{#if flash.notice}
+ {flash.notice}
+{/if}
+
+<%= human_name.pluralize %>
+
+
+ {#each <%= plural_table_name %> as <%= singular_table_name %> (<%= singular_table_name %>.id)}
+
+ <<%= inertia_component_name %> {<%= singular_table_name %>} />
+
+ `}>Show this <%= human_name.downcase %>
+
+
+ {/each}
+
+
+New <%= human_name.downcase %>
+
+
diff --git a/lib/generators/inertia_templates/scaffold/templates/svelte4/New.svelte.tt b/lib/generators/inertia_templates/scaffold/templates/svelte4/New.svelte.tt
new file mode 100644
index 00000000..6238cd2d
--- /dev/null
+++ b/lib/generators/inertia_templates/scaffold/templates/svelte4/New.svelte.tt
@@ -0,0 +1,30 @@
+
+
+
+ New <%= human_name.downcase %>
+
+
+New <%= human_name.downcase %>
+
+="<%= singular_table_name %>"
+ submitText="Create <%= human_name.downcase %>"
+ @onSubmit="handleSubmit"
+ />
+
+
+
+
+ Back to <%= human_name.pluralize.downcase %>
+
+
+
+
diff --git a/lib/generators/inertia_templates/scaffold/templates/vue/One.vue.tt b/lib/generators/inertia_templates/scaffold/templates/vue/One.vue.tt
new file mode 100644
index 00000000..a122467a
--- /dev/null
+++ b/lib/generators/inertia_templates/scaffold/templates/vue/One.vue.tt
@@ -0,0 +1,26 @@
+
+
+
+
+
diff --git a/lib/generators/inertia_templates/scaffold/templates/vue/Show.vue.tt b/lib/generators/inertia_templates/scaffold/templates/vue/Show.vue.tt
new file mode 100644
index 00000000..095a1067
--- /dev/null
+++ b/lib/generators/inertia_templates/scaffold/templates/vue/Show.vue.tt
@@ -0,0 +1,44 @@
+
+
+
+ {{ flash.notice }}
+
+ <%= human_name %> #{{ <%= singular_table_name %>.id }}
+
+ <<%= inertia_component_name %> :<%= singular_table_name %>="<%= singular_table_name %>" />
+
+
+ Edit this <%= human_name.downcase %> |
+ Back to <%= human_name.pluralize.downcase %>
+
+
+
+
+ Destroy this <%= human_name.downcase %>
+
+
+
+
+
+
+
diff --git a/lib/generators/inertia_tw_templates/controller/controller_generator.rb b/lib/generators/inertia_tw_templates/controller/controller_generator.rb
new file mode 100644
index 00000000..eb651ac9
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/controller/controller_generator.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+require 'inertia_rails/generators/controller_template_base'
+
+module InertiaTwTemplates
+ module Generators
+ class ControllerGenerator < InertiaRails::Generators::ControllerTemplateBase
+ hide!
+ source_root File.expand_path('./templates', __dir__)
+ end
+ end
+end
diff --git a/lib/generators/inertia_tw_templates/controller/templates/react/view.jsx.tt b/lib/generators/inertia_tw_templates/controller/templates/react/view.jsx.tt
new file mode 100644
index 00000000..7f9d97b3
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/controller/templates/react/view.jsx.tt
@@ -0,0 +1,8 @@
+export default function <%= @action.camelize %>() {
+ return (
+ <>
+ <%= class_name %>#<%= @action %>
+ Find me in <%= @path %>
+ >
+ );
+}
diff --git a/lib/generators/inertia_tw_templates/controller/templates/svelte/view.svelte.tt b/lib/generators/inertia_tw_templates/controller/templates/svelte/view.svelte.tt
new file mode 100644
index 00000000..764fff82
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/controller/templates/svelte/view.svelte.tt
@@ -0,0 +1,2 @@
+<%= class_name %>#<%= @action %>
+Find me in <%= @path %>
diff --git a/lib/generators/inertia_tw_templates/controller/templates/svelte4/view.svelte.tt b/lib/generators/inertia_tw_templates/controller/templates/svelte4/view.svelte.tt
new file mode 100644
index 00000000..764fff82
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/controller/templates/svelte4/view.svelte.tt
@@ -0,0 +1,2 @@
+<%= class_name %>#<%= @action %>
+Find me in <%= @path %>
diff --git a/lib/generators/inertia_tw_templates/controller/templates/vue/view.vue.tt b/lib/generators/inertia_tw_templates/controller/templates/vue/view.vue.tt
new file mode 100644
index 00000000..4f2d55a8
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/controller/templates/vue/view.vue.tt
@@ -0,0 +1,4 @@
+
+ <%= class_name %>#<%= @action %>
+ Find me in <%= @path %>
+
diff --git a/lib/generators/inertia_tw_templates/scaffold/scaffold_generator.rb b/lib/generators/inertia_tw_templates/scaffold/scaffold_generator.rb
new file mode 100644
index 00000000..114044c7
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/scaffold_generator.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+require 'inertia_rails/generators/scaffold_template_base'
+
+module InertiaTwTemplates
+ module Generators
+ class ScaffoldGenerator < InertiaRails::Generators::ScaffoldTemplateBase
+ hide!
+ source_root File.expand_path('./templates', __dir__)
+ end
+ end
+end
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/react/Edit.jsx.tt b/lib/generators/inertia_tw_templates/scaffold/templates/react/Edit.jsx.tt
new file mode 100644
index 00000000..8635dc73
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/react/Edit.jsx.tt
@@ -0,0 +1,42 @@
+import { Link, Head } from '@inertiajs/react'
+import Form from './Form'
+
+export default function Edit({ <%= singular_table_name %> }) {
+ return (
+ <>
+
+
+
+
Editing <%= human_name.downcase %>
+
+ ={<%= singular_table_name %>}
+ onSubmit={(form) => {
+ form.transform((data) => ({ <%= singular_table_name %>: data }))
+<% if attributes.any?(&:attachments?) -%>
+ form.post(`<%= js_resource_path %>`, {
+ headers: { 'X-HTTP-METHOD-OVERRIDE': 'put' },
+ })
+<% else -%>
+ form.patch(`<%= js_resource_path %>`)
+<% end -%>
+ }}
+ submitText="Update <%= human_name.downcase %>"
+ />
+
+ `}
+ className="ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium"
+ >
+ Show this <%= human_name.downcase %>
+
+
+ Back to <%= human_name.pluralize.downcase %>
+
+
+ >
+ )
+}
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/react/Form.jsx.tt b/lib/generators/inertia_tw_templates/scaffold/templates/react/Form.jsx.tt
new file mode 100644
index 00000000..3b222b10
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/react/Form.jsx.tt
@@ -0,0 +1,122 @@
+import { useForm } from '@inertiajs/react'
+
+export default function Form({ <%= singular_table_name %>, onSubmit, submitText }) {
+ const form = useForm({
+<% attributes.each do |attribute| -%>
+<% if attribute.password_digest? -%>
+ password: '',
+ password_confirmation: '',
+<% else -%>
+ <%= attribute.column_name %>: <%= singular_table_name %>.<%= attribute.column_name %> || <%= default_value(attribute) %>,
+<% end -%>
+<% end -%>
+ })
+ const { data, setData, errors, processing } = form
+
+ const handleSubmit = (e) => {
+ e.preventDefault()
+ onSubmit(form)
+ }
+
+ return (
+
+<% attributes.each do |attribute| -%>
+
+<% if attribute.password_digest? -%>
+
+
setData('password', e.target.value)}
+ />
+ {errors.password && (
+
+ {errors.password.join(', ')}
+
+ )}
+
+
+
+
+<% end -%>
+
+
+
+
+ )
+}
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/react/Index.jsx.tt b/lib/generators/inertia_tw_templates/scaffold/templates/react/Index.jsx.tt
new file mode 100644
index 00000000..e0618247
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/react/Index.jsx.tt
@@ -0,0 +1,43 @@
+import { Link, Head } from '@inertiajs/react'
+import { Fragment } from 'react'
+import <%= inertia_component_name %> from './<%= inertia_component_name %>'
+
+export default function Index({ <%= plural_table_name %>, flash }) {
+ return (
+ <>
+
+
+ {flash.notice && (
+
+ {flash.notice}
+
+ )}
+
+
<%= human_name.pluralize %>
+
+ New <%= human_name.downcase %>
+
+
+
+
+ {<%= plural_table_name %>.map((<%= singular_table_name %>) => (
+
.id}>
+ <<%= inertia_component_name %> <%= singular_table_name %>={<%= singular_table_name %>} />
+
+ `}
+ className="ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium"
+ >
+ Show this <%= human_name.downcase %>
+
+
+
+ ))}
+
+
+ >
+ )
+}
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/react/New.jsx.tt b/lib/generators/inertia_tw_templates/scaffold/templates/react/New.jsx.tt
new file mode 100644
index 00000000..1a100490
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/react/New.jsx.tt
@@ -0,0 +1,30 @@
+import { Link, Head } from '@inertiajs/react'
+import Form from './Form'
+
+export default function New({ <%= singular_table_name %> }) {
+ return (
+ <>
+
+
+
+
New <%= human_name.downcase %>
+
+ ={<%= singular_table_name %>}
+ onSubmit={(form) => {
+ form.transform((data) => ({ <%= singular_table_name %>: data }))
+ form.post('<%= js_resources_path %>')
+ }}
+ submitText="Create <%= human_name.downcase %>"
+ />
+
+
+ Back to <%= human_name.pluralize.downcase %>
+
+
+ >
+ )
+}
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/react/One.jsx.tt b/lib/generators/inertia_tw_templates/scaffold/templates/react/One.jsx.tt
new file mode 100644
index 00000000..4d40a7ec
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/react/One.jsx.tt
@@ -0,0 +1,26 @@
+export default function <%= inertia_component_name %>({ <%= singular_table_name %> }) {
+ return (
+
+<% attributes.reject(&:password_digest?).each do |attribute| -%>
+
+ <%= attribute.human_name %>:
+<% if attribute.attachment? -%>
+ {<%= singular_table_name %>.<%= attribute.column_name %> && (
+ .<%= attribute.column_name %>.url}>{<%= singular_table_name %>.<%= attribute.column_name %>.filename}
+ )}
+
+<% elsif attribute.attachments? -%>
+
+ {<%= singular_table_name %>.<%= attribute.column_name %>.map((file, i) => (
+
+ ))}
+<% else -%>
+ {<%= singular_table_name %>.<%= attribute.column_name %>?.toString()}
+
+<% end -%>
+<% end -%>
+
+ )
+}
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/react/Show.jsx.tt b/lib/generators/inertia_tw_templates/scaffold/templates/react/Show.jsx.tt
new file mode 100644
index 00000000..2bad94e9
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/react/Show.jsx.tt
@@ -0,0 +1,54 @@
+import { Link, Head } from '@inertiajs/react'
+import <%= inertia_component_name %> from './<%= inertia_component_name %>'
+
+export default function Show({ <%= singular_table_name %>, flash }) {
+ const onDestroy = (e) => {
+ if (!confirm('Are you sure you want to delete this <%= human_name.downcase %>?')) {
+ e.preventDefault()
+ }
+ }
+
+ return (
+ <>
+ #${<%= singular_table_name %>.id}`} />
+
+
+
+ {flash.notice && (
+
+ {flash.notice}
+
+ )}
+
+
<%= human_name %> #{<%= singular_table_name %>.id}
+
+ <<%= inertia_component_name %> <%= singular_table_name %>={<%= singular_table_name %>} />
+
+
`}
+ className="mt-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium"
+ >
+ Edit this <%= human_name.downcase %>
+
+
+ Back to <%= human_name.pluralize.downcase %>
+
+
+ `}
+ onClick={onDestroy}
+ as="button"
+ method="delete"
+ className="mt-2 rounded-lg py-3 px-5 bg-gray-100 font-medium"
+ >
+ Destroy this <%= human_name.downcase %>
+
+
+
+
+ >
+ )
+}
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/svelte/Edit.svelte.tt b/lib/generators/inertia_tw_templates/scaffold/templates/svelte/Edit.svelte.tt
new file mode 100644
index 00000000..18192e5c
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/svelte/Edit.svelte.tt
@@ -0,0 +1,44 @@
+
+
+
+ Editing <%= human_name.downcase %>
+
+
+
+
Editing <%= human_name.downcase %>
+
+ }
+ submitText="Update <%= human_name.downcase %>"
+ onSubmit={handleSubmit}
+ />
+
+ `}
+ class="mt-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium"
+ >
+ Show this <%= human_name.downcase %>
+
+
+ Back to <%= human_name.pluralize.downcase %>
+
+
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/svelte/Form.svelte.tt b/lib/generators/inertia_tw_templates/scaffold/templates/svelte/Form.svelte.tt
new file mode 100644
index 00000000..7059e11a
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/svelte/Form.svelte.tt
@@ -0,0 +1,119 @@
+
+
+
+<% attributes.each do |attribute| -%>
+
+<% if attribute.password_digest? -%>
+
+
+ {#if $form.errors.password}
+
+ {$form.errors.password.join(', ')}
+
+ {/if}
+
+
+
+
+<% end -%>
+
+
+
+
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/svelte/Index.svelte.tt b/lib/generators/inertia_tw_templates/scaffold/templates/svelte/Index.svelte.tt
new file mode 100644
index 00000000..2be8bfa1
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/svelte/Index.svelte.tt
@@ -0,0 +1,42 @@
+
+
+
+ <%= human_name.pluralize %>
+
+
+
+ {#if flash.notice}
+
+ {flash.notice}
+
+ {/if}
+
+
+
<%= human_name.pluralize %>
+
+ New <%= human_name.downcase %>
+
+
+
+
+ {#each <%= plural_table_name %> as <%= singular_table_name %> (<%= singular_table_name %>.id)}
+ <<%= inertia_component_name %> {<%= singular_table_name %>} />
+
+ `}
+ class="ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium"
+ >
+ Show this <%= human_name.downcase %>
+
+
+ {/each}
+
+
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/svelte/New.svelte.tt b/lib/generators/inertia_tw_templates/scaffold/templates/svelte/New.svelte.tt
new file mode 100644
index 00000000..d92a6f64
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/svelte/New.svelte.tt
@@ -0,0 +1,32 @@
+
+
+
+ New <%= human_name.downcase %>
+
+
+
+
New <%= human_name.downcase %>
+
+ }
+ submitText="Create <%= human_name.downcase %>"
+ onSubmit={handleSubmit}
+ />
+
+
+ Back to <%= human_name.pluralize.downcase %>
+
+
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/svelte/One.svelte.tt b/lib/generators/inertia_tw_templates/scaffold/templates/svelte/One.svelte.tt
new file mode 100644
index 00000000..1d4697f9
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/svelte/One.svelte.tt
@@ -0,0 +1,28 @@
+
+
+
+<% attributes.reject(&:password_digest?).each do |attribute| -%>
+
+ <%= attribute.human_name %>:
+<% if attribute.attachment? -%>
+ {#if <%= singular_table_name %>.<%= attribute.column_name %>}
+ .<%= attribute.column_name %>.url}>
+ {<%= singular_table_name %>.<%= attribute.column_name %>.filename}
+
+ {/if}
+
+<% elsif attribute.attachments? -%>
+
+ {#each <%= singular_table_name %>.<%= attribute.column_name %> as { url, filename }}
+
+ {/each}
+<% else -%>
+ {<%= singular_table_name %>.<%= attribute.column_name %>}
+
+<% end -%>
+<% end -%>
+
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/svelte/Show.svelte.tt b/lib/generators/inertia_tw_templates/scaffold/templates/svelte/Show.svelte.tt
new file mode 100644
index 00000000..c5c63804
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/svelte/Show.svelte.tt
@@ -0,0 +1,57 @@
+
+
+
+ <%= human_name %> #{<%= singular_table_name %>.id}
+
+
+
+
+ {#if flash.notice}
+
+ {flash.notice}
+
+ {/if}
+
+
<%= human_name %> #{<%= singular_table_name %>.id}
+
+ <<%= inertia_component_name %> {<%= singular_table_name %>} />
+
+
`}
+ class="ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium"
+ >
+ Edit this <%= human_name.downcase %>
+
+
+ Back to <%= human_name.pluralize.downcase %>
+
+
+ `}
+ method="delete"
+ onclick={onDestroy}
+ class="mt-2 rounded-lg py-3 px-5 bg-gray-100 font-medium"
+ >
+ Destroy this <%= human_name.downcase %>
+
+
+
+
+
+
+
+
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/Edit.svelte.tt b/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/Edit.svelte.tt
new file mode 100644
index 00000000..13728cfe
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/Edit.svelte.tt
@@ -0,0 +1,45 @@
+
+
+
+ Editing <%= human_name.downcase %>
+
+
+
+
Editing <%= human_name.downcase %>
+
+ }
+ submitText="Update <%= human_name.downcase %>"
+ on:submit={handleSubmit}
+ />
+
+ `}
+ class="mt-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium"
+ >
+ Show this <%= human_name.downcase %>
+
+
+ Back to <%= human_name.pluralize.downcase %>
+
+
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/Form.svelte.tt b/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/Form.svelte.tt
new file mode 100644
index 00000000..0bd8d596
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/Form.svelte.tt
@@ -0,0 +1,120 @@
+
+
+
+<% attributes.each do |attribute| -%>
+
+<% if attribute.password_digest? -%>
+
+
+ {#if $form.errors.password}
+
+ {$form.errors.password.join(', ')}
+
+ {/if}
+
+
+
+
+<% end -%>
+
+
+
+
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/Index.svelte.tt b/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/Index.svelte.tt
new file mode 100644
index 00000000..97001962
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/Index.svelte.tt
@@ -0,0 +1,43 @@
+
+
+
+ <%= human_name.pluralize %>
+
+
+
+ {#if flash.notice}
+
+ {flash.notice}
+
+ {/if}
+
+
+
<%= human_name.pluralize %>
+
+ New <%= human_name.downcase %>
+
+
+
+
+ {#each <%= plural_table_name %> as <%= singular_table_name %> (<%= singular_table_name %>.id)}
+ <<%= inertia_component_name %> {<%= singular_table_name %>} />
+
+ `}
+ class="ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium"
+ >
+ Show this <%= human_name.downcase %>
+
+
+ {/each}
+
+
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/New.svelte.tt b/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/New.svelte.tt
new file mode 100644
index 00000000..dc3b0a16
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/New.svelte.tt
@@ -0,0 +1,33 @@
+
+
+
+ New <%= human_name.downcase %>
+
+
+
+
New <%= human_name.downcase %>
+
+ }
+ submitText="Create <%= human_name.downcase %>"
+ on:submit={handleSubmit}
+ />
+
+
+ Back to <%= human_name.pluralize.downcase %>
+
+
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/One.svelte.tt b/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/One.svelte.tt
new file mode 100644
index 00000000..42c56dbb
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/One.svelte.tt
@@ -0,0 +1,28 @@
+
+
+
+<% attributes.reject(&:password_digest?).each do |attribute| -%>
+
+ <%= attribute.human_name %>:
+<% if attribute.attachment? -%>
+ {#if <%= singular_table_name %>.<%= attribute.column_name %>}
+ .<%= attribute.column_name %>.url}>
+ {<%= singular_table_name %>.<%= attribute.column_name %>.filename}
+
+ {/if}
+
+<% elsif attribute.attachments? -%>
+
+ {#each <%= singular_table_name %>.<%= attribute.column_name %> as { url, filename }}
+
+ {/each}
+<% else -%>
+ {<%= singular_table_name %>.<%= attribute.column_name %>}
+
+<% end -%>
+<% end -%>
+
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/Show.svelte.tt b/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/Show.svelte.tt
new file mode 100644
index 00000000..4ceafd1b
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/Show.svelte.tt
@@ -0,0 +1,58 @@
+
+
+
+ <%= human_name %> #{<%= singular_table_name %>.id}
+
+
+
+
+ {#if flash.notice}
+
+ {flash.notice}
+
+ {/if}
+
+
<%= human_name %> #{<%= singular_table_name %>.id}
+
+ <<%= inertia_component_name %> {<%= singular_table_name %>} />
+
+
`}
+ class="ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium"
+ >
+ Edit this <%= human_name.downcase %>
+
+
+ Back to <%= human_name.pluralize.downcase %>
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/vue/Edit.vue.tt b/lib/generators/inertia_tw_templates/scaffold/templates/vue/Edit.vue.tt
new file mode 100644
index 00000000..4657e860
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/vue/Edit.vue.tt
@@ -0,0 +1,44 @@
+
+
+
+
+
Editing <%= human_name.downcase %>
+
+ ="<%= singular_table_name %>"
+ submitText="Update <%= human_name.downcase %>"
+ @onSubmit="handleSubmit"
+ />
+
+
+ Show this <%= human_name.downcase %>
+
+
+ Back to <%= human_name.pluralize.downcase %>
+
+
+
+
+
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/vue/Form.vue.tt b/lib/generators/inertia_tw_templates/scaffold/templates/vue/Form.vue.tt
new file mode 100644
index 00000000..0640f8a4
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/vue/Form.vue.tt
@@ -0,0 +1,127 @@
+
+
+<% attributes.each do |attribute| -%>
+<% if attribute.password_digest? -%>
+
+
+
+
+ {{ form.errors.password.join(', ') }}
+
+
+
+
+
+
+
+ {{ form.errors.password_confirmation.join(', ') }}
+
+
+<% else -%>
+
+<% end -%>
+
+<% end -%>
+
+
+
+
+
+
+
+
+
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/vue/Index.vue.tt b/lib/generators/inertia_tw_templates/scaffold/templates/vue/Index.vue.tt
new file mode 100644
index 00000000..ae3ad1cf
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/vue/Index.vue.tt
@@ -0,0 +1,43 @@
+
+
+
+
+
+ {{ flash.notice }}
+
+
+
+
<%= human_name.pluralize %>
+
+ New <%= human_name.downcase %>
+
+
+
+
+
+ <<%= inertia_component_name %> :<%= singular_table_name %>="<%= singular_table_name %>" />
+
+
+ Show this <%= human_name.downcase %>
+
+
+
+
+
+
+
+
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/vue/New.vue.tt b/lib/generators/inertia_tw_templates/scaffold/templates/vue/New.vue.tt
new file mode 100644
index 00000000..025d7c88
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/vue/New.vue.tt
@@ -0,0 +1,32 @@
+
+
+
+
+
New <%= human_name.downcase %>
+
+ ="<%= singular_table_name %>"
+ submitText="Create <%= human_name.downcase %>"
+ @onSubmit="handleSubmit"
+ />
+
+
+ Back to <%= human_name.pluralize.downcase %>
+
+
+
+
+
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/vue/One.vue.tt b/lib/generators/inertia_tw_templates/scaffold/templates/vue/One.vue.tt
new file mode 100644
index 00000000..7a150e12
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/vue/One.vue.tt
@@ -0,0 +1,26 @@
+
+
+
+
+
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/vue/Show.vue.tt b/lib/generators/inertia_tw_templates/scaffold/templates/vue/Show.vue.tt
new file mode 100644
index 00000000..eedc10be
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/vue/Show.vue.tt
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+ {{ flash.notice }}
+
+
+
<%= human_name %> #{{ <%= singular_table_name %>.id }}
+
+ <<%= inertia_component_name %> :<%= singular_table_name %>="<%= singular_table_name %>" />
+
+
+ Edit this <%= human_name.downcase %>
+
+
+ Back to <%= human_name.pluralize.downcase %>
+
+
+
+
+ Destroy this <%= human_name.downcase %>
+
+
+
+
+
+
+
diff --git a/lib/inertia_rails/configuration.rb b/lib/inertia_rails/configuration.rb
index 02f73f05..870adbfc 100644
--- a/lib/inertia_rails/configuration.rb
+++ b/lib/inertia_rails/configuration.rb
@@ -63,7 +63,7 @@ def with_defaults(config)
end
def component_path_resolver(path:, action:)
- @options[:component_path_resolver].call(path:, action:)
+ @options[:component_path_resolver].call(path: path, action: action)
end
OPTION_NAMES.each do |option|
diff --git a/lib/inertia_rails/generators/controller_template_base.rb b/lib/inertia_rails/generators/controller_template_base.rb
new file mode 100644
index 00000000..7232aa47
--- /dev/null
+++ b/lib/inertia_rails/generators/controller_template_base.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+require 'rails/generators/named_base'
+require 'inertia_rails/generators/helper'
+
+module InertiaRails
+ module Generators
+ class ControllerTemplateBase < Rails::Generators::NamedBase
+ include Helper
+ class_option :frontend_framework, required: true, desc: 'Frontend framework to generate the views for.',
+ default: Helper.guess_the_default_framework
+
+ argument :actions, type: :array, default: [], banner: 'action action'
+
+ def empty_views_dir
+ empty_directory base_path
+ end
+
+ def copy_view_files
+ actions.each do |action|
+ @action = action
+ @path = File.join(base_path, "#{action.camelize}.#{extension}")
+ template "#{options.frontend_framework}/#{template_filename}.#{extension}", @path
+ end
+ end
+
+ private
+
+ def base_path
+ File.join(pages_path, inertia_base_path)
+ end
+
+ def template_filename
+ 'view'
+ end
+
+ def pages_path
+ "#{root_path}/pages"
+ end
+
+ def root_path
+ (defined?(ViteRuby) ? ViteRuby.config.source_code_dir : 'app/frontend')
+ end
+
+ def extension
+ case options.frontend_framework
+ when 'react' then 'jsx'
+ when 'vue' then 'vue'
+ when 'svelte' then 'svelte'
+ else
+ raise ArgumentError, "Unknown frontend framework: #{options.frontend_framework}"
+ end
+ end
+ end
+ end
+end
diff --git a/lib/inertia_rails/generators/helper.rb b/lib/inertia_rails/generators/helper.rb
new file mode 100644
index 00000000..e7474bf9
--- /dev/null
+++ b/lib/inertia_rails/generators/helper.rb
@@ -0,0 +1,89 @@
+# frozen_string_literal: true
+
+module InertiaRails
+ module Generators
+ module Helper
+ def self.guess_the_default_framework
+ package = Rails.root.join('package.json').read
+ case package
+ when %r{@inertiajs/react}
+ 'react'
+ when %r{@inertiajs/svelte}
+ package.match?(/"svelte": "\^5/) ? 'svelte' : 'svelte4'
+ when %r{@inertiajs/vue3}
+ 'vue'
+ else
+ Thor::Shell::Basic.new.say_error 'Could not determine the Inertia.js framework you are using.'
+ end
+ end
+
+ def self.guess_inertia_template
+ if Rails.root.join('tailwind.config.js').exist? || Rails.root.join('tailwind.config.ts').exist?
+ 'inertia_tw_templates'
+ else
+ 'inertia_templates'
+ end
+ end
+
+ def inertia_base_path
+ (class_path + [file_name]).map(&:camelize).join('/')
+ end
+
+ def inertia_component_name
+ singular_name.camelize
+ end
+
+ def attributes_to_serialize
+ [:id] + attributes.reject do |attribute|
+ attribute.password_digest? ||
+ attribute.attachment? ||
+ attribute.attachments?
+ end.map(&:column_name)
+ end
+
+ def js_resource_path
+ "#{route_url}/${#{singular_table_name}.id}"
+ end
+
+ def js_edit_resource_path
+ "#{route_url}/${#{singular_table_name}.id}/edit"
+ end
+
+ def js_new_resource_path
+ "#{route_url}/new"
+ end
+
+ def js_resources_path
+ route_url
+ end
+
+ def input_type(attribute)
+ case attribute.type
+ when :text, :rich_text
+ 'text_area'
+ when :integer, :float, :decimal
+ 'number'
+ when :datetime, :timestamp, :time
+ 'datetime-local'
+ when :date
+ 'date'
+ when :boolean
+ 'checkbox'
+ when :attachments, :attachment
+ 'file'
+ else
+ 'text'
+ end
+ end
+
+ def default_value(attribute)
+ case attribute.type
+ when :boolean
+ 'false'
+ else
+ "''"
+ end
+ end
+ end
+ end
+end
diff --git a/lib/inertia_rails/generators/scaffold_template_base.rb b/lib/inertia_rails/generators/scaffold_template_base.rb
new file mode 100644
index 00000000..a96c42f3
--- /dev/null
+++ b/lib/inertia_rails/generators/scaffold_template_base.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'rails/generators/resource_helpers'
+require_relative 'controller_template_base'
+
+module InertiaRails
+ module Generators
+ class ScaffoldTemplateBase < ControllerTemplateBase
+ include Rails::Generators::ResourceHelpers
+
+ remove_argument :actions
+
+ argument :attributes, type: :array, default: [], banner: 'field:type field:type'
+
+ def copy_view_files
+ available_views.each do |view|
+ filename = "#{view}.#{extension}"
+ template "#{options.frontend_framework}/#{filename}", File.join(base_path, filename)
+ end
+
+ template "#{options.frontend_framework}/#{partial_name}.#{extension}",
+ File.join(base_path, "#{inertia_component_name}.#{extension}")
+ end
+
+ private
+
+ def available_views
+ %w[Index Edit Show New Form]
+ end
+
+ def partial_name
+ 'One'
+ end
+ end
+ end
+end
diff --git a/spec/fixtures/install_generator/dummy/Gemfile b/spec/fixtures/install_generator/dummy/Gemfile
new file mode 100644
index 00000000..ebc45888
--- /dev/null
+++ b/spec/fixtures/install_generator/dummy/Gemfile
@@ -0,0 +1,3 @@
+# frozen_string_literal: true
+
+source 'https://rubygems.org'
diff --git a/spec/fixtures/install_generator/dummy/app/views/layouts/application.html.erb b/spec/fixtures/install_generator/dummy/app/views/layouts/application.html.erb
new file mode 100644
index 00000000..57ae714d
--- /dev/null
+++ b/spec/fixtures/install_generator/dummy/app/views/layouts/application.html.erb
@@ -0,0 +1,13 @@
+
+
+
+ TestContrib
+
+ <%= csrf_meta_tags %>
+ <%= csp_meta_tag %>
+
+
+
+<%= yield %>
+
+
diff --git a/spec/fixtures/install_generator/dummy/config/routes.rb b/spec/fixtures/install_generator/dummy/config/routes.rb
new file mode 100644
index 00000000..28a4baed
--- /dev/null
+++ b/spec/fixtures/install_generator/dummy/config/routes.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+Rails.application.routes.draw do
+ # root to: 'home#index'
+end
diff --git a/spec/fixtures/install_generator/with_vite/app/views/layouts/application.html.erb b/spec/fixtures/install_generator/with_vite/app/views/layouts/application.html.erb
new file mode 100644
index 00000000..5dc926b7
--- /dev/null
+++ b/spec/fixtures/install_generator/with_vite/app/views/layouts/application.html.erb
@@ -0,0 +1,16 @@
+
+
+
+ TestContrib
+
+ <%= csrf_meta_tags %>
+ <%= csp_meta_tag %>
+
+ <%= vite_client_tag %>
+ <%= vite_javascript_tag 'application' %>
+
+
+
+<%= yield %>
+
+
diff --git a/spec/fixtures/install_generator/with_vite/config/vite.json b/spec/fixtures/install_generator/with_vite/config/vite.json
new file mode 100644
index 00000000..0967ef42
--- /dev/null
+++ b/spec/fixtures/install_generator/with_vite/config/vite.json
@@ -0,0 +1 @@
+{}
diff --git a/spec/fixtures/install_generator/with_vite/package.json b/spec/fixtures/install_generator/with_vite/package.json
new file mode 100644
index 00000000..0967ef42
--- /dev/null
+++ b/spec/fixtures/install_generator/with_vite/package.json
@@ -0,0 +1 @@
+{}
diff --git a/spec/fixtures/install_generator/with_vite/vite.config.ts b/spec/fixtures/install_generator/with_vite/vite.config.ts
new file mode 100644
index 00000000..3129636e
--- /dev/null
+++ b/spec/fixtures/install_generator/with_vite/vite.config.ts
@@ -0,0 +1,8 @@
+import { defineConfig } from 'vite'
+import RubyPlugin from 'vite-plugin-ruby'
+
+export default defineConfig({
+ plugins: [
+ RubyPlugin(),
+ ],
+})
diff --git a/spec/generators/install/install_generator_spec.rb b/spec/generators/install/install_generator_spec.rb
new file mode 100644
index 00000000..35972db4
--- /dev/null
+++ b/spec/generators/install/install_generator_spec.rb
@@ -0,0 +1,314 @@
+# frozen_string_literal: true
+
+require_relative '../../../lib/generators/inertia/install/install_generator'
+require 'generator_spec'
+
+RSpec.describe Inertia::Generators::InstallGenerator, type: :generator do
+ destination File.expand_path('../../../tmp', __dir__)
+
+ let(:args) { %W[--framework=#{framework} --no-interactive -q] }
+ let(:framework) { :react }
+ let(:ext) { 'js' }
+
+ subject(:generator) { run_generator(args) }
+
+ shared_context 'assert framework structure' do
+ before { prepare_application }
+
+ it 'installs the Inertia adapter' do
+ expect { generator }.not_to raise_error
+
+ expect_example_page_for(framework, ext: ext)
+ expect_inertia_prepared_for(framework, ext: ext)
+ expect_packages_for(framework, ext: ext)
+ end
+ end
+
+ shared_context 'assert framework js and ts structures' do
+ include_context 'assert framework structure'
+
+ context 'with --typescript' do
+ let(:args) { super() + %w[--typescript] }
+ let(:ext) { 'ts' }
+
+ include_context 'assert framework structure'
+ end
+ end
+
+ context 'without vite' do
+ before do
+ prepare_application(with_vite: false)
+ end
+
+ it 'exits with an error' do
+ expect { generator }.to raise_error(SystemExit)
+ end
+
+ context 'with --install-vite' do
+ let(:args) { super() + %w[--install-vite] }
+
+ it 'installs Vite' do
+ expect { generator }.not_to raise_error
+ expect_example_page_for(:react)
+ expect_packages_for(:react)
+ expect(destination_root).to(have_structure do
+ directory('app/frontend') do
+ no_file('entrypoints/application.css')
+ end
+ no_file('postcss.config.js')
+ no_file('tailwind.config.js')
+ end)
+ end
+ end
+ end
+
+ context 'with --install-tailwind' do
+ let(:args) { super() + %w[--install-tailwind] }
+
+ before { prepare_application }
+
+ it 'installs Tailwind' do
+ expect { generator }.not_to raise_error
+ expect_tailwind_config
+ end
+ end
+
+ context 'with --framework=svelte' do
+ let(:framework) { :svelte }
+ include_context 'assert framework structure'
+
+ context 'with --typescript' do
+ let(:inertia_version) { '1.3.0-beta.1' }
+ let(:args) { super() + %W[--typescript --inertia-version=#{inertia_version}] }
+ let(:ext) { 'ts' }
+
+ include_context 'assert framework structure'
+
+ context 'with old Inertia version' do
+ let(:inertia_version) { '1.2.0' }
+ let(:ext) { 'js' }
+
+ include_context 'assert framework structure'
+ end
+ end
+ end
+
+ context 'with --framework=svelte4' do
+ let(:framework) { :svelte4 }
+ include_context 'assert framework structure'
+
+ context 'with --typescript' do
+ let(:inertia_version) { '1.3.0-beta.1' }
+ let(:args) { super() + %W[--typescript --inertia-version=#{inertia_version}] }
+ let(:ext) { 'ts' }
+
+ include_context 'assert framework structure'
+
+ context 'with old Inertia version' do
+ let(:inertia_version) { '1.2.0' }
+ let(:ext) { 'js' }
+
+ include_context 'assert framework structure'
+ end
+ end
+ end
+
+ context 'with --framework=vue' do
+ let(:framework) { :vue }
+
+ include_context 'assert framework js and ts structures'
+ end
+
+ context 'with --framework=react' do
+ let(:framework) { :react }
+
+ include_context 'assert framework js and ts structures'
+ end
+
+ def prepare_application(with_vite: true)
+ prepare_destination
+ FileUtils.cp_r(Dir['spec/fixtures/install_generator/dummy/*'], destination_root)
+ FileUtils.cp_r(Dir['spec/fixtures/install_generator/with_vite/*'], destination_root) if with_vite
+ end
+
+ def expect_tailwind_config
+ expect(destination_root).to(have_structure do
+ directory('app/frontend') do
+ file('entrypoints/application.css')
+ end
+ file('postcss.config.js')
+ file('tailwind.config.js')
+ end)
+ end
+
+ def expect_vite_config
+ expect(destination_root).to(have_structure do
+ directory('config') do
+ file('vite.json')
+ end
+ file('vite.config.js')
+ end)
+ end
+
+ def expect_packages_for(framework, ext: 'js')
+ expect(destination_root).to(have_structure do
+ file('package.json') do
+ case framework
+ when :react
+ contains('"@inertiajs/react":')
+ contains('"react":')
+ contains('"react-dom":')
+ contains('"@vitejs/plugin-react":')
+ if ext == 'ts'
+ contains('"@types/react":')
+ contains('"@types/react-dom":')
+ contains('"typescript":')
+ end
+ when :vue
+ contains('"@inertiajs/vue3":')
+ contains('"vue":')
+ contains('"@vitejs/plugin-vue":')
+ if ext == 'ts'
+ contains('"typescript":')
+ contains('"vue-tsc":')
+ end
+ when :svelte, :svelte4
+ contains('"@inertiajs/svelte":')
+ contains('"svelte":')
+ contains('"@sveltejs/vite-plugin-svelte":')
+ if ext == 'ts'
+ contains('"@tsconfig/svelte":')
+ contains('"svelte-check":')
+ contains('"typescript":')
+ contains('"tslib":')
+ end
+ end
+ end
+ end)
+ end
+
+ def expect_inertia_prepared_for(framework, ext: 'js')
+ expect(destination_root).to(have_structure do
+ case framework
+ when :react
+ file('vite.config.ts') do
+ contains('react()')
+ end
+ file("app/frontend/entrypoints/inertia.#{ext}") do
+ contains("import { createInertiaApp } from '@inertiajs/react'")
+ end
+ when :vue
+ file('vite.config.ts') do
+ contains('vue()')
+ end
+ file("app/frontend/entrypoints/inertia.#{ext}") do
+ contains("import { createInertiaApp } from '@inertiajs/vue3'")
+ end
+ when :svelte, :svelte4
+ file('svelte.config.js') do
+ contains('preprocess: vitePreprocess()')
+ end
+ file('vite.config.ts') do
+ contains('svelte()')
+ end
+ file("app/frontend/entrypoints/inertia.#{ext}") do
+ if ext == 'ts'
+ contains("import { createInertiaApp, type ResolvedComponent } from '@inertiajs/svelte'")
+ else
+ contains("import { createInertiaApp } from '@inertiajs/svelte'")
+ end
+ if framework == :svelte4
+ contains('new App({ target: el, props })')
+ else
+ contains('mount(App, { target: el, props })')
+ end
+ end
+ end
+ file('app/views/layouts/application.html.erb') do
+ if ext == 'ts'
+ contains('<%= vite_typescript_tag "inertia" %>')
+ else
+ contains('<%= vite_javascript_tag "inertia" %>')
+ end
+ if framework == :react
+ contains('<%= vite_react_refresh_tag %>')
+ else
+ does_not_contain('<%= vite_react_refresh_tag %>')
+ end
+ end
+ file('config/initializers/inertia_rails.rb') do
+ contains('config.version = ViteRuby.digest')
+ end
+
+ file('bin/dev') do
+ contains('overmind start -f Procfile.dev')
+ end
+
+ if ext == 'ts'
+ file('app/frontend/vite-env.d.ts') do
+ contains('/// ')
+ end
+ file('tsconfig.node.json') do
+ contains('"include": ["vite.config.ts"]')
+ end
+ case framework
+ when :react
+ file('tsconfig.json') do
+ contains('"path": "./tsconfig.app.json"')
+ end
+ file('tsconfig.app.json') do
+ contains('"include": ["app/frontend"]')
+ end
+ when :vue
+ file('tsconfig.json') do
+ contains('"path": "./tsconfig.app.json"')
+ end
+ file('tsconfig.app.json') do
+ contains('"include": ["app/frontend/**/*.ts", "app/frontend/**/*.tsx", "app/frontend/**/*.vue"]')
+ end
+ when :svelte, :svelte4
+ file('tsconfig.json') do
+ contains('"include": ["app/frontend/**/*.ts", "app/frontend/**/*.js", "app/frontend/**/*.svelte"]')
+ end
+ end
+ end
+ end)
+ end
+
+ def expect_example_page_for(framework, ext: 'js')
+ expect(destination_root).to(have_structure do
+ directory('app/frontend') do
+ case framework
+ when :react
+ file("pages/InertiaExample.#{ext == 'js' ? 'jsx' : 'tsx'}")
+ file('pages/InertiaExample.module.css')
+ file('assets/react.svg')
+ when :vue
+ file('pages/InertiaExample.vue')
+ file('assets/vue.svg')
+ when :svelte4
+ file('pages/InertiaExample.svelte') do
+ if ext == 'ts'
+ contains('export let name: string')
+ else
+ contains('export let name')
+ end
+ end
+ file('assets/svelte.svg')
+ when :svelte
+ file('pages/InertiaExample.svelte') do
+ if ext == 'ts'
+ contains('let { name }: { name: string } = $props()')
+ else
+ contains('let { name } = $props()')
+ end
+ end
+ file('assets/svelte.svg')
+ end
+
+ file('assets/inertia.svg')
+ file('assets/vite_ruby.svg')
+ end
+ end)
+ end
+end
From f370f2327d41c71c3eb678130b10a6ee2f9dbfa5 Mon Sep 17 00:00:00 2001
From: Svyatoslav Kryukov
Date: Mon, 11 Nov 2024 22:57:07 +0300
Subject: [PATCH 02/11] Add TypeScript support for React scaffolds
---
.../controller/templates/react/view.tsx.tt | 8 +
.../scaffold/templates/react/Edit.tsx.tt | 40 +++++
.../scaffold/templates/react/Form.tsx.tt | 140 ++++++++++++++++
.../scaffold/templates/react/Index.tsx.tt | 31 ++++
.../scaffold/templates/react/New.tsx.tt | 32 ++++
.../scaffold/templates/react/One.tsx.tt | 37 +++++
.../scaffold/templates/react/Show.tsx.tt | 45 ++++++
.../controller/templates/react/view.tsx.tt | 8 +
.../scaffold/templates/react/Edit.tsx.tt | 47 ++++++
.../scaffold/templates/react/Form.tsx.tt | 152 ++++++++++++++++++
.../scaffold/templates/react/Index.tsx.tt | 48 ++++++
.../scaffold/templates/react/New.tsx.tt | 35 ++++
.../scaffold/templates/react/One.tsx.tt | 37 +++++
.../scaffold/templates/react/Show.tsx.tt | 60 +++++++
.../generators/controller_template_base.rb | 9 +-
lib/inertia_rails/generators/helper.rb | 71 ++++++--
.../generators/scaffold_template_base.rb | 11 +-
17 files changed, 791 insertions(+), 20 deletions(-)
create mode 100644 lib/generators/inertia_templates/controller/templates/react/view.tsx.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/react/Edit.tsx.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/react/Form.tsx.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/react/Index.tsx.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/react/New.tsx.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/react/One.tsx.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/react/Show.tsx.tt
create mode 100644 lib/generators/inertia_tw_templates/controller/templates/react/view.tsx.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/react/Edit.tsx.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/react/Form.tsx.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/react/Index.tsx.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/react/New.tsx.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/react/One.tsx.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/react/Show.tsx.tt
diff --git a/lib/generators/inertia_templates/controller/templates/react/view.tsx.tt b/lib/generators/inertia_templates/controller/templates/react/view.tsx.tt
new file mode 100644
index 00000000..799ea4c5
--- /dev/null
+++ b/lib/generators/inertia_templates/controller/templates/react/view.tsx.tt
@@ -0,0 +1,8 @@
+export default function <%= @action.camelize %>() {
+ return (
+ <>
+ <%= class_name %>#<%= @action %>
+ Find me in <%= @path %>
+ >
+ );
+}
diff --git a/lib/generators/inertia_templates/scaffold/templates/react/Edit.tsx.tt b/lib/generators/inertia_templates/scaffold/templates/react/Edit.tsx.tt
new file mode 100644
index 00000000..d8d72e7c
--- /dev/null
+++ b/lib/generators/inertia_templates/scaffold/templates/react/Edit.tsx.tt
@@ -0,0 +1,40 @@
+import { Link, Head } from '@inertiajs/react'
+import Form from './Form'
+import { <%= inertia_model_type %> } from './<%= inertia_component_name %>'
+
+interface EditProps {
+ <%= singular_table_name %>: <%= inertia_model_type %>
+}
+
+export default function Edit({ <%= singular_table_name %> }: EditProps) {
+ return (
+ <>
+
+
+ Editing <%= human_name.downcase %>
+
+ ={<%= singular_table_name %>}
+ onSubmit={(form) => {
+ form.transform((data) => ({ <%= singular_table_name %>: data }))
+<% if attributes.any?(&:attachments?) -%>
+ form.post(`<%= js_resource_path %>`, {
+ headers: { 'X-HTTP-METHOD-OVERRIDE': 'put' },
+ })
+<% else -%>
+ form.patch(`<%= js_resource_path %>`)
+<% end -%>
+ }}
+ submitText="Update <%= human_name.downcase %>"
+ />
+
+
+
+
+ `}>Show this <%= human_name.downcase %>
+ {' | '}
+ Back to <%= human_name.pluralize.downcase %>
+
+ >
+ )
+}
diff --git a/lib/generators/inertia_templates/scaffold/templates/react/Form.tsx.tt b/lib/generators/inertia_templates/scaffold/templates/react/Form.tsx.tt
new file mode 100644
index 00000000..1d53c45d
--- /dev/null
+++ b/lib/generators/inertia_templates/scaffold/templates/react/Form.tsx.tt
@@ -0,0 +1,140 @@
+import { FormEvent } from 'react'
+import { useForm, InertiaFormProps } from '@inertiajs/react'
+import { <%= inertia_model_type %> } from './<%= inertia_component_name %>'
+
+interface FormProps {
+ <%= singular_table_name %>: <%= inertia_model_type %>
+ onSubmit: (form: InertiaFormProps<<%= inertia_component_name %>FormType>) => void
+ submitText: string
+}
+
+type <%= inertia_component_name %>FormType = Omit<<%= inertia_model_type %>, <%= omit_input_attributes.map { |a| "'#{a}'" }.join(' | ') %>><% if custom_form_attributes.any? -%> & {
+<% custom_form_attributes.map do |attribute| -%>
+<% if attribute.password_digest? -%>
+ password: string
+ password_confirmation: string
+<% elsif attribute.attachment? -%>
+ <%= attribute.column_name %>?: File
+<% elsif attribute.attachments? -%>
+ <%= attribute.column_name %>?: File[]
+<% end -%>
+<% end -%>
+}<% end -%>
+
+export default function Form({ <%= singular_table_name %>, onSubmit, submitText }: FormProps) {
+ const form = useForm<<%= inertia_component_name %>FormType>({
+<% attributes.reject { |a| a.attachment? || a.attachments? }.each do |attribute| -%>
+<% if attribute.password_digest? -%>
+ password: '',
+ password_confirmation: '',
+<% else -%>
+ <%= attribute.column_name %>: <%= singular_table_name %>.<%= attribute.column_name %>,
+<% end -%>
+<% end -%>
+ })
+ const { data, setData, errors, processing } = form
+
+ const handleSubmit = (e: FormEvent) => {
+ e.preventDefault()
+ onSubmit(form)
+ }
+
+ return (
+
+<% attributes.each do |attribute| -%>
+<% if attribute.password_digest? -%>
+
+
+
setData('password', e.target.value)}
+ />
+ {errors.password && (
+
{errors.password}
+ )}
+
+
+
+
+
setData('password_confirmation', e.target.value)}
+ />
+ {errors.password_confirmation && (
+
{errors.password_confirmation}
+ )}
+
+<% else -%>
+
+<% end -%>
+<% end -%>
+
+
+
+
+ )
+}
diff --git a/lib/generators/inertia_templates/scaffold/templates/react/Index.tsx.tt b/lib/generators/inertia_templates/scaffold/templates/react/Index.tsx.tt
new file mode 100644
index 00000000..6e1a0e24
--- /dev/null
+++ b/lib/generators/inertia_templates/scaffold/templates/react/Index.tsx.tt
@@ -0,0 +1,31 @@
+import { Link, Head } from '@inertiajs/react'
+import <%= inertia_component_name %>, { <%= inertia_model_type %> } from './<%= inertia_component_name %>'
+
+interface IndexProps {
+ <%= plural_table_name %>: <%= inertia_model_type %>[]
+ flash: { notice: string }
+}
+
+export default function Index({ <%= plural_table_name %>, flash }: IndexProps) {
+ return (
+ <>
+
+
+ {flash.notice && {flash.notice}
}
+
+ <%= human_name.pluralize %>
+
+ {<%= plural_table_name %>.map((<%= singular_table_name %>) => (
+
.id}>
+ <<%= inertia_component_name %> <%= singular_table_name %>={<%= singular_table_name %>} />
+
+ `}>Show this <%= human_name.downcase %>
+
+
+ ))}
+
+
+ New <%= human_name.downcase %>
+ >
+ )
+}
diff --git a/lib/generators/inertia_templates/scaffold/templates/react/New.tsx.tt b/lib/generators/inertia_templates/scaffold/templates/react/New.tsx.tt
new file mode 100644
index 00000000..56998be7
--- /dev/null
+++ b/lib/generators/inertia_templates/scaffold/templates/react/New.tsx.tt
@@ -0,0 +1,32 @@
+import { Link, Head } from '@inertiajs/react'
+import Form from './Form'
+import { <%= inertia_model_type %> } from './<%= inertia_component_name %>'
+
+interface NewProps {
+ <%= singular_table_name %>: <%= inertia_model_type %>
+}
+
+export default function New({ <%= singular_table_name %> }: NewProps) {
+ return (
+ <>
+
+
+ New <%= human_name.downcase %>
+
+ ={<%= singular_table_name %>}
+ onSubmit={(form) => {
+ form.transform((data) => ({ <%= singular_table_name %>: data }))
+ form.post('<%= js_resources_path %>')
+ }}
+ submitText="Create <%= human_name.downcase %>"
+ />
+
+
+
+
+ Back to <%= human_name.pluralize.downcase %>
+
+ >
+ )
+}
diff --git a/lib/generators/inertia_templates/scaffold/templates/react/One.tsx.tt b/lib/generators/inertia_templates/scaffold/templates/react/One.tsx.tt
new file mode 100644
index 00000000..04ca6212
--- /dev/null
+++ b/lib/generators/inertia_templates/scaffold/templates/react/One.tsx.tt
@@ -0,0 +1,37 @@
+export interface <%= inertia_model_type %> {
+ id: number
+<% attributes.reject(&:password_digest?).each do |attribute| -%>
+ <%= attribute.column_name %>: <%= ts_type(attribute) %>
+<% end -%>
+}
+
+interface <%= inertia_component_name %>Props {
+ <%= singular_table_name %>: <%= inertia_model_type %>
+}
+
+export default function <%= inertia_component_name %>({ <%= singular_table_name %> }: <%= inertia_component_name %>Props) {
+ return (
+
+<% attributes.reject(&:password_digest?).each do |attribute| -%>
+
+ <%= attribute.human_name %>:
+<% if attribute.attachment? -%>
+ {<%= singular_table_name %>.<%= attribute.column_name %> && (
+ .<%= attribute.column_name %>.url}>{<%= singular_table_name %>.<%= attribute.column_name %>.filename}
+ )}
+
+<% elsif attribute.attachments? -%>
+
+ {<%= singular_table_name %>.<%= attribute.column_name %>.map((file, i) => (
+
+ ))}
+<% else -%>
+ {<%= singular_table_name %>.<%= attribute.column_name %>.toString()}
+
+<% end -%>
+<% end -%>
+
+ )
+}
diff --git a/lib/generators/inertia_templates/scaffold/templates/react/Show.tsx.tt b/lib/generators/inertia_templates/scaffold/templates/react/Show.tsx.tt
new file mode 100644
index 00000000..178c61e3
--- /dev/null
+++ b/lib/generators/inertia_templates/scaffold/templates/react/Show.tsx.tt
@@ -0,0 +1,45 @@
+import { MouseEvent } from 'react'
+import { Link, Head } from '@inertiajs/react'
+import <%= inertia_component_name %>, { <%= inertia_model_type %> } from './<%= inertia_component_name %>'
+
+interface ShowProps {
+ <%= singular_table_name %>: <%= inertia_model_type %>
+ flash: { notice: string }
+}
+
+export default function Show({ <%= singular_table_name %>, flash }: ShowProps) {
+ const onDestroy = (e: MouseEvent) => {
+ if (!confirm('Are you sure you want to delete this <%= human_name.downcase %>?')) {
+ e.preventDefault()
+ }
+ }
+
+ return (
+ <>
+ #${<%= singular_table_name %>.id}`} />
+
+ {flash.notice && {flash.notice}
}
+
+ <%= human_name %> #{<%= singular_table_name %>.id}
+
+ <<%= inertia_component_name %> <%= singular_table_name %>={<%= singular_table_name %>} />
+
+
+ `}>Edit this <%= human_name.downcase %>
+ {' | '}
+ Back to <%= human_name.pluralize.downcase %>
+
+
+
+ `}
+ onClick={onDestroy}
+ as="button"
+ method="delete"
+ >
+ Destroy this <%= human_name.downcase %>
+
+
+ >
+ )
+}
diff --git a/lib/generators/inertia_tw_templates/controller/templates/react/view.tsx.tt b/lib/generators/inertia_tw_templates/controller/templates/react/view.tsx.tt
new file mode 100644
index 00000000..7f9d97b3
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/controller/templates/react/view.tsx.tt
@@ -0,0 +1,8 @@
+export default function <%= @action.camelize %>() {
+ return (
+ <>
+ <%= class_name %>#<%= @action %>
+ Find me in <%= @path %>
+ >
+ );
+}
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/react/Edit.tsx.tt b/lib/generators/inertia_tw_templates/scaffold/templates/react/Edit.tsx.tt
new file mode 100644
index 00000000..6e77a0f2
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/react/Edit.tsx.tt
@@ -0,0 +1,47 @@
+import { Link, Head } from '@inertiajs/react'
+import Form from './Form'
+import { <%= inertia_model_type %> } from './<%= inertia_component_name %>'
+
+interface EditProps {
+ <%= singular_table_name %>: <%= inertia_model_type %>
+}
+
+export default function Edit({ <%= singular_table_name %> }: EditProps) {
+ return (
+ <>
+
+
+
+
Editing <%= human_name.downcase %>
+
+ ={<%= singular_table_name %>}
+ onSubmit={(form) => {
+ form.transform((data) => ({ <%= singular_table_name %>: data }))
+<% if attributes.any?(&:attachments?) -%>
+ form.post(`<%= js_resource_path %>`, {
+ headers: { 'X-HTTP-METHOD-OVERRIDE': 'put' },
+ })
+<% else -%>
+ form.patch(`<%= js_resource_path %>`)
+<% end -%>
+ }}
+ submitText="Update <%= human_name.downcase %>"
+ />
+
+ `}
+ className="ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium"
+ >
+ Show this <%= human_name.downcase %>
+
+
+ Back to <%= human_name.pluralize.downcase %>
+
+
+ >
+ )
+}
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/react/Form.tsx.tt b/lib/generators/inertia_tw_templates/scaffold/templates/react/Form.tsx.tt
new file mode 100644
index 00000000..4f29b2e5
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/react/Form.tsx.tt
@@ -0,0 +1,152 @@
+import { FormEvent } from 'react'
+import { useForm, InertiaFormProps } from '@inertiajs/react'
+import { <%= inertia_model_type %> } from './<%= inertia_component_name %>'
+
+interface FormProps {
+ <%= singular_table_name %>: <%= inertia_model_type %>
+ onSubmit: (form: InertiaFormProps<<%= inertia_component_name %>FormType>) => void
+ submitText: string
+}
+
+type <%= inertia_component_name %>FormType = Omit<<%= inertia_model_type %>, <%= omit_input_attributes.map { |a| "'#{a}'" }.join(' | ') %>><% if custom_form_attributes.any? -%> & {
+<% custom_form_attributes.map do |attribute| -%>
+<% if attribute.password_digest? -%>
+ password: string
+ password_confirmation: string
+<% elsif attribute.attachment? -%>
+ <%= attribute.column_name %>?: File
+<% elsif attribute.attachments? -%>
+ <%= attribute.column_name %>?: File[]
+<% end -%>
+<% end -%>
+}<% end -%>
+
+export default function Form({ <%= singular_table_name %>, onSubmit, submitText }: FormProps) {
+ const form = useForm<<%= inertia_component_name %>FormType>({
+<% attributes.reject { |a| a.attachment? || a.attachments? }.each do |attribute| -%>
+<% if attribute.password_digest? -%>
+ password: '',
+ password_confirmation: '',
+<% else -%>
+ <%= attribute.column_name %>: <%= singular_table_name %>.<%= attribute.column_name %>,
+<% end -%>
+<% end -%>
+ })
+ const { data, setData, errors, processing } = form
+
+ const handleSubmit = (e: FormEvent) => {
+ e.preventDefault()
+ onSubmit(form)
+ }
+
+ return (
+
+<% attributes.each do |attribute| -%>
+
+<% if attribute.password_digest? -%>
+
+
setData('password', e.target.value)}
+ />
+ {errors.password && (
+
+ {errors.password}
+
+ )}
+
+
+
+
+<% end -%>
+
+
+
+
+ )
+}
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/react/Index.tsx.tt b/lib/generators/inertia_tw_templates/scaffold/templates/react/Index.tsx.tt
new file mode 100644
index 00000000..f87216b4
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/react/Index.tsx.tt
@@ -0,0 +1,48 @@
+import { Link, Head } from '@inertiajs/react'
+import { Fragment } from 'react'
+import <%= inertia_component_name %>, { <%= inertia_model_type %> } from './<%= inertia_component_name %>'
+
+interface IndexProps {
+ <%= plural_table_name %>: <%= inertia_model_type %>[]
+ flash: { notice: string }
+}
+
+export default function Index({ <%= plural_table_name %>, flash }: IndexProps) {
+ return (
+ <>
+
+
+ {flash.notice && (
+
+ {flash.notice}
+
+ )}
+
+
<%= human_name.pluralize %>
+
+ New <%= human_name.downcase %>
+
+
+
+
+ {<%= plural_table_name %>.map((<%= singular_table_name %>) => (
+
.id}>
+ <<%= inertia_component_name %> <%= singular_table_name %>={<%= singular_table_name %>} />
+
+ `}
+ className="ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium"
+ >
+ Show this <%= human_name.downcase %>
+
+
+
+ ))}
+
+
+ >
+ )
+}
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/react/New.tsx.tt b/lib/generators/inertia_tw_templates/scaffold/templates/react/New.tsx.tt
new file mode 100644
index 00000000..92ca1a77
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/react/New.tsx.tt
@@ -0,0 +1,35 @@
+import { Link, Head } from '@inertiajs/react'
+import Form from './Form'
+import { <%= inertia_model_type %> } from './<%= inertia_component_name %>'
+
+interface NewProps {
+ <%= singular_table_name %>: <%= inertia_model_type %>
+}
+
+export default function New({ <%= singular_table_name %> }: NewProps) {
+ return (
+ <>
+
+
+
+
New <%= human_name.downcase %>
+
+ ={<%= singular_table_name %>}
+ onSubmit={(form) => {
+ form.transform((data) => ({ <%= singular_table_name %>: data }))
+ form.post('<%= js_resources_path %>')
+ }}
+ submitText="Create <%= human_name.downcase %>"
+ />
+
+
+ Back to <%= human_name.pluralize.downcase %>
+
+
+ >
+ )
+}
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/react/One.tsx.tt b/lib/generators/inertia_tw_templates/scaffold/templates/react/One.tsx.tt
new file mode 100644
index 00000000..03eafa88
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/react/One.tsx.tt
@@ -0,0 +1,37 @@
+export interface <%= inertia_model_type %> {
+ id: number
+<% attributes.reject(&:password_digest?).each do |attribute| -%>
+ <%= attribute.column_name %>: <%= ts_type(attribute) %>
+<% end -%>
+}
+
+interface <%= inertia_component_name %>Props {
+ <%= singular_table_name %>: <%= inertia_model_type %>
+}
+
+export default function <%= inertia_component_name %>({ <%= singular_table_name %> }: <%= inertia_component_name %>Props) {
+ return (
+
+<% attributes.reject(&:password_digest?).each do |attribute| -%>
+
+ <%= attribute.human_name %>:
+<% if attribute.attachment? -%>
+ {<%= singular_table_name %>.<%= attribute.column_name %> && (
+ .<%= attribute.column_name %>.url}>{<%= singular_table_name %>.<%= attribute.column_name %>.filename}
+ )}
+
+<% elsif attribute.attachments? -%>
+
+ {<%= singular_table_name %>.<%= attribute.column_name %>.map((file, i) => (
+
+ ))}
+<% else -%>
+ {<%= singular_table_name %>.<%= attribute.column_name %>?.toString()}
+
+<% end -%>
+<% end -%>
+
+ )
+}
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/react/Show.tsx.tt b/lib/generators/inertia_tw_templates/scaffold/templates/react/Show.tsx.tt
new file mode 100644
index 00000000..faa855a0
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/react/Show.tsx.tt
@@ -0,0 +1,60 @@
+import { MouseEvent } from 'react'
+import { Link, Head } from '@inertiajs/react'
+import <%= inertia_component_name %>, { <%= inertia_model_type %> } from './<%= inertia_component_name %>'
+
+interface ShowProps {
+ <%= singular_table_name %>: <%= inertia_model_type %>
+ flash: { notice: string }
+}
+
+export default function Show({ <%= singular_table_name %>, flash }: ShowProps) {
+ const onDestroy = (e: MouseEvent) => {
+ if (!confirm('Are you sure you want to delete this <%= human_name.downcase %>?')) {
+ e.preventDefault()
+ }
+ }
+
+ return (
+ <>
+ #${<%= singular_table_name %>.id}`} />
+
+
+
+ {flash.notice && (
+
+ {flash.notice}
+
+ )}
+
+
<%= human_name %> #{<%= singular_table_name %>.id}
+
+ <<%= inertia_component_name %> <%= singular_table_name %>={<%= singular_table_name %>} />
+
+
`}
+ className="mt-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium"
+ >
+ Edit this <%= human_name.downcase %>
+
+
+ Back to <%= human_name.pluralize.downcase %>
+
+
+ `}
+ onClick={onDestroy}
+ as="button"
+ method="delete"
+ className="mt-2 rounded-lg py-3 px-5 bg-gray-100 font-medium"
+ >
+ Destroy this <%= human_name.downcase %>
+
+
+
+
+ >
+ )
+}
diff --git a/lib/inertia_rails/generators/controller_template_base.rb b/lib/inertia_rails/generators/controller_template_base.rb
index 7232aa47..fe0b7447 100644
--- a/lib/inertia_rails/generators/controller_template_base.rb
+++ b/lib/inertia_rails/generators/controller_template_base.rb
@@ -10,6 +10,9 @@ class ControllerTemplateBase < Rails::Generators::NamedBase
class_option :frontend_framework, required: true, desc: 'Frontend framework to generate the views for.',
default: Helper.guess_the_default_framework
+ class_option :typescript, type: :boolean, desc: 'Whether to use TypeScript',
+ default: Helper.guess_typescript
+
argument :actions, type: :array, default: [], banner: 'action action'
def empty_views_dir
@@ -44,13 +47,17 @@ def root_path
def extension
case options.frontend_framework
- when 'react' then 'jsx'
+ when 'react' then typescript? ? 'tsx' : 'jsx'
when 'vue' then 'vue'
when 'svelte' then 'svelte'
else
raise ArgumentError, "Unknown frontend framework: #{options.frontend_framework}"
end
end
+
+ def typescript?
+ options.typescript
+ end
end
end
end
diff --git a/lib/inertia_rails/generators/helper.rb b/lib/inertia_rails/generators/helper.rb
index e7474bf9..2e2a6bf5 100644
--- a/lib/inertia_rails/generators/helper.rb
+++ b/lib/inertia_rails/generators/helper.rb
@@ -3,25 +3,31 @@
module InertiaRails
module Generators
module Helper
- def self.guess_the_default_framework
- package = Rails.root.join('package.json').read
- case package
- when %r{@inertiajs/react}
- 'react'
- when %r{@inertiajs/svelte}
- package.match?(/"svelte": "\^5/) ? 'svelte' : 'svelte4'
- when %r{@inertiajs/vue3}
- 'vue'
- else
- Thor::Shell::Basic.new.say_error 'Could not determine the Inertia.js framework you are using.'
+ class << self
+ def guess_the_default_framework
+ package = Rails.root.join('package.json').read
+ case package
+ when %r{@inertiajs/react}
+ 'react'
+ when %r{@inertiajs/svelte}
+ package.match?(/"svelte": "\^5/) ? 'svelte' : 'svelte4'
+ when %r{@inertiajs/vue3}
+ 'vue'
+ else
+ Thor::Shell::Basic.new.say_error 'Could not determine the Inertia.js framework you are using.'
+ end
end
- end
- def self.guess_inertia_template
- if Rails.root.join('tailwind.config.js').exist? || Rails.root.join('tailwind.config.ts').exist?
- 'inertia_tw_templates'
- else
- 'inertia_templates'
+ def guess_typescript
+ Rails.root.join('tsconfig.json').exist?
+ end
+
+ def guess_inertia_template
+ if Rails.root.join('tailwind.config.js').exist? || Rails.root.join('tailwind.config.ts').exist?
+ 'inertia_tw_templates'
+ else
+ 'inertia_templates'
+ end
end
end
@@ -33,6 +39,10 @@ def inertia_component_name
singular_name.camelize
end
+ def inertia_model_type
+ "#{inertia_component_name}Type"
+ end
+
def attributes_to_serialize
[:id] + attributes.reject do |attribute|
attribute.password_digest? ||
@@ -41,6 +51,18 @@ def attributes_to_serialize
end.map(&:column_name)
end
+ def custom_form_attributes
+ attributes.select do |attribute|
+ attribute.password_digest? ||
+ attribute.attachment? ||
+ attribute.attachments?
+ end
+ end
+
+ def omit_input_attributes
+ ['id'] + attributes.select { |attribute| attribute.attachment? || attribute.attachments? }.map(&:column_name)
+ end
+
def js_resource_path
"#{route_url}/${#{singular_table_name}.id}"
end
@@ -57,6 +79,21 @@ def js_resources_path
route_url
end
+ def ts_type(attribute)
+ case attribute.type
+ when :float, :decimal, :integer
+ 'number'
+ when :boolean
+ 'boolean'
+ when :attachment
+ '{ filename: string; url: string }'
+ when :attachments
+ '{ filename: string; url: string }[]'
+ else
+ 'string'
+ end
+ end
+
def input_type(attribute)
case attribute.type
when :text, :rich_text
diff --git a/lib/inertia_rails/generators/scaffold_template_base.rb b/lib/inertia_rails/generators/scaffold_template_base.rb
index a96c42f3..51a8adff 100644
--- a/lib/inertia_rails/generators/scaffold_template_base.rb
+++ b/lib/inertia_rails/generators/scaffold_template_base.rb
@@ -14,16 +14,23 @@ class ScaffoldTemplateBase < ControllerTemplateBase
def copy_view_files
available_views.each do |view|
- filename = "#{view}.#{extension}"
+ filename = "#{view}.#{template_extension}"
template "#{options.frontend_framework}/#{filename}", File.join(base_path, filename)
end
- template "#{options.frontend_framework}/#{partial_name}.#{extension}",
+ template "#{options.frontend_framework}/#{partial_name}.#{template_extension}",
File.join(base_path, "#{inertia_component_name}.#{extension}")
end
private
+ def template_extension
+ return extension unless typescript?
+ return 'tsx' if options.frontend_framework == 'react'
+
+ "ts.#{extension}"
+ end
+
def available_views
%w[Index Edit Show New Form]
end
From c2864113dc191b51cf01c741a460f7642ed3ae0e Mon Sep 17 00:00:00 2001
From: Svyatoslav Kryukov
Date: Tue, 12 Nov 2024 22:18:24 +0300
Subject: [PATCH 03/11] Add TypeScript support for Vue scaffolds
---
.../scaffold/templates/react/Index.tsx.tt | 2 +-
.../scaffold/templates/react/Show.tsx.tt | 2 +-
.../scaffold/templates/vue/Edit.ts.vue.tt | 37 +++++
.../scaffold/templates/vue/Form.ts.vue.tt | 114 ++++++++++++++
.../scaffold/templates/vue/Index.ts.vue.tt | 31 ++++
.../scaffold/templates/vue/New.ts.vue.tt | 30 ++++
.../scaffold/templates/vue/One.ts.vue.tt | 33 ++++
.../scaffold/templates/vue/Show.ts.vue.tt | 47 ++++++
.../scaffold/templates/react/Index.tsx.tt | 2 +-
.../scaffold/templates/react/Show.tsx.tt | 2 +-
.../scaffold/templates/vue/Edit.ts.vue.tt | 45 ++++++
.../scaffold/templates/vue/Form.ts.vue.tt | 147 ++++++++++++++++++
.../scaffold/templates/vue/Index.ts.vue.tt | 43 +++++
.../scaffold/templates/vue/New.ts.vue.tt | 33 ++++
.../scaffold/templates/vue/One.ts.vue.tt | 33 ++++
.../scaffold/templates/vue/Show.ts.vue.tt | 59 +++++++
.../generators/scaffold_template_base.rb | 4 +-
17 files changed, 658 insertions(+), 6 deletions(-)
create mode 100644 lib/generators/inertia_templates/scaffold/templates/vue/Edit.ts.vue.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/vue/Form.ts.vue.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/vue/Index.ts.vue.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/vue/New.ts.vue.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/vue/One.ts.vue.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/vue/Show.ts.vue.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/vue/Edit.ts.vue.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/vue/Form.ts.vue.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/vue/Index.ts.vue.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/vue/New.ts.vue.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/vue/One.ts.vue.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/vue/Show.ts.vue.tt
diff --git a/lib/generators/inertia_templates/scaffold/templates/react/Index.tsx.tt b/lib/generators/inertia_templates/scaffold/templates/react/Index.tsx.tt
index 6e1a0e24..d65e9033 100644
--- a/lib/generators/inertia_templates/scaffold/templates/react/Index.tsx.tt
+++ b/lib/generators/inertia_templates/scaffold/templates/react/Index.tsx.tt
@@ -3,7 +3,7 @@ import <%= inertia_component_name %>, { <%= inertia_model_type %> } from './<%=
interface IndexProps {
<%= plural_table_name %>: <%= inertia_model_type %>[]
- flash: { notice: string }
+ flash: { notice?: string }
}
export default function Index({ <%= plural_table_name %>, flash }: IndexProps) {
diff --git a/lib/generators/inertia_templates/scaffold/templates/react/Show.tsx.tt b/lib/generators/inertia_templates/scaffold/templates/react/Show.tsx.tt
index 178c61e3..152e5507 100644
--- a/lib/generators/inertia_templates/scaffold/templates/react/Show.tsx.tt
+++ b/lib/generators/inertia_templates/scaffold/templates/react/Show.tsx.tt
@@ -4,7 +4,7 @@ import <%= inertia_component_name %>, { <%= inertia_model_type %> } from './<%=
interface ShowProps {
<%= singular_table_name %>: <%= inertia_model_type %>
- flash: { notice: string }
+ flash: { notice?: string }
}
export default function Show({ <%= singular_table_name %>, flash }: ShowProps) {
diff --git a/lib/generators/inertia_templates/scaffold/templates/vue/Edit.ts.vue.tt b/lib/generators/inertia_templates/scaffold/templates/vue/Edit.ts.vue.tt
new file mode 100644
index 00000000..1cfb81ab
--- /dev/null
+++ b/lib/generators/inertia_templates/scaffold/templates/vue/Edit.ts.vue.tt
@@ -0,0 +1,37 @@
+
+
+
+ Editing <%= human_name.downcase %>
+
+ ="<%= singular_table_name %>"
+ submitText="Update <%= human_name.downcase %>"
+ @onSubmit="handleSubmit"
+ />
+
+
+
+
+ Show this <%= human_name.downcase %> |
+ Back to <%= human_name.pluralize.downcase %>
+
+
+
+
diff --git a/lib/generators/inertia_templates/scaffold/templates/vue/Form.ts.vue.tt b/lib/generators/inertia_templates/scaffold/templates/vue/Form.ts.vue.tt
new file mode 100644
index 00000000..8ec8d4f0
--- /dev/null
+++ b/lib/generators/inertia_templates/scaffold/templates/vue/Form.ts.vue.tt
@@ -0,0 +1,114 @@
+
+
+<% attributes.each do |attribute| -%>
+<% if attribute.password_digest? -%>
+
+
+
+
+ {{ form.errors.password }}
+
+
+
+
+
+
+
+ {{ form.errors.password_confirmation }}
+
+
+<% else -%>
+
+<% end -%>
+<% end -%>
+
+
+
+
+
+
+
+
+
diff --git a/lib/generators/inertia_templates/scaffold/templates/vue/Index.ts.vue.tt b/lib/generators/inertia_templates/scaffold/templates/vue/Index.ts.vue.tt
new file mode 100644
index 00000000..96e643cc
--- /dev/null
+++ b/lib/generators/inertia_templates/scaffold/templates/vue/Index.ts.vue.tt
@@ -0,0 +1,31 @@
+
+
+
+ {{ flash.notice }}
+
+ <%= human_name.pluralize %>
+
+
+
+ <<%= inertia_component_name %> :<%= singular_table_name %>="<%= singular_table_name %>" />
+
+ Show this <%= human_name.downcase %>
+
+
+
+
+ New <%= human_name.downcase %>
+
+
+
+
+
diff --git a/lib/generators/inertia_templates/scaffold/templates/vue/New.ts.vue.tt b/lib/generators/inertia_templates/scaffold/templates/vue/New.ts.vue.tt
new file mode 100644
index 00000000..08ba7641
--- /dev/null
+++ b/lib/generators/inertia_templates/scaffold/templates/vue/New.ts.vue.tt
@@ -0,0 +1,30 @@
+
+
+
+ New <%= human_name.downcase %>
+
+ ="<%= singular_table_name %>"
+ submitText="Create <%= human_name.downcase %>"
+ @onSubmit="handleSubmit"
+ />
+
+
+
+
+ Back to <%= human_name.pluralize.downcase %>
+
+
+
+
diff --git a/lib/generators/inertia_templates/scaffold/templates/vue/One.ts.vue.tt b/lib/generators/inertia_templates/scaffold/templates/vue/One.ts.vue.tt
new file mode 100644
index 00000000..8f528968
--- /dev/null
+++ b/lib/generators/inertia_templates/scaffold/templates/vue/One.ts.vue.tt
@@ -0,0 +1,33 @@
+
+
+
+
+
diff --git a/lib/generators/inertia_templates/scaffold/templates/vue/Show.ts.vue.tt b/lib/generators/inertia_templates/scaffold/templates/vue/Show.ts.vue.tt
new file mode 100644
index 00000000..a4229f5f
--- /dev/null
+++ b/lib/generators/inertia_templates/scaffold/templates/vue/Show.ts.vue.tt
@@ -0,0 +1,47 @@
+
+
+
+ {{ flash.notice }}
+
+ <%= human_name %> #{{ <%= singular_table_name %>.id }}
+
+ <<%= inertia_component_name %> :<%= singular_table_name %>="<%= singular_table_name %>" />
+
+
+ Edit this <%= human_name.downcase %> |
+ Back to <%= human_name.pluralize.downcase %>
+
+
+
+
+ Destroy this <%= human_name.downcase %>
+
+
+
+
+
+
+
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/react/Index.tsx.tt b/lib/generators/inertia_tw_templates/scaffold/templates/react/Index.tsx.tt
index f87216b4..28df41cc 100644
--- a/lib/generators/inertia_tw_templates/scaffold/templates/react/Index.tsx.tt
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/react/Index.tsx.tt
@@ -4,7 +4,7 @@ import <%= inertia_component_name %>, { <%= inertia_model_type %> } from './<%=
interface IndexProps {
<%= plural_table_name %>: <%= inertia_model_type %>[]
- flash: { notice: string }
+ flash: { notice?: string }
}
export default function Index({ <%= plural_table_name %>, flash }: IndexProps) {
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/react/Show.tsx.tt b/lib/generators/inertia_tw_templates/scaffold/templates/react/Show.tsx.tt
index faa855a0..d32c7c5f 100644
--- a/lib/generators/inertia_tw_templates/scaffold/templates/react/Show.tsx.tt
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/react/Show.tsx.tt
@@ -4,7 +4,7 @@ import <%= inertia_component_name %>, { <%= inertia_model_type %> } from './<%=
interface ShowProps {
<%= singular_table_name %>: <%= inertia_model_type %>
- flash: { notice: string }
+ flash: { notice?: string }
}
export default function Show({ <%= singular_table_name %>, flash }: ShowProps) {
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/vue/Edit.ts.vue.tt b/lib/generators/inertia_tw_templates/scaffold/templates/vue/Edit.ts.vue.tt
new file mode 100644
index 00000000..3ff01eeb
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/vue/Edit.ts.vue.tt
@@ -0,0 +1,45 @@
+
+
+
+
+
Editing <%= human_name.downcase %>
+
+ ="<%= singular_table_name %>"
+ submitText="Update <%= human_name.downcase %>"
+ @onSubmit="handleSubmit"
+ />
+
+
+ Show this <%= human_name.downcase %>
+
+
+ Back to <%= human_name.pluralize.downcase %>
+
+
+
+
+
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/vue/Form.ts.vue.tt b/lib/generators/inertia_tw_templates/scaffold/templates/vue/Form.ts.vue.tt
new file mode 100644
index 00000000..ebe6373f
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/vue/Form.ts.vue.tt
@@ -0,0 +1,147 @@
+
+
+<% attributes.each do |attribute| -%>
+<% if attribute.password_digest? -%>
+
+
+
+
+ {{ form.errors.password }}
+
+
+
+
+
+
+
+ {{ form.errors.password_confirmation }}
+
+
+<% else -%>
+
+<% end -%>
+
+<% end -%>
+
+
+
+
+
+
+
+
+
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/vue/Index.ts.vue.tt b/lib/generators/inertia_tw_templates/scaffold/templates/vue/Index.ts.vue.tt
new file mode 100644
index 00000000..10b9baca
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/vue/Index.ts.vue.tt
@@ -0,0 +1,43 @@
+
+
+
+
+
+ {{ flash.notice }}
+
+
+
+
<%= human_name.pluralize %>
+
+ New <%= human_name.downcase %>
+
+
+
+
+
+ <<%= inertia_component_name %> :<%= singular_table_name %>="<%= singular_table_name %>" />
+
+
+ Show this <%= human_name.downcase %>
+
+
+
+
+
+
+
+
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/vue/New.ts.vue.tt b/lib/generators/inertia_tw_templates/scaffold/templates/vue/New.ts.vue.tt
new file mode 100644
index 00000000..d433e583
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/vue/New.ts.vue.tt
@@ -0,0 +1,33 @@
+
+
+
+
+
New <%= human_name.downcase %>
+
+ ="<%= singular_table_name %>"
+ submitText="Create <%= human_name.downcase %>"
+ @onSubmit="handleSubmit"
+ />
+
+
+ Back to <%= human_name.pluralize.downcase %>
+
+
+
+
+
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/vue/One.ts.vue.tt b/lib/generators/inertia_tw_templates/scaffold/templates/vue/One.ts.vue.tt
new file mode 100644
index 00000000..abe8e55d
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/vue/One.ts.vue.tt
@@ -0,0 +1,33 @@
+
+
+
+
+
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/vue/Show.ts.vue.tt b/lib/generators/inertia_tw_templates/scaffold/templates/vue/Show.ts.vue.tt
new file mode 100644
index 00000000..b102885b
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/vue/Show.ts.vue.tt
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+ {{ flash.notice }}
+
+
+
<%= human_name %> #{{ <%= singular_table_name %>.id }}
+
+ <<%= inertia_component_name %> :<%= singular_table_name %>="<%= singular_table_name %>" />
+
+
+ Edit this <%= human_name.downcase %>
+
+
+ Back to <%= human_name.pluralize.downcase %>
+
+
+
+
+ Destroy this <%= human_name.downcase %>
+
+
+
+
+
+
+
diff --git a/lib/inertia_rails/generators/scaffold_template_base.rb b/lib/inertia_rails/generators/scaffold_template_base.rb
index 51a8adff..e3f2064b 100644
--- a/lib/inertia_rails/generators/scaffold_template_base.rb
+++ b/lib/inertia_rails/generators/scaffold_template_base.rb
@@ -14,8 +14,8 @@ class ScaffoldTemplateBase < ControllerTemplateBase
def copy_view_files
available_views.each do |view|
- filename = "#{view}.#{template_extension}"
- template "#{options.frontend_framework}/#{filename}", File.join(base_path, filename)
+ template "#{options.frontend_framework}/#{view}.#{template_extension}",
+ File.join(base_path, "#{view}.#{extension}")
end
template "#{options.frontend_framework}/#{partial_name}.#{template_extension}",
From 08a164325d13bc163ba03a6d7f6a5d3539f99a55 Mon Sep 17 00:00:00 2001
From: Svyatoslav Kryukov
Date: Wed, 13 Nov 2024 10:36:16 +0300
Subject: [PATCH 04/11] Define shared types in types.ts
---
.../scaffold/templates/react/Edit.tsx.tt | 2 +-
.../scaffold/templates/react/Form.tsx.tt | 19 +++----------------
.../scaffold/templates/react/Index.tsx.tt | 3 ++-
.../scaffold/templates/react/New.tsx.tt | 2 +-
.../scaffold/templates/react/One.tsx.tt | 7 +------
.../scaffold/templates/react/Show.tsx.tt | 3 ++-
.../scaffold/templates/react/types.ts.tt | 19 +++++++++++++++++++
.../scaffold/templates/svelte/types.ts.tt | 19 +++++++++++++++++++
.../scaffold/templates/svelte4/types.ts.tt | 19 +++++++++++++++++++
.../scaffold/templates/vue/Edit.ts.vue.tt | 6 +++---
.../scaffold/templates/vue/Form.ts.vue.tt | 19 +++----------------
.../scaffold/templates/vue/Index.ts.vue.tt | 6 +++++-
.../scaffold/templates/vue/New.ts.vue.tt | 6 +++---
.../scaffold/templates/vue/One.ts.vue.tt | 7 +------
.../scaffold/templates/vue/Show.ts.vue.tt | 3 ++-
.../scaffold/templates/vue/types.ts.tt | 19 +++++++++++++++++++
.../scaffold/templates/react/Edit.tsx.tt | 2 +-
.../scaffold/templates/react/Form.tsx.tt | 19 +++----------------
.../scaffold/templates/react/Index.tsx.tt | 3 ++-
.../scaffold/templates/react/New.tsx.tt | 2 +-
.../scaffold/templates/react/One.tsx.tt | 7 +------
.../scaffold/templates/react/Show.tsx.tt | 3 ++-
.../scaffold/templates/react/types.ts.tt | 19 +++++++++++++++++++
.../scaffold/templates/svelte/types.ts.tt | 19 +++++++++++++++++++
.../scaffold/templates/svelte4/types.ts.tt | 19 +++++++++++++++++++
.../scaffold/templates/vue/Edit.ts.vue.tt | 6 +++---
.../scaffold/templates/vue/Form.ts.vue.tt | 19 +++----------------
.../scaffold/templates/vue/Index.ts.vue.tt | 6 +++++-
.../scaffold/templates/vue/New.ts.vue.tt | 6 +++---
.../scaffold/templates/vue/One.ts.vue.tt | 7 +------
.../scaffold/templates/vue/Show.ts.vue.tt | 3 ++-
.../scaffold/templates/vue/types.ts.tt | 19 +++++++++++++++++++
lib/inertia_rails/generators/helper.rb | 4 ++++
.../generators/scaffold_template_base.rb | 2 ++
34 files changed, 212 insertions(+), 112 deletions(-)
create mode 100644 lib/generators/inertia_templates/scaffold/templates/react/types.ts.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/svelte/types.ts.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/svelte4/types.ts.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/vue/types.ts.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/react/types.ts.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/svelte/types.ts.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/svelte4/types.ts.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/vue/types.ts.tt
diff --git a/lib/generators/inertia_templates/scaffold/templates/react/Edit.tsx.tt b/lib/generators/inertia_templates/scaffold/templates/react/Edit.tsx.tt
index d8d72e7c..36146789 100644
--- a/lib/generators/inertia_templates/scaffold/templates/react/Edit.tsx.tt
+++ b/lib/generators/inertia_templates/scaffold/templates/react/Edit.tsx.tt
@@ -1,6 +1,6 @@
import { Link, Head } from '@inertiajs/react'
import Form from './Form'
-import { <%= inertia_model_type %> } from './<%= inertia_component_name %>'
+import { <%= inertia_model_type %> } from './types'
interface EditProps {
<%= singular_table_name %>: <%= inertia_model_type %>
diff --git a/lib/generators/inertia_templates/scaffold/templates/react/Form.tsx.tt b/lib/generators/inertia_templates/scaffold/templates/react/Form.tsx.tt
index 1d53c45d..c6a7af76 100644
--- a/lib/generators/inertia_templates/scaffold/templates/react/Form.tsx.tt
+++ b/lib/generators/inertia_templates/scaffold/templates/react/Form.tsx.tt
@@ -1,28 +1,15 @@
import { FormEvent } from 'react'
import { useForm, InertiaFormProps } from '@inertiajs/react'
-import { <%= inertia_model_type %> } from './<%= inertia_component_name %>'
+import { <%= inertia_model_type %>, <%= inertia_model_form_type %> } from './types'
interface FormProps {
<%= singular_table_name %>: <%= inertia_model_type %>
- onSubmit: (form: InertiaFormProps<<%= inertia_component_name %>FormType>) => void
+ onSubmit: (form: InertiaFormProps<<%= inertia_model_form_type %>>) => void
submitText: string
}
-type <%= inertia_component_name %>FormType = Omit<<%= inertia_model_type %>, <%= omit_input_attributes.map { |a| "'#{a}'" }.join(' | ') %>><% if custom_form_attributes.any? -%> & {
-<% custom_form_attributes.map do |attribute| -%>
-<% if attribute.password_digest? -%>
- password: string
- password_confirmation: string
-<% elsif attribute.attachment? -%>
- <%= attribute.column_name %>?: File
-<% elsif attribute.attachments? -%>
- <%= attribute.column_name %>?: File[]
-<% end -%>
-<% end -%>
-}<% end -%>
-
export default function Form({ <%= singular_table_name %>, onSubmit, submitText }: FormProps) {
- const form = useForm<<%= inertia_component_name %>FormType>({
+ const form = useForm<<%= inertia_model_form_type %>>({
<% attributes.reject { |a| a.attachment? || a.attachments? }.each do |attribute| -%>
<% if attribute.password_digest? -%>
password: '',
diff --git a/lib/generators/inertia_templates/scaffold/templates/react/Index.tsx.tt b/lib/generators/inertia_templates/scaffold/templates/react/Index.tsx.tt
index d65e9033..ca8f8c41 100644
--- a/lib/generators/inertia_templates/scaffold/templates/react/Index.tsx.tt
+++ b/lib/generators/inertia_templates/scaffold/templates/react/Index.tsx.tt
@@ -1,5 +1,6 @@
import { Link, Head } from '@inertiajs/react'
-import <%= inertia_component_name %>, { <%= inertia_model_type %> } from './<%= inertia_component_name %>'
+import { <%= inertia_model_type %> } from './types'
+import <%= inertia_component_name %> from './<%= inertia_component_name %>'
interface IndexProps {
<%= plural_table_name %>: <%= inertia_model_type %>[]
diff --git a/lib/generators/inertia_templates/scaffold/templates/react/New.tsx.tt b/lib/generators/inertia_templates/scaffold/templates/react/New.tsx.tt
index 56998be7..0d88a3dd 100644
--- a/lib/generators/inertia_templates/scaffold/templates/react/New.tsx.tt
+++ b/lib/generators/inertia_templates/scaffold/templates/react/New.tsx.tt
@@ -1,6 +1,6 @@
import { Link, Head } from '@inertiajs/react'
import Form from './Form'
-import { <%= inertia_model_type %> } from './<%= inertia_component_name %>'
+import { <%= inertia_model_type %> } from './types'
interface NewProps {
<%= singular_table_name %>: <%= inertia_model_type %>
diff --git a/lib/generators/inertia_templates/scaffold/templates/react/One.tsx.tt b/lib/generators/inertia_templates/scaffold/templates/react/One.tsx.tt
index 04ca6212..9b0f1ace 100644
--- a/lib/generators/inertia_templates/scaffold/templates/react/One.tsx.tt
+++ b/lib/generators/inertia_templates/scaffold/templates/react/One.tsx.tt
@@ -1,9 +1,4 @@
-export interface <%= inertia_model_type %> {
- id: number
-<% attributes.reject(&:password_digest?).each do |attribute| -%>
- <%= attribute.column_name %>: <%= ts_type(attribute) %>
-<% end -%>
-}
+import { <%= inertia_model_type %> } from './types'
interface <%= inertia_component_name %>Props {
<%= singular_table_name %>: <%= inertia_model_type %>
diff --git a/lib/generators/inertia_templates/scaffold/templates/react/Show.tsx.tt b/lib/generators/inertia_templates/scaffold/templates/react/Show.tsx.tt
index 152e5507..82be7eaa 100644
--- a/lib/generators/inertia_templates/scaffold/templates/react/Show.tsx.tt
+++ b/lib/generators/inertia_templates/scaffold/templates/react/Show.tsx.tt
@@ -1,6 +1,7 @@
import { MouseEvent } from 'react'
import { Link, Head } from '@inertiajs/react'
-import <%= inertia_component_name %>, { <%= inertia_model_type %> } from './<%= inertia_component_name %>'
+import { <%= inertia_model_type %> } from './types'
+import <%= inertia_component_name %> from './<%= inertia_component_name %>'
interface ShowProps {
<%= singular_table_name %>: <%= inertia_model_type %>
diff --git a/lib/generators/inertia_templates/scaffold/templates/react/types.ts.tt b/lib/generators/inertia_templates/scaffold/templates/react/types.ts.tt
new file mode 100644
index 00000000..7d8e0cbd
--- /dev/null
+++ b/lib/generators/inertia_templates/scaffold/templates/react/types.ts.tt
@@ -0,0 +1,19 @@
+export interface <%= inertia_model_type %> {
+ id: number
+<% attributes.reject(&:password_digest?).each do |attribute| -%>
+ <%= attribute.column_name %>: <%= ts_type(attribute) %>
+<% end -%>
+}
+
+export type <%= inertia_model_form_type %> = Omit<<%= inertia_model_type %>, <%= omit_input_attributes.map { |a| "'#{a}'" }.join(' | ') %>><% if custom_form_attributes.any? -%> & {
+<% custom_form_attributes.map do |attribute| -%>
+<% if attribute.password_digest? -%>
+ password: string
+ password_confirmation: string
+<% elsif attribute.attachment? -%>
+ <%= attribute.column_name %>?: File
+<% elsif attribute.attachments? -%>
+ <%= attribute.column_name %>?: File[]
+<% end -%>
+<% end -%>
+}<% end -%>
diff --git a/lib/generators/inertia_templates/scaffold/templates/svelte/types.ts.tt b/lib/generators/inertia_templates/scaffold/templates/svelte/types.ts.tt
new file mode 100644
index 00000000..7d8e0cbd
--- /dev/null
+++ b/lib/generators/inertia_templates/scaffold/templates/svelte/types.ts.tt
@@ -0,0 +1,19 @@
+export interface <%= inertia_model_type %> {
+ id: number
+<% attributes.reject(&:password_digest?).each do |attribute| -%>
+ <%= attribute.column_name %>: <%= ts_type(attribute) %>
+<% end -%>
+}
+
+export type <%= inertia_model_form_type %> = Omit<<%= inertia_model_type %>, <%= omit_input_attributes.map { |a| "'#{a}'" }.join(' | ') %>><% if custom_form_attributes.any? -%> & {
+<% custom_form_attributes.map do |attribute| -%>
+<% if attribute.password_digest? -%>
+ password: string
+ password_confirmation: string
+<% elsif attribute.attachment? -%>
+ <%= attribute.column_name %>?: File
+<% elsif attribute.attachments? -%>
+ <%= attribute.column_name %>?: File[]
+<% end -%>
+<% end -%>
+}<% end -%>
diff --git a/lib/generators/inertia_templates/scaffold/templates/svelte4/types.ts.tt b/lib/generators/inertia_templates/scaffold/templates/svelte4/types.ts.tt
new file mode 100644
index 00000000..7d8e0cbd
--- /dev/null
+++ b/lib/generators/inertia_templates/scaffold/templates/svelte4/types.ts.tt
@@ -0,0 +1,19 @@
+export interface <%= inertia_model_type %> {
+ id: number
+<% attributes.reject(&:password_digest?).each do |attribute| -%>
+ <%= attribute.column_name %>: <%= ts_type(attribute) %>
+<% end -%>
+}
+
+export type <%= inertia_model_form_type %> = Omit<<%= inertia_model_type %>, <%= omit_input_attributes.map { |a| "'#{a}'" }.join(' | ') %>><% if custom_form_attributes.any? -%> & {
+<% custom_form_attributes.map do |attribute| -%>
+<% if attribute.password_digest? -%>
+ password: string
+ password_confirmation: string
+<% elsif attribute.attachment? -%>
+ <%= attribute.column_name %>?: File
+<% elsif attribute.attachments? -%>
+ <%= attribute.column_name %>?: File[]
+<% end -%>
+<% end -%>
+}<% end -%>
diff --git a/lib/generators/inertia_templates/scaffold/templates/vue/Edit.ts.vue.tt b/lib/generators/inertia_templates/scaffold/templates/vue/Edit.ts.vue.tt
index 1cfb81ab..b1b1092f 100644
--- a/lib/generators/inertia_templates/scaffold/templates/vue/Edit.ts.vue.tt
+++ b/lib/generators/inertia_templates/scaffold/templates/vue/Edit.ts.vue.tt
@@ -19,12 +19,12 @@
diff --git a/lib/generators/inertia_templates/scaffold/templates/svelte/Index.ts.svelte.tt b/lib/generators/inertia_templates/scaffold/templates/svelte/Index.ts.svelte.tt
new file mode 100644
index 00000000..a940d491
--- /dev/null
+++ b/lib/generators/inertia_templates/scaffold/templates/svelte/Index.ts.svelte.tt
@@ -0,0 +1,39 @@
+
+
+
+ <%= human_name.pluralize %>
+
+
+{#if flash.notice}
+ {flash.notice}
+{/if}
+
+<%= human_name.pluralize %>
+
+
+ {#each <%= plural_table_name %> as <%= singular_table_name %> (<%= singular_table_name %>.id)}
+
+ <<%= inertia_component_name %> {<%= singular_table_name %>} />
+
+ `}>Show this <%= human_name.downcase %>
+
+
+ {/each}
+
+
+New <%= human_name.downcase %>
+
+
diff --git a/lib/generators/inertia_templates/scaffold/templates/svelte/New.ts.svelte.tt b/lib/generators/inertia_templates/scaffold/templates/svelte/New.ts.svelte.tt
new file mode 100644
index 00000000..9c90af42
--- /dev/null
+++ b/lib/generators/inertia_templates/scaffold/templates/svelte/New.ts.svelte.tt
@@ -0,0 +1,30 @@
+
+
+
+ New <%= human_name.downcase %>
+
+
+New <%= human_name.downcase %>
+
+}
+ submitText="Create <%= human_name.downcase %>"
+ onSubmit={handleSubmit}
+/>
+
+
+
+
+ Back to <%= human_name.pluralize.downcase %>
+
diff --git a/lib/generators/inertia_templates/scaffold/templates/svelte/One.ts.svelte.tt b/lib/generators/inertia_templates/scaffold/templates/svelte/One.ts.svelte.tt
new file mode 100644
index 00000000..263b811b
--- /dev/null
+++ b/lib/generators/inertia_templates/scaffold/templates/svelte/One.ts.svelte.tt
@@ -0,0 +1,30 @@
+
+
+
+<% attributes.reject(&:password_digest?).each do |attribute| -%>
+
+ <%= attribute.human_name %>:
+<% if attribute.attachment? -%>
+ {#if <%= singular_table_name %>.<%= attribute.column_name %>}
+ .<%= attribute.column_name %>.url}>
+ {<%= singular_table_name %>.<%= attribute.column_name %>.filename}
+
+ {/if}
+
+<% elsif attribute.attachments? -%>
+
+ {#each <%= singular_table_name %>.<%= attribute.column_name %> as { url, filename }}
+
+ {/each}
+<% else -%>
+ {<%= singular_table_name %>.<%= attribute.column_name %>}
+
+<% end -%>
+<% end -%>
+
diff --git a/lib/generators/inertia_templates/scaffold/templates/svelte/Show.ts.svelte.tt b/lib/generators/inertia_templates/scaffold/templates/svelte/Show.ts.svelte.tt
new file mode 100644
index 00000000..12bcd88c
--- /dev/null
+++ b/lib/generators/inertia_templates/scaffold/templates/svelte/Show.ts.svelte.tt
@@ -0,0 +1,45 @@
+
+
+
+ <%= human_name %> #{<%= singular_table_name %>.id}
+
+
+{#if flash.notice}
+ {flash.notice}
+{/if}
+
+<%= human_name %> #{<%= singular_table_name %>.id}
+
+<<%= inertia_component_name %> {<%= singular_table_name %>} />
+
+
+ `}>Edit this <%= human_name.downcase %> |
+ Back to <%= human_name.pluralize.downcase %>
+
+
+
+ `} method="delete" onclick={onDestroy}>
+ Destroy this <%= human_name.downcase %>
+
+
+
+
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/svelte/Edit.ts.svelte.tt b/lib/generators/inertia_tw_templates/scaffold/templates/svelte/Edit.ts.svelte.tt
new file mode 100644
index 00000000..0be0468a
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/svelte/Edit.ts.svelte.tt
@@ -0,0 +1,45 @@
+
+
+
+ Editing <%= human_name.downcase %>
+
+
+
+
Editing <%= human_name.downcase %>
+
+ }
+ submitText="Update <%= human_name.downcase %>"
+ onSubmit={handleSubmit}
+ />
+
+ `}
+ class="mt-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium"
+ >
+ Show this <%= human_name.downcase %>
+
+
+ Back to <%= human_name.pluralize.downcase %>
+
+
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/svelte/Form.svelte.tt b/lib/generators/inertia_tw_templates/scaffold/templates/svelte/Form.svelte.tt
index 7059e11a..d57d459a 100644
--- a/lib/generators/inertia_tw_templates/scaffold/templates/svelte/Form.svelte.tt
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/svelte/Form.svelte.tt
@@ -1,6 +1,5 @@
+
+
+<% attributes.each do |attribute| -%>
+
+<% if attribute.password_digest? -%>
+
+
+ {#if $form.errors.password}
+
+ {$form.errors.password}
+
+ {/if}
+
+
+
+
+<% end -%>
+
+
+
+
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/svelte/Index.ts.svelte.tt b/lib/generators/inertia_tw_templates/scaffold/templates/svelte/Index.ts.svelte.tt
new file mode 100644
index 00000000..92981801
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/svelte/Index.ts.svelte.tt
@@ -0,0 +1,46 @@
+
+
+
+ <%= human_name.pluralize %>
+
+
+
+ {#if flash.notice}
+
+ {flash.notice}
+
+ {/if}
+
+
+
<%= human_name.pluralize %>
+
+ New <%= human_name.downcase %>
+
+
+
+
+ {#each <%= plural_table_name %> as <%= singular_table_name %> (<%= singular_table_name %>.id)}
+ <<%= inertia_component_name %> {<%= singular_table_name %>} />
+
+ `}
+ class="ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium"
+ >
+ Show this <%= human_name.downcase %>
+
+
+ {/each}
+
+
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/svelte/New.ts.svelte.tt b/lib/generators/inertia_tw_templates/scaffold/templates/svelte/New.ts.svelte.tt
new file mode 100644
index 00000000..ed52d0ab
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/svelte/New.ts.svelte.tt
@@ -0,0 +1,33 @@
+
+
+
+ New <%= human_name.downcase %>
+
+
+
+
New <%= human_name.downcase %>
+
+ }
+ submitText="Create <%= human_name.downcase %>"
+ onSubmit={handleSubmit}
+ />
+
+
+ Back to <%= human_name.pluralize.downcase %>
+
+
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/svelte/One.ts.svelte.tt b/lib/generators/inertia_tw_templates/scaffold/templates/svelte/One.ts.svelte.tt
new file mode 100644
index 00000000..f218ebdb
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/svelte/One.ts.svelte.tt
@@ -0,0 +1,30 @@
+
+
+
+<% attributes.reject(&:password_digest?).each do |attribute| -%>
+
+ <%= attribute.human_name %>:
+<% if attribute.attachment? -%>
+ {#if <%= singular_table_name %>.<%= attribute.column_name %>}
+ .<%= attribute.column_name %>.url}>
+ {<%= singular_table_name %>.<%= attribute.column_name %>.filename}
+
+ {/if}
+
+<% elsif attribute.attachments? -%>
+
+ {#each <%= singular_table_name %>.<%= attribute.column_name %> as { url, filename }}
+
+ {/each}
+<% else -%>
+ {<%= singular_table_name %>.<%= attribute.column_name %>}
+
+<% end -%>
+<% end -%>
+
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/svelte/Show.ts.svelte.tt b/lib/generators/inertia_tw_templates/scaffold/templates/svelte/Show.ts.svelte.tt
new file mode 100644
index 00000000..6a818b7f
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/svelte/Show.ts.svelte.tt
@@ -0,0 +1,61 @@
+
+
+
+ <%= human_name %> #{<%= singular_table_name %>.id}
+
+
+
+
+ {#if flash.notice}
+
+ {flash.notice}
+
+ {/if}
+
+
<%= human_name %> #{<%= singular_table_name %>.id}
+
+ <<%= inertia_component_name %> {<%= singular_table_name %>} />
+
+
`}
+ class="ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium"
+ >
+ Edit this <%= human_name.downcase %>
+
+
+ Back to <%= human_name.pluralize.downcase %>
+
+
+ `}
+ method="delete"
+ onclick={onDestroy}
+ class="mt-2 rounded-lg py-3 px-5 bg-gray-100 font-medium"
+ >
+ Destroy this <%= human_name.downcase %>
+
+
+
+
+
+
+
+
From 93ba2a616fb65e30ec7b236fc0308fcdfe460610 Mon Sep 17 00:00:00 2001
From: Svyatoslav Kryukov
Date: Wed, 13 Nov 2024 14:04:58 +0300
Subject: [PATCH 06/11] Add TypeScript support for Svelte 4 scaffolds
---
.../templates/svelte/Form.ts.svelte.tt | 4 +-
.../templates/svelte4/Edit.ts.svelte.tt | 38 +++++
.../scaffold/templates/svelte4/Form.svelte.tt | 4 +-
.../templates/svelte4/Form.ts.svelte.tt | 106 ++++++++++++++
.../templates/svelte4/Index.ts.svelte.tt | 37 +++++
.../templates/svelte4/New.ts.svelte.tt | 31 +++++
.../templates/svelte4/One.ts.svelte.tt | 30 ++++
.../templates/svelte4/Show.ts.svelte.tt | 47 +++++++
.../templates/svelte/Form.ts.svelte.tt | 4 +-
.../templates/svelte4/Edit.ts.svelte.tt | 46 +++++++
.../templates/svelte4/Form.ts.svelte.tt | 130 ++++++++++++++++++
.../templates/svelte4/Index.ts.svelte.tt | 44 ++++++
.../templates/svelte4/New.ts.svelte.tt | 34 +++++
.../templates/svelte4/One.ts.svelte.tt | 30 ++++
.../templates/svelte4/Show.ts.svelte.tt | 59 ++++++++
.../generators/controller_template_base.rb | 2 +-
16 files changed, 639 insertions(+), 7 deletions(-)
create mode 100644 lib/generators/inertia_templates/scaffold/templates/svelte4/Edit.ts.svelte.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/svelte4/Form.ts.svelte.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/svelte4/Index.ts.svelte.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/svelte4/New.ts.svelte.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/svelte4/One.ts.svelte.tt
create mode 100644 lib/generators/inertia_templates/scaffold/templates/svelte4/Show.ts.svelte.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/svelte4/Edit.ts.svelte.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/svelte4/Form.ts.svelte.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/svelte4/Index.ts.svelte.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/svelte4/New.ts.svelte.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/svelte4/One.ts.svelte.tt
create mode 100644 lib/generators/inertia_tw_templates/scaffold/templates/svelte4/Show.ts.svelte.tt
diff --git a/lib/generators/inertia_templates/scaffold/templates/svelte/Form.ts.svelte.tt b/lib/generators/inertia_templates/scaffold/templates/svelte/Form.ts.svelte.tt
index 592f0691..46d6790b 100644
--- a/lib/generators/inertia_templates/scaffold/templates/svelte/Form.ts.svelte.tt
+++ b/lib/generators/inertia_templates/scaffold/templates/svelte/Form.ts.svelte.tt
@@ -8,8 +8,8 @@
submitText: string
}>()
- const form = useForm({
-<% attributes.each do |attribute| -%>
+ const form = useForm<<%= inertia_model_form_type %>>({
+<% attributes.reject { |a| a.attachment? || a.attachments? }.each do |attribute| -%>
<% if attribute.password_digest? -%>
password: '',
password_confirmation: '',
diff --git a/lib/generators/inertia_templates/scaffold/templates/svelte4/Edit.ts.svelte.tt b/lib/generators/inertia_templates/scaffold/templates/svelte4/Edit.ts.svelte.tt
new file mode 100644
index 00000000..1bf8f975
--- /dev/null
+++ b/lib/generators/inertia_templates/scaffold/templates/svelte4/Edit.ts.svelte.tt
@@ -0,0 +1,38 @@
+
+
+
+ Editing <%= human_name.downcase %>
+
+
+Editing <%= human_name.downcase %>
+
+}
+ submitText="Update <%= human_name.downcase %>"
+ on:submit={handleSubmit}
+/>
+
+
+
+
+ `}>Show this <%= human_name.downcase %> |
+ Back to <%= human_name.pluralize.downcase %>
+
diff --git a/lib/generators/inertia_templates/scaffold/templates/svelte4/Form.svelte.tt b/lib/generators/inertia_templates/scaffold/templates/svelte4/Form.svelte.tt
index 8519c334..c777a83e 100644
--- a/lib/generators/inertia_templates/scaffold/templates/svelte4/Form.svelte.tt
+++ b/lib/generators/inertia_templates/scaffold/templates/svelte4/Form.svelte.tt
@@ -57,7 +57,7 @@
type="file"
name="<%= attribute.singular_name %>"
id="<%= attribute.singular_name %>"
- oninput={(e) => ($form.<%= attribute.column_name %> = e.target.files[0])}
+ on:input={(e) => ($form.<%= attribute.column_name %> = e.target.files[0])}
/>
<% elsif attribute.attachments? -%>
($form.<%= attribute.column_name %> = Array.from(e.target.files))}
+ on:input={(e) => ($form.<%= attribute.column_name %> = Array.from(e.target.files))}
/>
<% else -%>
+ import { useForm, type InertiaForm } from '@inertiajs/svelte'
+ import { createEventDispatcher } from 'svelte'
+ import type { <%= inertia_model_type %>, <%= inertia_model_form_type %> } from './types'
+
+ const dispatch = createEventDispatcher<{
+ submit: { form: InertiaForm<<%= inertia_model_form_type %>> }
+ }>()
+
+ export let <%= singular_table_name %>: <%= inertia_model_type %>
+ export let submitText: string
+
+<% if attributes.any? { |a| a.attachment? || a.attachments? } -%>
+ const filesFromEvent = (e: Event) => {
+ const target = e.target as HTMLInputElement
+ return Array.from(target.files || [])
+ }
+
+<% end -%>
+ const form = useForm<<%= inertia_model_form_type %>>({
+<% attributes.reject { |a| a.attachment? || a.attachments? }.each do |attribute| -%>
+<% if attribute.password_digest? -%>
+ password: '',
+ password_confirmation: '',
+<% else -%>
+ <%= attribute.column_name %>: <%= singular_table_name %>.<%= attribute.column_name %>,
+<% end -%>
+<% end -%>
+ })
+
+
+ dispatch('submit', { form: $form })}>
+<% attributes.each do |attribute| -%>
+<% if attribute.password_digest? -%>
+
+
+
+ {#if $form.errors.password}
+
{$form.errors.password}
+ {/if}
+
+
+
+
+
+ {#if $form.errors.password_confirmation}
+
{$form.errors.password_confirmation}
+ {/if}
+
+<% else -%>
+
+<% end -%>
+<% end -%>
+
+
+
+
+
+
diff --git a/lib/generators/inertia_templates/scaffold/templates/svelte4/Index.ts.svelte.tt b/lib/generators/inertia_templates/scaffold/templates/svelte4/Index.ts.svelte.tt
new file mode 100644
index 00000000..9b7590b5
--- /dev/null
+++ b/lib/generators/inertia_templates/scaffold/templates/svelte4/Index.ts.svelte.tt
@@ -0,0 +1,37 @@
+
+
+
+ <%= human_name.pluralize %>
+
+
+{#if flash.notice}
+ {flash.notice}
+{/if}
+
+<%= human_name.pluralize %>
+
+
+ {#each <%= plural_table_name %> as <%= singular_table_name %> (<%= singular_table_name %>.id)}
+
+ <<%= inertia_component_name %> {<%= singular_table_name %>} />
+
+ `}>Show this <%= human_name.downcase %>
+
+
+ {/each}
+
+
+New <%= human_name.downcase %>
+
+
diff --git a/lib/generators/inertia_templates/scaffold/templates/svelte4/New.ts.svelte.tt b/lib/generators/inertia_templates/scaffold/templates/svelte4/New.ts.svelte.tt
new file mode 100644
index 00000000..dcc7f054
--- /dev/null
+++ b/lib/generators/inertia_templates/scaffold/templates/svelte4/New.ts.svelte.tt
@@ -0,0 +1,31 @@
+
+
+
+ New <%= human_name.downcase %>
+
+
+New <%= human_name.downcase %>
+
+}
+ submitText="Create <%= human_name.downcase %>"
+ on:submit={handleSubmit}
+/>
+
+
+
+
+ Back to <%= human_name.pluralize.downcase %>
+
diff --git a/lib/generators/inertia_templates/scaffold/templates/svelte4/One.ts.svelte.tt b/lib/generators/inertia_templates/scaffold/templates/svelte4/One.ts.svelte.tt
new file mode 100644
index 00000000..1698c0c3
--- /dev/null
+++ b/lib/generators/inertia_templates/scaffold/templates/svelte4/One.ts.svelte.tt
@@ -0,0 +1,30 @@
+
+
+
+<% attributes.reject(&:password_digest?).each do |attribute| -%>
+
+ <%= attribute.human_name %>:
+<% if attribute.attachment? -%>
+ {#if <%= singular_table_name %>.<%= attribute.column_name %>}
+ .<%= attribute.column_name %>.url}>
+ {<%= singular_table_name %>.<%= attribute.column_name %>.filename}
+
+ {/if}
+
+<% elsif attribute.attachments? -%>
+
+ {#each <%= singular_table_name %>.<%= attribute.column_name %> as { url, filename }}
+
+ {/each}
+<% else -%>
+ {<%= singular_table_name %>.<%= attribute.column_name %>}
+
+<% end -%>
+<% end -%>
+
diff --git a/lib/generators/inertia_templates/scaffold/templates/svelte4/Show.ts.svelte.tt b/lib/generators/inertia_templates/scaffold/templates/svelte4/Show.ts.svelte.tt
new file mode 100644
index 00000000..f69b780f
--- /dev/null
+++ b/lib/generators/inertia_templates/scaffold/templates/svelte4/Show.ts.svelte.tt
@@ -0,0 +1,47 @@
+
+
+
+ <%= human_name %> #{<%= singular_table_name %>.id}
+
+
+{#if flash.notice}
+ {flash.notice}
+{/if}
+
+<%= human_name %> #{<%= singular_table_name %>.id}
+
+<<%= inertia_component_name %> {<%= singular_table_name %>} />
+
+
+ `}>Edit this <%= human_name.downcase %> |
+ Back to <%= human_name.pluralize.downcase %>
+
+
+
+
+
+
+
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/svelte/Form.ts.svelte.tt b/lib/generators/inertia_tw_templates/scaffold/templates/svelte/Form.ts.svelte.tt
index 2d8efd85..01185132 100644
--- a/lib/generators/inertia_tw_templates/scaffold/templates/svelte/Form.ts.svelte.tt
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/svelte/Form.ts.svelte.tt
@@ -8,8 +8,8 @@
submitText: string
}>()
- const form = useForm({
-<% attributes.each do |attribute| -%>
+ const form = useForm<<%= inertia_model_form_type %>>({
+<% attributes.reject { |a| a.attachment? || a.attachments? }.each do |attribute| -%>
<% if attribute.password_digest? -%>
password: '',
password_confirmation: '',
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/Edit.ts.svelte.tt b/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/Edit.ts.svelte.tt
new file mode 100644
index 00000000..a78d0d81
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/Edit.ts.svelte.tt
@@ -0,0 +1,46 @@
+
+
+
+ Editing <%= human_name.downcase %>
+
+
+
+
Editing <%= human_name.downcase %>
+
+ }
+ submitText="Update <%= human_name.downcase %>"
+ on:submit={handleSubmit}
+ />
+
+ `}
+ class="mt-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium"
+ >
+ Show this <%= human_name.downcase %>
+
+
+ Back to <%= human_name.pluralize.downcase %>
+
+
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/Form.ts.svelte.tt b/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/Form.ts.svelte.tt
new file mode 100644
index 00000000..bca1dc62
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/Form.ts.svelte.tt
@@ -0,0 +1,130 @@
+
+
+ dispatch('submit', { form: $form })}
+>
+<% attributes.each do |attribute| -%>
+
+<% if attribute.password_digest? -%>
+
+
+ {#if $form.errors.password}
+
+ {$form.errors.password}
+
+ {/if}
+
+
+
+
+<% end -%>
+
+
+
+
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/Index.ts.svelte.tt b/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/Index.ts.svelte.tt
new file mode 100644
index 00000000..a9a55c20
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/Index.ts.svelte.tt
@@ -0,0 +1,44 @@
+
+
+
+ <%= human_name.pluralize %>
+
+
+
+ {#if flash.notice}
+
+ {flash.notice}
+
+ {/if}
+
+
+
<%= human_name.pluralize %>
+
+ New <%= human_name.downcase %>
+
+
+
+
+ {#each <%= plural_table_name %> as <%= singular_table_name %> (<%= singular_table_name %>.id)}
+ <<%= inertia_component_name %> {<%= singular_table_name %>} />
+
+ `}
+ class="ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium"
+ >
+ Show this <%= human_name.downcase %>
+
+
+ {/each}
+
+
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/New.ts.svelte.tt b/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/New.ts.svelte.tt
new file mode 100644
index 00000000..736140f5
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/New.ts.svelte.tt
@@ -0,0 +1,34 @@
+
+
+
+ New <%= human_name.downcase %>
+
+
+
+
New <%= human_name.downcase %>
+
+ }
+ submitText="Create <%= human_name.downcase %>"
+ on:submit={handleSubmit}
+ />
+
+
+ Back to <%= human_name.pluralize.downcase %>
+
+
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/One.ts.svelte.tt b/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/One.ts.svelte.tt
new file mode 100644
index 00000000..4bd7485e
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/One.ts.svelte.tt
@@ -0,0 +1,30 @@
+
+
+
+<% attributes.reject(&:password_digest?).each do |attribute| -%>
+
+ <%= attribute.human_name %>:
+<% if attribute.attachment? -%>
+ {#if <%= singular_table_name %>.<%= attribute.column_name %>}
+ .<%= attribute.column_name %>.url}>
+ {<%= singular_table_name %>.<%= attribute.column_name %>.filename}
+
+ {/if}
+
+<% elsif attribute.attachments? -%>
+
+ {#each <%= singular_table_name %>.<%= attribute.column_name %> as { url, filename }}
+
+ {/each}
+<% else -%>
+ {<%= singular_table_name %>.<%= attribute.column_name %>}
+
+<% end -%>
+<% end -%>
+
diff --git a/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/Show.ts.svelte.tt b/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/Show.ts.svelte.tt
new file mode 100644
index 00000000..0d50f9de
--- /dev/null
+++ b/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/Show.ts.svelte.tt
@@ -0,0 +1,59 @@
+
+
+
+ <%= human_name %> #{<%= singular_table_name %>.id}
+
+
+
+
+ {#if flash.notice}
+
+ {flash.notice}
+
+ {/if}
+
+
<%= human_name %> #{<%= singular_table_name %>.id}
+
+ <<%= inertia_component_name %> {<%= singular_table_name %>} />
+
+
`}
+ class="ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium"
+ >
+ Edit this <%= human_name.downcase %>
+
+
+ Back to <%= human_name.pluralize.downcase %>
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/inertia_rails/generators/controller_template_base.rb b/lib/inertia_rails/generators/controller_template_base.rb
index fe0b7447..75d261b5 100644
--- a/lib/inertia_rails/generators/controller_template_base.rb
+++ b/lib/inertia_rails/generators/controller_template_base.rb
@@ -49,7 +49,7 @@ def extension
case options.frontend_framework
when 'react' then typescript? ? 'tsx' : 'jsx'
when 'vue' then 'vue'
- when 'svelte' then 'svelte'
+ when 'svelte', 'svelte4' then 'svelte'
else
raise ArgumentError, "Unknown frontend framework: #{options.frontend_framework}"
end
From fe81d04c104a6ca2b1e0dad1cfc56f5040b1fc96 Mon Sep 17 00:00:00 2001
From: Svyatoslav Kryukov
Date: Wed, 20 Nov 2024 21:56:36 +0300
Subject: [PATCH 07/11] Drop onDestroy alert to align with Rails scaffolds
---
.../scaffold/templates/react/Show.jsx.tt | 7 -------
.../scaffold/templates/react/Show.tsx.tt | 7 -------
.../scaffold/templates/svelte/Show.svelte.tt | 8 +-------
.../scaffold/templates/svelte/Show.ts.svelte.tt | 8 +-------
.../scaffold/templates/svelte4/Show.svelte.tt | 7 -------
.../scaffold/templates/svelte4/Show.ts.svelte.tt | 7 -------
.../scaffold/templates/vue/Show.ts.vue.tt | 7 -------
.../inertia_templates/scaffold/templates/vue/Show.vue.tt | 7 -------
.../scaffold/templates/react/Show.jsx.tt | 7 -------
.../scaffold/templates/react/Show.tsx.tt | 7 -------
.../scaffold/templates/svelte/Show.svelte.tt | 7 -------
.../scaffold/templates/svelte/Show.ts.svelte.tt | 7 -------
.../scaffold/templates/svelte4/Show.svelte.tt | 7 -------
.../scaffold/templates/svelte4/Show.ts.svelte.tt | 7 -------
.../scaffold/templates/vue/Show.ts.vue.tt | 7 -------
.../scaffold/templates/vue/Show.vue.tt | 7 -------
16 files changed, 2 insertions(+), 112 deletions(-)
diff --git a/lib/generators/inertia_templates/scaffold/templates/react/Show.jsx.tt b/lib/generators/inertia_templates/scaffold/templates/react/Show.jsx.tt
index 3128bc0b..bd207302 100644
--- a/lib/generators/inertia_templates/scaffold/templates/react/Show.jsx.tt
+++ b/lib/generators/inertia_templates/scaffold/templates/react/Show.jsx.tt
@@ -2,12 +2,6 @@ import { Link, Head } from '@inertiajs/react'
import <%= inertia_component_name %> from './<%= inertia_component_name %>'
export default function Show({ <%= singular_table_name %>, flash }) {
- const onDestroy = (e) => {
- if (!confirm('Are you sure you want to delete this <%= human_name.downcase %>?')) {
- e.preventDefault()
- }
- }
-
return (
<>
#${<%= singular_table_name %>.id}`} />
@@ -27,7 +21,6 @@ export default function Show({ <%= singular_table_name %>, flash }) {
`}
- onClick={onDestroy}
as="button"
method="delete"
>
diff --git a/lib/generators/inertia_templates/scaffold/templates/react/Show.tsx.tt b/lib/generators/inertia_templates/scaffold/templates/react/Show.tsx.tt
index 82be7eaa..cdb7ed05 100644
--- a/lib/generators/inertia_templates/scaffold/templates/react/Show.tsx.tt
+++ b/lib/generators/inertia_templates/scaffold/templates/react/Show.tsx.tt
@@ -9,12 +9,6 @@ interface ShowProps {
}
export default function Show({ <%= singular_table_name %>, flash }: ShowProps) {
- const onDestroy = (e: MouseEvent) => {
- if (!confirm('Are you sure you want to delete this <%= human_name.downcase %>?')) {
- e.preventDefault()
- }
- }
-
return (
<>
#${<%= singular_table_name %>.id}`} />
@@ -34,7 +28,6 @@ export default function Show({ <%= singular_table_name %>, flash }: ShowProps) {
`}
- onClick={onDestroy}
as="button"
method="delete"
>
diff --git a/lib/generators/inertia_templates/scaffold/templates/svelte/Show.svelte.tt b/lib/generators/inertia_templates/scaffold/templates/svelte/Show.svelte.tt
index 065a0587..97c244b4 100644
--- a/lib/generators/inertia_templates/scaffold/templates/svelte/Show.svelte.tt
+++ b/lib/generators/inertia_templates/scaffold/templates/svelte/Show.svelte.tt
@@ -3,12 +3,6 @@
import <%= inertia_component_name %> from './<%= inertia_component_name %>.svelte'
let { <%= singular_table_name %>, flash } = $props()
-
- const onDestroy = (e) => {
- if (!confirm('Are you sure you want to delete this <%= human_name.downcase %>?')) {
- e.preventDefault()
- }
- }
@@ -29,7 +23,7 @@
- `} method="delete" onclick={onDestroy}>
+ `} method="delete">
Destroy this <%= human_name.downcase %>
diff --git a/lib/generators/inertia_templates/scaffold/templates/svelte/Show.ts.svelte.tt b/lib/generators/inertia_templates/scaffold/templates/svelte/Show.ts.svelte.tt
index 12bcd88c..360da3e4 100644
--- a/lib/generators/inertia_templates/scaffold/templates/svelte/Show.ts.svelte.tt
+++ b/lib/generators/inertia_templates/scaffold/templates/svelte/Show.ts.svelte.tt
@@ -7,12 +7,6 @@
<%= singular_table_name %>: <%= inertia_model_type %>
flash: { notice?: string }
}>()
-
- const onDestroy = (e: MouseEvent) => {
- if (!confirm('Are you sure you want to delete this <%= human_name.downcase %>?')) {
- e.preventDefault()
- }
- }
@@ -33,7 +27,7 @@
- `} method="delete" onclick={onDestroy}>
+ `} method="delete">
Destroy this <%= human_name.downcase %>
diff --git a/lib/generators/inertia_templates/scaffold/templates/svelte4/Show.svelte.tt b/lib/generators/inertia_templates/scaffold/templates/svelte4/Show.svelte.tt
index c1653236..fc57c990 100644
--- a/lib/generators/inertia_templates/scaffold/templates/svelte4/Show.svelte.tt
+++ b/lib/generators/inertia_templates/scaffold/templates/svelte4/Show.svelte.tt
@@ -4,12 +4,6 @@
export let <%= singular_table_name %>
export let flash
-
- const onDestroy = (e) => {
- if (!confirm('Are you sure you want to delete this <%= human_name.downcase %>?')) {
- e.preventDefault()
- }
- }
@@ -32,7 +26,6 @@