serviceworker-rails 0.1.0 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5204e0b97606d5376b6f64929819f4a028112204
4
- data.tar.gz: 3c670957542a61203341a539becb33998e22f449
3
+ metadata.gz: e15c642851a30d7cf973bc826cdd953de5248df2
4
+ data.tar.gz: ad30587132acd6fbf1052370d5dafa12f5d24edb
5
5
  SHA512:
6
- metadata.gz: bc077d6c2e08e5f50d0f6c51abcba3c717c0ea78799cbbfdebb14c56175b1842e832b503d6a6737a0d598b2a94040ab7665d7496fd3b9156887114e6245cf01d
7
- data.tar.gz: 8e830544524431c811c9505e3aefc98466fa6ec7afaa628fa44243559d2f0046d7963340888f69961ce75ebf0c4b69a4e6c1a061d091a5b21e916d11e7efa5bc
6
+ metadata.gz: c695e3493724c49d99b7f8b72174057abd43ca4b73e6782706c80843efeca64c54512a535490f31a171b2f4e19175233b9a81f413fe5158d92b0e0ddaa3ef911
7
+ data.tar.gz: 2e4a8f6c092de36eb47fcaab1d0fb30bd21fa1244e8aa9b14dacf4757bcc87e5f0d7a9778c14d9af722b2002e1732188c5b5108a6f245fb2b208beb0d37c0048
data/Gemfile CHANGED
@@ -2,3 +2,7 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in serviceworker-rails.gemspec
4
4
  gemspec
5
+
6
+ gem "pry-byebug", platforms: [:ruby_23]
7
+ gem "guard"
8
+ gem "guard-minitest"
@@ -0,0 +1,42 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ ## Uncomment and set this to only include directories you want to watch
5
+ # directories %w(app lib config test spec features) \
6
+ # .select{|d| Dir.exists?(d) ? d : UI.warning("Directory #{d} does not exist")}
7
+
8
+ ## Note: if you are using the `directories` clause above and you are not
9
+ ## watching the project directory ('.'), then you will want to move
10
+ ## the Guardfile to a watched dir and symlink it back, e.g.
11
+ #
12
+ # $ mkdir config
13
+ # $ mv Guardfile config/
14
+ # $ ln -s config/Guardfile .
15
+ #
16
+ # and, you'll have to watch "config/Guardfile" instead of "Guardfile"
17
+
18
+ guard :minitest do
19
+ # with Minitest::Unit
20
+ watch(%r{^test/(.*)\/?(.*)_test\.rb$})
21
+ watch(%r{^lib/(.*/)?([^/]+)\.rb$}) { |m| "test/#{m[1]}#{m[2]}_test.rb" }
22
+ watch(%r{^test/test_helper\.rb$}) { 'test' }
23
+
24
+ # with Minitest::Spec
25
+ # watch(%r{^spec/(.*)_spec\.rb$})
26
+ # watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
27
+ # watch(%r{^spec/spec_helper\.rb$}) { 'spec' }
28
+
29
+ # Rails 4
30
+ # watch(%r{^app/(.+)\.rb$}) { |m| "test/#{m[1]}_test.rb" }
31
+ # watch(%r{^app/controllers/application_controller\.rb$}) { 'test/controllers' }
32
+ # watch(%r{^app/controllers/(.+)_controller\.rb$}) { |m| "test/integration/#{m[1]}_test.rb" }
33
+ # watch(%r{^app/views/(.+)_mailer/.+}) { |m| "test/mailers/#{m[1]}_mailer_test.rb" }
34
+ # watch(%r{^lib/(.+)\.rb$}) { |m| "test/lib/#{m[1]}_test.rb" }
35
+ # watch(%r{^test/.+_test\.rb$})
36
+ # watch(%r{^test/test_helper\.rb$}) { 'test' }
37
+
38
+ # Rails < 4
39
+ # watch(%r{^app/controllers/(.*)\.rb$}) { |m| "test/functional/#{m[1]}_test.rb" }
40
+ # watch(%r{^app/helpers/(.*)\.rb$}) { |m| "test/helpers/#{m[1]}_test.rb" }
41
+ # watch(%r{^app/models/(.*)\.rb$}) { |m| "test/unit/#{m[1]}_test.rb" }
42
+ end
data/README.md CHANGED
@@ -26,7 +26,40 @@ Or install it yourself as:
26
26
 
27
27
  ## Usage
28
28
 
29
- Currently, `serviceworker-rails` assumes your script resolves to `serviceworker.js`
29
+ To use `serviceworker-rails` in a Rails app, install the gem as above. When
30
+ `serviceworker-rails` is required, it will insert a middleware into the Rails
31
+ middleware stack. You'll want to configure it by mapping serviceworker routes to
32
+ Sprockets JavaScript assets, like the example below, in `application.rb`.
33
+
34
+ ```ruby
35
+ # application.rb
36
+
37
+ config.serviceworker.routes.draw do
38
+ get "/basic-serviceworker.js"
39
+
40
+ get "/proxied-serviceworker.js"
41
+ asset: "nested/asset/serviceworker.js"
42
+
43
+ get "/nested/serviceworker.js",
44
+ asset: "another/serviceworker.js"
45
+
46
+ get "/header-serviceworker.js",
47
+ asset: "another/serviceworker.js",
48
+ headers: { "X-Resource-Header" => "A resource" }
49
+
50
+ get "/*/serviceworker.js",
51
+ asset: "serviceworker.js"
52
+ end
53
+ ```
54
+
55
+ `Serviceworker-Rails` with insert a `Cache-Control` header to instruct browsers
56
+ not to cache your serviceworkers by default. You can customize the headers for all service worker routes if you'd like,
57
+ such as adding the experimental [`Service-Worker-Allowed`](https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#service-worker-allowed) header to set the allowed scope.
58
+
59
+ ```ruby
60
+ config.serviceworker.headers["Service-Worker-Allowed"] = "/"
61
+ config.serviceworker.headers["X-Custom-Header"] = "foobar"
62
+ ```
30
63
 
31
64
  ## Development
32
65
 
data/Rakefile CHANGED
@@ -1,6 +1,11 @@
1
1
  require "bundler/gem_tasks"
2
2
  require "rake/testtask"
3
3
 
4
+ APP_RAKEFILE = File.expand_path("../test/sample/Rakefile", __FILE__)
5
+ load "rails/tasks/engine.rake"
6
+
7
+ Bundler::GemHelper.install_tasks
8
+
4
9
  Rake::TestTask.new(:test) do |t|
5
10
  t.libs << "test"
6
11
  t.libs << "lib"
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application '_guard-core' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require "pathname"
10
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require "rubygems"
14
+ require "bundler/setup"
15
+
16
+ load Gem.bin_path("guard", "_guard-core")
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'guard' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require "pathname"
10
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require "rubygems"
14
+ require "bundler/setup"
15
+
16
+ load Gem.bin_path("guard", "guard")
@@ -1,19 +1,8 @@
1
1
  module ServiceWorker
2
- class << self
3
- # The path to the root of the application. ServiceWorker.rb uses this property
4
- # to . If you are using ServiceWorker.rb with Rails, you do not need to set
5
- # this attribute manually.
6
- #
7
- # @return [String]
8
- attr_accessor :root
9
-
10
- # The logger to use when logging exception details and backtraces. If you
11
- # are using Better Errors with Rails, you do not need to set this attribute
12
- # manually. If this attribute is `nil`, nothing will be logged.
13
- #
14
- # @return [Logger, nil]
15
- attr_accessor :logger
16
- end
2
+ Error = Class.new(StandardError)
3
+ RouteError = Class.new(Error)
17
4
  end
18
5
 
6
+ require "serviceworker/route"
7
+ require "serviceworker/router"
19
8
  require "serviceworker/middleware"
@@ -3,64 +3,52 @@ module ServiceWorker
3
3
  def initialize(app, opts = {})
4
4
  @app = app
5
5
  @opts = opts
6
-
7
- @logger = opts.fetch(:logger, ServiceWorker.logger)
6
+ @headers = opts.fetch(:headers, {}).merge(default_headers)
7
+ @router = opts.fetch(:routes, ServiceWorker::Router.new)
8
8
  end
9
9
 
10
10
  def call(env)
11
- case env['REQUEST_METHOD']
12
- when 'GET', 'HEAD'
13
- path = env['PATH_INFO'].chomp('/')
11
+ case env["REQUEST_METHOD"]
12
+ when "GET", "HEAD"
13
+ path = env["PATH_INFO"].chomp("/")
14
14
  info("responding to #{path}")
15
- return respond_to(path, env) if match?(path)
15
+ route = @router.match_route(path)
16
+ return respond_to_route(route, env) if route
16
17
  end
17
18
 
18
19
  @app.call(env)
19
20
  end
20
21
 
21
- def match?(path)
22
- path == '/serviceworker.js'
23
- end
24
-
25
22
  private
26
23
 
27
- def respond_to(path_info, env)
28
- status, headers, body = handle_request(path_info, env)
29
-
30
- headers['Cache-Control'] = 'private, max-age=0, no-cache'
31
-
32
- [status, headers, body]
24
+ def default_headers
25
+ {
26
+ "Cache-Control" => "private, max-age=0, no-cache"
27
+ }
33
28
  end
34
29
 
35
- def handle_request(path_info, env)
36
- if config.compile
37
- info "compiling #{path_info} from Sprockets"
38
- sprockets_server.call(env)
39
- else
40
- file_path = asset_path(path_info)
41
- info "Proxing #{path_info} from #{file_path}"
42
- file_server.call(env.merge('PATH_INFO' => file_path))
43
- end
44
- end
30
+ def respond_to_route(route, env)
31
+ status, headers, body = process_handler(route, env)
45
32
 
46
- def info(msg)
47
- @logger.info "[#{self.class}] - #{msg}"
33
+ [status, headers.merge(@headers).merge(route.headers), body]
48
34
  end
49
35
 
50
- def sprockets_server
51
- ::Rails.application.assets
36
+ def process_handler(route, env)
37
+ handler.call(env.merge("serviceworker.asset_name" => route.asset_name))
52
38
  end
53
39
 
54
- def file_server
55
- @file_server ||= ::Rack::File.new(::Rails.root.join("public"))
40
+ def info(msg)
41
+ logger.info "[#{self.class}] - #{msg}"
56
42
  end
57
43
 
58
- def config
59
- ::Rails.application.config.assets
44
+ # TODO
45
+ # provide non-rails handler as default
46
+ def handler
47
+ @handler ||= @opts.fetch(:handler)
60
48
  end
61
49
 
62
- def asset_path(path)
63
- ::ActionController::Base.helpers.asset_path(path.gsub(/^\//, ''))
50
+ def logger
51
+ @logger ||= @opts.fetch(:logger, Logger.new(STDOUT))
64
52
  end
65
53
  end
66
54
  end
@@ -1,8 +1,8 @@
1
- require "serviceworker/rails/version"
2
- require "serviceworker/railtie"
3
-
4
1
  module ServiceWorker
5
2
  module Rails
6
-
7
3
  end
8
4
  end
5
+
6
+ require "serviceworker/rails/version"
7
+ require "serviceworker/rails/handler"
8
+ require "serviceworker/railtie"
@@ -0,0 +1,33 @@
1
+ module ServiceWorker
2
+ module Rails
3
+ class Handler
4
+ def call(env)
5
+ path_info = env.fetch("serviceworker.asset_name")
6
+
7
+ if config.compile
8
+ sprockets_server.call(env.merge("PATH_INFO" => path_info))
9
+ else
10
+ file_server.call(env.merge("PATH_INFO" => asset_path(path_info)))
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def sprockets_server
17
+ ::Rails.application.assets
18
+ end
19
+
20
+ def file_server
21
+ @file_server ||= ::Rack::File.new(::Rails.root.join("public"))
22
+ end
23
+
24
+ def config
25
+ ::Rails.configuration.assets
26
+ end
27
+
28
+ def asset_path(path)
29
+ ::ActionController::Base.helpers.asset_path(path)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,5 +1,5 @@
1
1
  module ServiceWorker
2
2
  module Rails
3
- VERSION = "0.1.0"
3
+ VERSION = "0.2.0"
4
4
  end
5
5
  end
@@ -1,20 +1,19 @@
1
1
  require "rails"
2
2
  require "rails/railtie"
3
+ require "serviceworker"
3
4
 
4
5
  module ServiceWorker
5
6
  class Railtie < ::Rails::Railtie
7
+ config.serviceworker = ActiveSupport::OrderedOptions.new
8
+ config.serviceworker.headers = {}
9
+ config.serviceworker.routes = ServiceWorker::Router.new
10
+ config.serviceworker.handler = ServiceWorker::Rails::Handler.new
11
+
6
12
  initializer "serviceworker-rails.configure_rails_initialization" do
7
- insert_middleware
8
- ServiceWorker.logger = ::Rails.logger
9
- ServiceWorker.root = ::Rails.root.to_s
10
- end
13
+ config.serviceworker.logger ||= ::Rails.logger
14
+ config.serviceworker.routes.draw_default unless config.serviceworker.routes.any?
11
15
 
12
- def insert_middleware
13
- if defined? ::Rack::SendFile
14
- app.middleware.insert_after ::Rack::Sendfile, ServiceWorker::Middleware
15
- else
16
- app.middleware.use ServiceWorker::Middleware
17
- end
16
+ app.middleware.use ServiceWorker::Middleware, config.serviceworker
18
17
  end
19
18
 
20
19
  def app
@@ -0,0 +1,49 @@
1
+ module ServiceWorker
2
+ class Route
3
+ attr_reader :path, :options
4
+
5
+ def initialize(path, options = {})
6
+ @path = path
7
+ @options = options
8
+
9
+ @pattern = compile(path)
10
+ end
11
+
12
+ def match?(path)
13
+ @pattern =~ path
14
+ end
15
+
16
+ def asset_name
17
+ @options.fetch(:asset, @path.gsub(%r{^/}, ""))
18
+ rescue NoMethodError
19
+ raise RouteError, "Cannot determine asset name from #{path.inspect}. Please specify the :asset option for this path."
20
+ end
21
+
22
+ def headers
23
+ @options.fetch(:headers, {})
24
+ end
25
+
26
+ private
27
+
28
+ def compile(path)
29
+ if path.respond_to?(:to_str)
30
+ special_chars = %w[. + ( )]
31
+ pattern = path.to_str.gsub(/([\*#{special_chars.join}])/) do |match|
32
+ case match
33
+ when "*"
34
+ "(.*?)"
35
+ when *special_chars
36
+ Regexp.escape(match)
37
+ else
38
+ "([^/?&#]+)"
39
+ end
40
+ end
41
+ /^#{pattern}$/
42
+ elsif path.respond_to?(:match)
43
+ path
44
+ else
45
+ raise TypeError, path
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,46 @@
1
+ module ServiceWorker
2
+ class Router
3
+ def self.default
4
+ new.draw_default
5
+ end
6
+
7
+ attr_reader :routes
8
+
9
+ def initialize
10
+ @routes = []
11
+
12
+ draw(&Proc.new) if block_given?
13
+ end
14
+
15
+ def draw(&block)
16
+ return self unless block_given?
17
+
18
+ if block.arity == 1
19
+ block.call(self)
20
+ else
21
+ instance_eval(&block)
22
+ end
23
+
24
+ self
25
+ end
26
+
27
+ def draw_default
28
+ draw { get "/serviceworker.js" }
29
+ end
30
+
31
+ def get(path, options = {})
32
+ Route.new(path, options).tap do |route|
33
+ @routes << route
34
+ end
35
+ end
36
+
37
+ def any?
38
+ @routes.any?
39
+ end
40
+
41
+ def match_route(path)
42
+ @routes.detect { |r| r.match?(path) }
43
+ end
44
+ end
45
+
46
+ end
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
10
  spec.email = ["rosskaff@gmail.com"]
11
11
 
12
12
  spec.summary = %q{ServiceWorker for Rails 3+}
13
- spec.description = %q{Integrates ServiceWorker JavaScript support into the Rails asset pipeline.}
13
+ spec.description = %q{Integrates ServiceWorker into the Rails asset pipeline.}
14
14
  spec.homepage = "https://github.com/rossta/serviceworker-rails"
15
15
  spec.license = "MIT"
16
16
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: serviceworker-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ross Kaffenberger
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-04-23 00:00:00.000000000 Z
11
+ date: 2016-04-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: railties
@@ -94,7 +94,7 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
- description: Integrates ServiceWorker JavaScript support into the Rails asset pipeline.
97
+ description: Integrates ServiceWorker into the Rails asset pipeline.
98
98
  email:
99
99
  - rosskaff@gmail.com
100
100
  executables: []
@@ -105,10 +105,13 @@ files:
105
105
  - ".travis.yml"
106
106
  - CODE_OF_CONDUCT.md
107
107
  - Gemfile
108
+ - Guardfile
108
109
  - LICENSE.txt
109
110
  - README.md
110
111
  - Rakefile
112
+ - bin/_guard-core
111
113
  - bin/console
114
+ - bin/guard
112
115
  - bin/rake
113
116
  - bin/rspec
114
117
  - bin/setup
@@ -116,8 +119,11 @@ files:
116
119
  - lib/serviceworker.rb
117
120
  - lib/serviceworker/middleware.rb
118
121
  - lib/serviceworker/rails.rb
122
+ - lib/serviceworker/rails/handler.rb
119
123
  - lib/serviceworker/rails/version.rb
120
124
  - lib/serviceworker/railtie.rb
125
+ - lib/serviceworker/route.rb
126
+ - lib/serviceworker/router.rb
121
127
  - serviceworker-rails.gemspec
122
128
  homepage: https://github.com/rossta/serviceworker-rails
123
129
  licenses: