react_on_rails 2.0.0.beta.1 → 2.0.0.beta.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/.coveralls.yml +1 -0
  3. data/.dockerignore +2 -0
  4. data/.eslintignore +7 -0
  5. data/.eslintrc +19 -0
  6. data/.gitignore +28 -0
  7. data/.jscsrc +27 -0
  8. data/.npmignore +20 -0
  9. data/.rspec +2 -0
  10. data/.rubocop.yml +70 -0
  11. data/.scss-lint.yml +205 -0
  12. data/.travis.yml +43 -0
  13. data/CHANGELOG.md +34 -0
  14. data/Dockerfile_tests +12 -0
  15. data/Gemfile +40 -0
  16. data/README.md +365 -0
  17. data/Rakefile +5 -0
  18. data/app/helpers/react_on_rails_helper.rb +215 -0
  19. data/docker-compose.yml +11 -0
  20. data/docs/LICENSE +21 -0
  21. data/docs/additional_reading/heroku_deployment.md +23 -0
  22. data/docs/additional_reading/manual_installation.md +118 -0
  23. data/docs/additional_reading/node_dependencies_and_npm.md +29 -0
  24. data/docs/additional_reading/optional_configuration.md +33 -0
  25. data/docs/additional_reading/react-and-redux.md +36 -0
  26. data/docs/additional_reading/react_router.md +45 -0
  27. data/docs/additional_reading/server_rendering_tips.md +11 -0
  28. data/docs/additional_reading/tips.md +10 -0
  29. data/docs/additional_reading/webpack.md +46 -0
  30. data/docs/code_of_conduct.md +13 -0
  31. data/docs/coding-style/linters.md +64 -0
  32. data/docs/coding-style/style.md +42 -0
  33. data/docs/contributing.md +157 -0
  34. data/docs/generator_testing.md +20 -0
  35. data/docs/releasing.md +29 -0
  36. data/lib/generators/USAGE +99 -0
  37. data/lib/generators/react_on_rails/base_generator.rb +191 -0
  38. data/lib/generators/react_on_rails/bootstrap_generator.rb +89 -0
  39. data/lib/generators/react_on_rails/dev_tests_generator.rb +39 -0
  40. data/lib/generators/react_on_rails/generator_helper.rb +50 -0
  41. data/lib/generators/react_on_rails/heroku_deployment_generator.rb +30 -0
  42. data/lib/generators/react_on_rails/install_generator.rb +99 -0
  43. data/lib/generators/react_on_rails/js_linters_generator.rb +19 -0
  44. data/lib/generators/react_on_rails/react_no_redux_generator.rb +40 -0
  45. data/lib/generators/react_on_rails/react_with_redux_generator.rb +51 -0
  46. data/lib/generators/react_on_rails/ruby_linters_generator.rb +33 -0
  47. data/lib/generators/react_on_rails/templates/base/base/Procfile.dev.tt +4 -0
  48. data/lib/generators/react_on_rails/templates/base/base/REACT_ON_RAILS.md +16 -0
  49. data/lib/generators/react_on_rails/templates/base/base/app/controllers/hello_world_controller.rb +5 -0
  50. data/lib/generators/react_on_rails/templates/base/base/app/views/hello_world/index.html.erb.tt +4 -0
  51. data/lib/generators/react_on_rails/templates/base/base/client/.babelrc +3 -0
  52. data/lib/generators/react_on_rails/templates/base/base/client/REACT_ON_RAILS_CLIENT_README.md +3 -0
  53. data/lib/generators/react_on_rails/templates/base/base/client/app/bundles/HelloWorld/startup/clientRegistration.jsx.tt +5 -0
  54. data/lib/generators/react_on_rails/templates/base/base/client/index.jade +15 -0
  55. data/lib/generators/react_on_rails/templates/base/base/client/package.json.tt +104 -0
  56. data/lib/generators/react_on_rails/templates/base/base/client/server.js +64 -0
  57. data/lib/generators/react_on_rails/templates/base/base/client/webpack.client.base.config.js.tt +62 -0
  58. data/lib/generators/react_on_rails/templates/base/base/client/webpack.client.hot.config.js.tt +69 -0
  59. data/lib/generators/react_on_rails/templates/base/base/client/webpack.client.rails.config.js +42 -0
  60. data/lib/generators/react_on_rails/templates/base/base/config/initializers/react_on_rails.rb +26 -0
  61. data/lib/generators/react_on_rails/templates/base/base/lib/tasks/assets.rake.tt +26 -0
  62. data/lib/generators/react_on_rails/templates/base/base/lib/tasks/linters.rake.tt +88 -0
  63. data/lib/generators/react_on_rails/templates/base/base/package.json +31 -0
  64. data/lib/generators/react_on_rails/templates/base/server_rendering/client/app/bundles/HelloWorld/startup/serverRegistration.jsx +4 -0
  65. data/lib/generators/react_on_rails/templates/base/server_rendering/client/webpack.server.rails.config.js +39 -0
  66. data/lib/generators/react_on_rails/templates/bootstrap/app/assets/stylesheets/_bootstrap-custom.scss +63 -0
  67. data/lib/generators/react_on_rails/templates/bootstrap/client/assets/stylesheets/_post-bootstrap.scss +10 -0
  68. data/lib/generators/react_on_rails/templates/bootstrap/client/assets/stylesheets/_pre-bootstrap.scss +8 -0
  69. data/lib/generators/react_on_rails/templates/bootstrap/client/assets/stylesheets/_react-on-rails-sass-helper.scss +19 -0
  70. data/lib/generators/react_on_rails/templates/bootstrap/client/bootstrap-sass.config.js +89 -0
  71. data/lib/generators/react_on_rails/templates/dev_tests/.rspec +2 -0
  72. data/lib/generators/react_on_rails/templates/dev_tests/spec/features/hello_world_spec.rb +25 -0
  73. data/lib/generators/react_on_rails/templates/dev_tests/spec/rails_helper.rb +57 -0
  74. data/lib/generators/react_on_rails/templates/dev_tests/spec/simplecov_helper.rb +21 -0
  75. data/lib/generators/react_on_rails/templates/dev_tests/spec/spec_helper.rb +95 -0
  76. data/lib/generators/react_on_rails/templates/heroku_deployment/.buildpacks +2 -0
  77. data/lib/generators/react_on_rails/templates/heroku_deployment/Procfile +1 -0
  78. data/lib/generators/react_on_rails/templates/heroku_deployment/config/puma.rb +15 -0
  79. data/lib/generators/react_on_rails/templates/js_linters/client/.eslintignore +1 -0
  80. data/lib/generators/react_on_rails/templates/js_linters/client/.eslintrc +48 -0
  81. data/lib/generators/react_on_rails/templates/js_linters/client/.jscsrc +18 -0
  82. data/lib/generators/react_on_rails/templates/no_redux/base/client/app/bundles/HelloWorld/components/HelloWorldWidget.jsx +39 -0
  83. data/lib/generators/react_on_rails/templates/no_redux/base/client/app/bundles/HelloWorld/containers/HelloWorld.jsx +33 -0
  84. data/lib/generators/react_on_rails/templates/no_redux/base/client/app/bundles/HelloWorld/startup/HelloWorldAppClient.jsx.tt +8 -0
  85. data/lib/generators/react_on_rails/templates/no_redux/server_rendering/client/app/bundles/HelloWorld/startup/HelloWorldAppServer.jsx +8 -0
  86. data/lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/actions/helloWorldActionCreators.jsx +8 -0
  87. data/lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/components/HelloWorldWidget.jsx +48 -0
  88. data/lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/constants/helloWorldConstants.jsx +8 -0
  89. data/lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/containers/HelloWorld.jsx +43 -0
  90. data/lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/reducers/helloWorldReducer.jsx +19 -0
  91. data/lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/reducers/index.jsx +14 -0
  92. data/lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/startup/HelloWorldAppClient.jsx.tt +19 -0
  93. data/lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/store/helloWorldStore.jsx +35 -0
  94. data/lib/generators/react_on_rails/templates/redux/base/client/app/lib/middlewares/loggerMiddleware.js +20 -0
  95. data/lib/generators/react_on_rails/templates/redux/server_rendering/client/app/bundles/HelloWorld/startup/HelloWorldAppServer.jsx +19 -0
  96. data/lib/generators/react_on_rails/templates/ruby_linters/.rubocop.yml +26 -0
  97. data/lib/generators/react_on_rails/templates/ruby_linters/.scss-lint.yml +205 -0
  98. data/lib/generators/react_on_rails/templates/ruby_linters/lib/tasks/brakeman.rake +17 -0
  99. data/lib/generators/react_on_rails/templates/ruby_linters/lib/tasks/ci.rake +33 -0
  100. data/lib/generators/react_on_rails/templates/ruby_linters/ruby-lint.yml +20 -0
  101. data/lib/react_on_rails.rb +6 -0
  102. data/lib/react_on_rails/configuration.rb +60 -0
  103. data/lib/react_on_rails/engine.rb +7 -0
  104. data/lib/react_on_rails/prerender_error.rb +31 -0
  105. data/lib/react_on_rails/server_rendering_pool.rb +110 -0
  106. data/lib/react_on_rails/version.rb +3 -0
  107. data/package.json +76 -0
  108. data/rakelib/docker.rake +33 -0
  109. data/rakelib/dummy_apps.rake +20 -0
  110. data/rakelib/example_type.rb +160 -0
  111. data/rakelib/examples.rake +103 -0
  112. data/rakelib/examples_config.yml +19 -0
  113. data/rakelib/lint.rake +37 -0
  114. data/rakelib/node_package.rake +11 -0
  115. data/rakelib/run_rspec.rake +65 -0
  116. data/rakelib/task_helpers.rb +44 -0
  117. data/react_on_rails.gemspec +31 -0
  118. data/ruby-lint.yml +24 -0
  119. metadata +119 -2
