potassium 6.6.0 → 7.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +37 -0
  3. data/README.md +8 -1
  4. data/lib/potassium/assets/.circleci/config.yml.erb +31 -12
  5. data/lib/potassium/assets/.eslintrc.json +15 -8
  6. data/lib/potassium/assets/.rubocop.yml +62 -1
  7. data/lib/potassium/assets/README.yml +3 -9
  8. data/lib/potassium/assets/app/frontend/active_admin/jquery.js +2 -0
  9. data/lib/potassium/assets/app/frontend/api/__mocks__/index.mock.ts +3 -0
  10. data/lib/potassium/assets/app/frontend/api/index.ts +63 -0
  11. data/lib/potassium/assets/app/frontend/css/application.css +3 -0
  12. data/lib/potassium/assets/app/frontend/entrypoints/active_admin.js +7 -0
  13. data/lib/potassium/assets/app/frontend/entrypoints/active_admin.scss +38 -0
  14. data/lib/potassium/assets/app/frontend/entrypoints/application.js +12 -0
  15. data/lib/potassium/assets/app/{javascript → frontend}/types/vue.d.ts +1 -0
  16. data/lib/potassium/assets/app/frontend/utils/case-converter.ts +39 -0
  17. data/lib/potassium/assets/app/frontend/utils/csrf-token.ts +9 -0
  18. data/lib/potassium/assets/bin/setup.erb +1 -1
  19. data/lib/potassium/assets/bin/update.erb +1 -1
  20. data/lib/potassium/assets/config/sentry.rb.erb +2 -10
  21. data/lib/potassium/assets/lib/dotenv_monkeypatch.rb +19 -0
  22. data/lib/potassium/assets/package.json +7 -0
  23. data/lib/potassium/assets/tailwind.config.js +14 -0
  24. data/lib/potassium/assets/testing/simplecov_config.rb +9 -1
  25. data/lib/potassium/assets/tsconfig.config.json +8 -0
  26. data/lib/potassium/assets/tsconfig.json +11 -26
  27. data/lib/potassium/assets/vite.config.ts +46 -0
  28. data/lib/potassium/cli_options.rb +6 -4
  29. data/lib/potassium/platanus_config.rb +1 -1
  30. data/lib/potassium/recipes/admin.rb +40 -32
  31. data/lib/potassium/recipes/background_processor.rb +1 -1
  32. data/lib/potassium/recipes/bullet.rb +41 -0
  33. data/lib/potassium/recipes/ci.rb +1 -0
  34. data/lib/potassium/recipes/cleanup.rb +0 -1
  35. data/lib/potassium/recipes/coverage.rb +4 -27
  36. data/lib/potassium/recipes/database_container.rb +1 -1
  37. data/lib/potassium/recipes/error_reporting.rb +2 -2
  38. data/lib/potassium/recipes/file_storage.rb +1 -1
  39. data/lib/potassium/recipes/front_end_vite.rb +153 -0
  40. data/lib/potassium/recipes/google_tag_manager.rb +19 -23
  41. data/lib/potassium/recipes/mjml.rb +1 -1
  42. data/lib/potassium/recipes/node.rb +1 -1
  43. data/lib/potassium/recipes/style.rb +4 -5
  44. data/lib/potassium/recipes/vue_admin.rb +7 -13
  45. data/lib/potassium/recipes/yarn.rb +1 -1
  46. data/lib/potassium/templates/application.rb +4 -8
  47. data/lib/potassium/version.rb +9 -9
  48. data/spec/features/api_spec.rb +2 -2
  49. data/spec/features/background_processor_spec.rb +2 -2
  50. data/spec/features/bullet_spec.rb +29 -0
  51. data/spec/features/ci_spec.rb +10 -4
  52. data/spec/features/coverage_spec.rb +7 -6
  53. data/spec/features/database_container_spec.rb +1 -1
  54. data/spec/features/database_spec.rb +1 -1
  55. data/spec/features/draper_spec.rb +1 -1
  56. data/spec/features/error_reporting_spec.rb +2 -2
  57. data/spec/features/file_storage_spec.rb +4 -4
  58. data/spec/features/google_tag_manager_spec.rb +1 -1
  59. data/spec/features/i18n_spec.rb +1 -1
  60. data/spec/features/mailer_spec.rb +1 -0
  61. data/spec/features/new_project_spec.rb +1 -1
  62. data/spec/features/power_types_spec.rb +1 -1
  63. data/spec/features/pundit_spec.rb +1 -1
  64. data/spec/features/schedule_spec.rb +1 -1
  65. data/spec/features/testing_spec.rb +0 -1
  66. data/spec/features/vue_admin_spec.rb +1 -1
  67. data/spec/front_end_vite_spec.rb +81 -0
  68. metadata +26 -16
  69. data/lib/potassium/assets/config/webpack/rules/css.js +0 -5
  70. data/lib/potassium/assets/config/webpack/rules/index.js +0 -11
  71. data/lib/potassium/assets/config/webpack/rules/jquery.js +0 -11
  72. data/lib/potassium/assets/config/webpack/rules/typescript.js +0 -32
  73. data/lib/potassium/assets/config/webpack/rules/vue.js +0 -19
  74. data/lib/potassium/assets/config/webpack/webpack.config.js +0 -4
  75. data/lib/potassium/recipes/front_end.rb +0 -256
  76. data/spec/features/front_end_spec.rb +0 -71
  77. /data/lib/potassium/assets/app/{javascript → frontend}/components/app.spec.ts +0 -0
  78. /data/lib/potassium/assets/app/{javascript → frontend}/components/app.vue +0 -0
