plutonium 0.33.1 → 0.34.0

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 (143) hide show
  1. checksums.yaml +4 -4
  2. data/# Plutonium: The pre-alpha demo.md +4 -2
  3. data/.claude/skills/assets/SKILL.md +416 -0
  4. data/.claude/skills/connect-resource/SKILL.md +112 -0
  5. data/.claude/skills/controller/SKILL.md +302 -0
  6. data/.claude/skills/create-resource/SKILL.md +240 -0
  7. data/.claude/skills/definition/SKILL.md +218 -0
  8. data/.claude/skills/definition-actions/SKILL.md +386 -0
  9. data/.claude/skills/definition-fields/SKILL.md +474 -0
  10. data/.claude/skills/definition-query/SKILL.md +334 -0
  11. data/.claude/skills/forms/SKILL.md +439 -0
  12. data/.claude/skills/installation/SKILL.md +300 -0
  13. data/.claude/skills/interaction/SKILL.md +382 -0
  14. data/.claude/skills/model/SKILL.md +267 -0
  15. data/.claude/skills/model-features/SKILL.md +286 -0
  16. data/.claude/skills/nested-resources/SKILL.md +274 -0
  17. data/.claude/skills/package/SKILL.md +191 -0
  18. data/.claude/skills/policy/SKILL.md +352 -0
  19. data/.claude/skills/portal/SKILL.md +400 -0
  20. data/.claude/skills/resource/SKILL.md +281 -0
  21. data/.claude/skills/rodauth/SKILL.md +452 -0
  22. data/.claude/skills/views/SKILL.md +563 -0
  23. data/Appraisals +46 -4
  24. data/CHANGELOG.md +32 -1
  25. data/app/assets/plutonium.css +2 -2
  26. data/config/brakeman.ignore +239 -0
  27. data/config/initializers/action_policy.rb +1 -1
  28. data/docs/.vitepress/config.ts +132 -47
  29. data/docs/concepts/architecture.md +226 -0
  30. data/docs/concepts/auto-detection.md +254 -0
  31. data/docs/concepts/index.md +61 -0
  32. data/docs/concepts/packages-portals.md +304 -0
  33. data/docs/concepts/resources.md +224 -0
  34. data/docs/cookbook/blog.md +412 -0
  35. data/docs/cookbook/index.md +289 -0
  36. data/docs/cookbook/saas.md +481 -0
  37. data/docs/getting-started/index.md +56 -0
  38. data/docs/getting-started/installation.md +146 -0
  39. data/docs/getting-started/tutorial/01-setup.md +118 -0
  40. data/docs/getting-started/tutorial/02-first-resource.md +180 -0
  41. data/docs/getting-started/tutorial/03-authentication.md +246 -0
  42. data/docs/getting-started/tutorial/04-authorization.md +170 -0
  43. data/docs/getting-started/tutorial/05-custom-actions.md +202 -0
  44. data/docs/getting-started/tutorial/06-nested-resources.md +147 -0
  45. data/docs/getting-started/tutorial/07-customizing-ui.md +254 -0
  46. data/docs/getting-started/tutorial/index.md +64 -0
  47. data/docs/guides/adding-resources.md +420 -0
  48. data/docs/guides/authentication.md +551 -0
  49. data/docs/guides/authorization.md +468 -0
  50. data/docs/guides/creating-packages.md +380 -0
  51. data/docs/guides/custom-actions.md +523 -0
  52. data/docs/guides/index.md +45 -0
  53. data/docs/guides/multi-tenancy.md +302 -0
  54. data/docs/guides/nested-resources.md +411 -0
  55. data/docs/guides/search-filtering.md +266 -0
  56. data/docs/guides/theming.md +321 -0
  57. data/docs/index.md +67 -26
  58. data/docs/public/CLAUDE.md +64 -21
  59. data/docs/reference/assets/index.md +496 -0
  60. data/docs/reference/controller/index.md +363 -0
  61. data/docs/reference/definition/actions.md +400 -0
  62. data/docs/reference/definition/fields.md +350 -0
  63. data/docs/reference/definition/index.md +252 -0
  64. data/docs/reference/definition/query.md +342 -0
  65. data/docs/reference/generators/index.md +469 -0
  66. data/docs/reference/index.md +49 -0
  67. data/docs/reference/interaction/index.md +445 -0
  68. data/docs/reference/model/features.md +248 -0
  69. data/docs/reference/model/index.md +219 -0
  70. data/docs/reference/policy/index.md +385 -0
  71. data/docs/reference/portal/index.md +382 -0
  72. data/docs/reference/views/forms.md +396 -0
  73. data/docs/reference/views/index.md +479 -0
  74. data/gemfiles/rails_7.gemfile +9 -2
  75. data/gemfiles/rails_7.gemfile.lock +146 -111
  76. data/gemfiles/rails_8.0.gemfile +20 -0
  77. data/gemfiles/rails_8.0.gemfile.lock +417 -0
  78. data/gemfiles/rails_8.1.gemfile +20 -0
  79. data/gemfiles/rails_8.1.gemfile.lock +419 -0
  80. data/lib/generators/pu/gem/dotenv/templates/.env +2 -0
  81. data/lib/generators/pu/gem/dotenv/templates/config/initializers/001_ensure_required_env.rb +3 -1
  82. data/lib/generators/pu/lib/plutonium_generators/model_generator_base.rb +13 -16
  83. data/lib/generators/pu/pkg/portal/USAGE +65 -0
  84. data/lib/generators/pu/pkg/portal/portal_generator.rb +22 -9
  85. data/lib/generators/pu/res/conn/USAGE +71 -0
  86. data/lib/generators/pu/res/model/USAGE +106 -110
  87. data/lib/generators/pu/res/model/templates/model.rb.tt +6 -2
  88. data/lib/generators/pu/res/scaffold/USAGE +85 -0
  89. data/lib/generators/pu/rodauth/install_generator.rb +2 -6
  90. data/lib/generators/pu/rodauth/templates/config/initializers/url_options.rb +17 -0
  91. data/lib/generators/pu/skills/sync/USAGE +14 -0
  92. data/lib/generators/pu/skills/sync/sync_generator.rb +66 -0
  93. data/lib/plutonium/action_policy/sti_policy_lookup.rb +1 -1
  94. data/lib/plutonium/core/controller.rb +2 -2
  95. data/lib/plutonium/interaction/base.rb +1 -0
  96. data/lib/plutonium/package/engine.rb +2 -2
  97. data/lib/plutonium/query/adhoc_block.rb +6 -2
  98. data/lib/plutonium/query/model_scope.rb +1 -1
  99. data/lib/plutonium/railtie.rb +4 -0
  100. data/lib/plutonium/resource/controllers/crud_actions/index_action.rb +1 -1
  101. data/lib/plutonium/resource/query_object.rb +38 -8
  102. data/lib/plutonium/ui/table/components/scopes_bar.rb +39 -34
  103. data/lib/plutonium/version.rb +1 -1
  104. data/lib/tasks/release.rake +19 -4
  105. data/package.json +1 -1
  106. metadata +76 -39
  107. data/brakeman.ignore +0 -28
  108. data/docs/api-examples.md +0 -49
  109. data/docs/guide/claude-code-guide.md +0 -74
  110. data/docs/guide/deep-dive/authorization.md +0 -189
  111. data/docs/guide/deep-dive/multitenancy.md +0 -256
  112. data/docs/guide/deep-dive/resources.md +0 -390
  113. data/docs/guide/getting-started/01-installation.md +0 -165
  114. data/docs/guide/index.md +0 -28
  115. data/docs/guide/introduction/01-what-is-plutonium.md +0 -211
  116. data/docs/guide/introduction/02-core-concepts.md +0 -440
  117. data/docs/guide/tutorial/01-project-setup.md +0 -75
  118. data/docs/guide/tutorial/02-creating-a-feature-package.md +0 -45
  119. data/docs/guide/tutorial/03-defining-resources.md +0 -90
  120. data/docs/guide/tutorial/04-creating-a-portal.md +0 -101
  121. data/docs/guide/tutorial/05-customizing-the-ui.md +0 -128
  122. data/docs/guide/tutorial/06-adding-custom-actions.md +0 -101
  123. data/docs/guide/tutorial/07-implementing-authorization.md +0 -90
  124. data/docs/markdown-examples.md +0 -85
  125. data/docs/modules/action.md +0 -244
  126. data/docs/modules/authentication.md +0 -236
  127. data/docs/modules/configuration.md +0 -599
  128. data/docs/modules/controller.md +0 -443
  129. data/docs/modules/core.md +0 -316
  130. data/docs/modules/definition.md +0 -1308
  131. data/docs/modules/display.md +0 -759
  132. data/docs/modules/form.md +0 -495
  133. data/docs/modules/generator.md +0 -400
  134. data/docs/modules/index.md +0 -167
  135. data/docs/modules/interaction.md +0 -642
  136. data/docs/modules/package.md +0 -151
  137. data/docs/modules/policy.md +0 -176
  138. data/docs/modules/portal.md +0 -710
  139. data/docs/modules/query.md +0 -297
  140. data/docs/modules/resource_record.md +0 -618
  141. data/docs/modules/routing.md +0 -690
  142. data/docs/modules/table.md +0 -301
  143. data/docs/modules/ui.md +0 -631
