@currentjs/gen 0.2.2 → 0.3.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 (37) hide show
  1. package/CHANGELOG.md +80 -0
  2. package/README.md +256 -0
  3. package/dist/cli.js +26 -0
  4. package/dist/commands/createApp.js +2 -0
  5. package/dist/commands/generateAll.js +153 -29
  6. package/dist/commands/migrateCommit.d.ts +1 -0
  7. package/dist/commands/migrateCommit.js +201 -0
  8. package/dist/generators/controllerGenerator.d.ts +7 -0
  9. package/dist/generators/controllerGenerator.js +60 -29
  10. package/dist/generators/domainModelGenerator.d.ts +7 -0
  11. package/dist/generators/domainModelGenerator.js +57 -3
  12. package/dist/generators/serviceGenerator.d.ts +16 -1
  13. package/dist/generators/serviceGenerator.js +125 -12
  14. package/dist/generators/storeGenerator.d.ts +8 -0
  15. package/dist/generators/storeGenerator.js +133 -7
  16. package/dist/generators/templateGenerator.d.ts +19 -0
  17. package/dist/generators/templateGenerator.js +216 -11
  18. package/dist/generators/templates/appTemplates.d.ts +8 -7
  19. package/dist/generators/templates/appTemplates.js +11 -1572
  20. package/dist/generators/templates/data/appTsTemplate +39 -0
  21. package/dist/generators/templates/data/appYamlTemplate +4 -0
  22. package/dist/generators/templates/data/cursorRulesTemplate +671 -0
  23. package/dist/generators/templates/data/errorTemplate +28 -0
  24. package/dist/generators/templates/data/frontendScriptTemplate +739 -0
  25. package/dist/generators/templates/data/mainViewTemplate +16 -0
  26. package/dist/generators/templates/data/translationsTemplate +68 -0
  27. package/dist/generators/templates/data/tsConfigTemplate +19 -0
  28. package/dist/generators/templates/viewTemplates.d.ts +10 -1
  29. package/dist/generators/templates/viewTemplates.js +138 -6
  30. package/dist/generators/validationGenerator.d.ts +5 -0
  31. package/dist/generators/validationGenerator.js +51 -0
  32. package/dist/utils/constants.d.ts +3 -0
  33. package/dist/utils/constants.js +5 -2
  34. package/dist/utils/migrationUtils.d.ts +49 -0
  35. package/dist/utils/migrationUtils.js +291 -0
  36. package/howto.md +157 -65
  37. package/package.json +3 -2
package/CHANGELOG.md CHANGED
@@ -5,38 +5,78 @@ All notable changes to this project will be documented in this file.
5
5
 
6
6
 
7
7
 
8
+
9
+ ## [0.3.0] - 2025-10-03
10
+
11
+ - model relationship (between each other); - frontend script cleanup; - new command: migrate commit; - small refactoring.
12
+
8
13
  ## [0.2.2] - 2025-10-02
9
14
 
10
15
  fix bug: required params after optional in the generated models; fix: views(templates) are not stored in the registry and being regenerated (overwritten); small readme fix; running 'npm i' on 'create app' and 'npm run build' on 'generate'
11
16
 
17
+
18
+ ## [0.3.0] - 2025-10-03
19
+
20
+ - model relationship (between each other); - frontend script cleanup; - new command: migrate commit; - small refactoring.
21
+
12
22
  ## [0.2.1] - 2025-09-18
13
23
 
14
24
  Improve generated package.json
15
25
 
16
26
 
27
+
28
+ ## [0.3.0] - 2025-10-03
29
+
30
+ - model relationship (between each other); - frontend script cleanup; - new command: migrate commit; - small refactoring.
31
+
17
32
  ## [0.2.2] - 2025-10-02
18
33
 
19
34
  fix bug: required params after optional in the generated models; fix: views(templates) are not stored in the registry and being regenerated (overwritten); small readme fix; running 'npm i' on 'create app' and 'npm run build' on 'generate'
20
35
 
36
+
37
+ ## [0.3.0] - 2025-10-03
38
+
39
+ - model relationship (between each other); - frontend script cleanup; - new command: migrate commit; - small refactoring.
40
+
21
41
  ## [0.2.0] - 2025-09-18
22
42
 
23
43
  implement multi-model generation (controllers, services); fix service-controller interaction; update documentation: more clear & reflect important things
24
44
 
25
45
 
26
46
 
47
+
48
+ ## [0.3.0] - 2025-10-03
49
+
50
+ - model relationship (between each other); - frontend script cleanup; - new command: migrate commit; - small refactoring.
51
+
27
52
  ## [0.2.2] - 2025-10-02