@@ -1,31 +1,16 @@
1
1
  {
2
+ "extends": "@vue/tsconfig/tsconfig.web.json",
3
+ "include": ["env.d.ts", "app/**/*", "app/**/*.vue"],
2
4
  "compilerOptions": {
3
- "module": "ESNext",
4
- "moduleResolution": "Node",
5
- "resolveJsonModule": true,
6
- "useDefineForClassFields": true,
7
- "jsx": "preserve",
8
- "noImplicitThis": true,
9
- "strict": true,
10
- "isolatedModules": true,
11
- "preserveValueImports": true,
12
- "importsNotUsedAsValues": "error",
13
- "target": "esnext",
14
- "allowJs": true,
15
-
16
- // Recommended
17
- "esModuleInterop": true,
18
- "forceConsistentCasingInFileNames": true,
19
- // See <https://github.com/vuejs/vue-cli/pull/5688>
20
- "skipLibCheck": true,
21
- "baseUrl": "app/javascript/",
22
- "types": ["@types/jest", "@types/node"],
5
+ "baseUrl": ".",
6
+ "paths": {
7
+ "@/*": ["./app/frontend/*"]
8
+ }
23
9
  },
24
- "include": [
25
- "app/javascript/**/*.ts",
26
- "app/javascript/**/*.vue"
27
- ],
28
- "exclude": [
29
- "node_modules"
10
+
11
+ "references": [
12
+ {
13
+ "path": "./tsconfig.config.json"
14
+ }
30
15
  ]
31
16
  }
@@ -0,0 +1,46 @@
1
+ import { fileURLToPath, URL } from 'node:url';
2
+ import { defineConfig } from 'vitest/config'
3
+ import RubyPlugin from 'vite-plugin-ruby';
4
+ import vue from '@vitejs/plugin-vue';
5
+
6
+ export default defineConfig({
7
+ plugins: [
8
+ RubyPlugin(),
9
+ vue()
10
+ ],
11
+ resolve: {
12
+ alias: {
13
+ vue: 'vue/dist/vue.esm-bundler.js',
14
+ '@': fileURLToPath(new URL('./app/frontend', import.meta.url)),
15
+ },
16
+ },
17
+ test: {
18
+ globals: true,
19
+ environment: 'jsdom',
20
+ coverage: {
21
+ provider: 'c8',
22
+ all: true,
23
+ include: ['app/frontend/**/*.{js,ts,vue}'],
24
+ exclude: [
25
+ /* default excludes */
26
+ 'coverage/**',
27
+ 'dist/**',
28
+ 'packages/*/test{,s}/**',
29
+ '**/*.d.ts',
30
+ 'cypress/**',
31
+ 'test{,s}/**',
32
+ 'test{,-*}.{js,cjs,mjs,ts,tsx,jsx}',
33
+ '**/*{.,-}test.{js,cjs,mjs,ts,tsx,jsx}',
34
+ '**/*{.,-}spec.{js,cjs,mjs,ts,tsx,jsx}',
35
+ '**/__tests__/**',
36
+ '**/{karma,rollup,webpack,vite,vitest,jest,ava,babel,nyc,cypress,tsup,build}.config.*',
37
+ '**/.{eslint,mocha,prettier}rc.{js,cjs,yml}',
38
+ /* custom excludes */
39
+ 'app/frontend/**/*.spec.{js,ts,vue}',
40
+ 'app/frontend/**/*.mock.{js,ts,vue}',
41
+ 'app/frontend/active_admin/jquery.js',
42
+ 'app/frontend/entrypoints',
43
+ ]
44
+ }
45
+ },
46
+ })
@@ -172,10 +172,12 @@ module Potassium::CliOptions # rubocop:disable Metrics/ModuleLength
172
172
  default_test_value: false
173
173
  },
