middleman-caching-proxy 0.1.0 → 0.1.2

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: cefacd267c25aa55daa8c3aab6adba286294d201
4
- data.tar.gz: b02aa54ec0e117b924dedf78d0647d994f1d3d4e
3
+ metadata.gz: 81c6ce51f0c02f5c109266f1a158568dcd3dfc62
4
+ data.tar.gz: 968b0211af2b5c69a92d92fbc47da19c0903ce89
5
5
  SHA512:
6
- metadata.gz: dc4feea092dfe37bf0067a8faf6bd5d5f9289c305c6f10570d4f5e421083a8b0326c448b3bd38c9df79e39a5347de28350670b14e2717515a296d3c4e3414999
7
- data.tar.gz: 24be5f3a39fa8d3d8e10b5f3b27a1d27c83f747bd16996a818a123509fa61951479ad5eeceaf83b2377d2daf9767eb8acf1151e9906bdb256fc31b3c4d6ede0f
6
+ metadata.gz: d612e58dc98456e7a15ac4cbe0200925bba21575ce6df8b2c237d7bbc8b543f4f668975efae5bc5bd3bdfa30cfc54a44dfb3e9a5672c894684c04777043b086b
7
+ data.tar.gz: 23204aae5624bc0d4a3f86248ea084fc03739de55092239782620c2267c9cc297eb0139679e1f0980e1f932b91af8ada5e1ef10a6527c98a6e6fc1b4b04acd93
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source 'https://rubygems.org'
1
+ source "https://rubygems.org"
2
2
 
3
- # Specify your gem's dependencies in middleman-caching-proxy.gemspec
4
3
  gemspec