28
53
 
29
54
  fix bug: required params after optional in the generated models; fix: views(templates) are not stored in the registry and being regenerated (overwritten); small readme fix; running 'npm i' on 'create app' and 'npm run build' on 'generate'
30
55
 
56
+
57
+ ## [0.3.0] - 2025-10-03
58
+
59
+ - model relationship (between each other); - frontend script cleanup; - new command: migrate commit; - small refactoring.
60
+
31
61
  ## [0.2.1] - 2025-09-18
32
62
 
33
63
  Improve generated package.json
34
64
 
35
65
 
66
+
67
+ ## [0.3.0] - 2025-10-03
68
+
69
+ - model relationship (between each other); - frontend script cleanup; - new command: migrate commit; - small refactoring.
70
+
36
71
  ## [0.2.2] - 2025-10-02
37
72
 
38
73
  fix bug: required params after optional in the generated models; fix: views(templates) are not stored in the registry and being regenerated (overwritten); small readme fix; running 'npm i' on 'create app' and 'npm run build' on 'generate'
39
74
 
75
+
76
+ ## [0.3.0] - 2025-10-03
77
+
78
+ - model relationship (between each other); - frontend script cleanup; - new command: migrate commit; - small refactoring.
79
+
40
80
  ## [0.1.2] - 2025-09-18
41
81
 
42
82
  fix: failed to generate with empty permissions actions
@@ -44,38 +84,78 @@ fix: failed to generate with empty permissions actions
44
84
 
45
85
 
46
86
 
87
+
88
+ ## [0.3.0] - 2025-10-03
89
+
90
+ - model relationship (between each other); - frontend script cleanup; - new command: migrate commit; - small refactoring.
91
+
47
92
  ## [0.2.2] - 2025-10-02
48
93
 
49
94
  fix bug: required params after optional in the generated models; fix: views(templates) are not stored in the registry and being regenerated (overwritten); small readme fix; running 'npm i' on 'create app' and 'npm run build' on 'generate'
50
95
 
96
+
97
+ ## [0.3.0] - 2025-10-03
98
+
99
+ - model relationship (between each other); - frontend script cleanup; - new command: migrate commit; - small refactoring.
100
+
51
101
  ## [0.2.1] - 2025-09-18
52
102
 
53
103
  Improve generated package.json
54
104
 
55
105
 
106
+
107
+ ## [0.3.0] - 2025-10-03
108
+
109
+ - model relationship (between each other); - frontend script cleanup; - new command: migrate commit; - small refactoring.
110
+
56
111
  ## [0.2.2] - 2025-10-02
57
112
 
58
113
  fix bug: required params after optional in the generated models; fix: views(templates) are not stored in the registry and being regenerated (overwritten); small readme fix; running 'npm i' on 'create app' and 'npm run build' on 'generate'
59
114
 
115
+
116
+ ## [0.3.0] - 2025-10-03
117
+
118
+ - model relationship (between each other); - frontend script cleanup; - new command: migrate commit; - small refactoring.
119
+
60
120
  ## [0.2.0] - 2025-09-18
61
121
 
62
122
  implement multi-model generation (controllers, services); fix service-controller interaction; update documentation: more clear & reflect important things
63
123
 
64
124
 
65
125
 
126
+
127
+ ## [0.3.0] - 2025-10-03
128
+
129
+ - model relationship (between each other); - frontend script cleanup; - new command: migrate commit; - small refactoring.
130
+
66
131
  ## [0.2.2] - 2025-10-02
67
132
 
68
133
  fix bug: required params after optional in the generated models; fix: views(templates) are not stored in the registry and being regenerated (overwritten); small readme fix; running 'npm i' on 'create app' and 'npm run build' on 'generate'
69
134
 
135
+
136
+ ## [0.3.0] - 2025-10-03
137
+
138
+ - model relationship (between each other); - frontend script cleanup; - new command: migrate commit; - small refactoring.
139
+
70
140
  ## [0.2.1] - 2025-09-18
71
141
 
72
142
  Improve generated package.json
73
143
 
74
144
 
145
+
146
+ ## [0.3.0] - 2025-10-03
147
+
148
+ - model relationship (between each other); - frontend script cleanup; - new command: migrate commit; - small refactoring.
149
+
75
150
  ## [0.2.2] - 2025-10-02
76
151
 
77
152
  fix bug: required params after optional in the generated models; fix: views(templates) are not stored in the registry and being regenerated (overwritten); small readme fix; running 'npm i' on 'create app' and 'npm run build' on 'generate'
78
153
 