174
174
  {
175
- type: :flag,
176
- name: :front_end,
177
- desc: "Decides which front-end framework to use. Available: Vue, Angular 2, None",
178
- default_test_value: "None"
175
+ type: :switch,
176
+ name: :front_end_vite,
177
+ desc: "Whether to use Vite as frontend bundler",
178
+ negatable: true,
179
+ default_value: true,
180
+ default_test_value: true
179
181
  },
180
182
  {
181
183
  type: :switch,
@@ -10,7 +10,7 @@ module Potassium
10
10
  'db': 'postgresql', 'locale': 'es-CL', 'email_service': 'sendgrid', 'devise': true,
11
11
  'devise-user-model': true, 'admin': true, 'vue_admin': true, 'pundit': true,
12
12
  'api': true, 'storage': 'shrine', 'heroku': true, 'background_processor': true,
13
- 'draper': true, 'schedule': true, 'sentry': true, 'front_end': 'vue',
13
+ 'draper': true, 'schedule': true, 'sentry': true, 'front_end_vite': true,
14
14
  'google_tag_manager': true, 'test': true, 'spring': true
15
15
  }
16
16
  default_options = default_options.filter { |key, _| @option_key_names.include?(key) }
@@ -29,15 +29,14 @@ class Recipes::Admin < Rails::AppBuilder
29
29
  gem_exists?(/activeadmin/)
30
30
  end
31
31
 
32
- private
33
-
34
32
  def add_active_admin
33
+ recipe = self
35
34
  gather_gem 'activeadmin', '~> 2.9'
36
- gather_gem 'activeadmin_addons'
35
+ gather_gem 'activeadmin_addons', '~> 2.0.0.beta.0'
37
36
  add_readme_section :internal_dependencies, :active_admin
38
37
  after(:gem_install, wrap_in_action: :admin_install) do
39
38
  generate "active_admin:install --use_webpacker"
40
- run 'bin/yarn add @activeadmin/activeadmin'
39
+ run 'yarn add @activeadmin/activeadmin'
41
40
  line = "ActiveAdmin.setup do |config|"
42
41
  initializer = "config/initializers/active_admin.rb"
