@solidstarters/solid-core 1.2.178 → 1.2.180

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 (42) hide show
  1. package/dist/controllers/ai-interaction.controller.js.map +1 -1
  2. package/dist/controllers/service.controller.d.ts +8 -1
  3. package/dist/controllers/service.controller.d.ts.map +1 -1
  4. package/dist/controllers/service.controller.js +39 -2
  5. package/dist/controllers/service.controller.js.map +1 -1
  6. package/dist/helpers/date.helper.d.ts +2 -0
  7. package/dist/helpers/date.helper.d.ts.map +1 -0
  8. package/dist/helpers/date.helper.js +18 -0
  9. package/dist/helpers/date.helper.js.map +1 -0
  10. package/dist/jobs/database/trigger-mcp-client-subscriber-database.service.d.ts.map +1 -1
  11. package/dist/jobs/database/trigger-mcp-client-subscriber-database.service.js +23 -17
  12. package/dist/jobs/database/trigger-mcp-client-subscriber-database.service.js.map +1 -1
  13. package/dist/seeders/seed-data/solid-core-metadata.json +2 -1
  14. package/dist/services/ai-interaction.service.d.ts.map +1 -1
  15. package/dist/services/ai-interaction.service.js +11 -3
  16. package/dist/services/ai-interaction.service.js.map +1 -1
  17. package/dist/services/excel.service.js +2 -2
  18. package/dist/services/excel.service.js.map +1 -1
  19. package/dist/services/genai/ingest-metadata.service.d.ts.map +1 -1
  20. package/dist/services/genai/ingest-metadata.service.js +9 -8
  21. package/dist/services/genai/ingest-metadata.service.js.map +1 -1
  22. package/dist/services/import-transaction.service.d.ts.map +1 -1
  23. package/dist/services/import-transaction.service.js +37 -10
  24. package/dist/services/import-transaction.service.js.map +1 -1
  25. package/dist/services/mcp-tool-response-handlers/solid-create-model-with-fields-mcp-tool-response-handler.service.d.ts.map +1 -1
  26. package/dist/services/mcp-tool-response-handlers/solid-create-model-with-fields-mcp-tool-response-handler.service.js +2 -2
  27. package/dist/services/mcp-tool-response-handlers/solid-create-model-with-fields-mcp-tool-response-handler.service.js.map +1 -1
  28. package/dist/services/mcp-tool-response-handlers/solid-create-module-mcp-tool-response-handler.service.js +2 -2
  29. package/dist/services/mcp-tool-response-handlers/solid-create-module-mcp-tool-response-handler.service.js.map +1 -1
  30. package/dist/tsconfig.tsbuildinfo +1 -1
  31. package/package.json +3 -2
  32. package/src/controllers/ai-interaction.controller.ts +1 -1
  33. package/src/controllers/service.controller.ts +40 -2
  34. package/src/helpers/date.helper.ts +13 -0
  35. package/src/jobs/database/trigger-mcp-client-subscriber-database.service.ts +27 -18
  36. package/src/seeders/seed-data/solid-core-metadata.json +3 -1
  37. package/src/services/ai-interaction.service.ts +14 -7
  38. package/src/services/excel.service.ts +2 -2
  39. package/src/services/genai/ingest-metadata.service.ts +34 -8
  40. package/src/services/import-transaction.service.ts +46 -11
  41. package/src/services/mcp-tool-response-handlers/solid-create-model-with-fields-mcp-tool-response-handler.service.ts +3 -2
  42. package/src/services/mcp-tool-response-handlers/solid-create-module-mcp-tool-response-handler.service.ts +2 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solidstarters/solid-core",
3
- "version": "1.2.178",
3
+ "version": "1.2.180",
4
4
  "description": "This module is a NestJS module containing all the required core providers required by a Solid application",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -49,6 +49,7 @@
49
49
  "cache-manager-redis-store": "^3.0.1",
50
50
  "class-transformer": "^0.5.1",
51
51
  "class-validator": "^0.14.1",
52
+ "dayjs": "^1.11.18",
52
53
  "exceljs": "^4.4.0",
53
54
  "fast-csv": "^5.0.2",
54
55
  "handlebars": "^4.7.8",
@@ -69,7 +70,7 @@
69
70
  "pluralize": "^8.0.0",
70
71
  "puppeteer": "^23.2.0",
