ember-cli-rails 0.13.0.beta1 → 0.13.1
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 +24 -0
- data/README.md +97 -7
- data/lib/ember_cli/app.rb +70 -14
- data/lib/ember_cli/command.rb +14 -0
- data/lib/ember_cli/deploy/dev_server.rb +47 -0
- data/lib/ember_cli/dev_server.rb +187 -0
- data/lib/ember_cli/dev_server_proxy.rb +103 -0
- data/lib/ember_cli/errors.rb +1 -0
- data/lib/ember_cli/path_set.rb +18 -0
- data/lib/ember_cli/shell.rb +45 -7
- data/lib/ember_cli/version.rb +1 -1
- data/lib/ember_cli.rb +5 -1
- metadata +9 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b913a8d36b33cdc65fd77f4e8621cce6ced3f153d383acc240d9438c2966fb23
|
|
4
|
+
data.tar.gz: 8b18a2ad22595a8fc718ba0bd211ac7a17f4cdaac17ffdaf8a5c1e7ee20e699e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ce0418badce132724ae14a9e505f9a53da9a729f79bfe46f8576a7416c99f03fee30ff5e13e4053e9acc7294900563b78a2c8a7c934c836a6a4ccc762f6eeccb
|
|
7
|
+
data.tar.gz: 72f4d21d29fde8eb14a4d58ce7c924a9f0e3dafa9f213a0f7d148c2c15fb8cf5362f21d415cee2b39e86bbbec7ec63589fe0d4f5e4cb9cfccb2c542da30a3166
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,27 @@
|
|
|
1
|
+
0.13.1
|
|
2
|
+
------
|
|
3
|
+
|
|
4
|
+
* Fix `EmberCli::App#test` to report a failing suite by returning `false`
|
|
5
|
+
instead of exiting the process from inside the gem — one failing Ember suite
|
|
6
|
+
no longer aborts the caller (RSpec included) mid-run. `EmberCli.test!`
|
|
7
|
+
raises `EmberCli::TestFailureError` when a suite fails, which still exits
|
|
8
|
+
`rake ember:test` nonzero
|
|
9
|
+
|
|
10
|
+
0.13.0
|
|
11
|
+
------
|
|
12
|
+
|
|
13
|
+
* Serve Vite-based applications from Vite's development server in
|
|
14
|
+
`development`, so that changes are hot-reloaded instead of requiring a
|
|
15
|
+
restart. Configure it with the `dev_server` option, or opt out with
|
|
16
|
+
`dev_server: false`
|
|
17
|
+
* Require `ember-cli-rails-assets >= 0.9.0`, which serves the
|
|
18
|
+
`include_ember_script_tags` startup tags from Vite's development server
|
|
19
|
+
when the application is served from it
|
|
20
|
+
* Add an `origin` option to `dev_server`, separating the origin the browser
|
|
21
|
+
loads assets from, from the address the development server binds to — for
|
|
22
|
+
containers, where the server must bind to `0.0.0.0` but browsers refuse
|
|
23
|
+
that address as an origin
|
|
24
|
+
|
|
1
25
|
0.13.0.beta1
|
|
2
26
|
------
|
|
3
27
|
|
data/README.md
CHANGED
|
@@ -81,6 +81,10 @@ c.app :frontend, path: "~/projects/my-ember-app"
|
|
|
81
81
|
|
|
82
82
|
- `yarn` - enables the [yarn](https://github.com/yarnpkg/yarn) package manager when installing dependencies
|
|
83
83
|
|
|
84
|
+
- `dev_server` - configures [Vite's development server](#vite-based-applications)
|
|
85
|
+
for Vite-based applications in `development`. Pass `false` to opt out of it,
|
|
86
|
+
or a Hash of `host`, `port`, and `timeout` settings.
|
|
87
|
+
|
|
84
88
|
```ruby
|
|
85
89
|
EmberCli.configure do |c|
|
|
86
90
|
c.app :adminpanel # path defaults to `Rails.root.join("adminpanel")`
|
|
@@ -176,16 +180,83 @@ suites, configure the `default` task to depend on both `spec` and `ember:test`.
|
|
|
176
180
|
task default: [:spec, "ember:test"]
|
|
177
181
|
```
|
|
178
182
|
|
|
179
|
-
|
|
183
|
+
### Vite-based applications
|
|
180
184
|
|
|
181
185
|
When Rails is running in development mode, classic (Broccoli-based) Ember
|
|
182
186
|
applications are built with `ember build --watch`, so changes to the Ember
|
|
183
187
|
application are picked up automatically.
|
|
184
188
|
|
|
185
|
-
Vite-based Ember applications (generated with `ember-cli >= 6.8`) are
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
+
Vite-based Ember applications (generated with `ember-cli >= 6.8`) are served by
|
|
190
|
+
Vite's own development server instead — the same one the application's
|
|
191
|
+
`npm start` script runs. `ember-cli-rails` starts it on the first request,
|
|
192
|
+
waits for it to accept connections, and shuts it down when Rails exits.
|
|
193
|
+
|
|
194
|
+
Rails still renders the application's `index.html`, but reads it from the
|
|
195
|
+
development server rather than from disk. The root-relative URLs in that
|
|
196
|
+
document are rewritten to point at the development server, so the browser
|
|
197
|
+
loads the application's modules — and Vite's HMR client — from it directly.
|
|
198
|
+
Changes to the Ember application are hot-reloaded without reloading the page,
|
|
199
|
+
and without restarting Rails.
|
|
200
|
+
|
|
201
|
+
Assets that the Ember application references relatively (an `<img>` in a
|
|
202
|
+
template, for instance) are still requested from Rails, which proxies them to
|
|
203
|
+
the development server.
|
|
204
|
+
|
|
205
|
+
**Configuring the development server**
|
|
206
|
+
|
|
207
|
+
By default the development server listens on an available port on `127.0.0.1`,
|
|
208
|
+
and `ember-cli-rails` waits up to 30 seconds for it to start:
|
|
209
|
+
|
|
210
|
+
```rb
|
|
211
|
+
EmberCli.configure do |c|
|
|
212
|
+
c.app :frontend, dev_server: { host: "127.0.0.1", port: 4200, timeout: 60 }
|
|
213
|
+
end
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
If something is already listening on the configured `host` and `port`,
|
|
217
|
+
`ember-cli-rails` uses it instead of starting a second server. That makes it
|
|
218
|
+
possible to run `npm start` yourself, on a port the initializer names, and have
|
|
219
|
+
Rails serve the application from it.
|
|
220
|
+
|
|
221
|
+
`host` is both the address the development server binds to and — together with
|
|
222
|
+
`port` — the origin the browser loads the application's modules from. When the
|
|
223
|
+
two differ, configure the browser-facing origin separately with `origin`. The
|
|
224
|
+
typical case is Rails running in a container: the development server must bind
|
|
225
|
+
to `0.0.0.0` to be reachable through the container's published port, but
|
|
226
|
+
browsers refuse to connect to `http://0.0.0.0`:
|
|
227
|
+
|
|
228
|
+
```rb
|
|
229
|
+
EmberCli.configure do |c|
|
|
230
|
+
c.app :frontend, dev_server: {
|
|
231
|
+
host: "0.0.0.0",
|
|
232
|
+
port: 4200,
|
|
233
|
+
origin: "http://localhost:4200",
|
|
234
|
+
}
|
|
235
|
+
end
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
With `host: "0.0.0.0"`, Rails itself reaches the development server through the
|
|
239
|
+
loopback interface.
|
|
240
|
+
|
|
241
|
+
The development server's output is written to
|
|
242
|
+
`log/ember-<app>.<environment>.log`.
|
|
243
|
+
|
|
244
|
+
**Opting out**
|
|
245
|
+
|
|
246
|
+
To build the application once, synchronously, on the first request instead of
|
|
247
|
+
running a development server, disable it:
|
|
248
|
+
|
|
249
|
+
```rb
|
|
250
|
+
EmberCli.configure do |c|
|
|
251
|
+
c.app :frontend, dev_server: false
|
|
252
|
+
end
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
Changes to the Ember application are then only picked up by restarting the
|
|
256
|
+
Rails server.
|
|
257
|
+
|
|
258
|
+
The development server is only used in `development`. `test` and `production`
|
|
259
|
+
are served from the output of `ember build`, as they always have been.
|
|
189
260
|
|
|
190
261
|
## Deploy
|
|
191
262
|
|
|
@@ -472,6 +543,17 @@ and `modulepreload` links, and the ES module script tags — extracted from
|
|
|
472
543
|
the generated `index.html`. `include_ember_stylesheet_tags` only supports
|
|
473
544
|
classic (Broccoli-based) applications.
|
|
474
545
|
|
|
546
|
+
When the application is served by [Vite's development
|
|
547
|
+
server](#vite-based-applications), `include_ember_script_tags` (from
|
|
548
|
+
[ember-cli-rails-assets]) reads `index.html` from the server and emits the
|
|
549
|
+
startup tags with absolute URLs pointing at it — nothing is built, and changes
|
|
550
|
+
to the application are picked up by reloading the page.
|
|
551
|
+
|
|
552
|
+
With the development server disabled (`dev_server: false`), the helpers read
|
|
553
|
+
the output of `ember build` instead: the application is built once,
|
|
554
|
+
synchronously, on the first request, and changes to it are only picked up by
|
|
555
|
+
restarting the Rails server.
|
|
556
|
+
|
|
475
557
|
Following the example above, configure the mounted EmberCLI application to be
|
|
476
558
|
served by a custom controller (`ApplicationController`, in this case).
|
|
477
559
|
|
|
@@ -627,6 +709,11 @@ make sure it's configured to run a single worker process.
|
|
|
627
709
|
Without restricting the server to a single process, [it is possible for multiple
|
|
628
710
|
EmberCLI runners to clobber each others' work][#94].
|
|
629
711
|
|
|
712
|
+
This does not apply to Vite-based applications served by [Vite's development
|
|
713
|
+
server](#vite-based-applications): nothing is written to a shared build
|
|
714
|
+
directory. Give the application a fixed `port` so that the workers share a
|
|
715
|
+
single development server rather than starting one each.
|
|
716
|
+
|
|
630
717
|
[Puma]: https://github.com/puma/puma
|
|
631
718
|
[Unicorn]: https://rubygems.org/gems/unicorn
|
|
632
719
|
[#94]: https://github.com/tricknotes/ember-cli-rails/issues/94#issuecomment-77627453
|
|
@@ -689,8 +776,11 @@ Note the following limitations for Vite-based applications:
|
|
|
689
776
|
* `include_ember_script_tags` emits the full set of tags the application
|
|
690
777
|
needs to boot, stylesheets included; `include_ember_stylesheet_tags` is
|
|
691
778
|
classic-only and must not be called for Vite-based applications
|
|
692
|
-
* in development, the application is
|
|
693
|
-
|
|
779
|
+
* in development, the application is served by [Vite's development
|
|
780
|
+
server](#vite-based-applications) rather than out of a build directory. The
|
|
781
|
+
asset helpers serve their tags from the development server too; with
|
|
782
|
+
`dev_server: false` they read the build output, which is built once,
|
|
783
|
+
synchronously, on the first request
|
|
694
784
|
|
|
695
785
|
## Ruby and Rails support
|
|
696
786
|
|
data/lib/ember_cli/app.rb
CHANGED
|
@@ -2,7 +2,9 @@ require "html_page/renderer"
|
|
|
2
2
|
require "ember_cli/path_set"
|
|
3
3
|
require "ember_cli/shell"
|
|
4
4
|
require "ember_cli/build_monitor"
|
|
5
|
+
require "ember_cli/deploy/dev_server"
|
|
5
6
|
require "ember_cli/deploy/file"
|
|
7
|
+
require "ember_cli/dev_server"
|
|
6
8
|
|
|
7
9
|
module EmberCli
|
|
8
10
|
class App
|
|
@@ -49,20 +51,15 @@ module EmberCli
|
|
|
49
51
|
|
|
50
52
|
def build
|
|
51
53
|
unless EmberCli.skip?
|
|
52
|
-
if
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
end
|
|
61
|
-
elsif test?
|
|
62
|
-
compile
|
|
54
|
+
if dev_server?
|
|
55
|
+
# Vite's own development server rebuilds and hot-reloads the
|
|
56
|
+
# application, so there is nothing to build ahead of time.
|
|
57
|
+
dev_server.start
|
|
58
|
+
else
|
|
59
|
+
build_for_environment
|
|
60
|
+
|
|
61
|
+
@build.wait!
|
|
63
62
|
end
|
|
64
|
-
|
|
65
|
-
@build.wait!
|
|
66
63
|
end
|
|
67
64
|
end
|
|
68
65
|
|
|
@@ -106,6 +103,24 @@ module EmberCli
|
|
|
106
103
|
deploy.to_rack
|
|
107
104
|
end
|
|
108
105
|
|
|
106
|
+
def dev_server
|
|
107
|
+
@dev_server ||= DevServer.new(
|
|
108
|
+
name: name,
|
|
109
|
+
paths: paths,
|
|
110
|
+
shell: @shell,
|
|
111
|
+
options: dev_server_options,
|
|
112
|
+
)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Whether this application is served by Vite's development server rather
|
|
116
|
+
# than out of the directory `ember build` writes to.
|
|
117
|
+
def dev_server?
|
|
118
|
+
strategy = deploy_strategy
|
|
119
|
+
|
|
120
|
+
strategy.is_a?(Class) &&
|
|
121
|
+
strategy.ancestors.include?(EmberCli::Deploy::DevServer)
|
|
122
|
+
end
|
|
123
|
+
|
|
109
124
|
private
|
|
110
125
|
|
|
111
126
|
def development?
|
|
@@ -124,12 +139,38 @@ module EmberCli
|
|
|
124
139
|
strategy = options.fetch(:deploy, {})
|
|
125
140
|
|
|
126
141
|
if strategy.respond_to?(:fetch)
|
|
127
|
-
strategy.fetch(rails_env
|
|
142
|
+
strategy.fetch(rails_env) { default_deploy_strategy }
|
|
128
143
|
else
|
|
129
144
|
strategy
|
|
130
145
|
end
|
|
131
146
|
end
|
|
132
147
|
|
|
148
|
+
def default_deploy_strategy
|
|
149
|
+
if development? && paths.vite? && dev_server_enabled?
|
|
150
|
+
EmberCli::Deploy::DevServer
|
|
151
|
+
else
|
|
152
|
+
EmberCli::Deploy::File
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def dev_server_option
|
|
157
|
+
options.fetch(:dev_server, true)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def dev_server_enabled?
|
|
161
|
+
dev_server_option != false
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def dev_server_options
|
|
165
|
+
option = dev_server_option
|
|
166
|
+
|
|
167
|
+
if option.respond_to?(:fetch)
|
|
168
|
+
option
|
|
169
|
+
else
|
|
170
|
+
{}
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
133
174
|
def rails_env
|
|
134
175
|
Rails.env.to_s.to_sym
|
|
135
176
|
end
|
|
@@ -138,6 +179,21 @@ module EmberCli
|
|
|
138
179
|
EmberCli.env
|
|
139
180
|
end
|
|
140
181
|
|
|
182
|
+
def build_for_environment
|
|
183
|
+
if development?
|
|
184
|
+
if paths.vite?
|
|
185
|
+
# The Vite-based blueprint (`ember-cli >= 6.8`) has no
|
|
186
|
+
# `ember-cli-rails-addon` to manage the build lock, so build
|
|
187
|
+
# synchronously instead of watching for changes.
|
|
188
|
+
compile
|
|
189
|
+
else
|
|
190
|
+
build_and_watch
|
|
191
|
+
end
|
|
192
|
+
elsif test?
|
|
193
|
+
compile
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
|
|
141
197
|
def build_and_watch
|
|
142
198
|
prepare
|
|
143
199
|
@shell.build_and_watch
|
data/lib/ember_cli/command.rb
CHANGED
|
@@ -17,6 +17,20 @@ module EmberCli
|
|
|
17
17
|
ember_build(watch: watch)
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
+
# Boots Vite's development server for an application generated with the
|
|
21
|
+
# Vite-based blueprint (`ember-cli >= 6.8`). This is what the blueprint's
|
|
22
|
+
# own `npm start` script runs.
|
|
23
|
+
def dev_server(host:, port:)
|
|
24
|
+
line = Terrapin::CommandLine.new(paths.vite, [
|
|
25
|
+
"--host :host",
|
|
26
|
+
"--port :port",
|
|
27
|
+
"--strictPort",
|
|
28
|
+
"--clearScreen false",
|
|
29
|
+
].join(" "))
|
|
30
|
+
|
|
31
|
+
line.command(host: host.to_s, port: port.to_s)
|
|
32
|
+
end
|
|
33
|
+
|
|
20
34
|
private
|
|
21
35
|
|
|
22
36
|
attr_reader :options, :paths
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
require "ember_cli/dev_server_proxy"
|
|
2
|
+
require "ember_cli/errors"
|
|
3
|
+
|
|
4
|
+
module EmberCli
|
|
5
|
+
module Deploy
|
|
6
|
+
# Serves an Ember application from its Vite development server instead of
|
|
7
|
+
# from the `dist` directory written by `ember build`.
|
|
8
|
+
#
|
|
9
|
+
# The `index.html` served by the development server refers to its assets
|
|
10
|
+
# (`/@vite/client` included) with root-relative URLs. Rails serves the
|
|
11
|
+
# document from its own origin, so those URLs are rewritten to absolute
|
|
12
|
+
# URLs pointing at the development server. Loading them from there means
|
|
13
|
+
# the Vite client opens its HMR WebSocket against the development server
|
|
14
|
+
# directly, without Rails proxying it.
|
|
15
|
+
class DevServer
|
|
16
|
+
ROOT_RELATIVE_URL = %r{(\s)(src|href)=(["'])/(?!/)}i
|
|
17
|
+
|
|
18
|
+
def initialize(app)
|
|
19
|
+
@app = app
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def mountable?
|
|
23
|
+
true
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def to_rack
|
|
27
|
+
DevServerProxy.new(app)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def index_html
|
|
31
|
+
rewrite_root_relative_urls(dev_server.index_html)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
attr_reader :app
|
|
37
|
+
|
|
38
|
+
delegate :dev_server, to: :app
|
|
39
|
+
|
|
40
|
+
def rewrite_root_relative_urls(html)
|
|
41
|
+
html.gsub(ROOT_RELATIVE_URL) do
|
|
42
|
+
"#{$1}#{$2}=#{$3}#{dev_server.origin}/"
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
require "monitor"
|
|
2
|
+
require "net/http"
|
|
3
|
+
require "socket"
|
|
4
|
+
require "uri"
|
|
5
|
+
|
|
6
|
+
require "ember_cli/errors"
|
|
7
|
+
|
|
8
|
+
module EmberCli
|
|
9
|
+
# Manages the Vite development server backing a single Ember application.
|
|
10
|
+
#
|
|
11
|
+
# The server is booted lazily, and the Ember application's `index.html` and
|
|
12
|
+
# assets are read from it over HTTP instead of from the `dist` directory
|
|
13
|
+
# written by `ember build`.
|
|
14
|
+
class DevServer
|
|
15
|
+
DEFAULT_HOST = "127.0.0.1".freeze
|
|
16
|
+
DEFAULT_TIMEOUT = 30
|
|
17
|
+
POLL_INTERVAL = 0.1
|
|
18
|
+
CONNECT_TIMEOUT = 1
|
|
19
|
+
|
|
20
|
+
def initialize(name:, paths:, shell:, options: {})
|
|
21
|
+
@name = name
|
|
22
|
+
@paths = paths
|
|
23
|
+
@shell = shell
|
|
24
|
+
@options = options.respond_to?(:fetch) ? options : {}
|
|
25
|
+
@monitor = Monitor.new
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def host
|
|
29
|
+
@host ||= option(:host) { DEFAULT_HOST }.to_s
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def port
|
|
33
|
+
@port ||= option(:port) { available_port }.to_i
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def timeout
|
|
37
|
+
@timeout ||= option(:timeout) { DEFAULT_TIMEOUT }.to_f
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# The origin the browser loads the application's assets from. It defaults
|
|
41
|
+
# to the address the development server binds to, but can be configured
|
|
42
|
+
# separately for setups where the two differ — a development server bound
|
|
43
|
+
# to `0.0.0.0` inside a container, reached by the browser through a
|
|
44
|
+
# published port, for instance.
|
|
45
|
+
def origin
|
|
46
|
+
@origin ||= option(:origin) { "http://#{host}:#{port}" }.to_s.chomp("/")
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Boots the development server unless something is already listening on
|
|
50
|
+
# its address, and blocks until it accepts connections.
|
|
51
|
+
def start
|
|
52
|
+
return true if listening?
|
|
53
|
+
|
|
54
|
+
# Requests are served concurrently, so make sure only one of them boots
|
|
55
|
+
# the development server.
|
|
56
|
+
monitor.synchronize do
|
|
57
|
+
return true if listening?
|
|
58
|
+
|
|
59
|
+
shell.start_dev_server(host: host, port: port)
|
|
60
|
+
|
|
61
|
+
wait_until_listening!
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def index_html
|
|
66
|
+
response = get("/")
|
|
67
|
+
|
|
68
|
+
unless response.is_a?(Net::HTTPSuccess)
|
|
69
|
+
fail BuildError.new(<<~MSG)
|
|
70
|
+
#{name.inspect} failed to serve an `index.html` file.
|
|
71
|
+
|
|
72
|
+
#{origin}/ responded with #{response.code} #{response.message}:
|
|
73
|
+
|
|
74
|
+
#{response.body}
|
|
75
|
+
MSG
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
response.body.to_s
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def get(path, headers = {})
|
|
82
|
+
request(Net::HTTP::Get, path, headers)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def head(path, headers = {})
|
|
86
|
+
request(Net::HTTP::Head, path, headers)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def options_request(path, headers = {})
|
|
90
|
+
request(Net::HTTP::Options, path, headers)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
private
|
|
94
|
+
|
|
95
|
+
attr_reader :monitor, :name, :options, :paths, :shell
|
|
96
|
+
|
|
97
|
+
def option(key)
|
|
98
|
+
options.fetch(key) { options.fetch(key.to_s) { yield } }
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def request(request_class, path, headers)
|
|
102
|
+
start
|
|
103
|
+
|
|
104
|
+
uri = URI.join("http://#{connect_host}:#{port}", path)
|
|
105
|
+
# Pass `nil` as the proxy address so that a `http_proxy` environment
|
|
106
|
+
# variable never routes requests for the local server through a proxy.
|
|
107
|
+
Net::HTTP.start(uri.hostname, uri.port, nil, read_timeout: timeout) do |http|
|
|
108
|
+
http.request(request_class.new(uri, headers))
|
|
109
|
+
end
|
|
110
|
+
rescue SystemCallError, IOError, Timeout::Error => error
|
|
111
|
+
fail BuildError.new(<<~MSG)
|
|
112
|
+
#{name.inspect} could not reach its development server at #{origin}.
|
|
113
|
+
|
|
114
|
+
#{error.class}: #{error.message}
|
|
115
|
+
|
|
116
|
+
Its output is written to #{paths.log}.
|
|
117
|
+
MSG
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# The address Rails connects to the development server on. `0.0.0.0` asks
|
|
121
|
+
# the server to listen on every interface, but is not an address to
|
|
122
|
+
# connect to, so requests go to the loopback interface instead.
|
|
123
|
+
def connect_host
|
|
124
|
+
if host == "0.0.0.0"
|
|
125
|
+
"127.0.0.1"
|
|
126
|
+
else
|
|
127
|
+
host
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def listening?
|
|
132
|
+
Socket.tcp(connect_host, port, connect_timeout: CONNECT_TIMEOUT, &:close)
|
|
133
|
+
|
|
134
|
+
true
|
|
135
|
+
rescue SystemCallError, IOError
|
|
136
|
+
false
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def wait_until_listening!
|
|
140
|
+
deadline = now + timeout
|
|
141
|
+
|
|
142
|
+
loop do
|
|
143
|
+
return true if listening?
|
|
144
|
+
|
|
145
|
+
unless shell.dev_server_running?
|
|
146
|
+
fail BuildError.new(<<~MSG)
|
|
147
|
+
#{name.inspect} failed to start its development server on #{origin}.
|
|
148
|
+
|
|
149
|
+
Its output is written to #{paths.log}.
|
|
150
|
+
MSG
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
if now >= deadline
|
|
154
|
+
fail BuildError.new(<<~MSG)
|
|
155
|
+
#{name.inspect} timed out after #{timeout.round} seconds waiting for
|
|
156
|
+
its development server to listen on #{origin}.
|
|
157
|
+
|
|
158
|
+
Its output is written to #{paths.log}.
|
|
159
|
+
|
|
160
|
+
Configure a longer timeout with:
|
|
161
|
+
|
|
162
|
+
EmberCli.configure do |config|
|
|
163
|
+
config.app #{name.to_sym.inspect}, dev_server: { timeout: 60 }
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
MSG
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
sleep POLL_INTERVAL
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def now
|
|
174
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def available_port
|
|
178
|
+
server = TCPServer.new(host, 0)
|
|
179
|
+
|
|
180
|
+
begin
|
|
181
|
+
server.addr[1]
|
|
182
|
+
ensure
|
|
183
|
+
server.close
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
require "rack"
|
|
2
|
+
|
|
3
|
+
module EmberCli
|
|
4
|
+
# Forwards requests made to an Ember application's mount point to its Vite
|
|
5
|
+
# development server.
|
|
6
|
+
#
|
|
7
|
+
# Assets referenced by the Ember application itself (rather than by its
|
|
8
|
+
# `index.html`) are resolved against the document's URL, so they are
|
|
9
|
+
# requested from Rails. Proxying them keeps those references working the
|
|
10
|
+
# same way they do when the application is served out of `dist`.
|
|
11
|
+
class DevServerProxy
|
|
12
|
+
ALLOWED_VERBS = %w[GET HEAD OPTIONS].freeze
|
|
13
|
+
# Hop-by-hop headers, plus the `Content-Encoding` header describing a body
|
|
14
|
+
# that `Net::HTTP` may have decoded already.
|
|
15
|
+
SKIPPED_HEADERS = %w[
|
|
16
|
+
connection
|
|
17
|
+
content-encoding
|
|
18
|
+
keep-alive
|
|
19
|
+
proxy-authenticate
|
|
20
|
+
proxy-authorization
|
|
21
|
+
te
|
|
22
|
+
trailer
|
|
23
|
+
transfer-encoding
|
|
24
|
+
upgrade
|
|
25
|
+
].freeze
|
|
26
|
+
|
|
27
|
+
def initialize(app)
|
|
28
|
+
@app = app
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def call(env)
|
|
32
|
+
request = Rack::Request.new(env)
|
|
33
|
+
|
|
34
|
+
unless ALLOWED_VERBS.include?(request.request_method)
|
|
35
|
+
return method_not_allowed
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
rack_response(proxy(request))
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
attr_reader :app
|
|
44
|
+
|
|
45
|
+
delegate :dev_server, to: :app
|
|
46
|
+
|
|
47
|
+
def proxy(request)
|
|
48
|
+
path = path_for(request)
|
|
49
|
+
headers = { "accept-encoding" => "identity" }
|
|
50
|
+
|
|
51
|
+
case request.request_method
|
|
52
|
+
when "HEAD" then dev_server.head(path, headers)
|
|
53
|
+
when "OPTIONS" then dev_server.options_request(path, headers)
|
|
54
|
+
else dev_server.get(path, headers)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def path_for(request)
|
|
59
|
+
path = request.path_info.presence || "/"
|
|
60
|
+
query = request.query_string
|
|
61
|
+
|
|
62
|
+
if query.present?
|
|
63
|
+
"#{path}?#{query}"
|
|
64
|
+
else
|
|
65
|
+
path
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def rack_response(response)
|
|
70
|
+
body = response.body.to_s
|
|
71
|
+
|
|
72
|
+
[response.code.to_i, response_headers(response, body), [body]]
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def response_headers(response, body)
|
|
76
|
+
headers = {}
|
|
77
|
+
|
|
78
|
+
response.each_header do |name, value|
|
|
79
|
+
unless SKIPPED_HEADERS.include?(name.downcase)
|
|
80
|
+
headers[name.downcase] = value
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
headers["content-length"] ||= body.bytesize.to_s
|
|
85
|
+
|
|
86
|
+
headers
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def method_not_allowed
|
|
90
|
+
body = "Method Not Allowed"
|
|
91
|
+
|
|
92
|
+
[
|
|
93
|
+
405,
|
|
94
|
+
{
|
|
95
|
+
"allow" => ALLOWED_VERBS.join(", "),
|
|
96
|
+
"content-type" => "text/plain",
|
|
97
|
+
"content-length" => body.bytesize.to_s,
|
|
98
|
+
},
|
|
99
|
+
[body],
|
|
100
|
+
]
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
data/lib/ember_cli/errors.rb
CHANGED
data/lib/ember_cli/path_set.rb
CHANGED
|
@@ -64,6 +64,24 @@ module EmberCli
|
|
|
64
64
|
end
|
|
65
65
|
end
|
|
66
66
|
|
|
67
|
+
def vite
|
|
68
|
+
@vite ||= begin
|
|
69
|
+
root.join("node_modules", ".bin", "vite").tap do |path|
|
|
70
|
+
unless path.executable?
|
|
71
|
+
fail DependencyError.new <<-MSG.strip_heredoc
|
|
72
|
+
No `vite` executable found for `#{app_name}`.
|
|
73
|
+
|
|
74
|
+
Install it:
|
|
75
|
+
|
|
76
|
+
$ cd #{root}
|
|
77
|
+
$ #{package_manager} install
|
|
78
|
+
|
|
79
|
+
MSG
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
67
85
|
def lockfile
|
|
68
86
|
@lockfile ||= tmp.join("build.lock")
|
|
69
87
|
end
|
data/lib/ember_cli/shell.rb
CHANGED
|
@@ -20,16 +20,44 @@ module EmberCli
|
|
|
20
20
|
def build_and_watch
|
|
21
21
|
unless running?
|
|
22
22
|
lock_buildfile
|
|
23
|
-
self.pid = spawn
|
|
23
|
+
self.pid = spawn(
|
|
24
|
+
ember.build(watch: true),
|
|
25
|
+
err: paths.build_error_file.to_s,
|
|
26
|
+
)
|
|
24
27
|
detach
|
|
25
28
|
end
|
|
26
29
|
end
|
|
27
30
|
|
|
31
|
+
def start_dev_server(host:, port:)
|
|
32
|
+
unless dev_server_running?
|
|
33
|
+
# Run the development server in its own process group so that the
|
|
34
|
+
# whole tree can be signaled when Rails exits.
|
|
35
|
+
self.dev_server_pid = spawn(
|
|
36
|
+
ember.dev_server(host: host, port: port),
|
|
37
|
+
out: [paths.log.to_s, "a"],
|
|
38
|
+
err: [:child, :out],
|
|
39
|
+
pgroup: true,
|
|
40
|
+
)
|
|
41
|
+
Process.detach(dev_server_pid)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
dev_server_pid
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def dev_server_running?
|
|
48
|
+
process_running?(dev_server_pid)
|
|
49
|
+
end
|
|
50
|
+
|
|
28
51
|
def stop
|
|
29
52
|
if pid.present?
|
|
30
|
-
|
|
53
|
+
signal(pid)
|
|
31
54
|
self.pid = nil
|
|
32
55
|
end
|
|
56
|
+
|
|
57
|
+
if dev_server_pid.present?
|
|
58
|
+
signal(-dev_server_pid)
|
|
59
|
+
self.dev_server_pid = nil
|
|
60
|
+
end
|
|
33
61
|
end
|
|
34
62
|
|
|
35
63
|
def install
|
|
@@ -53,12 +81,12 @@ module EmberCli
|
|
|
53
81
|
end
|
|
54
82
|
|
|
55
83
|
def test
|
|
56
|
-
run
|
|
84
|
+
run ember.test
|
|
57
85
|
end
|
|
58
86
|
|
|
59
87
|
private
|
|
60
88
|
|
|
61
|
-
attr_accessor :pid
|
|
89
|
+
attr_accessor :dev_server_pid, :pid
|
|
62
90
|
attr_reader :ember, :env, :options, :paths
|
|
63
91
|
|
|
64
92
|
delegate :run, :run!, to: :runner
|
|
@@ -80,15 +108,21 @@ module EmberCli
|
|
|
80
108
|
].select(&:exist?)
|
|
81
109
|
end
|
|
82
110
|
|
|
83
|
-
def spawn(command)
|
|
111
|
+
def spawn(command, **redirects)
|
|
84
112
|
Kernel.spawn(
|
|
85
113
|
env,
|
|
86
114
|
command,
|
|
87
115
|
chdir: paths.root.to_s,
|
|
88
|
-
|
|
116
|
+
**redirects,
|
|
89
117
|
) || exit(1)
|
|
90
118
|
end
|
|
91
119
|
|
|
120
|
+
def signal(process_id)
|
|
121
|
+
Process.kill(:INT, process_id)
|
|
122
|
+
rescue Errno::ESRCH, Errno::EPERM
|
|
123
|
+
nil
|
|
124
|
+
end
|
|
125
|
+
|
|
92
126
|
def runner
|
|
93
127
|
Runner.new(
|
|
94
128
|
options: { chdir: paths.root.to_s },
|
|
@@ -99,7 +133,11 @@ module EmberCli
|
|
|
99
133
|
end
|
|
100
134
|
|
|
101
135
|
def running?
|
|
102
|
-
|
|
136
|
+
process_running?(pid)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def process_running?(process_id)
|
|
140
|
+
process_id.present? && !!Process.getpgid(process_id)
|
|
103
141
|
rescue Errno::ESRCH
|
|
104
142
|
false
|
|
105
143
|
end
|
data/lib/ember_cli/version.rb
CHANGED
data/lib/ember_cli.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ember-cli-rails
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.13.
|
|
4
|
+
version: 0.13.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Pavel Pravosud
|
|
@@ -18,7 +18,7 @@ dependencies:
|
|
|
18
18
|
requirements:
|
|
19
19
|
- - ">="
|
|
20
20
|
- !ruby/object:Gem::Version
|
|
21
|
-
version: 0.
|
|
21
|
+
version: 0.9.0
|
|
22
22
|
- - "<"
|
|
23
23
|
- !ruby/object:Gem::Version
|
|
24
24
|
version: '1.0'
|
|
@@ -28,7 +28,7 @@ dependencies:
|
|
|
28
28
|
requirements:
|
|
29
29
|
- - ">="
|
|
30
30
|
- !ruby/object:Gem::Version
|
|
31
|
-
version: 0.
|
|
31
|
+
version: 0.9.0
|
|
32
32
|
- - "<"
|
|
33
33
|
- !ruby/object:Gem::Version
|
|
34
34
|
version: '1.0'
|
|
@@ -117,7 +117,7 @@ dependencies:
|
|
|
117
117
|
version: 3.6.0
|
|
118
118
|
- - "<"
|
|
119
119
|
- !ruby/object:Gem::Version
|
|
120
|
-
version: '
|
|
120
|
+
version: '9.0'
|
|
121
121
|
type: :development
|
|
122
122
|
prerelease: false
|
|
123
123
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -127,7 +127,7 @@ dependencies:
|
|
|
127
127
|
version: 3.6.0
|
|
128
128
|
- - "<"
|
|
129
129
|
- !ruby/object:Gem::Version
|
|
130
|
-
version: '
|
|
130
|
+
version: '9.0'
|
|
131
131
|
- !ruby/object:Gem::Dependency
|
|
132
132
|
name: capybara-selenium
|
|
133
133
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -177,7 +177,10 @@ files:
|
|
|
177
177
|
- lib/ember_cli/build_monitor.rb
|
|
178
178
|
- lib/ember_cli/command.rb
|
|
179
179
|
- lib/ember_cli/configuration.rb
|
|
180
|
+
- lib/ember_cli/deploy/dev_server.rb
|
|
180
181
|
- lib/ember_cli/deploy/file.rb
|
|
182
|
+
- lib/ember_cli/dev_server.rb
|
|
183
|
+
- lib/ember_cli/dev_server_proxy.rb
|
|
181
184
|
- lib/ember_cli/ember_constraint.rb
|
|
182
185
|
- lib/ember_cli/engine.rb
|
|
183
186
|
- lib/ember_cli/errors.rb
|
|
@@ -214,7 +217,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
214
217
|
- !ruby/object:Gem::Version
|
|
215
218
|
version: '0'
|
|
216
219
|
requirements: []
|
|
217
|
-
rubygems_version: 4.0.
|
|
220
|
+
rubygems_version: 4.0.20
|
|
218
221
|
specification_version: 4
|
|
219
222
|
summary: Integration between Ember CLI and Rails
|
|
220
223
|
test_files: []
|