4
+
data/README.md CHANGED
@@ -1,8 +1,7 @@
1
- # Middleman::Caching::Proxy
1
+ # Middleman::CachingProxy
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/middleman/caching/proxy`. To experiment with that code, run `bin/console` for an interactive prompt.
4
-
5
- TODO: Delete this and the text above, and describe your gem
3
+ Caches the result of `proxy` calls allong with the fingerprint of their inputs.
4
+ If the inputs remain the same, uses the cached version.
6
5
 
7
6
  ## Installation
8
7
 
@@ -22,20 +21,51 @@ Or install it yourself as:
22
21
 
23
22
  ## Usage
24
23
 
25
- TODO: Write usage instructions here
24
+ In `config.rb`:
25
+
26
+ ```ruby
27
+ activate :caching_proxy
28
+
29
+ things.each do |thing|
30
+ proxy_with_cache(
31
+ path: "/things/#{thing.slug}",
32
+ template: "/templates/thing_template.html",
33
+ proxy_options: {locals: {thing: thing}},
34
+ fingerprint: thing.updated_at.to_i
35
+ )
36
+ end
37
+ ```
38
+
39
+ There are 4 required parameters:
40
+
41
+ * `path`: the page path,
42
+ * `template`: the page template,
43
+ * `proxy_options`: options to pass to the `proxy` invocation,
44
+ * `fingerprint`: a value that indicates the 'version' of the item. If this
45
+ value changes, the cached version will be skipped and updated.
26
46
 
27
47
  ## Development
28
48
 
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
49
+ After checking out the repo, run `bin/setup` to install dependencies.
50
+ Then, run `rake spec` to run the tests.
51
+ You can also run `bin/console` for an interactive prompt that will allow you
52
+ to experiment.
30
53
 
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
54
+ To install this gem onto your local machine, run `bundle exec rake install`.
55
+ To release a new version, update the version number in `version.rb`, and then
56
+ run `bundle exec rake release`, which will create a git tag for the version,
57
+ push git commits and tags, and push the `.gem` file to
58
+ [rubygems.org](https://rubygems.org).
32
59
 
33
60
  ## Contributing
34
61
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/middleman-caching-proxy. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
36
-
62
+ Bug reports and pull requests are welcome on GitHub at
63
+ https://github.com/joeyates/middleman-caching-proxy. This project is intended
64
+ to be a safe, welcoming space for collaboration, and contributors are expected
65
+ to adhere to the [Contributor Covenant](http://contributor-covenant.org) code
66
+ of conduct.
37
67
 
38
68
  ## License
39
69
 
40
- The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
41
-
70
+ The gem is available as open source under the terms of the
71
+ [MIT License](http://opensource.org/licenses/MIT).
@@ -1,179 +1,7 @@
1
1
  require "middleman-core"
2
- require "middleman-core/sitemap/resource"
3
- require "semantic"
4
2
 
5
- class CacheItem
6
- attr_reader :path
7
- attr_reader :template
8
- attr_reader :proxy_options
9
- attr_reader :fingerprint
3
+ require "middleman/caching_proxy/extension"
10
4
 
11
- def initialize(path:, template:, proxy_options:, fingerprint:)
12
- @path = path
13
- @template = template
14
- @proxy_options = proxy_options
15
- @fingerprint = fingerprint
16
- end
17
- end
18
-
19
- class CachedResource
20
- attr_reader :path
21
- attr_reader :cached_path
22
- attr_reader :build_path
23
-
24
- def initialize(path:, cached_path:, build_path:)
25
- @path = path
26
- @cached_path = cached_path
27
- @build_path = build_path
28
- end
29
-
30
- def destination_path
31
- path[1..-1]
32
- end
33
-
34
- def ext
35
- ""
36
- end
37
-
38
- def ignored?
39
- false # Seems to mean "actualyy include in build?"
40
- end
41
-
42
- def binary?
43
- true # Seems to mean "do a binary copy or make a rack request?"
44
- end
45
-
46
- def source_file
47
- cached_path
48
- end
49
-
50
- def content_type
51
- "text/html"
52
- end
53
- end
54
-
55
- class MiddlemanExtension < ::Middleman::Extension
56
- option :cache_directory,
57
- "tmp/proxy_cache",
58
- "The directory where cache files will be stored"
59
-
60
- if Semantic::Version.new(Middleman::VERSION).major >= 4
61
- expose_to_config :proxy_with_cache
62
- end
63
-
64
- attr_reader :copy_from_cache
65
- attr_reader :copy_to_cache
66
-
67
- def initialize(app, options_hash = {}, &block)
68
- super
69
-
70
- require "fileutils"
71
-
72
- if Semantic::Version.new(Middleman::VERSION).major <= 3
73
- app.send :include, InstanceMethods
74
- end
75
-
76
- @cache_manifest = nil
77
- @copy_from_cache = []
78
- @copy_to_cache = []
79
- end
80
-
81
- def after_configuration
82
- ensure_cache_directory
83
- end
84
-
85
- def after_build(builder)
86
- copy_proxied_files_to_cache
87
- File.open(cache_manifest_path, "w") do |f|
88
- f.write cache.to_json
89
- end
90
- end
91
-
92
- def add(item)
93
- if matches_cached?(item)
94
- copy_from_cache << item
95
- true
96
- else
97
- cache[item.path] = item.fingerprint
98
- copy_to_cache << item
99
- false
100
- end
101
- end
102
-
103
- def manipulate_resource_list(resources)
104
- resources + cached_resources
105
- end
106
-
107
- module InstanceMethods
108
- def proxy_with_cache(path:, template:, proxy_options:, fingerprint:)
109
- item = CacheItem.new(
110
- path: path,
111
- template: template,
112
- proxy_options: proxy_options,
113
- fingerprint: fingerprint
114
- )
115
- will_use_cache = extensions[:caching_proxy].add(item)
116
- if !will_use_cache
117
- proxy item.path, item.template, item.proxy_options
118
- end
119
- end
120
- end
121
-
122
- private
123
-
124
- def matches_cached?(item)
125
- cached_path = cache_path(item.path)
126
- exists = File.exist?(cached_path)
127
- return false if !exists
128
- return false if cache[item.path].nil?
129
- return false if cache[item.path] != item.fingerprint
130
- true
131
- end
132
-
133
- def copy_proxied_files_to_cache
134
- copy_to_cache.each do |item|
135
- cached_path = cache_path(item.path)
136
- build = build_path(item.path)
137
- cache_subdirectory = File.dirname(cached_path)
138
- FileUtils.mkdir_p cache_subdirectory
139
- FileUtils.cp build, cached_path
140
- end
141
- end
142
-
143
- def cached_resources
144
- copy_from_cache.map do |item|
145
- cached_path = cache_path(item.path)
146
- build = build_path(item.path)
147
- CachedResource.new(
148
- path: item.path, cached_path: cached_path, build_path: build
149
- )
150
- end
151
- end
152
-
153
- def cache
154
- return @cache_manifest if @cache_manifest
155
- if File.exist?(cache_manifest_path)
156
- @cache_manifest = JSON.load(File.read(cache_manifest_path))
157
- else
158
- @cache_manifest = {}
159
- end
160
- end
161
-
162
- def cache_manifest_path
163
- cache_path(".cache.json")
164
- end
165
-
166
- def cache_path(path)
167
- ::File.join(options.cache_directory, path)
168
- end
169
-
170
- def build_path(path)
171
- File.join("build", path)
172
- end
173
-
174
- def ensure_cache_directory
175
- FileUtils.mkdir_p options.cache_directory
176
- end
177
- end
178
-
179
- ::Middleman::Extensions.register(:caching_proxy, MiddlemanExtension)
5
+ ::Middleman::Extensions.register(
6
+ :caching_proxy, Middleman::CachingProxy::Extension
7
+ )
@@ -0,0 +1,44 @@
1
+ require "autostruct/wrap"
2
+ require "fileutils"
3
+
4
+ require "middleman/caching_proxy/cache_manifest"
5
+
6
+ class Cache
7
+ def initialize(path:, key:)
8
+ @manifest = nil
9
+ end
10
+ include Autostruct::Wrap
11
+
12
+ def has?(item)
13
+ cached_path = full_path(item: item)
14
+ return false if !::File.exist?(cached_path)
15
+ manifest.has?(item)
16
+ end
17
+
18
+ def add(item:, source:)
19
+ manifest.add item
20
+ cached_path = full_path(item: item)
21
+ copy_in source, cached_path
22
+ end
23
+
24
+ def full_path(item:)
25
+ ::File.join(path, "items", item.path)
26
+ end
27
+
28
+ def save
29
+ manifest.save
30
+ end
31
+
32
+ private
33
+
34
+ def manifest
35
+ @manifest ||= CacheManifest.new(path: path, key: key)
36
+ end
37
+
38
+ def copy_in(source, cached_path)
39
+ cache_subdirectory = ::File.dirname(cached_path)
40
+ FileUtils.mkdir_p cache_subdirectory
41
+
42
+ FileUtils.cp source, cached_path
43
+ end
44
+ end
@@ -0,0 +1,6 @@
1
+ require "autostruct/wrap"
2
+
3
+ class CacheItem
4
+ def initialize(path:, template:, proxy_options:, fingerprint:); end
5
+ include Autostruct::Wrap
6
+ end
@@ -0,0 +1,79 @@
1
+ require "autostruct/wrap"
2
+ require "fileutils"
3
+
4
+ require "middleman/caching_proxy/version"
5
+
6
+ class CacheManifest
7
+ FILENAME = ".manifest.json"
8
+ KEY = "key"
9
+ ITEMS = "items"
10
+ VERSION = "version"
11
+
12
+ def initialize(path:, key:)
13
+ @manifest = nil
14
+ @items = nil
15
+ end
16
+ include Autostruct::Wrap
17
+
18
+ def has?(item)
19
+ items[item.path] == item.fingerprint
20
+ end
21
+
22
+ def add(item)
23
+ items[item.path] = item.fingerprint
24
+ end
25
+
26
+ def save
27
+ ensure_cache_directory
28
+ File.open(manifest_path, "w") do |f|
29
+ f.write build(items: items).to_json
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def items
36
+ @items ||= manifest[ITEMS]
37
+ end
38
+
39
+ def manifest_path
40
+ ::File.join(path, FILENAME)
41
+ end
42
+
43
+ def manifest
44
+ return @manifest if @manifest
45
+ @manifest = build
46
+ if File.exist?(manifest_path)
47
+ from_disk = JSON.load(File.read(manifest_path))
48
+ if is_ok?(from_disk)
49
+ @manifest = from_disk
50
+ end
51
+ end
52
+ @manifest
53
+ end
54
+
55
+ def is_ok?(manifest)
56
+ return false if manifest.nil?
57
+ return false if manifest[VERSION] != version
58
+ # Clear cache if key changes
59
+ return false if manifest[KEY] != key
60
+ return false if !manifest[ITEMS].is_a?(Hash)
61
+ true
62
+ end
63
+
64
+ def build(items: [])
65
+ {
66
+ KEY => key,
67
+ ITEMS => items,
68
+ VERSION => version
69
+ }
70
+ end
71
+
72
+ def version
73
+ Middleman::CachingProxy::VERSION
74
+ end
75
+
76
+ def ensure_cache_directory
77
+ FileUtils.mkdir_p path
78
+ end
79
+ end
@@ -0,0 +1,30 @@
1
+ require "autostruct/wrap"
2
+
3
+ class CachedResource
4
+ def initialize(path:, cached_path:, build_path:); end
5
+ include Autostruct::Wrap
6
+
7
+ def destination_path
8
+ path[1..-1]
9
+ end
10
+
11
+ def ext
12
+ ""
13
+ end
14
+
15
+ def ignored?
16
+ false # Seems to mean "actually include in build?"
17
+ end
18
+
19
+ def binary?
20
+ true # Seems to mean "do a binary copy or make a rack request?"
21
+ end
22
+
23
+ def source_file
24
+ cached_path
25
+ end
26
+
27
+ def content_type
28
+ "text/html"
29
+ end
30
+ end
@@ -0,0 +1,102 @@
1
+ require "middleman-core"
2
+ require "semantic"
3
+
4
+ require "middleman/caching_proxy/cache"
5
+ require "middleman/caching_proxy/cache_item"
6
+ require "middleman/caching_proxy/cached_resource"
7
+
8
+ class Middleman::CachingProxy::Extension < ::Middleman::Extension
9
+ option :cache_directory,
10
+ "tmp/proxy_cache",
11
+ "The directory where cache files will be stored"
12
+ option :cache_key,
13
+ nil,
14
+ "A global cache key"
15
+
16
+ if Semantic::Version.new(Middleman::VERSION).major >= 4
17
+ expose_to_config :proxy_with_cache
18
+ end
19
+
20
+ module InstanceMethods
21
+ def proxy_with_cache(path:, template:, proxy_options:, fingerprint:)
22
+ item = CacheItem.new(
23
+ path: path,
24
+ template: template,
25
+ proxy_options: proxy_options,
26
+ fingerprint: fingerprint
27
+ )
28
+ will_use_cache = extensions[:caching_proxy].add(item)
29
+ if !will_use_cache
30
+ proxy item.path, item.template, item.proxy_options
31
+ end
32
+ end
33
+ end
34
+
35
+ attr_reader :copy_from_cache
36
+ attr_reader :add_to_cache
37
+
38
+ def initialize(app, options_hash = {}, &block)
39
+ super
40
+
41
+ if Semantic::Version.new(Middleman::VERSION).major <= 3
42
+ app.send :include, InstanceMethods
43
+ end
44
+
45
+ if !options.cache_key
46
+ raise "Please supply a cache_key value"
47
+ end
48
+
49
+ @copy_from_cache = []
50
+ @add_to_cache = []
51
+ @cache = nil
52
+ end
53
+
54
+ def manipulate_resource_list(resources)
55
+ resources + cached_resources
56
+ end
57
+
58
+ def after_build(_builder)
59
+ copy_new_files_to_cache
60
+ cache.save
61
+ end
62
+
63
+ def add(item)
64
+ if cache.has?(item)
65
+ copy_from_cache << item
66
+ true
67
+ else
68
+ add_to_cache << item
69
+ false
70
+ end
71
+ end
72
+
73
+ private
74
+
75
+ def cache
76
+ @cache ||= Cache.new(path: options.cache_directory, key: options.cache_key)
77
+ end
78
+
79
+ def copy_new_files_to_cache
80
+ add_to_cache.each do |item|
81
+ # Handle directory_indexes extension
82
+ resource = app.sitemap.find_resource_by_path(item.path)
83
+ build_path = relative_build_path(resource.destination_path)
84
+ cache.add item: item, source: build_path
85
+ end
86
+ end
87
+
88
+ def cached_resources
89
+ copy_from_cache.map do |item|
90
+ cached_path = cache.full_path(item: item)
91
+ # TODO: Handle directory_indexes extension
92
+ build_path = relative_build_path(item.path)
93
+ CachedResource.new(
94
+ path: item.path, cached_path: cached_path, build_path: build_path
95
+ )
96
+ end
97
+ end
98
+
99
+ def relative_build_path(path)
100
+ File.join("build", path)
101
+ end
102
+ end
@@ -2,6 +2,6 @@ module Middleman; end
2
2
 
3
3
  module Middleman
4
4
  module CachingProxy
5
- VERSION = "0.1.0"
5
+ VERSION = "0.1.2"
6
6
  end
7
7
  end
@@ -1,7 +1,7 @@
1
1
  # coding: utf-8
2
2
  lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'middleman/caching_proxy/version'
4
+ require "middleman/caching_proxy/version"
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "middleman-caching-proxy"
@@ -21,6 +21,7 @@ Gem::Specification.new do |spec|
21
21
 
22
22
  spec.add_runtime_dependency "middleman", ">= 3.0.0", "< 4.0.0"
23
23
  spec.add_runtime_dependency "semantic"
24
+ spec.add_runtime_dependency "autostruct"
24
25
 
25
26
  spec.add_development_dependency "bundler", "~> 1.13"
26
27
  spec.add_development_dependency "rake", "~> 10.0"
@@ -1,11 +1,7 @@
1
1
  require "spec_helper"
2
2
 
3
- describe Middleman::Caching::Proxy do
3
+ describe Middleman::CachingProxy do
4
4
  it "has a version number" do
5
5
  expect(Middleman::Caching::Proxy::VERSION).not_to be nil
6
6
  end
7
-
8
- it "does something useful" do
9
- expect(false).to eq(true)
10
- end
11
7
  end
data/spec/spec_helper.rb CHANGED
@@ -1,2 +1,2 @@
1
1
  $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
2
- require "middleman/caching/proxy"
2
+ require "middleman/caching_proxy"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: middleman-caching-proxy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joe Yates
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-11-16 00:00:00.000000000 Z
11
+ date: 2016-11-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: middleman
@@ -44,6 +44,20 @@ dependencies:
44
44
  - - ">="
45
45
  - !ruby/object:Gem::Version
46
46
  version: '0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: autostruct
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
47
61
  - !ruby/object:Gem::Dependency
48
62
  name: bundler
49
63
  requirement: !ruby/object:Gem::Requirement
@@ -106,9 +120,14 @@ files:
106
120
  - bin/setup
107
121
  - lib/middleman-caching-proxy.rb
108
122
  - lib/middleman/caching_proxy.rb
123
+ - lib/middleman/caching_proxy/cache.rb
124
+ - lib/middleman/caching_proxy/cache_item.rb
125
+ - lib/middleman/caching_proxy/cache_manifest.rb
126
+ - lib/middleman/caching_proxy/cached_resource.rb
127
+ - lib/middleman/caching_proxy/extension.rb
109
128
  - lib/middleman/caching_proxy/version.rb
110
129
  - middleman-caching-proxy.gemspec
111
- - spec/middleman/caching/proxy_spec.rb
130
+ - spec/middleman/caching_proxy_spec.rb
112
131
  - spec/spec_helper.rb
113
132
  homepage: https://github.com/joeyates/middleman-caching-proxy
114
133
  licenses: