webpacker_uploader 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -1,6 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "bundler/gem_tasks"
2
4
  require "rake/testtask"
3
5
 
6
+ require "yard"
7
+ YARD::Rake::YardocTask.new
8
+
4
9
  Rake::TestTask.new(:test) do |t|
5
10
  t.libs << "test"
6
11
  t.libs << "lib"
@@ -1,21 +1,31 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/core_ext/object/blank"
4
- require "active_support/logger"
5
- require "active_support/tagged_logging"
6
4
 
7
5
  module WebpackerUploader
8
6
  extend self
9
7
 
8
+ # @private
10
9
  def instance=(instance)
11
10
  @instance = instance
12
11
  end
13
12
 
13
+ # @private
14
14
  def instance
15
15
  @instance ||= WebpackerUploader::Instance.new
16
16
  end
17
17
 
18
- delegate :logger, :logger=, :configure, :config, :upload!, to: :instance
18
+ # @!attribute [rw] config
19
+ # @see Instance#config
20
+ # @!scope class
21
+ # @!method configure
22
+ # @see Instance#configure
23
+ # @!scope class
24
+ # @!method upload!
25
+ # @return [void]
26
+ # @see Instance#upload!
27
+ # @!scope class
28
+ delegate :configure, :config, :upload!, to: :instance
19
29
  end
20
30
 
21
31
  require "webpacker_uploader/configuration"
@@ -1,13 +1,33 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/logger"
4
+ require "active_support/tagged_logging"
5
+
6
+ # This is the class which holds the configuration options.
7
+ #
8
+ # Options are set and retrieved using `WebpackerUploader.config`
9
+ # and `WebpackerUploader.configure`.
3
10
  class WebpackerUploader::Configuration
4
- attr_accessor :ignored_extensions, :log_output
5
- attr_reader :public_manifest_path, :public_path
11
+ # @return [Array] the file extentions ignored by the uploader.
12
+ attr_accessor :ignored_extensions
13
+
14
+ # @return [ActiveSupport::Logger] the logger to use.
15
+ attr_accessor :logger
16
+
17
+ # @return [Boolean] whether or not to log operations.
18
+ attr_accessor :log_output
19
+
20
+ # @return [Pathname] the path to manifest.json, defaults to Webpacker public manifest path.
21
+ attr_reader :public_manifest_path
22
+
23
+ # @return [Pathname] the public root path, defaults to Webpacker public root path.
24
+ attr_reader :public_path
6
25
 
7
26
  alias_method :log_output?, :log_output
8
27
 
9
28
  def initialize
10
29
  @ignored_extensions = []
30
+ @logger = ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new(STDOUT))
11
31
  @log_output = true
12
32
  @public_manifest_path = ::Webpacker.config.public_manifest_path
13
33
  @public_path = ::Webpacker.config.public_path
@@ -1,22 +1,50 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class WebpackerUploader::Instance
4
- cattr_accessor(:logger) { ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new(STDOUT)) }
5
-
6
4
  attr_writer :config
7
5
 
6
+ # @private
8
7
  def manifest
9
8
  @manifest ||= WebpackerUploader::Manifest.new
10
9
  end
11
10
 
11
+ # Returns the global WebpackerUploader::Configuration object.
12
+ # Use this to set and retrieve specific configuration options.
13
+ #
14
+ # @return [WebpackerUploader::Configuration]
15
+ #
16
+ # @example Disable log output
17
+ # WebpackerUploader.config.log_output = false
18
+ #
19
+ # @example Get the list of excluded file extension
20
+ # puts WebpackerUploader.config.ignored_extensions
21
+ #
22
+ # @see WebpackerUploader::Configuration
12
23
  def config
13
24
  @config ||= WebpackerUploader::Configuration.new
14
25
  end
15
26
 
27
+ # Yields the global configuration to a block. Use this to
28
+ # configure the base gem features.
29
+ #
30
+ # @example
31
+ # WebpackerUploader.configure do |config|
32
+ # config.ignored_extensions = [".png", ".jpg", ".webp"]
33
+ # config.log_output = false
34
+ # config.public_manifest_path = "path/to/manifest.json"
35
+ # config.public_path = "path/to/public/dir"
36
+ # end
37
+ #
38
+ # @see WebpackerUploader::Configuration
16
39
  def configure