43
42
  gsub_file initializer, /(#{Regexp.escape(line)})/mi do |_match|
@@ -58,39 +57,48 @@ class Recipes::Admin < Rails::AppBuilder
58
57
 
59
58
  generate "activeadmin_addons:install"
60
59
 
61
- run "bin/yarn add arctic_admin @fortawesome/fontawesome-free"
60
+ run "yarn add arctic_admin @fortawesome/fontawesome-free"
61
+
62
+ run 'rm -rf config/webpack/plugins'
63
+ run 'rm app/javascript/packs/active_admin.js'
64
+ run 'rm -rf app/javascript/packs/active_admin'
65
+ run 'rm app/javascript/stylesheets/active_admin.scss'
66
+ run 'rmdir app/javascript/packs'
67
+ run 'rmdir app/javascript/stylesheets'
68
+ run 'rmdir app/javascript'
62
69
 
63
- aa_style = "app/javascript/stylesheets/active_admin.scss"
70
+ recipe.copy_frontend_files
71
+ recipe.insert_vite_monkeypatch
72
+ end
73
+ end
64
74
 
65
- gsub_file(
66
- aa_style,
67
- "@import \"~@activeadmin/activeadmin/src/scss/mixins\";\n" +
68
- "@import \"~@activeadmin/activeadmin/src/scss/base\";",
69
- "@import '~arctic_admin/src/scss/main'; \n"
70
- )
75
+ def copy_frontend_files
76
+ copy_file '../assets/app/frontend/entrypoints/active_admin.js',
77
+ 'app/frontend/entrypoints/active_admin.js'
78
+ copy_file '../assets/app/frontend/entrypoints/active_admin.scss',
79
+ 'app/frontend/entrypoints/active_admin.scss'
80
+ copy_file '../assets/app/frontend/active_admin/jquery.js', 'app/frontend/active_admin/jquery.js'
81
+ end
71
82
 
72
- aa_js = "app/javascript/packs/active_admin.js"
73
- js_line = "import \"@activeadmin/activeadmin\";\n"
83
+ def insert_vite_monkeypatch
84
+ monkeypatch =
85
+ <<~HERE
86
+ module ActiveAdminViteJS
87
+ def stylesheet_pack_tag(style, **options)
88
+ style = 'active_admin.scss' if style == 'active_admin.css'
89
+ vite_stylesheet_tag(style, **options)
90
+ end
74
91
 
75
- gsub_file(
76
- aa_js,
77
- js_line,
78
- <<~HERE
79
- #{js_line}
80
- import '@fortawesome/fontawesome-free/css/all.css';
81
- import 'arctic_admin';
82
- HERE
83
- )
92
+ def javascript_pack_tag(script, **options)
93
+ vite_javascript_tag(script, **options)
94
+ end
95
+ end
84
96
 
85
- run "mv app/javascript/packs/active_admin.js app/javascript/active_admin.js"
86
- gsub_file(
87
- "app/javascript/active_admin.js",
88
- 'import "../stylesheets/active_admin";',
89
- 'import "./stylesheets/active_admin.scss";'
90
- )
97
+ ActiveAdmin::Views::Pages::Base.include ActiveAdminViteJS
98
+ ActiveSupport.on_load(:action_view) { include ActiveAdminViteJS }
91
99
 
92
- run 'rm -rf config/webpack/plugins'
93
- run 'rm -rf app/javascript/packs/active_admin'
94
- end
100
+ HERE
101
+ insert_into_file "config/initializers/active_admin.rb", monkeypatch,
102
+ before: "ActiveAdmin.setup do |config|"
95
103
  end
96
104
  end
@@ -89,7 +89,7 @@ class Recipes::BackgroundProcessor < Rails::AppBuilder
89
89
  '.env.development',
90
90
  <<~TEXT
91
91
  REDIS_HOST=127.0.0.1
92
- REDIS_PORT=$(make services-port SERVICE=redis PORT=6379)
92
+ REDIS_PORT=COMMAND_EXPAND(make services-port SERVICE=redis PORT=6379)
93
93
  REDIS_URL=redis://${REDIS_HOST}:${REDIS_PORT}/1
94
94
  TEXT
95
95
  )
