serviceworker-rails 0.1.0 → 0.2.0

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
  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: