@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.
@@ -50,6 +50,7 @@ function moduleYamlTemplate(moduleName) {
50
50
  ],
51
51
  api: {
52
52
  prefix: `/api/${lower}`,
53
+ model: entityName,
53
54
  endpoints: [
54
55
  { method: 'GET', path: '/', action: 'list' },
55
56
  { method: 'GET', path: '/:id', action: 'get' },
@@ -60,6 +61,7 @@ function moduleYamlTemplate(moduleName) {
60
61
  },
61
62
  routes: {
62
63
  prefix: `/${lower}`,
64
+ model: entityName,
63
65
  strategy: ['back', 'toast'],
64
66
  endpoints: [
65
67
  //bug: the order of the endpoints is important (to fix it in the router)
@@ -70,11 +72,11 @@ function moduleYamlTemplate(moduleName) {
70
72
  ]
71
73
  },
72
74
  actions: {
73
- list: { handlers: ['default:list'] },
74
- get: { handlers: ['default:getById'] },
75
- create: { handlers: ['default:create'] },
76
- update: { handlers: ['default:update'] },
77
- delete: { handlers: ['default:delete'] }
75
+ list: { handlers: [`${entityName}:default:list`] },
76
+ get: { handlers: [`${entityName}:default:get`] },
77
+ create: { handlers: [`${entityName}:default:create`] },
78
+ update: { handlers: [`${entityName}:default:update`] },
79
+ delete: { handlers: [`${entityName}:default:delete`] }
78
80
  },
79
81
  permissions: []
80
82
  };
@@ -5,12 +5,15 @@ export declare class ControllerGenerator {
5
5
  private needsUserParam;
6
6
  private getHttpMethodName;
7
7
  private getHttpDecorator;
8
+ private getMethodCallParams;
9
+ private generateParameterExtractions;
8
10
  private generateMethodImplementation;
9
11
  private replaceTemplateVars;
10
12
  private generateControllerMethod;
11
13
  private getWebMethodName;
12
14
  private getPathSuffix;
13
15
  private getReturnType;
16
+ private generateControllerForModel;
14
17
  private generateController;
15
18
  generateFromYamlFile(yamlFilePath: string): Record<string, string>;
16
19
  generateAndSaveFiles(yamlFilePath?: string, outputDir?: string, opts?: {
@@ -91,7 +91,92 @@ class ControllerGenerator {
91
91
  return 'Get';
92
92
  }
93
93
  }
94
- generateMethodImplementation(action, entityName, hasUserParam) {
94
+ getMethodCallParams(action, entityName) {
95
+ const dtoType = entityName ? `${entityName}DTO` : 'any';
96
+ switch (action) {
97
+ case 'list':
98
+ return 'page, limit';
99
+ case 'get':
100
+ case 'getById':
101
+ return 'id';
102
+ case 'create':
103
+ return `context.request.body as ${dtoType}`;
104
+ case 'update':
105
+ return `id, context.request.body as ${dtoType}`;
106
+ case 'delete':
107
+ return 'id';
108
+ default:
109
+ return '/* custom params */';
110
+ }
111
+ }
112
+ generateParameterExtractions(action) {
113
+ switch (action) {
114
+ case 'list':
115
+ return `
116
+ // Extract pagination from URL parameters
117
+ const page = parseInt(context.request.parameters.page as string) || 1;
118
+ const limit = parseInt(context.request.parameters.limit as string) || 10;`;
119
+ case 'get':
120
+ case 'getById':
121
+ case 'update':
122
+ case 'delete':
123
+ return `
124
+ const id = parseInt(context.request.parameters.id as string);
125
+ if (isNaN(id)) {
126
+ throw new Error('Invalid ID parameter');
127
+ }`;
128
+ case 'create':
129
+ return ''; // No additional parameter extraction needed for create
130
+ default:
131
+ return '';
132
+ }
133
+ }
134
+ generateMethodImplementation(action, entityName, hasUserParam, actions) {
135
+ // Check if we have action handlers
136
+ if (actions && actions[action] && actions[action].handlers) {
137
+ const handlers = actions[action].handlers;
138
+ const entityLower = entityName.toLowerCase();
139
+ // Filter handlers that apply to this model
140
+ const modelHandlers = handlers.filter(h => h.startsWith(`${entityLower}:`) || h.startsWith(`${entityName}:`));
141
+ if (modelHandlers.length === 0) {
142
+ return `// TODO: No valid handlers found for action ${action}. Use ${entityName}:default:${action} or ${entityName}:customMethodName format.`;
143
+ }
144
+ const userExtraction = hasUserParam ? controllerTemplates_1.controllerTemplates.userExtraction : '';
145
+ const userParam = hasUserParam ? ', user' : '';
146
+ // Generate parameter extraction based on action type
147
+ const paramExtractions = this.generateParameterExtractions(action);
148
+ // Generate step-by-step calls for each handler
149
+ const handlerCalls = modelHandlers.map((handler, index) => {
150
+ const parts = handler.split(':');
151
+ let methodName;
152
+ let params;
153
+ if (parts.length === 3 && parts[1] === 'default') {
154
+ // Format: modelname:default:action
155
+ const actionName = parts[2];
156
+ methodName = actionName === 'getById' ? 'get' : actionName; // Use 'get' instead of 'getById'
157
+ // For default handlers, use extracted parameters
158
+ params = this.getMethodCallParams(actionName, entityName) + userParam;
159
+ }
160
+ else if (parts.length === 2) {
161
+ // Format: modelname:custommethod
162
+ methodName = parts[1];
163
+ // For custom handlers, pass result from previous handler (or null) and context
164
+ const prevResult = index === 0 ? 'null' : `result${index}`;
165
+ params = `${prevResult}, context${userParam}`;
166
+ }
167
+ else {
168
+ return `// Invalid handler format: ${handler}`;
169
+ }
170
+ const isLast = index === modelHandlers.length - 1;
171
+ const resultVar = isLast ? 'result' : `result${index + 1}`;
172
+ return `const ${resultVar} = await this.${entityLower}Service.${methodName}(${params});`;
173
+ }).join('\n ');
174
+ // For multiple handlers, return the last result
175
+ const returnStatement = '\n return result;';
176
+ return `${userExtraction}${paramExtractions}
177
+ ${handlerCalls}${returnStatement}`;
178
+ }
179
+ // Fallback to existing template lookup
95
180
  const template = controllerTemplates_1.controllerTemplates.methodImplementations[action];
96
181
  if (!template) {
97
182
  return ` // TODO: Implement ${action} method\n return {} as any;`;
@@ -112,11 +197,11 @@ class ControllerGenerator {
112
197
  });
113
198
  return result;
114
199
  }
115
- generateControllerMethod(endpoint, entityName, roles, hasPermissions, kind) {
200
+ generateControllerMethod(endpoint, entityName, roles, hasPermissions, kind, actions) {
116
201
  const methodName = kind === 'web' ? this.getWebMethodName(endpoint) : this.getHttpMethodName(endpoint.method, endpoint.action);
117
202
  const httpDecorator = kind === 'web' ? 'Get' : this.getHttpDecorator(endpoint.method);
118
203
  const needsUser = this.needsUserParam(roles);
119
- const methodImplementation = this.generateMethodImplementation(endpoint.action, entityName, needsUser);
204
+ const methodImplementation = this.generateMethodImplementation(endpoint.action, entityName, needsUser, actions);
120
205
  const returnType = this.getReturnType(endpoint.action, entityName);
121
206
  const renderDecorator = kind === 'web' && endpoint.view
122
207
  ? `\n @Render("${endpoint.view}"${endpoint.layout ? `, "${endpoint.layout}"` : ', "main_view"'})`
@@ -169,17 +254,27 @@ class ControllerGenerator {
169
254
  return 'any';
170
255
  }
171
256
  }
172
- generateController(moduleName, moduleConfig, hasGlobalPermissions, kind) {
173
- if (!moduleConfig.models || moduleConfig.models.length === 0) {
174
- return '';
175
- }
257
+ generateControllerForModel(model, moduleName, moduleConfig, hasGlobalPermissions, kind) {
258
+ var _a;
176
259
  const isApi = kind === 'api';
177
260
  const cfgRaw = isApi ? moduleConfig.api : moduleConfig.routes;
178
261
  let cfg = cfgRaw;
262
+ const entityName = model.name;
263
+ const entityLower = entityName.toLowerCase();
264
+ // Determine if we should generate a controller for this model
265
+ const configModel = (cfg === null || cfg === void 0 ? void 0 : cfg.model) || (moduleConfig.models && moduleConfig.models[0] ? moduleConfig.models[0].name : null);
266
+ const topLevelMatches = !configModel || configModel === entityName || configModel.toLowerCase() === entityLower;
267
+ // Also check if any endpoints specifically target this model
268
+ const hasEndpointForThisModel = ((_a = cfg === null || cfg === void 0 ? void 0 : cfg.endpoints) === null || _a === void 0 ? void 0 : _a.some(endpoint => {
269
+ const endpointModel = endpoint.model || configModel;
270
+ return endpointModel === entityName || (endpointModel === null || endpointModel === void 0 ? void 0 : endpointModel.toLowerCase()) === entityLower;
271
+ })) || false;
272
+ const shouldGenerateForThisModel = topLevelMatches || hasEndpointForThisModel;
273
+ if (!shouldGenerateForThisModel) {
274
+ return '';
275
+ }
179
276
  if (!isApi) {
180
277
  // Ensure sensible defaults for Web routes: list, detail, create (empty), edit (get)
181
- const entityName = moduleConfig.models[0].name;
182
- const entityLower = entityName.toLowerCase();
183
278
  if (!cfgRaw || !cfgRaw.endpoints || cfgRaw.endpoints.length === 0) {
184
279
  cfg = {
185
280
  prefix: `/${entityLower}`,
@@ -201,19 +296,22 @@ class ControllerGenerator {
201
296
  }
202
297
  if (!cfg)
203
298
  return '';
204
- const entityName = moduleConfig.models[0].name;
205
- const entityLower = entityName.toLowerCase();
206
299
  const controllerBase = (cfg.prefix || `/${isApi ? 'api/' : ''}${entityLower}`).replace(/\/$/, '');
207
300
  const actionPermissions = this.getActionPermissions(moduleName, moduleConfig);
208
301
  const hasPermissions = hasGlobalPermissions && !!(moduleConfig.permissions && moduleConfig.permissions.length > 0);
209
- const controllerMethods = (cfg.endpoints || [])
302
+ // Filter endpoints that apply to this model
303
+ const modelEndpoints = (cfg.endpoints || []).filter(endpoint => {
304
+ const endpointModel = endpoint.model || (cfg === null || cfg === void 0 ? void 0 : cfg.model) || (moduleConfig.models && moduleConfig.models[0] ? moduleConfig.models[0].name : null);
305
+ return endpointModel === entityName || (endpointModel === null || endpointModel === void 0 ? void 0 : endpointModel.toLowerCase()) === entityLower;
306
+ });
307
+ const controllerMethods = modelEndpoints
210
308
  .filter(endpoint => {
211
309
  const roles = actionPermissions[endpoint.action] || [];
212
310
  return this.shouldGenerateMethod(endpoint.action, roles);
213
311
  })
214
312
  .map(endpoint => {
215
313
  const roles = actionPermissions[endpoint.action] || [];
216
- return this.generateControllerMethod(endpoint, entityName, roles, hasPermissions, kind);
314
+ return this.generateControllerMethod(endpoint, entityName, roles, hasPermissions, kind, moduleConfig.actions);
217
315
  })
218
316
  .join('\n\n');
219
317
  const controllerClass = this.replaceTemplateVars(controllerTemplates_1.controllerTemplates.controllerClass, {
@@ -229,6 +327,13 @@ class ControllerGenerator {
229
327
  CONTROLLER_CLASS: controllerClass
230
328
  });
231
329
  }
330
+ generateController(moduleName, moduleConfig, hasGlobalPermissions, kind) {
331
+ // Legacy method for backward compatibility - use first model
332
+ if (!moduleConfig.models || moduleConfig.models.length === 0) {
333
+ return '';
334
+ }
335
+ return this.generateControllerForModel(moduleConfig.models[0], moduleName, moduleConfig, hasGlobalPermissions, kind);
336
+ }
232
337
  generateFromYamlFile(yamlFilePath) {
233
338
  const yamlContent = fs.readFileSync(yamlFilePath, 'utf8');
234
339
  const config = (0, yaml_1.parse)(yamlContent);
@@ -236,24 +341,33 @@ class ControllerGenerator {
236
341
  const hasGlobalPermissions = this.hasPermissions(config);
237
342
  if (config.modules) {
238
343
  Object.entries(config.modules).forEach(([moduleName, moduleConfig]) => {
239
- const entityName = moduleConfig.models && moduleConfig.models[0] ? moduleConfig.models[0].name : 'Module';
240
- const apiControllerCode = this.generateController(moduleName, moduleConfig, hasGlobalPermissions, 'api');
241
- if (apiControllerCode)
242
- result[`${entityName}Api`] = apiControllerCode;
243
- const webControllerCode = this.generateController(moduleName, moduleConfig, hasGlobalPermissions, 'web');
244
- if (webControllerCode)
245
- result[`${entityName}Web`] = webControllerCode;
344
+ if (moduleConfig.models && moduleConfig.models.length > 0) {
345
+ // Generate controllers for each model
346
+ moduleConfig.models.forEach(model => {
347
+ const apiControllerCode = this.generateControllerForModel(model, moduleName, moduleConfig, hasGlobalPermissions, 'api');
348
+ if (apiControllerCode)
349
+ result[`${model.name}Api`] = apiControllerCode;
350
+ const webControllerCode = this.generateControllerForModel(model, moduleName, moduleConfig, hasGlobalPermissions, 'web');
351
+ if (webControllerCode)
352
+ result[`${model.name}Web`] = webControllerCode;
353
+ });
354
+ }
246
355
  });
247
356
  }
248
357
  else {
358
+ const moduleName = 'Module';
249
359
  const moduleConfig = config;
250
- const moduleName = moduleConfig.models && moduleConfig.models[0] ? moduleConfig.models[0].name : 'Module';
251
- const apiControllerCode = this.generateController(moduleName, moduleConfig, hasGlobalPermissions, 'api');
252
- if (apiControllerCode)
253
- result[`${moduleName}Api`] = apiControllerCode;
254
- const webControllerCode = this.generateController(moduleName, moduleConfig, hasGlobalPermissions, 'web');
255
- if (webControllerCode)
256
- result[`${moduleName}Web`] = webControllerCode;
360
+ if (moduleConfig.models && moduleConfig.models.length > 0) {
361
+ // Generate controllers for each model
362
+ moduleConfig.models.forEach(model => {
363
+ const apiControllerCode = this.generateControllerForModel(model, moduleName, moduleConfig, hasGlobalPermissions, 'api');
364
+ if (apiControllerCode)
365
+ result[`${model.name}Api`] = apiControllerCode;
366
+ const webControllerCode = this.generateControllerForModel(model, moduleName, moduleConfig, hasGlobalPermissions, 'web');
367
+ if (webControllerCode)
368
+ result[`${model.name}Web`] = webControllerCode;
369
+ });
370
+ }
257
371
  }
258
372
  return result;
259
373
  }
@@ -27,7 +27,9 @@ export declare class ServiceGenerator {
27
27
  private generateConstructorArgs;
28
28
  private generateUpdateSetterCalls;
29
29
  private replaceTemplateVars;
30
- private generateServiceMethod;
30
+ private getServiceMethodName;
31
+ private generateHandlerMethod;
32
+ generateServiceForModel(model: ModelConfig, moduleName: string, moduleConfig: ModuleConfig, hasGlobalPermissions: boolean): string;
31
33
  generateService(moduleName: string, moduleConfig: ModuleConfig, hasGlobalPermissions: boolean): string;
32
34
  private generateCustomImports;
33
35
  generateFromYamlFile(yamlFilePath: string): Record<string, string>;