hyperstack-config 0.1

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.
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