superglue 2.0.0.rc.2 → 2.0.0.rc.4

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 (46) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/superglue/install/install_generator.rb +242 -60
  3. data/lib/generators/superglue/install/templates/bun/bun.config.deepkit.js +1 -0
  4. data/lib/generators/superglue/install/templates/bun/bun.config.js +1 -0
  5. data/lib/generators/superglue/install/templates/bun/bun.config.ts.js +1 -0
  6. data/lib/generators/superglue/install/templates/bun/bun.config.typia.js +3 -2
  7. data/lib/generators/superglue/install/templates/bun/page_to_page_mapping.js +1 -1
  8. data/lib/generators/superglue/install/templates/bun/page_to_page_mapping.ts +1 -1
  9. data/lib/generators/superglue/install/templates/js/application.jsx +5 -8
  10. data/lib/generators/superglue/install/templates/js/build.mjs +1 -0
  11. data/lib/generators/superglue/install/templates/js/inputs.jsx +1 -1
  12. data/lib/generators/superglue/install/templates/js/jsconfig.json +3 -3
  13. data/lib/generators/superglue/install/templates/js/layout.jsx +2 -3
  14. data/lib/generators/superglue/install/templates/rollup/rollup.config.deepkit.js +8 -11
  15. data/lib/generators/superglue/install/templates/rollup/rollup.config.js +2 -6
  16. data/lib/generators/superglue/install/templates/rollup/rollup.config.ts.js +2 -9
  17. data/lib/generators/superglue/install/templates/rollup/rollup.config.typia.js +5 -10
  18. data/lib/generators/superglue/install/templates/ssr/bun.build_ssr.js +1 -0
  19. data/lib/generators/superglue/install/templates/ssr/esbuild.build_ssr.mjs +1 -0
  20. data/lib/generators/superglue/install/templates/ssr/rollup.build_ssr.config.js +6 -7
  21. data/lib/generators/superglue/install/templates/ssr/server_rendering.jsx +6 -4
  22. data/lib/generators/superglue/install/templates/ssr/server_rendering.tsx +5 -3
  23. data/lib/generators/superglue/install/templates/ssr/webpack.build_ssr.js +2 -1
  24. data/lib/generators/superglue/install/templates/ts/application.tsx +5 -8
  25. data/lib/generators/superglue/install/templates/ts/build.deepkit.mjs +1 -0
  26. data/lib/generators/superglue/install/templates/ts/build.mjs +1 -0
  27. data/lib/generators/superglue/install/templates/ts/build.typia.mjs +1 -0
  28. data/lib/generators/superglue/install/templates/ts/flash.ts +3 -0
  29. data/lib/generators/superglue/install/templates/ts/inputs.tsx +1 -1
  30. data/lib/generators/superglue/install/templates/ts/layout.tsx +4 -3
  31. data/lib/generators/superglue/install/templates/ts/tsconfig.json +3 -4
  32. data/lib/generators/superglue/install/templates/webpack/webpack.config.deepkit.js +2 -1
  33. data/lib/generators/superglue/install/templates/webpack/webpack.config.js +2 -1
  34. data/lib/generators/superglue/install/templates/webpack/webpack.config.ts.js +2 -1
  35. data/lib/generators/superglue/install/templates/webpack/webpack.config.typia.js +2 -1
  36. data/lib/generators/superglue/scaffold_controller/scaffold_controller_generator.rb +12 -12
  37. data/lib/generators/superglue/view_collection/templates/js/edit.html.jsx +2 -4
  38. data/lib/generators/superglue/view_collection/templates/js/index.html.jsx +3 -4
  39. data/lib/generators/superglue/view_collection/templates/js/new.html.jsx +2 -4
  40. data/lib/generators/superglue/view_collection/templates/js/show.html.jsx +2 -4
  41. data/lib/generators/superglue/view_collection/templates/ts/edit.html.tsx +2 -4
  42. data/lib/generators/superglue/view_collection/templates/ts/index.html.tsx +3 -4
  43. data/lib/generators/superglue/view_collection/templates/ts/new.html.tsx +2 -4
  44. data/lib/generators/superglue/view_collection/templates/ts/show.html.tsx +3 -5
  45. data/lib/generators/superglue/view_collection/view_collection_generator.rb +8 -35
  46. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f1f55d71343032c2ba77a23c74ae0af75e1e823c358b606b33c84af34bee88da