71
72
  "r2r-js": "^0.4.43",
72
- "reflect-metadata": "^0.1.13",
73
+ "reflect-metadata": "^0.2.2",
73
74
  "rxjs": "^7.8.1",
74
75
  "swagger-ui-express": "^5.0.0",
75
76
  "twilio": "^5.8.0",
@@ -95,7 +95,7 @@ export class AiInteractionController {
95
95
  @ApiBearerAuth("jwt")
96
96
  @Post('/trigger-mcp-client-job')
97
97
  async triggerMcpClientJob(@Body() dto: InvokeAiPromptDto, @ActiveUser() activeUser: ActiveUserData) {
98
- return this.service.triggerMcpClientJob(dto,activeUser.sub);
98
+ return this.service.triggerMcpClientJob(dto, activeUser.sub);
99
99
  }
100
100
 
101
101
  @ApiBearerAuth("jwt")
@@ -5,10 +5,14 @@ import { Public } from 'src/decorators/public.decorator';
5
5
  import { ErrorMapperService } from 'src/helpers/error-mapper.service';
6
6
  import { ActiveUserData } from 'src/interfaces/active-user-data.interface';
7
7
  import { AiInteractionService } from 'src/services/ai-interaction.service';
8
+ import { IngestMetadataService } from 'src/services/genai/ingest-metadata.service';
8
9
  import { MqMessageService } from 'src/services/mq-message.service';
9
10
  import { SolidRegistry } from '../helpers/solid-registry';
10
11
 
11
-
12
+ export interface PostProcessCodeGenConfig {
13
+ runModuleMetadataSeeder?: boolean; // If true, regenerate module metadata
14
+ runSolidIngestion?: boolean; // If true, run solid ingestion command
15
+ }
12
16
  @Controller('')
13
17
  @ApiTags("Common")
14
18
  // @UseGuards(ThrottlerGuard)
@@ -20,7 +24,9 @@ export class ServiceController {
20
24
  private readonly solidRegistry: SolidRegistry,
21
25
  private readonly aiInteractionService: AiInteractionService,
22
26
  private readonly mqMessageService: MqMessageService,
23
- private readonly errorMapper: ErrorMapperService
27
+ private readonly errorMapper: ErrorMapperService,
28
+ private readonly ingestMetadataService: IngestMetadataService,
29
+
24
30
  ) { }
25
31
 
26
32
  @Public()
@@ -103,6 +109,38 @@ export class ServiceController {
103
109
  return { message: `seed data for ${seedData.seeder}` };
104
110
  }
105
111
 
112
+ @ApiBearerAuth("jwt")
113
+ @Post('code-generation/post-process')
114
+ async postProcessCodeGeneration(@Body() config : PostProcessCodeGenConfig) {
115
+ // Set defaults if not provided
116
+ config.runModuleMetadataSeeder = config.runModuleMetadataSeeder ?? true;
117
+ config.runSolidIngestion = config.runSolidIngestion ?? true;
118
+
119
+ // Run the Module Metadata Seeder Service
120
+ if (config.runModuleMetadataSeeder) {
121
+ this.logger.debug(`Running the Module Metadata Seeder Service as part of post-process code generation`);
122
+ const seeder = this.solidRegistry
123
+ .getSeeders()
124
+ .filter((seeder) => seeder.name === 'ModuleMetadataSeederService')
125
+ .map((seeder) => seeder.instance)
126
+ .pop();
127
+ if (!seeder) {
128
+ this.logger.error(`Seeder service ModuleMetadataSeederService not found. Does your service have a seed() method?`);
129
+ } else {
130
+ await seeder.seed();
131
+ }
132
+ } else {
133
+ this.logger.debug(`Skipping the Module Metadata Seeder Service as part of post-process code generation`);
134
+ }
135
+
136
+ // Run the Solid ingestion command
137
+ if (config.runSolidIngestion) {
138
+ this.logger.debug(`Running the Solid ingestion command as part of post-process code generation`);
139
+ await this.ingestMetadataService.ingest();
140
+ }
141
+ }
142
+
143
+
106
144
  // @Public()
107
145
  // @Get('play')
108
146
  // play() {
@@ -0,0 +1,13 @@
1
+ import dayjs from 'dayjs';
2
+
3
+
4
+ export function parseFlexibleDate(value: string): Date | null {
5
+ if (!value) return null;
6
+ const formats = ['DD-MM-YYYY', 'YYYY-MM-DD'];
7
+ const parsed = dayjs(value, formats, true); // true = strict parsing
8
+ if (!parsed.isValid()) {
9
+ return null;
10
+ }
11
+ return parsed.toDate();
12
+ }
13
+
@@ -92,22 +92,26 @@ export class TriggerMcpClientSubscriberDatabase extends DatabaseSubscriber<Trigg
92
92
  responseTimeMs: 0, // Updated after we receive the response
93
93
  metadata: '', // Updated in the tool
94
94
  isApplied: false, // Updated after we receive the response
95
- status: '' // Updated after we receive the response
95
+ status: 'pending' // Updated after we receive the response
96
96
  });
