hyperstack-config 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.travis.yml +29 -0
  4. data/Gemfile +3 -0
  5. data/Gemfile.lock +303 -0
  6. data/README.md +73 -0
  7. data/Rakefile +11 -0
  8. data/bin/hyperstack-hotloader +22 -0
  9. data/hyperstack-config.gemspec +45 -0
  10. data/lib/hyperstack-config.rb +45 -0
  11. data/lib/hyperstack-hotloader-config.js.erb +7 -0
  12. data/lib/hyperstack-loader-application.rb.erb +1 -0
  13. data/lib/hyperstack-loader-system-code.rb.erb +1 -0
  14. data/lib/hyperstack-loader.js +6 -0
  15. data/lib/hyperstack-prerender-loader-application.rb.erb +1 -0
  16. data/lib/hyperstack-prerender-loader-system-code.rb.erb +1 -0
  17. data/lib/hyperstack-prerender-loader.js +4 -0
  18. data/lib/hyperstack/active_support_string_inquirer.rb +32 -0
  19. data/lib/hyperstack/autoloader.rb +140 -0
  20. data/lib/hyperstack/autoloader_starter.rb +15 -0
  21. data/lib/hyperstack/boot.rb +41 -0
  22. data/lib/hyperstack/client_readers.rb +19 -0
  23. data/lib/hyperstack/client_stubs.rb +12 -0
  24. data/lib/hyperstack/config/version.rb +5 -0
  25. data/lib/hyperstack/config_settings.rb +49 -0
  26. data/lib/hyperstack/context.rb +36 -0
  27. data/lib/hyperstack/deprecation_warning.rb +10 -0
  28. data/lib/hyperstack/env.rb +10 -0
  29. data/lib/hyperstack/environment/development/hyperstack_env.rb +5 -0
  30. data/lib/hyperstack/environment/production/hyperstack_env.rb +5 -0
  31. data/lib/hyperstack/environment/staging/hyperstack_env.rb +5 -0
  32. data/lib/hyperstack/environment/test/hyperstack_env.rb +5 -0
  33. data/lib/hyperstack/hotloader.rb +129 -0
  34. data/lib/hyperstack/hotloader/add_error_boundry.rb +31 -0
  35. data/lib/hyperstack/hotloader/css_reloader.rb +41 -0
  36. data/lib/hyperstack/hotloader/server.rb +296 -0
  37. data/lib/hyperstack/hotloader/short_cut.js +9 -0
  38. data/lib/hyperstack/hotloader/socket.rb +136 -0
  39. data/lib/hyperstack/hotloader/stack-trace.js +2977 -0
  40. data/lib/hyperstack/hotloader/stub.rb +10 -0
  41. data/lib/hyperstack/imports.rb +104 -0
  42. data/lib/hyperstack/js_imports.rb +18 -0
  43. data/lib/hyperstack/on_client.rb +5 -0
  44. data/lib/hyperstack/on_error.rb +5 -0
  45. data/lib/hyperstack/rail_tie.rb +87 -0
  46. data/lib/hyperstack/string.rb +6 -0
  47. 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,4 @@
1
+ //= require hyperstack-prerender-loader-system-code
2
+ //= require hyperstack-prerender-loader-application
3
+ Opal.load('hyperstack-prerender-loader-system-code')
4
+ Opal.load('hyperstack-prerender-loader-application')
@@ -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,12 @@
1
+ module Hyperstack
2
+ class << self
3
+ def import(*args)
4
+ end
5
+
6
+ def imports(*args)
7
+ end
8
+
9
+ def import_tree(*args)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,5 @@
1
+ module Hyperstack
2
+ module Config
3
+ VERSION = '0.1'
4
+ end
5
+ 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