webpacker_uploader 0.3.0 → 0.4.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.
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