@@ -0,0 +1,419 @@
1
+ PATH
2
+ remote: ..
3
+ specs:
4
+ plutonium (0.33.1)
5
+ action_policy (~> 0.7.0)
6
+ listen (~> 3.8)
7
+ pagy (~> 9.0)
8
+ phlex (~> 2.0)
9
+ phlex-rails
10
+ phlex-slotable (>= 1.0.0)
11
+ phlex-tabler_icons
12
+ phlexi-display (>= 0.2.0)
13
+ phlexi-field (>= 0.2.0)
14
+ phlexi-form (>= 0.10.0)
15
+ phlexi-menu (>= 0.4.0)
16
+ phlexi-table (>= 0.2.0)
17
+ rabl (~> 0.16.1)
18
+ rails (>= 7.2)
19
+ redcarpet
20
+ semantic_range (~> 3.0)
21
+ tailwind_merge
22
+ tty-prompt (~> 0.23.1)
23
+ zeitwerk
24
+
25
+ GEM
26
+ remote: https://rubygems.org/
27
+ specs:
28
+ action_policy (0.7.6)
29
+ ruby-next-core (>= 1.0)
30
+ action_text-trix (2.1.16)
31
+ railties
32
+ actioncable (8.1.1)
33
+ actionpack (= 8.1.1)
34
+ activesupport (= 8.1.1)
35
+ nio4r (~> 2.0)
36
+ websocket-driver (>= 0.6.1)
37
+ zeitwerk (~> 2.6)
38
+ actionmailbox (8.1.1)
39
+ actionpack (= 8.1.1)
40
+ activejob (= 8.1.1)
41
+ activerecord (= 8.1.1)
42
+ activestorage (= 8.1.1)
43
+ activesupport (= 8.1.1)
44
+ mail (>= 2.8.0)
45
+ actionmailer (8.1.1)
46
+ actionpack (= 8.1.1)
47
+ actionview (= 8.1.1)
48
+ activejob (= 8.1.1)
49
+ activesupport (= 8.1.1)
50
+ mail (>= 2.8.0)
51
+ rails-dom-testing (~> 2.2)
52
+ actionpack (8.1.1)
53
+ actionview (= 8.1.1)
54
+ activesupport (= 8.1.1)
55
+ nokogiri (>= 1.8.5)
56
+ rack (>= 2.2.4)
57
+ rack-session (>= 1.0.1)
58
+ rack-test (>= 0.6.3)
59
+ rails-dom-testing (~> 2.2)
60
+ rails-html-sanitizer (~> 1.6)
61
+ useragent (~> 0.16)
62
+ actiontext (8.1.1)
63
+ action_text-trix (~> 2.1.15)
64
+ actionpack (= 8.1.1)
65
+ activerecord (= 8.1.1)
66
+ activestorage (= 8.1.1)
67
+ activesupport (= 8.1.1)
68
+ globalid (>= 0.6.0)
69
+ nokogiri (>= 1.8.5)
70
+ actionview (8.1.1)
71
+ activesupport (= 8.1.1)
72
+ builder (~> 3.1)
73
+ erubi (~> 1.11)
74
+ rails-dom-testing (~> 2.2)
75
+ rails-html-sanitizer (~> 1.6)
76
+ activejob (8.1.1)
77
+ activesupport (= 8.1.1)
78
+ globalid (>= 0.3.6)
79
+ activemodel (8.1.1)
80
+ activesupport (= 8.1.1)
81
+ activerecord (8.1.1)
82
+ activemodel (= 8.1.1)
83
+ activesupport (= 8.1.1)
84
+ timeout (>= 0.4.0)
85
+ activestorage (8.1.1)
86
+ actionpack (= 8.1.1)
87
+ activejob (= 8.1.1)
88
+ activerecord (= 8.1.1)
89
+ activesupport (= 8.1.1)
90
+ marcel (~> 1.0)
91
+ activesupport (8.1.1)
92
+ base64
93
+ bigdecimal
94
+ concurrent-ruby (~> 1.0, >= 1.3.1)
95
+ connection_pool (>= 2.2.5)
96
+ drb
97
+ i18n (>= 1.6, < 2)
98
+ json
99
+ logger (>= 1.4.2)
100
+ minitest (>= 5.1)
101
+ securerandom (>= 0.3)
102
+ tzinfo (~> 2.0, >= 2.0.5)
103
+ uri (>= 0.13.1)
104
+ ansi (1.5.0)
105
+ appraisal (2.5.0)
106
+ bundler
107
+ rake
108
+ thor (>= 0.14.0)
109
+ ast (2.4.3)
110
+ base64 (0.3.0)
111
+ bcrypt (3.1.21)
112
+ bigdecimal (4.0.1)
113
+ brakeman (7.1.1)
114
+ racc
115
+ builder (3.3.0)
116
+ bundle-audit (0.1.0)
117
+ bundler-audit
118
+ bundler-audit (0.9.2)
119
+ bundler (>= 1.2.0, < 3)
120
+ thor (~> 1.0)
121
+ chunky_png (1.4.0)
122
+ combustion (1.5.0)
123
+ activesupport (>= 3.0.0)
124
+ railties (>= 3.0.0)
125
+ thor (>= 0.14.6)
126
+ concurrent-ruby (1.3.6)
127
+ connection_pool (3.0.2)
128
+ crass (1.0.6)
129
+ date (3.5.1)
130
+ drb (2.2.3)
131
+ erb (6.0.1)
132
+ erubi (1.13.1)
133
+ ffi (1.17.3-arm64-darwin)
134
+ fiber-local (1.1.0)
135
+ fiber-storage
136
+ fiber-storage (1.0.1)
137
+ globalid (1.3.0)
138
+ activesupport (>= 6.1)
139
+ i18n (1.14.8)
140
+ concurrent-ruby (~> 1.0)
141
+ importmap-rails (2.1.0)
142
+ actionpack (>= 6.0.0)
143
+ activesupport (>= 6.0.0)
144
+ railties (>= 6.0.0)
145
+ io-console (0.8.2)
146
+ irb (1.16.0)
147
+ pp (>= 0.6.0)
148
+ rdoc (>= 4.0.0)
149
+ reline (>= 0.4.2)
150
+ json (2.18.0)
151
+ language_server-protocol (3.17.0.5)
152
+ lint_roller (1.1.0)
153
+ listen (3.10.0)
154
+ logger
155
+ rb-fsevent (~> 0.10, >= 0.10.3)
156
+ rb-inotify (~> 0.9, >= 0.9.10)
157
+ logger (1.7.0)
158
+ loofah (2.25.0)
159
+ crass (~> 1.0.2)
160
+ nokogiri (>= 1.12.0)
161
+ mail (2.9.0)
162
+ logger
163
+ mini_mime (>= 0.1.1)
164
+ net-imap
165
+ net-pop
166
+ net-smtp
167
+ marcel (1.1.0)
168
+ mini_mime (1.1.5)
169
+ minitest (6.0.1)
170
+ prism (~> 1.5)
171
+ minitest-reporters (1.7.1)
172
+ ansi
173
+ builder
174
+ minitest (>= 5.0)
175
+ ruby-progressbar
176
+ net-imap (0.6.2)
177
+ date
178
+ net-protocol
179
+ net-pop (0.1.2)
180
+ net-protocol
181
+ net-protocol (0.2.2)
182
+ timeout
183
+ net-smtp (0.5.1)
184
+ net-protocol
185
+ nio4r (2.7.5)
186
+ nokogiri (1.19.0-arm64-darwin)
187
+ racc (~> 1.4)
188
+ pagy (9.4.0)
189
+ parallel (1.27.0)
190
+ parser (3.3.10.0)
191
+ ast (~> 2.4.1)
192
+ racc
193
+ pastel (0.8.0)
194
+ tty-color (~> 0.5)
195
+ phlex (2.3.1)
196
+ zeitwerk (~> 2.7)
197
+ phlex-rails (2.3.1)
198
+ phlex (~> 2.3.0)
199
+ railties (>= 7.1, < 9)
200
+ zeitwerk (~> 2.7)
201
+ phlex-slotable (1.0.0)
202
+ phlex (>= 2, < 3)
203
+ phlex-tabler_icons (0.3.0)
204
+ phlexi-display (0.2.0)
205
+ activesupport
206
+ phlex (~> 2.0)
207
+ phlexi-field (~> 0.2.0)
208
+ zeitwerk
209
+ phlexi-field (0.2.0)
210
+ activesupport (>= 7.1)
211
+ fiber-local
212
+ phlex (~> 2.0)
213
+ zeitwerk
214
+ phlexi-form (0.11.0)
215
+ activesupport
216
+ phlex (~> 2.0)
217
+ phlexi-field (~> 0.2.0)
218
+ zeitwerk
219
+ phlexi-menu (0.4.0)
220
+ phlex (~> 2.0)
221
+ phlexi-field (~> 0.2.0)
222
+ zeitwerk
223
+ phlexi-table (0.2.0)
224
+ activesupport
225
+ phlex (~> 2.0)
226
+ phlexi-display
227
+ phlexi-field (~> 0.2.0)
228
+ zeitwerk
229
+ pp (0.6.3)
230
+ prettyprint
231
+ prettyprint (0.2.0)
232
+ prism (1.7.0)
233
+ propshaft (1.3.1)
234
+ actionpack (>= 7.0.0)
235
+ activesupport (>= 7.0.0)
236
+ rack
237
+ psych (5.3.1)
238
+ date
239
+ stringio
240
+ puma (6.5.0)
241
+ nio4r (~> 2.0)
242
+ rabl (0.16.1)
243
+ activesupport (>= 2.3.14)
244
+ racc (1.8.1)
245
+ rack (3.2.4)
246
+ rack-session (2.1.1)
247
+ base64 (>= 0.1.0)
248
+ rack (>= 3.0.0)
249
+ rack-test (2.2.0)
250
+ rack (>= 1.3)
251
+ rackup (2.3.1)
252
+ rack (>= 3)
253
+ rails (8.1.1)
254
+ actioncable (= 8.1.1)
255
+ actionmailbox (= 8.1.1)
256
+ actionmailer (= 8.1.1)
257
+ actionpack (= 8.1.1)
258
+ actiontext (= 8.1.1)
259
+ actionview (= 8.1.1)
260
+ activejob (= 8.1.1)
261
+ activemodel (= 8.1.1)
262
+ activerecord (= 8.1.1)
263
+ activestorage (= 8.1.1)
264
+ activesupport (= 8.1.1)
265
+ bundler (>= 1.15.0)
266
+ railties (= 8.1.1)
267
+ rails-dom-testing (2.3.0)
268
+ activesupport (>= 5.0.0)
269
+ minitest
270
+ nokogiri (>= 1.6)
271
+ rails-html-sanitizer (1.6.2)
272
+ loofah (~> 2.21)
273
+ nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
274
+ railties (8.1.1)
275
+ actionpack (= 8.1.1)
276
+ activesupport (= 8.1.1)
277
+ irb (~> 1.13)
278
+ rackup (>= 1.0.0)
279
+ rake (>= 12.2)
280
+ thor (~> 1.0, >= 1.2.2)
281
+ tsort (>= 0.2)
282
+ zeitwerk (~> 2.6)
283
+ rainbow (3.1.1)
284
+ rake (13.3.1)
285
+ rb-fsevent (0.11.2)
286
+ rb-inotify (0.11.1)
287
+ ffi (~> 1.0)
288
+ rdoc (7.0.3)
289
+ erb
290
+ psych (>= 4.0.0)
291
+ tsort
292
+ redcarpet (3.6.1)
293
+ regexp_parser (2.11.3)
294
+ reline (0.6.3)
295
+ io-console (~> 0.5)
296
+ roda (3.100.0)
297
+ rack
298
+ rodauth (2.42.0)
299
+ roda (>= 2.6.0)
300
+ sequel (>= 4)
301
+ rodauth-model (0.4.0)
302
+ rodauth (~> 2.28)
303
+ rodauth-rails (2.1.2)
304
+ railties (>= 5.1)
305
+ roda (~> 3.76)
306
+ rodauth (~> 2.36)
307
+ rodauth-model (~> 0.2)
308
+ rotp (6.3.0)
309
+ rqrcode (3.2.0)
310
+ chunky_png (~> 1.0)
311
+ rqrcode_core (~> 2.0)
312
+ rqrcode_core (2.1.0)
313
+ rubocop (1.80.2)
314
+ json (~> 2.3)
315
+ language_server-protocol (~> 3.17.0.2)
316
+ lint_roller (~> 1.1.0)
317
+ parallel (~> 1.10)
318
+ parser (>= 3.3.0.2)
319
+ rainbow (>= 2.2.2, < 4.0)
320
+ regexp_parser (>= 2.9.3, < 3.0)
321
+ rubocop-ast (>= 1.46.0, < 2.0)
322
+ ruby-progressbar (~> 1.7)
323
+ unicode-display_width (>= 2.4.0, < 4.0)
324
+ rubocop-ast (1.47.1)
325
+ parser (>= 3.3.7.2)
326
+ prism (~> 1.4)
327
+ rubocop-performance (1.25.0)
328
+ lint_roller (~> 1.1)
329
+ rubocop (>= 1.75.0, < 2.0)
330
+ rubocop-ast (>= 1.38.0, < 2.0)
331
+ ruby-next-core (1.2.0)
332
+ ruby-progressbar (1.13.0)
333
+ securerandom (0.4.1)
334
+ semantic_range (3.1.0)
335
+ sequel (5.100.0)
336
+ bigdecimal
337
+ sequel-activerecord_connection (2.0.1)
338
+ activerecord (>= 5.1)
339
+ sequel (~> 5.38)
340
+ sin_lru_redux (2.5.2)
341
+ sqlite3 (2.6.0-arm64-darwin)
342
+ standard (1.51.1)
343
+ language_server-protocol (~> 3.17.0.2)
344
+ lint_roller (~> 1.0)
345
+ rubocop (~> 1.80.2)
346
+ standard-custom (~> 1.0.0)
347
+ standard-performance (~> 1.8)
348
+ standard-custom (1.0.2)
349
+ lint_roller (~> 1.0)
350
+ rubocop (~> 1.50)
351
+ standard-performance (1.8.0)
352
+ lint_roller (~> 1.1)
353
+ rubocop-performance (~> 1.25.0)
354
+ stimulus-rails (1.3.4)
355
+ railties (>= 6.0.0)
356
+ stringio (3.2.0)
357
+ tailwind_merge (1.3.2)
358
+ sin_lru_redux (~> 2.5)
359
+ thor (1.5.0)
360
+ tilt (2.7.0)
361
+ timeout (0.6.0)
362
+ tsort (0.2.0)
363
+ tty-color (0.6.0)
364
+ tty-cursor (0.7.1)
365
+ tty-prompt (0.23.1)
366
+ pastel (~> 0.8)
367
+ tty-reader (~> 0.8)
368
+ tty-reader (0.9.0)
369
+ tty-cursor (~> 0.7)
370
+ tty-screen (~> 0.8)
371
+ wisper (~> 2.0)
372
+ tty-screen (0.8.2)
373
+ turbo-rails (2.0.13)
374
+ actionpack (>= 7.1.0)
375
+ railties (>= 7.1.0)
376
+ tzinfo (2.0.6)
377
+ concurrent-ruby (~> 1.0)
378
+ unicode-display_width (3.2.0)
379
+ unicode-emoji (~> 4.1)
380
+ unicode-emoji (4.1.0)
381
+ uri (1.1.1)
382
+ useragent (0.16.11)
383
+ websocket-driver (0.8.0)
384
+ base64
385
+ websocket-extensions (>= 0.1.0)
386
+ websocket-extensions (0.1.5)
387
+ wisper (2.0.1)
388
+ zeitwerk (2.7.4)
389
+
390
+ PLATFORMS
391
+ arm64-darwin
392
+
393
+ DEPENDENCIES
394
+ appraisal
395
+ bcrypt
396
+ brakeman
397
+ bundle-audit
398
+ combustion
399
+ importmap-rails
400
+ minitest
401
+ minitest-reporters
402
+ plutonium!
403
+ propshaft
404
+ puma (>= 5.0)
405
+ rails (~> 8.1.0)
406
+ rake
407
+ rodauth-rails
408
+ rotp
409
+ rqrcode
410
+ sequel-activerecord_connection
411
+ sqlite3
412
+ standard
413
+ stimulus-rails
414
+ tilt
415
+ turbo-rails
416
+ tzinfo-data
417
+
418
+ BUNDLED WITH
419
+ 2.5.16
@@ -1,6 +1,8 @@
1
1
  # Secrets should NOT be added here.
