serviceworker-rails 0.5.5 → 0.7.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.
Files changed (59) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ci.yml +66 -0
  3. data/.github/workflows/release.yml +31 -0
  4. data/.gitignore +4 -3
  5. data/.node-version +1 -0
  6. data/.rubocop.yml +18 -91
  7. data/.ruby-version +1 -0
  8. data/.standard.yml +1 -0
  9. data/CHANGELOG.md +13 -0
  10. data/Gemfile +8 -6
  11. data/Gemfile.lock +355 -0
  12. data/Guardfile +5 -3
  13. data/README.md +6 -5
  14. data/Rakefile +19 -5
  15. data/bin/_guard-core +2 -1
  16. data/bin/console +1 -0
  17. data/bin/guard +2 -1
  18. data/bin/rake +3 -1
  19. data/bin/rubocop +3 -1
  20. data/bin/setup +4 -1
  21. data/bin/standardrb +29 -0
  22. data/gemfiles/rails_7.0.gemfile +12 -0
  23. data/gemfiles/rails_7.0.gemfile.lock +324 -0
  24. data/gemfiles/rails_7.1.gemfile +12 -0
  25. data/gemfiles/rails_7.1.gemfile.lock +348 -0
  26. data/gemfiles/rails_8.0.gemfile +12 -0
  27. data/gemfiles/rails_8.0.gemfile.lock +479 -0
  28. data/gemfiles/rails_8.1.gemfile +12 -0
  29. data/gemfiles/rails_8.1.gemfile.lock +486 -0
  30. data/gemfiles/rails_8.1_rack3.gemfile +20 -0
  31. data/gemfiles/rails_8.1_rack3.gemfile.lock +485 -0
  32. data/lib/assets/images/convert.rb +4 -0
  33. data/lib/assets/images/serviceworker-rails/heart-144x144.png +0 -0
  34. data/lib/assets/images/serviceworker-rails/heart-384x384.png +0 -0
  35. data/lib/generators/serviceworker/install_generator.rb +4 -20
  36. data/lib/generators/serviceworker/templates/serviceworker-companion.js +10 -5
  37. data/lib/generators/serviceworker/templates/serviceworker.js +3 -3
  38. data/lib/generators/serviceworker/templates/serviceworker.rb +2 -0
  39. data/lib/service_worker.rb +2 -0
  40. data/lib/serviceworker/engine.rb +3 -2
  41. data/lib/serviceworker/handlers/rack_handler.rb +35 -0
  42. data/lib/serviceworker/{rails/handler.rb → handlers/sprockets_handler.rb} +14 -5
  43. data/lib/serviceworker/handlers.rb +64 -0
  44. data/lib/serviceworker/middleware.rb +16 -14
  45. data/lib/serviceworker/rails/version.rb +2 -1
  46. data/lib/serviceworker/rails.rb +2 -1
  47. data/lib/serviceworker/route.rb +28 -23
  48. data/lib/serviceworker/router.rb +9 -9
  49. data/lib/serviceworker-rails.rb +2 -1
  50. data/lib/serviceworker.rb +2 -0
  51. data/serviceworker-rails.gemspec +28 -19
  52. metadata +163 -41
  53. data/.travis.yml +0 -10
  54. data/Appraisals +0 -12
  55. data/bin/appraisal +0 -17
  56. data/gemfiles/rails_3.gemfile +0 -15
  57. data/gemfiles/rails_4.gemfile +0 -14
  58. data/gemfiles/rails_5.gemfile +0 -14
  59. data/lib/serviceworker/handler.rb +0 -22
@@ -1,9 +1,8 @@
1
1
  # frozen_string_literal: true
2
- require "rack/file"
3
2
 
4
3
  module ServiceWorker
5
- module Rails
6
- class Handler
4
+ module Handlers
5
+ class SprocketsHandler
7
6
  def call(env)
8
7
  path_info = env.fetch("serviceworker.asset_name")