4
- data.tar.gz: 0a2e8ad51c13e8467f06c88229a4f863aa7bd8d888228186ff10af6e2cc8179a
3
+ metadata.gz: aff506e09c15008bbc37ae8c5e14ce6c7ab0520956fd0f31653a3deb90a6e674
4
+ data.tar.gz: 9a3f7534e42d41ae13e08f496debbc3d692d085f99dc36875f6b047956a1eda4
5
5
  SHA512:
6
- metadata.gz: 210c9b55e64faaac22fcc10b1e61bb5882a13d1ec2cd91bd6380002734f1d86f59e90af21cfa13daf0e071081ff1a7e5f4db255625b9bf3a587f4d0a4dd67839
7
- data.tar.gz: 11034825a30df06cc80525daca022d66b14ac9b4fd5566656faf3cb29d09521290a45f4f83409d85272872e95d66733ba5e9766052fc72b234a7f96ff2186c1f
6
+ metadata.gz: 2a1b558cad7439918dde128f6cf45ba12b6d028d63d4cca79d22d125d8add1f81ee486f9319d5a5d9fb1e43cccdb86d33d42a5100e603ffb22371a63d6978272
7
+ data.tar.gz: e285f3872cbc1f9235971fc27171cc277121ca4f89a5aa91a8c775b040f8599253001382f7aee66f799c6a93ff54349df95f5a498ce115d6d0660f0f42577572
@@ -1,4 +1,5 @@
1
1
  require "json"
2
+ require "shellwords"
2
3
  require "rails/generators/named_base"
3
4
  require "rails/generators/resource_helpers"
4
5
 
@@ -9,32 +10,33 @@ module Superglue
9
10
 
10
11
  class_option :typescript,
11
12
  type: :boolean,
12
- required: false,
13
- default: false,
14
- desc: "Use typescript"
13
+ default: true,
14
+ desc: "Use TypeScript. Pass --no-typescript for JavaScript."
15
15
 
16
16
  class_option :bundler,
17
17
  type: :string,
18
18
  required: false,
19
- desc: "JavaScript bundler to use (esbuild, bun, rollup, webpack). Skips interactive prompt."
19
+ desc: "JavaScript bundler to use (esbuild, bun, rollup, webpack). Defaults to the detected bundler."
20
20
 
21
+ # A string default, rather than nil, lets `--no-validator` (which Thor
22
+ # parses as nil) be told apart from leaving the option out.
21
23
  class_option :validator,
22
24
  type: :string,
23
- required: false,
24
- desc: "Runtime type validator to use (deepkit, typia, none). Skips interactive prompt."
25
+ default: "auto",
26
+ desc: "Runtime type validator to use (deepkit, typia). Pass --no-validator to skip it. " \
27
+ "auto picks typia on TypeScript 7 or later (or when TypeScript is not installed yet) " \
28
+ "and deepkit on TypeScript 6 or earlier."
25
29
 
26
30
  class_option :svgr,
27
31
  type: :boolean,
28
- required: false,
29
- desc: "Enable SVGR to import SVGs as React components. Skips interactive prompt."
32
+ default: true,
33
+ desc: "Enable SVGR to import SVGs as React components. Pass --no-svgr to disable."
30
34
 
31
35
  def create_files
32
36
  remove_file "#{app_js_path}/application.js"
33
37
 
34
- @use_typescript = options["typescript"]
35
- @bundler = ask_bundler
36
- @validator = @use_typescript ? ask_validator : "none"
37
- @use_svgr = ask_svgr
38
+ resolve_choices
39
+ say_choices
38
40
 
39
41
  if @use_typescript
40
42
  copy_ts_files
@@ -60,6 +62,9 @@ module Superglue
60
62
  say "Copying stream.json.props"
61
63
  copy_file "#{__dir__}/templates/stream.json.props", "app/views/layouts/stream.json.props"
62
64
 
65
+ say "Adding initial page state and #app container to application.html.erb"
66
+ update_application_layout
67
+
63
68
  say "Adding required member methods to ApplicationRecord"
64
69
  add_member_methods
65
70
 
@@ -102,20 +107,33 @@ module Superglue
102
107
  false
103
108
  end
104
109
 