2
2
  # Set them in `.env.local`
3
3
 
4
+ RAILS_DEFAULT_URL="http://localhost:3000"
5
+
4
6
  # # == S3
5
7
  # S3_REGION=S3_REGION
6
8
  # S3_BUCKET=S3_BUCKET
@@ -1,7 +1,9 @@
1
1
  return if ENV["SECRET_KEY_BASE_DUMMY"].present?
2
2
 
3
3
  # Add required env vars to this list
4
- required_env_vars = %w[]
4
+ required_env_vars = %w[
5
+ RAILS_DEFAULT_URL
6
+ ]
5
7
 
6
8
  if Rails.env.production?
7
9
  required_env_vars += %w[RAILS_MASTER_KEY DATABASE_URL]
@@ -93,13 +93,13 @@ module PlutoniumGenerators
93
93
  end
94
94
 
95
95
  if name.include? "/"
96
- attr_options[:to_table] = name.tr("/", "_").pluralize.to_sym
96
+ attr_options[:to_table] = name.underscore.tr("/", "_").pluralize.to_sym
97
97
  attr_options[:class_name] = name.classify
98
+ name = name.underscore
98
99
  if (shared_namespace = find_shared_namespace(model_name, name, separator: "/"))
99
- name = name.sub "#{shared_namespace}/", ""
100
+ name = name.sub("#{shared_namespace}/", "")
100
101
  end
