@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/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:getById]
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
- **Custom Handlers (`service:`):**
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
- **Handler Chaining:**
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
- ### Permissions & Security 🔐
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
- **Special Roles:**
521
- - **`all`** - Any user, including anonymous (no authentication required)
522
- - **`authenticated`** - Any logged-in user
523
- - **`owner`** - The user who owns/created the entity (automatic ownership check)
524
- - **`admin`**, **`editor`**, **`user`** - Custom roles from your authentication system
525
-
526
- **How It Works:**
527
- ```typescript
528
- // Generated service methods automatically include permission checks
529
- async create(data: CreatePostDto, user?: AuthenticatedUser): Promise<Post> {
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
- **No Permissions = Open Access:**
539
- ```yaml
540
- permissions: [] # No restrictions - all actions available to everyone
541
- ```
413
+ ### Complete Module Configuration Example
542
414
 
543
- **Ownership-Based Permissions:**
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: list
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] # Show success message and navigate 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:getById]
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
- service:checkCanDelete, # Custom business logic
631
- default:delete
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
- publish:
612
+ customFirst:
634
613
  handlers: [
635
- default:getById,
636
- service:validateForPublish,
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
- - action: list
642
- roles: [all] # Anyone can view list
643
- - action: get
644
- roles: [all] # Anyone can view individual posts
645
- - action: create
646
- roles: [authenticated] # Must be logged in to create
647
- - action: update
648
- roles: [owner, admin] # Authors and admins can edit
649
- - action: delete
650
- roles: [admin] # Only admins can delete
651
- - action: publish
652
- roles: [owner, admin] # Authors and admins can publish
653
- ```
654
-
655
- This configuration creates a sophisticated blog system with proper security, custom business logic, and user-friendly interface behaviors.
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