105
- def ask_bundler
106
- if options["bundler"]
107
- bundler = options["bundler"]
108
- unless BUNDLERS.include?(bundler)
109
- raise Thor::Error, "Unknown bundler '#{bundler}'. Must be one of: #{BUNDLERS.join(", ")}"
110
- end
111
- say "Using bundler: #{bundler}", :green
112
- return bundler
113
- end
110
+ # typia's ttsc toolchain needs TypeScript 7's native compiler, while
111
+ # deepkit's type compiler needs the JavaScript compiler API that
112
+ # TypeScript 7 removed.
113
+ TYPIA_MIN_TYPESCRIPT = 7
114
+ DEEPKIT_MAX_TYPESCRIPT = 6
115
+ AUTO_VALIDATOR = "auto"
116
+
117
+ def resolve_choices
118
+ @bundler = resolve_bundler
119
+ @use_typescript = options["typescript"]
120
+ @typescript_major = detect_typescript_major
121
+ @validator = resolve_validator
122
+ @use_svgr = options["svgr"]
123
+ end
114
124
 
115
- detected = detect_bundler
125
+ def resolve_bundler
126
+ requested_bundler = options["bundler"]
127
+ detected_bundler = detect_bundler
116
128
 
117
- if detected
118
- say "Detected #{detected} in your project.", :green
129
+ if requested_bundler
130
+ unless BUNDLERS.include?(requested_bundler)
131
+ raise Thor::Error, "Unknown bundler '#{requested_bundler}'. Must be one of: #{BUNDLERS.join(", ")}"
132
+ end
133
+
134
+ requested_bundler
135
+ elsif detected_bundler
136
+ detected_bundler
119
137
  else
120
138
  say "No JavaScript bundler detected.", :red
121
139
  say "Install one first via jsbundling-rails:"
@@ -123,38 +141,141 @@ module Superglue
123
141
  say "See: https://github.com/rails/jsbundling-rails"
124
142
  raise Thor::Error, "No bundler found. Install one via jsbundling-rails and re-run this generator."
125
143
  end
144
+ end
126
145
 
127
- ask("Which bundler are you using?", limited_to: BUNDLERS, default: detected)
146
+ # The major version of the project's TypeScript: the installed package
147
+ # first, then the range declared in package.json. nil when TypeScript is
148
+ # not part of the project yet, or its range has no version (e.g. "latest").
149
+ def detect_typescript_major
150
+ installed_version = installed_typescript_version
151
+ declared_range = declared_typescript_range
152
+ version = installed_version || declared_range
153
+
154
+ version.to_s[/\d+/]&.to_i
128
155
  end
129
156
 
130
- def ask_validator
131
- if options["validator"]
132
- validator = options["validator"]
133
- unless VALIDATORS.include?(validator)
134
- raise Thor::Error, "Unknown validator '#{validator}'. Must be one of: #{VALIDATORS.join(", ")}"
135
- end
136
- say "Runtime type validator: #{validator}", :green
137
- return validator
157
+ def installed_typescript_version
158
+ manifest_path = "node_modules/typescript/package.json"
159
+
160
+ if File.exist?(manifest_path)
161
+ JSON.parse(File.read(manifest_path))["version"]
138
162
  end
163
+ rescue JSON::ParserError
164
+ nil
165
+ end
139
166
 
