turbo_desktop-rails 0.1.1 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +34 -0
- data/README.md +30 -3
- data/app/controllers/turbo_desktop/inspector_assets_controller.rb +6 -0
- data/lib/generators/turbo_desktop/install/templates/initializer.rb.tt +11 -0
- data/lib/turbo_desktop/configuration.rb +5 -1
- data/lib/turbo_desktop/detection.rb +38 -0
- data/lib/turbo_desktop/version.rb +1 -1
- data/lib/turbo_desktop/view_helpers.rb +19 -1
- metadata +5 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 70be4836df6cf6ff273081949ad0ee0c42bf155357525f73467d47000d18dfe0
|
|
4
|
+
data.tar.gz: 67f724b78eb69afa13d18bcf7844c0e63d56c2a6b9fdd3738f0e7a7466c72135
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6b136e03d0f7d1b15abfc88b322139abbfd5575f5a3ac6e0353b38223773b083eb9dbc3d7eb139811b9b2a92cbff40fc3dede0e577e3eeef6ba942f747f78968
|
|
7
|
+
data.tar.gz: 4c536312a7cfe78b51897f70a8117f3fa134dca8be0759add4ec65280af2d7326974cd7b8398fc78eabd21e280d97f26862f162a92d294f5075b09242ef45ade
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,39 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.3 (2026-09-27)
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- The Dev Inspector now loads in apps with forgery protection on, which is
|
|
8
|
+
every app that uses `load_defaults`. Its modules are fetched with `import()`,
|
|
9
|
+
a plain GET for JavaScript, which Rails refused with a 422 as a cross-origin
|
|
10
|
+
script embed. The inspector's controller serves a fixed list of public,
|
|
11
|
+
static files and no longer takes part in that check.
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- The README shows the Gemfile line pinned (`"~> 0.2"`), states Ruby >= 3.2 to
|
|
16
|
+
match the gemspec, and quotes a current User-Agent.
|
|
17
|
+
|
|
18
|
+
## 0.2.2 (2026-09-27)
|
|
19
|
+
|
|
20
|
+
Version aligned with the desktop shell's 0.2.2 release. The CLI now scaffolds
|
|
21
|
+
new apps with `gem "turbo_desktop-rails", "~> 0.2"`; it previously wrote
|
|
22
|
+
`"~> 0.1"`, which resolved to 0.1.1. First 0.2.x version published to RubyGems.
|
|
23
|
+
No gem-side API changes.
|
|
24
|
+
|
|
25
|
+
## 0.2.1 (2026-07-29)
|
|
26
|
+
|
|
27
|
+
Version aligned with the desktop shell's 0.2.1 release, which fixes bridge
|
|
28
|
+
events (shell/sudo output streaming, drag & drop, component onReceive) never
|
|
29
|
+
reaching pages loaded from the app server. No gem-side API changes.
|
|
30
|
+
|
|
31
|
+
## 0.2.0 (2026-07-29)
|
|
32
|
+
|
|
33
|
+
Version aligned with the desktop shell's 0.2.0 release (server auto-start,
|
|
34
|
+
Windows support, cross-platform sudo, drag & drop, file associations,
|
|
35
|
+
clipboard, launch-at-login). No gem-side API changes.
|
|
36
|
+
|
|
3
37
|
## 0.1.1 (2026-07-27)
|
|
4
38
|
|
|
5
39
|
### Added
|
data/README.md
CHANGED
|
@@ -9,7 +9,7 @@ This gem gives your Rails app awareness of the Turbo Desktop shell, exactly like
|
|
|
9
9
|
Add to your Gemfile:
|
|
10
10
|
|
|
11
11
|
```ruby
|
|
12
|
-
gem "turbo_desktop-rails"
|
|
12
|
+
gem "turbo_desktop-rails", "~> 0.2"
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
Then run:
|
|
@@ -23,7 +23,7 @@ rails generate turbo_desktop:install
|
|
|
23
23
|
|
|
24
24
|
### Detection
|
|
25
25
|
|
|
26
|
-
The gem detects Turbo Desktop requests via the User-Agent header (`Turbo Desktop/0.
|
|
26
|
+
The gem detects Turbo Desktop requests via the User-Agent header (`Turbo Desktop/0.2.3 (macOS; aarch64)`).
|
|
27
27
|
|
|
28
28
|
```ruby
|
|
29
29
|
# In controllers
|
|
@@ -56,6 +56,33 @@ turbo_desktop_arch # => "aarch64", "x86_64", or nil
|
|
|
56
56
|
) %>
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
+
### Desktop-only templates
|
|
60
|
+
|
|
61
|
+
Requests from the desktop app are marked with a Rails variant, so a whole
|
|
62
|
+
template can be written for it rather than branching inside a shared one:
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
app/views/orders/show.html.erb # everyone
|
|
66
|
+
app/views/orders/show.html+desktop.erb # the desktop app
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Layouts work the same way — `app/views/layouts/application.html+desktop.erb`.
|
|
70
|
+
Rails falls back to the plain template wherever no variant exists, so this costs
|
|
71
|
+
nothing until you add one.
|
|
72
|
+
|
|
73
|
+
The block helpers above are still the right tool for a button or a nav bar. Reach
|
|
74
|
+
for a variant when the whole page differs.
|
|
75
|
+
|
|
76
|
+
Rename it, or turn it off, in the initializer:
|
|
77
|
+
|
|
78
|
+
```ruby
|
|
79
|
+
TurboDesktop.configure do |config|
|
|
80
|
+
config.variant = :desktop # nil leaves variants alone
|
|
81
|
+
end
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
It is added to any variants you have already set rather than replacing them.
|
|
85
|
+
|
|
59
86
|
### Path Configuration
|
|
60
87
|
|
|
61
88
|
The gem mounts a path configuration endpoint at `/turbo-desktop/path-configuration.json`:
|
|
@@ -76,7 +103,7 @@ end
|
|
|
76
103
|
|
|
77
104
|
## Requirements
|
|
78
105
|
|
|
79
|
-
- Ruby >= 3.
|
|
106
|
+
- Ruby >= 3.2
|
|
80
107
|
- Rails >= 7.0
|
|
81
108
|
- turbo-rails >= 1.0
|
|
82
109
|
|
|
@@ -10,6 +10,12 @@ module TurboDesktop
|
|
|
10
10
|
# path traversal). Enabled implicitly by mounting the engine; the meta-tag
|
|
11
11
|
# helper points the shell at these URLs.
|
|
12
12
|
class InspectorAssetsController < ActionController::Base
|
|
13
|
+
# These are public, static modules fetched by import(), which is a plain
|
|
14
|
+
# GET for JavaScript. Rails reads that as a cross-origin <script> embed and
|
|
15
|
+
# refuses it with a 422. Nothing here depends on the session or carries
|
|
16
|
+
# per-user data, so there is nothing for that check to protect.
|
|
17
|
+
skip_forgery_protection
|
|
18
|
+
|
|
13
19
|
ASSET_ROOT = TurboDesktop::Engine.root.join("lib/turbo_desktop/inspector_assets").freeze
|
|
14
20
|
|
|
15
21
|
# Relative paths (as requested by the browser) → allowed. Anything else 404s.
|
|
@@ -17,6 +17,17 @@ TurboDesktop.configure do |config|
|
|
|
17
17
|
# presentation. Enable it in development only:
|
|
18
18
|
config.inspector_enabled = Rails.env.development?
|
|
19
19
|
|
|
20
|
+
# Requests from the desktop app are marked with a Rails variant, so you can
|
|
21
|
+
# write a whole template for it instead of branching inside a shared one:
|
|
22
|
+
#
|
|
23
|
+
# app/views/orders/show.html.erb # everyone
|
|
24
|
+
# app/views/orders/show.html+desktop.erb # the desktop app
|
|
25
|
+
#
|
|
26
|
+
# Layouts work the same way (layouts/application.html+desktop.erb), and Rails
|
|
27
|
+
# falls back to the plain template wherever no variant exists. Rename it, or
|
|
28
|
+
# set it to nil to leave variants alone.
|
|
29
|
+
# config.variant = :desktop
|
|
30
|
+
|
|
20
31
|
config.path_configuration = {
|
|
21
32
|
settings: {
|
|
22
33
|
screenshots_enabled: false
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
module TurboDesktop
|
|
2
2
|
class Configuration
|
|
3
|
-
attr_accessor :path_configuration, :user_agent_pattern, :inspector_enabled,
|
|
3
|
+
attr_accessor :path_configuration, :user_agent_pattern, :inspector_enabled,
|
|
4
|
+
:inspector_mount_path, :variant
|
|
4
5
|
|
|
5
6
|
def initialize
|
|
6
7
|
@path_configuration = default_path_configuration
|
|
7
8
|
@user_agent_pattern = /Turbo Desktop/
|
|
8
9
|
@inspector_enabled = false
|
|
10
|
+
# Rails variant set on requests from the desktop app, so views can be
|
|
11
|
+
# written as show.html+desktop.erb. Set to nil to leave variants alone.
|
|
12
|
+
@variant = :desktop
|
|
9
13
|
# Where the engine is mounted; the inspector meta tag advertises assets
|
|
10
14
|
# under this prefix. Override if you mount the engine elsewhere.
|
|
11
15
|
@inspector_mount_path = "/turbo-desktop"
|
|
@@ -11,6 +11,23 @@ module TurboDesktop
|
|
|
11
11
|
|
|
12
12
|
included do
|
|
13
13
|
helper_method :turbo_desktop_app?, :turbo_desktop_platform, :turbo_desktop_arch
|
|
14
|
+
|
|
15
|
+
before_action :set_turbo_desktop_variant
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# The variant list a request should end up with, or nil to leave it alone.
|
|
19
|
+
#
|
|
20
|
+
# Kept separate from the controller so the decision can be exercised on its
|
|
21
|
+
# own. Adds to whatever variants are already set rather than replacing them:
|
|
22
|
+
# an app may well be using variants for something else.
|
|
23
|
+
def self.variant_for(current:, desktop:, configured:)
|
|
24
|
+
return nil if configured.blank? || !desktop
|
|
25
|
+
|
|
26
|
+
current = Array(current).map(&:to_sym)
|
|
27
|
+
configured = configured.to_sym
|
|
28
|
+
return nil if current.include?(configured)
|
|
29
|
+
|
|
30
|
+
current + [ configured ]
|
|
14
31
|
end
|
|
15
32
|
|
|
16
33
|
# Returns true if the request is from a Turbo Desktop app.
|
|
@@ -31,6 +48,27 @@ module TurboDesktop
|
|
|
31
48
|
end
|
|
32
49
|
end
|
|
33
50
|
|
|
51
|
+
# Mark desktop requests with a Rails variant, so a whole template can be
|
|
52
|
+
# written for the desktop app instead of branching inside a shared one:
|
|
53
|
+
#
|
|
54
|
+
# app/views/orders/show.html.erb # everyone
|
|
55
|
+
# app/views/orders/show.html+desktop.erb # the desktop app
|
|
56
|
+
#
|
|
57
|
+
# Layouts pick it up too — layouts/application.html+desktop.erb. Rails falls
|
|
58
|
+
# back to the plain template wherever no variant exists, so this costs
|
|
59
|
+
# nothing until you add one.
|
|
60
|
+
#
|
|
61
|
+
# Set config.variant to nil to turn it off.
|
|
62
|
+
def set_turbo_desktop_variant
|
|
63
|
+
variant = TurboDesktop::Detection.variant_for(
|
|
64
|
+
current: request.variant,
|
|
65
|
+
desktop: turbo_desktop_app?,
|
|
66
|
+
configured: TurboDesktop.configuration.variant
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
request.variant = variant if variant
|
|
70
|
+
end
|
|
71
|
+
|
|
34
72
|
# Returns the architecture: "aarch64", "x86_64", or nil.
|
|
35
73
|
def turbo_desktop_arch
|
|
36
74
|
return nil unless turbo_desktop_app?
|
|
@@ -26,12 +26,20 @@ module TurboDesktop
|
|
|
26
26
|
end
|
|
27
27
|
end
|
|
28
28
|
|
|
29
|
+
# Attribute name fragments we are willing to build a data-* attribute from.
|
|
30
|
+
# Values are escaped by the tag helpers, but names are interpolated, so they
|
|
31
|
+
# are restricted rather than escaped.
|
|
32
|
+
BRIDGE_NAME_PATTERN = /\A[a-zA-Z0-9_-]+\z/
|
|
33
|
+
|
|
29
34
|
# Renders a bridge component data attribute.
|
|
30
35
|
#
|
|
31
36
|
# <%= tag.button "Export", **turbo_desktop_bridge("menu-item", title: "Export PDF", shortcut: "Cmd+E") %>
|
|
32
37
|
def turbo_desktop_bridge(component, **options)
|
|
33
|
-
|
|
38
|
+
validate_bridge_name!(component, "component")
|
|
39
|
+
|
|
40
|
+
attrs = { "data-turbo-desktop-bridge" => component.to_s }
|
|
34
41
|
options.each do |key, value|
|
|
42
|
+
validate_bridge_name!(key, "option name")
|
|
35
43
|
attrs["data-turbo-desktop-bridge-#{key}"] = value.to_s
|
|
36
44
|
end
|
|
37
45
|
attrs
|
|
@@ -73,5 +81,15 @@ module TurboDesktop
|
|
|
73
81
|
def turbo_desktop_inspector_url
|
|
74
82
|
"#{TurboDesktop.configuration.inspector_mount_path.chomp("/")}/inspector.js"
|
|
75
83
|
end
|
|
84
|
+
|
|
85
|
+
private
|
|
86
|
+
|
|
87
|
+
def validate_bridge_name!(name, label)
|
|
88
|
+
return if name.to_s.match?(BRIDGE_NAME_PATTERN)
|
|
89
|
+
|
|
90
|
+
raise ArgumentError,
|
|
91
|
+
"turbo_desktop_bridge #{label} #{name.inspect} may only contain " \
|
|
92
|
+
"letters, numbers, hyphens and underscores"
|
|
93
|
+
end
|
|
76
94
|
end
|
|
77
95
|
end
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: turbo_desktop-rails
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
|
-
-
|
|
7
|
+
- aguspe
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date:
|
|
10
|
+
date: 2026-09-27 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: rails
|
|
@@ -80,14 +80,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
80
80
|
requirements:
|
|
81
81
|
- - ">="
|
|
82
82
|
- !ruby/object:Gem::Version
|
|
83
|
-
version: 3.
|
|
83
|
+
version: 3.2.0
|
|
84
84
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
85
85
|
requirements:
|
|
86
86
|
- - ">="
|
|
87
87
|
- !ruby/object:Gem::Version
|
|
88
88
|
version: '0'
|
|
89
89
|
requirements: []
|
|
90
|
-
rubygems_version:
|
|
90
|
+
rubygems_version: 3.6.2
|
|
91
91
|
specification_version: 4
|
|
92
92
|
summary: Turbo Native for Desktop — Rails integration
|
|
93
93
|
test_files: []
|