hyperloop-config 0.9.11 → 0.99.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +7 -1
- data/.travis.yml +29 -0
- data/DOCS.md +45 -0
- data/Gemfile +1 -2
- data/Gemfile.lock +299 -0
- data/README.md +58 -30
- data/Rakefile +9 -0
- data/hyperloop-config.gemspec +32 -26
- data/lib/hyperloop/active_support_string_inquirer.rb +32 -0
- data/lib/hyperloop/autoloader.rb +138 -0
- data/lib/hyperloop/autoloader_starter.rb +15 -0
- data/lib/hyperloop/config/version.rb +5 -0
- data/lib/hyperloop/env.rb +10 -0
- data/lib/hyperloop/environment/development/hyperloop_env.rb +5 -0
- data/lib/hyperloop/environment/production/hyperloop_env.rb +5 -0
- data/lib/hyperloop/environment/staging/hyperloop_env.rb +5 -0
- data/lib/hyperloop/environment/test/hyperloop_env.rb +5 -0
- data/lib/hyperloop/imports.rb +35 -50
- data/lib/hyperloop/js_imports.rb +18 -0
- data/lib/hyperloop/on_error.rb +5 -0
- data/lib/hyperloop/rail_tie.rb +35 -12
- data/lib/hyperloop/string.rb +6 -0
- data/lib/hyperloop-config.rb +18 -0
- data/lib/hyperloop-loader.js +1 -1
- data/lib/hyperloop-prerender-loader.js +1 -1
- metadata +127 -38
- data/CODE_OF_CONDUCT.md +0 -49
- data/LICENSE.txt +0 -21
- data/lib/hyperloop-loader-system.js.erb +0 -1
- data/lib/hyperloop-prerender-loader-system.js.erb +0 -1
data/Rakefile
CHANGED
data/hyperloop-config.gemspec
CHANGED
@@ -1,37 +1,43 @@
|
|
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 'hyperloop/config/version'
|
4
5
|
|
5
6
|
Gem::Specification.new do |spec|
|
6
|
-
spec.name =
|
7
|
-
spec.version =
|
8
|
-
spec.authors = [
|
9
|
-
spec.email = [
|
10
|
-
|
7
|
+
spec.name = 'hyperloop-config'
|
8
|
+
spec.version = Hyperloop::Config::VERSION
|
9
|
+
spec.authors = ['Mitch VanDuyn', 'Jan Biedermann']
|
10
|
+
spec.email = ['mitch@catprint.com', 'jan@kursator.com']
|
11
11
|
spec.summary = %q{Provides a single point configuration module for hyperloop gems}
|
12
|
-
spec.homepage =
|
13
|
-
spec.license =
|
12
|
+
spec.homepage = 'http://ruby-hyperloop.org'
|
13
|
+
spec.license = 'MIT'
|
14
|
+
# spec.metadata = {
|
15
|
+
# "homepage_uri" => 'http://ruby-hyperloop.org',
|
16
|
+
# "source_code_uri" => 'https://github.com/ruby-hyperloop/hyper-component'
|
17
|
+
# }
|
14
18
|
|
15
19
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
16
|
-
spec.bindir =
|
20
|
+
spec.bindir = 'exe'
|
17
21
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
18
|
-
spec.require_paths = [
|
19
|
-
|
20
|
-
spec.add_dependency '
|
21
|
-
spec.add_dependency '
|
22
|
-
|
23
|
-
spec.
|
24
|
-
spec.
|
25
|
-
|
26
|
-
|
27
|
-
spec.add_development_dependency '
|
28
|
-
spec.add_development_dependency '
|
29
|
-
spec.add_development_dependency '
|
22
|
+
spec.require_paths = ['lib']
|
23
|
+
|
24
|
+
spec.add_dependency 'libv8', '~> 6.3.0' # see https://github.com/discourse/mini_racer/issues/92
|
25
|
+
spec.add_dependency 'mini_racer', '~> 0.1.15'
|
26
|
+
spec.add_dependency 'opal', '>= 0.11.0', '< 0.12.0'
|
27
|
+
spec.add_dependency 'opal-browser', '~> 0.2.0'
|
28
|
+
spec.add_dependency 'uglifier'
|
29
|
+
|
30
|
+
|
31
|
+
spec.add_development_dependency 'bundler', '~> 1.16.0'
|
32
|
+
spec.add_development_dependency 'chromedriver-helper'
|
33
|
+
spec.add_development_dependency 'hyper-spec', Hyperloop::Config::VERSION
|
34
|
+
spec.add_development_dependency 'opal-rails', '~> 0.9.4'
|
35
|
+
spec.add_development_dependency 'pry'
|
36
|
+
spec.add_development_dependency 'puma'
|
37
|
+
spec.add_development_dependency 'rails', '>= 4.0.0'
|
38
|
+
spec.add_development_dependency 'rake'
|
39
|
+
spec.add_development_dependency 'rspec', '~> 3.7.0'
|
40
|
+
spec.add_development_dependency 'rubocop', '~> 0.51.0'
|
30
41
|
spec.add_development_dependency 'sqlite3'
|
31
|
-
spec.add_development_dependency '
|
32
|
-
spec.add_development_dependency 'jquery-rails'
|
33
|
-
|
34
|
-
# Keep linter-rubocop happy
|
35
|
-
spec.add_development_dependency 'rubocop'
|
36
|
-
|
42
|
+
spec.add_development_dependency 'timecop', '~> 0.8.1'
|
37
43
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module ActiveSupport
|
2
|
+
# Wrapping a string in this class gives you a prettier way to test
|
3
|
+
# for equality. The value returned by <tt>Rails.env</tt> is wrapped
|
4
|
+
# in a StringInquirer object, so instead of calling this:
|
5
|
+
#
|
6
|
+
# Rails.env == 'production'
|
7
|
+
#
|
8
|
+
# you can call this:
|
9
|
+
#
|
10
|
+
# Rails.env.production?
|
11
|
+
#
|
12
|
+
# == Instantiating a new StringInquirer
|
13
|
+
#
|
14
|
+
# vehicle = ActiveSupport::StringInquirer.new('car')
|
15
|
+
# vehicle.car? # => true
|
16
|
+
# vehicle.bike? # => false
|
17
|
+
class StringInquirer < String
|
18
|
+
private
|
19
|
+
|
20
|
+
def respond_to_missing?(method_name, include_private = false)
|
21
|
+
(method_name[-1] == "?") || super
|
22
|
+
end
|
23
|
+
|
24
|
+
def method_missing(method_name, *arguments)
|
25
|
+
if method_name[-1] == "?"
|
26
|
+
self == method_name[0..-2]
|
27
|
+
else
|
28
|
+
super
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module Hyperloop
|
4
|
+
class Autoloader
|
5
|
+
# All files ever loaded.
|
6
|
+
def self.history=(a)
|
7
|
+
@@history = a
|
8
|
+
end
|
9
|
+
def self.history
|
10
|
+
@@history
|
11
|
+
end
|
12
|
+
self.history = Set.new
|
13
|
+
|
14
|
+
def self.load_paths=(a)
|
15
|
+
@@load_paths = a
|
16
|
+
end
|
17
|
+
def self.load_paths
|
18
|
+
@@load_paths
|
19
|
+
end
|
20
|
+
self.load_paths = []
|
21
|
+
|
22
|
+
def self.loaded=(a)
|
23
|
+
@@loaded = a
|
24
|
+
end
|
25
|
+
def self.loaded
|
26
|
+
@@loaded
|
27
|
+
end
|
28
|
+
self.loaded = Set.new
|
29
|
+
|
30
|
+
def self.loading=(a)
|
31
|
+
@@loading = a
|
32
|
+
end
|
33
|
+
def self.loading
|
34
|
+
@@loading
|
35
|
+
end
|
36
|
+
self.loading = []
|
37
|
+
|
38
|
+
def self.const_missing(const_name, mod)
|
39
|
+
# name.nil? is testing for anonymous
|
40
|
+
from_mod = mod.name.nil? ? guess_for_anonymous(const_name) : mod
|
41
|
+
load_missing_constant(from_mod, const_name)
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.guess_for_anonymous(const_name)
|
45
|
+
if Object.const_defined?(const_name)
|
46
|
+
raise NameError.new "#{const_name} cannot be autoloaded from an anonymous class or module", const_name
|
47
|
+
else
|
48
|
+
Object
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.load_missing_constant(from_mod, const_name)
|
53
|
+
# see active_support/dependencies.rb in case of reloading on how to handle
|
54
|
+
qualified_name = qualified_name_for(from_mod, const_name)
|
55
|
+
qualified_path = underscore(qualified_name)
|
56
|
+
|
57
|
+
module_path = search_for_module(qualified_path)
|
58
|
+
if module_path
|
59
|
+
if loading.include?(module_path)
|
60
|
+
raise "Circular dependency detected while autoloading constant #{qualified_name}"
|
61
|
+
else
|
62
|
+
require_or_load(from_mod, module_path)
|
63
|
+
raise LoadError, "Unable to autoload constant #{qualified_name}, expected #{module_path} to define it" unless from_mod.const_defined?(const_name, false)
|
64
|
+
return from_mod.const_get(const_name)
|
65
|
+
end
|
66
|
+
elsif (parent = from_mod.parent) && parent != from_mod &&
|
67
|
+
! from_mod.parents.any? { |p| p.const_defined?(const_name, false) }
|
68
|
+
begin
|
69
|
+
return parent.const_missing(const_name)
|
70
|
+
rescue NameError => e
|
71
|
+
raise unless missing_name?(e, qualified_name_for(parent, const_name))
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.missing_name?(e, name)
|
77
|
+
mn = if /undefined/ !~ e.message
|
78
|
+
$1 if /((::)?([A-Z]\w*)(::[A-Z]\w*)*)$/ =~ e.message
|
79
|
+
end
|
80
|
+
mn == name
|
81
|
+
end
|
82
|
+
|
83
|
+
# Returns the constant path for the provided parent and constant name.
|
84
|
+
def self.qualified_name_for(mod, name)
|
85
|
+
mod_name = to_constant_name(mod)
|
86
|
+
mod_name == 'Object' ? name.to_s : "#{mod_name}::#{name}"
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.require_or_load(from_mod, module_path)
|
90
|
+
return if loaded.include?(module_path)
|
91
|
+
loaded << module_path
|
92
|
+
loading << module_path
|
93
|
+
|
94
|
+
begin
|
95
|
+
result = require module_path
|
96
|
+
rescue Exception
|
97
|
+
loaded.delete module_path
|
98
|
+
raise LoadError, "Unable to autoload: require_or_load #{module_path} failed"
|
99
|
+
ensure
|
100
|
+
loading.pop
|
101
|
+
end
|
102
|
+
|
103
|
+
# Record history *after* loading so first load gets warnings.
|
104
|
+
history << module_path
|
105
|
+
result
|
106
|
+
# end
|
107
|
+
end
|
108
|
+
|
109
|
+
def self.search_for_module(path)
|
110
|
+
# oh my! imagine Bart Simpson, writing on the board:
|
111
|
+
# "javascript is not ruby, javascript is not ruby, javascript is not ruby, ..."
|
112
|
+
# then running home, starting irb, on the fly developing a chat client and opening a session with Homer at his workplace: "Hi Dad ..."
|
113
|
+
load_paths.each do |load_path|
|
114
|
+
mod_path = load_path + '/' + path
|
115
|
+
return mod_path if `Opal.modules.hasOwnProperty(#{mod_path})`
|
116
|
+
end
|
117
|
+
return path if `Opal.modules.hasOwnProperty(#{path})`
|
118
|
+
nil # Gee, I sure wish we had first_match ;-)
|
119
|
+
end
|
120
|
+
|
121
|
+
# Convert the provided const desc to a qualified constant name (as a string).
|
122
|
+
# A module, class, symbol, or string may be provided.
|
123
|
+
def self.to_constant_name(desc) #:nodoc:
|
124
|
+
case desc
|
125
|
+
when String then desc.sub(/^::/, '')
|
126
|
+
when Symbol then desc.to_s
|
127
|
+
when Module
|
128
|
+
desc.name ||
|
129
|
+
raise(ArgumentError, 'Anonymous modules have no name to be referenced by')
|
130
|
+
else raise TypeError, "Not a valid constant descriptor: #{desc.inspect}"
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def self.underscore(string)
|
135
|
+
string.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').gsub(/([a-z\d])([A-Z])/,'\1_\2').tr("-", "_").downcase
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
Hyperloop::Autoloader.load_paths = %w[components models operations stores]
|
2
|
+
|
3
|
+
class Object
|
4
|
+
class << self
|
5
|
+
alias _autoloader_original_const_missing const_missing
|
6
|
+
|
7
|
+
def const_missing(const_name)
|
8
|
+
# need to call original code because some things are set up there
|
9
|
+
# original code may also be overloaded by reactrb, for example
|
10
|
+
_autoloader_original_const_missing(const_name)
|
11
|
+
rescue StandardError => e
|
12
|
+
Hyperloop::Autoloader.const_missing(const_name, self) || raise(e)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/hyperloop/imports.rb
CHANGED
@@ -5,41 +5,49 @@ module Hyperloop
|
|
5
5
|
@import_list ||= []
|
6
6
|
end
|
7
7
|
|
8
|
-
def import(value, gem: nil,
|
9
|
-
if
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
raise [
|
15
|
-
"Could not substitute import '#{instead_of}' with '#{value}'. '#{instead_of}' not found.",
|
16
|
-
'The following files are currently being imported:',
|
17
|
-
*import_list.collect { |old_value, *_rest| old_value }
|
18
|
-
].join("\n")
|
19
|
-
end
|
20
|
-
elsif !import_list.detect { |current_value, *_rest| value == current_value }
|
21
|
-
kind = if tree
|
22
|
-
:tree
|
23
|
-
else
|
24
|
-
:gem
|
25
|
-
end
|
26
|
-
import_list << [value, !client_only, !server_only, kind]
|
27
|
-
end
|
8
|
+
def import(value, gem: nil, cancelled: nil, client_only: nil, server_only: nil, tree: nil, js_import: nil, at_head: nil)
|
9
|
+
return if import_list.detect { |current_value, *_rest| value == current_value }
|
10
|
+
new_element = [
|
11
|
+
value, cancelled, !client_only, !server_only, (tree ? :tree : :gem), js_import
|
12
|
+
]
|
13
|
+
import_list.send(at_head ? :unshift : :push, new_element)
|
28
14
|
end
|
29
15
|
|
30
16
|
alias imports import
|
31
17
|
|
32
|
-
def import_tree(value,
|
33
|
-
import(value,
|
18
|
+
def import_tree(value, cancelled: nil, client_only: nil, server_only: nil)
|
19
|
+
import(value, cancelled: cancelled, client_only: client_only, server_only: server_only, tree: true)
|
34
20
|
end
|
35
21
|
|
36
22
|
def cancel_import(value)
|
37
|
-
|
23
|
+
return unless value
|
24
|
+
current_spec = import_list.detect { |old_value, *_rest| value == old_value }
|
25
|
+
if current_spec
|
26
|
+
current_spec[1] = true
|
27
|
+
else
|
28
|
+
import_list << [value, true, true, true, false]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def cancel_webpack_imports
|
33
|
+
import_list.collect { |name, _c, _co, _so, _t, js_import, *_rest| js_import && name }
|
34
|
+
.each { |name| cancel_import name }
|
35
|
+
end
|
36
|
+
|
37
|
+
def handle_webpack
|
38
|
+
return unless defined? Webpacker
|
39
|
+
client_only_manifest = Webpacker.manifest.lookup("client_only.js")
|
40
|
+
client_and_server_manifest = Webpacker.manifest.lookup("client_and_server.js")
|
41
|
+
return unless client_only_manifest || client_and_server_manifest
|
42
|
+
cancel_webpack_imports
|
43
|
+
import client_only_manifest.split("/").last, client_only: true, at_head: true if client_only_manifest
|
44
|
+
import client_and_server_manifest.split("/").last, at_head: true if client_and_server_manifest
|
38
45
|
end
|
39
46
|
|
40
47
|
def generate_requires(mode, sys, file)
|
41
|
-
|
42
|
-
|
48
|
+
handle_webpack
|
49
|
+
import_list.collect do |value, cancelled, render_on_server, render_on_client, kind|
|
50
|
+
next if cancelled
|
43
51
|
next if (sys && kind == :tree) || (!sys && kind != :tree)
|
44
52
|
next if mode == :client && !render_on_client
|
45
53
|
next if mode == :server && !render_on_server
|
@@ -89,31 +97,8 @@ module Hyperloop
|
|
89
97
|
end
|
90
98
|
end
|
91
99
|
|
92
|
-
Hyperloop.define_setting
|
93
|
-
|
94
|
-
def compile_and_compress(name, never_compress: false)
|
95
|
-
start_time = Time.now
|
96
|
-
|
97
|
-
puts "\n\n##########################################################################\n"
|
98
|
-
puts " HYPERLOOP LIBRARIES PRECOMPILING AND MINIFYING\n"
|
99
|
-
puts " FIRST TIME BOOTING YOUR APP IT CAN TAKE 1 OR 2 MINUTES\n"
|
100
|
-
puts " NB: You can force precompiling again by cleaning cache: rm -rf tmp/cache \n"
|
101
|
-
puts "##########################################################################\n\n"
|
102
|
-
|
103
|
-
puts "Compiling the system assets for #{name}"
|
104
|
-
|
105
|
-
compiled_code = Rails.application.assets[name].to_s
|
106
|
-
compilation_time = Time.now
|
107
|
-
compiled_code_length = compiled_code.length
|
108
|
-
puts " compiled - length: #{compiled_code_length}"
|
109
|
-
if Hyperloop.compress_system_assets && !never_compress
|
110
|
-
compiled_code = Uglifier.new.compile(compiled_code)
|
111
|
-
puts " minimized - length: #{compiled_code.length}"
|
112
|
-
puts " minification ratio #{(compiled_code.length*100.0/compiled_code_length).round}%"
|
113
|
-
end
|
114
|
-
puts " total time: #{(Time.now-start_time).to_f.round(2)} seconds"
|
115
|
-
compiled_code
|
100
|
+
Hyperloop.define_setting(:compress_system_assets, true) do
|
101
|
+
puts "INFO: The configuration option 'compress_system_assets' is no longer used."
|
116
102
|
end
|
117
|
-
|
118
103
|
end
|
119
104
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Hyperloop
|
2
|
+
class << self
|
3
|
+
def js_import(value, client_only: nil, server_only: nil, defines:)
|
4
|
+
defines = [*defines]
|
5
|
+
if RUBY_ENGINE != 'opal'
|
6
|
+
import(value, client_only: client_only, server_only: server_only, js_import: true)
|
7
|
+
else
|
8
|
+
on_server = `typeof Opal.global.document === 'undefined'`
|
9
|
+
return if (server_only && !on_server) || (client_only && on_server)
|
10
|
+
defines.each do |name|
|
11
|
+
next unless `Opal.global[#{name}] === undefined`
|
12
|
+
raise "The package #{name} was not found. Add it to the webpack "\
|
13
|
+
"#{client_only ? 'client_only.js' : 'client_and_server.js'} manifest."
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|