140
- say ""
141
- say "Superglue can add runtime type validation during development."
142
- say " deepkit - works with TypeScript 5 and below (uses bundler plugin)"
143
- say " typia - works with TypeScript 6 and above (uses ttsc)"
144
- say " none - skip runtime type validation"
145
- ask("Which runtime type validator would you like to use?", limited_to: VALIDATORS, default: "none")
167
+ def declared_typescript_range
168
+ if File.exist?("package.json")
169
+ package_json = JSON.parse(File.read("package.json"))
170
+ dependencies = (package_json["dependencies"] || {}).merge(package_json["devDependencies"] || {})
171
+ dependencies["typescript"]
172
+ end
173
+ rescue JSON::ParserError
174
+ nil
175
+ end
176
+
177
+ # --no-validator and --skip-validator arrive as nil; --validator=none
178
+ # still works too.
179
+ def resolve_validator
180
+ requested_validator = options["validator"]
181
+ validator_disabled = requested_validator.nil? || requested_validator == "none"
182
+ validator_automatic = requested_validator == AUTO_VALIDATOR
183
+
184
+ if validator_disabled
185
+ "none"
186
+ elsif validator_automatic
187
+ @use_typescript ? default_validator : "none"
188
+ elsif !@use_typescript
189
+ raise Thor::Error, "--validator=#{requested_validator} requires TypeScript. Remove --no-typescript."
190
+ else
191
+ ensure_validator_supported(requested_validator)
192
+ requested_validator
193
+ end
194
+ end
195
+
196
+ def default_validator
197
+ typescript_supports_typia = @typescript_major.nil? || @typescript_major >= TYPIA_MIN_TYPESCRIPT
198
+
199
+ if typescript_supports_typia
200
+ "typia"
201
+ else
202
+ "deepkit"
203
+ end
204
+ end
205
+
206
+ def ensure_validator_supported(validator)
207
+ typescript_detected = !@typescript_major.nil?
208
+ typia_unsupported = validator == "typia" && typescript_detected && @typescript_major < TYPIA_MIN_TYPESCRIPT
209
+ deepkit_unsupported = validator == "deepkit" && typescript_detected && @typescript_major > DEEPKIT_MAX_TYPESCRIPT
210
+
211
+ if !VALIDATORS.include?(validator)
212
+ raise Thor::Error, "Unknown validator '#{validator}'. Must be one of: #{VALIDATORS.join(", ")}"
213
+ elsif typia_unsupported
214
+ raise Thor::Error, "typia requires TypeScript #{TYPIA_MIN_TYPESCRIPT} or later, found TypeScript #{@typescript_major}"
215
+ elsif deepkit_unsupported
216
+ raise Thor::Error, "deepkit requires TypeScript #{DEEPKIT_MAX_TYPESCRIPT} or earlier, found TypeScript #{@typescript_major}"
217
+ end
218
+ end
219
+
220
+ # The TypeScript package to install, or nil to keep the project's own.
221
+ # Re-adding an existing typescript would upgrade it to the latest release.
222
+ def typescript_package
223
+ typescript_missing = @typescript_major.nil?
224
+
225
+ if typescript_missing && @validator == "deepkit"
226
+ "typescript@^#{DEEPKIT_MAX_TYPESCRIPT}"
227
+ elsif typescript_missing
228
+ "typescript@^#{TYPIA_MIN_TYPESCRIPT}"
229
+ end
146
230
  end
147
231
 
148
- def ask_svgr
149
- unless options["svgr"].nil?
150
- say "SVGR: #{options["svgr"] ? "enabled" : "disabled"}", :green
151
- return options["svgr"]
232
+ # Pins each package to the range @thoughtbot/superglue declares as a
233
+ # peer, so the validator toolchain matches what superglue was tested
234
+ # against. Runs after superglue is installed; a package superglue
235
+ # doesn't declare installs at its latest version.
236
+ def superglue_peer_packages(*package_names)
237
+ manifest_path = "node_modules/@thoughtbot/superglue/package.json"
238
+ peer_ranges = if File.exist?(manifest_path)
239
+ JSON.parse(File.read(manifest_path))["peerDependencies"] || {}
240
+ else
241
+ {}
242
+ end
243
+
244
+ package_names.map do |package_name|
245
+ peer_range = peer_ranges[package_name]
246
+
247
+ if peer_range
248
+ Shellwords.escape("#{package_name}@#{peer_range}")
249
+ else
250
+ package_name
251
+ end
252
+ end
253
+ end
254
+
255
+ def say_choices
256
+ bundler_source = options["bundler"] ? "from --bundler" : "detected"
257
+ typescript_source = if @typescript_major
258
+ "TypeScript #{@typescript_major} detected"
259
+ else
260
+ "will install #{typescript_package}"
261
+ end
262
+ validator_source = case options["validator"]
263
+ when AUTO_VALIDATOR then typescript_source
264
+ when nil then "from --no-validator"
265
+ else "from --validator"
152
266
  end
153
267
 
154
268
  say ""
155
- say "SVGR lets you import SVGs as React components."
156
- say "e.g., import Logo from '@images/logo.svg'"
157
- yes?("Would you like to enable SVGR? [y/N]")
269
+ say "Installing Superglue with:", :green
270
+ say " Bundler: #{@bundler} (#{bundler_source}; change with --bundler)"
271
+ if @use_typescript
272
+ say " TypeScript: yes (#{typescript_source}; --no-typescript for JavaScript)"
273
+ say " Validator: #{@validator} (#{validator_source}; change with --validator=deepkit|typia or --no-validator)"
274
+ else
275
+ say " TypeScript: no (--typescript to enable)"
276
+ end
277
+ say " SVGR: #{@use_svgr ? "yes (--no-svgr to disable)" : "no (--svgr to enable)"}"
278
+ say ""
158
279
  end
159
280
 
160
281
  def update_build_script
@@ -234,18 +355,19 @@ module Superglue
234
355
 
