@currentjs/gen 0.1.2 → 0.2.1
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.
- package/CHANGELOG.md +30 -0
- package/README.md +327 -251
- package/dist/commands/createModule.js +7 -5
- package/dist/generators/controllerGenerator.d.ts +3 -0
- package/dist/generators/controllerGenerator.js +141 -27
- package/dist/generators/serviceGenerator.d.ts +3 -1
- package/dist/generators/serviceGenerator.js +223 -50
- package/dist/generators/templates/appTemplates.d.ts +1 -1
- package/dist/generators/templates/appTemplates.js +71 -38
- package/dist/generators/templates/serviceTemplates.d.ts +1 -0
- package/dist/generators/templates/serviceTemplates.js +5 -0
- package/howto.md +48 -29
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -34,6 +34,42 @@ currentjs generate
|
|
|
34
34
|
currentjs generate Blog --yaml app.yaml
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
+
## Step-by-Step Development Workflow 🔄
|
|
38
|
+
|
|
39
|
+
### Basic Development Flow
|
|
40
|
+
|
|
41
|
+
1. **Create an empty app**
|
|
42
|
+
```bash
|
|
43
|
+
currentjs create app # will create an app inside the current directory
|
|
44
|
+
# or:
|
|
45
|
+
currentjs create app my-project # will create a directory "my-project" and create an app there
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
2. **Create a new module**
|
|
49
|
+
```bash
|
|
50
|
+
currentjs create module Blog
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
3. **Define your module's configuration** in `src/modules/Blog/blog.yaml`:
|
|
54
|
+
- Define your data models
|
|
55
|
+
- Configure API routes & actions (CRUD is already configured)
|
|
56
|
+
- Set up permissions
|
|
57
|
+
|
|
58
|
+
4. **Generate TypeScript files**
|
|
59
|
+
```bash
|
|
60
|
+
currentjs generate Blog
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
5. **Make custom changes** (if needed) to:
|
|
64
|
+
- Business logic in models
|
|
65
|
+
- Custom actions in services
|
|
66
|
+
- HTML templates
|
|
67
|
+
|
|
68
|
+
6. **Commit your changes** to preserve them
|
|
69
|
+
```bash
|
|
70
|
+
currentjs commit
|
|
71
|
+
```
|
|
72
|
+
|
|
37
73
|
## What Does This Actually Do? 🤔
|
|
38
74
|
|
|
39
75
|
This generator takes your YAML specifications and creates:
|
|
@@ -159,35 +195,6 @@ currentjs diff Blog
|
|
|
159
195
|
+ }
|
|
160
196
|
```
|
|
161
197
|
|
|
162
|
-
#### 🎯 **registry.json Explained**
|
|
163
|
-
|
|
164
|
-
The registry tracks the "fingerprint" of each generated file:
|
|
165
|
-
|
|
166
|
-
```json
|
|
167
|
-
{
|
|
168
|
-
"src/modules/Blog/services/PostService.ts": {
|
|
169
|
-
"hash": "a1b2c3d4...", // Hash of the generated baseline
|
|
170
|
-
"updatedAt": "2024-01-15T10:30:00.000Z",
|
|
171
|
-
"diffFormat": "hunks-v1", // Change tracking format
|
|
172
|
-
"diffBaseHash": "a1b2c3d4...", // Hash of baseline this diff applies to
|
|
173
|
-
"diffHunks": [ // Your custom changes as patches
|
|
174
|
-
{
|
|
175
|
-
"oldStart": 15,
|
|
176
|
-
"newStart": 16,
|
|
177
|
-
"oldLines": 0,
|
|
178
|
-
"newLines": 8,
|
|
179
|
-
"oldContent": [],
|
|
180
|
-
"newContent": [
|
|
181
|
-
" async publishPost(id: number): Promise<void> {",
|
|
182
|
-
" const post = await this.getById(id);",
|
|
183
|
-
" // ... your custom logic"
|
|
184
|
-
]
|
|
185
|
-
}
|
|
186
|
-
]
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
```
|
|
190
|
-
|
|
191
198
|
#### 🌟 **Workflow Benefits**
|
|
192
199
|
|
|
193
200
|
**For Solo Development:**
|
|
@@ -210,23 +217,6 @@ npm run build
|
|
|
210
217
|
npm run deploy
|
|
211
218
|
```
|
|
212
219
|
|
|
213
|
-
#### 🔄 **Advanced Workflows**
|
|
214
|
-
|
|
215
|
-
**Evolving Your Schema:**
|
|
216
|
-
```bash
|
|
217
|
-
# 1. Modify your YAML files
|
|
218
|
-
vim src/modules/Blog/Blog.yaml
|
|
219
|
-
|
|
220
|
-
# 2. See what would change
|
|
221
|
-
currentjs diff Blog
|
|
222
|
-
|
|
223
|
-
# 3. Regenerate with preserved customizations
|
|
224
|
-
currentjs generate --force
|
|
225
|
-
|
|
226
|
-
# 4. Commit any new customizations
|
|
227
|
-
currentjs commit
|
|
228
|
-
```
|
|
229
|
-
|
|
230
220
|
**Sharing Customizations:**
|
|
231
221
|
```bash
|
|
232
222
|
# Export your modifications
|
|
@@ -239,17 +229,6 @@ git pull
|
|
|
239
229
|
currentjs generate # Their code automatically includes your customizations
|
|
240
230
|
```
|
|
241
231
|
|
|
242
|
-
**Branching Strategy:**
|
|
243
|
-
```bash
|
|
244
|
-
# Feature branch: only track YAML changes
|
|
245
|
-
git checkout -b feature/add-comments
|
|
246
|
-
# Edit Blog.yaml to add Comment model
|
|
247
|
-
currentjs generate
|
|
248
|
-
currentjs commit # Save any customizations
|
|
249
|
-
git add src/modules/Blog/Blog.yaml registry.json
|
|
250
|
-
git commit -m "Add comment system"
|
|
251
|
-
```
|
|
252
|
-
|
|
253
232
|
This change management system solves the age-old problem of "generated code vs. version control" by treating your customizations as first-class citizens while keeping your repository clean and merge-friendly!
|
|
254
233
|
|
|
255
234
|
#### 📝 **Recommended .gitignore Setup**
|
|
@@ -264,7 +243,6 @@ src/modules/*/application/validation/*.ts
|
|
|
264
243
|
src/modules/*/infrastructure/controllers/*.ts
|
|
265
244
|
src/modules/*/infrastructure/stores/*.ts
|
|
266
245
|
src/modules/*/infrastructure/interfaces/*.ts
|
|
267
|
-
src/modules/*/views/*.html
|
|
268
246
|
|
|
269
247
|
# Keep these in version control
|
|
270
248
|
!*.yaml
|
|
@@ -282,7 +260,7 @@ With this setup, your repository stays focused on what matters: your specificati
|
|
|
282
260
|
|
|
283
261
|
## Example: Building a Blog System 📝
|
|
284
262
|
|
|
285
|
-
Here's how you'd create a complete blog system:
|
|
263
|
+
Here's how you'd create a complete very simple blog system:
|
|
286
264
|
|
|
287
265
|
### 1. Create the app and module
|
|
288
266
|
```bash
|
|
@@ -312,6 +290,7 @@ models:
|
|
|
312
290
|
# this part is already generated for you!
|
|
313
291
|
api:
|
|
314
292
|
prefix: /api/posts
|
|
293
|
+
model: Post # Optional: specify which model this API serves
|
|
315
294
|
endpoints:
|
|
316
295
|
- method: GET
|
|
317
296
|
path: /
|
|
@@ -331,6 +310,7 @@ api:
|
|
|
331
310
|
|
|
332
311
|
routes:
|
|
333
312
|
prefix: /posts
|
|
313
|
+
model: Post # Optional: specify which model this route serves
|
|
334
314
|
strategy: [back, toast]
|
|
335
315
|
endpoints:
|
|
336
316
|
- path: /
|
|
@@ -348,15 +328,15 @@ routes:
|
|
|
348
328
|
|
|
349
329
|
actions:
|
|
350
330
|
list:
|
|
351
|
-
handlers: [default:list]
|
|
331
|
+
handlers: [Post:default:list]
|
|
352
332
|
get:
|
|
353
|
-
handlers: [default:
|
|
333
|
+
handlers: [Post:default:get]
|
|
354
334
|
create:
|
|
355
|
-
handlers: [default:create]
|
|
335
|
+
handlers: [Post:default:create]
|
|
356
336
|
update:
|
|
357
|
-
handlers: [default:update]
|
|
337
|
+
handlers: [Post:default:update]
|
|
358
338
|
delete:
|
|
359
|
-
handlers: [default:delete]
|
|
339
|
+
handlers: [Post:default:delete]
|
|
360
340
|
|
|
361
341
|
permissions: []
|
|
362
342
|
```
|
|
@@ -409,157 +389,38 @@ my-app/
|
|
|
409
389
|
└── translations.json # i18n support
|
|
410
390
|
```
|
|
411
391
|
|
|
412
|
-
## YAML Configuration Reference 📋
|
|
413
|
-
|
|
414
|
-
Understanding the key configuration sections in your module YAML files:
|
|
415
|
-
|
|
416
|
-
### Strategy Settings 🎯
|
|
417
|
-
|
|
418
|
-
The `strategy` array controls what happens after successful form submissions in your web interface:
|
|
419
|
-
|
|
420
|
-
```yaml
|
|
421
|
-
routes:
|
|
422
|
-
prefix: /posts
|
|
423
|
-
strategy: [back, toast] # Multiple strategies can be combined
|
|
424
|
-
endpoints:
|
|
425
|
-
# ... your routes
|
|
426
|
-
```
|
|
427
|
-
|
|
428
|
-
**Available Strategies:**
|
|
429
|
-
- **`toast`** - Shows a success notification popup (most common)
|
|
430
|
-
- **`back`** - Navigates back to the previous page using browser history
|
|
431
|
-
- **`message`** - Displays a success message in a specific element on the page
|
|
432
|
-
- **`modal`** - Shows a success message in a modal dialog
|
|
433
|
-
- **`redirect`** - Redirects to a specific URL after success
|
|
434
|
-
- **`refresh`** - Refreshes the current page
|
|
435
|
-
|
|
436
|
-
**Examples:**
|
|
437
|
-
```yaml
|
|
438
|
-
# Show toast and go back
|
|
439
|
-
strategy: [toast, back]
|
|
440
|
-
|
|
441
|
-
# Just show a toast notification
|
|
442
|
-
strategy: [toast]
|
|
443
|
-
|
|
444
|
-
# Show message in a specific element
|
|
445
|
-
strategy: [message]
|
|
446
|
-
|
|
447
|
-
# Multiple feedback mechanisms
|
|
448
|
-
strategy: [toast, modal, back]
|
|
449
|
-
```
|
|
450
|
-
|
|
451
|
-
The strategy is automatically applied to all form submissions in your generated templates (create, update forms).
|
|
452
|
-
|
|
453
|
-
### Actions & Handlers 🔧
|
|
454
|
-
|
|
455
|
-
The `actions` section maps logical business operations to their implementations:
|
|
456
|
-
|
|
457
|
-
```yaml
|
|
458
|
-
actions:
|
|
459
|
-
list:
|
|
460
|
-
handlers: [default:list] # Built-in CRUD handler
|
|
461
|
-
get:
|
|
462
|
-
handlers: [default:getById] # Built-in get by ID
|
|
463
|
-
create:
|
|
464
|
-
handlers: [default:create] # Built-in create
|
|
465
|
-
update:
|
|
466
|
-
handlers: [default:update] # Built-in update
|
|
467
|
-
delete:
|
|
468
|
-
handlers: [default:delete] # Built-in delete
|
|
469
|
-
customAction:
|
|
470
|
-
handlers: [service:myMethod] # Custom service method
|
|
471
|
-
complexAction:
|
|
472
|
-
handlers: [ # Multiple handlers (executed in order)
|
|
473
|
-
default:getById,
|
|
474
|
-
service:validateData,
|
|
475
|
-
default:update
|
|
476
|
-
]
|
|
477
|
-
```
|
|
478
|
-
|
|
479
|
-
**Built-in Handlers (`default:`):**
|
|
480
|
-
- **`default:list`** - Returns all entities with optional filtering/pagination
|
|
481
|
-
- **`default:getById`** - Fetches a single entity by ID
|
|
482
|
-
- **`default:create`** - Creates a new entity with validation
|
|
483
|
-
- **`default:update`** - Updates an existing entity by ID
|
|
484
|
-
- **`default:delete`** - Soft or hard deletes an entity by ID
|
|
485
392
|
|
|
486
|
-
|
|
487
|
-
- **`service:methodName`** - Calls a custom method on your service class
|
|
488
|
-
- Useful for complex business logic beyond basic CRUD
|
|
489
|
-
- Methods are automatically generated with proper type signatures
|
|
393
|
+
## Complete YAML Configuration Guide 📋
|
|
490
394
|
|
|
491
|
-
|
|
492
|
-
You can chain multiple handlers to create complex workflows:
|
|
493
|
-
```yaml
|
|
494
|
-
actions:
|
|
495
|
-
publish:
|
|
496
|
-
handlers: [
|
|
497
|
-
default:getById, # First, fetch the entity
|
|
498
|
-
service:validateForPublish, # Then, run custom validation
|
|
499
|
-
service:updatePublishStatus, # Finally, update status
|
|
500
|
-
service:sendNotification # And send notifications
|
|
501
|
-
]
|
|
502
|
-
```
|
|
395
|
+
### Module Structure Overview
|
|
503
396
|
|
|
504
|
-
|
|
397
|
+
When you create a module, you'll work primarily with the `ModuleName.yaml` file. This file defines everything about your module:
|
|
505
398
|
|
|
506
|
-
The `permissions` array controls role-based access to your actions:
|
|
507
|
-
|
|
508
|
-
```yaml
|
|
509
|
-
permissions:
|
|
510
|
-
- action: create
|
|
511
|
-
roles: [admin, editor] # Only admins and editors can create
|
|
512
|
-
- action: delete
|
|
513
|
-
roles: [admin] # Only admins can delete
|
|
514
|
-
- action: list
|
|
515
|
-
roles: [all] # Everyone can list (including anonymous)
|
|
516
|
-
- action: update
|
|
517
|
-
roles: [admin, editor, owner] # Multiple roles allowed
|
|
518
399
|
```
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
// Auto-generated permission check
|
|
531
|
-
if (!user || !['admin', 'editor'].includes(user.role)) {
|
|
532
|
-
throw new Error('Insufficient permissions');
|
|
533
|
-
}
|
|
534
|
-
// ... rest of create logic
|
|
535
|
-
}
|
|
400
|
+
src/modules/YourModule/
|
|
401
|
+
├── YourModule.yaml # ← This is where you define everything
|
|
402
|
+
├── domain/
|
|
403
|
+
│ └── entities/ # Generated domain models
|
|
404
|
+
├── application/
|
|
405
|
+
│ ├── services/ # Generated business logic
|
|
406
|
+
│ └── validation/ # Generated input validation
|
|
407
|
+
├── infrastructure/
|
|
408
|
+
│ ├── controllers/ # Generated HTTP endpoints
|
|
409
|
+
│ └── stores/ # Generated data access
|
|
410
|
+
└── views/ # Generated HTML templates
|
|
536
411
|
```
|
|
537
412
|
|
|
538
|
-
|
|
539
|
-
```yaml
|
|
540
|
-
permissions: [] # No restrictions - all actions available to everyone
|
|
541
|
-
```
|
|
413
|
+
### Complete Module Configuration Example
|
|
542
414
|
|
|
543
|
-
|
|
544
|
-
```yaml
|
|
545
|
-
permissions:
|
|
546
|
-
- action: update
|
|
547
|
-
roles: [owner, admin] # Users can update their own posts, admins can update any
|
|
548
|
-
- action: delete
|
|
549
|
-
roles: [owner] # Only the creator can delete their post
|
|
550
|
-
```
|
|
551
|
-
|
|
552
|
-
### Complete Configuration Example 🚀
|
|
553
|
-
|
|
554
|
-
Here's a real-world blog module with all concepts combined:
|
|
415
|
+
Here's a comprehensive example showing all available configuration options:
|
|
555
416
|
|
|
556
417
|
```yaml
|
|
557
418
|
models:
|
|
558
|
-
- name: Post
|
|
419
|
+
- name: Post # Entity name (capitalized)
|
|
559
420
|
fields:
|
|
560
|
-
- name: title
|
|
561
|
-
type: string
|
|
562
|
-
required: true
|
|
421
|
+
- name: title # Field name
|
|
422
|
+
type: string # Field type: string, number, boolean, datetime
|
|
423
|
+
required: true # Validation requirement
|
|
563
424
|
- name: content
|
|
564
425
|
type: string
|
|
565
426
|
required: true
|
|
@@ -573,86 +434,301 @@ models:
|
|
|
573
434
|
type: string
|
|
574
435
|
required: true
|
|
575
436
|
|
|
576
|
-
api:
|
|
577
|
-
prefix: /api/posts
|
|
437
|
+
api: # REST API configuration
|
|
438
|
+
prefix: /api/posts # Base URL for API endpoints
|
|
578
439
|
endpoints:
|
|
440
|
+
- method: GET # HTTP method
|
|
441
|
+
path: / # Relative path (becomes /api/posts/)
|
|
442
|
+
action: list # Action name (references actions section)
|
|
579
443
|
- method: GET
|
|
580
|
-
path:
|
|
581
|
-
action:
|
|
444
|
+
path: /:id # Path parameter
|
|
445
|
+
action: get
|
|
582
446
|
- method: POST
|
|
583
447
|
path: /
|
|
584
448
|
action: create
|
|
585
|
-
- method: GET
|
|
586
|
-
path: /:id
|
|
587
|
-
action: get
|
|
588
449
|
- method: PUT
|
|
589
450
|
path: /:id
|
|
590
451
|
action: update
|
|
591
452
|
- method: DELETE
|
|
592
453
|
path: /:id
|
|
593
454
|
action: delete
|
|
594
|
-
- method: POST
|
|
455
|
+
- method: POST # Custom endpoint
|
|
595
456
|
path: /:id/publish
|
|
596
457
|
action: publish
|
|
597
458
|
|
|
598
|
-
routes:
|
|
599
|
-
prefix: /posts
|
|
600
|
-
strategy: [toast, back]
|
|
459
|
+
routes: # Web interface configuration
|
|
460
|
+
prefix: /posts # Base URL for web pages
|
|
461
|
+
strategy: [toast, back] # Default success strategies for forms
|
|
601
462
|
endpoints:
|
|
602
|
-
- path: /
|
|
463
|
+
- path: / # List page
|
|
603
464
|
action: list
|
|
604
|
-
view: postList
|
|
605
|
-
- path: /:id
|
|
465
|
+
view: postList # Template name
|
|
466
|
+
- path: /:id # Detail page
|
|
606
467
|
action: get
|
|
607
468
|
view: postDetail
|
|
608
|
-
- path: /create
|
|
609
|
-
action: empty
|
|
469
|
+
- path: /create # Create form page
|
|
470
|
+
action: empty # No data loading action
|
|
610
471
|
view: postCreate
|
|
611
|
-
- path: /:id/edit
|
|
612
|
-
action: get
|
|
472
|
+
- path: /:id/edit # Edit form page
|
|
473
|
+
action: get # Load existing data
|
|
613
474
|
view: postUpdate
|
|
614
475
|
|
|
615
|
-
actions:
|
|
476
|
+
actions: # Business logic mapping
|
|
616
477
|
list:
|
|
617
|
-
handlers: [default:list]
|
|
478
|
+
handlers: [Post:default:list] # Use built-in list handler
|
|
618
479
|
get:
|
|
619
|
-
handlers: [default:
|
|
480
|
+
handlers: [Post:default:get] # Use built-in get handler
|
|
620
481
|
create:
|
|
621
|
-
handlers: [
|
|
622
|
-
service:validateContent, # Custom validation
|
|
623
|
-
default:create, # Standard creation
|
|
624
|
-
service:sendCreationNotice # Custom notification
|
|
625
|
-
]
|
|
482
|
+
handlers: [Post:default:create] # Built-in create
|
|
626
483
|
update:
|
|
627
|
-
handlers: [default:update]
|
|
484
|
+
handlers: [Post:default:update]
|
|
628
485
|
delete:
|
|
486
|
+
handlers: [ # Chain multiple handlers
|
|
487
|
+
Post:checkCanDelete, # Custom business logic
|
|
488
|
+
Post:default:delete
|
|
489
|
+
]
|
|
490
|
+
publish: # Custom action
|
|
491
|
+
handlers: [
|
|
492
|
+
Post:default:get, # Fetch entity
|
|
493
|
+
Post:validateForPublish, # Custom validation
|
|
494
|
+
Post:updatePublishStatus # Custom update logic
|
|
495
|
+
]
|
|
496
|
+
|
|
497
|
+
permissions: # Role-based access control
|
|
498
|
+
- role: all
|
|
499
|
+
actions: [list, get] # Anyone (including anonymous)
|
|
500
|
+
- role: authenticated
|
|
501
|
+
actions: [create] # Must be logged in
|
|
502
|
+
- role: owner
|
|
503
|
+
actions: [update, publish] # Entity owner permissions
|
|
504
|
+
- role: admin
|
|
505
|
+
actions: [update, delete, publish] # Admin role permissions
|
|
506
|
+
- role: editor
|
|
507
|
+
actions: [publish] # Editor role permissions
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
### Field Types and Validation
|
|
511
|
+
|
|
512
|
+
**Available Field Types:**
|
|
513
|
+
- `string` - Text data (VARCHAR in database)
|
|
514
|
+
- `number` - Numeric data (INT/DECIMAL in database)
|
|
515
|
+
- `boolean` - True/false values (BOOLEAN in database)
|
|
516
|
+
- `datetime` - Date and time values (DATETIME in database)
|
|
517
|
+
|
|
518
|
+
**Important Field Rules:**
|
|
519
|
+
- **Never include `id`/`owner_id`/`is_deleted` fields** - these are added automatically
|
|
520
|
+
- Use `required: true` for mandatory fields
|
|
521
|
+
- Use `required: false` for optional fields
|
|
522
|
+
|
|
523
|
+
```yaml
|
|
524
|
+
models:
|
|
525
|
+
- name: User
|
|
526
|
+
fields:
|
|
527
|
+
- name: email
|
|
528
|
+
type: string
|
|
529
|
+
required: true
|
|
530
|
+
- name: age
|
|
531
|
+
type: number
|
|
532
|
+
required: false
|
|
533
|
+
- name: isActive
|
|
534
|
+
type: boolean
|
|
535
|
+
required: true
|
|
536
|
+
- name: lastLoginAt
|
|
537
|
+
type: datetime
|
|
538
|
+
required: false
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
### Action Handlers Explained
|
|
542
|
+
|
|
543
|
+
**🔄 Handler vs Action Distinction:**
|
|
544
|
+
- **Handler**: Creates a separate service method (one handler = one method)
|
|
545
|
+
- **Action**: Virtual controller concept that calls handler methods step-by-step
|
|
546
|
+
|
|
547
|
+
**Built-in Handlers:**
|
|
548
|
+
- `ModelName:default:list` - Creates service method with pagination parameters
|
|
549
|
+
- `ModelName:default:get` - Creates service method named `get` with ID parameter
|
|
550
|
+
- `ModelName:default:create` - Creates service method with DTO parameter
|
|
551
|
+
- `ModelName:default:update` - Creates service method with ID and DTO parameters
|
|
552
|
+
- `ModelName:default:delete` - Creates service method with ID parameter
|
|
553
|
+
|
|
554
|
+
**Custom Handlers:**
|
|
555
|
+
- `ModelName:customMethodName` - Creates service method that accepts `result, context` parameters
|
|
556
|
+
- `result`: Result from previous handler (or `null` if it's the first handler)
|
|
557
|
+
- `context`: The request context object
|
|
558
|
+
- User can customize the implementation after generation
|
|
559
|
+
- Each handler generates a separate method in the service
|
|
560
|
+
|
|
561
|
+
**🔗 Multiple Handlers per Action:**
|
|
562
|
+
When an action has multiple handlers, each handler generates a separate service method, and the controller action calls them sequentially:
|
|
563
|
+
|
|
564
|
+
```yaml
|
|
565
|
+
actions:
|
|
566
|
+
get:
|
|
567
|
+
handlers:
|
|
568
|
+
- Invoice:default:get # Creates Invoice.get() method
|
|
569
|
+
- Invoice:enrichData # Creates Invoice.enrichData() method
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
**Generated Code Example:**
|
|
573
|
+
```typescript
|
|
574
|
+
// InvoiceService.ts
|
|
575
|
+
async get(id: number): Promise<Invoice> {
|
|
576
|
+
// Standard get implementation
|
|
577
|
+
}
|
|
578
|
+
async enrichData(result: any, context: any): Promise<any> {
|
|
579
|
+
// TODO: Implement custom enrichData method
|
|
580
|
+
// result = result from previous handler (Invoice object in this case)
|
|
581
|
+
// context = request context
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
// InvoiceController.ts
|
|
585
|
+
async get(context: IContext): Promise<Invoice> {
|
|
586
|
+
const id = parseInt(context.request.parameters.id as string);
|
|
587
|
+
const result1 = await this.invoiceService.get(id);
|
|
588
|
+
const result = await this.invoiceService.enrichData(result1, context);
|
|
589
|
+
return result; // Returns result from last handler
|
|
590
|
+
}
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
**Parameter Passing Rules:**
|
|
594
|
+
- **Default handlers** (`:default:`): Receive standard parameters (id, pagination, DTO, etc.)
|
|
595
|
+
- **Custom handlers**: Receive `(result, context)` where:
|
|
596
|
+
- `result`: Result from previous handler, or `null` if it's the first handler
|
|
597
|
+
- `context`: Request context object
|
|
598
|
+
|
|
599
|
+
**Handler Format Examples:**
|
|
600
|
+
```yaml
|
|
601
|
+
actions:
|
|
602
|
+
list:
|
|
603
|
+
handlers: [Post:default:list] # Single handler: list(page, limit)
|
|
604
|
+
get:
|
|
605
|
+
handlers: [Post:default:get] # Single handler: get(id)
|
|
606
|
+
complexFlow:
|
|
629
607
|
handlers: [
|
|
630
|
-
|
|
631
|
-
|
|
608
|
+
Post:default:create, # create(userData) - standard parameters
|
|
609
|
+
Post:sendNotification, # sendNotification(result, context) - result from create
|
|
610
|
+
Comment:default:create # create(userData) - standard parameters
|
|
632
611
|
]
|
|
633
|
-
|
|
612
|
+
customFirst:
|
|
634
613
|
handlers: [
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
service:updatePublishStatus
|
|
614
|
+
Post:validateInput, # validateInput(null, context) - first handler
|
|
615
|
+
Post:default:create # create(userData) - standard parameters
|
|
638
616
|
]
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
### Multi-Model Support 🔄
|
|
620
|
+
|
|
621
|
+
When you have multiple models in a single module, the system generates individual services, controllers, and stores for each model:
|
|
622
|
+
|
|
623
|
+
```yaml
|
|
624
|
+
models:
|
|
625
|
+
- name: Post
|
|
626
|
+
fields: [...]
|
|
627
|
+
- name: Comment
|
|
628
|
+
fields: [...]
|
|
629
|
+
|
|
630
|
+
api:
|
|
631
|
+
model: Post # This API serves the Post model
|
|
632
|
+
prefix: /api/posts
|
|
633
|
+
endpoints: [...]
|
|
634
|
+
|
|
635
|
+
# You can create separate API configs for other models
|
|
636
|
+
commentApi:
|
|
637
|
+
model: Comment # This API serves the Comment model
|
|
638
|
+
prefix: /api/comments
|
|
639
|
+
endpoints: [...]
|
|
640
|
+
|
|
641
|
+
actions:
|
|
642
|
+
createPost:
|
|
643
|
+
handlers: [Post:default:create] # Calls PostService.create()
|
|
644
|
+
addComment:
|
|
645
|
+
handlers: [Comment:default:create] # Calls CommentService.create()
|
|
646
|
+
publishPost:
|
|
647
|
+
handlers: [
|
|
648
|
+
Post:validateContent, # Calls PostService.validateContent()
|
|
649
|
+
Comment:notifySubscribers # Calls CommentService.notifySubscribers()
|
|
650
|
+
]
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
**Key Points:**
|
|
654
|
+
- Each model gets its own Service, Controller, and Store classes
|
|
655
|
+
- Use `model` parameter to specify which model an API/route serves (defaults to first model)
|
|
656
|
+
- Use `ModelName:default:action` for built-in operations (list, create, etc.)
|
|
657
|
+
- Use `ModelName:customMethod` for custom service methods
|
|
658
|
+
- You can mix actions across different models in a single handler chain
|
|
639
659
|
|
|
660
|
+
### Strategy Options for Forms
|
|
661
|
+
|
|
662
|
+
Configure what happens after successful form submissions:
|
|
663
|
+
|
|
664
|
+
```yaml
|
|
665
|
+
routes:
|
|
666
|
+
strategy: [toast, back] # Show success message and go back
|
|
667
|
+
```
|
|
668
|
+
|
|
669
|
+
**Available Strategies:**
|
|
670
|
+
- `toast` - Success toast notification (most common)
|
|
671
|
+
- `back` - Navigate back in browser history
|
|
672
|
+
- `message` - Inline success message
|
|
673
|
+
- `modal` - Modal success dialog
|
|
674
|
+
- `redirect` - Redirect to specific URL
|
|
675
|
+
- `refresh` - Reload current page
|
|
676
|
+
|
|
677
|
+
**Common Strategy Combinations:**
|
|
678
|
+
```yaml
|
|
679
|
+
# Most common: Show message and go back
|
|
680
|
+
strategy: [toast, back]
|
|
681
|
+
|
|
682
|
+
# Show message and stay on page
|
|
683
|
+
strategy: [toast]
|
|
684
|
+
|
|
685
|
+
# Show modal dialog
|
|
686
|
+
strategy: [modal]
|
|
687
|
+
|
|
688
|
+
# Multiple feedback
|
|
689
|
+
strategy: [toast, modal, back]
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
### Permission System
|
|
693
|
+
|
|
694
|
+
Control who can access what actions:
|
|
695
|
+
|
|
696
|
+
```yaml
|
|
640
697
|
permissions:
|
|
641
|
-
-
|
|
642
|
-
|
|
643
|
-
-
|
|
644
|
-
|
|
645
|
-
-
|
|
646
|
-
|
|
647
|
-
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
698
|
+
- role: all
|
|
699
|
+
actions: [list] # Anyone (including anonymous)
|
|
700
|
+
- role: authenticated
|
|
701
|
+
actions: [create] # Any logged-in user
|
|
702
|
+
- role: owner
|
|
703
|
+
actions: [update] # Owner of entity
|
|
704
|
+
- role: admin
|
|
705
|
+
actions: [update, delete] # Admin permissions
|
|
706
|
+
```
|
|
707
|
+
|
|
708
|
+
**Special Roles:**
|
|
709
|
+
- `all` - Everyone (including anonymous users)
|
|
710
|
+
- `authenticated` - Any logged-in user
|
|
711
|
+
- `owner` - User who created the entity
|
|
712
|
+
- `admin`, `editor`, `user` - Custom roles from JWT token
|
|
713
|
+
|
|
714
|
+
**How Ownership Works:**
|
|
715
|
+
The system automatically adds an `owner_id` field to track who created each entity. When you use `owner` role, it checks if the current user's ID matches the entity's `owner_id`.
|
|
716
|
+
|
|
717
|
+
### Code vs Configuration Guidelines
|
|
718
|
+
|
|
719
|
+
**✅ Use YAML Configuration For:**
|
|
720
|
+
- Basic CRUD operations
|
|
721
|
+
- Standard REST endpoints
|
|
722
|
+
- Simple permission rules
|
|
723
|
+
- Form success strategies
|
|
724
|
+
- Standard data field types
|
|
725
|
+
|
|
726
|
+
**✅ Write Custom Code For:**
|
|
727
|
+
- Complex business logic
|
|
728
|
+
- Custom validation rules
|
|
729
|
+
- Data transformations
|
|
730
|
+
- Integration with external services
|
|
731
|
+
- Complex database queries
|
|
656
732
|
|
|
657
733
|
## Part of the Framework Ecosystem 🌍
|
|
658
734
|
|