superglue 2.0.0.rc.3 → 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.
- checksums.yaml +4 -4
- data/lib/generators/superglue/install/install_generator.rb +191 -67
- data/lib/generators/superglue/install/templates/bun/bun.config.typia.js +2 -2
- data/lib/generators/superglue/install/templates/bun/page_to_page_mapping.js +1 -1
- data/lib/generators/superglue/install/templates/bun/page_to_page_mapping.ts +1 -1
- data/lib/generators/superglue/install/templates/js/application.jsx +5 -7
- data/lib/generators/superglue/install/templates/js/jsconfig.json +2 -3
- data/lib/generators/superglue/install/templates/js/layout.jsx +2 -2
- data/lib/generators/superglue/install/templates/rollup/rollup.config.deepkit.js +8 -11
- data/lib/generators/superglue/install/templates/rollup/rollup.config.js +2 -6
- data/lib/generators/superglue/install/templates/rollup/rollup.config.ts.js +2 -9
- data/lib/generators/superglue/install/templates/rollup/rollup.config.typia.js +5 -10
- data/lib/generators/superglue/install/templates/ssr/rollup.build_ssr.config.js +6 -7
- data/lib/generators/superglue/install/templates/ssr/server_rendering.jsx +6 -3
- data/lib/generators/superglue/install/templates/ssr/server_rendering.tsx +5 -2
- data/lib/generators/superglue/install/templates/ts/application.tsx +5 -7
- data/lib/generators/superglue/install/templates/ts/flash.ts +3 -0
- data/lib/generators/superglue/install/templates/ts/layout.tsx +3 -2
- data/lib/generators/superglue/install/templates/ts/tsconfig.json +2 -3
- data/lib/generators/superglue/scaffold_controller/scaffold_controller_generator.rb +12 -12
- data/lib/generators/superglue/view_collection/templates/js/edit.html.jsx +2 -3
- data/lib/generators/superglue/view_collection/templates/js/index.html.jsx +3 -3
- data/lib/generators/superglue/view_collection/templates/js/new.html.jsx +2 -3
- data/lib/generators/superglue/view_collection/templates/js/show.html.jsx +2 -3
- data/lib/generators/superglue/view_collection/templates/ts/edit.html.tsx +2 -3
- data/lib/generators/superglue/view_collection/templates/ts/index.html.tsx +3 -3
- data/lib/generators/superglue/view_collection/templates/ts/new.html.tsx +2 -3
- data/lib/generators/superglue/view_collection/templates/ts/show.html.tsx +3 -4
- data/lib/generators/superglue/view_collection/view_collection_generator.rb +0 -34
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: aff506e09c15008bbc37ae8c5e14ce6c7ab0520956fd0f31653a3deb90a6e674
|
|
4
|
+
data.tar.gz: 9a3f7534e42d41ae13e08f496debbc3d692d085f99dc36875f6b047956a1eda4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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,31 +10,33 @@ module Superglue
|
|
|
9
10
|
|
|
10
11
|
class_option :typescript,
|
|
11
12
|
type: :boolean,
|
|
12
|
-
|
|
13
|
-
desc: "Use TypeScript.
|
|
13
|
+
default: true,
|
|
14
|
+
desc: "Use TypeScript. Pass --no-typescript for JavaScript."
|
|
14
15
|
|
|
15
16
|
class_option :bundler,
|
|
16
17
|
type: :string,
|
|
17
18
|
required: false,
|
|
18
|
-
desc: "JavaScript bundler to use (esbuild, bun, rollup, webpack).
|
|
19
|
+
desc: "JavaScript bundler to use (esbuild, bun, rollup, webpack). Defaults to the detected bundler."
|
|
19
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.
|
|
20
23
|
class_option :validator,
|
|
21
24
|
type: :string,
|
|
22
|
-
|
|
23
|
-
desc: "Runtime type validator to use (deepkit, typia
|
|
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."
|
|
24
29
|
|
|
25
30
|
class_option :svgr,
|
|
26
31
|
type: :boolean,
|
|
27
|
-
|
|
28
|
-
desc: "Enable SVGR to import SVGs as React components.
|
|
32
|
+
default: true,
|
|
33
|
+
desc: "Enable SVGR to import SVGs as React components. Pass --no-svgr to disable."
|
|
29
34
|
|
|
30
35
|
def create_files
|
|
31
36
|
remove_file "#{app_js_path}/application.js"
|
|
32
37
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
@validator = @use_typescript ? ask_validator : "none"
|
|
36
|
-
@use_svgr = ask_svgr
|
|
38
|
+
resolve_choices
|
|
39
|
+
say_choices
|
|
37
40
|
|
|
38
41
|
if @use_typescript
|
|
39
42
|
copy_ts_files
|
|
@@ -59,6 +62,9 @@ module Superglue
|
|
|
59
62
|
say "Copying stream.json.props"
|
|
60
63
|
copy_file "#{__dir__}/templates/stream.json.props", "app/views/layouts/stream.json.props"
|
|
61
64
|
|
|
65
|
+
say "Adding initial page state and #app container to application.html.erb"
|
|
66
|
+
update_application_layout
|
|
67
|
+
|
|
62
68
|
say "Adding required member methods to ApplicationRecord"
|
|
63
69
|
add_member_methods
|
|
64
70
|
|
|
@@ -101,20 +107,33 @@ module Superglue
|
|
|
101
107
|
false
|
|
102
108
|
end
|
|
103
109
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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
|
|
113
124
|
|
|
114
|
-
|
|
125
|
+
def resolve_bundler
|
|
126
|
+
requested_bundler = options["bundler"]
|
|
127
|
+
detected_bundler = detect_bundler
|
|
115
128
|
|
|
116
|
-
if
|
|
117
|
-
|
|
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
|
|
118
137
|
else
|
|
119
138
|
say "No JavaScript bundler detected.", :red
|
|
120
139
|
say "Install one first via jsbundling-rails:"
|
|
@@ -122,48 +141,141 @@ module Superglue
|
|
|
122
141
|
say "See: https://github.com/rails/jsbundling-rails"
|
|
123
142
|
raise Thor::Error, "No bundler found. Install one via jsbundling-rails and re-run this generator."
|
|
124
143
|
end
|
|
144
|
+
end
|
|
145
|
+
|
|
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
|
|
125
153
|
|
|
126
|
-
|
|
154
|
+
version.to_s[/\d+/]&.to_i
|
|
127
155
|
end
|
|
128
156
|
|
|
129
|
-
def
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
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"]
|
|
133
162
|
end
|
|
163
|
+
rescue JSON::ParserError
|
|
164
|
+
nil
|
|
165
|
+
end
|
|
134
166
|
|
|
135
|
-
|
|
136
|
-
|
|
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
|
|
137
175
|
end
|
|
138
176
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
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
|
|
147
193
|
end
|
|
194
|
+
end
|
|
148
195
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
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
|
|
155
218
|
end
|
|
156
219
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
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
|
|
230
|
+
end
|
|
231
|
+
|
|
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"
|
|
161
266
|
end
|
|
162
267
|
|
|
163
268
|
say ""
|
|
164
|
-
say "
|
|
165
|
-
say "
|
|
166
|
-
|
|
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 ""
|
|
167
279
|
end
|
|
168
280
|
|
|
169
281
|
def update_build_script
|
|
@@ -243,18 +355,19 @@ module Superglue
|
|
|
243
355
|
|
|
244
356
|
def install_packages
|
|
245
357
|
say "Installing Superglue and friends"
|
|
246
|
-
run "yarn add react react-dom @thoughtbot/superglue@^2.0.0-rc.
|
|
358
|
+
run "yarn add react react-dom @thoughtbot/superglue@^2.0.0-rc.3"
|
|
247
359
|
|
|
248
360
|
if @use_typescript
|
|
249
|
-
|
|
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(" ")}"
|
|
250
363
|
end
|
|
251
364
|
|
|
252
365
|
if @validator == "deepkit"
|
|
253
366
|
say "Installing Deepkit for runtime type validation"
|
|
254
|
-
run "yarn add -D @deepkit/
|
|
367
|
+
run "yarn add -D @deepkit/core #{superglue_peer_packages("@deepkit/type", "@deepkit/type-compiler", "unplugin").join(" ")}"
|
|
255
368
|
elsif @validator == "typia"
|
|
256
369
|
say "Installing Typia and ttsc for runtime type validation"
|
|
257
|
-
run "yarn add -D typia ttsc @ttsc/unplugin"
|
|
370
|
+
run "yarn add -D #{superglue_peer_packages("typia", "ttsc", "@ttsc/unplugin").join(" ")}"
|
|
258
371
|
end
|
|
259
372
|
|
|
260
373
|
case @bundler
|
|
@@ -268,11 +381,8 @@ module Superglue
|
|
|
268
381
|
say "Installing esbuild-loader for JSX support"
|
|
269
382
|
run "yarn add -D esbuild-loader"
|
|
270
383
|
when "rollup"
|
|
271
|
-
say "Installing rollup plugins for JSX and glob support"
|
|
272
|
-
run "yarn add -D
|
|
273
|
-
if @use_typescript
|
|
274
|
-
run "yarn add -D @babel/preset-typescript"
|
|
275
|
-
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"
|
|
276
386
|
end
|
|
277
387
|
|
|
278
388
|
say "Installing build dependencies"
|
|
@@ -347,6 +457,23 @@ module Superglue
|
|
|
347
457
|
end
|
|
348
458
|
end
|
|
349
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
|
+
|
|
350
477
|
def copy_ssr_files
|
|
351
478
|
say "Adding ssr_context to ApplicationController"
|
|
352
479
|
inject_into_file "app/controllers/application_controller.rb", after: "class ApplicationController < ActionController::Base\n" do
|
|
@@ -375,11 +502,6 @@ module Superglue
|
|
|
375
502
|
when "rollup"
|
|
376
503
|
copy_file "#{__dir__}/templates/ssr/rollup.build_ssr.config.js", "rollup.config.ssr.js"
|
|
377
504
|
gsub_file "rollup.config.ssr.js", "server_rendering.jsx", "server_rendering.#{ssr_ext}"
|
|
378
|
-
if @use_typescript
|
|
379
|
-
gsub_file "rollup.config.ssr.js",
|
|
380
|
-
'presets: [["@babel/preset-react", { runtime: "automatic" }]],',
|
|
381
|
-
'presets: [["@babel/preset-react", { runtime: "automatic" }], "@babel/preset-typescript"],'
|
|
382
|
-
end
|
|
383
505
|
run %(npm pkg set scripts.build:ssr="rollup -c rollup.config.ssr.js")
|
|
384
506
|
end
|
|
385
507
|
|
|
@@ -448,7 +570,9 @@ module Superglue
|
|
|
448
570
|
gsub_file "webpack.config.ssr.js", " })\n ]\n}", " }),\n #{dev_only_plugin}\n ]\n}"
|
|
449
571
|
when "rollup"
|
|
450
572
|
inject_into_file "rollup.config.ssr.js", plugin_import, after: "import importMetaGlob from \"rollup-plugin-import-meta-glob\"\n"
|
|
451
|
-
|
|
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"
|
|
452
576
|
end
|
|
453
577
|
end
|
|
454
578
|
|
|
@@ -465,7 +589,7 @@ module Superglue
|
|
|
465
589
|
when ["typia", "esbuild"]
|
|
466
590
|
"import ttsc from '@ttsc/unplugin'\nconst ttscPlugin = ttsc.esbuild\n"
|
|
467
591
|
when ["typia", "bun"]
|
|
468
|
-
"import
|
|
592
|
+
"import ttscPlugin from '@ttsc/unplugin/bun'\n"
|
|
469
593
|
when ["typia", "webpack"]
|
|
470
594
|
"const ttscPlugin = require(\"@ttsc/unplugin\").default.webpack\n"
|
|
471
595
|
when ["typia", "rollup"]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { globImportPlugin } from 'bun-plugin-glob-import'
|
|
2
|
-
|
|
3
|
-
|
|
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')
|
|
@@ -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
|
|
|
@@ -26,13 +26,11 @@ if (typeof window !== "undefined" && window.SUPERGLUE_INITIAL_PAGE_STATE) {
|
|
|
26
26
|
})
|
|
27
27
|
|
|
28
28
|
const app = (
|
|
29
|
-
<
|
|
30
|
-
<
|
|
31
|
-
<
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
</Provider>
|
|
35
|
-
</div>
|
|
29
|
+
<Provider>
|
|
30
|
+
<Layout onClick={ujs.onClick} onSubmit={ujs.onSubmit}>
|
|
31
|
+
<Outlet />
|
|
32
|
+
</Layout>
|
|
33
|
+
</Provider>
|
|
36
34
|
)
|
|
37
35
|
|
|
38
36
|
if (appEl.hasChildNodes()) {
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"compilerOptions": {
|
|
3
3
|
"jsx": "react-jsx",
|
|
4
|
-
"baseUrl": ".", // Usually the root of your project
|
|
5
4
|
"paths": {
|
|
6
|
-
"@javascript/*": ["app/javascript/*"],
|
|
7
|
-
"@views/*": ["app/views/*"]
|
|
5
|
+
"@javascript/*": ["./app/javascript/*"],
|
|
6
|
+
"@views/*": ["./app/views/*"]
|
|
8
7
|
}
|
|
9
8
|
}
|
|
10
9
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { useAppFlash } from '@javascript/flash'
|
|
2
2
|
|
|
3
|
-
export const Layout = ({children}) => {
|
|
3
|
+
export const Layout = ({children, onClick, onSubmit}) => {
|
|
4
4
|
const flash = useAppFlash()
|
|
5
5
|
|
|
6
6
|
return (
|
|
7
|
-
<div>
|
|
7
|
+
<div onClick={onClick} onSubmit={onSubmit}>
|
|
8
8
|
{flash.success && <p>{flash.success}</p>}
|
|
9
9
|
{flash.notice && <p>{flash.notice}</p>}
|
|
10
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
|
|
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
|
-
|
|
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
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
}
|
|
@@ -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
|
|
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 ttsc from "@ttsc/unplugin"
|
|
@@ -24,15 +24,10 @@ export default {
|
|
|
24
24
|
}),
|
|
25
25
|
resolve({ extensions: [".ts", ".tsx", ".js", ".jsx"] }),
|
|
26
26
|
commonjs(),
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
"@babel/preset-typescript"
|
|
32
|
-
],
|
|
33
|
-
extensions: [".ts", ".tsx", ".js", ".jsx"]
|
|
34
|
-
}),
|
|
27
|
+
// Before esbuild: it rewrites the TypeScript source, and esbuild compiles
|
|
28
|
+
// its output (rollup runs plugins in order and ignores `enforce`).
|
|
29
|
+
...(process.env.NODE_ENV === 'production' ? [] : [ttscPlugin()]),
|
|
30
|
+
esbuild({ jsx: "automatic" }),
|
|
35
31
|
importMetaGlob(),
|
|
36
|
-
...(process.env.NODE_ENV === 'production' ? [] : [ttscPlugin()])
|
|
37
32
|
]
|
|
38
33
|
}
|
|
@@ -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
|
|
4
|
+
import esbuild from "rollup-plugin-esbuild"
|
|
5
5
|
import alias from "@rollup/plugin-alias"
|
|
6
6
|
import replace from "@rollup/plugin-replace"
|
|
7
7
|
import importMetaGlob from "rollup-plugin-import-meta-glob"
|
|
@@ -29,14 +29,13 @@ export default {
|
|
|
29
29
|
resolve({
|
|
30
30
|
extensions: [".js", ".jsx", ".ts", ".tsx"],
|
|
31
31
|
browser: true,
|
|
32
|
-
exportConditions: ["browser"]
|
|
32
|
+
exportConditions: ["browser"],
|
|
33
|
+
// Bundle npm polyfills (e.g. "buffer", imported by @deepkit/type)
|
|
34
|
+
// rather than Node built-ins, which MiniRacer does not have.
|
|
35
|
+
preferBuiltins: false
|
|
33
36
|
}),
|
|
34
37
|
commonjs(),
|
|
35
|
-
|
|
36
|
-
babelHelpers: "bundled",
|
|
37
|
-
presets: [["@babel/preset-react", { runtime: "automatic" }]],
|
|
38
|
-
extensions: [".js", ".jsx", ".ts", ".tsx"]
|
|
39
|
-
}),
|
|
38
|
+
esbuild({ jsx: "automatic" }),
|
|
40
39
|
importMetaGlob(),
|
|
41
40
|
]
|
|
42
41
|
}
|
|
@@ -2,10 +2,11 @@ import { createApp } from "@thoughtbot/superglue";
|
|
|
2
2
|
import { buildVisitAndRemote } from "./application_visit";
|
|
3
3
|
import { pageIdentifierToPageComponent } from "./page_to_page_mapping";
|
|
4
4
|
import { renderToString } from "react-dom/server";
|
|
5
|
+
import { Layout } from "./components";
|
|
5
6
|
|
|
6
7
|
setHumidRenderer((json, baseUrl, path) => {
|
|
7
8
|
const initialState = JSON.parse(json);
|
|
8
|
-
const { Provider, Outlet } = createApp({
|
|
9
|
+
const { Provider, Outlet, ujs } = createApp({
|
|
9
10
|
baseUrl,
|
|
10
11
|
initialPage: initialState,
|
|
11
12
|
path,
|
|
@@ -15,7 +16,9 @@ setHumidRenderer((json, baseUrl, path) => {
|
|
|
15
16
|
|
|
16
17
|
return renderToString(
|
|
17
18
|
<Provider>
|
|
18
|
-
<
|
|
19
|
-
|
|
19
|
+
<Layout onClick={ujs.onClick} onSubmit={ujs.onSubmit}>
|
|
20
|
+
<Outlet />
|
|
21
|
+
</Layout>
|
|
22
|
+
</Provider>
|
|
20
23
|
);
|
|
21
24
|
});
|
|
@@ -2,6 +2,7 @@ import { createApp } from "@thoughtbot/superglue";
|
|
|
2
2
|
import { buildVisitAndRemote } from "./application_visit";
|
|
3
3
|
import { pageIdentifierToPageComponent } from "./page_to_page_mapping";
|
|
4
4
|
import { renderToString } from "react-dom/server";
|
|
5
|
+
import { Layout } from "./components";
|
|
5
6
|
|
|
6
7
|
declare function setHumidRenderer(
|
|
7
8
|
fn: (json: string, baseUrl: string, path: string) => string,
|
|
@@ -9,7 +10,7 @@ declare function setHumidRenderer(
|
|
|
9
10
|
|
|
10
11
|
setHumidRenderer((json, baseUrl, path) => {
|
|
11
12
|
const initialState = JSON.parse(json);
|
|
12
|
-
const { Provider, Outlet } = createApp({
|
|
13
|
+
const { Provider, Outlet, ujs } = createApp({
|
|
13
14
|
baseUrl,
|
|
14
15
|
initialPage: initialState,
|
|
15
16
|
path,
|
|
@@ -19,7 +20,9 @@ setHumidRenderer((json, baseUrl, path) => {
|
|
|
19
20
|
|
|
20
21
|
return renderToString(
|
|
21
22
|
<Provider>
|
|
22
|
-
<
|
|
23
|
+
<Layout onClick={ujs.onClick} onSubmit={ujs.onSubmit}>
|
|
24
|
+
<Outlet />
|
|
25
|
+
</Layout>
|
|
23
26
|
</Provider>,
|
|
24
27
|
);
|
|
25
28
|
});
|
|
@@ -31,13 +31,11 @@ if (typeof window !== "undefined" && window.SUPERGLUE_INITIAL_PAGE_STATE) {
|
|
|
31
31
|
});
|
|
32
32
|
|
|
33
33
|
const app = (
|
|
34
|
-
<
|
|
35
|
-
<
|
|
36
|
-
<
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
</Provider>
|
|
40
|
-
</div>
|
|
34
|
+
<Provider>
|
|
35
|
+
<Layout onClick={ujs.onClick} onSubmit={ujs.onSubmit}>
|
|
36
|
+
<Outlet />
|
|
37
|
+
</Layout>
|
|
38
|
+
</Provider>
|
|
41
39
|
);
|
|
42
40
|
|
|
43
41
|
if (appEl.hasChildNodes()) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { useFlash } from "@thoughtbot/superglue";
|
|
2
|
+
import type { ValidationErrors } from "@thoughtbot/candy_wrapper";
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Customize this type to match the flash keys your application uses.
|
|
@@ -8,6 +9,8 @@ export type AppFlash = {
|
|
|
8
9
|
notice?: string;
|
|
9
10
|
alert?: string;
|
|
10
11
|
error?: string;
|
|
12
|
+
// Form errors the scaffold stores under e.g. flash["postFormErrors"]
|
|
13
|
+
[key: `${string}FormErrors`]: ValidationErrors | undefined;
|
|
11
14
|
[key: string]: unknown;
|
|
12
15
|
};
|
|
13
16
|
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import type { ReactNode } from 'react'
|
|
2
|
+
import type { Handlers } from '@thoughtbot/superglue'
|
|
2
3
|
import { useAppFlash } from '@javascript/flash'
|
|
3
4
|
|
|
4
|
-
export const Layout = ({children}: {children: ReactNode}) => {
|
|
5
|
+
export const Layout = ({children, onClick, onSubmit}: {children: ReactNode} & Partial<Handlers>) => {
|
|
5
6
|
const flash = useAppFlash()
|
|
6
7
|
|
|
7
8
|
return (
|
|
8
|
-
<div>
|
|
9
|
+
<div onClick={onClick} onSubmit={onSubmit}>
|
|
9
10
|
{flash.success && <p>{flash.success}</p>}
|
|
10
11
|
{flash.notice && <p>{flash.notice}</p>}
|
|
11
12
|
{flash.error && <p>{flash.error}</p>}
|
|
@@ -14,10 +14,9 @@
|
|
|
14
14
|
"esModuleInterop": true,
|
|
15
15
|
"noEmit": true,
|
|
16
16
|
"allowImportingTsExtensions": true,
|
|
17
|
-
"baseUrl": ".", // Usually the root of your project
|
|
18
17
|
"paths": {
|
|
19
|
-
"@javascript/*": ["app/javascript/*"],
|
|
20
|
-
"@views/*": ["app/views/*"]
|
|
18
|
+
"@javascript/*": ["./app/javascript/*"],
|
|
19
|
+
"@views/*": ["./app/views/*"]
|
|
21
20
|
},
|
|
22
21
|
"types": ["node"]
|
|
23
22
|
},
|
|
@@ -18,7 +18,7 @@ module Superglue
|
|
|
18
18
|
|
|
19
19
|
class_option :helper, type: :boolean
|
|
20
20
|
class_option :orm, banner: "NAME", type: :string, required: true,
|
|
21
|
-
|
|
21
|
+
desc: "ORM to generate the controller for"
|
|
22
22
|
|
|
23
23
|
class_option :skip_routes, type: :boolean, desc: "Don't add routes to config/routes.rb."
|
|
24
24
|
|
|
@@ -46,17 +46,17 @@ module Superglue
|
|
|
46
46
|
|
|
47
47
|
private
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
49
|
+
def permitted_params
|
|
50
|
+
attachments, others = attributes_names.partition { |name| attachments?(name) }
|
|
51
|
+
params = others.map { |name| ":#{name}" }
|
|
52
|
+
params += attachments.map { |name| "#{name}: []" }
|
|
53
|
+
params.join(", ")
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def attachments?(name)
|
|
57
|
+
attribute = attributes.find { |attr| attr.name == name }
|
|
58
|
+
attribute&.attachments?
|
|
59
|
+
end
|
|
60
60
|
end
|
|
61
61
|
end
|
|
62
62
|
end
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Form,
|
|
3
|
-
Layout,
|
|
4
3
|
<%- attributes.each do |attr| -%>
|
|
5
4
|
<%= js_component(attr)%>,
|
|
6
5
|
<%- end -%>
|
|
@@ -25,7 +24,7 @@ export default function <%= js_plural_table_name(:upper) %>Edit() {
|
|
|
25
24
|
const validationErrors = flash["<%= js_singular_table_name%>FormErrors"]
|
|
26
25
|
|
|
27
26
|
return (
|
|
28
|
-
|
|
27
|
+
<>
|
|
29
28
|
<Form {...form} extras={extras} validationErrors={validationErrors} data-sg-visit>
|
|
30
29
|
<%- attributes.each do |attr| -%>
|
|
31
30
|
<<%= js_component(attr)%> {...inputs.<%= attr.column_name.camelize(:lower)%>} label="<%= attr.column_name.humanize %>" errorKey="<%= attr.column_name %>" />
|
|
@@ -35,6 +34,6 @@ export default function <%= js_plural_table_name(:upper) %>Edit() {
|
|
|
35
34
|
|
|
36
35
|
<a href={<%= js_singular_table_name %>Path} data-sg-visit>Show</a>
|
|
37
36
|
<a href={<%= js_plural_table_name %>Path} data-sg-visit>Back</a>
|
|
38
|
-
|
|
37
|
+
</>
|
|
39
38
|
)
|
|
40
39
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Form
|
|
1
|
+
import { Form } from '@javascript/components'
|
|
2
2
|
import { useContent } from '@thoughtbot/superglue'
|
|
3
3
|
|
|
4
4
|
export default function <%= js_plural_table_name(:upper) %>Index() {
|
|
@@ -37,7 +37,7 @@ export default function <%= js_plural_table_name(:upper) %>Index() {
|
|
|
37
37
|
})
|
|
38
38
|
|
|
39
39
|
return (
|
|
40
|
-
|
|
40
|
+
<>
|
|
41
41
|
<h1><%= js_plural_table_name(:upper) %></h1>
|
|
42
42
|
|
|
43
43
|
<table>
|
|
@@ -56,6 +56,6 @@ export default function <%= js_plural_table_name(:upper) %>Index() {
|
|
|
56
56
|
</table>
|
|
57
57
|
<br />
|
|
58
58
|
<a href={new<%= js_singular_table_name(:upper) %>Path} data-sg-visit>New <%= singular_table_name.humanize %></a>
|
|
59
|
-
|
|
59
|
+
</>
|
|
60
60
|
)
|
|
61
61
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Form,
|
|
3
|
-
Layout,
|
|
4
3
|
<%- attributes.each do |attr| -%>
|
|
5
4
|
<%= js_component(attr)%>,
|
|
6
5
|
<%- end -%>
|
|
@@ -24,7 +23,7 @@ export default function <%= js_plural_table_name(:upper) %>New() {
|
|
|
24
23
|
const validationErrors = flash["<%= js_singular_table_name%>FormErrors"]
|
|
25
24
|
|
|
26
25
|
return (
|
|
27
|
-
|
|
26
|
+
<>
|
|
28
27
|
<Form {...form} extras={extras} validationErrors={validationErrors} data-sg-visit>
|
|
29
28
|
<%- attributes.each do |attr| -%>
|
|
30
29
|
<<%= js_component(attr)%> {...inputs.<%= attr.column_name.camelize(:lower)%>} label="<%= attr.column_name.humanize %>" errorKey="<%= attr.column_name %>" />
|
|
@@ -33,6 +32,6 @@ export default function <%= js_plural_table_name(:upper) %>New() {
|
|
|
33
32
|
</Form>
|
|
34
33
|
|
|
35
34
|
<a href={<%= js_plural_table_name %>Path} data-sg-visit>Back</a>
|
|
36
|
-
|
|
35
|
+
</>
|
|
37
36
|
)
|
|
38
37
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { Layout } from '@javascript/components'
|
|
2
1
|
import { useContent } from '@thoughtbot/superglue'
|
|
3
2
|
|
|
4
3
|
export default function <%= js_plural_table_name(:upper) %>Show() {
|
|
@@ -11,7 +10,7 @@ export default function <%= js_plural_table_name(:upper) %>Show() {
|
|
|
11
10
|
} = useContent()
|
|
12
11
|
|
|
13
12
|
return (
|
|
14
|
-
|
|
13
|
+
<>
|
|
15
14
|
<%- showable_attributes.each do |attr| -%>
|
|
16
15
|
<p>
|
|
17
16
|
<strong><%= attr.column_name.humanize %>:</strong>
|
|
@@ -20,6 +19,6 @@ export default function <%= js_plural_table_name(:upper) %>Show() {
|
|
|
20
19
|
<%- end -%>
|
|
21
20
|
<a href={ edit<%= js_singular_table_name(:upper) %>Path } data-sg-visit>Edit</a>
|
|
22
21
|
<a href={ <%= js_plural_table_name %>Path } data-sg-visit>Back</a>
|
|
23
|
-
|
|
22
|
+
</>
|
|
24
23
|
)
|
|
25
24
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Form,
|
|
3
3
|
FormProps,
|
|
4
|
-
Layout,
|
|
5
4
|
<%- attributes.each do |attr| -%>
|
|
6
5
|
<%= js_component(attr)%>,
|
|
7
6
|
Rails<%= js_component(attr)%>Props,
|
|
@@ -39,7 +38,7 @@ export default function <%= js_plural_table_name(:upper) %>Edit() {
|
|
|
39
38
|
const validationErrors = flash["<%= js_singular_table_name%>FormErrors"]
|
|
40
39
|
|
|
41
40
|
return (
|
|
42
|
-
|
|
41
|
+
<>
|
|
43
42
|
<Form {...form} extras={extras} validationErrors={validationErrors} data-sg-visit>
|
|
44
43
|
<%- attributes.each do |attr| -%>
|
|
45
44
|
<<%= js_component(attr)%> {...inputs.<%= attr.column_name.camelize(:lower)%>} label="<%= attr.column_name.humanize %>" errorKey="<%= attr.column_name %>" />
|
|
@@ -49,6 +48,6 @@ export default function <%= js_plural_table_name(:upper) %>Edit() {
|
|
|
49
48
|
|
|
50
49
|
<a href={<%= js_singular_table_name %>Path} data-sg-visit>Show</a>
|
|
51
50
|
<a href={<%= js_plural_table_name %>Path} data-sg-visit>Back</a>
|
|
52
|
-
|
|
51
|
+
</>
|
|
53
52
|
)
|
|
54
53
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Form, FormProps
|
|
1
|
+
import { Form, FormProps } from '@javascript/components'
|
|
2
2
|
import { useContent } from '@thoughtbot/superglue'
|
|
3
3
|
|
|
4
4
|
type ContentProps = {
|
|
@@ -52,7 +52,7 @@ export default function <%= js_plural_table_name(:upper) %>Index() {
|
|
|
52
52
|
})
|
|
53
53
|
|
|
54
54
|
return (
|
|
55
|
-
|
|
55
|
+
<>
|
|
56
56
|
<h1><%= js_plural_table_name(:upper) %></h1>
|
|
57
57
|
|
|
58
58
|
<table>
|
|
@@ -71,6 +71,6 @@ export default function <%= js_plural_table_name(:upper) %>Index() {
|
|
|
71
71
|
</table>
|
|
72
72
|
<br />
|
|
73
73
|
<a href={new<%= js_singular_table_name(:upper) %>Path} data-sg-visit>New <%= singular_table_name.humanize %></a>
|
|
74
|
-
|
|
74
|
+
</>
|
|
75
75
|
)
|
|
76
76
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Form,
|
|
3
3
|
FormProps,
|
|
4
|
-
Layout,
|
|
5
4
|
<%- attributes.each do |attr| -%>
|
|
6
5
|
<%= js_component(attr)%>,
|
|
7
6
|
Rails<%= js_component(attr)%>Props,
|
|
@@ -36,7 +35,7 @@ export default function <%= js_plural_table_name(:upper) %>New() {
|
|
|
36
35
|
const validationErrors = flash["<%= js_singular_table_name%>FormErrors"]
|
|
37
36
|
|
|
38
37
|
return (
|
|
39
|
-
|
|
38
|
+
<>
|
|
40
39
|
<Form {...form} extras={extras} validationErrors={validationErrors} data-sg-visit>
|
|
41
40
|
<%- attributes.each do |attr| -%>
|
|
42
41
|
<<%= js_component(attr)%> {...inputs.<%= attr.column_name.camelize(:lower)%>} label="<%= attr.column_name.humanize %>" errorKey="<%= attr.column_name %>" />
|
|
@@ -45,6 +44,6 @@ export default function <%= js_plural_table_name(:upper) %>New() {
|
|
|
45
44
|
</Form>
|
|
46
45
|
|
|
47
46
|
<a href={<%= js_plural_table_name %>Path} data-sg-visit>Back</a>
|
|
48
|
-
|
|
47
|
+
</>
|
|
49
48
|
)
|
|
50
49
|
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { Layout } from '@javascript/components'
|
|
2
1
|
import { useContent } from '@thoughtbot/superglue'
|
|
3
2
|
|
|
4
3
|
type ContentProps = {
|
|
5
|
-
id:
|
|
4
|
+
id: number
|
|
6
5
|
<%- attributes.each do |attr| -%>
|
|
7
6
|
<%= attr.column_name.camelize(:lower)%>: <%= json_mappable_type(attr)%>
|
|
8
7
|
<%- end -%>
|
|
@@ -22,7 +21,7 @@ export default function <%= js_plural_table_name(:upper) %>Show() {
|
|
|
22
21
|
} = useContent<ContentProps>()
|
|
23
22
|
|
|
24
23
|
return (
|
|
25
|
-
|
|
24
|
+
<>
|
|
26
25
|
<%- showable_attributes.each do |attr| -%>
|
|
27
26
|
<p>
|
|
28
27
|
<strong><%= attr.column_name.humanize %>:</strong>
|
|
@@ -31,6 +30,6 @@ export default function <%= js_plural_table_name(:upper) %>Show() {
|
|
|
31
30
|
<%- end -%>
|
|
32
31
|
<a href={ edit<%= js_singular_table_name(:upper) %>Path } data-sg-visit>Edit</a>
|
|
33
32
|
<a href={ <%= js_plural_table_name %>Path } data-sg-visit>Back</a>
|
|
34
|
-
|
|
33
|
+
</>
|
|
35
34
|
)
|
|
36
35
|
}
|
|
@@ -43,32 +43,6 @@ module Superglue
|
|
|
43
43
|
end
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
-
def append_mapping
|
|
47
|
-
available_views.each do |action|
|
|
48
|
-
app_js = if use_typescript?
|
|
49
|
-
"#{app_js_path}/page_to_page_mapping.ts"
|
|
50
|
-
else
|
|
51
|
-
"#{app_js_path}/page_to_page_mapping.js"
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
component_name = [plural_table_name, action].map(&:camelcase).join
|
|
55
|
-
|
|
56
|
-
js_ext = use_typescript? ? "html.tsx" : "html.jsx"
|
|
57
|
-
|
|
58
|
-
if match_file(app_js, /pageIdentifierToPageComponent = {$/)
|
|
59
|
-
prepend_to_file app_js do
|
|
60
|
-
"import #{component_name} from '#{view_path}/#{controller_file_path}/#{action}.#{js_ext}'\n"
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
inject_into_file app_js, after: /pageIdentifierToPageComponent = {$/ do
|
|
64
|
-
"\n '#{[controller_file_path, action].join("/")}': #{component_name},"
|
|
65
|
-
end
|
|
66
|
-
else
|
|
67
|
-
say "Skipping appending to #{app_js}, you may be using a bundler that supports globing."
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
|
|
72
46
|
protected
|
|
73
47
|
|
|
74
48
|
def use_typescript?
|
|
@@ -131,14 +105,6 @@ module Superglue
|
|
|
131
105
|
%w[index edit show new]
|
|
132
106
|
end
|
|
133
107
|
|
|
134
|
-
def view_path
|
|
135
|
-
"@views"
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
def app_js_path
|
|
139
|
-
"app/javascript"
|
|
140
|
-
end
|
|
141
|
-
|
|
142
108
|
attr_reader :action_name
|
|
143
109
|
|
|
144
110
|
def attributes_names
|