@currentjs/gen 0.3.2 → 0.5.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 (69) hide show
  1. package/CHANGELOG.md +10 -611
  2. package/README.md +623 -427
  3. package/dist/cli.js +2 -1
  4. package/dist/commands/commit.js +25 -42
  5. package/dist/commands/createApp.js +1 -0
  6. package/dist/commands/createModule.js +151 -45
  7. package/dist/commands/diff.js +27 -40
  8. package/dist/commands/generateAll.js +141 -291
  9. package/dist/commands/migrateCommit.js +6 -18
  10. package/dist/commands/migratePush.d.ts +1 -0
  11. package/dist/commands/migratePush.js +135 -0
  12. package/dist/commands/migrateUpdate.d.ts +1 -0
  13. package/dist/commands/migrateUpdate.js +147 -0
  14. package/dist/commands/newGenerateAll.d.ts +4 -0
  15. package/dist/commands/newGenerateAll.js +336 -0
  16. package/dist/generators/controllerGenerator.d.ts +43 -19
  17. package/dist/generators/controllerGenerator.js +547 -329
  18. package/dist/generators/domainLayerGenerator.d.ts +21 -0
  19. package/dist/generators/domainLayerGenerator.js +276 -0
  20. package/dist/generators/dtoGenerator.d.ts +21 -0
  21. package/dist/generators/dtoGenerator.js +518 -0
  22. package/dist/generators/newControllerGenerator.d.ts +55 -0
  23. package/dist/generators/newControllerGenerator.js +644 -0
  24. package/dist/generators/newServiceGenerator.d.ts +19 -0
  25. package/dist/generators/newServiceGenerator.js +266 -0
  26. package/dist/generators/newStoreGenerator.d.ts +39 -0
  27. package/dist/generators/newStoreGenerator.js +408 -0
  28. package/dist/generators/newTemplateGenerator.d.ts +29 -0
  29. package/dist/generators/newTemplateGenerator.js +510 -0
  30. package/dist/generators/serviceGenerator.d.ts +16 -51
  31. package/dist/generators/serviceGenerator.js +167 -586
  32. package/dist/generators/storeGenerator.d.ts +35 -32
  33. package/dist/generators/storeGenerator.js +291 -238
  34. package/dist/generators/storeGeneratorV2.d.ts +31 -0
  35. package/dist/generators/storeGeneratorV2.js +190 -0
  36. package/dist/generators/templateGenerator.d.ts +21 -21
  37. package/dist/generators/templateGenerator.js +393 -268
  38. package/dist/generators/templates/appTemplates.d.ts +3 -1
  39. package/dist/generators/templates/appTemplates.js +15 -10
  40. package/dist/generators/templates/data/appYamlTemplate +5 -2
  41. package/dist/generators/templates/data/cursorRulesTemplate +315 -221
  42. package/dist/generators/templates/data/frontendScriptTemplate +45 -11
  43. package/dist/generators/templates/data/mainViewTemplate +1 -1
  44. package/dist/generators/templates/data/systemTsTemplate +5 -0
  45. package/dist/generators/templates/index.d.ts +0 -3
  46. package/dist/generators/templates/index.js +0 -3
  47. package/dist/generators/templates/newStoreTemplates.d.ts +5 -0
  48. package/dist/generators/templates/newStoreTemplates.js +141 -0
  49. package/dist/generators/templates/storeTemplates.d.ts +1 -5
  50. package/dist/generators/templates/storeTemplates.js +102 -219
  51. package/dist/generators/templates/viewTemplates.js +1 -1
  52. package/dist/generators/useCaseGenerator.d.ts +13 -0
  53. package/dist/generators/useCaseGenerator.js +188 -0
  54. package/dist/types/configTypes.d.ts +148 -0
  55. package/dist/types/configTypes.js +10 -0
  56. package/dist/utils/childEntityUtils.d.ts +18 -0
  57. package/dist/utils/childEntityUtils.js +78 -0
  58. package/dist/utils/commandUtils.d.ts +43 -0
  59. package/dist/utils/commandUtils.js +124 -0
  60. package/dist/utils/commitUtils.d.ts +4 -1
  61. package/dist/utils/constants.d.ts +10 -0
  62. package/dist/utils/constants.js +13 -1
  63. package/dist/utils/diResolver.d.ts +32 -0
  64. package/dist/utils/diResolver.js +204 -0
  65. package/dist/utils/new_parts_of_migrationUtils.d.ts +0 -0
  66. package/dist/utils/new_parts_of_migrationUtils.js +164 -0
  67. package/dist/utils/typeUtils.d.ts +19 -0
  68. package/dist/utils/typeUtils.js +70 -0
  69. package/package.json +7 -3