235
356
  def install_packages
236
357
  say "Installing Superglue and friends"
237
- run "yarn add react react-dom @thoughtbot/superglue@^2.0.0-rc.1"
358
+ run "yarn add react react-dom @thoughtbot/superglue@^2.0.0-rc.3"
238
359
 
239
360
  if @use_typescript
240
- run "yarn add -D @types/react-dom @types/react @types/node @thoughtbot/candy_wrapper@0.0.4 typescript"
361
+ typescript_dev_packages = ["@types/react-dom", "@types/react", "@types/node", "@thoughtbot/candy_wrapper@0.0.4", typescript_package]
362
+ run "yarn add -D #{typescript_dev_packages.compact.join(" ")}"
241
363
  end
242
364
 
243
365
  if @validator == "deepkit"
244
366
  say "Installing Deepkit for runtime type validation"
245
- run "yarn add -D @deepkit/type @deepkit/core @deepkit/type-compiler"
367
+ run "yarn add -D @deepkit/core #{superglue_peer_packages("@deepkit/type", "@deepkit/type-compiler", "unplugin").join(" ")}"
246
368
  elsif @validator == "typia"
247
369
  say "Installing Typia and ttsc for runtime type validation"
248
- run "yarn add -D typia ttsc @ttsc/unplugin"
370
+ run "yarn add -D #{superglue_peer_packages("typia", "ttsc", "@ttsc/unplugin").join(" ")}"
249
371
  end
250
372
 
251
373
  case @bundler
@@ -259,11 +381,8 @@ module Superglue
259
381
  say "Installing esbuild-loader for JSX support"
260
382
  run "yarn add -D esbuild-loader"
261
383
  when "rollup"
262
- say "Installing rollup plugins for JSX and glob support"
263
- run "yarn add -D @rollup/plugin-babel @babel/core @babel/preset-react @rollup/plugin-commonjs @rollup/plugin-alias @rollup/plugin-replace rollup-plugin-import-meta-glob"
264
- if @use_typescript
265
- run "yarn add -D @babel/preset-typescript"
266
- end
384
+ say "Installing rollup plugins for JSX, TypeScript, and glob support"
385
+ run "yarn add -D rollup-plugin-esbuild esbuild @rollup/plugin-commonjs @rollup/plugin-alias @rollup/plugin-replace rollup-plugin-import-meta-glob"
267
386
  end
268
387
 
269
388
  say "Installing build dependencies"
@@ -338,6 +457,23 @@ module Superglue
338
457
  end
339
458
  end
340
459
 
460
+ def update_application_layout
461
+ layout_path = "app/views/layouts/application.html.erb"
462
+
463
+ inject_into_file layout_path, before: /^\s*<%= javascript_include_tag/ do
464
+ <<-ERB
465
+
466
+ <script type="text/javascript">
467
+ window.SUPERGLUE_INITIAL_PAGE_STATE=<%= render_props %>;<%# erblint:disable ErbSafety %>
468
+ </script>
469
+
470
+ ERB
471
+ end
472
+
473
+ inject_into_file layout_path, '<div id="app">', before: "<%= yield %>"
474
+ inject_into_file layout_path, "</div>", after: "<%= yield %>"
475
+ end
476
+
341
477
  def copy_ssr_files
342
478
  say "Adding ssr_context to ApplicationController"
343
479
  inject_into_file "app/controllers/application_controller.rb", after: "class ApplicationController < ActionController::Base\n" do
@@ -366,14 +502,14 @@ module Superglue
366
502
  when "rollup"
367
503
  copy_file "#{__dir__}/templates/ssr/rollup.build_ssr.config.js", "rollup.config.ssr.js"
368
504
  gsub_file "rollup.config.ssr.js", "server_rendering.jsx", "server_rendering.#{ssr_ext}"
369
- if @use_typescript
370
- gsub_file "rollup.config.ssr.js",
371
- 'presets: [["@babel/preset-react", { runtime: "automatic" }]],',
372
- 'presets: [["@babel/preset-react", { runtime: "automatic" }], "@babel/preset-typescript"],'
373
- end
374
505
  run %(npm pkg set scripts.build:ssr="rollup -c rollup.config.ssr.js")
375
506
  end
376
507
 
508
+ if @validator != "none"
509
+ say "Adding #{@validator} plugin to SSR build"
510
+ add_validator_to_ssr_build
511
+ end
512
+
377
513
  if @use_typescript
378
514
  say "Copying server_rendering.tsx"
