@currentjs/gen 0.2.1 → 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 (41) hide show
  1. package/CHANGELOG.md +120 -0
  2. package/README.md +256 -8
  3. package/dist/cli.js +26 -0
  4. package/dist/commands/commit.js +4 -0
  5. package/dist/commands/createApp.js +7 -0
  6. package/dist/commands/diff.js +4 -0
  7. package/dist/commands/generateAll.js +159 -29
  8. package/dist/commands/migrateCommit.d.ts +1 -0
  9. package/dist/commands/migrateCommit.js +201 -0
  10. package/dist/generators/controllerGenerator.d.ts +7 -0
  11. package/dist/generators/controllerGenerator.js +60 -29
  12. package/dist/generators/domainModelGenerator.d.ts +8 -0
  13. package/dist/generators/domainModelGenerator.js +71 -4
  14. package/dist/generators/serviceGenerator.d.ts +17 -1
  15. package/dist/generators/serviceGenerator.js +139 -12
  16. package/dist/generators/storeGenerator.d.ts +9 -0
  17. package/dist/generators/storeGenerator.js +148 -8
  18. package/dist/generators/templateGenerator.d.ts +19 -0
  19. package/dist/generators/templateGenerator.js +216 -11
  20. package/dist/generators/templates/appTemplates.d.ts +8 -7
  21. package/dist/generators/templates/appTemplates.js +11 -1572
  22. package/dist/generators/templates/data/appTsTemplate +39 -0
  23. package/dist/generators/templates/data/appYamlTemplate +4 -0
  24. package/dist/generators/templates/data/cursorRulesTemplate +671 -0
  25. package/dist/generators/templates/data/errorTemplate +28 -0
  26. package/dist/generators/templates/data/frontendScriptTemplate +739 -0
  27. package/dist/generators/templates/data/mainViewTemplate +16 -0
  28. package/dist/generators/templates/data/translationsTemplate +68 -0
  29. package/dist/generators/templates/data/tsConfigTemplate +19 -0
  30. package/dist/generators/templates/viewTemplates.d.ts +10 -1
  31. package/dist/generators/templates/viewTemplates.js +138 -6
  32. package/dist/generators/validationGenerator.d.ts +5 -0
  33. package/dist/generators/validationGenerator.js +51 -0
  34. package/dist/utils/cliUtils.d.ts +6 -0
  35. package/dist/utils/cliUtils.js +24 -0
  36. package/dist/utils/constants.d.ts +3 -0
  37. package/dist/utils/constants.js +5 -2
  38. package/dist/utils/migrationUtils.d.ts +49 -0
  39. package/dist/utils/migrationUtils.js +291 -0
  40. package/howto.md +158 -66
  41. package/package.json +3 -2
@@ -50,6 +50,7 @@ class DomainModelGenerator {
50
50
  array: 'any[]',
51
51
  object: 'object'
52
52
  };
53
+ this.availableModels = new Set();
53
54
  }