@@ -3,11 +3,14 @@
3
3
  ## Architecture Overview
4
4
  This is a CurrentJS framework application using clean architecture principles with the following layers:
5
5
  - **Controllers**: Handle HTTP requests/responses and route handling
6
+ - **UseCases**: Orchestrate handler calls in sequence
6
7
  - **Services**: Contain business logic and orchestrate operations
7
8
  - **Stores**: Provide data access layer and database operations
8
9
  - **Domain Entities**: Core business models
9
10
  - **Views**: HTML templates for server-side rendering
10
11
 
12
+ All layers (except Domain and Views) are auto-wired via **dependency injection** — the generator scans `@Injectable` and `@Controller` decorators, resolves constructor dependencies, and generates wiring code in `src/app.ts`.
13
+
11
14
  ## Commands
12
15
 
13
16
  ```bash
@@ -26,9 +29,10 @@ current diff [module] # Show differences between generated and current code
26
29
  1. Create an empty app (`current create app`) – this step is already done.
27
30
  2. Create a new module: `current create module Name`
28
31
  3. In the module's yaml file, define module's:
29
- - model(s)
30
- - routes & actions
31
- - permissions
32
+ - domain (aggregates and value objects)
33
+ - useCases (with input/output and handlers)
34
+ - api endpoints (with auth)
35
+ - web pages (with auth and onSuccess/onError)
32
36
  4. Generate TypeScript files: `current generate Name`
33
37
  5. If required, make changes in the:
34
38
  - model (i.e. some specific business rules or validations)
@@ -38,7 +42,7 @@ current diff [module] # Show differences between generated and current code
38
42
  --- If needed more than CRUD: ---
39
43
 
40
44
  7. Define action in the service by creating a method
41
- 8. Describe this action in the module's yaml. Additionaly, you may define routes and permissions.
45
+ 8. Describe this action in the module's yaml under useCases. Additionally, you may define api/web endpoints.
42
46
  9. `current generate Modulename`
43
47
  10. commit changes: `current commit`
44
48
 
@@ -54,189 +58,223 @@ current diff [module] # Show differences between generated and current code
54
58
 
55
59
  **Complete Module Example:**
56
60
  ```yaml