97
97
 
98
98
  const finalPrompt = `
99
- # User Prompt:
100
- ${prompt}
101
-
102
- # System Instructions:
103
- - aiInteractionId: ${genAiInteraction.id}
104
- - moduleName:${message.payload.moduleName}
105
- - You will be invoking tools if needed.
106
- - If a tool is invoked, you must return **exactly** the raw output from the tool, without any additional formatting, commentary, or text.
107
- - Do not wrap the result in quotes, JSON, or markdown fences.
108
- - Do not explain what the result means.
109
- - Your final response must be identical to the tool output.
110
- `
99
+ # User Prompt:
100
+ ${prompt}
101
+
102
+ # System Instructions:
103
+ - aiInteractionId: ${genAiInteraction.id}
104
+ - moduleName:${message.payload.moduleName}
105
+ - You will be invoking tools if needed.
106
+ - If a tool is invoked, you must return **exactly** the raw output from the tool, without any json envelopes, additional formatting, commentary, or text.
107
+ - Do not wrap the result in quotes, JSON, or markdown fences.
108
+ - Do not explain what the result means.
109
+
110
+ # Past Interactions:
111
+ This section contains the last 10 interactions done between the human and LLM. These are sorted by oldest first.
112
+ Use these interactions to further identify concerns based on the current User Prompt.
113
+
114
+ `
111
115
 
112
116
  const aiResponse = await this.aiInteractionService.runMcpPrompt(finalPrompt);
113
117
  this.triggerMcpClientSubscriberLogger.log(`aiResponse: `);
@@ -116,8 +120,8 @@ export class TriggerMcpClientSubscriberDatabase extends DatabaseSubscriber<Trigg
116
120
  if (!aiResponse.success) {
117
121
  this.triggerMcpClientSubscriberLogger.log(`Gen ai has returned with a false status code`);
118
122
 
119
- const errorsStr = aiResponse.errors.join('\n ');
120
- const errorTrace = aiResponse.error_trace.join('\n');
123
+ const errorsStr = aiResponse.errors?.join('\n ');
124
+ const errorTrace = aiResponse.error_trace?.join('\n');
121
125
 
122
126
  // await this.aiInteractionService.create({
123
127
  // userId: aiInteraction.user.id,
@@ -148,7 +152,7 @@ export class TriggerMcpClientSubscriberDatabase extends DatabaseSubscriber<Trigg
148
152
  throw new Error(errorsStr);
149
153
  }
150
154
  else {
151
- // let nestedResponse = this.cleanNestedResponse(aiResponse);
155
+ let nestedResponse = this.cleanNestedResponse(aiResponse);
152
156
 
153
157
  // const genAiInteraction = await this.aiInteractionService.create({
154
158
  // userId: aiInteraction.user.id,
@@ -166,14 +170,19 @@ export class TriggerMcpClientSubscriberDatabase extends DatabaseSubscriber<Trigg
166
170
  // });
167
171
 
168
172
  // TODO: Update the previously created genAiInteraction record with the respective success fields and save to DB
173
+ const errorsStr = nestedResponse.status == "error" && nestedResponse.errors.join('\n ');
174
+
169
175
  await this.aiInteractionService.update(genAiInteraction.id, {
176
+ errorMessage: nestedResponse.status == "error" ? `${errorsStr}` : "",
177
+ // errorMessage:"",
170
178
  // contentType: aiResponse.content_type,
171
- errorMessage: '',
172
179
  // message: nestedResponse,
173
180
  modelUsed: aiResponse.model,
174
181
  responseTimeMs: aiResponse.duration_ms,
175
182
  isApplied: aiInteraction.isApplied,
176
- status: aiResponse.success ? 'succeeded' : 'failed'
183
+
184
+ // status: aiResponse.success ? 'succeeded' : 'failed'
185
+ status: aiResponse.success && nestedResponse.status == "success" ? 'succeeded' : 'failed'
177
186
  }, [], true);
178
187
 
179
188
  // If the human interaction was with isAutoApply=true, then we can go ahead and autoApply.
@@ -12331,7 +12331,9 @@
12331
12331
  "type": "field",
12332
12332
  "attrs": {
12333
12333
  "name": "metadata",
12334
- "height": "80vh"
12334
+ "height": "80vh",
12335
+ "viewWidget":"SolidAiInteractionMetadataFieldFormWidget"
12336
+
12335
12337
  }
12336
12338
  }
12337
12339
  ]
@@ -62,7 +62,7 @@ export class AiInteractionService extends CRUDService<AiInteraction> {
62
62
  const m = {
63
63
  payload: {
64
64
  aiInteractionId: aiInteraction.id,
65
- moduleName:dto.moduleName
65
+ moduleName: dto.moduleName
66
66
  },
67
67
  parentEntity: 'aiInteraction',
68
68
  parentEntityId: aiInteraction.id,
@@ -149,6 +149,7 @@ export class AiInteractionService extends CRUDService<AiInteraction> {
149
149
  }
150
150
  catch (ex) {
151
151
  this.logger.warn(`Attempting to parse mcp client response assuming it is JSON, however it is not: ${parsedResponse}`);
152
+ // raw.success = false
152
153
  }
153
154
  // Parse the response string into an object
154
155
  // const parsedResponse = JSON.parse(raw.response);
@@ -203,16 +204,22 @@ export class AiInteractionService extends CRUDService<AiInteraction> {
203
204
  }
204
205
 
205
206
  // TODO: Validation: Check if JSON.parse(metadata).tools_invoked starts with solid_
206
- let metadata = {};
207
+ let metadata: any = {};
207
208
  try {
208
- metadata = JSON.parse(aiInteraction.metadata);
209
- }
210
- catch (e) {
209
+ if (typeof aiInteraction.metadata === "string") {
210
+ metadata = JSON.parse(aiInteraction.metadata);
211
+ } else if (typeof aiInteraction.metadata === "object" && aiInteraction.metadata !== null) {
212
+ metadata = aiInteraction.metadata;
213
+ } else {
214
+ // optional fallback
215
+ metadata = {};
216
+ }
217
+ } catch (e) {
211
218
  // TODO: RESPONSE SHAPE ALERT Check if we want to control the shape of the response....
212
- throw new Error(e);
219
+ throw new Error(`Invalid metadata JSON: ${e}`);
213
220
  }
214
221
 
215
- const toolsInvoked = metadata['tools_invoked'];
222
+ const toolsInvoked = metadata['toolsInvoked'];
216
223
  if (!toolsInvoked) {
217
224
  // TODO: RESPONSE SHAPE ALERT Check if we want to control the shape of the response....
218
225
  throw new Error(ERROR_MESSAGES.UNABLE_TO_RESOLVE_SOLID_COMMAND);
@@ -59,7 +59,7 @@ export class ExcelService {
59
59
  // headers.reduce((acc, header) => ({ ...acc, [header]: '' }), {})
60
60
  // ).commit(); // Write a dummy record with headers
61
61
 
62
- await workbook.commit();
62
+ workbook.commit();
63
63
  return passThrough;
64
64
  }
65
65
 
@@ -86,7 +86,7 @@ export class ExcelService {
86
86
  this.logger.debug(`✅ Chunk ${chunkIndex} written to Excel`);
87
87
  }
88
88
 
89
- await workbook.commit();
89
+ workbook.commit();
90
90
  // passThrough.end(); // ✅ Properly close the stream
91
91
  } catch (error) {
92
92
  this.logger.error(`❌ Error writing Excel: ${error.message}`);
@@ -121,7 +121,7 @@ export class IngestMetadataService {
121
121
  ingestionInfo.collectionId = collectionId;
122
122
 
123
123
  // Delete and re-insert a document representing the full json...
124
- await this.deleteInsertRagDocumentForModuleMetadataJsonFile(ingestionInfo, fullPath, fileName)
124
+ // await this.deleteInsertRagDocumentForModuleMetadataJsonFile(ingestionInfo, fullPath, fileName)
125
125
 
126
126
  // Delete and re-insert a chunk representing the module.
127
127
  await this.deleteInsertRagChunkForModule(ingestionInfo, moduleMetadata);
@@ -129,11 +129,29 @@ export class IngestMetadataService {
129
129
  // Delete and re-insert chunks representing each model.
130
130
  for (const model of moduleMetadata.models) {
131
131
  await this.deleteInsertRagChunkForModel(ingestionInfo, enabledModule, model);
132
- for (const field of model.fields) {
133
- await this.deleteInsertRagChunkForField(ingestionInfo, enabledModule, model.singularName, field);
134
- }
132
+
133
+ // Disabling this for now...
134
+ // for (const field of model.fields) {
135
+ // await this.deleteInsertRagChunkForField(ingestionInfo, enabledModule, model.singularName, field);
136
+ // }
135
137
  }
136
138
 
139
+ // TODO: Delete and re-insert chunks representing roles
140
+
141
+ // TODO: Delete and re-insert chunks representing menus
142
+
143
+ // TODO: Delete and re-insert chunks representing actions
144
+
145
+ // TODO: Delete and re-insert chunks representing list views
146
+
147
+ // TODO: Delete and re-insert chunks representing kanban views
148
+
149
+ // TODO: Delete and re-insert chunks representing form views
150
+
151
+ // TODO: Delete and re-insert chunks representing security rules
152
+
153
+ // TODO: Delete and re-insert chunks representing scheduled jobs
154
+
137
155
  // Save ingestion info to disk...
138
156
  fs.writeFileSync(enabledModulIngestionInfoFullPath, JSON.stringify({ ...ingestionInfo }, null, 2), 'utf8');
139
157
  }
@@ -242,7 +260,7 @@ export class IngestMetadataService {
242
260
  description: m?.description ?? null,
243
261
 
244
262
  // Include field names to detect field-level changes at module granularity - maybe remove this later?
245
- fields: Array.isArray(m?.fields) ? m.fields.map((f: any) => f?.name ?? null) : [],
263
+ // fields: Array.isArray(m?.fields) ? m.fields.map((f: any) => f?.name ?? null) : [],
246
264
  })),
247
265
  });
248
266
 
@@ -270,6 +288,7 @@ Usage: Use this chunk to choose the correct model/field chunks for code generati
270
288
 
271
289
  // metadata has to be concise and queryable
272
290
  const metadata = {
291
+ collectionName: `${moduleName}-rag-collection`,
273
292
  kind: 'solidx-metadata',
274
293
  type: 'module',
275
294
  moduleName,
@@ -288,7 +307,8 @@ Usage: Use this chunk to choose the correct model/field chunks for code generati
288
307
  }
289
308
 
290
309
  const r = await this.ragClient.documents.create({
291
- raw_text: text,
310
+ chunks: [text],
311
+ // raw_text: text,
292
312
  metadata: metadata,
293
313
  collectionIds: [ingestionInfo.collectionId],
294
314
  });
@@ -364,10 +384,15 @@ Fields (${fields.length}) [name:type|flags]:
364
384
  ${fieldSummaryLines.join('\n')}
365
385
 
366
386
  Usage: Use this chunk to generate DTOs, subscribers, custom service methods, and CRUD handlers for ${modelName}.
367
- For exact constraints (enum/min/max/regex/default), consult the individual field chunks.`;
387
+
388
+ Full model metadata json:
389
+ ${JSON.stringify(model)}
390
+
391
+ `;
368
392
 
369
393
  // 4) Metadata (concise & queryable)
370
394
  const metadata = {
395
+ collectionName: `${moduleName}-rag-collection`,
371
396
  kind: 'solidx-metadata',
372
397
  type: 'model',
373
398
  moduleName,
@@ -392,7 +417,7 @@ For exact constraints (enum/min/max/regex/default), consult the individual field
392
417
 
393
418
  // 6) Create new document (R2R auto-generates the ID)
394
419
  const r = await this.ragClient.documents.create({
395
- raw_text: text,
420
+ chunks: [text],
396
421
  metadata,
397
422
  collectionIds: [ingestionInfo.collectionId],
398
423
  });
@@ -661,6 +686,7 @@ For exact constraints (enum/min/max/regex/default), consult the individual field
661
686
 
662
687
  // 4) Build text + metadata tailored to FieldMetadata
663
688
  const { text, metadata } = this._buildFieldTextAndMetadata(moduleName, modelName, field);
689
+
664
690
  // also keep the hash in metadata for audit/debug
665
691
  (metadata as any).schemaHash = schemaHash;
666
692
 
@@ -26,6 +26,7 @@ import { CsvService } from './csv.service';
26
26
  import { ExcelService } from './excel.service';
27
27
  import { SolidIntrospectService } from './solid-introspect.service';
28
28
  import { ERROR_MESSAGES } from 'src/constants/error-messages';
29
+ import { parseFlexibleDate } from 'src/helpers/date.helper';
29
30
 
30
31
  interface ImportTemplateFileInfo {
31
32
  stream: NodeJS.ReadableStream;
@@ -566,10 +567,11 @@ export class ImportTransactionService extends CRUDService<ImportTransaction> {
566
567
  // TODO Move this logic to field crud managers i.e add a parse method to the field crud manager interface
567
568
  switch (fieldType) {
568
569
  case SolidFieldType.relation: {
569
- return await this.populateDtoForRelations(fieldMetadata, record, key, dtoRecord);
570
+ return await this.populateDtoForRelations(fieldMetadata, record, key, dtoRecord);
570
571
  }
571
572
  case SolidFieldType.date:
572
- case SolidFieldType.datetime: return this.populateDtoForDate(record, key, fieldMetadata, dtoRecord);
573
+ case SolidFieldType.datetime:
574
+ return this.populateDtoForDate(record, key, fieldMetadata, dtoRecord);
573
575
  case SolidFieldType.int:
574
576
  case SolidFieldType.bigint:
575
577
  case SolidFieldType.decimal:
@@ -579,16 +581,24 @@ export class ImportTransactionService extends CRUDService<ImportTransaction> {
579
581
  case SolidFieldType.selectionStatic:
580
582
  case SolidFieldType.selectionDynamic:
581
583
  return this.populateDtoForSelectionValues(dtoRecord, fieldMetadata, record, key);
582
- default:
584
+ case SolidFieldType.email:
585
+ case SolidFieldType.shortText:
586
+ case SolidFieldType.longtext:
587
+ case SolidFieldType.richText: {
588
+ dtoRecord[fieldMetadata.name] = record[key] ? String(record[key]).trim() : null; // Trim text fields and set to null if empty
589
+ return dtoRecord;
590
+ }
591
+ default: {
583
592
  dtoRecord[fieldMetadata.name] = record[key];
584
593
  return dtoRecord;
594
+ }
585
595
  }
586
596
  }
587
597
 
588
598
  private populateDtoForSelectionValues(dtoRecord: Record<string, any>, fieldMetadata: FieldMetadata, record: Record<string, any>, key: string) {
589
599
  const rawValue = record[key];
590
600
 
591
- if (rawValue == null) {
601
+ if (rawValue == null || rawValue === '' || (typeof rawValue === 'string' && rawValue.trim() === '')) {
592
602
  dtoRecord[fieldMetadata.name] = null;
593
603
  return dtoRecord;
594
604
  }
@@ -611,16 +621,28 @@ export class ImportTransactionService extends CRUDService<ImportTransaction> {
611
621
 
612
622
 
613
623
  private populateDtoForBoolean(dtoRecord: Record<string, any>, fieldMetadata: FieldMetadata, record: Record<string, any>, key: string) {
614
- const booleanValue = Boolean(record[key]);
615
- if (typeof booleanValue !== 'boolean') {
616
- throw new Error(`Invalid boolean value for cell ${key} with value ${record[key]}`);
624
+ const cellValue = record[key];
625
+ if (cellValue === null || cellValue === undefined || cellValue === '') {
626
+ dtoRecord[fieldMetadata.name] = null; // If the cell is empty, set the field to null
627
+ return dtoRecord;
628
+ }
629
+
630
+ // If the cell contains values other than 'true', '1', 'yes', 'false', '0', 'no', throw an error
631
+ const booleanValue = (String(cellValue).toLowerCase() === 'true' || String(cellValue) === '1' || String(cellValue).toLowerCase() === 'yes') ? true : (String(cellValue).toLowerCase() === 'false' || String(cellValue) === '0' || String(cellValue).toLowerCase() === 'no') ? false : null;
632
+ if (booleanValue === null) {
633
+ throw new Error(`Invalid boolean value for cell ${key} with value ${cellValue}`);
617
634
  }
618
635
  dtoRecord[fieldMetadata.name] = booleanValue;
619
636
  return dtoRecord;
620
637
  }
621
638
 
622
639
  private populateDtoForNumber(dtoRecord: Record<string, any>, fieldMetadata: FieldMetadata, record: Record<string, any>, key: string) {
623
- const numberValue = Number(record[key]);
640
+ const cellValue = record[key];
641
+ if (cellValue === null || cellValue === undefined || cellValue === '') {
642
+ dtoRecord[fieldMetadata.name] = null; // If the cell is empty, set the field to null
643
+ return dtoRecord;
644
+ }
645
+ const numberValue = Number(cellValue);
624
646
  if (isNaN(numberValue)) {
625
647
  throw new Error(`Invalid number value for cell ${key} with value ${record[key]}`);
626
648
  }
@@ -630,10 +652,23 @@ export class ImportTransactionService extends CRUDService<ImportTransaction> {
630
652
 
631
653
  private populateDtoForDate(record: Record<string, any>, key: string, fieldMetadata: FieldMetadata, dtoRecord: Record<string, any>) {
632
654
  {
633
- const dateValue = new Date(record[key]);
634
- if (isNaN(dateValue.getTime())) {
635
- throw new Error(`Invalid date value for cell ${key} with value ${record[key]}`);
655
+ // Get the cell value
656
+ const cellValue = record[key];
657
+ if (!cellValue) { //If cell is a falsy value (empty)
658
+ dtoRecord[fieldMetadata.name] = null; // If the cell is empty, set the field to null
659
+ return dtoRecord;
636
660
  }
661
+ // Use flexible date parser
662
+ console.log(cellValue,'cellValue');
663
+
664
+ const dateValue = parseFlexibleDate(cellValue);
665
+ console.log(dateValue,'dateValue');
666
+
667
+ if (!dateValue) {
668
+ throw new Error(
669
+ `Invalid date value for cell ${key} with value ${cellValue}`
670
+ );
671
+ }
637
672
  dtoRecord[fieldMetadata.name] = dateValue;
638
673
  return dtoRecord;
639
674
  }
@@ -5,6 +5,7 @@ import { SolidRegistry } from "src/helpers/solid-registry";
5
5
  import { ModelMetadataService } from "../model-metadata.service";
6
6
  import { CreateModelMetadataDto } from "src/dtos/create-model-metadata.dto";
7
7
  import { ModuleMetadataService } from "../module-metadata.service";
8
+ import { model } from "mongoose";
8
9
 
9
10
  @Injectable()
10
11
  export class SolidCreateModelWithFieldsMcpToolResponseHandler implements IMcpToolResponseHandler {
@@ -19,9 +20,9 @@ export class SolidCreateModelWithFieldsMcpToolResponseHandler implements IMcpToo
19
20
  async apply(aiInteraction: AiInteraction) {
20
21
  // const aiResponse = JSON.parse(aiInteraction.message);
21
22
  const escapedMessage = aiInteraction.message.replace(/\\'/g, "'");
22
- const aiResponse = JSON.parse(escapedMessage);
23
+ const aiResponseMessage = JSON.parse(escapedMessage);
23
24
 
24
- const { moduleUserKey, modelSchema } = aiResponse;
25
+ const { moduleUserKey, ...modelSchema } = aiResponseMessage;
25
26
  const moduleMetadata = await this.moduleMetadataService.findOneByUserKey(moduleUserKey);
26
27
  if (!moduleMetadata) {
27
28
  throw new Error(`Module with user key ${moduleUserKey} not found.`);
@@ -16,9 +16,9 @@ export class SolidCreateModuleMcpToolResponseHandler implements IMcpToolResponse
16
16
  }
17
17
 
18
18
  async apply(aiInteraction: AiInteraction) {
19
- const aiResponse = JSON.parse(aiInteraction.message);
19
+ const aiResponseMessage = JSON.parse(aiInteraction.message);
20
20
 
21
- const moduleMetadata = aiResponse?.data?.moduleMetadata ?? {};
21
+ const moduleMetadata = aiResponseMessage?.moduleMetadata ?? {};
22
22
 
23
23
  // TODO: Validate if another module with same name exists, if it does then raise an error...
24
24