101
-
102
- name = name.tr "/", "_"
102
+ name = name.tr("/", "_")
103
103
  end
104
104
  end
105
105
 
@@ -109,12 +109,12 @@ module PlutoniumGenerators
109
109
  private
110
110
 
111
111
  def parse_type_and_options(type)
112
+ nullable = type&.include?("?")
113
+ type = type&.sub("?", "") if nullable
114
+
112
115
  parsed_type, parsed_options = super
113
116
 
114
- if type&.ends_with?("?")
115
- parsed_type.remove!("?")
116
- parsed_options[:null] = true
117
- end
117
+ parsed_options[:null] = nullable ? true : false
118
118
 
119
119
  [parsed_type, parsed_options]
120
120
  end
@@ -122,14 +122,10 @@ module PlutoniumGenerators
122
122
  private
123
123
 
124
124
  def find_shared_namespace(model1, model2, separator: "::")
125
- # Split the model names by separator to get the namespaces and class names as arrays
126
- parts1 = model1.split(separator)
127
- parts2 = model2.split(separator)
125
+ parts1 = model1.underscore.split(separator)
126
+ parts2 = model2.underscore.split(separator)
128
127
 
129
- # Initialize an array to hold the shared namespace parts
130
128
  shared_namespace = []
131
-
132
- # Iterate over the shorter of the two arrays
133
129
  [parts1.length, parts2.length].min.times do |i|