57
- models:
58
- - name: Post # Entity name (capitalized)
59
- fields:
60
- - name: title # Field name
61
- type: string # Field type: string, number, boolean, datetime
62
- required: true # Validation requirement
63
- - name: content
64
- type: string
65
- required: true
66
- - name: authorId
67
- type: number
68
- required: true
69
- - name: publishedAt
70
- type: datetime
71
- required: false
72
- - name: status
73
- type: string
74
- required: true
75
-
76
- api: # REST API configuration
77
- prefix: /api/posts # Base URL for API endpoints
78
- model: Post # Optional: which model this API serves (defaults to first model)
79
- endpoints:
80
- - method: GET # HTTP method
81
- path: / # Relative path (becomes /api/posts/)
82
- action: list # Action name (references actions section)
83
- - method: GET
84
- path: /:id # Path parameter
85
- action: get
86
- - method: POST
87
- path: /
88
- action: create
89
- - method: PUT
90
- path: /:id
91
- action: update
92
- - method: DELETE
93
- path: /:id
94
- action: delete
95
- - method: POST # Custom endpoint
96
- path: /:id/publish
97
- action: publish
98
- model: Post # Optional: override model for specific endpoint
99
-
100
- routes: # Web interface configuration
101
- prefix: /posts # Base URL for web pages
102
- model: Post # Optional: which model this route serves (defaults to first model)
103
- strategy: [toast, back] # Default success strategies for forms
104
- endpoints:
105
- - path: / # List page
106
- action: list
107
- view: postList # Template name
108
- - path: /:id # Detail page
109
- action: get
110
- view: postDetail
111
- - path: /create # Create form page
112
- action: empty # No data loading action
113
- view: postCreate
114
- - path: /:id/edit # Edit form page
115
- action: get # Load existing data
116
- view: postUpdate
117
- model: Post # Optional: override model for specific endpoint
118
-
119
- actions: # Business logic mapping
120
- list:
121
- handlers: [Post:default:list] # Use built-in list handler
122
- get:
123
- handlers: [Post:default:get] # Use built-in get handler
124
- create:
125
- handlers: [Post:default:create] # Built-in create
126
- update:
127
- handlers: [Post:default:update]
128
- delete:
129
- handlers: [ # Chain multiple handlers
130
- Post:checkCanDelete, # Custom business logic
131
- Post:default:delete
132
- ]
133
- publish: # Custom action
134
- handlers: [
135
- Post:default:get, # Fetch entity
136
- Post:validateForPublish, # Custom validation
137
- Post:updatePublishStatus # Custom update logic
138
- ]
139
-
140
- permissions: # Role-based access control
141
- - role: all
142
- actions: [list, get] # Anyone (including anonymous)
143
- - role: authenticated
144
- actions: [create] # Must be logged in
145
- - role: owner
146
- actions: [update, publish] # Entity owner permissions
147
- - role: admin
148
- actions: [update, delete, publish] # Admin role permissions
149
- - role: editor
150
- actions: [publish] # Editor role permissions
61
+ domain:
62
+ aggregates:
63
+ Post:
64
+ root: true # Marks as aggregate root
65
+ fields:
66
+ title: { type: string, required: true }
67
+ content: { type: string, required: true }
68
+ authorId: { type: id, required: true }
69
+ publishedAt: { type: datetime }
70
+ status: { type: string, required: true }
71
+
72
+ useCases:
73
+ Post:
74
+ list:
75
+ input:
76
+ pagination: { type: offset, defaults: { limit: 20, maxLimit: 100 } }
77
+ output: { from: Post, pagination: true }
78
+ handlers: [default:list] # Built-in list handler
79
+ get:
80
+ input: { identifier: id }
81
+ output: { from: Post }
82
+ handlers: [default:get] # Built-in get handler
83
+ create:
84
+ input: { from: Post }
85
+ output: { from: Post }
86
+ handlers: [default:create] # Built-in create
87
+ update:
88
+ input: { identifier: id, from: Post, partial: true }
89
+ output: { from: Post }
90
+ handlers: [default:update]
91
+ delete:
92
+ input: { identifier: id }
93
+ output: void
94
+ handlers: [ # Chain multiple handlers
95
+ checkCanDelete, # Custom → PostService.checkCanDelete(result, input)
96
+ default:delete # Built-in delete
97
+ ]
98
+ publish: # Custom action
99
+ input: { identifier: id }
100
+ output: { from: Post }
101
+ handlers: [
102
+ default:get, # Fetch entity
103
+ validateForPublish, # Custom → PostService.validateForPublish(result, input)
104
+ updatePublishStatus # Custom PostService.updatePublishStatus(result, input)
105
+ ]
106
+
107
+ api: # REST API configuration
108
+ Post: # Keyed by model name
109
+ prefix: /api/posts # Base URL for API endpoints
110
+ endpoints:
111
+ - method: GET # HTTP method
112
+ path: / # Relative path (becomes /api/posts/)
113
+ useCase: Post:list # References useCases.Post.list
114
+ auth: all # Public access
115
+ - method: GET
116
+ path: /:id # Path parameter
117
+ useCase: Post:get
118
+ auth: all
119
+ - method: POST
120
+ path: /
121
+ useCase: Post:create
122
+ auth: authenticated # Must be logged in
123
+ - method: PUT
124
+ path: /:id
125
+ useCase: Post:update
126
+ auth: [owner, admin] # Owner OR admin (OR logic)
127
+ - method: DELETE
128
+ path: /:id
129
+ useCase: Post:delete
130
+ auth: [owner, admin]
131
+ - method: POST # Custom endpoint
132
+ path: /:id/publish
133
+ useCase: Post:publish
134
+ auth: [owner, editor, admin]
135
+
136
+ web: # Web interface configuration
137
+ Post: # Keyed by model name
138
+ prefix: /posts # Base URL for web pages
139
+ layout: main_view # Layout template name
140
+ pages:
141
+ - path: / # List page
142
+ useCase: Post:list
143
+ view: postList # Template name
144
+ auth: all
145
+ - path: /:id # Detail page
146
+ useCase: Post:get
147
+ view: postDetail
148
+ auth: all
149
+ - path: /create # Create form (GET = show form)
150
+ method: GET
151
+ view: postCreate
152
+ auth: authenticated
153
+ - path: /create # Create form (POST = submit)
154
+ method: POST
155
+ useCase: Post:create
156
+ auth: authenticated
157
+ onSuccess: # What happens after successful submission
158
+ redirect: /posts/:id
159
+ toast: "Post created successfully"
160
+ onError:
161
+ stay: true
162
+ toast: error
163
+ - path: /:id/edit # Edit form (GET = show form)
164
+ method: GET
165
+ useCase: Post:get # Load existing data
166
+ view: postUpdate
167
+ auth: [owner, admin]
168
+ - path: /:id/edit # Edit form (POST = submit)
169
+ method: POST
170
+ useCase: Post:update
171
+ auth: [owner, admin]
172
+ onSuccess:
173
+ back: true
174
+ toast: "Post updated successfully"
151
175
  ```
152
176
 
153
- **Make sure no `ID`/`owner id`/`is deleted` fields are present in the model definition, since it's added automatically**
154
-
155
- **Field Types:**
156
- - `string` - Text data
157
- - `number` - Numeric data (integer or float)
158
- - `boolean` - True/false values
159
- - `datetime` - Date and time values
160
- - `ModelName` - Relationship to another model (e.g., `Owner`, `User`, `Post`)
161
-
162
- **Multi-Model Endpoint Configuration:**
177
+ **Make sure no `id`/`owner_id`/`created_at`/`updated_at`/`deleted_at` fields are present in the domain definition, since they are added automatically**
163
178
 
164
- When working with multiple models in a single module, you have flexible options:
179
+ **Use case option: withChild (aggregate root with child entities)**
165
180
 
166
- **Option 1: Per-Endpoint Model Override**
167
-
168
- Specify `model` on individual endpoints to override the section default:
181
+ Per use case you can set `withChild: true` (default `false`) to show child entities on the root's pages. Only applies when the entity has child entities (e.g. Invoice with InvoiceItem). Ignored if there are no child entities.
182
+ - **list** + `withChild: true`: adds a link column on the list page to the child entity list (no extra loading).
183
+ - **get** + `withChild: true`: on the detail page, renders a table of child entities below the main card, with View/Edit/Add links.
169
184
 
185
+ Example:
170
186
  ```yaml
171
- models:
172
- - name: Cat
173
- - name: Person
174
-
175
- routes:
176
- prefix: /cat
177
- model: Cat # Default for this section
178
- endpoints:
179
- - path: /create
180
- view: catCreate
181
- # Uses Cat model
182
-
183
- - path: /createOwner
184
- view: ownerCreate
185
- model: Person # Override for this endpoint
187
+ useCases:
188
+ Invoice:
189
+ get:
190
+ withChild: true
191
+ input: { identifier: id }
192
+ output: { from: Invoice }
193
+ handlers: [default:get]
186
194
  ```
187
195
 
188
- **Option 2: Multiple API/Routes Sections**
196
+ **Field Types:**
197
+ - `string` - Text data (VARCHAR in database)
198
+ - `number` - Numeric data (INT/DECIMAL in database)
199
+ - `integer` - Integer data (INT in database)
200
+ - `decimal` - Decimal data (DECIMAL in database)
201
+ - `boolean` - True/false values (BOOLEAN in database)
202
+ - `datetime` - Date and time values (DATETIME in database)
203
+ - `date` - Date values (DATE in database)
204
+ - `id` - Foreign key reference (INT in database)
205
+ - `json` - JSON data
206
+ - `enum` - Enumerated values (use with `values: [...]`)
207
+ - `ModelName` - Relationship to another model (e.g., `Owner`, `User`, `Post`)
208
+
209
+ **Multi-Model Configuration:**
189
210
 
190
- Use arrays to organize endpoints by model:
211
+ When working with multiple models in a single module, each model is a separate key in `api` and `web`:
191
212
 
192
213
  ```yaml
193
- routes:
194
- - prefix: /cat
195
- model: Cat
196
- endpoints: [...]
197
-
198
- - prefix: /person
199
- model: Person
200
- endpoints: [...]
201
-
202
- # Same works for api sections
214
+ domain:
215
+ aggregates:
216
+ Cat:
217
+ root: true
218
+ fields:
219
+ name: { type: string, required: true }
220
+ Person:
221
+ root: true
222
+ fields:
223
+ name: { type: string, required: true }
224
+ email: { type: string, required: true }
225
+
203
226
  api:
