vite_ruby 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 522fa472785527e2ee77fac1df4b7471a7d9dbce81ac768f0723604389151d74
4
+ data.tar.gz: 7e080892e4b503768b43d04cd9c562c655ff76cb939ceb956b72e278500994fe
5
+ SHA512:
6
+ metadata.gz: 14cc69c07939b2b67a0bb1f7a2ef3db95373f2ab12e83bf826ade50ceb877ff7d25db823c8b928247c7e81ee8a50e556c213806317a64c09a77c4c88a4f68c62
7
+ data.tar.gz: e41055b2a38e7e24ee8ba3a9f942448068f427187f8c300d6a3721a295573937a08c956307d9a4246d30a440e00ec015815e45ee2a8aef49d2790e7e0004164f
data/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ ## Vite Ruby 1.0.0 (2020-02-09)
2
+
3
+ - Initial release, extracted core functionality from `vite_rails`.
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,33 @@
1
+ ## Setting Up a Development Environment
2
+
3
+ 1. Install [Yarn](https://yarnpkg.com/)
4
+
5
+ 2. Run the following commands to set up the development environment.
6
+
7
+ ```
8
+ bundle install
9
+ ```
10
+
11
+ ## Making sure your changes pass all tests
12
+ There are a number of automated checks which run on GitHub Actions when a pull request is created.
13
+ You can run those checks on your own locally to make sure that your changes would not break the CI build.
14
+
15
+ ### 1. Check the code for JavaScript style violations
16
+ ```
17
+ yarn lint
18
+ ```
19
+
20
+ ### 2. Check the code for Ruby style violations
21
+ ```
22
+ bundle exec rubocop
23
+ ```
24
+
25
+ ### 3. Run the JavaScript test suite
26
+ ```
27
+ yarn test
28
+ ```
29
+
30
+ ### 4. Run the Ruby test suite
31
+ ```
32
+ bundle exec rake test
33
+ ```
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2020 Maximo Mussini
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,82 @@
1
+ <h1 align="center">
2
+ <a href="https://vite-rails.netlify.app/">
3
+ <img src="https://raw.githubusercontent.com/ElMassimo/vite_rails/main/docs/public/logo.svg" width="120px"/>
4
+ </a>
5
+
6
+ <br>
7
+
8
+ <a href="https://vite-rails.netlify.app/">
9
+ Vite Ruby
10
+ </a>
11
+
12
+ <br>
13
+
14
+ <p align="center">
15
+ <a href="https://github.com/ElMassimo/vite_rails/actions">
16
+ <img alt="Build Status" src="https://github.com/ElMassimo/vite_rails/workflows/build/badge.svg"/>
17
+ </a>
18
+ <a href="https://codeclimate.com/github/ElMassimo/vite_rails">
19
+ <img alt="Maintainability" src="https://codeclimate.com/github/ElMassimo/vite_rails/badges/gpa.svg"/>
20
+ </a>
21
+ <a href="https://codeclimate.com/github/ElMassimo/vite_rails">
22
+ <img alt="Test Coverage" src="https://codeclimate.com/github/ElMassimo/vite_rails/badges/coverage.svg"/>
23
+ </a>
24
+ <a href="https://rubygems.org/gems/vite_ruby">
25
+ <img alt="Gem Version" src="https://img.shields.io/gem/v/vite_ruby.svg?colorB=e9573f"/>
26
+ </a>
27
+ <a href="https://github.com/ElMassimo/vite_rails/blob/master/LICENSE.txt">
28
+ <img alt="License" src="https://img.shields.io/badge/license-MIT-428F7E.svg"/>
29
+ </a>
30
+ </p>
31
+ </h1>
32
+
33
+ [website]: https://vite-rails.netlify.app/
34
+ [configuration reference]: https://vite-rails.netlify.app/config/
35
+ [features]: https://vite-rails.netlify.app/guide/introduction.html
36
+ [guides]: https://vite-rails.netlify.app/guide/
37
+ [config]: https://vite-rails.netlify.app/config/
38
+ [vite_rails]: https://github.com/ElMassimo/vite_rails
39
+ [webpacker]: https://github.com/rails/webpacker
40
+ [vite]: http://vitejs.dev/
41
+ [config file]: https://github.com/ElMassimo/vite_rails/blob/main/vite-plugin-ruby/default.vite.json
42
+ [example app]: https://github.com/ElMassimo/pingcrm-vite
43
+ [heroku]: https://pingcrm-vite.herokuapp.com/
44
+ [Issues]: https://github.com/ElMassimo/vite_rails/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc
45
+ [Discussions]: https://github.com/ElMassimo/vite_rails/discussions
46
+ [vite_rails]: https://github.com/ElMassimo/vite_rails/tree/main/vite_rails
47
+ [vite_ruby]: https://github.com/ElMassimo/vite_rails/tree/main/vite_ruby
48
+ [vite_hanami]: https://github.com/ElMassimo/vite_rails/tree/main/vite_hanami
49
+
50
+
51
+ [Vite] is to frontend tooling as Ruby to programming, pure joy! 😍
52
+
53
+ This is the core library for Rack apps, used by [<kbd>vite_rails</kbd>][vite_rails] and [<kbd>vite_hanami</kbd>][vite_hanami].
54
+
55
+ ## Features ⚡️
56
+
57
+ - 💡 Instant server start
58
+ - ⚡️ Blazing fast hot reload
59
+ - 🚀 Zero-config deployments
60
+ - 🤝 Integrated with <kbd>assets:precompile</kbd>
61
+ - [And more!][features]
62
+
63
+ ## Documentation 📖
64
+
65
+ Visit the [documentation website][website] to check out the [guides] and searchable [configuration reference].
66
+
67
+ ## Contact ✉️
68
+
69
+ Please use [Issues] to report bugs you find, and [Discussions] to make feature requests or get help.
70
+
71
+ Don't hesitate to _⭐️ star the project_ if you find it useful!
72
+
73
+
74
+ ## Special Thanks 🙏
75
+
76
+ - [webpacker]
77
+ - [vite]
78
+
79
+
80
+ ## License
81
+
82
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/default.vite.json ADDED
@@ -0,0 +1,17 @@
1
+ {
2
+ "assetHost": null,
3
+ "assetsDir": "assets",
4
+ "autoBuild": false,
5
+ "buildCacheDir": "tmp/cache/vite",
6
+ "publicOutputDir": "vite",
7
+ "configPath": "config/vite.json",
8
+ "devServerConnectTimeout": 0.01,
9
+ "publicDir": "public",
10
+ "entrypointsDir": "entrypoints",
11
+ "sourceCodeDir": "app/frontend",
12
+ "host": "localhost",
13
+ "https": null,
14
+ "port": 3036,
15
+ "hideBuildConsoleOutput": false,
16
+ "watchAdditionalPaths": []
17
+ }
data/exe/vite ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ ENV['RAILS_ENV'] ||= ENV['RACK_ENV']
5
+
6
+ require 'bundler/setup'
7
+ require 'vite_ruby'
8
+
9
+ cli = ViteRuby::CLI
10
+ Dry::CLI.new(cli).call
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ $stdout.sync = true
4
+
5
+ require 'rake'
6
+
7
+ namespace :vite do
8
+ task :binstubs do
9
+ ViteRuby.commands.install_binstubs
10
+ end
11
+
12
+ desc 'Compile JavaScript packs using vite for production with digests'
13
+ task build: :'vite:verify_install' do
14
+ ViteRuby.commands.build_from_task
15
+ end
16
+
17
+ desc 'Remove old compiled vites'
18
+ task :clean, [:keep, :age] => :'vite:verify_install' do |_, args|
19
+ ViteRuby.commands.clean_from_task(args)
20
+ end
21
+
22
+ desc 'Remove the vite build output directory'
23
+ task clobber: :'vite:verify_install' do
24
+ ViteRuby.commands.clobber
25
+ $stdout.puts "Removed vite build output directory #{ ViteRuby.config.build_output_dir }"
26
+ end
27
+
28
+ desc 'Verifies if ViteRuby is properly installed in this application'
29
+ task :verify_install do
30
+ ViteRuby.commands.verify_install
31
+ end
32
+
33
+ desc 'Install all JavaScript dependencies'
34
+ task :install_dependencies do
35
+ system({ 'NODE_ENV' => 'development' }, 'npx ci')
36
+ end
37
+
38
+ desc "Provide information on ViteRuby's environment"
39
+ task :info do
40
+ ViteRuby.commands.print_info
41
+ end
42
+ end
43
+
44
+ if Rake::Task.task_defined?('assets:precompile')
45
+ Rake::Task['assets:precompile'].enhance do |task|
46
+ prefix = task.name.split(/#|assets:precompile/).first
47
+ Rake::Task["#{ prefix }vite:build"].invoke
48
+ end
49
+ else
50
+ Rake::Task.define_task('assets:precompile' => ['vite:install_dependencies', 'vite:build'])
51
+ end
data/lib/vite_ruby.rb ADDED
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'logger'
4
+ require 'forwardable'
5
+ require 'pathname'
6
+
7
+ require 'zeitwerk'
8
+ loader = Zeitwerk::Loader.for_gem
9
+ loader.ignore("#{ __dir__ }/install")
10
+ loader.ignore("#{ __dir__ }/tasks")
11
+ loader.ignore("#{ __dir__ }/exe")
12
+ loader.inflector.inflect('cli' => 'CLI')
13
+ loader.setup
14
+
15
+ class ViteRuby
16
+ # Internal: Prefix used for environment variables that modify the configuration.
17
+ ENV_PREFIX = 'VITE_RUBY'
18
+
19
+ # Internal: Versions used by default when running `vite install`.
20
+ DEFAULT_VITE_VERSION = '^2.0.0-beta.65'
21
+ DEFAULT_PLUGIN_VERSION = '^1.0.8'
22
+
23
+ # Internal: Ruby Frameworks that have a companion library for Vite Ruby.
24
+ SUPPORTED_FRAMEWORKS = %w[rails hanami roda].freeze
25
+
26
+ class << self
27
+ extend Forwardable
28
+
29
+ def_delegators :instance, :config, :commands, :run_proxy?
30
+ def_delegators :config, :mode
31
+ def_delegators :commands, :build
32
+ def_delegators 'ViteRuby::Runner.new', :run
33
+
34
+ def instance
35
+ @instance ||= ViteRuby.new
36
+ end
37
+
38
+ # Public: Additional environment variables to pass to Vite.
39
+ #
40
+ # Example:
41
+ # ViteRuby.env['VITE_RUBY_CONFIG_PATH'] = 'config/alternate_vite.json'
42
+ def env
43
+ @env ||= load_env_variables
44
+ end
45
+
46
+ # Internal: Refreshes the manifest.
47
+ def bootstrap
48
+ instance.manifest.refresh
49
+ end
50
+
51
+ # Internal: Loads all available rake tasks.
52
+ def install_tasks
53
+ load File.expand_path('tasks/vite.rake', __dir__)
54
+ end
55
+
56
+ # Internal: Refreshes the config after setting the env vars.
57
+ def reload_with(env_vars)
58
+ env.update(env_vars)
59
+ @instance = nil
60
+ config
61
+ end
62
+
63
+ # Internal: Allows to obtain any env variables for configuration options.
64
+ def load_env_variables
65
+ ENV.select { |key, _| key.start_with?(ENV_PREFIX) }
66
+ end
67
+
68
+ # Internal: Detects if the application has installed a framework-specific
69
+ # variant of Vite Ruby.
70
+ def framework_libraries
71
+ SUPPORTED_FRAMEWORKS.map { |framework|
72
+ if library = Gem.loaded_specs["vite_#{ framework }"]
73
+ [framework, library]
74
+ end
75
+ }.compact
76
+ end
77
+ end
78
+
79
+ attr_writer :logger
80
+
81
+ def logger
82
+ @logger ||= Logger.new($stdout)
83
+ end
84
+
85
+ # Public: Returns true if the Vite development server is currently running.
86
+ # NOTE: Checks only once every second since every lookup calls this method.
87
+ def dev_server_running?
88
+ return false unless run_proxy?
89
+ return true if defined?(@running_at) && @running_at && Time.now - @running_at < 1
90
+
91
+ Socket.tcp(config.host, config.port, connect_timeout: config.dev_server_connect_timeout).close
92
+ @running_at = Time.now
93
+ true
94
+ rescue SystemCallError
95
+ @running_at = false
96
+ end
97
+
98
+ # Public: The proxy for assets should only run in development mode.
99
+ def run_proxy?
100
+ config.mode == 'development'
101
+ rescue StandardError => error
102
+ logger.error("Failed to check mode for Vite: #{ error.message }")
103
+ false
104
+ end
105
+
106
+ # Public: Keeps track of watched files and triggers builds as needed.
107
+ def builder
108
+ @builder ||= ViteRuby::Builder.new(self)
109
+ end
110
+
111
+ # Internal: Helper to run commands related with Vite.
112
+ def commands
113
+ @commands ||= ViteRuby::Commands.new(self)
114
+ end
115
+
116
+ # Public: Current instance configuration for Vite.
117
+ def config
118
+ @config ||= ViteRuby::Config.resolve_config
119
+ end
120
+
121
+ # Public: Enables looking up assets managed by Vite using name and type.
122
+ def manifest
123
+ @manifest ||= ViteRuby::Manifest.new(self)
124
+ end
125
+ end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'digest/sha1'
4
+
5
+ # Public: Keeps track of watched files and triggers builds as needed.
6
+ class ViteRuby::Builder
7
+ def initialize(vite_ruby)
8
+ @vite_ruby = vite_ruby
9
+ end
10
+
11
+ # Public: Checks if the watched files have changed since the last compilation,
12
+ # and triggers a Vite build if any files have changed.
13
+ def build
14
+ if stale?
15
+ build_with_vite.tap { record_files_digest }
16
+ else
17
+ logger.debug 'Skipping build. Vite assets are already up-to-date ⚡️'
18
+ true
19
+ end
20
+ end
21
+
22
+ # Public: Returns true if all the assets built by Vite are up to date.
23
+ def fresh?
24
+ previous_files_digest&.== watched_files_digest
25
+ end
26
+
27
+ # Public: Returns true if any of the assets built by Vite is out of date.
28
+ def stale?
29
+ !fresh?
30
+ end
31
+
32
+ private
33
+
34
+ extend Forwardable
35
+
36
+ def_delegators :@vite_ruby, :config, :logger
37
+
38
+ # Internal: Writes a digest of the watched files to disk for future checks.
39
+ def record_files_digest
40
+ config.build_cache_dir.mkpath
41
+ files_digest_path.write(watched_files_digest)
42
+ end
43
+
44
+ # Internal: The path of where a digest of the watched files is stored.
45
+ def files_digest_path
46
+ config.build_cache_dir.join("last-compilation-digest-#{ config.mode }")
47
+ end
48
+
49
+ # Internal: Reads a digest of watched files from disk.
50
+ def previous_files_digest
51
+ files_digest_path.read if files_digest_path.exist? && config.manifest_path.exist?
52
+ rescue Errno::ENOENT, Errno::ENOTDIR
53
+ end
54
+
55
+ # Internal: Returns a digest of all the watched files, allowing to detect
56
+ # changes, and skip Vite builds if no files have changed.
57
+ def watched_files_digest
58
+ Dir.chdir File.expand_path(config.root) do
59
+ files = Dir[*watched_paths].reject { |f| File.directory?(f) }
60
+ file_ids = files.sort.map { |f| "#{ File.basename(f) }/#{ Digest::SHA1.file(f).hexdigest }" }
61
+ Digest::SHA1.hexdigest(file_ids.join('/'))
62
+ end
63
+ end
64
+
65
+ # Public: Initiates a Vite build command to generate assets.
66
+ #
67
+ # Returns true if the build is successful, or false if it failed.
68
+ def build_with_vite
69
+ logger.info 'Building with Vite ⚡️'
70
+
71
+ stdout, stderr, status = ViteRuby.run(['build'], capture: true)
72
+ log_build_result(stdout, stderr, status)
73
+
74
+ status.success?
75
+ end
76
+
77
+ # Internal: Outputs the build results.
78
+ #
79
+ # NOTE: By default it also outputs the manifest entries.
80
+ def log_build_result(stdout, stderr, status)
81
+ if status.success?
82
+ logger.info "Build with Vite complete: #{ config.build_output_dir }"
83
+ logger.error(stderr.to_s) unless stderr.empty?
84
+ logger.info(stdout) unless config.hide_build_console_output
85
+ else
86
+ non_empty_streams = [stdout, stderr].delete_if(&:empty?)
87
+ logger.error "Build with Vite failed:\n#{ non_empty_streams.join("\n\n") }"
88
+ end
89
+ end
90
+
91
+ # Internal: Files and directories that should be watched for changes.
92
+ #
93
+ # NOTE: You can specify additional ones in vite.json using "watchAdditionalPaths": [...]
94
+ def watched_paths
95
+ [
96
+ *config.watch_additional_paths,
97
+ "#{ config.source_code_dir }/**/*",
98
+ 'yarn.lock',
99
+ 'package.json',
100
+ config.config_path,
101
+ ].freeze
102
+ end
103
+ end