54
55
  getDefaultValue(type) {
55
56
  switch (type) {
@@ -71,8 +72,27 @@ class DomainModelGenerator {
71
72
  }
72
73
  }
73
74
  mapType(yamlType) {
75
+ // Check if this is a known model (relationship)
76
+ if (this.availableModels.has(yamlType)) {
77
+ return yamlType;
78
+ }
74
79
  return this.typeMapping[yamlType] || 'any';
75
80
  }
81
+ setAvailableModels(models) {
82
+ this.availableModels.clear();
83
+ models.forEach(model => {
84
+ this.availableModels.add(model.name);
85
+ });
86
+ }
87
+ getRelatedModelImports(modelConfig) {
88
+ const imports = [];
89
+ modelConfig.fields.forEach(field => {
90
+ if (this.availableModels.has(field.type) && field.type !== modelConfig.name) {
91
+ imports.push(`import { ${field.type} } from './${field.type}';`);
92
+ }
93
+ });
94
+ return imports;
95
+ }
76
96
  generateConstructorParameter(field) {
77
97
  const tsType = this.mapType(field.type);
78
98
  const isOptional = !field.required && !field.auto;
@@ -87,14 +107,34 @@ class DomainModelGenerator {
87
107
  }
88
108
  return param;
89
109
  }
110
+ isRelationshipField(field) {
111
+ return this.availableModels.has(field.type);
112
+ }
113
+ getForeignKeyFieldName(field) {
114
+ // Convention: fieldName + 'Id' (e.g., owner -> ownerId)
115
+ return field.name + 'Id';
116
+ }
117
+ generateForeignKeyParameter(field) {
118
+ const foreignKeyName = this.getForeignKeyFieldName(field);
119
+ const isOptional = !field.required && !field.auto;
120
+ let param = `public ${foreignKeyName}`;
121
+ if (isOptional) {
122
+ param += '?';
123
+ }
124
+ param += ': number';
125
+ return param;
126
+ }
90
127
  generateSetterMethods(modelConfig) {
91
128
  const setterMethods = [];
92
129
  modelConfig.fields.forEach(field => {
93
130
  if (!field.auto && field.name !== 'id') {
94
131
  const tsType = this.mapType(field.type);
95
132
  const methodName = `set${field.name.charAt(0).toUpperCase() + field.name.slice(1)}`;
133
+ // For all fields (including relationships), generate simple setter
134
+ // Domain model doesn't care about FKs - that's infrastructure concern
135
+ const isOptional = !field.required && !field.auto;
96
136
  const setter = `
97
- ${methodName}(${field.name}: ${tsType}): void {
137
+ ${methodName}(${field.name}: ${tsType}${isOptional ? ' | undefined' : ''}): void {
98
138
  this.${field.name} = ${field.name};
99
139
  }`;
100
140
  setterMethods.push(setter);
@@ -102,17 +142,35 @@ class DomainModelGenerator {
102
142
  });
103
143
  return setterMethods.join('\n');
104
144
  }
145
+ sortFieldsByRequired(fields) {
146
+ // Sort fields: required fields first, then optional fields
147
+ return [...fields].sort((a, b) => {
148
+ const aRequired = a.required !== false && !a.auto;
149
+ const bRequired = b.required !== false && !b.auto;
150
+ if (aRequired === bRequired) {
151
+ return 0; // Keep original order if both have same required status
152
+ }
153
+ return aRequired ? -1 : 1; // Required fields come first
154
+ });
155
+ }
105
156
  generateModel(modelConfig) {
106
157
  const className = modelConfig.name;
107
158
  // Always add id field first
108
159
  const constructorParams = ['public id: number'];
160
+ // Sort fields to put required fields before optional ones
161
+ const sortedFields = this.sortFieldsByRequired(modelConfig.fields);
109
162
  // Process other fields
110
- modelConfig.fields.forEach(field => {
163
+ sortedFields.forEach(field => {
164
+ // For relationship fields, only add the relationship object (not FK)
165
+ // Domain model works with objects only - FK is infrastructure concern
111
166
  constructorParams.push(this.generateConstructorParameter(field));
112
167
  });
113
168
  const constructorParamsStr = constructorParams.join(',\n ');
114
169
  const setterMethods = this.generateSetterMethods(modelConfig);
115
- return `export class ${className} {
170
+ // Generate imports for related models
171
+ const imports = this.getRelatedModelImports(modelConfig);
172
+ const importsStr = imports.length > 0 ? imports.join('\n') + '\n\n' : '';
173
+ return `${importsStr}export class ${className} {
116
174
  public constructor(
117
175
  ${constructorParamsStr}
118
176
  ) { }
@@ -130,6 +188,8 @@ ${setterMethods}
130
188
  const app = config;
131
189
  Object.values(app.modules).forEach(moduleConfig => {
132
190
  if (moduleConfig.models && moduleConfig.models.length > 0) {
191
+ // Set available models for relationship detection
192
+ this.setAvailableModels(moduleConfig.models);
133
193
  moduleConfig.models.forEach(m => {
134
194
  result[m.name] = this.generateModel(m);
135
195
  });
@@ -138,6 +198,8 @@ ${setterMethods}
138
198
  }
139
199
  else if (config.models) {
140
200
  const module = config;
201
+ // Set available models for relationship detection
202
+ this.setAvailableModels(module.models);
141
203
  module.models.forEach(m => {
142
204
  result[m.name] = this.generateModel(m);
143
205
  });
@@ -149,6 +211,8 @@ ${setterMethods}
149
211
  if (config.modules) {
150
212
  Object.values(config.modules).forEach(moduleConfig => {
151
213
  if (moduleConfig.models && moduleConfig.models.length > 0) {
214
+ // Set available models for relationship detection
215
+ this.setAvailableModels(moduleConfig.models);
152
216
  moduleConfig.models.forEach(m => {
153
217
  result[m.name] = this.generateModel(m);
154
218
  });
@@ -156,7 +220,10 @@ ${setterMethods}
156
220
  });
157
221
  }
158
222
  else if (config.models) {
159
- config.models.forEach(m => {
223
+ const module = config;
224
+ // Set available models for relationship detection
225
+ this.setAvailableModels(module.models);
226
+ module.models.forEach(m => {
160
227
  result[m.name] = this.generateModel(m);
161
228
  });
162
229
  }
@@ -1,3 +1,11 @@
1
+ interface FieldConfig {
2
+ name: string;
3
+ type: string;
4
+ required?: boolean;
5
+ unique?: boolean;
6
+ auto?: boolean;
7
+ displayFields?: string[];
8
+ }
1
9
  interface ActionConfig {
2
10
  handlers: string[];
3
11
  }
@@ -7,7 +15,7 @@ interface PermissionConfig {
7
15
  }
8
16
  interface ModelConfig {
9
17
  name: string;
10
- fields: any[];
18
+ fields: FieldConfig[];
11
19
  }
12
20
  type ModuleConfig = {
13
21
  models?: ModelConfig[];
@@ -15,6 +23,10 @@ type ModuleConfig = {
15
23
  permissions?: PermissionConfig[];
16
24
  };
17
25
  export declare class ServiceGenerator {
26
+ private availableModels;
27
+ private setAvailableModels;
28
+ private isRelationshipField;
29
+ private getForeignKeyFieldName;
18
30
  private hasPermissions;
19
31
  private getActionPermissions;
20
32
  private generatePermissionCheck;
@@ -24,13 +36,17 @@ export declare class ServiceGenerator {
24
36
  private generateMethodImplementation;
25
37
  private extractFunctionName;
26
38
  private getMethodCallParams;
39
+ private sortFieldsByRequired;
27
40
  private generateConstructorArgs;
41
+ private generateRelationshipLoading;
28
42
  private generateUpdateSetterCalls;
29
43
  private replaceTemplateVars;
30
44
  private getServiceMethodName;
31
45
  private generateHandlerMethod;
32
46
  generateServiceForModel(model: ModelConfig, moduleName: string, moduleConfig: ModuleConfig, hasGlobalPermissions: boolean): string;
33
47
  generateService(moduleName: string, moduleConfig: ModuleConfig, hasGlobalPermissions: boolean): string;
48
+ private generateForeignStoreImports;
49
+ private generateForeignStoreConstructorParams;
34
50
  private generateCustomImports;
35
51
  generateFromYamlFile(yamlFilePath: string): Record<string, string>;
36
52
  generateAndSaveFiles(yamlFilePath?: string, outputDir?: string, opts?: {
@@ -42,6 +42,22 @@ const generationRegistry_1 = require("../utils/generationRegistry");
42
42
  const colors_1 = require("../utils/colors");
43
43
  const constants_1 = require("../utils/constants");
44
44
  class ServiceGenerator {
45
+ constructor() {
46
+ this.availableModels = new Set();
47
+ }
48
+ setAvailableModels(models) {
49
+ this.availableModels.clear();
50
+ models.forEach(model => {
51
+ this.availableModels.add(model.name);
52
+ });
53
+ }
54
+ isRelationshipField(field) {
55
+ return this.availableModels.has(field.type);
56
+ }
57
+ getForeignKeyFieldName(field) {
58
+ // Convention: fieldName + 'Id' (e.g., owner -> ownerId)
59
+ return field.name + 'Id';
60
+ }
45
61
  hasPermissions(config) {
46
62
  if (config.modules) {
47
63
  return Object.values(config.modules).some(module => module.permissions && module.permissions.length > 0);
@@ -198,12 +214,17 @@ class ServiceGenerator {
198
214
  .replace(/{{ENTITY_LOWER}}/g, entityLower);
199
215
  // Handle constructor args for create action
200
216
  if (actionName === 'create') {
217
+ const relationshipLoading = this.generateRelationshipLoading(moduleConfig, entityName);
201
218
  const constructorArgs = this.generateConstructorArgs(moduleConfig, entityName);
219
+ if (relationshipLoading) {
220
+ // Insert relationship loading before the entity creation
221
+ processedTemplate = relationshipLoading + '\n ' + processedTemplate;
222
+ }
202
223
  processedTemplate = processedTemplate.replace(/{{CONSTRUCTOR_ARGS}}/g, constructorArgs);
203
224
  }
204
225
  // Handle setter calls for update action
205
226
  if (actionName === 'update') {
206
- const setterCalls = this.generateUpdateSetterCalls(moduleConfig, entityName);
227
+ const setterCalls = this.generateUpdateSetterCalls(moduleConfig, entityName, true);
207
228
  processedTemplate = processedTemplate.replace(/{{UPDATE_SETTER_CALLS}}/g, setterCalls);
208
229
  }
209
230
  // Special-case: list action with only owner role → fetch by userId
@@ -288,34 +309,105 @@ class ServiceGenerator {
288
309
  return '/* custom params */';
289
310
  }
290
311
  }
312
+ sortFieldsByRequired(fields) {
313
+ // Sort fields: required fields first, then optional fields
314
+ // This must match the order used in domainModelGenerator
315
+ return [...fields].sort((a, b) => {
316
+ const aRequired = a.required !== false && !a.auto;
317
+ const bRequired = b.required !== false && !b.auto;
318
+ if (aRequired === bRequired) {
319
+ return 0; // Keep original order if both have same required status
320
+ }
321
+ return aRequired ? -1 : 1; // Required fields come first
322
+ });
323
+ }
291
324
  generateConstructorArgs(moduleConfig, entityName) {
292
325
  if (!moduleConfig.models || moduleConfig.models.length === 0) {
293
326
  return '';
294
327
  }
295
328
  // Find the correct model by entityName instead of always using first model
296
- const model = moduleConfig.models.find(m => m.name === entityName) || moduleConfig.models[0];
329
+ const model = moduleConfig.models.find((m) => m.name === entityName) || moduleConfig.models[0];
297
330
  const entityLower = entityName.toLowerCase();
298
- return model.fields
331
+ // Sort fields to match the constructor parameter order
332
+ const sortedFields = this.sortFieldsByRequired(model.fields);
333
+ const args = [];
334
+ sortedFields
299
335
  .filter(field => !field.auto && field.name !== 'id')
300
- .map(field => `${entityLower}Data.${field.name}`)
301
- .join(', ');
336
+ .forEach(field => {
337
+ // For relationship fields, reference the loaded object variable
338
+ if (this.isRelationshipField(field)) {
339
+ args.push(`${field.name}Object`);
340
+ }
341
+ else {
342
+ args.push(`${entityLower}Data.${field.name}`);
343
+ }
344
+ });
345
+ return args.join(', ');
346
+ }
347
+ generateRelationshipLoading(moduleConfig, entityName) {
348
+ if (!moduleConfig.models || moduleConfig.models.length === 0) {
349
+ return '';
350
+ }
351
+ const model = moduleConfig.models.find((m) => m.name === entityName) || moduleConfig.models[0];
352
+ const entityLower = entityName.toLowerCase();
353
+ const relationshipFields = model.fields.filter(f => this.isRelationshipField(f));
354
+ if (relationshipFields.length === 0) {
355
+ return '';
356
+ }
357
+ const loadingCode = relationshipFields.map(field => {
358
+ const foreignKeyName = this.getForeignKeyFieldName(field);
359
+ const relatedModel = field.type;
360
+ const relatedModelLower = relatedModel.toLowerCase();
361
+ const varName = `${field.name}Object`;
362
+ if (field.required) {
363
+ return `const ${varName} = await this.${relatedModelLower}Store.getById(${entityLower}Data.${foreignKeyName});
364
+ if (!${varName}) {
365
+ throw new Error('${relatedModel} not found with id ' + ${entityLower}Data.${foreignKeyName});
366
+ }`;
367
+ }
368
+ else {
369
+ return `const ${varName} = ${entityLower}Data.${foreignKeyName}
370
+ ? await this.${relatedModelLower}Store.getById(${entityLower}Data.${foreignKeyName})
371
+ : null;`;
372
+ }
373
+ }).join('\n ');
374
+ return ' // Load relationship objects\n ' + loadingCode;
302
375
  }
303
- generateUpdateSetterCalls(moduleConfig, entityName) {
376
+ generateUpdateSetterCalls(moduleConfig, entityName, includeRelationshipLoading = false) {
304
377
  if (!moduleConfig.models || moduleConfig.models.length === 0) {
305
378
  return '';
306
379
  }
307
380
  // Find the correct model by entityName instead of always using first model
308
381
  const model = moduleConfig.models.find(m => m.name === entityName) || moduleConfig.models[0];
309
382
  const entityLower = entityName.toLowerCase();
310
- return model.fields
383
+ let code = '';
384
+ // Add relationship loading if requested
385
+ if (includeRelationshipLoading) {
386
+ const relationshipLoading = this.generateRelationshipLoading(moduleConfig, entityName);
387
+ if (relationshipLoading) {
388
+ code = relationshipLoading + '\n ';
389
+ }
390
+ }
391
+ const setterCalls = model.fields
311
392
  .filter(field => !field.auto && field.name !== 'id')
312
393
  .map(field => {
313
- const methodName = `set${field.name.charAt(0).toUpperCase() + field.name.slice(1)}`;
314
- return `if (${entityLower}Data.${field.name} !== undefined) {
394
+ // For relationship fields, set the loaded object
395
+ if (this.isRelationshipField(field)) {
396
+ const foreignKeyName = this.getForeignKeyFieldName(field);
397
+ const methodName = `set${field.name.charAt(0).toUpperCase() + field.name.slice(1)}`;
398
+ return `if (${entityLower}Data.${foreignKeyName} !== undefined) {
399
+ existing${entityName}.${methodName}(${field.name}Object);
400
+ }`;
401
+ }
402
+ else {
403
+ const methodName = `set${field.name.charAt(0).toUpperCase() + field.name.slice(1)}`;
404
+ return `if (${entityLower}Data.${field.name} !== undefined) {
315
405
  existing${entityName}.${methodName}(${entityLower}Data.${field.name});
316
406
  }`;
407
+ }
317
408
  })
318
409
  .join('\n ');
410
+ return code + setterCalls;
319
411
  }
320
412
  replaceTemplateVars(template, variables) {
321
413
  let result = template;
@@ -393,12 +485,17 @@ class ServiceGenerator {
393
485
  .replace(/{{ENTITY_LOWER}}/g, entityLower);
394
486
  // Handle constructor args for create action
395
487
  if (actionName === 'create') {
488
+ const relationshipLoading = this.generateRelationshipLoading(moduleConfig, entityName);
396
489
  const constructorArgs = this.generateConstructorArgs(moduleConfig, entityName);
490
+ if (relationshipLoading) {
491
+ // Insert relationship loading before the entity creation
492
+ methodImplementation = relationshipLoading + '\n ' + methodImplementation;
493
+ }
397
494
  methodImplementation = methodImplementation.replace(/{{CONSTRUCTOR_ARGS}}/g, constructorArgs);
398
495
  }
399
496
  // Handle setter calls for update action
400
497
  if (actionName === 'update') {
401
- const setterCalls = this.generateUpdateSetterCalls(moduleConfig, entityName);
498
+ const setterCalls = this.generateUpdateSetterCalls(moduleConfig, entityName, true);
402
499
  methodImplementation = methodImplementation.replace(/{{UPDATE_SETTER_CALLS}}/g, setterCalls);
403
500
  }
404
501
  // Special-case: list action with only owner role → fetch by userId
@@ -464,17 +561,20 @@ class ServiceGenerator {
464
561
  })
465
562
  .filter(method => method) // Remove empty methods
466
563
  .join('\n\n');
564
+ // Add foreign store constructor params
565
+ const foreignStoreParams = this.generateForeignStoreConstructorParams(model);
467
566
  const serviceClass = this.replaceTemplateVars(serviceTemplates_1.serviceTemplates.serviceClass, {
468
567
  ENTITY_NAME: entityName,
469
568
  ENTITY_LOWER: entityLower,
470
- AUTH_SERVICE_PARAM: '',
569
+ AUTH_SERVICE_PARAM: foreignStoreParams,
471
570
  SERVICE_METHODS: serviceMethods
472
571
  });
473
572
  const customImports = this.generateCustomImports(moduleConfig);
573
+ const foreignStoreImports = this.generateForeignStoreImports(model);
474
574
  return this.replaceTemplateVars(serviceTemplates_1.serviceFileTemplate, {
475
575
  ENTITY_NAME: entityName,
476
576
  PERMISSIONS_IMPORT: hasPermissions ? "\nimport type { AuthenticatedUser } from '@currentjs/router';" : '',
477
- CUSTOM_IMPORTS: customImports,
577
+ CUSTOM_IMPORTS: customImports + foreignStoreImports,
478
578
  SERVICE_CLASS: serviceClass
479
579
  });
480
580
  }
@@ -485,6 +585,29 @@ class ServiceGenerator {
485
585
  }
486
586
  return this.generateServiceForModel(moduleConfig.models[0], moduleName, moduleConfig, hasGlobalPermissions);
487
587
  }
588
+ generateForeignStoreImports(model) {
589
+ const relationshipFields = model.fields.filter(f => this.isRelationshipField(f));
590
+ if (relationshipFields.length === 0) {
591
+ return '';
592
+ }
593
+ const imports = relationshipFields.map(field => {
594
+ const relatedModel = field.type;
595
+ return `import { ${relatedModel}Store } from '../../infrastructure/stores/${relatedModel}Store';`;
596
+ });
597
+ return '\n' + imports.join('\n');
598
+ }
599
+ generateForeignStoreConstructorParams(model) {
600
+ const relationshipFields = model.fields.filter(f => this.isRelationshipField(f));
601
+ if (relationshipFields.length === 0) {
602
+ return '';
603
+ }
604
+ const params = relationshipFields.map(field => {
605
+ const relatedModel = field.type;
606
+ const relatedModelLower = relatedModel.toLowerCase();
607
+ return `,\n private ${relatedModelLower}Store: ${relatedModel}Store`;
608
+ });
609
+ return params.join('');
610
+ }
488
611
  generateCustomImports(moduleConfig) {
489
612
  if (!moduleConfig.actions)
490
613
  return '';
@@ -510,6 +633,8 @@ class ServiceGenerator {
510
633
  if (config.modules) {
511
634
  Object.entries(config.modules).forEach(([moduleName, moduleConfig]) => {
512
635
  if (moduleConfig.models && moduleConfig.models.length > 0) {
636
+ // Set available models for relationship detection
637
+ this.setAvailableModels(moduleConfig.models);
513
638
  // Generate a service for each model
514
639
  moduleConfig.models.forEach(model => {
515
640
  const serviceCode = this.generateServiceForModel(model, moduleName, moduleConfig, hasGlobalPermissions);
@@ -524,6 +649,8 @@ class ServiceGenerator {
524
649
  const moduleName = 'Module';
525
650
  const moduleConfig = config;
526
651
  if (moduleConfig.models && moduleConfig.models.length > 0) {
652
+ // Set available models for relationship detection
653
+ this.setAvailableModels(moduleConfig.models);
527
654
  // Generate a service for each model
528
655
  moduleConfig.models.forEach(model => {
529
656
  const serviceCode = this.generateServiceForModel(model, moduleName, moduleConfig, hasGlobalPermissions);
@@ -4,6 +4,7 @@ interface FieldConfig {
4
4
  required?: boolean;
5
5
  unique?: boolean;
6
6
  auto?: boolean;
7
+ displayFields?: string[];
7
8
  }
8
9
  interface ModelConfig {
9
10
  name: string;
@@ -11,15 +12,23 @@ interface ModelConfig {
11
12
  }
12
13
  export declare class StoreGenerator {
13
14
  private typeMapping;
15
+ private availableModels;
14
16
  private mapType;
17
+ private setAvailableModels;
18
+ private isRelationshipField;
19
+ private getForeignKeyFieldName;
15
20
  private generateRowFields;
16
21
  private generateFilterableFields;
17
22
  private generateFilterableFieldsArray;
18
23
  private generateUpdatableFieldsArray;
24
+ private sortFieldsByRequired;
19
25
  private generateRowToModelMapping;
20
26
  private generateModelToRowMapping;
21
27
  private replaceTemplateVars;
22
28
  generateStoreInterface(): string;
29
+ private generateRelationshipMethods;
30
+ private generateStoreConstructorParams;
31
+ private generateRelationshipImports;
23
32
  generateStore(modelConfig: ModelConfig): string;
24
33
  generateStores(models: ModelConfig[]): Record<string, string>;
25
34
  generateFromYamlFile(yamlFilePath: string): Record<string, string>;