204
- - prefix: /api/cat
205
- model: Cat
206
- endpoints: [...]
207
-
208
- - prefix: /api/person
209
- model: Person
210
- endpoints: [...]
227
+ Cat:
228
+ prefix: /api/cat
229
+ endpoints:
230
+ - method: GET
231
+ path: /
232
+ useCase: Cat:list
233
+ auth: all
234
+ Person:
235
+ prefix: /api/person
236
+ endpoints:
237
+ - method: GET
238
+ path: /
239
+ useCase: Person:list
240
+ auth: all
241
+
242
+ web:
243
+ Cat:
244
+ prefix: /cat
245
+ layout: main_view
246
+ pages:
247
+ - path: /
248
+ useCase: Cat:list
249
+ view: catList
250
+ auth: all
251
+ Person:
252
+ prefix: /person
253
+ layout: main_view
254
+ pages:
255
+ - path: /
256
+ useCase: Person:list
257
+ view: personList
258
+ auth: all
211
259
  ```
212
260
 
213
- **Model Resolution Priority:**
214
- 1. `endpoint.model` (explicit override)
215
- 2. Inferred from action handler (e.g., `Person:default:create`)
216
- 3. `api.model` or `routes.model` (section default)
217
- 4. First model in `models[]` array (fallback)
218
-
219
261
  **Model Relationships:**
220
262
 
221
- Define relationships by using another model's name as the field type:
263
+ Define relationships by using another model's name as the field type in `domain.aggregates`:
222
264
 
223
265
  ```yaml
