ruby_everywhere 0.12.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +35 -33
- data/bridge/README.md +23 -23
- data/lib/everywhere/android_resources.rb +9 -9
- data/lib/everywhere/android_sdk.rb +9 -9
- data/lib/everywhere/asset_catalog.rb +7 -7
- data/lib/everywhere/blake2b.rb +1 -1
- data/lib/everywhere/boot.rb +1 -1
- data/lib/everywhere/builders/android.rb +25 -25
- data/lib/everywhere/builders/desktop.rb +6 -6
- data/lib/everywhere/builders/ios.rb +14 -14
- data/lib/everywhere/builders/native_sources.rb +1 -1
- data/lib/everywhere/child_supervision.rb +1 -1
- data/lib/everywhere/commands/build.rb +54 -24
- data/lib/everywhere/commands/clean.rb +1 -1
- data/lib/everywhere/commands/dev.rb +11 -11
- data/lib/everywhere/commands/doctor.rb +7 -7
- data/lib/everywhere/commands/icon.rb +2 -2
- data/lib/everywhere/commands/install.rb +21 -21
- data/lib/everywhere/commands/logs.rb +6 -6
- data/lib/everywhere/commands/platform/auth_status.rb +3 -3
- data/lib/everywhere/commands/platform/build.rb +7 -7
- data/lib/everywhere/commands/platform/login.rb +5 -5
- data/lib/everywhere/commands/platform/logout.rb +1 -1
- data/lib/everywhere/commands/platform/runner.rb +6 -6
- data/lib/everywhere/commands/preview.rb +14 -14
- data/lib/everywhere/commands/publish.rb +14 -14
- data/lib/everywhere/commands/release.rb +13 -9
- data/lib/everywhere/commands/updates_keygen.rb +4 -4
- data/lib/everywhere/config/app.rb +3 -3
- data/lib/everywhere/config/mobile.rb +2 -2
- data/lib/everywhere/config/native_desktop.rb +2 -2
- data/lib/everywhere/config/native_mobile.rb +3 -3
- data/lib/everywhere/config/updates.rb +11 -1
- data/lib/everywhere/database.rb +3 -3
- data/lib/everywhere/desktop_assets.rb +5 -5
- data/lib/everywhere/desktop_dev_app.rb +1 -1
- data/lib/everywhere/emulator.rb +5 -5
- data/lib/everywhere/log_filter.rb +1 -1
- data/lib/everywhere/omniauth.rb +1 -1
- data/lib/everywhere/paths.rb +1 -1
- data/lib/everywhere/platform/credentials.rb +1 -1
- data/lib/everywhere/request_context.rb +2 -2
- data/lib/everywhere/shellout.rb +2 -2
- data/lib/everywhere/simulator.rb +1 -1
- data/lib/everywhere/tab_filter.rb +2 -2
- data/lib/everywhere/version.rb +1 -1
- data/support/agents/AGENTS.md +7 -7
- data/support/agents/frameworks/hanami-views.md +8 -8
- data/support/agents/frameworks/hanami.md +2 -2
- data/support/agents/frameworks/rails-views.md +7 -7
- data/support/agents/frameworks/rails.md +8 -8
- data/support/agents/frameworks/sinatra-views.md +7 -7
- data/support/agents/frameworks/sinatra.md +2 -2
- data/support/agents/modes/local.md +2 -2
- data/support/agents/modes/remote.md +2 -2
- data/support/desktop/src-tauri/src/updater.rs +1 -1
- metadata +1 -1
|
@@ -33,7 +33,7 @@ module Everywhere
|
|
|
33
33
|
# rebuild, no app-store release. Wrap the registration in `to_prepare` so a
|
|
34
34
|
# reload in development doesn't leave the block closed over stale constants.
|
|
35
35
|
def tabs(&block)
|
|
36
|
-
raise ArgumentError, "Everywhere.tabs needs a block
|
|
36
|
+
raise ArgumentError, "Everywhere.tabs needs a block: Everywhere.tabs { |tabs, ctx| … }" unless block
|
|
37
37
|
|
|
38
38
|
@tabs_filter = block
|
|
39
39
|
end
|
|
@@ -68,7 +68,7 @@ module Everywhere
|
|
|
68
68
|
# Return nil for a signed-out request. Runs at most once per request.
|
|
69
69
|
def current_user(&block)
|
|
70
70
|
unless block
|
|
71
|
-
raise ArgumentError, "Everywhere.current_user needs a block
|
|
71
|
+
raise ArgumentError, "Everywhere.current_user needs a block. It registers the resolver " \
|
|
72
72
|
"(ask a RequestContext for the user itself: ctx.current_user)"
|
|
73
73
|
end
|
|
74
74
|
|
data/lib/everywhere/version.rb
CHANGED
data/support/agents/AGENTS.md
CHANGED
|
@@ -6,7 +6,7 @@ shells are Hotwire Native, and all three are driven from one config file
|
|
|
6
6
|
(`config/everywhere.yml`), one CLI (`every`, aliased `rbe`), and one JavaScript API
|
|
7
7
|
(`Everywhere`) with server-side helpers to match.
|
|
8
8
|
|
|
9
|
-
**The web app is the source of truth.** You do not edit the shells
|
|
9
|
+
**The web app is the source of truth.** You do not edit the shells. You edit the app, its
|
|
10
10
|
views, and the config. Full docs: <https://rubyeverywhere.com/docs>.
|
|
11
11
|
|
|
12
12
|
### How this app reaches its users: {{MODE}} mode
|
|
@@ -32,7 +32,7 @@ Things that bite:
|
|
|
32
32
|
the sentence iOS shows when asking, or the build fails.
|
|
33
33
|
- **`tabs:` and `rules:` deploy with the web app.** They're baked into the bundle *and* served
|
|
34
34
|
live from `/everywhere/ios_v1.json` and `/everywhere/android_v1.json`, so changing a tab or a
|
|
35
|
-
presentation rule ships with your next deploy
|
|
35
|
+
presentation rule ships with your next deploy. No app-store release.
|
|
36
36
|
- Most other keys (`window`, `menu`, `tray`, `permissions`, `appearance`) are read at build
|
|
37
37
|
time and do need a new build.
|
|
38
38
|
|
|
@@ -53,7 +53,7 @@ namespaces `auth`, `clipboard`, `haptics`, `permissions`, `biometrics`, `instanc
|
|
|
53
53
|
and `updates` (`check`/`install`/`setChannel`/`on`).
|
|
54
54
|
|
|
55
55
|
Reach for the bridge when something has to happen in response to JS. For anything you can
|
|
56
|
-
render, prefer the markup above
|
|
56
|
+
render, prefer the markup above: it's CSP-safe, correct on first paint, and works in a
|
|
57
57
|
browser without a code path of its own.
|
|
58
58
|
|
|
59
59
|
### Commands
|
|
@@ -64,24 +64,24 @@ Run these from the app root.
|
|
|
64
64
|
| --- | --- |
|
|
65
65
|
| `every dev` | Dev server plus native shells on demand, live reload (`--desktop --ios --android --mobile --browser`) |
|
|
66
66
|
| `every doctor` | Check the toolchain before a first build |
|
|
67
|
-
| `every build` | Build the native shells
|
|
67
|
+
| `every build` | Build the native shells: desktop, or `--ios` / `--android` |
|
|
68
68
|
| `every logs` | Stream shell logs from the iOS Simulator or an Android device |
|
|
69
69
|
| `every icon` | Generate `.icns` / `.ico` / Linux icons from a source PNG |
|
|
70
70
|
| `every release` | Sign, notarize, staple, and emit `dist/release.json` |
|
|
71
71
|
| `every publish` | Publish a release to the app's update bucket |
|
|
72
72
|
| `every clean` | Remove the shell build caches |
|
|
73
73
|
|
|
74
|
-
`every dev` never packages anything
|
|
74
|
+
`every dev` never packages anything: it runs the ordinary dev server and points the shells
|
|
75
75
|
at it, so the edit-refresh loop is unchanged.
|
|
76
76
|
|
|
77
77
|
Two directories are build output, never source: `dist/` (artifacts) and `~/.rubyeverywhere`
|
|
78
|
-
(stamped shell projects and caches). Don't commit them, don't hand-edit them
|
|
78
|
+
(stamped shell projects and caches). Don't commit them, don't hand-edit them; the next build
|
|
79
79
|
overwrites both.
|
|
80
80
|
|
|
81
81
|
### Config `every install` touched
|
|
82
82
|
|
|
83
83
|
These exist so this codebase can also be compiled and shipped on-device, and several of them
|
|
84
|
-
look like mistakes if you don't know that. Leave them in place
|
|
84
|
+
look like mistakes if you don't know that. Leave them in place; full rationale at
|
|
85
85
|
<https://rubyeverywhere.com/docs>.
|
|
86
86
|
|
|
87
87
|
{{FRAMEWORK_NOTES}}
|
|
@@ -2,25 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
The ERB helpers (`native_app?`, `everywhere_nav_button`, `everywhere_fab`, …) ship with the
|
|
4
4
|
Rails engine, so they aren't available here. The markup contract behind them is public,
|
|
5
|
-
though, and the shell watches for it on every Turbo visit
|
|
5
|
+
though, and the shell watches for it on every Turbo visit, so write it directly:
|
|
6
6
|
|
|
7
7
|
- `data-everywhere-nav-button` (+ `-nav-title`, `-nav-icon`, `-nav-icon-ios`,
|
|
8
|
-
`-nav-icon-android`, `-nav-style`, `side`)
|
|
8
|
+
`-nav-icon-android`, `-nav-style`, `side`): lifts a link or submit button into the top
|
|
9
9
|
navigation bar. Tapping the native control clicks your element.
|
|
10
10
|
- `data-everywhere-nav-menu` with `data-everywhere-menu-item` children (+ `-menu-title`,
|
|
11
|
-
`-menu-style`)
|
|
12
|
-
- `data-everywhere-menu` + `-menu-trigger` + `-menu-items
|
|
13
|
-
- `data-everywhere-haptic
|
|
11
|
+
`-menu-style`): a native pull-down menu.
|
|
12
|
+
- `data-everywhere-menu` + `-menu-trigger` + `-menu-items`: an in-content action sheet.
|
|
13
|
+
- `data-everywhere-haptic`: a tap haptic.
|
|
14
14
|
- `data-everywhere-biometric-lock` (+ `-content`, `-locked`, `-unlock`, `-reason`,
|
|
15
|
-
`-passcode`)
|
|
15
|
+
`-passcode`): the Face ID / Touch ID gate.
|
|
16
16
|
- `<meta name="everywhere:badge">` and `<meta name="everywhere:tab-badge">` (JSON
|
|
17
|
-
`{path, count}`)
|
|
17
|
+
`{path, count}`): app-icon and tab badges, CSP-safe and correct on first paint.
|
|
18
18
|
|
|
19
19
|
Detect the shell server-side from the User-Agent: the shells prepend
|
|
20
20
|
`RubyEverywhere/<version> (<os>)` to Hotwire Native's own marker. Client-side, use
|
|
21
21
|
`Everywhere.platform` / `Everywhere.native`.
|
|
22
22
|
|
|
23
|
-
`public/native.css`, served via `Rack::Static`, carries the styling helpers
|
|
23
|
+
`public/native.css`, served via `Rack::Static`, carries the styling helpers, including
|
|
24
24
|
`.everywhere-titlebar-inset` for `window.title_bar: overlay`. Hanami's CSP forbids inline
|
|
25
25
|
scripts, so every bit of this has to be attributes and external files; that's the same reason
|
|
26
26
|
the markup contract exists in the first place.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
- `native_boot.rb
|
|
2
|
-
- `public/bridge.js` and `public/native.css
|
|
1
|
+
- `native_boot.rb`: the packaged-app entry point. Keep it thin and keep it at the app root.
|
|
2
|
+
- `public/bridge.js` and `public/native.css`: the bridge, vendored and refreshed on each
|
|
3
3
|
`every install`. Serve `public/` via `Rack::Static` and load `/bridge.js` as an **external**
|
|
4
4
|
module; Hanami's CSP forbids inline scripts.
|
|
5
5
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
`Everywhere::Engine` mixes a set of helpers into every view. **Prefer these over hand-written
|
|
4
4
|
markup or JavaScript.** They render a real link or button that works in a browser, and carry
|
|
5
|
-
the `data-everywhere-*` attributes the shell lifts into native chrome
|
|
5
|
+
the `data-everywhere-*` attributes the shell lifts into native chrome. Tapping the native
|
|
6
6
|
control just clicks the element it mirrors, so behavior is defined once and CSP is never an
|
|
7
7
|
issue.
|
|
8
8
|
|
|
@@ -13,15 +13,15 @@ names an SF Symbol and a Material Symbol respectively.
|
|
|
13
13
|
|
|
14
14
|
| Helper | |
|
|
15
15
|
| --- | --- |
|
|
16
|
-
| `native_app?` | any shell
|
|
16
|
+
| `native_app?` | any shell: iOS, Android, or desktop. "Not a browser tab." |
|
|
17
17
|
| `mobile_app?` | a phone: safe-area insets, the native tab bar, biometrics, the OAuth handoff |
|
|
18
18
|
| `desktop_app?` | the desktop window: title bar, menu bar, pointer |
|
|
19
19
|
| `native_platform` | `:ios`, `:android`, `:desktop`, or `nil` in a browser |
|
|
20
20
|
| `mobile_platform` | `:ios`, `:android`, or `nil` (including on desktop) |
|
|
21
|
-
| `native_version` | the shell's version as a `Gem::Version
|
|
21
|
+
| `native_version` | the shell's version as a `Gem::Version`, to gate features that need a newer shell |
|
|
22
22
|
|
|
23
23
|
Detection is by User-Agent, so it's correct on the server before the JS bridge has booted.
|
|
24
|
-
Hiding a web nav in favor of native chrome is usually `mobile_app?`, not `native_app
|
|
24
|
+
Hiding a web nav in favor of native chrome is usually `mobile_app?`, not `native_app?`; the
|
|
25
25
|
desktop shell has no native navigation to replace it with.
|
|
26
26
|
|
|
27
27
|
**Navigation bar.** Renders in the page for browsers; the shell hides the in-page copy and
|
|
@@ -49,7 +49,7 @@ makes it a Turbo method link, `type: :submit` with `form:` submits a form, and
|
|
|
49
49
|
**In-content controls.**
|
|
50
50
|
|
|
51
51
|
```erb
|
|
52
|
-
<%# floating action button
|
|
52
|
+
<%# floating action button: fixed, safe-area-aware, tap haptic in the shell %>
|
|
53
53
|
<%= everywhere_fab new_note_path, icon: :plus, label: "New note" %>
|
|
54
54
|
<%= everywhere_fab compose_path, icon: :pencil, label: "Compose", extended: true %>
|
|
55
55
|
|
|
@@ -61,7 +61,7 @@ makes it a Turbo method link, `type: :submit` with `form:` submits a form, and
|
|
|
61
61
|
```
|
|
62
62
|
|
|
63
63
|
`everywhere_fab` accepts `icon:` (a built-in line glyph), `label:` (accessible name, plus a
|
|
64
|
-
visible pill with `extended: true`), `side:`, and `haptic
|
|
64
|
+
visible pill with `extended: true`), `side:`, and `haptic:`, or a block for custom content.
|
|
65
65
|
|
|
66
66
|
**Badges.** Server-rendered meta tags the bridge applies on every Turbo visit; `0` clears.
|
|
67
67
|
|
|
@@ -92,7 +92,7 @@ redirect_to everywhere_auth_redirect(after_authentication_url)
|
|
|
92
92
|
```
|
|
93
93
|
|
|
94
94
|
**Tab bar, per request.** `Everywhere.tabs { |tabs, ctx| … }` in an initializer (inside
|
|
95
|
-
`to_prepare`) builds the mobile tab bar
|
|
95
|
+
`to_prepare`) builds the mobile tab bar. Return the list to serve, or `[]` to hide the bar.
|
|
96
96
|
`ctx` carries `platform`, `session`/`cookies`, and `current_user` (register the lookup once
|
|
97
97
|
with `Everywhere.current_user { |ctx| … }`). `ctx.tab("Name")` pulls in a tab declared
|
|
98
98
|
`visible: false` in `everywhere.yml`.
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
- `native_boot.rb
|
|
2
|
-
- `config/initializers/everywhere.rb
|
|
3
|
-
- `config/boot.rb
|
|
1
|
+
- `native_boot.rb`: the packaged-app entry point. Keep it thin and keep it at the app root.
|
|
2
|
+
- `config/initializers/everywhere.rb`: packaged-only public-path and session-store setup.
|
|
3
|
+
- `config/boot.rb`: bootsnap guarded with `unless ENV["NATIVE_PACKAGED"]` (its cache dir is
|
|
4
4
|
read-only when packaged).
|
|
5
|
-
- `config/environments/production.rb
|
|
5
|
+
- `config/environments/production.rb`: `force_ssl` and `assume_ssl` are `false`, because a
|
|
6
6
|
packaged app's webview talks plain HTTP to `127.0.0.1`.
|
|
7
|
-
- `config/puma.rb
|
|
8
|
-
- `config/database.yml
|
|
7
|
+
- `config/puma.rb`: keep-alives off when packaged; WebKit reuses connections Puma has closed.
|
|
8
|
+
- `config/database.yml`: the production SQLite path reads
|
|
9
9
|
`<%= ENV.fetch("NATIVE_STORAGE_DIR", "storage") %>`. Any database you add should use the same
|
|
10
10
|
lookup.
|
|
11
|
-
- `app/javascript/application.js
|
|
11
|
+
- `app/javascript/application.js`: imports the bridge and exposes it as `window.Everywhere`.
|
|
12
12
|
|
|
13
13
|
One rule that matters in every mode: the bridge is served and importmap-pinned by
|
|
14
14
|
`Everywhere::Engine` straight from the gem, so it updates with `bundle update ruby_everywhere`.
|
|
15
|
-
Don't vendor it into `vendor/javascript/` or pin it in `config/importmap.rb
|
|
15
|
+
Don't vendor it into `vendor/javascript/` or pin it in `config/importmap.rb`; a local copy
|
|
16
16
|
shadows the engine's and freezes the app on an old bridge.
|
|
@@ -2,19 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
The ERB helpers (`native_app?`, `everywhere_nav_button`, `everywhere_fab`, …) ship with the
|
|
4
4
|
Rails engine, so they aren't available here. The markup contract behind them is public,
|
|
5
|
-
though, and the shell watches for it on every Turbo visit
|
|
5
|
+
though, and the shell watches for it on every Turbo visit, so write it directly:
|
|
6
6
|
|
|
7
7
|
- `data-everywhere-nav-button` (+ `-nav-title`, `-nav-icon`, `-nav-icon-ios`,
|
|
8
|
-
`-nav-icon-android`, `-nav-style`, `side`)
|
|
8
|
+
`-nav-icon-android`, `-nav-style`, `side`): lifts a link or submit button into the top
|
|
9
9
|
navigation bar. Tapping the native control clicks your element.
|
|
10
10
|
- `data-everywhere-nav-menu` with `data-everywhere-menu-item` children (+ `-menu-title`,
|
|
11
|
-
`-menu-style`)
|
|
12
|
-
- `data-everywhere-menu` + `-menu-trigger` + `-menu-items
|
|
13
|
-
- `data-everywhere-haptic
|
|
11
|
+
`-menu-style`): a native pull-down menu.
|
|
12
|
+
- `data-everywhere-menu` + `-menu-trigger` + `-menu-items`: an in-content action sheet.
|
|
13
|
+
- `data-everywhere-haptic`: a tap haptic.
|
|
14
14
|
- `data-everywhere-biometric-lock` (+ `-content`, `-locked`, `-unlock`, `-reason`,
|
|
15
|
-
`-passcode`)
|
|
15
|
+
`-passcode`): the Face ID / Touch ID gate.
|
|
16
16
|
- `<meta name="everywhere:badge">` and `<meta name="everywhere:tab-badge">` (JSON
|
|
17
|
-
`{path, count}`)
|
|
17
|
+
`{path, count}`): app-icon and tab badges, CSP-safe and correct on first paint.
|
|
18
18
|
|
|
19
19
|
Detect the shell server-side from the User-Agent: the shells prepend
|
|
20
20
|
`RubyEverywhere/<version> (<os>)` to Hotwire Native's own marker. Client-side, use
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
- `native_boot.rb
|
|
2
|
-
- `public/bridge.js` and `public/native.css
|
|
1
|
+
- `native_boot.rb`: the packaged-app entry point. Keep it thin and keep it at the app root.
|
|
2
|
+
- `public/bridge.js` and `public/native.css`: the bridge, vendored and refreshed on each
|
|
3
3
|
`every install`. Load it with `<script type="module" src="/bridge.js"></script>`.
|
|
4
4
|
|
|
5
5
|
Rack apps vary too much for the CLI to auto-edit their boot files, so the rest is by hand and
|
|
@@ -2,8 +2,8 @@ The app itself is compiled into the shipped binary and runs on the user's machin
|
|
|
2
2
|
the shells pointing at a deployed site. Shipping a change means cutting a new build and
|
|
3
3
|
release.
|
|
4
4
|
|
|
5
|
-
That trade brings constraints the docs cover properly
|
|
6
|
-
with a separate writable data directory, SQLite only, desktop only
|
|
5
|
+
That trade brings constraints the docs cover properly: a read-only application filesystem
|
|
6
|
+
with a separate writable data directory, SQLite only, desktop only. Read
|
|
7
7
|
<https://rubyeverywhere.com/docs> before changing anything that writes to disk, boots the app,
|
|
8
8
|
or touches `native_boot.rb`. The short version: anything written at runtime belongs under
|
|
9
9
|
`ENV.fetch("NATIVE_STORAGE_DIR", "storage")`, and `ENV["NATIVE_PACKAGED"]` is the guard for
|
|
@@ -2,7 +2,7 @@ The native shells are a thin wrapper around the deployed site at `remote.url` in
|
|
|
2
2
|
`config/everywhere.yml`. Nothing about the app is compiled into them.
|
|
3
3
|
|
|
4
4
|
**So you are working on an ordinary web app.** Ship a change by deploying as you always have,
|
|
5
|
-
and users see it on their next launch
|
|
5
|
+
and users see it on their next launch. No rebuild, no app-store review. Normal databases,
|
|
6
6
|
background jobs, and hosting all apply, unchanged.
|
|
7
7
|
|
|
8
8
|
Only three things are native-specific, and they're all covered below: what
|
|
@@ -10,5 +10,5 @@ Only three things are native-specific, and they're all covered below: what
|
|
|
10
10
|
`Everywhere` JavaScript API. Of those, tab and path-rule changes deploy with the app; the rest
|
|
11
11
|
of `config/everywhere.yml` needs a new build of the shells.
|
|
12
12
|
|
|
13
|
-
Remote is also the only mode mobile supports
|
|
13
|
+
Remote is also the only mode mobile supports: iOS and Android are always a shell around a
|
|
14
14
|
deployed app.
|
|
@@ -480,7 +480,7 @@ fn verify_signature(path: &Path, signature: &str, public_key: &str) -> Result<()
|
|
|
480
480
|
let pk = minisign_verify::PublicKey::from_base64(public_key)
|
|
481
481
|
.map_err(|e| format!("bad updates.public_key: {e}"))?;
|
|
482
482
|
let sig = minisign_verify::Signature::decode(signature)
|
|
483
|
-
.map_err(|e| format!("
|
|
483
|
+
.map_err(|e| format!("unreadable artifact signature: {e}"))?;
|
|
484
484
|
let data = std::fs::read(path).map_err(|e| e.to_string())?;
|
|
485
485
|
pk.verify(&data, &sig, false)
|
|
486
486
|
.map_err(|_| "signature verification FAILED — artifact does not match the app's signing key".to_string())
|