proscenium 0.11.0.pre.7-x86_64-linux → 0.11.0.pre.8-x86_64-linux
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 +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: 90ea3174caa7312b84d189b74ec6a5171cf0ee934eec92f3b0bca057aa4aee81
|
4
|
+
data.tar.gz: 9c865f250eb246a0e418a0c88cdd53db37b86f907fe61c90bfc8c6bf49b6a8aa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9c789cf77502528b0132e29199ae2896a7aa2da6ed438ce7a0f42ffa72b27875da48209edad61dd240d0d24d3797ce0d1d4166c506b569a462a59e733093e527
|
7
|
+
data.tar.gz: 8c038b9c6afca87a4b16ea3efd89f6309a270d907b249fa3c33523ba15bee7e8ad1c5acdf29214f49bd3c4fa75c9e743f5d3cbe4adb48478fdbac018e3a8cf85
|
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-linux
|
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
|