17
40
  yield config
18
41
  end
19
42
 
43
+ # Uploads assets using the supplied provider. Currently only AWS S3 is implemented.
44
+ #
45
+ # @return [void]
46
+ # @param provider [WebpackerUploader::Providers::Aws] A provider to use for file uploading.
47
+ # @param prefix [String] Used to prefix the remote file paths.
20
48
  def upload!(provider, prefix: nil)
21
49
  manifest.assets.each do |name, js_path|
22
50
  path = js_path[1..-1]
@@ -31,11 +59,11 @@ class WebpackerUploader::Instance
31
59
  file_path = config.public_path.join(path)
32
60
 
33
61
  if name.end_with?(*config.ignored_extensions)
34
- logger.info("Skipping #{file_path}") if config.log_output?
62
+ config.logger.info("Skipping #{file_path}") if config.log_output?
35
63
  else
36
64
  content_type = WebpackerUploader::Mime.mime_type(path)
37
65
 
38
- logger.info("Processing #{file_path} as #{content_type}") if config.log_output?
66
+ config.logger.info("Processing #{file_path} as #{content_type}") if config.log_output?
39
67
 
40
68
  provider.upload!(remote_path, file_path, content_type)
41
69
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class WebpackerUploader::Manifest
3
+ class WebpackerUploader::Manifest # @private
4
4
  attr_reader :assets
5
5
 
6
6
  def initialize
@@ -3,6 +3,12 @@
3
3
  require "mime-types"
4
4
 
5
5
  module WebpackerUploader::Mime
6
+ # Returns the mime type for the given file in the filesystem.
7
+ # If it's unable to detect the mime type, it returns +application/octet-stream+
8
+ # as a fallback.
9
+ #
10
+ # @param file_path [String] A file path in the local filesystem.
11
+ # @return [String] The file mime type.
6
12
  def mime_type(file_path)
7
13
  fallback = MIME::Types.type_for(file_path).first&.content_type || "application/octet-stream"
8
14
  Rack::Mime.mime_type(File.extname(file_path), fallback)
@@ -3,18 +3,59 @@
3
3
  require "aws-sdk-s3"
4
4
 
5
5
  module WebpackerUploader
6
+ # Namespace for the upload providers.
6
7
  module Providers
8
+ # AWS provider uploads files to AWS S3. It uses the +aws-sdk-s3+ gem.
7
9
  class Aws
8
- attr_reader :client
9
- attr_reader :resource
10
- attr_reader :bucket
10
+ attr_reader :client, :resource, :bucket # @private
11
11
 
12
+ # @param [Hash] options
13
+ # * :region (String) The S3 region name.
14
+ # * :bucket (String) The S3 bucket name.
15
+ # * :credentials (Hash) credential options for the AWS provider:
16
+ # * :profile_name (String) use a named profile configured in ~/.aws/credentials
17
+ # * :instance_profile (Boolean) use an instance profile from an EC2
18
+ # * :access_key_id (String) the AWS credentials access id.
19
+ # * :secret_access_key (String) the AWS credentials secret access key.
20
+ #
21
+ # @example Initialize the using a named profile:
22
+ #
23
+ # provider_options = {
24
+ # credentials: { profile_name: "staging" },
25
+ # region: "eu-central-1",
26
+ # bucket: "application-assets-20200929124523451600000001"
27
+ # }
28
+ # provider = WebpackerUploader::Providers::Aws.new(provider_options)
29
+ #
30
+ # @example Initialize using IAM keys
31
+ #
32
+ # provider_options = {
33
+ # credentials: { access_key_id: "KEY_ID", secret_access_key: "ACCESS_KEY" },
34
+ # region: "eu-central-1",
35
+ # bucket: "application-assets-20200929124523451600000001"
36
+ # }
37
+ # provider = WebpackerUploader::Providers::Aws.new(provider_options)
38
+ #
39
+ # @example Initialize using an EC2 instance profile
40
+ #
41
+ # provider_options = {
42
+ # credentials: { instance_profile: true },
43
+ # region: "eu-central-1",
44
+ # bucket: "application-assets-20200929124523451600000001"
45
+ # }
46
+ # provider = WebpackerUploader::Providers::Aws.new(provider_options)
12
47
  def initialize(options)