@@ -0,0 +1,17 @@
1
+ namespace :brakeman do
2
+
3
+ desc "Run Brakeman"
4
+ task :run, :output_files do |t, args|
5
+ require 'brakeman'
6
+
7
+ files = args[:output_files].split(' ') if args[:output_files]
8
+ Brakeman.run :app_path => ".", :output_files => files, :print_report => true
9
+ end
10
+
11
+ desc "Check your code with Brakeman"
12
+ task :check do
13
+ require 'brakeman'
14
+ result = Brakeman.run app_path: '.', print_report: true
15
+ exit Brakeman::Warnings_Found_Exit_Code unless result.filtered_warnings.empty?
16
+ end
17
+ end
@@ -0,0 +1,33 @@
1
+ if Rails.env.development?
2
+ # See tasks/linters.rake
3
+
4
+ task :bundle_audit do
5
+ puts Rainbow("Running security audit on gems (bundle_audit)").green
6
+ Rake::Task["bundle_audit"].invoke
7
+ end
8
+
9
+ task :security_audit do
10
+ puts Rainbow("Running security audit on code (brakeman)").green
11
+
12
+ sh "brakeman --exit-on-warn --quiet -A -z"
13
+ end
14
+
15
+ namespace :ci do
16
+ desc "Run all audits and tests"
17
+ task all: [:environment, :lint, :spec, :bundle_audit, :security_audit] do
18
+ begin
19
+ puts Rainbow("PASSED").green
20
+ puts ""
21
+ rescue Exception => e
22
+ puts "#{e}"
23
+ puts Rainbow("FAILED").red
24
+ puts ""
25
+ raise(e)
26
+ end
27
+ end
28
+ end
29
+
30
+ task ci: "ci:all"
31
+
32
+ task(:default).clear.enhance([:ci])
33
+ end
@@ -0,0 +1,20 @@
1
+ presenter: syntastic
2
+
3
+ directories:
4
+ - app
5
+ - config
6
+ - spec
7
+
8
+ ignore_paths:
9
+ - client
10
+ - node_modules
11
+
12
+ analysis_classes:
13
+ # - argument_amount
14
+ - pedantics
15
+ - shadowing_variables
16
+ # Too many false positives for these
17
+ # - undefined_methods
18
+ # - undefined_variables
19
+ # - unused_variables
20
+ - useless_equality_checks
@@ -0,0 +1,6 @@
1
+ require "rails"
2
+
3
+ require "react_on_rails/version"
4
+ require "react_on_rails/configuration"
5
+ require "react_on_rails/server_rendering_pool"
6
+ require "react_on_rails/engine"
@@ -0,0 +1,60 @@
1
+ module ReactOnRails
2
+ def self.configure
3
+ yield(configuration)
4
+ end
5
+
6
+ # TODO ROB
7
+ # parse the client/package.json and ensure that either:
8
+ # 1. version number matches
9
+ # 2. version number is a relative path (for testing)
10
+ # Throw error if not.
11
+ # Allow skipping this check in the configuration in case somebody has a wacky configuration, such
12
+ # as you don't know where their package.json
13
+
14
+ def self.configuration
15
+ @configuration ||= Configuration.new(
16
+ server_bundle_js_file: "app/assets/javascripts/generated/server.js",
17
+ prerender: false,
18
+ replay_console: true,
19
+ logging_on_server: true,
20
+ raise_on_prerender_error: false,
21
+ trace: Rails.env.development?,
22
+ development_mode: Rails.env.development?,
23
+ server_renderer_pool_size: 1,
24
+ server_renderer_timeout: 20)
25
+ # TODO ROB: do the version check
26
+ end
27
+
28
+ class Configuration
29
+ attr_accessor :server_bundle_js_file, :prerender, :replay_console,
30
+ :trace, :development_mode,
31
+ :logging_on_server, :server_renderer_pool_size,
32
+ :server_renderer_timeout, :raise_on_prerender_error
33
+
34
+ def initialize(server_bundle_js_file: nil, prerender: nil, replay_console: nil,
35
+ trace: nil, development_mode: nil,
36
+ logging_on_server: nil, server_renderer_pool_size: nil,
37
+ server_renderer_timeout: nil, raise_on_prerender_error: nil)
38
+ if File.exist?(server_bundle_js_file)
39
+ self.server_bundle_js_file = server_bundle_js_file
40
+ else
41
+ self.server_bundle_js_file = nil
42
+ end
43
+
44
+ self.prerender = prerender
45
+ self.replay_console = replay_console
46
+ self.logging_on_server = logging_on_server
47
+ if development_mode.nil?
48
+ self.development_mode = Rails.env.development?
49
+ else
50
+ self.development_mode = development_mode
51
+ end
52
+ self.trace = trace.nil? ? Rails.env.development? : trace
53
+ self.raise_on_prerender_error = raise_on_prerender_error
54
+
55
+ # Server rendering:
56
+ self.server_renderer_pool_size = self.development_mode ? 1 : server_renderer_pool_size
57
+ self.server_renderer_timeout = server_renderer_timeout # seconds
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,7 @@
1
+ module ReactOnRails
2
+ class Engine < ::Rails::Engine
3
+ config.to_prepare do
4
+ ReactOnRails::ServerRenderingPool.reset_pool
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,31 @@
1
+ module ReactOnRails
2
+ class PrerenderError < RuntimeError
3
+ # err might be nil if JS caught the error
4
+ def initialize(component_name: nil, err: nil, props: nil,
5
+ js_code: nil, console_messages: nil)
6
+ message = "ERROR in SERVER PRERENDERING\n"
7
+ if err
8
+ message << <<-MSG
9
+ Encountered error: \"#{err}\"
10
+ MSG
11
+ backtrace = err.backtrace.join("\n")
12
+ else
13
+ backtrace = nil
14
+ end
15
+ message << <<-MSG
16
+ when prerendering #{component_name} with props: #{props}
17
+ js_code was:
18
+ #{js_code}
19
+ MSG
20
+
21
+ if console_messages
22
+ message << <<-MSG
23
+ console messages:
24
+ #{console_messages}
25
+ MSG
26
+ end
27
+
28
+ super([message, backtrace].compact.join("\n"))
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,110 @@
1
+ require "connection_pool"
2
+
3
+ # Based on the react-rails gem.
4
+ # None of these methods should be called directly.
5
+ # See app/helpers/react_on_rails_helper.rb
6
+ module ReactOnRails
7
+ class ServerRenderingPool
8
+ def self.reset_pool
9
+ options = { size: ReactOnRails.configuration.server_renderer_pool_size,
10
+ timeout: ReactOnRails.configuration.server_renderer_pool_size }
11
+ @js_context_pool = ConnectionPool.new(options) { create_js_context }
12
+ end
13
+
14
+ def self.reset_pool_if_server_bundle_was_modified
15
+ return unless ReactOnRails.configuration.development_mode
16
+ file_mtime = File.mtime(ReactOnRails.configuration.server_bundle_js_file)
17
+ @server_bundle_timestamp ||= file_mtime
18
+ return if @server_bundle_timestamp == file_mtime
19
+ ReactOnRails::ServerRenderingPool.reset_pool
20
+ @server_bundle_timestamp = file_mtime
21
+ end
22
+
23
+ # js_code: JavaScript expression that returns a string.
24
+ # Returns a Hash:
25
+ # html: string of HTML for direct insertion on the page by evaluating js_code
26
+ # consoleReplayScript: script for replaying console
27
+ # hasErrors: true if server rendering errors
28
+ # Note, js_code does not have to be based on React.
29
+ # js_code MUST RETURN json stringify Object
30
+ # Calling code will probably call 'html_safe' on return value before rendering to the view.
31
+ def self.server_render_js_with_console_logging(js_code)
32
+ trace_messsage(js_code)
33
+ json_string = eval_js(js_code)
34
+ result = JSON.parse(json_string)
35
+
36
+ if ReactOnRails.configuration.logging_on_server
37
+ console_script = result["consoleReplayScript"]
38
+ console_script_lines = console_script.split("\n")
39
+ console_script_lines = console_script_lines[2..-2]
40
+ re = /console\.log\.apply\(console, \["\[SERVER\] (?<msg>.*)"\]\);/
41
+ if console_script_lines
42
+ console_script_lines.each do |line|
43
+ match = re.match(line)
44
+ Rails.logger.info { "[react_on_rails] #{match[:msg]}" } if match
45
+ end
46
+ end
47
+ end
48
+ result
49
+ end
50
+
51
+ class << self
52
+ private
53
+
54
+ def trace_messsage(js_code)
55
+ return unless ENV["TRACE_REACT_ON_RAILS"].present?
56
+ # Set to anything to print generated code.
57
+ puts "Z" * 80
58
+ puts "react_renderer.rb: 92"
59
+ puts "wrote file tmp/server-generated.js"
60
+ File.write("tmp/server-generated.js", js_code)
61
+ puts "Z" * 80
62
+ end
63
+
64
+ def eval_js(js_code)
65
+ @js_context_pool.with do |js_context|
66
+ result = js_context.eval(js_code)
67
+ js_context.eval("console.history = []")
68
+ result
69
+ end
70
+ end
71
+
72
+ def create_js_context
73
+ server_js_file = ReactOnRails.configuration.server_bundle_js_file
74
+ if server_js_file.present? && File.exist?(server_js_file)
75
+ bundle_js_code = File.read(server_js_file)
76
+ base_js_code = <<-JS
77
+ #{console_polyfill}
78
+ #{bundle_js_code};
79
+ JS
80
+ ExecJS.compile(base_js_code)
81
+ else
82
+ if server_js_file.present?
83
+ msg = "You specified server rendering JS file: #{server_js_file}, but it cannot be "\
84
+ "read. You may set the server_bundle_js_file in your configuration to be \"\" to "\
85
+ "avoid this warning"
86
+ Rails.logger.warn msg
87
+ puts msg
88
+ end
89
+ ExecJS.compile("")
90
+ end
91
+ end
92
+
93
+ # Reimplement console methods for replaying on the client
94
+ def console_polyfill
95
+ <<-JS
96
+ var console = { history: [] };
97
+ ['error', 'log', 'info', 'warn'].forEach(function (level) {
98
+ console[level] = function () {
99
+ var argArray = Array.prototype.slice.call(arguments);
100
+ if (argArray.length > 0) {
101
+ argArray[0] = '[SERVER] ' + argArray[0];
102
+ }
103
+ console.history.push({level: level, arguments: argArray});
104
+ };
105
+ });
106
+ JS
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,3 @@
1
+ module ReactOnRails
2
+ VERSION = "2.0.0.beta.2"
3
+ end
@@ -0,0 +1,76 @@
1
+ {
2
+ "name": "react-on-rails",
3
+ "version": "2.0.0-beta.1",
4
+ "description": "react-on-rails JavaScript for react_on_rails Ruby gem",
5
+ "main": "node_package/lib/ReactOnRails.js",
6
+ "directories": {
7
+ "doc": "docs"
8
+ },
9
+ "dependencies": {},
10
+ "devDependencies": {
11
+ "babel": "^6.3.13",
12
+ "babel-cli": "^6.3.17",
13
+ "babel-core": "^6.3.17",
14
+ "babel-eslint": "^5.0.0-beta4",
15
+ "babel-loader": "^6.2.0",
16
+ "babel-plugin-transform-runtime": "^6.3.13",
17
+ "babel-preset-es2015": "^6.3.13",
18
+ "babel-preset-react": "^6.3.13",
19
+ "babel-preset-stage-0": "^6.3.13",
20
+ "babel-runtime": "^6.3.13",
21
+ "babel-tape-runner": "^2.0.0",
22
+ "babelify": "^7.2.0",
23
+ "blue-tape": "^0.1.11",
24
+ "eslint": "^1.10.3",
25
+ "eslint-config-airbnb": "^2.0.0",
26
+ "eslint-plugin-babel": "^3.0.0",
27
+ "eslint-plugin-react": "^3.11.3",
28
+ "jscs": "^2.6.0",
29
+ "react": "^0.14.3",
30
+ "react-dom": "^0.14.3",
31
+ "tap-spec": "^4.1.1",
32
+ "tape": "^4.4.0",
33
+ "webpack": "^1.12.9"
34
+ },
35
+ "peerDependencies": {
36
+ "react": ">= 0.14",
37
+ "react-dom": ">= 0.14"
38
+ },
39
+ "files": [
40
+ "node_package/lib"
41
+ ],
42
+ "scripts": {
43
+ "test": "node_package/scripts/test",
44
+ "clean": "node_package/scripts/clean",
45
+ "prepublish": "npm run build",
46
+ "build": "node_package/scripts/build",
47
+ "lint": "node_package/scripts/lint && cd spec/dummy/client && npm run lint",
48
+ "lint:fix": "node_package/scripts/lint-fix",
49
+ "check": "npm run lint && npm run test",
50
+ "prerelease": "npm run check && npm run clean && npm run build",
51
+ "release:patch": "node_package/scripts/release patch",
52
+ "release:minor": "node_package/scripts/release minor",
53
+ "release:major": "node_package/scripts/release major",
54
+ "dummy:install": "rake dummy_apps",
55
+ "dummy:spec": "rake run_rspec:dummy",
56
+ "local": "echo 'Be sure to run npm run dummy:install' && npm run build && cd spec/dummy && foreman start"
57
+ },
58
+ "repository": {
59
+ "type": "git",
60
+ "url": "git+https://github.com/shakacode/react_on_rails.git"
61
+ },
62
+ "keywords": [
63
+ "react",
64
+ "webpack",
65
+ "JavaScript",
66
+ "Ruby",
67
+ "on",
68
+ "Rails"
69
+ ],
70
+ "author": "justin.gordon@gmail.com",
71
+ "license": "MIT",
72
+ "bugs": {
73
+ "url": "https://github.com/shakacode/react_on_rails/issues"
74
+ },
75
+ "homepage": "https://github.com/shakacode/react_on_rails#readme"
76
+ }
@@ -0,0 +1,33 @@
1
+ namespace :docker do
2
+ desc "Run Rubocop linter from docker"
3
+ task :rubocop do
4
+ sh "docker-compose run lint rake lint:rubocop"
5
+ end
6
+
7
+ desc "Run ruby-lint linter from docker"
8
+ task :ruby do
9
+ sh "docker-compose run lint rake lint:ruby"
10
+ end
11
+
12
+ desc "Run scss-lint linter from docker"
13
+ task :scss do
14
+ sh "docker-compose run lint rake lint:scss"
15
+ end
16
+
17
+ desc "Run eslint linter from docker"
18
+ task :eslint do
19
+ sh "docker-compose run lint rake lint:eslint"
20
+ end
21
+
22
+ desc "Run jscs linter from docker"
23
+ task :jscs do
24
+ sh "docker-compose run lint rake lint:jscs"
25
+ end
26
+ desc "Run all linting from docker"
27
+ task :lint do
28
+ sh "docker-compose run lint rake lint"
29
+ end
30
+ end
31
+
32
+ desc "Runs all linters from docker. Run `rake -D docker` to see all available lint options"
33
+ task docker: ["docker:lint"]
@@ -0,0 +1,20 @@
1
+ require_relative "task_helpers"
2
+ include ReactOnRails::TaskHelpers
3
+
4
+ namespace :dummy_apps do
5
+ task :dummy_app do
6
+ dummy_app_dir = File.join(gem_root, "spec/dummy")
7
+ bundle_install_in(dummy_app_dir)
8
+ dummy_app_client_dir = File.join(dummy_app_dir, "client")
9
+ sh_in_dir(dummy_app_client_dir, ["npm install",
10
+ "$(npm bin)/webpack --config webpack.server.js",
11
+ "$(npm bin)/webpack --config webpack.client.js"])
12
+ end
13
+
14
+ task dummy_apps: [:dummy_app, :node_package] do
15
+ puts "Prepared all Dummy Apps"
16
+ end
17
+ end
18
+
19
+ desc "Prepares all dummy apps by installing dependencies"
20
+ task dummy_apps: ["dummy_apps:dummy_apps"]
@@ -0,0 +1,160 @@
1
+ require "rake"
2
+ require "pathname"
3
+
4
+ require_relative "task_helpers"
5
+
6
+ # Defines the ExampleType class, where each object represents a unique type of example
7
+ # app that we can generate.
8
+ module ReactOnRails
9
+ module TaskHelpers
10
+ class ExampleType
11
+ def self.all
12
+ @example_types ||= []
13
+ end
14
+
15
+ def self.namespace_name
16
+ "examples"
17
+ end
18
+
19
+ attr_reader :name, :generator_options
20
+
21
+ def initialize(name:, generator_options:)
22
+ @name = name
23
+ @generator_options = generator_options
24
+ self.class.all << self
25
+ end
26
+
27
+ def name_pretty
28
+ "#{@name} example app"
29
+ end
30
+
31
+ def server_rendering?
32
+ generator_options.include?("--server-rendering")
33
+ end
34
+
35
+ def dir
36
+ File.join(examples_dir, name)
37
+ end
38
+
39
+ def dir_exist?
40
+ Dir.exist?(dir)
41
+ end
42
+
43
+ def client_dir
44
+ File.join(dir, "client")
45
+ end
46
+
47
+ def source_package_json
48
+ File.join(gem_root, "lib/generators/react_on_rails/templates/base/base/client/package.json.tt")
49
+ end
50
+
51
+ def node_modules_dir
52
+ File.join(client_dir, "node_modules")
53
+ end
54
+
55
+ def webpack_bundles_dir
56
+ File.join(dir, "app", "assets", "javascripts", "generated")
57
+ end
58
+
59
+ def webpack_bundles
60
+ bundles = []
61
+ bundles << File.join(webpack_bundles_dir, "app-bundle.js")
62
+ bundles << File.join(webpack_bundles_dir, "server-bundle.js") if server_rendering?
63
+ bundles << File.join(webpack_bundles_dir, "vendor-bundle.js")
64
+ end
65
+
66
+ def gemfile
67
+ File.join(dir, "Gemfile")
68
+ end
69
+
70
+ def gemfile_lock
71
+ "#{gemfile}.lock"
72
+ end
73
+
74
+ def package_json
75
+ File.join(client_dir, "package.json")
76
+ end
77
+
78
+ # Gems we need to add to the Gemfile before bundle installing
79
+ def required_gems
80
+ relative_gem_root = Pathname(gem_root).relative_path_from(Pathname(dir))
81
+ ["gem 'react_on_rails', path: '#{relative_gem_root}'"]
82
+ end
83
+
84
+ # Options we pass when running `rails new` from the command-line
85
+ def rails_options
86
+ "--skip-bundle --skip-spring --skip-git --skip-test-unit --skip-active-record"
87
+ end
88
+
89
+ # Methods for retrieving the name of a task specific to the example type
90
+ %w(gen prepare clean clobber npm_install build_webpack_bundles).each do |task_type|
91
+ method = "#{task_type}_task_name" # ex: `clean_task_name`
92
+ task_name = "#{task_type}_#{name}" # ex: `clean_basic`
93
+
94
+ define_method(method) { "#{self.class.namespace_name}:#{task_name}" }
95
+ define_method("#{method}_short") { task_name }
96
+ end
97
+
98
+ def rspec_task_name_short
99
+ "example_#{name}"
100
+ end
101
+
102
+ def rspec_task_name
103
+ "run_rspec:#{rspec_task_name_short}"
104
+ end
105
+
106
+ def source_files
107
+ FileList.new(all_files_in_dir(generators_source_dir))
108
+ end
109
+
110
+ # Note: we need to explicitly declare a file we know is supposed to be there
111
+ # to indicate that the example is in need of being rebuilt in the case of its absence.
112
+ def generated_files
113
+ FileList.new(all_files_in_dir(dir)) do |fl|
114
+ fl.include(gemfile) # explicitly declared file (dependency of Gemfile.lock)
115
+ fl.include(package_json) # explicitly declared file (dependency of NPM Install)
116
+ fl.exclude(%r{client(/node_modules(.+)?)?$}) # leave node_modules folder
117
+ end
118
+ end
119
+
120
+ def generated_client_files
121
+ generated_files.exclude { |f| !f.start_with?(client_dir) }
122
+ end
123
+
124
+ # generated files plus explicitly included files resulting from running
125
+ # bundle install, npm install, and generating the webpack bundles
126
+ def prepared_files
127
+ generated_files
128
+ .include(webpack_bundles)
129
+ .include(node_modules_dir)
130
+ .include(gemfile_lock)
131
+ end
132
+
133
+ def clean_files
134
+ generated_files
135
+ end
136
+
137
+ # Assumes we are inside client folder
138
+ def build_webpack_bundles_shell_commands
139
+ webpack_command = File.join("$(npm bin)", "webpack")
140
+ shell_commands = []
141
+ shell_commands << "#{webpack_command} --config webpack.server.rails.config.js" if server_rendering?
142
+ shell_commands << "#{webpack_command} --config webpack.client.rails.config.js"
143
+ end
144
+
145
+ # Assumes we are inside a rails app's folder and necessary gems have been installed
146
+ def generator_shell_commands
147
+ shell_commands = []
148
+ shell_commands << "rails generate react_on_rails:install #{generator_options}"
149
+ shell_commands << "rails generate react_on_rails:dev_tests #{generator_options}"
150
+ end
151
+
152
+ private
153
+
154
+ # Defines globs that scoop up all files (including dotfiles) in given directory
155
+ def all_files_in_dir(p_dir)
156
+ [File.join(p_dir, "**", "*"), File.join(p_dir, "**", ".*")]
157
+ end
158
+ end
159
+ end
160
+ end