224
- models:
225
- - name: Owner
226
- fields:
227
- - name: name
228
- type: string
229
- required: true
230
-
231
- - name: Cat
232
- fields:
233
- - name: name
234
- type: string
235
- required: true
236
- - name: owner
237
- type: Owner # Creates relationship with Owner model
238
- required: true # Auto-generates foreign key: ownerId
239
- displayFields: [name] # Optional: fields to show in dropdowns
266
+ domain:
267
+ aggregates:
268
+ Owner:
269
+ root: true
270
+ fields:
271
+ name: { type: string, required: true }
272
+
273
+ Cat:
274
+ root: true
275
+ fields:
276
+ name: { type: string, required: true }
277
+ owner: { type: Owner, required: true } # Creates relationship with Owner model
240
278
  ```
241
279
 
242
280
  **Generated Behavior:**
@@ -255,90 +293,146 @@ Foreign keys are auto-generated following the pattern `fieldName + 'Id'`:
255
293
 
256
294
  The foreign key always references the `id` field of the related model.
257
295
 
258
- **🔄 Handler vs Action Architecture:**
296
+ **🔄 Handler vs Use Case Architecture:**
259
297
  - **Handler**: Creates a separate service method (one handler = one service method)
260
- - **Action**: Virtual controller concept that calls handler methods step-by-step
298
+ - **Use Case**: Defined under `useCases.ModelName.actionName`, calls handler methods step-by-step
299
+ - **UseCase reference**: Used in `api`/`web` endpoints as `ModelName:actionName` (e.g., `Post:list`)
300
+
301
+ **Built-in Handlers (used in `useCases.*.*.handlers`):**
302
+ - `default:list` - Creates service method with pagination parameters
303
+ - `default:get` - Creates service method named `get` with ID parameter
304
+ - `default:create` - Creates service method with DTO parameter
305
+ - `default:update` - Creates service method with ID and DTO parameters
306
+ - `default:delete` - Creates service method with ID parameter
261
307
 
262
- **Built-in Action Handlers:**
263
- - `ModelName:default:list` - Creates service method with pagination parameters
264
- - `ModelName:default:get` - Creates service method named `get` with ID parameter
265
- - `ModelName:default:create` - Creates service method with DTO parameter
266
- - `ModelName:default:update` - Creates service method with ID and DTO parameters
267
- - `ModelName:default:delete` - Creates service method with ID parameter
308
+ Note: Handlers within `useCases` do NOT need a model prefix because the model is already the key.
268
309
 
269
- **Custom Action Handlers:**
270
- - `ModelName:customMethodName` - Creates service method that accepts `result, context` parameters
310
+ **Custom Handlers:**
311
+ - `customMethodName` - Creates service method that accepts `(result, input)` parameters
271
312
  - `result`: Result from previous handler (or `null` if it's the first handler)
272
- - `context`: The request context object
313
+ - `input`: The parsed input DTO
273
314
  - Each handler generates a separate method in the service
274
315
  - User can customize the implementation after generation
275
316
 
276
- **🔗 Multiple Handlers per Action:**
277
- When an action has multiple handlers, each handler generates a separate service method, and the controller action calls them sequentially. The action returns the result from the last handler.
317
+ **🔗 Multiple Handlers per Use Case:**
318
+ When a use case has multiple handlers, each handler generates a separate service method, and the use case orchestrator calls them sequentially. The use case returns the result from the last handler.
278
319
 
279
320
  **Parameter Passing Rules:**
280
- - **Default handlers** (`:default:`): Receive standard parameters (id, pagination, DTO, etc.)
281
- - **Custom handlers**: Receive `(result, context)` where:
321
+ - **Default handlers** (`default:*`): Receive standard parameters (id, pagination, DTO, etc.)
322
+ - **Custom handlers**: Receive `(result, input)` where:
282
323
  - `result`: Result from previous handler, or `null` if it's the first handler
283
- - `context`: Request context object
284
-
285
- **Handler Format Examples:**
286
- - `Post:default:list` - Creates Post service method `list(page, limit)`
287
- - `Post:default:get` - Creates Post service method `get(id)`
288
- - `Post:validateContent` - Creates Post service method `validateContent(result, context)`
289
- - `Comment:notifySubscribers` - Creates Comment service method `notifySubscribers(result, context)`
290
-
291
- **Strategy Options (for forms):**
292
- - `toast` - Success toast notification
293
- - `back` - Navigate back in browser history
294
- - `message` - Inline success message
295
- - `modal` - Modal success dialog
296
- - `redirect` - Redirect to specific URL
297
- - `refresh` - Reload current page
324
+ - `input`: Parsed input DTO
325
+
326
+ **Handler Format Examples (inside `useCases`):**
327
+ - `default:list` - Creates service method `list(page, limit)`
328
+ - `default:get` - Creates service method `get(id)`
329
+ - `validateContent` - Creates service method `validateContent(result, input)`
330
+ - `notifySubscribers` - Creates service method `notifySubscribers(result, input)`
331
+
332
+ **Form Success/Error Handling (in `web` pages):**
333
+
334
+ Instead of a separate `strategy` field, use `onSuccess` and `onError` on web page endpoints:
335
+ ```yaml
336
+ onSuccess:
337
+ redirect: /posts/:id # Redirect to URL
338
+ toast: "Saved!" # Show toast notification
339
+ back: true # Navigate back in browser history
340
+ stay: true # Stay on current page
341
+ onError:
342
+ stay: true # Stay on current page
343
+ toast: error # Show error toast
344
+ ```
298
345
 
299
- **Permission Roles:**
346
+ The template generator converts `onSuccess` options into `data-strategy` attributes on HTML forms.
347
+
348
+ **Auth Configuration (per endpoint in `api` and `web`):**
300
349
  - `all` - Anyone (including anonymous users)
301
350
  - `authenticated` - Any logged-in user
302
- - `owner` - User who created the entity
351
+ - `owner` - User who created the entity (checks `ownerId` field)
303
352
  - `admin`, `editor`, `user` - Custom roles from JWT token
304
- - Multiple roles can be specified for each action
353
+ - `[owner, admin]` - Array syntax: user must match ANY (OR logic). Privileged roles bypass ownership check.
305
354
 
306
355
  **Generated Files from Configuration:**
307
356
  - Domain entity class (one per model)
308
- - Service class (one per model)
357
+ - Use case orchestrator (one per model)
358
+ - Service class with handler methods (one per model)
359
+ - Input/Output DTOs (one per use case)
309
360
  - API controller with REST endpoints (one per model)
310
361
  - Web controller with page rendering (one per model)
311
362
  - Store class with database operations (one per model)
312
363
  - HTML templates for all views
313
- - TypeScript interfaces and DTOs
314
364
 
315
365
  **Multi-Model Support:**
316
- - Each model gets its own service, controller, and store
317
- - Use `model` parameter in `api` and `routes` to specify which model to use (defaults to first model)
318
- - Use `model` parameter on individual endpoints to override model for specific endpoints
319
- - Action handlers use `modelname:action` format to specify which model's service method to call
366
+ - Each model gets its own Service, UseCase, Controller, and Store classes
367
+ - In `api`/`web`, each model is a separate key (e.g., `api.Cat`, `api.Person`)
368
+ - UseCase references use `ModelName:actionName` format (e.g., `Post:list`, `Person:create`)
369
+ - Handlers within `useCases` do not need model prefix (model is already the key)
320
370
  - Controllers and services are generated per model, not per module
321
371
 
372
+ ## Dependency Injection & Wiring
373
+
374
+ The application uses a decorator-driven DI system. All wiring is auto-generated in `src/app.ts` between `// currentjs:controllers:start` and `// currentjs:controllers:end` markers. **Never edit this block manually** — it is regenerated on each `current generate`.
375
+
376
+ ### `@Injectable` Decorator
377
+
378
+ Lives in `src/system.ts`. Marks a class for automatic DI discovery:
379
+
380
+ ```typescript
381
+ import { Injectable } from '../../../../system';
382
+
383
+ @Injectable()
384
+ export class MyService {
385
+ constructor(private myStore: MyStore) {}
386
+ }
387
+ ```
388
+
389
+ Generated Stores, Services, and UseCases already have `@Injectable()`. Controllers use `@Controller()` from `@currentjs/router` instead.
390
+
391
+ ### Adding Custom Classes to DI
392
+
393
+ If you create a new class that should be auto-wired:
394
+ 1. Add `@Injectable()` decorator (import from `src/system.ts`)
395
+ 2. Declare dependencies as constructor parameters with their types
396
+ 3. Run `current generate` — the class will be auto-imported and instantiated in `app.ts`
397
+ 4. Run `current commit` to preserve your changes
398
+
399
+ ### How Wiring Works
400
+
401
+ The generator:
402
+ 1. Scans all module `.ts` files for `@Injectable` and `@Controller` decorators
403
+ 2. Parses constructor parameters to build a dependency graph
404
+ 3. Topologically sorts classes (stores → services → use cases → controllers)
405
+ 4. Generates imports, instantiations, and the `controllers` array in `app.ts`
406
+
407
+ Database provider instances are injected into stores based on `app.yaml` configuration (global, with optional per-module overrides). Both npm packages and local file paths are supported as providers.
408
+
322
409
  ## Module Structure
