jets 2.1.0 → 2.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7210442948a1180913859f3afbd0aebb049560adfdf53faf02357c4f299bb246
4
- data.tar.gz: b94be0bc50ec242e9c6e908050a4ddd342874e9026cdf12f28ae54e465d12303
3
+ metadata.gz: 82e56d77408579a757373a115134668315a2c47fdbcd297f8eae827951274f6a
4
+ data.tar.gz: 0152fbf8fe291033319761e987667026a77958b67398ba237d9152cc70a00615
5
5
  SHA512:
6
- metadata.gz: 95f6b7c61d0867b09c6af7f099fc84ec3de07defec86707f8aaadc8aac2da318557260b828142133384350163bd0bcbccc0a0f5bd204eb1c2645be0791e9637e
7
- data.tar.gz: 0cb91a7f2593103a557a59f0d3d8b2732f9ba196725ed2825d12b34db2f2879e72bff137e8193411aecb0e31522c704bacbf2bbf9b5329242dad514655f38b5d
6
+ metadata.gz: f638230df0a341ee7b4e0a73355a89a650a78178d7ebb46326c4215d40ea4d33d6648a3d0909a98789e416b4c03c59bae8b5c8e5a94e254c45de78915e5214c4
7
+ data.tar.gz: 5a9e606725ae25d18c3ce4b1ea901780d7062245035c20a9d5139566b0e92ab998d9c3e6d2bb14081a5e77c04bfa5bb871ed95db51ac48467c42f186292b82ab
@@ -3,6 +3,13 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  This project *loosely tries* to adhere to [Semantic Versioning](http://semver.org/).
5
5
 
6
+ ## [2.1.1]
7
+ - #347 Add documentation about torch vs. warm
8
+ - #348 Provide another minimal privileges example
9
+ - #349 Fix route params for specs
10
+ - #350 Fix config.autoload_paths setting
11
+ - remove the jets c warning
12
+
6
13
  ## [2.1.0]
7
14
  - #345 upgrade to use rails 6 components
8
15
 
@@ -13,8 +13,9 @@ class Jets::Application
13
13
 
14
14
  def setup!
15
15
  load_default_config
16
- autoload_paths = config.autoload_paths + config.extra_autoload_paths
17
- setup_auto_load_paths(autoload_paths)
16
+ setup_autoload_paths
17
+ setup_ignore_paths
18
+ main_loader_setup
18
19
  end
19
20
 
20
21
  def configs!
@@ -99,14 +100,29 @@ class Jets::Application
99
100
  end
100
101
  end
101
102
 
102
- def setup_auto_load_paths(autoload_paths=default_autoload_paths)
103
- loader = Jets::Autoloaders.main
103
+ def main_loader
104
+ Jets::Autoloaders.main
105
+ end
106
+
107
+ def setup_autoload_paths
108
+ autoload_paths = default_autoload_paths + config.autoload_paths
104
109
  autoload_paths.each do |path|
105
110
  next unless File.exist?(path)
106
- loader.push_dir(path)
111
+ main_loader.push_dir(path)
107
112
  end
108
- loader.enable_reloading if Jets.env.development?
109
- loader.setup
113
+ end
114
+
115
+ # Allow use to add config.ignore_paths just in case there's some case Jets hasn't considered
116
+ def setup_ignore_paths
117
+ ignore_paths = default_ignore_paths + config.ignore_paths
118
+ ignore_paths.each do |path|
119
+ main_loader.ignore("#{Jets.root}/#{path}")
120
+ end
121
+ end
122
+
123
+ def main_loader_setup
124
+ main_loader.enable_reloading if Jets.env.development?
125
+ main_loader.setup # only respected on the first call
110
126
  end
111
127
 
112
128
  def each_app_autoload_path(expression)
@@ -54,8 +54,8 @@ class Jets::Application
54
54
  config = ActiveSupport::OrderedOptions.new
55
55
  config.project_name = parse_project_name # must set early because other configs requires this
56
56
  config.cors = false
57
- config.autoload_paths = default_autoload_paths
58
- config.extra_autoload_paths = []
57
+ config.autoload_paths = [] # allows for customization
58
+ config.ignore_paths = [] # allows for customization
59
59
  config.logger = Jets::Logger.new($stderr)
60
60
 
61
61
  # function properties defaults
@@ -176,5 +176,12 @@ class Jets::Application
176
176
 
177
177
  paths
178
178
  end
179
+
180
+ def default_ignore_paths
181
+ %w[
182
+ app/functions
183
+ app/shared/functions
184
+ ]
185
+ end
179
186
  end
180
187
  end
@@ -27,7 +27,8 @@ module Jets
27
27
  Zeitwerk::Loader.new.tap do |loader|
28
28
  loader.tag = "jets.main"
29
29
  # loader.inflector = Inflector.new # TODO: allow custom app inflector
30
- loader.ignore("#{Jets.root}/app/shared/functions")
30
+ # The main loader is configured later on in Jets::Application#setup_autoload_paths
31
+ # because it needs access to Jets.root and Jets.config settings
31
32
  end
32
33
  end
33
34
  memoize :main
@@ -11,7 +11,7 @@ class Jets::Booter
11
11
 
12
12
  Jets.application.setup!
13
13
 
14
- # Turbines are loaded after setup_auto_load_paths in Jets.application.setup! Some Turbine options are defined
14
+ # Turbines are loaded after setup_autoload_paths in Jets.application.setup! Some Turbine options are defined
15
15
  # in the project so setup must happen before internal Turbines are loaded.
16
16
  load_internal_turbines
17
17
 
@@ -25,7 +25,7 @@ class Jets::Booter
25
25
 
26
26
  setup_db # establish db connections in Lambda Execution Context.
27
27
  # The eager load calls connects_to in models and establish those connections in Lambda Execution Context also.
28
- Jets::Autoloaders.main.eager_load # Eager load project code. Rather have user find out early than later on AWS Lambda.
28
+ eager_load
29
29
 
30
30
  # TODO: Figure out how to build middleware during Jets.boot without breaking jets new and webpacker:install
31
31
  # build_middleware_stack
@@ -33,6 +33,22 @@ class Jets::Booter
33
33
  @booted = true
34
34
  end
35
35
 
36
+ def eager_load
37
+ preload_extensions
38
+ Jets::Autoloaders.main.eager_load # Eager load project code. Rather have user find out early than later on AWS Lambda.
39
+ end
40
+
41
+ def preload_extensions
42
+ base_path = "#{Jets.root}/app/extensions"
43
+ Dir.glob("#{base_path}/**/*.rb").each do |path|
44
+ next unless File.file?(path)
45
+
46
+ class_name = path.sub("#{base_path}/", '').sub(/\.rb/,'').camelize
47
+ klass = class_name.constantize # autoload
48
+ Jets::Lambda::Functions.extend(klass)
49
+ end
50
+ end
51
+
36
52
  # Using ActiveRecord outside of Rails, so we need to set up the db connection ourself.
37
53
  #
38
54
  # Only connects to database for ActiveRecord and when config/database.yml exists.
@@ -78,8 +78,7 @@ class Jets::CLI
78
78
 
79
79
  # jets generate is a special command requires doesn't puts out the help menu automatically when
80
80
  # `jets generate` is called without additional args. We'll take it over early and fix it here.
81
- autocomplete_command = Jets::Commands::Base.autocomplete(args[0])
82
- generate = autocomplete_command == "generate"
81
+ generate = full_command == "generate"
83
82
 
84
83
  if generate && ((args.size == 1 || help_flags.include?(args.last)) || args.size == 2)
85
84
  puts Jets::Generator.help
@@ -138,7 +138,6 @@ class Jets::Commands::Base < Thor
138
138
  def eager_load!
139
139
  return if Jets::Turbo.afterburner?
140
140
 
141
- Jets.application.setup_auto_load_paths # in case an app/extension is defined
142
141
  Jets::Autoloaders.once.eager_load
143
142
  end
144
143
  memoize :eager_load!
@@ -12,7 +12,7 @@ Jets.application.configure do
12
12
  <% end -%>
13
13
 
14
14
  # config.env_extra = 2 # can also set this with JETS_ENV_EXTRA
15
- # config.extra_autoload_paths = []
15
+ # config.autoload_paths = []
16
16
 
17
17
  # config.asset_base_url = 'https://cloudfront.domain.com/assets' # example
18
18
 
@@ -14,6 +14,7 @@ module Jets::Commands
14
14
  inject_csrf_meta_tags
15
15
  update_crud_js
16
16
  update_config_application_rb
17
+ update_autoload_paths_config
17
18
  puts "Upgrade complete."
18
19
  end
19
20
 
@@ -75,5 +76,30 @@ module Jets::Commands
75
76
  IO.write(app_rb, content)
76
77
  puts "Update: #{app_rb} with default_protect_from_forgery"
77
78
  end
79
+
80
+ def update_autoload_paths_config
81
+ app_rb = "config/application.rb"
82
+ lines = IO.readlines(app_rb)
83
+
84
+ new_config = lines.find { |l| l.include?('config.autoload_paths') }
85
+ return if new_config
86
+
87
+ old_config = lines.find { |l| l.include?('config.extra_autoload_paths') }
88
+ return unless old_config
89
+
90
+ lines.map! do |line|
91
+ md = line.match(/config\.extra_autoload_paths(.*)/)
92
+ if md
93
+ rest = md[1]
94
+ " config.autoload_paths#{rest}"
95
+ else
96
+ line
97
+ end
98
+ end
99
+
100
+ content = lines.join
101
+ IO.write(app_rb, content)
102
+ puts "Update: #{app_rb} with config.autoload_paths"
103
+ end
78
104
  end
79
105
  end
@@ -5,102 +5,18 @@ class Jets::Controller::Middleware::Local
5
5
  end
6
6
 
7
7
  def find_route
8
- reset_routes!
9
- # Precedence:
10
- # 1. Routes with no captures get highest precedence: posts/new
11
- # 2. Then we consider the routes with captures: post/:id
12
- #
13
- # Within these 2 groups we consider the routes with the longest path first
14
- # since posts/:id and posts/:id/edit can both match.
15
- routes = router.ordered_routes
16
- route = routes.find do |r|
17
- route_found?(r)
18
- end
19
- route
8
+ Jets::Router::Finder.new(method, path).run
20
9
  end
21
10
 
22
- # "hot reload" for development
23
- def reset_routes!
24
- return unless Jets.env.development?
11
+ private
12
+ attr_reader :env
25
13
 
26
- Jets::Router.clear!
27
- Jets.application.load_routes(refresh: true)
14
+ def path
15
+ env["REQUEST_METHOD"] || "GET"
28
16
  end
29
17
 
30
- def route_found?(route)
31
- request_method = @env["REQUEST_METHOD"] || "GET"
32
- actual_path = @env["PATH_INFO"].sub(/^\//,'') # remove beginning slash
33
-
34
- # Immediately stop checking when the request method: GET, POST, ANY, etc
35
- # doesnt match.
36
- return false if request_method != route.method and route.method != "ANY"
37
-
38
- path = route.path
39
-
40
- if actual_path == path
41
- # regular string match detection
42
- return true # exact route matches are highest precedence
43
- end
44
-
45
- # Check path for route capture and wildcard matches:
46
- # A colon (:) means the variable has a variable
47
- if path.include?(':') # 2nd highest precedence
48
- capture_detection(path, actual_path) # early return true or false
49
- # A star (*) means the variable has a glob
50
- elsif path.include?('*') # lowest precedence
51
- proxy_detection(path, actual_path) # early return true or false
52
- else
53
- false # reach here, means no route matched
54
- end
55
- end
56
-
57
- # catchall/globbing/wildcard/proxy routes. Examples:
58
- #
59
- # get "files/*path", to: "files#show"
60
- # get "others/*rest", to: "others#show"
61
- # get "*catchall", to: "public_files#show" # last catchall route for Jets
62
- #
63
- def proxy_detection(route_path, actual_path)
64
- # drop the proxy_segment
65
- leading_path = route_path.split('/')[0..-2].join('/')
66
-
67
- # get "*catchall", to: "public_files#show"
68
- if leading_path.empty? # This is the last catchall route "*catchall"
69
- return true # always return true here because the entire path
70
- # will always match
71
- end
72
-
73
- # Other types of wildcard route:
74
- #
75
- # get "files/*path", to: "files#show"
76
- # get "others/*rest", to: "others#show"
77
- unless leading_path.ends_with?('/')
78
- # Ensure trailing slash to make pattern matching stricter
79
- leading_path = "#{leading_path}/"
80
- end
81
-
82
- pattern = "^#{leading_path}"
83
- regexp = Regexp.new(pattern)
84
- !!regexp.match(actual_path) # could be true or false
85
- end
86
-
87
- def capture_detection(route_path, actual_path)
88
- # changes path to a string used for a regexp
89
- # posts/:id/edit => posts\/(.*)\/edit
90
-
91
- regexp_string = route_path.split('/').map do |s|
92
- s.include?(':') ? Jets::Router::Route::CAPTURE_REGEX : s
93
- end.join('\/')
94
- # make sure beginning and end of the string matches
95
- regexp_string = "^#{regexp_string}$"
96
-
97
- regexp = Regexp.new(regexp_string)
98
- !!regexp.match(actual_path) # could be true or false
99
- end
100
-
101
- def router
102
- return @router if @router
103
- @router = Jets.application.routes
18
+ def method
19
+ env["PATH_INFO"].sub(/^\//,'')
104
20
  end
105
21
  end
106
22
  end
@@ -401,19 +401,4 @@ module Jets::Lambda::Dsl
401
401
  end
402
402
  end # end of class << self
403
403
  end # end of included
404
-
405
- def self.add_custom_resource_extensions(base)
406
- base_path = "#{Jets.root}/app/extensions"
407
- Dir.glob("#{base_path}/**/*.rb").each do |path|
408
- next unless File.file?(path)
409
-
410
- class_name = path.sub("#{base_path}/", '').sub(/\.rb/,'').camelize
411
- klass = class_name.constantize # autoload
412
- base.extend(klass)
413
- end
414
- end
415
-
416
- def self.included(base)
417
- add_custom_resource_extensions(base)
418
- end
419
404
  end
@@ -0,0 +1,47 @@
1
+ class Jets::Router
2
+ class Finder
3
+ extend Memoist
4
+
5
+ def initialize(path, method)
6
+ @path = path
7
+ @method = method.to_s.upcase
8
+ end
9
+
10
+ def run
11
+ reset_routes!
12
+ # Precedence:
13
+ # 1. Routes with no captures get highest precedence: posts/new
14
+ # 2. Then we consider the routes with captures: post/:id
15
+ #
16
+ # Within these 2 groups we consider the routes with the longest path first
17
+ # since posts/:id and posts/:id/edit can both match.
18
+ routes = router.ordered_routes
19
+ route = routes.find do |r|
20
+ matcher.match?(r)
21
+ end
22
+ route
23
+ end
24
+
25
+ private
26
+
27
+ attr_reader :path, :method
28
+
29
+ # "hot reload" for development
30
+ def reset_routes!
31
+ return unless Jets.env.development?
32
+
33
+ Jets::Router.clear!
34
+ Jets.application.load_routes(refresh: true)
35
+ end
36
+
37
+ def matcher
38
+ Jets::Router::Matcher.new(path, method)
39
+ end
40
+ memoize :matcher
41
+
42
+ def router
43
+ Jets.application.routes
44
+ end
45
+ memoize :router
46
+ end
47
+ end
@@ -0,0 +1,81 @@
1
+ class Jets::Router
2
+ class Matcher
3
+ def initialize(path, method)
4
+ @path = path.sub(/^\//,'')
5
+ @method = method.to_s.upcase
6
+ end
7
+
8
+ def match?(route)
9
+ # Immediately stop checking when the request method: GET, POST, ANY, etc
10
+ # doesnt match.
11
+
12
+ return false if method != route.method && route.method != "ANY"
13
+
14
+ route_path = route.path
15
+
16
+ if path == route_path
17
+ # regular string match detection
18
+ return true # exact route matches are highest precedence
19
+ end
20
+
21
+ # Check path for route capture and wildcard matches:
22
+ # A colon (:) means the variable has a variable
23
+ if route_path.include?(':') # 2nd highest precedence
24
+ capture_detection(route_path, path) # early return true or false
25
+ # A star (*) means the variable has a glob
26
+ elsif route_path.include?('*') # lowest precedence
27
+ proxy_detection(route_path, path) # early return true or false
28
+ else
29
+ false # reach here, means no route matched
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ attr_reader :path, :method
36
+
37
+ # catchall/globbing/wildcard/proxy routes. Examples:
38
+ #
39
+ # get "files/*path", to: "files#show"
40
+ # get "others/*rest", to: "others#show"
41
+ # get "*catchall", to: "public_files#show" # last catchall route for Jets
42
+ #
43
+ def proxy_detection(route_path, actual_path)
44
+ # drop the proxy_segment
45
+ leading_path = route_path.split('/')[0..-2].join('/')
46
+
47
+ # get "*catchall", to: "public_files#show"
48
+ if leading_path.empty? # This is the last catchall route "*catchall"
49
+ return true # always return true here because the entire path
50
+ # will always match
51
+ end
52
+
53
+ # Other types of wildcard route:
54
+ #
55
+ # get "files/*path", to: "files#show"
56
+ # get "others/*rest", to: "others#show"
57
+ unless leading_path.ends_with?('/')
58
+ # Ensure trailing slash to make pattern matching stricter
59
+ leading_path = "#{leading_path}/"
60
+ end
61
+
62
+ pattern = "^#{leading_path}"
63
+ regexp = Regexp.new(pattern)
64
+ !!regexp.match(actual_path) # could be true or false
65
+ end
66
+
67
+ def capture_detection(route_path, actual_path)
68
+ # changes path to a string used for a regexp
69
+ # posts/:id/edit => posts\/(.*)\/edit
70
+ regexp_string = route_path.split('/').map do |s|
71
+ s.include?(':') ? Jets::Router::Route::CAPTURE_REGEX : s
72
+ end.join('\/')
73
+ # make sure beginning and end of the string matches
74
+ regexp_string = "^#{regexp_string}$"
75
+
76
+ regexp = Regexp.new(regexp_string)
77
+
78
+ !!regexp.match(actual_path) # could be true or false
79
+ end
80
+ end
81
+ end
@@ -1,5 +1,7 @@
1
1
  module Jets::SpecHelpers::Controllers
2
2
  class Request
3
+ extend Memoist
4
+
3
5
  attr_accessor :method, :path, :headers, :params
4
6
  def initialize(method, path, headers={}, params={})
5
7
  @method, @path, @headers, @params = method, path, headers, params
@@ -7,14 +9,14 @@ module Jets::SpecHelpers::Controllers
7
9
 
8
10
  def event
9
11
  json = {}
10
- id_params = path.scan(%r{:([^/]+)}).flatten
12
+ id_params = route.path.scan(%r{:([^/]+)}).flatten
11
13
  expanded_path = path.dup
12
14
  path_parameters = {}
13
15
 
14
16
  id_params.each do |id_param|
15
- raise "missing param: :#{id_param}" unless params.path_params.include? id_param.to_sym
17
+ raise "missing param: :#{id_param}" unless path_params.include? id_param.to_sym
16
18
 
17
- path_param_value = params.path_params[id_param.to_sym]
19
+ path_param_value = path_params[id_param.to_sym]
18
20
  raise "Path param :#{id_param} value cannot be blank" if path_param_value.blank?
19
21
 
20
22
  expanded_path.gsub!(":#{id_param}", path_param_value.to_s)
@@ -50,19 +52,28 @@ module Jets::SpecHelpers::Controllers
50
52
  json
51
53
  end
52
54
 
53
- def find_route!
55
+ def path_params
56
+ params.path_params.reverse_merge(extract_parameters)
57
+ end
58
+ memoize :path_params
59
+
60
+ def extract_parameters
61
+ route.extract_parameters(normalized_path).symbolize_keys
62
+ end
63
+
64
+ def normalized_path
54
65
  path = self.path
55
66
  path = path[0..-2] if path.end_with? '/'
56
67
  path = path[1..-1] if path.start_with? '/'
68
+ path
69
+ end
57
70
 
58
- route = Jets::Router.routes.find { |r| r.path == path && r.method == method.to_s.upcase }
59
- raise "Route not found: #{method.to_s.upcase} #{path}" if route.blank?
60
-
61
- route
71
+ def route
72
+ Jets::Router::Finder.new(normalized_path, method).run
62
73
  end
74
+ memoize :route
63
75
 
64
76
  def dispatch!
65
- route = find_route!
66
77
  klass = Object.const_get(route.controller_name)
67
78
  controller = klass.new(event, {}, route.action_name)
68
79
  response = controller.process! # response is API Gateway Hash
@@ -1,3 +1,3 @@
1
1
  module Jets
2
- VERSION = "2.1.0"
2
+ VERSION = "2.1.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jets
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 2.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tung Nguyen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-08-18 00:00:00.000000000 Z
11
+ date: 2019-08-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionmailer
@@ -895,9 +895,11 @@ files:
895
895
  - lib/jets/router.rb
896
896
  - lib/jets/router/dsl.rb
897
897
  - lib/jets/router/error.rb
898
+ - lib/jets/router/finder.rb
898
899
  - lib/jets/router/helpers.rb
899
900
  - lib/jets/router/helpers/core_helper.rb
900
901
  - lib/jets/router/helpers/named_routes_helper.rb
902
+ - lib/jets/router/matcher.rb
901
903
  - lib/jets/router/method_creator.rb
902
904
  - lib/jets/router/method_creator/code.rb
903
905
  - lib/jets/router/method_creator/edit.rb