134
130
  if parts1[i] == parts2[i]
135
131
  shared_namespace << parts1[i]
@@ -138,13 +134,14 @@ module PlutoniumGenerators
138
134
  end
139
135
  end
140
136
 
141
- # Return the shared namespace, joined by '::' or nil if there's no shared namespace
142
137
  shared_namespace.empty? ? nil : shared_namespace.join(separator)
143
138
  end
144
139
  end
145
140
 
146
141
  def required?
147
- super || attr_options[:null] != true
142
+ return false if attr_options[:null] == true
143
+
144
+ super
148
145
  end
149
146
 
150
147
  def cents?
@@ -0,0 +1,65 @@
1
+ Description:
2
+ Generates a Plutonium portal package (web interface).
3
+
4
+ Usage:
5
+ rails g pu:pkg:portal NAME [options]
6
+
7
+ Options:
8
+ --auth=NAME Rodauth account to authenticate with (e.g., --auth=user)
9
+ --public Grant public access (no authentication required)
10
+ --byo Bring your own authentication (configure manually)
11
+
12
+ Without options, the generator prompts interactively for authentication choice.
13
+
14
+ Examples:
15
+ # Interactive mode (prompts for auth configuration)
16
+ rails g pu:pkg:portal admin
17
+
18
+ # With Rodauth authentication
19
+ rails g pu:pkg:portal admin --auth=admin
20
+ rails g pu:pkg:portal dashboard --auth=user
21
+
22
+ # Public access (no authentication)
23
+ rails g pu:pkg:portal api --public
24
+
25
+ # Custom authentication (implement your own)
26
+ rails g pu:pkg:portal custom --byo
27
+
28
+ Generated Structure:
29
+ packages/[name]_portal/
30
+ ├── app/
31
+ │ ├── controllers/[name]_portal/
32
+ │ │ ├── concerns/controller.rb
33
+ │ │ ├── plutonium_controller.rb
34
+ │ │ ├── resource_controller.rb
35
+ │ │ └── dashboard_controller.rb
36
+ │ ├── definitions/[name]_portal/
37
+ │ ├── policies/[name]_portal/
38
+ │ └── views/[name]_portal/
39
+ ├── config/
40
+ │ └── routes.rb
41
+ └── lib/
42
+ └── engine.rb
43
+
44
+ Authentication Modes:
45
+ Rodauth:
46
+ Uses Plutonium::Auth::Rodauth(:account_name) in controller concern.
47
+ Requires rodauth account to be set up first.
48
+
49
+ Public:
50
+ Uses Plutonium::Auth::Public in controller concern.
51
+ No authentication required for any routes.
52
+
53
+ Bring Your Own:
54
+ Uses Plutonium::Auth::Public as base.
55
+ Implement current_user method in controller concern.
56
+
57
+ After Generation:
58
+ 1. Mount the portal in config/routes.rb:
59
+ mount AdminPortal::Engine, at: "/admin"
60
+
61
+ 2. Connect resources to the portal:
62
+ rails g pu:res:conn Post --dest=admin_portal
63
+
64
+ 3. Optionally configure entity scoping in engine.rb:
65
+ scope_to_entity Organization, strategy: :path
@@ -13,17 +13,13 @@ module Pu
13
13
 