@@ -0,0 +1,41 @@
1
+ class Recipes::Bullet < Rails::AppBuilder
2
+ def create
3
+ gather_gem 'bullet'
4
+ recipe = self
5
+ after(:gem_install) do
6
+ recipe.bullet_config
7
+ end
8
+ end
9
+
10
+ def installed?
11
+ gem_exists?(/bullet/)
12
+ end
13
+
14
+ def install
15
+ create
16
+ end
17
+
18
+ def bullet_config
19
+ application bullet_after_initialize, env: "development"
20
+ insert_into_file "app/jobs/application_job.rb", bullet_application_job_config, before: "end"
21
+ end
22
+
23
+ private
24
+
25
+ def bullet_after_initialize
26
+ <<~RUBY
27
+ config.after_initialize do
28
+ Bullet.enable = true
29
+ Bullet.alert = true
30
+ Bullet.bullet_logger = true
31
+ Bullet.console = true
32
+ Bullet.rails_logger = true
33
+ Bullet.add_footer = true
34
+ end
35
+ RUBY
36
+ end
37
+
38
+ def bullet_application_job_config
39
+ " include Bullet::ActiveJob if Rails.env.development?\n"
40
+ end
41
+ end
@@ -1,6 +1,7 @@
1
1
  class Recipes::Ci < Rails::AppBuilder
2
2
  def create
3
3
  template '../assets/.circleci/config.yml.erb', '.circleci/config.yml'
4
+ gather_gem 'repo_analyzer'
4
5
 
5
6
  gather_gems(:test) do
6
7
  gather_gem 'rspec_junit_formatter', '~> 0.4'
@@ -4,6 +4,5 @@ class Recipes::Cleanup < Rails::AppBuilder
4
4
  erase_comments "config/environments/production.rb"
5
5
  erase_comments "config/environments/test.rb"
6
6
  erase_comments "config/environments/development.rb"
7
- cut_comments "config/initializers/backtrace_silencers.rb", limit: 100
8
7
  end
9
8
  end
@@ -4,9 +4,8 @@ class Recipes::Coverage < Rails::AppBuilder
4
4
  configure_rails_helper
5
5
  append_to_file('.gitignore', "/coverage/*\n")
6
6
  recipe = self
7
- after(:setup_jest) do
8
- recipe.configure_jest_coverage
9
- recipe.setup_jest_text_formatter
7
+ after(:vite_install) do
8
+ recipe.setup_coverage_dependencies
10
9
  end
11
10
  end
12
11
 
@@ -18,16 +17,8 @@ class Recipes::Coverage < Rails::AppBuilder
18
17
  create
19
18
  end
20
19
 
21
- def configure_jest_coverage
22
- json_file = File.read(Pathname.new("package.json"))
23
- js_package = JSON.parse(json_file)
24
- js_package = add_coverage_config(js_package)
25
- json_string = JSON.pretty_generate(js_package)
26
- create_file 'package.json', json_string, force: true
27
- end
28
-
29
- def setup_jest_text_formatter
30
- run "bin/yarn add jest-text-formatter@1.0.2 --dev"
20
+ def setup_coverage_dependencies
21
+ run "yarn add jest-text-formatter@1.0.2 c8 --dev"
31
22
  end
32
23
 
33
24
  private
@@ -49,18 +40,4 @@ class Recipes::Coverage < Rails::AppBuilder
49
40
  end
50
41
  end
51
42
  end
52
-
53
- def add_coverage_config(js_package)
54
- js_package['scripts']['test:changes'] = 'jest --changedSince=master'
55
- js_package['jest'] = js_package['jest'].merge(coverage_defaults)
56
- js_package
57
- end
58
-
59
- def coverage_defaults
60
- {
61
- collectCoverage: true,
62
- collectCoverageFrom: ['**/*.{js,ts,vue}', '!**/node_modules/**'],
63
- coverageReporters: ['text']
64
- }
65
- end
66
43
  end
@@ -81,7 +81,7 @@ class Recipes::DatabaseContainer < Rails::AppBuilder
81
81
 
82
82
  # Database
83
83
  DB_HOST=127.0.0.1
