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

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