14
14
  argument :name
15
15
 
16
+ class_option :auth, type: :string, desc: "Rodauth account to authenticate with (e.g., --auth=user)"
17
+ class_option :public, type: :boolean, default: false, desc: "Grant public access (no authentication)"
18
+ class_option :byo, type: :boolean, default: false, desc: "Bring your own authentication"
19
+
16
20
  def start
17
21
  validate_package_name name
18
-
19
- if defined?(RodauthApp) && (rodauths = RodauthApp.opts[:rodauths].keys).present?
20
- rodauth_account = prompt.select("Select rodauth account to authenticate with:", rodauths + [:none])
21
- @rodauth_account = rodauth_account unless rodauth_account == :none
22
- elsif prompt.yes?("Do you want to grant public access?")
23
- @public_access = true
24
- else
25
- @bring_your_own_auth = true
26
- end
22
+ configure_authentication
27
23
 
28
24
  template "lib/engine.rb", "packages/#{package_namespace}/lib/engine.rb"
29
25
  template "config/routes.rb", "packages/#{package_namespace}/config/routes.rb"
@@ -56,6 +52,23 @@ module Pu
56
52
 
57
53
  attr_reader :rodauth_account
58
54
 
55
+ def configure_authentication
56
+ if options[:auth].present?
57
+ @rodauth_account = options[:auth].to_sym
58
+ elsif options[:public]
59
+ @public_access = true
60
+ elsif options[:byo]
61
+ @bring_your_own_auth = true
62
+ elsif defined?(RodauthApp) && (rodauths = RodauthApp.opts[:rodauths].keys).present?
63
+ rodauth_account = prompt.select("Select rodauth account to authenticate with:", rodauths + [:none])
64
+ @rodauth_account = rodauth_account unless rodauth_account == :none
65
+ elsif prompt.yes?("Do you want to grant public access?")
66
+ @public_access = true
67
+ else
68
+ @bring_your_own_auth = true
69
+ end
70
+ end
71
+
59
72
  def package_name