323
410
  ```
324
411
  src/modules/ModuleName/
325
- ├── application/
326
- │ ├── services/ModuleService.ts # Business logic
327
- │ └── validation/ModuleValidation.ts # DTOs and validation
328
412
  ├── domain/
329
- └── entities/Module.ts # Domain model
413
+ ├── entities/
414
+ │ │ └── Entity.ts # Domain model (aggregate root)
415
+ │ └── valueObjects/
416
+ │ └── ValueObject.ts # Value objects (if any)
417
+ ├── application/
418
+ │ ├── useCases/
419
+ │ │ └── EntityUseCase.ts # Use case orchestrator
420
+ │ ├── services/
421
+ │ │ └── EntityService.ts # Business logic handlers
422
+ │ └── dto/
423
+ │ └── EntityAction.ts # Input/Output DTOs per action
330
424
  ├── infrastructure/
331
425
  │ ├── controllers/
332
- │ │ ├── ModuleApiController.ts # REST API endpoints
333
- │ │ └── ModuleWebController.ts # Web page controllers
334
- ├── interfaces/StoreInterface.ts # Data access interface
335
- └── stores/ModuleStore.ts # Data access implementation
426
+ │ │ ├── EntityApiController.ts # REST API endpoints
427
+ │ │ └── EntityWebController.ts # Web page controllers
428
+ └── stores/
429
+ └── EntityStore.ts # Data access implementation
336
430
  ├── views/
337
- │ ├── modulelist.html # List view template
338
- │ ├── moduledetail.html # Detail view template
339
- │ ├── modulecreate.html # Create form template
340
- │ └── moduleupdate.html # Update form template
341
- └── module.yaml # Module configuration
431
+ │ ├── entityList.html # List view template
432
+ │ ├── entityDetail.html # Detail view template
433
+ │ ├── entityCreate.html # Create form template
434
+ │ └── entityEdit.html # Edit form template
435
+ └── modulename.yaml # Module configuration
342
436
  ```
343
437
 
344
438
  ## Best Practices