9
8
 
@@ -14,14 +13,24 @@ module ServiceWorker
14
13
  end
15
14
  end
16
15
 
17
- private
16
+ private
18
17
 
19
18
  def sprockets_server
20
19
  ::Rails.application.assets
21
20
  end
22
21
 
23
22
  def file_server
24
- @file_server ||= ::Rack::File.new(::Rails.public_path)
23
+ @file_server ||= rack_files_class.new(::Rails.public_path)
24
+ end
25
+
26
+ def rack_files_class
27
+ @rack_files_class ||= begin
28
+ require "rack/files"
29
+ ::Rack::Files
30
+ rescue LoadError
31
+ require "rack/file"
32
+ ::Rack::File
33
+ end
25
34
  end
26
35
 
27
36
  def config
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "serviceworker/handlers/rack_handler"
4
+
5
+ module ServiceWorker
6
+ module Handlers
7
+ extend self
8
+
9
+ def build(handler)
10
+ resolve_handler(handler) || default_handler
11
+ end
12
+
13
+ def handler_for_route_match(route_match)
14
+ options = route_match.options
15
+ return sprockets_handler if Route.sprockets?(options)
16
+
17
+ nil
18
+ end
19
+
20
+ def ===(other)
21
+ other.respond_to?(:call)
22
+ end
23
+
24
+ def handler_for_name(name)
25
+ available_handlers = %w[sprockets rack]
26
+ if available_handlers.include?(name.to_s)
27
+ send(:"#{name}_handler")
28
+ else
29
+ raise ServiceWorker::Error,
30
+ "Unknown handler #{name.inspect}. Please use one of #{available_handlers.inspect}"
31
+ end
32
+ end
33
+
34
+ def resolve_handler(handler)
35
+ case handler
36
+ when Handlers
37
+ handler
38
+ when Symbol, String
39
+ handler_for_name(handler)
40
+ end
41
+ end
42
+
43
+ def sprockets_handler
44
+ require "serviceworker/handlers/sprockets_handler"
45
+ ServiceWorker::Handlers::SprocketsHandler.new
46
+ end
47
+
48
+ def rack_handler
49
+ ServiceWorker::Handlers::RackHandler.new
50
+ end
51
+
52
+ def default_handler
53
+ if sprockets?
54
+ sprockets_handler
55
+ else
56
+ rack_handler
57
+ end
58
+ end
59
+
60
+ def sprockets?
61
+ defined?(::Rails) && ::Rails.configuration.assets
62
+ end
63
+ end
64
+ end
@@ -1,9 +1,12 @@
1
1
  # frozen_string_literal: true
2
+
3
+ require "serviceworker/handlers"
4
+
2
5
  module ServiceWorker
3
6
  class Middleware
4
- REQUEST_METHOD = "REQUEST_METHOD".freeze
5
- GET = "GET".freeze
6
- HEAD = "HEAD".freeze
7
+ REQUEST_METHOD = "REQUEST_METHOD"
8
+ GET = "GET"
9
+ HEAD = "HEAD"
7
10
 
8
11
  # Initialize the Rack middleware for responding to serviceworker asset
9
12
  # requests
@@ -17,14 +20,14 @@ module ServiceWorker
17
20
  def initialize(app, opts = {})
18
21
  @app = app
19
22
  @opts = opts
20
- @headers = opts.fetch(:headers, {}).merge(default_headers)
23
+ @headers = default_headers.merge(opts.fetch(:headers, {}))
21
24
  @router = opts.fetch(:routes, ServiceWorker::Router.new)
22
- @handler = @opts.fetch(:handler, default_handler)
25
+ @handler = Handlers.build(@opts.fetch(:handler, nil))
23
26
  end
24
27
 
25
28
  def call(env)
26
29
  case env[REQUEST_METHOD]
27
- when GET, HEAD
30
+ when GET, HEAD
28
31
  route_match = @router.match_route(env)