154
+
155
+ ## [0.3.0] - 2025-10-03
156
+
157
+ - model relationship (between each other); - frontend script cleanup; - new command: migrate commit; - small refactoring.
158
+
79
159
  ## [0.1.1] - 2025-09-17
80
160
 
81
161
  Initial release
package/README.md CHANGED
@@ -257,6 +257,94 @@ dist/
257
257
 
258
258
  With this setup, your repository stays focused on what matters: your specifications and customizations, not generated boilerplate!
259
259
 
260
+ ## Multi-Model Endpoint Support 🔀
261
+
262
+ Working with multiple related models in a single module? CurrentJS now supports flexible endpoint configurations for multi-model scenarios.
263
+
264
+ ### Per-Endpoint Model Override
265
+
266
+ Override the model for specific endpoints when you need to mix models within the same API or routes section:
267
+
268
+ ```yaml
269
+ models:
270
+ - name: Cat
271
+ fields:
272
+ - name: name
273
+ type: string
274
+ - name: Person
275
+ fields:
276
+ - name: name
277
+ type: string
278
+ - name: email
279
+ type: string
280
+
281
+ routes:
282
+ prefix: /cat
283
+ model: Cat # Default model for this section
284
+ endpoints:
285
+ - path: /create
286
+ action: empty
287
+ view: catCreate
288
+ # Uses Cat model (from default)
289
+
290
+ - path: /createOwner
291
+ action: empty
292
+ view: ownerCreate
293
+ model: Person # Override to use Person model for this endpoint
294
+ ```
295
+
296
+ **Result**: The `/cat/createOwner` page will generate a form with Person fields (name, email), not Cat fields.
297
+
298
+ ### Multiple API/Routes Sections
299
+
300
+ Organize endpoints by model or functionality using arrays:
301
+
302
+ ```yaml
303
+ # Multiple routes sections for different models
304
+ routes:
305
+ - prefix: /cat
306
+ model: Cat
307
+ endpoints:
308
+ - path: /
309
+ action: list
310
+ view: catList
311
+ - path: /create
312
+ action: empty
313
+ view: catCreate
314
+
315
+ - prefix: /person
316
+ model: Person
317
+ endpoints:
318
+ - path: /
319
+ action: list
320
+ view: personList
321
+ - path: /create
322
+ action: empty
323
+ view: personCreate
324
+ ```
325
+
326
+ **Result**: Generates separate controllers with their own base paths and endpoints.
327
+
328
+ ### Automatic Model Inference
329
+
330
+ If you don't specify a `model`, the system will infer it from the action handler:
331
+
332
+ ```yaml
333
+ routes:
334
+ prefix: /cat
335
+ endpoints:
336
+ - path: /createOwner
337
+ action: createOwner
338
+ view: ownerCreate
339
+ # No model specified - inferred from action below
340
+
341
+ actions:
342
+ createOwner:
343
+ handlers: [Person:default:create] # Infers Person model
344
+ ```
345
+
346
+ **Priority**: `endpoint.model` → inferred from handler → section `model` → first model in array
347
+
260
348
  ## Example: Building a Blog System 📝
261
349
 
262
350
  Here's how you'd create a complete very simple blog system:
@@ -536,6 +624,174 @@ models:
536
624
  required: false