60
73
  name.camelize + "Portal"
61
74
  end
@@ -0,0 +1,71 @@
1
+ Description:
2
+ Connects resources to a portal for web access. Creates portal-specific
3
+ controller, policy, and definition, and registers routes.
4
+
5
+ Usage:
6
+ rails g pu:res:conn [RESOURCES...] [options]
7
+
8
+ Options:
9
+ --dest=PORTAL Target portal package (e.g., admin_portal)
10
+ --src=PACKAGE Source feature package (optional)
11
+ Use main_app for resources in the main application
12
+ Use package name for resources in a feature package
13
+
14
+ Arguments:
15
+ RESOURCES Space-separated list of model names to connect.
16
+ Use full namespaced names for packaged resources.
17
+ If omitted, prompts for interactive selection.
18
+
19
+ Examples:
20
+ # Connect main_app resource (not in a package)
21
+ rails g pu:res:conn PropertyAmenity --dest=admin_portal
22
+
23
+ # Connect multiple main_app resources
24
+ rails g pu:res:conn Post Comment Tag --dest=admin_portal
25
+
26
+ # Connect namespaced resources (from a feature package)
27
+ rails g pu:res:conn Blogging::Post Blogging::Comment --dest=admin_portal
28
+
29
+ # Interactive mode (prompts for everything)
30
+ rails g pu:res:conn
31
+
32
+ # Specify source package explicitly
33
+ rails g pu:res:conn --src=blogging --dest=admin_portal
34
+
35
+ # Specify main_app as source explicitly
36
+ rails g pu:res:conn --src=main_app --dest=admin_portal
37
+
38
+ Generated Files:
39
+ For resource Post connected to admin_portal:
40
+
41
+ Controller: packages/admin_portal/app/controllers/admin_portal/posts_controller.rb
42
+ Policy: packages/admin_portal/app/policies/admin_portal/post_policy.rb (if needed)
43
+ Definition: packages/admin_portal/app/definitions/admin_portal/post_definition.rb (if needed)
44
+ Routes: Updates packages/admin_portal/config/routes.rb
45
+
46
+ Generated Code:
47
+ Controller inherits from resource's base controller:
48
+ class AdminPortal::PostsController < ::PostsController
49
+ include AdminPortal::Concerns::Controller
50
+ end
51
+
52
+ Policy inherits from resource's base policy with portal mixin:
53
+ class AdminPortal::PostPolicy < ::PostPolicy
54
+ include AdminPortal::ResourcePolicy
55
+ end
56
+
57
+ Routes register the resource:
58
+ register_resource ::Blogging::Post
59
+
60
+ Workflow:
61
+ 1. Create feature package: rails g pu:pkg:package blogging
62
+ 2. Create resources: rails g pu:res:scaffold Post ... --dest=blogging
63
+ 3. Run migrations: rails db:migrate
64
+ 4. Create portal: rails g pu:pkg:portal admin
65
+ 5. Connect to portal: rails g pu:res:conn Blogging::Post --dest=admin_portal
66
+
67
+ Notes:
68
+ - Always use this generator instead of manually connecting resources
69
+ - Portal policies/definitions allow per-portal customization
70
+ - Run after creating resources with pu:res:scaffold
71
+ - Run after migrations so attributes can be detected