84
- DB_PORT=$(make services-port SERVICE=#{_service_name} PORT=#{_port})
84
+ DB_PORT=COMMAND_EXPAND(make services-port SERVICE=#{_service_name} PORT=#{_port})
85
85
  DB_USER=#{_user}
86
86
 
87
87
  TEXT
@@ -8,7 +8,7 @@ class Recipes::ErrorReporting < Rails::AppBuilder
8
8
 
9
9
  def create
10
10
  if selected?(:report_error)
11
- gather_gem 'sentry-raven'
11
+ gather_gem 'sentry-rails'
12
12
  template '../assets/config/sentry.rb.erb', 'config/initializers/sentry.rb'
13
13
  append_to_file '.env.development', "SENTRY_DSN=\n"
14
14
  add_readme_section :internal_dependencies, :sentry
@@ -21,6 +21,6 @@ class Recipes::ErrorReporting < Rails::AppBuilder
21
21
  end
22
22
 
23
23
  def installed?
24
- gem_exists?(/sentry-raven/) && file_exist?('config/initializers/sentry.rb')
24
+ gem_exists?(/sentry-rails/) && file_exist?('config/initializers/sentry.rb')
25
25
  end
26
26
  end
@@ -86,7 +86,7 @@ class Recipes::FileStorage < Rails::AppBuilder
86
86
  end
87
87
 
88
88
  def add_image_handling_heroku_setup
89
- append_to_file(
89
+ prepend_file(
90
90
  '.buildpacks',
91
91
  <<~HERE
92
92
  https://github.com/heroku/heroku-buildpack-apt
@@ -0,0 +1,153 @@
1
+ class Recipes::FrontEndVite < Rails::AppBuilder
2
+ VUE_VERSION = Potassium::VUE_VERSION
3
+ POSTCSS_VERSION = Potassium::POSTCSS_VERSION
4
+ TAILWINDCSS_VERSION = Potassium::TAILWINDCSS_VERSION
5
+ AUTOPREFIXER_VERSION = Potassium::AUTOPREFIXER_VERSION
6
+ VUE_TEST_UTILS_VERSION = Potassium::VUE_TEST_UTILS_VERSION
7
+
8
+ DEPENDENCIES = {
9
+ tailwind: [
10
+ "postcss@#{POSTCSS_VERSION}",
11
+ "tailwindcss@#{TAILWINDCSS_VERSION}",
12
+ "autoprefixer@#{AUTOPREFIXER_VERSION}",
13
+ "sass"
14
+ ],
15
+ typescript: [
16
+ "typescript"
17
+ ],
18
+ typescript_dev: [
19
+ "@types/node"
20
+ ],
21
+ vue: [
22
+ "vue@#{VUE_VERSION}"
23
+ ],
24
+ vue_dev: [
25
+ "@vitejs/plugin-vue",
26
+ "@vue/tsconfig",
27
+ "vue-tsc"
28
+ ],
29
+ vitest_dev: [
30
+ "vitest",
31
+ "@vue/test-utils@#{VUE_TEST_UTILS_VERSION}",
32
+ "jsdom"
33
+ ],
34
+ api: [
35
+ "axios",
36
+ "humps"
37
+ ],
38
+ api_dev: [
39
+ "@types/humps"
40
+ ]
41
+ }
42
+
43
+ def installed?
44
+ gem_exists?(/vite_rails/)
45
+ end
46
+
47
+ def create
48
+ add_vite
49
+ end
50
+
51
+ def install
52
+ add_vite
53
+ end
54
+
55
+ def add_vite
56
+ gather_gem("vite_rails")
57
+ recipe = self
58
+ after(:gem_install, wrap_in_action: :vite_install) do
59
+ run "yarn install"
60
+ run "bundle exec vite install"
61
+ recipe.install_packages
62
+ recipe.setup_tailwind
63
+ recipe.copy_config_files
64
+ recipe.setup_vite
65
+ recipe.copy_default_assets
66
+ recipe.insert_vue_into_layout
67
+ recipe.setup_api_client
68
+ add_readme_header :vite
69
+ end
70
+ end
71
+
72
+ def install_packages
73
+ packages, dev_packages = DEPENDENCIES.partition { |k, _| !k.to_s.end_with?('_dev') }.map(&:to_h)
74
+
75
+ run "yarn add #{packages.values.flatten.join(' ')}"
76
+ run "yarn add --dev #{dev_packages.values.flatten.join(' ')}"
77
+ end
78
+
79
+ def setup_tailwind
80
+ run "npx tailwindcss init -p"
81
+ end
82
+
83
+ def copy_config_files
84
+ copy_file '../assets/vite.config.ts', 'vite.config.ts', force: true
85
+ copy_file '../assets/tailwind.config.js', 'tailwind.config.js', force: true
86
+ copy_file '../assets/tsconfig.json', 'tsconfig.json', force: true
87
+ copy_file '../assets/tsconfig.config.json', 'tsconfig.config.json', force: true
88
+ end
89
+
90
+ def setup_vite
91
+ add_vite_dev_ws_content_security_policy
92
+ copy_dotenv_monkeypatch
93
+ end
94
+
95
+ def copy_default_assets
96
+ copy_file '../assets/app/frontend/entrypoints/application.js',
97
+ 'app/frontend/entrypoints/application.js', force: true
98
+ copy_file '../assets/app/frontend/css/application.css', 'app/frontend/css/application.css',
99
+ force: true
100
+ copy_file '../assets/app/frontend/components/app.vue', 'app/frontend/components/app.vue',
101
+ force: true
102
+ copy_file '../assets/app/frontend/types/vue.d.ts', 'app/frontend/types/vue.d.ts'
103
+ copy_file '../assets/app/frontend/components/app.spec.ts',
104
+ 'app/frontend/components/app.spec.ts'
105
+ end
106
+
107
+ def insert_vue_into_layout
108
+ layout_file = "app/views/layouts/application.html.erb"
109
+ insert_into_file(
110
+ layout_file,
111
+ "<div id=\"vue-app\">\n <app></app>\n ",
112
+ before: "<%= yield %>"
113
+ )
114
+ insert_into_file layout_file, "\n </div>", after: "<%= yield %>"
115
+ end
116
+
117
+ def setup_api_client
118
+ copy_file '../assets/app/frontend/api/index.ts', 'app/frontend/api/index.ts'
119
+ copy_file '../assets/app/frontend/api/__mocks__/index.mock.ts',
120
+ 'app/frontend/api/__mocks__/index.mock.ts'
121
+ copy_file '../assets/app/frontend/utils/case-converter.ts',
122
+ 'app/frontend/utils/case-converter.ts'
123
+ copy_file '../assets/app/frontend/utils/csrf-token.ts',
124
+ 'app/frontend/utils/csrf-token.ts'
125
+ end
126
+
127
+ def add_vite_dev_ws_content_security_policy
128
+ initializer = "config/initializers/content_security_policy.rb"
129
+ line = "# policy.style_src *policy.style_src, :unsafe_inline if Rails.env.development?"
130
+ policy = <<~HERE.chomp
131
+ # if Rails.env.development?
132
+ # policy.connect_src *policy.connect_src,
133
+ # "ws://\#{ViteRuby.config.host_with_port}"
134
+ # end
135
+ HERE
136
+ # check if policy already exists
137
+ return if File.read(initializer).include?("policy.connect_src *policy.connect_src")
138
+
139
+ inject_into_file initializer, after: line do
140
+ policy
141
+ end
142
+ end
143
+
144
+ def copy_dotenv_monkeypatch
145
+ copy_file '../assets/lib/dotenv_monkeypatch.rb',
146
+ 'lib/dotenv_monkeypatch.rb', force: true
147
+ insert_into_file(
148
+ "config/application.rb",
149
+ "\nrequire_relative '../lib/dotenv_monkeypatch'\n",
150
+ after: "Bundler.require(*Rails.groups)"
151
+ )
152
+ end
153
+ end
@@ -25,7 +25,8 @@ class Recipes::GoogleTagManager < Rails::AppBuilder
25
25
  def add_content_security_policy
26
26
  inject_into_file(
27
27
  'config/initializers/content_security_policy.rb',
28
- content_security_policy_code
28
+ content_security_policy_code,
29
+ before: '# Report violations without enforcing the policy.'
29
30
  )
30
31
  end
31
32
 
@@ -67,28 +68,23 @@ class Recipes::GoogleTagManager < Rails::AppBuilder
67
68
 
68
69
  def content_security_policy_code
69
70
  <<~HERE
70
- Rails.application.config.content_security_policy do |policy|
71
- policy.connect_src(
72
- :self,
73
- :https,
74
- 'http://localhost:3035',
75
- 'ws://localhost:3035',
76
- 'https://www.google-analytics.com'
77
- )
78
- # google tag manager requires to enable unsafe inline and vue unsave eval:
79
- # https://developers.google.com/tag-manager/web/csp
80
- # https://vuejs.org/v2/guide/installation.html#CSP-environments
81
- policy.script_src(
82
- :self,
83
- :https,
84
- :unsafe_inline,
85
- :unsafe_eval,
86
- 'https://www.googletagmanager.com',
87
- 'https://www.google-analytics.com',
88
- 'https://ssl.google-analytics.com'
89
- )
90
- policy.img_src :self, 'data:', :https, 'https://www.googletagmanager.com', 'https://www.google-analytics.com'
91
- end
71
+ # policy.connect_src(
72
+ # *policy.connect_src,
73
+ # 'https://www.google-analytics.com'
74
+ # )
75
+ # google tag manager requires to enable unsafe inline:
76
+ # https://developers.google.com/tag-manager/web/csp
77
+ # policy.script_src(
78
+ # *policy.script_src,
79
+ # 'https://www.googletagmanager.com',
80
+ # 'https://www.google-analytics.com',
81
+ # 'https://ssl.google-analytics.com'
82
+ # )
83
+ # policy.img_src(
84
+ # *policy.img_src,
85
+ # 'https://www.googletagmanager.com',
86
+ # 'https://www.google-analytics.com'
87
+ # )
92
88
  HERE
93
89
  end
94
90
  end
@@ -4,7 +4,7 @@ class Recipes::Mjml < Rails::AppBuilder
4
4
 
5
5
  gather_gem 'mjml-rails'
6
6
  after(:gem_install) do
7
- run 'bin/yarn add mjml'
7
+ run 'yarn add mjml'
8
8
  mjml_config
9
9
  end
10
10
  end
@@ -8,7 +8,7 @@ class Recipes::Node < Rails::AppBuilder
8
8
  def create
9
9
  info "Using node version LTS #{NODE_VERSION}"
10
10
  create_file '.node-version', NODE_VERSION, force: true
11
- after(:webpacker_install) do
11
+ after(:vite_install) do
12
12
  json_file = File.read(Pathname.new("package.json"))
13
13
  js_package = JSON.parse(json_file)
14
14
  js_package["engines"] = { "node" => "#{NODE_VERSION}.x" }
@@ -20,12 +20,11 @@ class Recipes::Style < Rails::AppBuilder
20
20
  gather_gem 'rubocop-platanus'
21
21
  end
22
22
 
23
- after(:webpacker_install) do
23
+ after(:vite_install) do
24
24
  run "yarn add --dev stylelint eslint eslint-plugin-import "\
25
- "@typescript-eslint/eslint-plugin @types/jest @typescript-eslint/parser eslint-plugin-jest"
26
- if selected?(:front_end, :vue)
27
- run 'yarn add --dev eslint-plugin-vue @vue/eslint-config-typescript'
28
- end
25
+ "@typescript-eslint/eslint-plugin @types/jest @typescript-eslint/parser "\
26
+ "eslint-plugin-jest eslint-plugin-platanus eslint-plugin-vue "\
27
+ "@vue/eslint-config-typescript eslint-plugin-tailwindcss"
29
28
  end
30
29
  end
31
30