proscenium 0.11.0.pre.7-x86_64-darwin → 0.11.0.pre.8-x86_64-darwin
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +23 -6
- data/lib/proscenium/builder.rb +16 -5
- data/lib/proscenium/ext/proscenium +0 -0
- data/lib/proscenium/ext/proscenium.h +1 -1
- data/lib/proscenium/importer.rb +1 -1
- data/lib/proscenium/middleware/engines.rb +37 -0
- data/lib/proscenium/middleware/esbuild.rb +3 -3
- data/lib/proscenium/middleware.rb +10 -2
- data/lib/proscenium/monkey.rb +8 -0
- data/lib/proscenium/railtie.rb +25 -17
- data/lib/proscenium/resolver.rb +6 -10
- data/lib/proscenium/templates/rescues/build_error.html.erb +27 -0
- data/lib/proscenium/version.rb +1 -1
- data/lib/proscenium.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aec72bb2fdbfb6fdc6862af4a350188e6a1a851be686cff124b528fa4764a659
|
4
|
+
data.tar.gz: 657d521ec0f5b6baea484baf80495114c58421eee7a20d11cb2ce264b32e1515
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 689f2dc2829a7260c13a5881941da8ecc4c7b8c16a89d572ab297872be5118ca7a2b4c667ddc218a8f352bcc03a0802bb08f52b65fdaf136dea9aa1b422b2f2e
|
7
|
+
data.tar.gz: 8ed0cb3e9ed37e60b0782346032ad2036266e7a58e761ed0accbc927afc91732bfc83eaafa18487ad90fdb6876bac9302f651eb8732b2c2862c3579f2a11607d
|
data/README.md
CHANGED
@@ -757,18 +757,35 @@ Rails.application.config.proscenium.cache_max_age = 12.months.to_i
|
|
757
757
|
|
758
758
|
Proscenium brings back RJS! Any path ending in .rjs will be served from your Rails app. This allows you to import server rendered javascript.
|
759
759
|
|
760
|
+
## Resolution
|
760
761
|
|
761
|
-
|
762
|
-
|
763
|
-
Proscenium will serve files ending with any of these extension: `js,mjs,ts,css,jsx,tsx` from the following directories, and their sub-directories: `/app`, `/lib`, `/config`, `/node_modules`, `/vendor`.
|
762
|
+
Proscenium will serve files ending with any of these extension: `js,mjs,ts,css,jsx,tsx` from the following directories, and their sub-directories of your Rails application's root: `/app`, `/lib`, `/config`, `/node_modules`, `/vendor`.
|
764
763
|
|
765
764
|
So a file at `/app/views/users/index.js` will be served from `https://yourapp.com/app/views/users/index.js`.
|
766
765
|
|
767
|
-
You can continue to access any file in the `/public` directory as you normally would
|
766
|
+
You can continue to access any file in the `/public` directory as you normally would. Proscenium will not process files in the `/public` directory.
|
767
|
+
|
768
|
+
If requesting a file that exists in a root directory and the public directory, the file in the public directory will be served. For example, if you have a file at `/lib/foo.js` and `/public/lib/foo.js`, and you request `/lib/foo.js`, the file in the public directory (`/public/lib/foo.js`) will be served.
|
769
|
+
|
770
|
+
### Assets from Rails Engines
|
771
|
+
|
772
|
+
Proscenium can serve assets from Rails Engines that are installed in your Rails app.
|
773
|
+
|
774
|
+
An engine that wants to expose its assets via Proscenium to the application must add Proscenium as a dependency, and add itself to the list of engines in the Proscenium config options `Proscenium.config.engines`.
|
775
|
+
|
776
|
+
For example, we have a gem called `gem1` that has Proscenium as a dependency, and exposes a Rails engine. It has some assets that it wants to expose to the application. To do this, it adds itself to the list of engines in the Proscenium config `engines` option:
|
777
|
+
|
778
|
+
```ruby
|
779
|
+
class Gem1::Engine < ::Rails::Engine
|
780
|
+
config.proscenium.engines << self
|
781
|
+
end
|
782
|
+
```
|
783
|
+
|
784
|
+
When this gem is installed in any Rails application, its assets will be available at the URL `/gem1/...`. For example, if the gem has a file `lib/styles.css`, it can be requested at `/gem1/lib/styles.css`.
|
768
785
|
|
769
|
-
|
786
|
+
The same directories and file extensions are supported as for the application itself.
|
770
787
|
|
771
|
-
|
788
|
+
It is important to note that the application takes precedence over the gem. So if the application has a file at `/public/gem1/lib/styles.css`, and the gem also has a file at `/lib/styles.css`, then the file in the application will be served. This is because both files would be accessible at the same URL: `/gem1/lib/styles.css`.
|
772
789
|
|
773
790
|
## Thanks
|
774
791
|
|
data/lib/proscenium/builder.rb
CHANGED
@@ -29,6 +29,7 @@ module Proscenium
|
|
29
29
|
:string, # Proscenium gem root
|
30
30
|
:environment, # Rails environment as a Symbol
|
31
31
|
:bool, # code splitting enabled?
|
32
|
+
:string, # engine names and paths as a JSON string
|
32
33
|
:bool # debugging enabled?
|
33
34
|
], Result.by_value
|
34
35
|
|
@@ -45,12 +46,17 @@ module Proscenium
|
|
45
46
|
end
|
46
47
|
|
47
48
|
class BuildError < StandardError
|
48
|
-
attr_reader :error
|
49
|
+
attr_reader :error
|
49
50
|
|
50
|
-
def initialize(
|
51
|
-
error = Oj.load(error, mode: :strict).deep_transform_keys(&:underscore)
|
51
|
+
def initialize(error)
|
52
|
+
@error = Oj.load(error, mode: :strict).deep_transform_keys(&:underscore)
|
52
53
|
|
53
|
-
|
54
|
+
msg = @error['text']
|
55
|
+
if (location = @error['location'])
|
56
|
+
msg << " at #{location['file']}:#{location['line']}:#{location['column']}"
|
57
|
+
end
|
58
|
+
|
59
|
+
super msg
|
54
60
|
end
|
55
61
|
end
|
56
62
|
|
@@ -82,9 +88,10 @@ module Proscenium
|
|
82
88
|
Pathname.new(__dir__).join('..', '..').to_s,
|
83
89
|
Rails.env.to_sym,
|
84
90
|
Proscenium.config.code_splitting,
|
91
|
+
engines.to_json,
|
85
92
|
Proscenium.config.debug)
|
86
93
|
|
87
|
-
raise BuildError
|
94
|
+
raise BuildError, result[:response] unless result[:success]
|
88
95
|
|
89
96
|
result[:response]
|
90
97
|
end
|
@@ -116,6 +123,10 @@ module Proscenium
|
|
116
123
|
q ? "--cache-query-string #{q}" : nil
|
117
124
|
end
|
118
125
|
|
126
|
+
def engines
|
127
|
+
Proscenium.config.engines.to_h { |e| [e.engine_name, e.root.to_s] }
|
128
|
+
end
|
129
|
+
|
119
130
|
def import_map
|
120
131
|
return unless (path = Rails.root&.join('config'))
|
121
132
|
|
Binary file
|
@@ -97,7 +97,7 @@ extern "C" {
|
|
97
97
|
// - codeSpitting?
|
98
98
|
// - debug?
|
99
99
|
//
|
100
|
-
extern struct Result build(char* filepath, char* baseUrl, char* importMap, char* envVars, char* appRoot, char* gemPath, unsigned int env, GoUint8 codeSplitting, GoUint8 debug);
|
100
|
+
extern struct Result build(char* filepath, char* baseUrl, char* importMap, char* envVars, char* appRoot, char* gemPath, unsigned int env, GoUint8 codeSplitting, char* engines, GoUint8 debug);
|
101
101
|
|
102
102
|
// Resolve the given `path` relative to the `root`.
|
103
103
|
//
|
data/lib/proscenium/importer.rb
CHANGED
@@ -21,7 +21,7 @@ module Proscenium
|
|
21
21
|
class << self
|
22
22
|
# Import the given `filepath`. This is idempotent - it will never include duplicates.
|
23
23
|
#
|
24
|
-
# @param filepath [String] Absolute path (relative to Rails root) of the file to import.
|
24
|
+
# @param filepath [String] Absolute URL path (relative to Rails root) of the file to import.
|
25
25
|
# Should be the actual asset file, eg. app.css, some/component.js.
|
26
26
|
# @param resolve [String] description of the file to resolve and import.
|
27
27
|
# @return [String] the digest of the imported file path if a css module (*.module.css).
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Proscenium
|
4
|
+
class Middleware
|
5
|
+
# This middleware handles requests for assets in Rails engines. An engine that wants to expose
|
6
|
+
# its assets via Proscenium to the application must add itself to the list of engines in the
|
7
|
+
# Proscenium config options `Proscenium.config.engines`.
|
8
|
+
#
|
9
|
+
# For example, we have a gem that exposes a Rails engine.
|
10
|
+
#
|
11
|
+
# module Gem1
|
12
|
+
# class Engine < ::Rails::Engine
|
13
|
+
# config.proscenium.engines << self
|
14
|
+
# end
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# When this gem is installed in any Rails application, its assets will be available at the URL
|
18
|
+
# `/gem1/...`. For example, if the gem has a file `lib/styles.css`, it can be requested at
|
19
|
+
# `/gem1/lib/styles.css`.
|
20
|
+
#
|
21
|
+
class Engines < Esbuild
|
22
|
+
def real_path
|
23
|
+
@real_path ||= Pathname.new(@request.path.delete_prefix("/#{engine.engine_name}")).to_s
|
24
|
+
end
|
25
|
+
|
26
|
+
def root_for_readable
|
27
|
+
engine.root
|
28
|
+
end
|
29
|
+
|
30
|
+
def engine
|
31
|
+
@engine ||= Proscenium.config.engines.find do |engine|
|
32
|
+
@request.path.start_with?("/#{engine.engine_name}")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -20,9 +20,9 @@ module Proscenium
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def attempt
|
23
|
-
render_response
|
24
|
-
|
25
|
-
rescue
|
23
|
+
render_response Builder.build(path_to_build, root: Rails.root.to_s,
|
24
|
+
base_url: @request.base_url)
|
25
|
+
rescue Builder::CompileError => e
|
26
26
|
raise self.class::CompileError, { file: @request.fullpath, detail: e.message }, caller
|
27
27
|
end
|
28
28
|
end
|
@@ -9,6 +9,7 @@ module Proscenium
|
|
9
9
|
|
10
10
|
autoload :Base
|
11
11
|
autoload :Esbuild
|
12
|
+
autoload :Engines
|
12
13
|
autoload :Runtime
|
13
14
|
autoload :Url
|
14
15
|
|
@@ -42,12 +43,19 @@ module Proscenium
|
|
42
43
|
def find_type(request)
|
43
44
|
return Url if request.path.match?(%r{^/https?%3A%2F%2F})
|
44
45
|
return Runtime if request.path.match?(%r{^/@proscenium/})
|
46
|
+
return Esbuild if Pathname.new(request.path).fnmatch?(app_path_glob, File::FNM_EXTGLOB)
|
45
47
|
|
46
|
-
|
48
|
+
Engines if Pathname.new(request.path).fnmatch?(engines_path_glob, File::FNM_EXTGLOB)
|
47
49
|
end
|
48
50
|
|
49
51
|
def app_path_glob
|
50
|
-
"/{#{Proscenium::ALLOWED_DIRECTORIES
|
52
|
+
"/{#{Proscenium::ALLOWED_DIRECTORIES}}/**.{#{FILE_EXTENSIONS.join(',')}}"
|
53
|
+
end
|
54
|
+
|
55
|
+
def engines_path_glob
|
56
|
+
names = Proscenium.config.engines.map(&:engine_name)
|
57
|
+
|
58
|
+
"/{#{names.join(',')}}/{#{Proscenium::ALLOWED_DIRECTORIES}}/**.{#{FILE_EXTENSIONS.join(',')}}"
|
51
59
|
end
|
52
60
|
|
53
61
|
# TODO: handle precompiled assets
|
data/lib/proscenium/monkey.rb
CHANGED
@@ -3,6 +3,14 @@
|
|
3
3
|
module Proscenium
|
4
4
|
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
5
5
|
module Monkey
|
6
|
+
module DebugView
|
7
|
+
def initialize(assigns)
|
8
|
+
paths = [RESCUES_TEMPLATE_PATH, Rails.root.join('lib', 'templates').to_s]
|
9
|
+
lookup_context = ActionView::LookupContext.new(paths)
|
10
|
+
super(lookup_context, assigns, nil)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
6
14
|
module TemplateRenderer
|
7
15
|
private
|
8
16
|
|
data/lib/proscenium/railtie.rb
CHANGED
@@ -29,31 +29,29 @@ module Proscenium
|
|
29
29
|
# defined means a faster build, as esbuild will have less to do.
|
30
30
|
config.proscenium.env_vars = Set.new
|
31
31
|
|
32
|
-
#
|
32
|
+
# Rails engines to expose and allow Proscenium to serve their assets.
|
33
33
|
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
37
|
-
# path to the gem's root, and side load the asset.
|
38
|
-
#
|
39
|
-
# Side loading gems rely on NPM and a package.json file in the gem root. This ensures that any
|
40
|
-
# dependencies are resolved correctly. This is required even if your gem has no package
|
41
|
-
# dependencies.
|
34
|
+
# A Rails engine that has assets, can add Proscenium as a gem dependency, and then add itself
|
35
|
+
# to this list. Proscenium will then serve the engine's assets at the URL path beginning with
|
36
|
+
# the engine name.
|
42
37
|
#
|
43
38
|
# Example:
|
44
|
-
#
|
45
|
-
#
|
46
|
-
#
|
47
|
-
|
48
|
-
|
39
|
+
# class Gem1::Engine < ::Rails::Engine
|
40
|
+
# config.proscenium.engines << self
|
41
|
+
# end
|
42
|
+
config.proscenium.engines = Set.new
|
43
|
+
|
44
|
+
config.action_dispatch.rescue_templates = {
|
45
|
+
'Proscenium::Builder::BuildError' => 'build_error'
|
46
|
+
}
|
49
47
|
|
50
48
|
initializer 'proscenium.middleware' do |app|
|
51
49
|
app.middleware.insert_after ActionDispatch::Static, Middleware
|
52
|
-
app.middleware.insert_after ActionDispatch::Static, Rack::ETag, 'no-cache'
|
53
|
-
app.middleware.insert_after ActionDispatch::Static, Rack::ConditionalGet
|
50
|
+
# app.middleware.insert_after ActionDispatch::Static, Rack::ETag, 'no-cache'
|
51
|
+
# app.middleware.insert_after ActionDispatch::Static, Rack::ConditionalGet
|
54
52
|
end
|
55
53
|
|
56
|
-
initializer 'proscenium.
|
54
|
+
initializer 'proscenium.monkey_patches' do
|
57
55
|
ActiveSupport.on_load(:action_view) do
|
58
56
|
ActionView::TemplateRenderer.prepend Monkey::TemplateRenderer
|
59
57
|
ActionView::PartialRenderer.prepend Monkey::PartialRenderer
|
@@ -71,3 +69,13 @@ module Proscenium
|
|
71
69
|
end
|
72
70
|
end
|
73
71
|
end
|
72
|
+
|
73
|
+
# Monkey path ActionDispatch::DebugView to use our custom error template on BuildError exceptions.
|
74
|
+
class ActionDispatch::DebugView
|
75
|
+
def initialize(assigns)
|
76
|
+
paths = [RESCUES_TEMPLATE_PATH,
|
77
|
+
Proscenium::Railtie.root.join('lib', 'proscenium', 'templates').to_s]
|
78
|
+
lookup_context = ActionView::LookupContext.new(paths)
|
79
|
+
super(lookup_context, assigns, nil)
|
80
|
+
end
|
81
|
+
end
|
data/lib/proscenium/resolver.rb
CHANGED
@@ -11,7 +11,9 @@ module Proscenium
|
|
11
11
|
#
|
12
12
|
# @param path [String] Can be URL path, file system path, or bare specifier (ie. NPM package).
|
13
13
|
# @return [String] URL path.
|
14
|
-
|
14
|
+
#
|
15
|
+
# rubocop:disable Metrics/*
|
16
|
+
def self.resolve(path)
|
15
17
|
self.resolved ||= {}
|
16
18
|
|
17
19
|
self.resolved[path] ||= begin
|
@@ -21,15 +23,8 @@ module Proscenium
|
|
21
23
|
|
22
24
|
if path.start_with?('@proscenium/')
|
23
25
|
"/#{path}"
|
24
|
-
elsif (
|
25
|
-
|
26
|
-
end)
|
27
|
-
unless (package_name = gem[1][:package_name] || gem[0])
|
28
|
-
# TODO: manually resolve the path without esbuild
|
29
|
-
raise PathResolutionFailed, path
|
30
|
-
end
|
31
|
-
|
32
|
-
Builder.resolve "#{package_name}/#{path.delete_prefix("#{gem[1][:root]}/")}"
|
26
|
+
elsif (engine = Proscenium.config.engines.find { |e| path.start_with? "#{e.root}/" })
|
27
|
+
path.sub(/^#{engine.root}/, "/#{engine.engine_name}")
|
33
28
|
elsif path.start_with?("#{Rails.root}/")
|
34
29
|
path.delete_prefix Rails.root.to_s
|
35
30
|
else
|
@@ -37,5 +32,6 @@ module Proscenium
|
|
37
32
|
end
|
38
33
|
end
|
39
34
|
end
|
35
|
+
# rubocop:enable Metrics/*
|
40
36
|
end
|
41
37
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
<header>
|
2
|
+
<h1>
|
3
|
+
<%= @exception.class.to_s %>
|
4
|
+
</h1>
|
5
|
+
</header>
|
6
|
+
|
7
|
+
<main role="main" id="container">
|
8
|
+
<%= render "rescues/message_and_suggestions", exception: @exception %>
|
9
|
+
|
10
|
+
<% if @exception.error['location'] %>
|
11
|
+
<div class="source">
|
12
|
+
<div class="data">
|
13
|
+
<pre>
|
14
|
+
|
15
|
+
<%= @exception.error['location']['file'] %>:<%= @exception.error['location']['line'] %>:<%= @exception.error['location']['column'] %>
|
16
|
+
|
17
|
+
<%= @exception.error['location']['line'].to_s.rjust 5 %> │ <%= @exception.error['location']['line_text'] %>
|
18
|
+
│ <%= (@exception.error['location']['length'] > 1 ? "~" * @exception.error['location']['length'] : "^").rjust(@exception.error['location']['column'] + @exception.error['location']['length']) %>
|
19
|
+
<%- if @exception.error['location']['suggestion'].present? -%> + │ <%= @exception.error['location']['suggestion'].rjust(@exception.error['location']['column'] + 1) %>
|
20
|
+
<% else %> <%- end -%>
|
21
|
+
</pre>
|
22
|
+
</div>
|
23
|
+
</div>
|
24
|
+
<% end %>
|
25
|
+
|
26
|
+
<%= render template: "rescues/_request_and_response" %>
|
27
|
+
</main>
|
data/lib/proscenium/version.rb
CHANGED
data/lib/proscenium.rb
CHANGED
@@ -8,7 +8,7 @@ module Proscenium
|
|
8
8
|
FILE_EXTENSIONS = ['js', 'mjs', 'ts', 'jsx', 'tsx', 'css', 'js.map', 'mjs.map', 'jsx.map',
|
9
9
|
'ts.map', 'tsx.map', 'css.map'].freeze
|
10
10
|
|
11
|
-
ALLOWED_DIRECTORIES =
|
11
|
+
ALLOWED_DIRECTORIES = 'app,lib,config,vendor,node_modules'
|
12
12
|
|
13
13
|
# Environment variables that should always be passed to the builder.
|
14
14
|
DEFAULT_ENV_VARS = Set['RAILS_ENV', 'NODE_ENV'].freeze
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: proscenium
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.11.0.pre.
|
4
|
+
version: 0.11.0.pre.8
|
5
5
|
platform: x86_64-darwin
|
6
6
|
authors:
|
7
7
|
- Joel Moss
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-09-
|
11
|
+
date: 2023-09-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -105,6 +105,7 @@ files:
|
|
105
105
|
- lib/proscenium/log_subscriber.rb
|
106
106
|
- lib/proscenium/middleware.rb
|
107
107
|
- lib/proscenium/middleware/base.rb
|
108
|
+
- lib/proscenium/middleware/engines.rb
|
108
109
|
- lib/proscenium/middleware/esbuild.rb
|
109
110
|
- lib/proscenium/middleware/runtime.rb
|
110
111
|
- lib/proscenium/middleware/url.rb
|
@@ -118,6 +119,7 @@ files:
|
|
118
119
|
- lib/proscenium/resolver.rb
|
119
120
|
- lib/proscenium/side_load.rb
|
120
121
|
- lib/proscenium/source_path.rb
|
122
|
+
- lib/proscenium/templates/rescues/build_error.html.erb
|
121
123
|
- lib/proscenium/utils.rb
|
122
124
|
- lib/proscenium/version.rb
|
123
125
|
- lib/proscenium/view_component.rb
|