29
32
  return respond_to_match(route_match, env) if route_match
30
33
  end
@@ -32,7 +35,7 @@ module ServiceWorker
32
35
  @app.call(env)
33
36
  end
34
37
 
35
- private
38
+ private
36
39
 
37
40
  def default_headers
38
41
  {
@@ -43,22 +46,21 @@ module ServiceWorker
43
46
  def respond_to_match(route_match, env)
44
47
  env = env.merge("serviceworker.asset_name" => route_match.asset_name)
45
48
 
46
- status, headers, body = @handler.call(env)
49
+ status, headers, body = handler_for_route_match(route_match).call(env)
47
50
 
48
51
  [status, headers.merge(@headers).merge(route_match.headers), body]
49
52
  end
50
53
 
54
+ def handler_for_route_match(route_match)
55
+ Handlers.handler_for_route_match(route_match) || @handler
56
+ end
57
+
51
58
  def info(msg)
52
59
  logger.info "[#{self.class}] - #{msg}"
53
60
  end
54
61
 
55
62
  def logger
56
- @logger ||= @opts.fetch(:logger, Logger.new(STDOUT))
57
- end
58
-
59
- def default_handler
60
- require "serviceworker/handler"
61
- ServiceWorker::Handler.new
63
+ @logger ||= @opts.fetch(:logger, Logger.new($stdout))
62
64
  end
63
65
  end
64
66
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module ServiceWorker
3
4
  module Rails
4
- VERSION = "0.5.5".freeze
5
+ VERSION = "0.7.0"
5
6
  end
6
7
  end
@@ -1,8 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ServiceWorker
2
4
  module Rails
3
5
  end
4
6
  end
5
7
 
6
8
  require "serviceworker/rails/version"
7
- require "serviceworker/rails/handler"
8
9
  require "serviceworker/engine"
@@ -1,14 +1,19 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module ServiceWorker
3
4
  class Route
4
5
  attr_reader :path_pattern, :asset_pattern, :options
5
6
 
6
- RouteMatch = Struct.new(:path, :asset_name, :headers) do
7
+ RouteMatch = Struct.new(:path, :asset_name, :headers, :options) do
7
8
  def to_s
8
9
  asset_name
9
10
  end
10
11
  end
11
12
 
13
+ def self.sprockets?(options)
14
+ options.key?(:asset)
15
+ end
16
+
12
17
  def initialize(path_pattern, asset_pattern = nil, options = {})
13
18
  if asset_pattern.is_a?(Hash)
14
19
  options = asset_pattern
@@ -16,16 +21,16 @@ module ServiceWorker
16
21
  end
17
22
 
18
23
  @path_pattern = path_pattern
19
- @asset_pattern = asset_pattern || options[:asset] || path_pattern
24
+ @asset_pattern = asset_pattern || options.fetch(:asset, path_pattern)
20
25
  @options = options
21
26
  end
22
27
 
23
28
  def match(path)
24
29
  raise ArgumentError, "path is required" if path.to_s.strip.empty?
25
30
 
26
- asset = resolver.call(path) or return nil
31
+ (asset = resolver.call(path)) || (return nil)
27
32
 
28
- RouteMatch.new(path, asset, headers)
33
+ RouteMatch.new(path, asset, headers, options)
29
34
  end
30
35
 
31
36
  def headers
@@ -39,14 +44,14 @@ module ServiceWorker
39
44
  end
40
45
 
41
46
  class AssetResolver
42
- PATH_INFO = "PATH_INFO".freeze
47
+ PATH_INFO = "PATH_INFO"
43
48
  DEFAULT_WILDCARD_NAME = :paths
44
- WILDCARD_PATTERN = %r{\/\*([^\/]*)}
45
- NAMED_SEGMENTS_PATTERN = %r{\/([^\/]*):([^:$\/]+)}
46
- LEADING_SLASH_PATTERN = %r{^\/}
49
+ WILDCARD_PATTERN = %r{/\*([^/]*)}
50
+ NAMED_SEGMENTS_PATTERN = %r{/([^/]*):([^:$/]+)}
51
+ LEADING_SLASH_PATTERN = %r{^/}
47
52
  INTERPOLATION_PATTERN = Regexp.union(
48
53
  /%%/,
49
- /%\{(\w+)\}/, # matches placeholders like "%{foo}"
54
+ /%\{(\w+)\}/ # matches placeholders like "%{foo}"
50
55
  )
51
56
 
52
57
  attr_reader :path_pattern, :asset_pattern
@@ -59,7 +64,7 @@ module ServiceWorker
59
64
  def call(path)
60
65
  raise ArgumentError, "path is required" if path.to_s.strip.empty?
61
66
 
62
- captures = path_captures(regexp, path) or return nil
67
+ (captures = path_captures(regexp, path)) || (return nil)
63
68
 
64
69
  interpolate_captures(asset_pattern, captures)
65
70
  end
@@ -79,28 +84,28 @@ module ServiceWorker
79
84
  pattern_match = pattern.match(WILDCARD_PATTERN)
80
85
  if pattern_match
81
86
  @wildcard_name = if pattern_match[1].to_s.strip.empty?
82
- DEFAULT_WILDCARD_NAME
83
- else
84
- pattern_match[1].to_sym
85
- end
87
+ DEFAULT_WILDCARD_NAME
88
+ else
89
+ pattern_match[1].to_sym
90
+ end
86
91
  pattern.gsub(WILDCARD_PATTERN, "(?:/(.*)|)")
87
92
  else
88
93
  p = if pattern.match(NAMED_SEGMENTS_PATTERN)
89
- pattern.gsub(NAMED_SEGMENTS_PATTERN, '/\1(?<\2>[^.$/]+)')
90
- else
91
- pattern
92
- end
94
+ pattern.gsub(NAMED_SEGMENTS_PATTERN, '/\1(?<\2>[^.$/]+)')
95
+ else
96
+ pattern
97
+ end
93
98
  p + '(?:\.(?<format>.*))?'
94
99
  end
95
100
  end
96
101
 
97
102
  def path_captures(regexp, path)
98
- path_match = path.match(regexp) or return nil
103
+ (path_match = path.match(regexp)) || (return nil)
99
104
  params = if @wildcard_name
100
- { @wildcard_name => path_match[1].to_s.split("/") }
101
- else
102
- Hash[path_match.names.map(&:to_sym).zip(path_match.captures)]
103
- end
105
+ {@wildcard_name => path_match[1].to_s.split("/")}
106
+ else
107
+ path_match.names.map(&:to_sym).zip(path_match.captures).to_h
108
+ end
104
109
  params.delete(:format) if params.key?(:format) && params[:format].nil?
105
110
  params
106
111
  end
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module ServiceWorker
3
4
  class Router
4
- PATH_INFO = "PATH_INFO".freeze
5
+ PATH_INFO = "PATH_INFO"
5
6
 
6
7
  def self.default
7
8
  new.draw_default
@@ -9,14 +10,15 @@ module ServiceWorker
9
10
 
10
11
  attr_reader :routes
11
12
 
12
- def initialize
13
+ # standard:disable Style/ArgumentsForwarding
14
+ def initialize(&block)
13
15
  @routes = []
14
16
 
15
- draw(&Proc.new) if block_given?
17
+ draw(&block)
16
18
  end
17
19
 
18
20
  def draw(&block)
19
- return self unless block_given?
21
+ return self unless block
20
22
 
21
23
  if block.arity == 1
22
24
  yield(self)
@@ -26,6 +28,7 @@ module ServiceWorker
26
28
 
27
29
  self
28
30
  end
31
+ # standard:enable Style/ArgumentsForwarding
29
32
 
30
33
  def draw_default
31
34
  draw { get "/serviceworker.js" }
@@ -42,7 +45,7 @@ module ServiceWorker
42
45
  @routes << route
43
46
  end
44
47
  end
45
- alias get match
48
+ alias_method :get, :match
46
49
 
47
50
  def any?
48
51
  @routes.any?
@@ -50,10 +53,7 @@ module ServiceWorker
50
53
 
51
54
  def match_route(env)
52
55
  path = env[PATH_INFO]
53
- @routes.each do |route|
54
- match = route.match(path) and return match
55
- end
56
- nil
56
+ @routes.lazy.map { |route| route.match(path) }.detect(&:itself)
57
57
  end
58
58
  end
59
59
  end
@@ -1,3 +1,4 @@
1
- # rubocop:disable Style/FileName
1
+ # frozen_string_literal: true
2
+
2
3
  require "serviceworker"
3
4
  require "serviceworker/rails"
data/lib/serviceworker.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ServiceWorker
2
4
  Error = Class.new(StandardError)
3
5
  RouteError = Class.new(Error)
@@ -1,33 +1,42 @@
1
- # coding: utf-8
2
- lib = File.expand_path("../lib", __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path("lib", __dir__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
5
  require "serviceworker/rails/version"
5
6
 
6
7
  Gem::Specification.new do |spec|
7
- spec.name = "serviceworker-rails"
8
- spec.version = ServiceWorker::Rails::VERSION
9
- spec.authors = ["Ross Kaffenberger"]
10
- spec.email = ["rosskaff@gmail.com"]
8
+ spec.name = "serviceworker-rails"
9
+ spec.version = ServiceWorker::Rails::VERSION
10
+ spec.authors = ["Ross Kaffenberger"]
11
+ spec.email = ["rosskaff@gmail.com"]
11
12
 
12
- spec.summary = "ServiceWorker for Rails 3+"
13
- spec.description = "Integrates ServiceWorker into the Rails asset pipeline."
14
- spec.homepage = "https://github.com/rossta/serviceworker-rails"
15
- spec.license = "MIT"
13
+ spec.summary = "ServiceWorker for Rails 7+"
14
+ spec.description = "Integrates ServiceWorker into the Rails asset pipeline."
15
+ spec.homepage = "https://github.com/rossta/serviceworker-rails"
16
+ spec.license = "MIT"
16
17
 
17
- spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
- spec.bindir = "exe"
19
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
18
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
19
+ spec.bindir = "exe"
20
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
21
  spec.require_paths = ["lib"]
21
22
 
22
- spec.add_dependency "railties", [">= 3.1"]
23
+ spec.add_dependency "railties", ">= 7.0"
24
+ spec.add_dependency "rack", [">= 2.1"]
25
+ spec.add_dependency "logger"
26
+ spec.add_dependency "benchmark"
27
+ spec.add_dependency "bigdecimal"
28
+ spec.add_dependency "ostruct"
29
+ spec.add_dependency "mutex_m"
30
+ spec.add_dependency "drb"
31
+ spec.add_dependency "cgi"
23
32
 
24
- spec.add_development_dependency "sprockets-rails"
25
- spec.add_development_dependency "bundler", "~> 1.11"
26
- spec.add_development_dependency "rake", "~> 11.0"
27
33
  spec.add_development_dependency "minitest", "~> 5.0"
28
34
  spec.add_development_dependency "rack-test"
29
- spec.add_development_dependency "rubocop", "0.46.0"
30
35
  spec.add_development_dependency "rails"
31
- spec.add_development_dependency "appraisal", "~> 2.1.0"
36
+ spec.add_development_dependency "rake"
37
+ spec.add_development_dependency "parallel", "~> 1.27"
32
38
  spec.add_development_dependency "simplecov"
39
+ spec.add_development_dependency "sprockets", "~> 3.0"
40
+ spec.add_development_dependency "sprockets-rails"
41
+ spec.add_development_dependency "standard"
33
42
  end