379
515
  copy_file "#{__dir__}/templates/ssr/server_rendering.tsx", "#{app_js_path}/server_rendering.tsx"
@@ -415,6 +551,52 @@ module Superglue
415
551
  end
416
552
  end
417
553
 
554
+ def add_validator_to_ssr_build
555
+ plugin_call = (@validator == "deepkit") ? "deepkitPlugin()" : "ttscPlugin()"
556
+ dev_only_plugin = "...(process.env.NODE_ENV === 'production' ? [] : [#{plugin_call}])"
557
+ plugin_import = ssr_validator_import
558
+
559
+ case @bundler
560
+ when "esbuild"
561
+ inject_into_file "build_ssr.mjs", plugin_import, after: "const importGlobPlugin = importGlob.default\n"
562
+ inject_into_file "build_ssr.mjs", " #{dev_only_plugin},\n", after: " importGlobPlugin(),\n"
563
+ when "bun"
564
+ inject_into_file "build_ssr.js", plugin_import, after: "import { globImportPlugin } from 'bun-plugin-glob-import'\n"
565
+ gsub_file "build_ssr.js",
566
+ "plugins: [globImportPlugin()],",
567
+ "plugins: [\n globImportPlugin(),\n #{dev_only_plugin}\n ],"
568
+ when "webpack"
569
+ inject_into_file "webpack.config.ssr.js", plugin_import, after: "const webpack = require(\"webpack\")\n"
570
+ gsub_file "webpack.config.ssr.js", " })\n ]\n}", " }),\n #{dev_only_plugin}\n ]\n}"
571
+ when "rollup"
572
+ inject_into_file "rollup.config.ssr.js", plugin_import, after: "import importMetaGlob from \"rollup-plugin-import-meta-glob\"\n"
573
+ # Before esbuild: the validator rewrites the TypeScript source and
574
+ # esbuild compiles its output. Rollup runs plugins in array order.
575
+ inject_into_file "rollup.config.ssr.js", " #{dev_only_plugin},\n", before: " esbuild({ jsx: \"automatic\" }),\n"
576
+ end
577
+ end
578
+
579
+ def ssr_validator_import
580
+ case [@validator, @bundler]
581
+ when ["deepkit", "esbuild"]
582
+ "import { esbuild as deepkitPlugin } from '@thoughtbot/superglue/deepkit'\n"
583
+ when ["deepkit", "bun"]
584
+ "import { bun as deepkitPlugin } from '@thoughtbot/superglue/deepkit'\n"
585
+ when ["deepkit", "webpack"]
586
+ "const { webpack: deepkitPlugin } = require(\"@thoughtbot/superglue/deepkit\")\n"
587
+ when ["deepkit", "rollup"]
588
+ "import { rollup as deepkitPlugin } from \"@thoughtbot/superglue/deepkit\"\n"
589
+ when ["typia", "esbuild"]
590
+ "import ttsc from '@ttsc/unplugin'\nconst ttscPlugin = ttsc.esbuild\n"
591
+ when ["typia", "bun"]
592
+ "import ttscPlugin from '@ttsc/unplugin/bun'\n"
593
+ when ["typia", "webpack"]
594
+ "const ttscPlugin = require(\"@ttsc/unplugin\").default.webpack\n"
595
+ when ["typia", "rollup"]
596
+ "import ttsc from \"@ttsc/unplugin\"\nconst ttscPlugin = ttsc.rollup\n"
597
+ end
598
+ end
599
+
418
600
  def configure_svgr
419
601
  say "Configuring SVGR"
420
602
 
