hyperstack-config 0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/.travis.yml +29 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +303 -0
- data/README.md +73 -0
- data/Rakefile +11 -0
- data/bin/hyperstack-hotloader +22 -0
- data/hyperstack-config.gemspec +45 -0
- data/lib/hyperstack-config.rb +45 -0
- data/lib/hyperstack-hotloader-config.js.erb +7 -0
- data/lib/hyperstack-loader-application.rb.erb +1 -0
- data/lib/hyperstack-loader-system-code.rb.erb +1 -0
- data/lib/hyperstack-loader.js +6 -0
- data/lib/hyperstack-prerender-loader-application.rb.erb +1 -0
- data/lib/hyperstack-prerender-loader-system-code.rb.erb +1 -0
- data/lib/hyperstack-prerender-loader.js +4 -0
- data/lib/hyperstack/active_support_string_inquirer.rb +32 -0
- data/lib/hyperstack/autoloader.rb +140 -0
- data/lib/hyperstack/autoloader_starter.rb +15 -0
- data/lib/hyperstack/boot.rb +41 -0
- data/lib/hyperstack/client_readers.rb +19 -0
- data/lib/hyperstack/client_stubs.rb +12 -0
- data/lib/hyperstack/config/version.rb +5 -0
- data/lib/hyperstack/config_settings.rb +49 -0
- data/lib/hyperstack/context.rb +36 -0
- data/lib/hyperstack/deprecation_warning.rb +10 -0
- data/lib/hyperstack/env.rb +10 -0
- data/lib/hyperstack/environment/development/hyperstack_env.rb +5 -0
- data/lib/hyperstack/environment/production/hyperstack_env.rb +5 -0
- data/lib/hyperstack/environment/staging/hyperstack_env.rb +5 -0
- data/lib/hyperstack/environment/test/hyperstack_env.rb +5 -0
- data/lib/hyperstack/hotloader.rb +129 -0
- data/lib/hyperstack/hotloader/add_error_boundry.rb +31 -0
- data/lib/hyperstack/hotloader/css_reloader.rb +41 -0
- data/lib/hyperstack/hotloader/server.rb +296 -0
- data/lib/hyperstack/hotloader/short_cut.js +9 -0
- data/lib/hyperstack/hotloader/socket.rb +136 -0
- data/lib/hyperstack/hotloader/stack-trace.js +2977 -0
- data/lib/hyperstack/hotloader/stub.rb +10 -0
- data/lib/hyperstack/imports.rb +104 -0
- data/lib/hyperstack/js_imports.rb +18 -0
- data/lib/hyperstack/on_client.rb +5 -0
- data/lib/hyperstack/on_error.rb +5 -0
- data/lib/hyperstack/rail_tie.rb +87 -0
- data/lib/hyperstack/string.rb +6 -0
- metadata +350 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require "hyperstack/hotloader/server"
|
5
|
+
|
6
|
+
options = {:port => 25222, :directories => []}
|
7
|
+
OptionParser.new do |opts|
|
8
|
+
opts.banner = "Usage: opal-hot-reloader [options]"
|
9
|
+
|
10
|
+
opts.on("-p", '--port [INTEGER]', Integer, 'port to run on, defaults to 25222') do |v|
|
11
|
+
options[:port] = v
|
12
|
+
end
|
13
|
+
|
14
|
+
opts.on("-d", '--directories x,y,z', Array, "comma separated directories to watch. Ex. to add 2 directories '-d app/assets/js,app/client/components'. Directoriess automatically included if they exist are:\n\t\t* app/assets/javascripts\n\t\t* app/views/components") do |v|
|
15
|
+
options[:directories] = v
|
16
|
+
end
|
17
|
+
|
18
|
+
end.parse!
|
19
|
+
|
20
|
+
server = Hyperstack::Hotloader::Server.new(options)
|
21
|
+
puts "Listening on port #{options[:port]}, watching for changes in #{options[:directories].join(', ')}"
|
22
|
+
server.loop
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'hyperstack/config/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'hyperstack-config'
|
8
|
+
spec.version = Hyperstack::Config::VERSION
|
9
|
+
spec.authors = ['Mitch VanDuyn', 'Jan Biedermann']
|
10
|
+
spec.email = ['mitch@catprint.com', 'jan@kursator.com']
|
11
|
+
spec.summary = %q{Provides a single point configuration module for hyperstack gems}
|
12
|
+
spec.homepage = 'http://ruby-hyperstack.org'
|
13
|
+
spec.license = 'MIT'
|
14
|
+
# spec.metadata = {
|
15
|
+
# "homepage_uri" => 'http://ruby-hyperstack.org',
|
16
|
+
# "source_code_uri" => 'https://github.com/ruby-hyperstack/hyper-component'
|
17
|
+
# }
|
18
|
+
|
19
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
20
|
+
#spec.bindir = 'exe'
|
21
|
+
#spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
22
|
+
spec.executables << 'hyperstack-hotloader'
|
23
|
+
spec.require_paths = ['lib']
|
24
|
+
|
25
|
+
spec.add_dependency 'libv8', '~> 6.3.0' # see https://github.com/discourse/mini_racer/issues/92
|
26
|
+
spec.add_dependency 'listen', '~> 3.0' # for hot loader
|
27
|
+
spec.add_dependency 'mini_racer', '~> 0.1.15'
|
28
|
+
spec.add_dependency 'opal', '>= 0.11.0', '< 0.12.0'
|
29
|
+
spec.add_dependency 'opal-browser', '~> 0.2.0'
|
30
|
+
spec.add_dependency 'uglifier'
|
31
|
+
spec.add_dependency 'websocket' # for hot loader
|
32
|
+
|
33
|
+
|
34
|
+
spec.add_development_dependency 'bundler', '~> 1.16.0'
|
35
|
+
spec.add_development_dependency 'chromedriver-helper'
|
36
|
+
spec.add_development_dependency 'opal-rails', '~> 0.9.4'
|
37
|
+
spec.add_development_dependency 'pry'
|
38
|
+
spec.add_development_dependency 'puma'
|
39
|
+
spec.add_development_dependency 'rails', '>= 4.0.0'
|
40
|
+
spec.add_development_dependency 'rake'
|
41
|
+
spec.add_development_dependency 'rspec', '~> 3.7.0'
|
42
|
+
spec.add_development_dependency 'rubocop', '~> 0.51.0'
|
43
|
+
spec.add_development_dependency 'sqlite3'
|
44
|
+
spec.add_development_dependency 'timecop', '~> 0.8.1'
|
45
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'hyperstack/boot'
|
2
|
+
if RUBY_ENGINE == 'opal'
|
3
|
+
require 'hyperstack/deprecation_warning'
|
4
|
+
require 'hyperstack/string'
|
5
|
+
require 'hyperstack/client_stubs'
|
6
|
+
require 'hyperstack/context'
|
7
|
+
require 'hyperstack/js_imports'
|
8
|
+
require 'hyperstack/on_client'
|
9
|
+
require 'hyperstack/active_support_string_inquirer.rb'
|
10
|
+
require 'hyperstack_env'
|
11
|
+
require 'hyperstack/hotloader/stub'
|
12
|
+
else
|
13
|
+
require 'opal'
|
14
|
+
require 'opal-browser'
|
15
|
+
# We need opal-rails to be loaded for Gem code to be properly included by sprockets.
|
16
|
+
begin
|
17
|
+
require 'opal-rails' if defined? Rails
|
18
|
+
rescue LoadError
|
19
|
+
puts "****** WARNING: To use Hyperstack with Rails you must include the 'opal-rails' gem in your gem file."
|
20
|
+
end
|
21
|
+
require 'hyperstack/config_settings'
|
22
|
+
require 'hyperstack/context'
|
23
|
+
require 'hyperstack/imports'
|
24
|
+
require 'hyperstack/js_imports'
|
25
|
+
require 'hyperstack/client_readers'
|
26
|
+
require 'hyperstack/on_client'
|
27
|
+
|
28
|
+
if defined? Rails
|
29
|
+
require 'hyperstack/rail_tie'
|
30
|
+
end
|
31
|
+
require 'hyperstack/active_support_string_inquirer.rb' unless defined? ActiveSupport
|
32
|
+
require 'hyperstack/env'
|
33
|
+
require 'hyperstack/on_error'
|
34
|
+
Hyperstack.define_setting :hotloader_port, 25222
|
35
|
+
Hyperstack.define_setting :hotloader_ping, nil
|
36
|
+
Hyperstack.import 'opal', gem: true
|
37
|
+
Hyperstack.import 'browser', client_only: true
|
38
|
+
Hyperstack.import 'hyperstack-config', gem: true
|
39
|
+
Hyperstack.import 'hyperstack/autoloader'
|
40
|
+
Hyperstack.import 'hyperstack/autoloader_starter'
|
41
|
+
# based on the environment pick the directory containing the file with the matching
|
42
|
+
# value for the client. This avoids use of ERB for builds outside of sprockets environment
|
43
|
+
Opal.append_path(File.expand_path("../hyperstack/environment/#{Hyperstack.env}/", __FILE__).untaint)
|
44
|
+
Opal.append_path(File.expand_path('../', __FILE__).untaint)
|
45
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
console.log('hotloader config doing its thing')
|
2
|
+
if ((typeof(window) !== 'undefined') && (window.Hyperstack==undefined || window.Hyperstack.hotloader==undefined)) {
|
3
|
+
window.Hyperstack = { hotloader: function(port, ping) { }}
|
4
|
+
}
|
5
|
+
//if (typeof(Hyperstack) === 'undefined') { Hyperstack = {} }
|
6
|
+
Hyperstack.hotloader.port = <%= Hyperstack.hotloader_port %>
|
7
|
+
Hyperstack.hotloader.ping = <%= !!Hyperstack.hotloader_ping %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= Hyperstack.generate_requires(:client, false, __FILE__) %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= Hyperstack.generate_requires(:client, true, __FILE__) %>
|
@@ -0,0 +1,6 @@
|
|
1
|
+
//= require hyperstack-loader-system-code
|
2
|
+
//= require hyperstack-loader-application
|
3
|
+
//= require hyperstack-hotloader-config
|
4
|
+
Opal.load('hyperstack-loader-system-code')
|
5
|
+
Opal.load('hyperstack-loader-application')
|
6
|
+
Hyperstack.hotloader(Hyperstack.hotloader.port, Hyperstack.hotloader.ping)
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= Hyperstack.generate_requires(:server, false, __FILE__) %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= Hyperstack.generate_requires(:server, true, __FILE__) %>
|
@@ -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,140 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module Hyperstack
|
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
|
+
rescue Exception => e
|
43
|
+
puts "HyperStack autoloader failed attempting to load #{mod}::#{const_name}. Could be a bug in autoloader"
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.guess_for_anonymous(const_name)
|
47
|
+
if Object.const_defined?(const_name)
|
48
|
+
raise NameError.new "#{const_name} cannot be autoloaded from an anonymous class or module", const_name
|
49
|
+
else
|
50
|
+
Object
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.load_missing_constant(from_mod, const_name)
|
55
|
+
# see active_support/dependencies.rb in case of reloading on how to handle
|
56
|
+
qualified_name = qualified_name_for(from_mod, const_name)
|
57
|
+
qualified_path = underscore(qualified_name)
|
58
|
+
|
59
|
+
module_path = search_for_module(qualified_path)
|
60
|
+
if module_path
|
61
|
+
if loading.include?(module_path)
|
62
|
+
raise "Circular dependency detected while autoloading constant #{qualified_name}"
|
63
|
+
else
|
64
|
+
require_or_load(from_mod, module_path)
|
65
|
+
raise LoadError, "Unable to autoload constant #{qualified_name}, expected #{module_path} to define it" unless from_mod.const_defined?(const_name, false)
|
66
|
+
return from_mod.const_get(const_name)
|
67
|
+
end
|
68
|
+
elsif from_mod.respond_to?(:parent) && (parent = from_mod.parent) && parent != from_mod &&
|
69
|
+
! from_mod.parents.any? { |p| p.const_defined?(const_name, false) }
|
70
|
+
begin
|
71
|
+
return parent.const_missing(const_name)
|
72
|
+
rescue NameError => e
|
73
|
+
raise unless missing_name?(e, qualified_name_for(parent, const_name))
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.missing_name?(e, name)
|
79
|
+
mn = if /undefined/ !~ e.message
|
80
|
+
$1 if /((::)?([A-Z]\w*)(::[A-Z]\w*)*)$/ =~ e.message
|
81
|
+
end
|
82
|
+
mn == name
|
83
|
+
end
|
84
|
+
|
85
|
+
# Returns the constant path for the provided parent and constant name.
|
86
|
+
def self.qualified_name_for(mod, name)
|
87
|
+
mod_name = to_constant_name(mod)
|
88
|
+
mod_name == 'Object' ? name.to_s : "#{mod_name}::#{name}"
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.require_or_load(from_mod, module_path)
|
92
|
+
return if loaded.include?(module_path)
|
93
|
+
loaded << module_path
|
94
|
+
loading << module_path
|
95
|
+
|
96
|
+
begin
|
97
|
+
result = require module_path
|
98
|
+
rescue Exception
|
99
|
+
loaded.delete module_path
|
100
|
+
raise LoadError, "Unable to autoload: require_or_load #{module_path} failed"
|
101
|
+
ensure
|
102
|
+
loading.pop
|
103
|
+
end
|
104
|
+
|
105
|
+
# Record history *after* loading so first load gets warnings.
|
106
|
+
history << module_path
|
107
|
+
result
|
108
|
+
# end
|
109
|
+
end
|
110
|
+
|
111
|
+
def self.search_for_module(path)
|
112
|
+
# oh my! imagine Bart Simpson, writing on the board:
|
113
|
+
# "javascript is not ruby, javascript is not ruby, javascript is not ruby, ..."
|
114
|
+
# then running home, starting irb, on the fly developing a chat client and opening a session with Homer at his workplace: "Hi Dad ..."
|
115
|
+
load_paths.each do |load_path|
|
116
|
+
mod_path = load_path + '/' + path
|
117
|
+
return mod_path if `Opal.modules.hasOwnProperty(#{mod_path})`
|
118
|
+
end
|
119
|
+
return path if `Opal.modules.hasOwnProperty(#{path})`
|
120
|
+
nil # Gee, I sure wish we had first_match ;-)
|
121
|
+
end
|
122
|
+
|
123
|
+
# Convert the provided const desc to a qualified constant name (as a string).
|
124
|
+
# A module, class, symbol, or string may be provided.
|
125
|
+
def self.to_constant_name(desc) #:nodoc:
|
126
|
+
case desc
|
127
|
+
when String then desc.sub(/^::/, '')
|
128
|
+
when Symbol then desc.to_s
|
129
|
+
when Module
|
130
|
+
desc.name ||
|
131
|
+
raise(ArgumentError, 'Anonymous modules have no name to be referenced by')
|
132
|
+
else raise TypeError, "Not a valid constant descriptor: #{desc.inspect}"
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def self.underscore(string)
|
137
|
+
string.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').gsub(/([a-z\d])([A-Z])/,'\1_\2').tr("-", "_").downcase
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
Hyperstack::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
|
+
Hyperstack::Autoloader.const_missing(const_name, self) || raise(e)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# Define a primitive Boot Operation that will act like a full blown operation.
|
2
|
+
# If Operation is defined before this then we skip the whole exercise. Likewise
|
3
|
+
# when Operation defines the Boot class, it will check for a receivers method and
|
4
|
+
# copy any defined receivers into the updated Boot class.
|
5
|
+
|
6
|
+
module Hyperstack
|
7
|
+
unless defined? Operation
|
8
|
+
class Operation
|
9
|
+
end
|
10
|
+
class Application
|
11
|
+
class Boot < Operation
|
12
|
+
class ReactDummyParams
|
13
|
+
# behaves simplistically like a true Operation broadcast Params object with a
|
14
|
+
# single param named context.
|
15
|
+
attr_reader :context
|
16
|
+
def initialize(context)
|
17
|
+
@context = context
|
18
|
+
end
|
19
|
+
end
|
20
|
+
class << self
|
21
|
+
def on_dispatch(&block)
|
22
|
+
receivers << block
|
23
|
+
end
|
24
|
+
|
25
|
+
def receivers
|
26
|
+
# use the force: true option so that system code needing to receive
|
27
|
+
# boot will NOT be erased on the next Hyperloop::Context.reset!
|
28
|
+
Hyperstack::Context.set_var(self, :@receivers, force: true) { [] }
|
29
|
+
end
|
30
|
+
|
31
|
+
def run(context: nil)
|
32
|
+
params = ReactDummyParams.new(context)
|
33
|
+
receivers.each do |receiver|
|
34
|
+
receiver.call params
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Hyperstack
|
2
|
+
# configuration utility
|
3
|
+
class << self
|
4
|
+
def client_readers
|
5
|
+
@client_readers ||= []
|
6
|
+
end
|
7
|
+
|
8
|
+
def client_reader_hash
|
9
|
+
@client_readers_hash ||= {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def client_reader(*args)
|
13
|
+
# configuration.client_reader[:foo] = 12 initialize your own client value
|
14
|
+
# configuration.client_reader :foo, :bar make previous setting readable on client
|
15
|
+
client_readers += [*args]
|
16
|
+
client_reader_hash
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Hyperstack
|
2
|
+
# configuration utility
|
3
|
+
class << self
|
4
|
+
def initialized_blocks
|
5
|
+
@initialized_blocks ||= []
|
6
|
+
end
|
7
|
+
|
8
|
+
def reset_blocks
|
9
|
+
@reset_blocks ||= []
|
10
|
+
end
|
11
|
+
|
12
|
+
def configuration
|
13
|
+
reset_blocks.each(&:call)
|
14
|
+
yield self
|
15
|
+
initialized_blocks.each(&:call)
|
16
|
+
end
|
17
|
+
|
18
|
+
def define_setting(name, default = nil, &block)
|
19
|
+
class_variable_set("@@#{name}", default)
|
20
|
+
|
21
|
+
define_class_method "#{name}=" do |value|
|
22
|
+
class_variable_set("@@#{name}", value)
|
23
|
+
block.call value if block
|
24
|
+
value
|
25
|
+
end
|
26
|
+
|
27
|
+
define_class_method name do
|
28
|
+
class_variable_get("@@#{name}")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
def on_config_reset &block
|
34
|
+
reset_blocks << block
|
35
|
+
end
|
36
|
+
|
37
|
+
def on_config_initialized &block
|
38
|
+
initialized_blocks << block
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def define_class_method(name, &block)
|
44
|
+
(class << self; self; end).instance_eval do
|
45
|
+
define_method name, &block
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|