13
48
  @client = ::Aws::S3::Client.new(credentials: credentials(options[:credentials]), region: options[:region])
14
49
  @resource = ::Aws::S3::Resource.new(client: @client)
15
50
  @bucket = @resource.bucket(options[:bucket])
16
51
  end
17
52
 
53
+ # Uploads a file to AWS S3.
54
+ #
55
+ # @param object_key [String] Is the remote path name for the S3 object.
56
+ # @param file [Pathname] Path of the local file.
57
+ # @param content_type [String] The content type that will be set to the S3 object.
58
+ # @return [void]
18
59
  def upload!(object_key, file, content_type = "")
19
60
  object = @bucket.object(object_key)
20
61
  object.upload_file(file, content_type: content_type)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WebpackerUploader
2
- VERSION = "0.3.0"
4
+ VERSION = "0.4.0"
3
5
  end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ class ConfigurationTest < Minitest::Test
6
+ def setup
7
+ @config = WebpackerUploader::Configuration.new
8
+ end
9
+
10
+ def teardown
11
+ WebpackerUploader.reset!
12
+ end
13
+
14
+ def test_default_config_options
15
+ assert_empty @config.ignored_extensions
16
+
17
+ assert_instance_of ActiveSupport::Logger, @config.logger
18
+
19
+ assert @config.log_output
20
+ assert @config.log_output?
21
+
22
+ public_manifest_path = Pathname.new(File.expand_path("test_app/public/packs/manifest.json", __dir__))
23
+ assert_equal public_manifest_path, @config.public_manifest_path
24
+
25
+ public_path = Pathname.new(File.expand_path("test_app/public/", __dir__))
26
+ assert_equal public_path, @config.public_path
27
+ end
28
+
29
+ def test_changing_config_options
30
+ @config.ignored_extensions = [".css", ".js"]
31
+ assert_equal [".css", ".js"], @config.ignored_extensions
32
+
33
+ @config.logger = Logger.new(STDOUT)
34
+ assert_instance_of Logger, @config.logger
35
+
36
+ @config.log_output = false
37
+ refute @config.log_output
38
+ refute @config.log_output?
39
+
40
+ @config.public_manifest_path = "test_app/manifest.json"
41
+ assert_equal "test_app/manifest.json", @config.public_manifest_path.to_s
42
+
43
+ @config.public_path = "test_app"
44
+ assert_equal "test_app", @config.public_path.to_s
45
+ end
46
+
47
+ def test_configure_block
48
+ WebpackerUploader.configure do |c|
49
+ c.ignored_extensions = [".js"]
50
+ c.logger = Logger.new(STDOUT)
51
+ c.log_output = false
52
+ c.public_manifest_path = "path/to/manifest.json"
53
+ c.public_path = "path/to/public/dir"
54
+ end
55
+
56
+ assert_equal [".js"], WebpackerUploader.config.ignored_extensions
57
+ assert_instance_of Logger, WebpackerUploader.config.logger
58
+ refute WebpackerUploader.config.log_output
59
+ refute WebpackerUploader.config.log_output?
60
+ assert_equal "path/to/manifest.json", WebpackerUploader.config.public_manifest_path.to_s
61
+ assert_equal "path/to/public/dir", WebpackerUploader.config.public_path.to_s
62
+
63
+ assert_raises(NoMethodError) do
64
+ WebpackerUploader.configure do |c|
65
+ c.unknown = true
66
+ end
67
+ end
68
+ end
69
+
70
+ def test_pathname_casting
71
+ WebpackerUploader.config do |c|
72
+ c.public_manifest_path = "path/to/manifest.json"
73
+ c.public_path = "path/to/public/dir"
74
+ end
75
+
76
+ assert_instance_of Pathname, WebpackerUploader.config.public_manifest_path
77
+ assert_instance_of Pathname, WebpackerUploader.config.public_path
78
+
79
+ WebpackerUploader.configure do |c|
80
+ c.public_manifest_path = Pathname.new("path/to/manifest.json")
81
+ c.public_path = Pathname.new("path/to/public/dir")
82
+ end
83
+
84
+ assert_instance_of Pathname, WebpackerUploader.config.public_manifest_path
85
+ assert_instance_of Pathname, WebpackerUploader.config.public_path
86
+ end
87
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ class ManifestTest < Minitest::Test
6
+ def setup
7
+ @manifest = ::WebpackerUploader::Manifest.new
8
+ end
9
+
10
+ def teardown
11
+ WebpackerUploader.reset!
12
+ end
13
+
14
+ def test_assets
15
+ assert_includes @manifest.assets, "application.css"
16
+ assert_includes @manifest.assets, "application.js"
17
+ assert_includes @manifest.assets, "application.png"
18
+ refute_includes @manifest.assets, "entrypoints"
19
+ end
20
+
21
+ def test_missing_manifest
22
+ WebpackerUploader.config.public_manifest_path = "missing.json"
23
+ @empty_manifest = WebpackerUploader::Manifest.new
24
+
25
+ assert_empty @empty_manifest.assets
26
+ end
27
+ end
data/test/mime_test.rb ADDED
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ class MimeTest < Minitest::Test
6
+ def test_for_webp
7
+ # Rack < 3.x does not support this so we have a fallback mechanism in place
8
+ assert_equal "image/webp", WebpackerUploader::Mime.mime_type("image-dd6b1cd38bfa093df600.webp")
9
+ end
10
+
11
+ def test_for_sourcemap
12
+ assert_equal "application/octet-stream", WebpackerUploader::Mime.mime_type("application-dd6b1cd38bfa093df600.css.map")
13
+ end
14
+ end
@@ -0,0 +1,103 @@
1
+ # Note: You must restart bin/webpack-dev-server for changes to take effect
2
+
3
+ default: &default
4
+ source_path: app/javascript
5
+ source_entry_path: packs
6
+ public_root_path: public
7
+ public_output_path: packs
8
+ cache_path: tmp/cache/webpacker
9
+ webpack_compile_output: false
10
+
11
+ # Additional paths webpack should lookup modules
12
+ # ['app/assets', 'engine/foo/app/assets']
13
+ additional_paths:
14
+ - app/assets
15
+ - /etc/yarn
16
+
17
+ # This configuration option is deprecated and is only here for testing, to
18
+ # ensure backwards-compatibility. Please use `additional_paths`.
19
+ resolved_paths:
20
+ - app/elm
21
+
22
+ # Reload manifest.json on all requests so we reload latest compiled packs
23
+ cache_manifest: false
24
+
25
+ # Extract and emit a css file
26
+ extract_css: false
27
+
28
+ static_assets_extensions:
29
+ - .jpg
30
+ - .jpeg
31
+ - .png
32
+ - .gif
33
+ - .tiff
34
+ - .ico
35
+ - .svg
36
+
37
+ extensions:
38
+ - .mjs
39
+ - .js
40
+ - .sass
41
+ - .scss
42
+ - .css
43
+ - .module.sass
44
+ - .module.scss
45
+ - .module.css
46
+ - .png
47
+ - .svg
48
+ - .gif
49
+ - .jpeg
50
+ - .jpg
51
+ - .elm
52
+
53
+ development:
54
+ <<: *default
55
+ compile: true
56
+
57
+ # Reference: https://webpack.js.org/configuration/dev-server/
58
+ dev_server:
59
+ https: false
60
+ host: localhost
61
+ port: 3035
62
+ public: localhost:3035
63
+ hmr: false
64
+ # Inline should be set to true if using HMR
65
+ inline: true
66
+ overlay: true
67
+ disable_host_check: true
68
+ use_local_ip: false
69
+ pretty: false
70
+
71
+ test:
72
+ <<: *default
73
+ compile: true
74
+
75
+ # Compile test packs to a separate directory
76
+ public_output_path: packs-test
77
+
78
+ production:
79
+ <<: *default
80
+
81
+ # Production depends on precompilation of packs prior to booting for performance.
82
+ compile: false
83
+
84
+ # Extract and emit a css file
85
+ extract_css: true
86
+
87
+ # Cache manifest.json for performance
88
+ cache_manifest: true
89
+
90
+ staging:
91
+ <<: *default
92
+
93
+ # Production depends on precompilation of packs prior to booting for performance.
94
+ compile: false
95
+
96
+ # Extract and emit a css file
97
+ extract_css: true
98
+
99
+ # Cache manifest.json for performance
100
+ cache_manifest: true
101
+
102
+ # Compile staging packs to a separate directory
103
+ public_output_path: packs-staging