plutonium 0.50.0 → 0.51.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 (132) hide show
  1. checksums.yaml +4 -4
  2. data/.claude/skills/plutonium/SKILL.md +85 -102
  3. data/.claude/skills/plutonium-app/SKILL.md +572 -0
  4. data/.claude/skills/plutonium-auth/SKILL.md +163 -300
  5. data/.claude/skills/plutonium-behavior/SKILL.md +838 -0
  6. data/.claude/skills/plutonium-resource/SKILL.md +1176 -0
  7. data/.claude/skills/plutonium-tenancy/SKILL.md +655 -0
  8. data/.claude/skills/plutonium-testing/SKILL.md +6 -5
  9. data/.claude/skills/plutonium-ui/SKILL.md +900 -0
  10. data/CHANGELOG.md +27 -2
  11. data/Rakefile +2 -1
  12. data/app/assets/plutonium.css +1 -11
  13. data/app/assets/plutonium.js +1009 -1214
  14. data/app/assets/plutonium.js.map +3 -3
  15. data/app/assets/plutonium.min.js +52 -51
  16. data/app/assets/plutonium.min.js.map +3 -3
  17. data/docs/.vitepress/config.ts +37 -27
  18. data/docs/getting-started/index.md +22 -29
  19. data/docs/getting-started/installation.md +37 -80
  20. data/docs/getting-started/tutorial/index.md +4 -5
  21. data/docs/guides/adding-resources.md +66 -377
  22. data/docs/guides/authentication.md +94 -463
  23. data/docs/guides/authorization.md +124 -370
  24. data/docs/guides/creating-packages.md +94 -296
  25. data/docs/guides/custom-actions.md +121 -441
  26. data/docs/guides/index.md +22 -42
  27. data/docs/guides/multi-tenancy.md +116 -187
  28. data/docs/guides/nested-resources.md +103 -431
  29. data/docs/guides/search-filtering.md +123 -240
  30. data/docs/guides/testing.md +5 -4
  31. data/docs/guides/theming.md +157 -407
  32. data/docs/guides/troubleshooting.md +5 -3
  33. data/docs/guides/user-invites.md +106 -425
  34. data/docs/guides/user-profile.md +76 -243
  35. data/docs/index.md +1 -1
  36. data/docs/reference/app/generators.md +517 -0
  37. data/docs/reference/app/index.md +158 -0
  38. data/docs/reference/app/packages.md +146 -0
  39. data/docs/reference/app/portals.md +377 -0
  40. data/docs/reference/auth/accounts.md +230 -0
  41. data/docs/reference/auth/index.md +88 -0
  42. data/docs/reference/auth/profile.md +185 -0
  43. data/docs/reference/behavior/controllers.md +395 -0
  44. data/docs/reference/behavior/index.md +22 -0
  45. data/docs/reference/behavior/interactions.md +341 -0
  46. data/docs/reference/behavior/policies.md +417 -0
  47. data/docs/reference/index.md +56 -49
  48. data/docs/reference/resource/actions.md +423 -0
  49. data/docs/reference/resource/definition.md +508 -0
  50. data/docs/reference/resource/index.md +50 -0
  51. data/docs/reference/resource/model.md +348 -0
  52. data/docs/reference/resource/query.md +305 -0
  53. data/docs/reference/tenancy/entity-scoping.md +361 -0
  54. data/docs/reference/tenancy/index.md +36 -0
  55. data/docs/reference/tenancy/invites.md +393 -0
  56. data/docs/reference/tenancy/nested-resources.md +267 -0
  57. data/docs/reference/testing/index.md +287 -0
  58. data/docs/reference/ui/assets.md +400 -0
  59. data/docs/reference/ui/components.md +165 -0
  60. data/docs/reference/ui/displays.md +104 -0
  61. data/docs/reference/ui/forms.md +284 -0
  62. data/docs/reference/ui/index.md +30 -0
  63. data/docs/reference/ui/layouts.md +106 -0
  64. data/docs/reference/ui/pages.md +189 -0
  65. data/docs/reference/ui/tables.md +117 -0
  66. data/docs/superpowers/specs/2026-05-09-typeahead-endpoint-design.md +203 -0
  67. data/docs/superpowers/specs/2026-05-12-skill-compaction-design.md +99 -0
  68. data/docs/superpowers/specs/2026-05-13-docs-restructure-design.md +186 -0
  69. data/gemfiles/rails_7.gemfile.lock +1 -1
  70. data/gemfiles/rails_8.0.gemfile.lock +1 -1
  71. data/gemfiles/rails_8.1.gemfile.lock +1 -1
  72. data/lib/generators/pu/core/update/update_generator.rb +0 -20
  73. data/lib/generators/pu/invites/install_generator.rb +1 -0
  74. data/lib/plutonium/definition/base.rb +1 -1
  75. data/lib/plutonium/definition/{views.rb → index_views.rb} +21 -20
  76. data/lib/plutonium/helpers/turbo_helper.rb +11 -0
  77. data/lib/plutonium/helpers/turbo_stream_actions_helper.rb +14 -0
  78. data/lib/plutonium/resource/controller.rb +1 -0
  79. data/lib/plutonium/resource/controllers/crud_actions.rb +19 -1
  80. data/lib/plutonium/resource/controllers/typeahead.rb +180 -0
  81. data/lib/plutonium/resource/policy.rb +7 -0
  82. data/lib/plutonium/routing/mapper_extensions.rb +15 -0
  83. data/lib/plutonium/ui/component/methods.rb +4 -0
  84. data/lib/plutonium/ui/form/base.rb +6 -2
  85. data/lib/plutonium/ui/form/components/json.rb +58 -0
  86. data/lib/plutonium/ui/form/components/resource_select.rb +62 -8
  87. data/lib/plutonium/ui/form/components/secure_association.rb +98 -22
  88. data/lib/plutonium/ui/form/concerns/typeahead_attributes.rb +83 -0
  89. data/lib/plutonium/ui/form/resource.rb +0 -4
  90. data/lib/plutonium/ui/grid/resource.rb +1 -1
  91. data/lib/plutonium/ui/layout/base.rb +1 -0
  92. data/lib/plutonium/ui/page/base.rb +0 -7
  93. data/lib/plutonium/ui/page/index.rb +4 -4
  94. data/lib/plutonium/ui/table/resource.rb +1 -1
  95. data/lib/plutonium/version.rb +1 -1
  96. data/lib/plutonium.rb +8 -0
  97. data/lib/tasks/release.rake +15 -1
  98. data/package.json +10 -10
  99. data/src/css/slim_select.css +4 -0
  100. data/src/js/controllers/slim_select_controller.js +61 -0
  101. data/src/js/turbo/turbo_actions.js +33 -0
  102. data/yarn.lock +553 -543
  103. metadata +44 -33
  104. data/.claude/skills/plutonium-assets/SKILL.md +0 -512
  105. data/.claude/skills/plutonium-controller/SKILL.md +0 -396
  106. data/.claude/skills/plutonium-create-resource/SKILL.md +0 -303
  107. data/.claude/skills/plutonium-definition/SKILL.md +0 -1223
  108. data/.claude/skills/plutonium-entity-scoping/SKILL.md +0 -317
  109. data/.claude/skills/plutonium-forms/SKILL.md +0 -465
  110. data/.claude/skills/plutonium-installation/SKILL.md +0 -331
  111. data/.claude/skills/plutonium-interaction/SKILL.md +0 -413
  112. data/.claude/skills/plutonium-invites/SKILL.md +0 -408
  113. data/.claude/skills/plutonium-model/SKILL.md +0 -440
  114. data/.claude/skills/plutonium-nested-resources/SKILL.md +0 -360
  115. data/.claude/skills/plutonium-package/SKILL.md +0 -198
  116. data/.claude/skills/plutonium-policy/SKILL.md +0 -456
  117. data/.claude/skills/plutonium-portal/SKILL.md +0 -410
  118. data/.claude/skills/plutonium-views/SKILL.md +0 -651
  119. data/docs/reference/assets/index.md +0 -496
  120. data/docs/reference/controller/index.md +0 -412
  121. data/docs/reference/definition/actions.md +0 -462
  122. data/docs/reference/definition/fields.md +0 -383
  123. data/docs/reference/definition/index.md +0 -326
  124. data/docs/reference/definition/query.md +0 -351
  125. data/docs/reference/generators/index.md +0 -648
  126. data/docs/reference/interaction/index.md +0 -449
  127. data/docs/reference/model/features.md +0 -248
  128. data/docs/reference/model/index.md +0 -218
  129. data/docs/reference/policy/index.md +0 -456
  130. data/docs/reference/portal/index.md +0 -379
  131. data/docs/reference/views/forms.md +0 -411
  132. data/docs/reference/views/index.md +0 -544