@@ -8,6 +8,7 @@ const config = {
8
8
  entrypoints: ['app/javascript/application.tsx'],
9
9
  outdir: 'app/assets/builds',
10
10
  sourcemap: 'external',
11
+ jsx: { runtime: 'automatic' },
11
12
  plugins: [
12
13
  globImportPlugin(),
13
14
  ...(process.env.NODE_ENV === 'production' ? [] : [deepkitPlugin()])
@@ -7,6 +7,7 @@ const config = {
7
7
  entrypoints: ['app/javascript/application.jsx'],
8
8
  outdir: 'app/assets/builds',
9
9
  sourcemap: 'external',
10
+ jsx: { runtime: 'automatic' },
10
11
  plugins: [globImportPlugin()],
11
12
  }
12
13
 
@@ -7,6 +7,7 @@ const config = {
7
7
  entrypoints: ['app/javascript/application.tsx'],
8
8
  outdir: 'app/assets/builds',
9
9
  sourcemap: 'external',
10
+ jsx: { runtime: 'automatic' },
10
11
  plugins: [globImportPlugin()],
11
12
  }
12
13
 
@@ -1,6 +1,6 @@
1
1
  import { globImportPlugin } from 'bun-plugin-glob-import'
2
- import ttsc from '@ttsc/unplugin'
3
- const ttscPlugin = ttsc.bun
2
+ // Bun's adapter is its own entry point; the main export has no `bun`.
3
+ import ttscPlugin from '@ttsc/unplugin/bun'
4
4
  import { watch } from 'fs'
5
5
 
6
6
  const isWatch = process.argv.includes('--watch')
@@ -9,6 +9,7 @@ const config = {
9
9
  entrypoints: ['app/javascript/application.tsx'],
10
10
  outdir: 'app/assets/builds',
11
11
  sourcemap: 'external',
12
+ jsx: { runtime: 'automatic' },
12
13
  plugins: [
13
14
  globImportPlugin(),
14
15
  ...(process.env.NODE_ENV === 'production' ? [] : [ttscPlugin()])
@@ -3,7 +3,7 @@ import { asObject as pages } from '../views/**/*.{tsx,jsx}'
3
3
  const pageIdentifierToPageComponent = {}
4
4
 
5
5
  for (const key in pages) {
6
- const identifier = key.split('.')[0]
6
+ const identifier = key.replace('../views/', '').split('.')[0]
7
7
  pageIdentifierToPageComponent[identifier] = pages[key].default
8
8
  }
9
9
 
@@ -3,7 +3,7 @@ import { asObject as pages } from '../views/**/*.{tsx,jsx}'
3
3
  const pageIdentifierToPageComponent: Record<string, React.ComponentType> = {}
4
4
 
5
5
  for (const key in pages) {
6
- const identifier = key.split('.')[0]
6
+ const identifier = key.replace('../views/', '').split('.')[0]
7
7
  pageIdentifierToPageComponent[identifier] = (pages[key] as { default: React.ComponentType }).default
8
8
  }
9
9
 
@@ -1,4 +1,3 @@
1
- import React from "react"
2
1
  import { createRoot, hydrateRoot } from "react-dom/client"
3
2
  import { createApp } from "@thoughtbot/superglue"
4
3
  import { buildVisitAndRemote } from "./application_visit"
@@ -27,13 +26,11 @@ if (typeof window !== "undefined" && window.SUPERGLUE_INITIAL_PAGE_STATE) {
27
26
  })
28
27
 
29
28
  const app = (
30
- <div onClick={ujs.onClick} onSubmit={ujs.onSubmit}>
31
- <Provider>
32
- <Layout>
33
- <Outlet />
34
- </Layout>
35
- </Provider>
36
- </div>
29
+ <Provider>
30
+ <Layout onClick={ujs.onClick} onSubmit={ujs.onSubmit}>
31
+ <Outlet />
32
+ </Layout>
33
+ </Provider>
37
34
  )
38
35
 
39
36
  if (appEl.hasChildNodes()) {
@@ -10,6 +10,7 @@ const buildOptions = {
10
10
  'app/javascript/application.jsx',
11
11
  ],
12
12
  bundle: true,
13
+ jsx: 'automatic',
13
14
  sourcemap: true,
14
15
  format: 'esm',
15
16
  outdir: 'app/assets/builds',
@@ -7,7 +7,7 @@
7
7
  * There is no style and structured with bare necessities. You should modify
8
8
  * these components to fit your design needs.
9
9
  */
10
- import React, { createContext, useContext, useMemo } from 'react'
10
+ import { createContext, useContext, useMemo } from 'react'
11
11
  export const ValidationContext = createContext({})
12
12
  export const useErrorMessage = (errorKey) => {
13
13
  const errors = useContext(ValidationContext)
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "compilerOptions": {
3
- "baseUrl": ".", // Usually the root of your project
3
+ "jsx": "react-jsx",
4
4
  "paths": {
5
- "@javascript/*": ["app/javascript/*"],
6
- "@views/*": ["app/views/*"]
5
+ "@javascript/*": ["./app/javascript/*"],
6
+ "@views/*": ["./app/views/*"]
7
7
  }
8
8
  }
9
9
  }
@@ -1,11 +1,10 @@
1
- import React from 'react'
2
1
  import { useAppFlash } from '@javascript/flash'
3
2
 
4
- export const Layout = ({children}) => {
3
+ export const Layout = ({children, onClick, onSubmit}) => {
5
4
  const flash = useAppFlash()
6
5
 
7
6
  return (
8
- <div>
7
+ <div onClick={onClick} onSubmit={onSubmit}>
9
8
  {flash.success && <p>{flash.success}</p>}
10
9
  {flash.notice && <p>{flash.notice}</p>}
11
10
  {flash.error && <p>{flash.error}</p>}
@@ -1,7 +1,7 @@
1
1
  import path from "path"
2
2
  import resolve from "@rollup/plugin-node-resolve"
3
3
  import commonjs from "@rollup/plugin-commonjs"
4
- import babel from "@rollup/plugin-babel"
4
+ import esbuild from "rollup-plugin-esbuild"
5
5
  import alias from "@rollup/plugin-alias"
6
6
  import importMetaGlob from "rollup-plugin-import-meta-glob"
7
7
  import { rollup as deepkitPlugin } from "@thoughtbot/superglue/deepkit"
@@ -21,17 +21,14 @@ export default {
21
21
  { find: "@views", replacement: path.resolve("app/views") }
22
22
  ]
23
23
  }),
24
- resolve({ extensions: [".ts", ".tsx", ".js", ".jsx"] }),
24
+ // @deepkit/type imports "buffer"; bundle the npm polyfill instead of
25
+ // leaving it to a Node built-in the browser does not have.
26
+ resolve({ extensions: [".ts", ".tsx", ".js", ".jsx"], preferBuiltins: false }),
25
27
  commonjs(),
26
- babel({
27
- babelHelpers: "bundled",
28
- presets: [
29
- ["@babel/preset-react", { runtime: "automatic" }],
30
- "@babel/preset-typescript"
31
- ],
32
- extensions: [".ts", ".tsx", ".js", ".jsx"]
33
- }),
28
+ // Before esbuild: it rewrites the TypeScript source, and esbuild compiles
29
+ // its output (rollup runs plugins in order and ignores `enforce`).
30
+ ...(process.env.NODE_ENV === 'production' ? [] : [deepkitPlugin()]),
31
+ esbuild({ jsx: "automatic" }),
34
32
  importMetaGlob(),
35
- ...(process.env.NODE_ENV === 'production' ? [] : [deepkitPlugin()])
36
33
  ]
37
34
  }
@@ -1,7 +1,7 @@
1
1
  import path from "path"
2
2
  import resolve from "@rollup/plugin-node-resolve"
3
3
  import commonjs from "@rollup/plugin-commonjs"
4
- import babel from "@rollup/plugin-babel"
4
+ import esbuild from "rollup-plugin-esbuild"
5
5
  import alias from "@rollup/plugin-alias"
6
6
  import importMetaGlob from "rollup-plugin-import-meta-glob"
7
7
 
@@ -22,11 +22,7 @@ export default {
22
22
  }),
23
23
  resolve({ extensions: [".js", ".jsx"] }),
24
24
  commonjs(),
25
- babel({
26
- babelHelpers: "bundled",
27
- presets: [["@babel/preset-react", { runtime: "automatic" }]],
28
- extensions: [".js", ".jsx"]
29
- }),
25
+ esbuild({ jsx: "automatic" }),
30
26
  importMetaGlob(),
31
27
  ]
32
28
  }
@@ -1,7 +1,7 @@
1
1
  import path from "path"
2
2
  import resolve from "@rollup/plugin-node-resolve"
3
3
  import commonjs from "@rollup/plugin-commonjs"
4
- import babel from "@rollup/plugin-babel"
4
+ import esbuild from "rollup-plugin-esbuild"
5
5
  import alias from "@rollup/plugin-alias"
6
6
  import importMetaGlob from "rollup-plugin-import-meta-glob"
7
7
 
@@ -22,14 +22,7 @@ export default {
22
22
  }),
23
23
  resolve({ extensions: [".ts", ".tsx", ".js", ".jsx"] }),
24
24
  commonjs(),
25
- babel({
26
- babelHelpers: "bundled",
27
- presets: [
28
- ["@babel/preset-react", { runtime: "automatic" }],
29
- "@babel/preset-typescript"
30
- ],
31
- extensions: [".ts", ".tsx", ".js", ".jsx"]
32
- }),
25
+ esbuild({ jsx: "automatic" }),
33
26
  importMetaGlob(),
34
27
  ]
35
28
  }