537
625
  ```
538
626
 
627
+ ### 🔗 Model Relationships
628
+
629
+ You can define relationships between models by specifying another model name as the field type. The generator will automatically handle foreign keys, type checking, and UI components.
630
+
631
+ **Basic Relationship Example:**
632
+ ```yaml
633
+ models:
634
+ - name: Owner
635
+ fields:
636
+ - name: name
637
+ type: string
638
+ required: true
639
+ - name: email
640
+ type: string
641
+ required: true
642
+
643
+ - name: Cat
644
+ fields:
645
+ - name: name
646
+ type: string
647
+ required: true
648
+ - name: breed
649
+ type: string
650
+ required: false
651
+ - name: owner
652
+ type: Owner # Relationship to Owner model
653
+ required: true
654
+ ```
655
+
656
+ **Architecture: Rich Domain Models**
657
+
658
+ The generator uses **Infrastructure-Level Relationship Assembly**:
659
+
660
+ - **Domain Layer**: Works with full objects (no FKs)
661
+ - **Infrastructure (Store)**: Handles FK ↔ Object conversion
662
+ - **DTOs**: Use FKs for API transmission
663
+
664
+ **What Gets Generated:**
665
+
666
+ 1. **Domain Model**: Pure business objects
667
+ ```typescript
668
+ import { Owner } from './Owner';
669
+
670
+ export class Cat {
671
+ constructor(
672
+ public id: number,
673
+ public name: string,
674
+ public breed?: string,
675
+ public owner: Owner // ✨ Full object, no FK!
676
+ ) {}
677
+ }
678
+ ```
679
+
680
+ 2. **DTOs**: Use foreign keys for API
681
+ ```typescript
682
+ export interface CatDTO {
683
+ name: string;
684
+ breed?: string;
685
+ ownerId: number; // ✨ FK for over-the-wire
686
+ }
687
+ ```
688
+
689
+ 3. **Store**: Converts FK ↔ Object
690
+ ```typescript
691
+ export class CatStore {
692
+ constructor(
693
+ private db: ISqlProvider,
694
+ private ownerStore: OwnerStore // ✨ Foreign store dependency
695
+ ) {}
696
+
697
+ async loadRelationships(entity: Cat, row: CatRow): Promise<Cat> {
698
+ const owner = await this.ownerStore.getById(row.ownerId);
699
+ if (owner) entity.setOwner(owner);
700
+ return entity;
701
+ }
702
+
703
+ async insert(cat: Cat): Promise<Cat> {
704
+ const row = {
705
+ name: cat.name,
706
+ ownerId: cat.owner?.id // ✨ Extract FK to save
707
+ };
708
+ // ...
709
+ }
710
+ }
711
+ ```
712
+
713
+ 4. **Service**: Loads objects from FKs
714
+ ```typescript
715
+ export class CatService {
716
+ constructor(
717
+ private catStore: CatStore,
718
+ private ownerStore: OwnerStore // ✨ To load relationships
719
+ ) {}
720
+
721
+ async create(catData: CatDTO): Promise<Cat> {
722
+ // ✨ Load full owner object from FK
723
+ const owner = await this.ownerStore.getById(catData.ownerId);
724
+ const cat = new Cat(0, catData.name, catData.breed, owner);
725
+ return await this.catStore.insert(cat);
726
+ }
727
+ }
728
+ ```
729
+
730
+ 5. **HTML Forms**: Select dropdown with "Create New" button
731
+ ```html
732
+ <select id="ownerId" name="ownerId" required>
733
+ <option value="">-- Select Owner --</option>
734
+ <!-- Options loaded from /api/owner -->
735
+ </select>
736
+ <button onclick="window.open('/owner/create')">+ New</button>
737
+ ```
738
+
739
+ **Relationship Naming Convention:**
740
+
741
+ The generator automatically creates foreign key fields following this convention:
742
+ - **Field name**: `owner` → **Foreign key**: `ownerId`
743
+ - **Field name**: `author` → **Foreign key**: `authorId`
744
+ - **Field name**: `parentComment` → **Foreign key**: `parentCommentId`
745
+
746
+ The foreign key always references the `id` field of the related model.
747
+
748
+ **Optional Configuration:**
749
+
750
+ ```yaml
751
+ models:
752
+ - name: Post
753
+ fields:
754
+ - name: title
755
+ type: string
756
+ required: true
757
+ - name: author
758
+ type: User
759
+ required: true
760
+ displayFields: [name, email] # Fields to show in dropdowns (optional)
761
+ ```
762
+
763
+ **Configuration Options:**
764
+ - `displayFields`: Array of fields from the related model to display in UI dropdowns (optional, defaults to showing the ID)
765
+
766
+ **Multiple Relationships:**
767
+ ```yaml
768
+ models:
769
+ - name: Comment
770
+ fields:
771
+ - name: content
772
+ type: string
773
+ required: true
774
+ - name: post
775
+ type: Post # Creates foreign key: postId
776
+ required: true
777
+ - name: author
778
+ type: User # Creates foreign key: authorId
779
+ required: true
780
+ displayFields: [username, email]
781
+ - name: parentComment
782
+ type: Comment # Self-referential relationship
783
+ required: false # Creates foreign key: parentCommentId
784
+ ```
785
+
786
+ **Relationship Best Practices:**
787
+ - ✅ Always define the foreign model first in the same module
788
+ - ✅ Use descriptive field names for relationships (e.g., `author` instead of `user`)
789
+ - ✅ Set appropriate `displayFields` to show meaningful data in dropdowns
790
+ - ✅ Use `required: false` for optional relationships
791
+ - ✅ Foreign keys are auto-generated following the pattern `fieldName + 'Id'`
792
+ - ❌ Don't manually add foreign key fields (they're auto-generated)
793
+ - ❌ Don't create circular dependencies between modules
794
+
539
795
  ### Action Handlers Explained
540
796
 
541
797
  **🔄 Handler vs Action Distinction:**
package/dist/cli.js CHANGED
@@ -8,6 +8,9 @@ const commit_1 = require("./commands/commit");
8
8
  const diff_1 = require("./commands/diff");
9
9
  const colors_1 = require("./utils/colors");
10
10
  const infer_1 = require("./commands/infer");
11
+ const migrateCommit_1 = require("./commands/migrateCommit");
12
+ // import { handleMigratePush } from './commands/migratePush';
13
+ // import { handleMigrateUpdate } from './commands/migrateUpdate';
11
14
  function printHelp() {
12
15
  const title = colors_1.colors.bold(colors_1.colors.brightCyan('currentjs - Clean architecture CLI'));
13
16
  const usage = colors_1.colors.bold('Usage:');
@@ -24,6 +27,7 @@ ${usage}
24
27
  ${cmd('currentjs commit')} ${colors_1.colors.gray('[<file> ...]')} ${flag('--yaml')} ${colors_1.colors.gray('app.yaml')}
25
28
  ${cmd('currentjs diff')} ${colors_1.colors.gray('<module|*>')} ${flag('--yaml')} ${colors_1.colors.gray('app.yaml')}
26
29
  ${cmd('currentjs infer')} ${flag('--file')} ${colors_1.colors.gray('src/modules/<Module>/domain/entities/<Entity>.ts')} ${colors_1.colors.gray('[')}${flag('--write')}${colors_1.colors.gray(']')}
30
+ ${cmd('currentjs migrate commit')} ${flag('--yaml')} ${colors_1.colors.gray('app.yaml')}
27
31
 
28
32
  ${options}
29
33
  ${flag('--yaml')} <path> ${colors_1.colors.gray('Path to app.yaml (default: ./app.yaml)')}
@@ -65,6 +69,9 @@ function parseArgs(argv) {
65
69
  else if (result.command === 'infer') {
66
70
  // no subcommands
67
71
  }
72
+ else if (result.command === 'migrate') {
73
+ result.sub = rest.shift();
74
+ }
68
75
  for (let i = 0; i < rest.length; i += 1) {
69
76
  const token = rest[i];
70
77
  if (token === '--yaml') {
@@ -127,6 +134,25 @@ async function run() {
127
134
  (0, infer_1.handleInfer)(fileArg, write);
128
135
  return;
129
136
  }
137
+ case 'migrate': {
138
+ if (args.sub === 'commit') {
139
+ (0, migrateCommit_1.handleMigrateCommit)(args.yaml);
140
+ return;
141
+ }
142
+ if (args.sub === 'push') {
143
+ console.log(colors_1.colors.yellow('⚠️ Not implemented yet'));
144
+ // await handleMigratePush(args.yaml);
145
+ return;
146
+ }
147
+ if (args.sub === 'update') {
148
+ console.log(colors_1.colors.yellow('⚠️ Not implemented yet'));
149
+ // await handleMigrateUpdate(args.yaml);
150
+ return;
151
+ }
152
+ printHelp();
153
+ process.exitCode = 1;
154
+ return;
155
+ }
130
156
  default: {
131
157
  printHelp();
132
158
  process.exitCode = 1;
@@ -46,11 +46,13 @@ function handleCreateApp(rawName) {
46
46
  const webDir = path.join(targetRoot, appTemplates_1.DEFAULT_DIRECTORIES.WEB);
47
47
  const templatesDir = path.join(targetRoot, appTemplates_1.DEFAULT_DIRECTORIES.TEMPLATES);
48
48
  const servicesDir = path.join(targetRoot, appTemplates_1.DEFAULT_DIRECTORIES.SERVICES);
49
+ const migrationsDir = path.join(targetRoot, appTemplates_1.DEFAULT_DIRECTORIES.MIGRATIONS);
49
50
  (0, cliUtils_1.ensureDir)(srcDir);
50
51
  (0, cliUtils_1.ensureDir)(distDir);
51
52
  (0, cliUtils_1.ensureDir)(webDir);
52
53
  (0, cliUtils_1.ensureDir)(templatesDir);
53
54
  (0, cliUtils_1.ensureDir)(servicesDir);
55
+ (0, cliUtils_1.ensureDir)(migrationsDir);
54
56
  // Files using imported templates
55
57
  (0, cliUtils_1.writeFileIfMissing)(path.join(targetRoot, appTemplates_1.DEFAULT_FILES.PACKAGE_JSON), (0, appTemplates_1.packageJsonTemplate)(path.basename(targetRoot)));
56
58
  (0, cliUtils_1.writeFileIfMissing)(path.join(targetRoot, appTemplates_1.DEFAULT_FILES.TSCONFIG), appTemplates_1.tsconfigTemplate);