@@ -1,648 +0,0 @@
1
- # Generators Reference
2
-
3
- Complete reference for Plutonium CLI generators.
4
-
5
- ## Overview
6
-
7
- Plutonium provides generators for scaffolding:
8
- - Resources (model, controller, definition, policy)
9
- - Packages (feature and portal)
10
- - Authentication (Rodauth)
11
- - Assets and configuration
12
-
13
- ## Resource Generators
14
-
15
- ### pu:res:scaffold
16
-
17
- Generate a complete resource with model, controller, definition, and policy.
18
-
19
- ```bash
20
- rails generate pu:res:scaffold Post title:string body:text published:boolean
21
- ```
22
-
23
- #### Options
24
-
25
- | Option | Description |
26
- |--------|-------------|
27
- | `--dest NAME` | Destination package (prompted if not provided) |
28
- | `--no-model` | Skip model generation (use for existing models) |
29
-
30
- #### Examples
31
-
32
- ```bash
33
- # Basic resource (prompts for destination)
34
- rails generate pu:res:scaffold Post title:string body:text
35
-
36
- # Import existing model (no attributes needed)
37
- rails generate pu:res:scaffold Post
38
-
39
- # With associations
40
- rails generate pu:res:scaffold Comment body:text user:belongs_to post:belongs_to
41
-
42
- # With custom class_name (author -> User)
43
- rails generate pu:res:scaffold Post 'author:belongs_to{class_name:User}'
44
-
45
- # Skip model generation for existing models
46
- rails generate pu:res:scaffold Post title:string --no-model
47
- ```
48
-
49
- ### Field Types
50
-
51
- | Type | Example | Database Type |
52
- |------|---------|---------------|
53
- | `string` | `title:string` | `string` |
54
- | `text` | `body:text` | `text` |
55
- | `integer` | `count:integer` | `integer` |
56
- | `float` | `rating:float` | `float` |
57
- | `decimal` | `price:decimal` | `decimal` |
58
- | `boolean` | `active:boolean` | `boolean` |
59
- | `date` | `published_on:date` | `date` |
60
- | `datetime` | `published_at:datetime` | `datetime` |
61
- | `time` | `starts_at:time` | `time` |
62
- | `json` | `metadata:json` | `json` |
63
- | `jsonb` | `settings:jsonb` | `jsonb` (PostgreSQL) / `json` (SQLite) |
64
- | `uuid` | `external_id:uuid` | `uuid` (PostgreSQL) / `string` (SQLite) |
65
- | `belongs_to` | `user:belongs_to` | `references` |
66
- | `references` | `user:references` | `references` |
67
- | `rich_text` | `content:rich_text` | Action Text |
68
-
69
- #### PostgreSQL-Specific Types
70
-
71
- These types work in both PostgreSQL and SQLite (mapped to compatible types):
72
-
73
- | Type | PostgreSQL | SQLite Equivalent |
74
- |------|------------|-------------------|
75
- | `jsonb` | `jsonb` | `json` |
76
- | `hstore` | `hstore` | `json` |
77
- | `uuid` | `uuid` | `string` |
78
- | `inet` | `inet` | `string` |
79
- | `cidr` | `cidr` | `string` |
80
- | `macaddr` | `macaddr` | `string` |
81
- | `ltree` | `ltree` | `string` |
82
-
83
- #### Nullable Fields
84
-
85
- Append `?` to make a field nullable:
86
-
87
- ```bash
88
- rails generate pu:res:scaffold Post title:string 'description:text?'
89
- ```
90
-
91
- #### Default Values
92
-
93
- Use `{default:value}` syntax to set default values:
94
-
95
- ```bash
96
- # String with default
97
- rails generate pu:res:scaffold Post 'status:string{default:draft}'
98
-
99
- # Boolean with default (supports true/false/yes/1)
100
- rails generate pu:res:scaffold Post 'active:boolean{default:true}'
101
-
102
- # Integer with default
103
- rails generate pu:res:scaffold Post 'priority:integer{default:0}'
104
-
105
- # Decimal with precision and default
106
- rails generate pu:res:scaffold Product 'price:decimal{10,2,default:0}'
107
-
108
- # Nullable with default
109
- rails generate pu:res:scaffold Post 'category:string?{default:general}'
110
-
111
- # JSONB with empty hash default
112
- rails generate pu:res:scaffold Post 'metadata:jsonb{default:{}}'
113
-
114
- # JSONB with empty array default
115
- rails generate pu:res:scaffold Post 'tags:jsonb{default:[]}'
116
-
117
- # JSONB with object default
118
- rails generate pu:res:scaffold Post 'settings:jsonb{default:{"theme":"dark"}}'
119
- ```
120
-
121
- ::: tip Shell Quoting
122
- Always quote fields containing `?` or `{}` to prevent shell expansion.
123
- :::
124
-
125
- ::: tip JSON Default Values
126
- Default values are parsed as JSON first. This allows structured defaults like `{}` and `[]` for JSONB fields. If JSON parsing fails, the value is treated as a string (or coerced based on the column type for integers, floats, and booleans).
127
- :::
128
-
129
- #### Associations
130
-
131
- ```bash
132
- # Required belongs_to
133
- rails generate pu:res:scaffold Comment user:belongs_to post:belongs_to
134
-
135
- # Nullable belongs_to
136
- rails generate pu:res:scaffold Post 'parent:belongs_to?'
137
-
138
- # Custom class_name (author_id column -> User model)
139
- rails generate pu:res:scaffold Post 'author:belongs_to{class_name:User}'
140
-
141
- # Nullable with custom class_name
142
- rails generate pu:res:scaffold Post 'reviewer:belongs_to?{class_name:User}'
143
-
144
- # Cross-package reference
145
- rails generate pu:res:scaffold Comment blogging/post:belongs_to
146
- ```
147
-
148
- #### Money Fields (has_cents)
149
-
150
- Integer fields ending in `_cents` are treated as money fields:
151
-
152
- ```bash
153
- rails generate pu:res:scaffold Product name:string price_cents:integer
154
- ```
155
-
156
- ### pu:res:conn
157
-
158
- Connect a resource to a portal.
159
-
160
- ```bash
161
- rails generate pu:res:conn Post --dest=admin_portal
162
- ```
163
-
164
- Creates portal-specific controller, definition, and policy (if needed) and registers the resource in the portal routes.
165
-
166
- #### Options
167
-
168
- | Option | Description |
169
- |--------|-------------|
170
- | `--dest NAME` | Destination portal (prompted if not provided) |
171
- | `--singular` | Register as a singular resource (e.g., profile, dashboard) |
172
-
173
- #### Examples
174
-
175
- ```bash
176
- # Connect a resource to a portal
177
- rails generate pu:res:conn Post --dest=admin_portal
178
-
179
- # Connect multiple resources
180
- rails generate pu:res:conn Post Comment --dest=admin_portal
181
-
182
- # Connect a singular resource
183
- rails generate pu:res:conn Profile --dest=customer_portal --singular
184
-
185
- # Interactive mode (prompts for resource and portal)
186
- rails generate pu:res:conn
187
- ```
188
-
189
- ::: tip Nested Resources
190
- Nesting is automatic based on `belongs_to` associations. If `Comment` belongs to `Post`, nested routes are created automatically when both are registered in the same portal.
191
- :::
192
-
193
- ### pu:res:model
194
-
195
- Generate just a model with migration.
196
-
197
- ```bash
198
- rails generate pu:res:model Post title:string body:text
199
- ```
200
-
201
- ## Package Generators
202
-
203
- ### pu:pkg:package
204
-
205
- Generate a feature package for organizing domain code.
206
-
207
- ```bash
208
- rails generate pu:pkg:package blogging
209
- ```
210
-
211
- #### Generated Structure
212
-
213
- ```
214
- packages/blogging/
215
- ├── app/
216
- │ ├── controllers/blogging/
217
- │ ├── definitions/blogging/
218
- │ ├── interactions/blogging/
219
- │ ├── models/blogging/
220
- │ ├── policies/blogging/
221
- │ └── views/blogging/
222
- └── lib/
223
- └── engine.rb
224
- ```
225
-
226
- ### pu:pkg:portal
227
-
228
- Generate a portal package (web interface).
229
-
230
- ```bash
231
- rails generate pu:pkg:portal admin
232
- ```
233
-
234
- #### Options
235
-
236
- | Option | Description |
237
- |--------|-------------|
238
- | `--auth NAME` | Rodauth account to authenticate with (e.g., `--auth=user`) |
239
- | `--public` | Grant public access (no authentication) |
240
- | `--byo` | Bring your own authentication |
241
- | `--scope CLASS` | Entity class to scope to for multi-tenancy (e.g., `--scope=Organization`) |
242
-
243
- #### Examples
244
-
245
- ```bash
246
- # Interactive mode (prompts for auth choice)
247
- rails generate pu:pkg:portal admin
248
-
249
- # Non-interactive with Rodauth account
250
- rails generate pu:pkg:portal admin --auth=admin
251
-
252
- # Public access portal
253
- rails generate pu:pkg:portal api --public
254
-
255
- # Bring your own authentication
256
- rails generate pu:pkg:portal custom --byo
257
-
258
- # With entity scoping (multi-tenancy)
259
- rails generate pu:pkg:portal admin --auth=admin --scope=Organization
260
- ```
261
-
262
- Without flags, the generator prompts for authentication configuration:
263
- - Select a Rodauth account (if Rodauth is installed)
264
- - Grant public access (no authentication)
265
- - Bring your own auth (configure manually)
266
-
267
- #### Generated Structure
268
-
269
- ```
270
- packages/admin_portal/
271
- ├── app/
272
- │ ├── controllers/admin_portal/
273
- │ │ ├── concerns/controller.rb
274
- │ │ ├── plutonium_controller.rb
275
- │ │ ├── resource_controller.rb
276
- │ │ └── dashboard_controller.rb
277
- │ ├── definitions/admin_portal/
278
- │ ├── policies/admin_portal/
279
- │ └── views/admin_portal/
280
- ├── config/
281
- │ └── routes.rb
282
- └── lib/
283
- └── engine.rb
284
- ```
285
-
286
- ## Authentication Generators
287
-
288
- ### pu:rodauth:install
289
-
290
- Install Rodauth authentication framework.
291
-
292
- ```bash
293
- rails generate pu:rodauth:install
294
- ```
295
-
296
- This creates:
297
- - `app/rodauth/rodauth_app.rb` - Main Roda app
298
- - `app/rodauth/rodauth_plugin.rb` - Base plugin
299
- - `app/controllers/rodauth_controller.rb` - Base controller
300
- - `config/initializers/rodauth.rb` - Configuration
301
- - PostgreSQL extension migration (if using PostgreSQL)
302
-
303
- ### pu:rodauth:account
304
-
305
- Generate a user account with configurable features.
306
-
307
- ```bash
308
- rails generate pu:rodauth:account user
309
- ```
310
-
311
- #### Options
312
-
313
- | Option | Description |
314
- |--------|-------------|
315
- | `--primary` | Mark as primary account (no URL prefix) |
316
- | `--no-mails` | Skip mailer setup |
317
- | `--argon2` | Use Argon2 for password hashing |
318
- | `--api_only` | Configure for JSON API only |
319
- | `--defaults` | Enable default features (default: true) |
320
- | `--kitchen_sink` | Enable ALL features |
321
-
322
- #### Feature Options
323
-
324
- Default features (enabled with `--defaults`):
325
-
326
- | Feature | Description |
327
- |---------|-------------|
328
- | `--login` | Login functionality |
329
- | `--logout` | Logout functionality |
330
- | `--remember` | "Remember me" cookies |
331
- | `--create_account` | User registration |
332
- | `--verify_account` | Email verification |
333
- | `--verify_account_grace_period` | Grace period for verification |
334
- | `--reset_password` | Password reset via email |
335
- | `--reset_password_notify` | Notify on password reset |
336
- | `--change_login` | Change email address |
337
- | `--verify_login_change` | Verify email changes |
338
- | `--change_password` | Change password |
339
- | `--change_password_notify` | Notify on password change |
340
- | `--case_insensitive_login` | Case insensitive email |
341
- | `--internal_request` | Internal request support |
342
-
343
- Additional features:
344
-
345
- | Feature | Description |
346
- |---------|-------------|
347
- | `--otp` | TOTP two-factor auth |
348
- | `--recovery_codes` | Recovery codes for 2FA |
349
- | `--sms_codes` | SMS-based 2FA |
350
- | `--webauthn` | WebAuthn/passkeys |
351
- | `--lockout` | Account lockout |
352
- | `--active_sessions` | Track active sessions |
353
- | `--audit_logging` | Log auth events |
354
- | `--close_account` | Allow account deletion |
355
- | `--email_auth` | Passwordless email login |
356
- | `--jwt` | JWT authentication |
357
- | `--jwt_refresh` | JWT refresh tokens |
358
- | `--password_expiration` | Force password changes |
359
- | `--disallow_password_reuse` | Prevent password reuse |
360
-
361
- #### Examples
362
-
363
- ```bash
364
- # Basic account with defaults
365
- rails generate pu:rodauth:account user
366
-
367
- # Primary account (no /users prefix)
368
- rails generate pu:rodauth:account user --primary
369
-
370
- # With 2FA features
371
- rails generate pu:rodauth:account user --otp --recovery_codes
372
-
373
- # API-only with JWT
374
- rails generate pu:rodauth:account api_user --api_only --jwt --jwt_refresh
375
-
376
- # Everything enabled
377
- rails generate pu:rodauth:account user --kitchen_sink
378
- ```
379
-
380
- ### pu:rodauth:admin
381
-
382
- Generate an admin account with enhanced security.
383
-
384
- ```bash
385
- rails generate pu:rodauth:admin admin
386
- ```
387
-
388
- Pre-configured with:
389
- - Multi-phase login (email first, then password)
390
- - TOTP two-factor authentication (required)
391
- - Recovery codes
392
- - Account lockout
393
- - Active sessions tracking
394
- - Audit logging
395
- - No public signup
396
-
397
- Creates a rake task for account creation:
398
-
399
- ```bash
400
- rails rodauth_admin:create[admin@example.com,password123]
401
- ```
402
-
403
- ## SaaS Generators
404
-
405
- ### pu:saas:setup
406
-
407
- Generate a complete multi-tenant SaaS setup with user, entity, and membership.
408
-
409
- ```bash
410
- rails generate pu:saas:setup --user Customer --entity Organization
411
- rails generate pu:saas:setup --user Customer --entity Organization --roles=member,admin,owner
412
- rails generate pu:saas:setup --user Customer --entity Organization --no-allow-signup
413
- rails generate pu:saas:setup --user Customer --entity Organization --api_client ApiClient
414
- ```
415
-
416
- #### Options
417
-
418
- | Option | Description |
419
- |--------|-------------|
420
- | `--user NAME` | User account model name (required) |
421
- | `--entity NAME` | Entity model name (required) |
422
- | `--allow-signup` | Allow public registration (default: true) |
423
- | `--roles` | Comma-separated membership roles (default: member,owner) |
424
- | `--skip-entity` | Skip entity model generation |
425
- | `--skip-membership` | Skip membership model generation |
426
- | `--user-attributes` | Additional user model attributes |
427
- | `--entity-attributes` | Additional entity model attributes |
428
- | `--membership-attributes` | Additional membership model attributes |
429
- | `--api_client NAME` | Generate an API client model for M2M auth |
430
- | `--api_client_roles` | Roles for API client (default: read_only,write,admin) |
431
-
432
- Creates:
433
- - User account model with Rodauth authentication
434
- - Entity model with unique name
435
- - Membership join model with role enum
436
- - Has-many-through associations with `dependent: :destroy`
437
- - (Optional) API client with HTTP Basic Auth, scoped to entity
438
-
439
- ### pu:saas:user
440
-
441
- Generate just a SaaS user account.
442
-
443
- ```bash
444
- rails generate pu:saas:user Customer
445
- rails generate pu:saas:user Customer --no-allow-signup
446
- rails generate pu:saas:user Customer --extra-attributes=name:string
447
- ```
448
-
449
- ### pu:saas:entity
450
-
451
- Generate just an entity model.
452
-
453
- ```bash
454
- rails generate pu:saas:entity Organization
455
- rails generate pu:saas:entity Organization --extra-attributes=slug:string
456
- ```
457
-
458
- ### pu:saas:membership
459
-
460
- Generate just a membership model (requires user and entity to exist).
461
-
462
- ```bash
463
- rails generate pu:saas:membership --user Customer --entity Organization
464
- rails generate pu:saas:membership --user Customer --entity Organization --roles=member,admin,owner
465
- ```
466
-
467
- ### pu:saas:api_client
468
-
469
- Generate an API client account for machine-to-machine authentication.
470
-
471
- ```bash
472
- rails generate pu:saas:api_client ApiClient
473
- rails generate pu:saas:api_client ApiClient --entity=Organization
474
- rails generate pu:saas:api_client ApiClient --entity=Organization --roles=read_only,write,admin
475
- ```
476
-
477
- #### Options
478
-
479
- | Option | Description |
480
- |--------|-------------|
481
- | `--entity NAME` | Entity model to scope API clients to |
482
- | `--roles` | Available roles (default: read_only,write,admin) |
483
- | `--extra_attributes` | Additional model attributes |
484
- | `--dest` | Destination package |
485
-
486
- Creates:
487
- - Rodauth account with HTTP Basic Auth (login + auto-generated password)
488
- - Create and Disable interactions
489
- - Rake task for CLI creation (`rake api_clients:create`)
490
- - (If entity) Membership model with roles
491
-
492
- #### Usage
493
-
494
- ```bash
495
- # Create via rake task
496
- rake api_clients:create LOGIN=my-service
497
-
498
- # With entity scoping
499
- rake api_clients:create LOGIN=my-service ORGANIZATION=acme ROLE=write
500
- ```
501
-
502
- ::: tip Credentials
503
- Credentials are displayed once on creation and cannot be retrieved later. The password is auto-generated using `SecureRandom.base64(32)`.
504
- :::
505
-
506
- ## Core Generators
507
-
508
- ### pu:core:install
509
-
510
- Install Plutonium in an existing Rails app.
511
-
512
- ```bash
513
- rails generate pu:core:install
514
- ```
515
-
516
- Creates:
517
- - `config/initializers/plutonium.rb` - Configuration
518
- - Base classes (ResourceRecord, ResourcePolicy, etc.)
519
- - Package loading configuration
520
-
521
- ### pu:core:assets
522
-
523
- Setup custom TailwindCSS and Stimulus assets.
524
-
525
- ```bash
526
- rails generate pu:core:assets
527
- ```
528
-
529
- This:
530
- 1. Installs npm packages (`@radioactive-labs/plutonium`, TailwindCSS plugins)
531
- 2. Creates `tailwind.config.js` extending Plutonium's config
532
- 3. Imports Plutonium CSS into your stylesheet
533
- 4. Registers Plutonium's Stimulus controllers
534
- 5. Updates Plutonium config to use your assets
535
-
536
- ## Eject Generators
537
-
538
- ### pu:eject:layout
539
-
540
- Eject layout views for customization.
541
-
542
- ```bash
543
- rails generate pu:eject:layout
544
- ```
545
-
546
- Copies layout files to your portal for customization.
547
-
548
- ### pu:eject:shell
549
-
550
- Eject shell components (sidebar, header).
551
-
552
- ```bash
553
- rails generate pu:eject:shell
554
- ```
555
-
556
- ## Common Patterns
557
-
558
- ### Full Application Setup
559
-
560
- ```bash
561
- # Create Rails app with Plutonium template
562
- rails new myapp -a propshaft -j esbuild -c tailwind \
563
- -m https://radioactive-labs.github.io/plutonium-core/templates/plutonium.rb
564
-
565
- # Or add to existing app
566
- rails generate pu:core:install
567
- rails generate pu:rodauth:install
568
-
569
- # Create admin account type
570
- rails generate pu:rodauth:admin admin
571
-
572
- # Create resources
573
- rails generate pu:res:scaffold Post title:string body:text
574
- rails generate pu:res:scaffold Comment body:text post:belongs_to
575
-
576
- # Create portal (prompts for auth)
577
- rails generate pu:pkg:portal admin
578
-
579
- # Connect resources
580
- rails generate pu:res:conn Post Comment --dest=admin_portal
581
-
582
- # Run migrations
583
- rails db:migrate
584
-
585
- # Create admin account
586
- rails rodauth_admin:create[admin@example.com,password123]
587
- ```
588
-
589
- ### Adding a New Resource
590
-
591
- ```bash
592
- # Generate the resource
593
- rails generate pu:res:scaffold Product name:string price_cents:integer
594
-
595
- # Connect to portal
596
- rails generate pu:res:conn Product --dest=admin_portal
597
-
598
- # Run migration
599
- rails db:migrate
600
- ```
601
-
602
- ### Adding a New Portal
603
-
604
- ```bash
605
- # Create SaaS setup (user + entity + membership)
606
- rails generate pu:saas:setup --user Customer --entity Organization
607
-
608
- # Create portal
609
- rails generate pu:pkg:portal customer
610
-
611
- # Connect resources
612
- rails generate pu:res:conn Order --dest=customer_portal
613
-
614
- # Run migrations
615
- rails db:migrate
616
- ```
617
-
618
- ## Undoing Generators
619
-
620
- ```bash
621
- rails destroy pu:res:scaffold Post
622
- rails destroy pu:pkg:portal admin
623
- ```
624
-
625
- ## Troubleshooting
626
-
627
- ### Generator Not Found
628
-
629
- Ensure Plutonium is installed:
630
-
631
- ```ruby
632
- # Gemfile
633
- gem "plutonium"
634
- ```
635
-
636
- ### Package Not Found
637
-
638
- Generators run from Rails root. Package names are case-sensitive.
639
-
640
- ### Migration Already Exists
641
-
642
- If a migration with the same timestamp exists, wait a second and retry.
643
-
644
- ## Related
645
-
646
- - [Adding Resources Guide](/guides/adding-resources)
647
- - [Creating Packages Guide](/guides/creating-packages)
648
- - [Authentication Guide](/guides/authentication)