@solidstarters/solid-core 1.2.183 → 1.2.185

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 (64) hide show
  1. package/dev-grooming-docs/ozzy-prompts.txt +32 -0
  2. package/dist/config/iam.config.d.ts +2 -0
  3. package/dist/config/iam.config.d.ts.map +1 -1
  4. package/dist/config/iam.config.js +1 -0
  5. package/dist/config/iam.config.js.map +1 -1
  6. package/dist/interfaces.d.ts +9 -1
  7. package/dist/interfaces.d.ts.map +1 -1
  8. package/dist/interfaces.js.map +1 -1
  9. package/dist/jobs/database/trigger-mcp-client-subscriber-database.service.d.ts +10 -8
  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 +35 -11
  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 +48 -48
  14. package/dist/services/chatter-message.service.d.ts.map +1 -1
  15. package/dist/services/chatter-message.service.js +9 -2
  16. package/dist/services/chatter-message.service.js.map +1 -1
  17. package/dist/services/computed-fields/entity/uuid-externalid-entity-computed-field-provider.service.d.ts +10 -0
  18. package/dist/services/computed-fields/entity/uuid-externalid-entity-computed-field-provider.service.d.ts.map +1 -0
  19. package/dist/services/computed-fields/entity/uuid-externalid-entity-computed-field-provider.service.js +35 -0
  20. package/dist/services/computed-fields/entity/uuid-externalid-entity-computed-field-provider.service.js.map +1 -0
  21. package/dist/services/genai/mcp-handlers/solid-add-custom-service-method-mcp-handler.service.d.ts +16 -0
  22. package/dist/services/genai/mcp-handlers/solid-add-custom-service-method-mcp-handler.service.d.ts.map +1 -0
  23. package/dist/services/genai/mcp-handlers/solid-add-custom-service-method-mcp-handler.service.js +74 -0
  24. package/dist/services/genai/mcp-handlers/solid-add-custom-service-method-mcp-handler.service.js.map +1 -0
  25. package/dist/services/genai/mcp-handlers/solid-add-question-to-dashboard-mcp-handler.service.d.ts +12 -0
  26. package/dist/services/genai/mcp-handlers/solid-add-question-to-dashboard-mcp-handler.service.d.ts.map +1 -0
  27. package/dist/services/genai/mcp-handlers/solid-add-question-to-dashboard-mcp-handler.service.js +41 -0
  28. package/dist/services/genai/mcp-handlers/solid-add-question-to-dashboard-mcp-handler.service.js.map +1 -0
  29. package/dist/services/genai/mcp-handlers/solid-add-variable-to-dashboard-mcp-handler.service.d.ts +12 -0
  30. package/dist/services/genai/mcp-handlers/solid-add-variable-to-dashboard-mcp-handler.service.d.ts.map +1 -0
  31. package/dist/services/genai/mcp-handlers/solid-add-variable-to-dashboard-mcp-handler.service.js +42 -0
  32. package/dist/services/genai/mcp-handlers/solid-add-variable-to-dashboard-mcp-handler.service.js.map +1 -0
  33. package/dist/services/genai/mcp-handlers/solid-create-dashboard-mcp-handler.service.d.ts +1 -1
  34. package/dist/services/genai/mcp-handlers/solid-create-dashboard-mcp-handler.service.d.ts.map +1 -1
  35. package/dist/services/genai/mcp-handlers/solid-create-dashboard-mcp-handler.service.js +8 -6
  36. package/dist/services/genai/mcp-handlers/solid-create-dashboard-mcp-handler.service.js.map +1 -1
  37. package/dist/services/model-metadata.service.js +4 -4
  38. package/dist/services/model-metadata.service.js.map +1 -1
  39. package/dist/services/setting.service.d.ts.map +1 -1
  40. package/dist/services/setting.service.js +4 -2
  41. package/dist/services/setting.service.js.map +1 -1
  42. package/dist/services/solid-ts-morph.service.d.ts +5 -0
  43. package/dist/services/solid-ts-morph.service.d.ts.map +1 -1
  44. package/dist/services/solid-ts-morph.service.js +21 -0
  45. package/dist/services/solid-ts-morph.service.js.map +1 -1
  46. package/dist/solid-core.module.d.ts.map +1 -1
  47. package/dist/solid-core.module.js +9 -1
  48. package/dist/solid-core.module.js.map +1 -1
  49. package/dist/tsconfig.tsbuildinfo +1 -1
  50. package/package.json +1 -1
  51. package/src/config/iam.config.ts +2 -1
  52. package/src/interfaces.ts +12 -1
  53. package/src/jobs/database/trigger-mcp-client-subscriber-database.service.ts +45 -10
  54. package/src/seeders/seed-data/solid-core-metadata.json +48 -48
  55. package/src/services/chatter-message.service.ts +11 -3
  56. package/src/services/computed-fields/entity/uuid-externalid-entity-computed-field-provider.service.ts +34 -0
  57. package/src/services/genai/mcp-handlers/solid-add-custom-service-method-mcp-handler.service.ts +69 -0
  58. package/src/services/genai/mcp-handlers/solid-add-question-to-dashboard-mcp-handler.service.ts +43 -0
  59. package/src/services/genai/mcp-handlers/solid-add-variable-to-dashboard-mcp-handler.service.ts +44 -0
  60. package/src/services/genai/mcp-handlers/solid-create-dashboard-mcp-handler.service.ts +4 -3
  61. package/src/services/model-metadata.service.ts +4 -4
  62. package/src/services/setting.service.ts +4 -2
  63. package/src/services/solid-ts-morph.service.ts +37 -0
  64. package/src/solid-core.module.ts +12 -3
@@ -0,0 +1,69 @@
1
+ import { Injectable, Logger } from "@nestjs/common";
2
+ import { AiInteraction } from "src/entities/ai-interaction.entity";
3
+ import { IMcpToolResponseHandler, McpComputedProviderResponse, PlanStep } from "../../../interfaces";
4
+ import { SolidTsMorphService } from "src/services/solid-ts-morph.service";
5
+
6
+ const RESTART_TOUCH_FILE = process.env.MCP_RESTART_TOUCH_FILE || "tmp/restart.touch";
7
+
8
+ @Injectable()
9
+ export class SolidAddCustomServiceMethodMcpHandler implements IMcpToolResponseHandler {
10
+ private readonly logger = new Logger(SolidAddCustomServiceMethodMcpHandler.name);
11
+
12
+ constructor(private readonly tsMorph: SolidTsMorphService) { }
13
+
14
+ async apply(aiInteraction: AiInteraction) {
15
+ const raw = this.safeParse(aiInteraction.message);
16
+ const payload: McpComputedProviderResponse | undefined = (raw?.data?.plan ? raw.data : raw) as McpComputedProviderResponse;
17
+
18
+ if (!payload || !Array.isArray(payload.plan)) {
19
+ throw new Error("SolidAddCustomServiceMethodMcpHandler: invalid MCP response; missing plan[]");
20
+ }
21
+
22
+ // Batch all plan steps in a single txn so nodemon restarts only once.
23
+ this.tsMorph.begin();
24
+ try {
25
+ for (const step of payload.plan as PlanStep[]) {
26
+ switch (step.type) {
27
+ case "createNewFile": {
28
+ const overwrite = step.overwrite ?? false;
29
+ this.tsMorph.createNewFile(step.path, step.content, overwrite);
30
+ break;
31
+ }
32
+ case "addMethodToExistingClass": {
33
+ this.tsMorph.addMethodToExistingClass(
34
+ step.path,
35
+ step.className,
36
+ step.methodName,
37
+ step.content,
38
+ );
39
+ break;
40
+ }
41
+ default:
42
+ throw new Error(`Unsupported plan step type: ${(step as any).type}`);
43
+ }
44
+ }
45
+
46
+ const result = await this.tsMorph.commit();
47
+
48
+ return {
49
+ seedingRequired: false,
50
+ serverRebooting: true,
51
+ appliedSteps: payload.plan.length,
52
+ wroteFiles: result.wrote,
53
+ };
54
+ } catch (err) {
55
+ this.logger.error(`Apply failed; rolling back. ${String(err)}`);
56
+ this.tsMorph.rollback();
57
+ throw err;
58
+ }
59
+ }
60
+
61
+ private safeParse(str: string): any {
62
+ try {
63
+ return JSON.parse(str);
64
+ } catch {
65
+ const unescaped = str.replace(/\\'/g, "'");
66
+ return JSON.parse(unescaped);
67
+ }
68
+ }
69
+ }
@@ -0,0 +1,43 @@
1
+ import { Injectable } from "@nestjs/common";
2
+ import { plainToInstance } from "class-transformer";
3
+ import { CreateDashboardQuestionDto } from "src/dtos/create-dashboard-question.dto";
4
+ import { AiInteraction } from "src/entities/ai-interaction.entity";
5
+ import { IMcpToolResponseHandler } from "../../../interfaces";
6
+ import { DashboardQuestionService } from "../../dashboard-question.service";
7
+
8
+ @Injectable()
9
+ export class SolidAddQuestionToDashboardMcpHandler implements IMcpToolResponseHandler {
10
+
11
+ constructor(
12
+ private readonly dashboardQuestionService: DashboardQuestionService,
13
+ ) {
14
+ }
15
+
16
+ async apply(aiInteraction: AiInteraction) {
17
+ const escapedMessage = aiInteraction.message.replace(/\\'/g, "'");
18
+ const aiResponseMessage = JSON.parse(escapedMessage);
19
+
20
+ const {data} = aiResponseMessage;
21
+ const { dashboardUserKey, schema} = data;
22
+
23
+ //FIXME: Replace \' with ' in the response, since the AI response seems to contain \' which is invalid JSON.
24
+ // This is a workaround for now, until we find a better solution.
25
+ // const aiResponseMessageReplaced = aiResponseMessage['message'].replace(/\\'/g, "'");
26
+ // const dashboardUserKey = aiResponseMessageReplaced['dashboardUserKey'];
27
+ // if (!dashboardUserKey) {
28
+ // throw new Error("Dashboard User Key is required to create a Dashboard Question.");
29
+ // }
30
+ const dashboardQuestionDto = plainToInstance(CreateDashboardQuestionDto, schema);
31
+ dashboardQuestionDto['questionSqlDatasetConfigsCommand'] = "update";
32
+ dashboardQuestionDto['dashboardUserKey'] = dashboardUserKey;
33
+
34
+ const dashboardQuestion = await this.dashboardQuestionService.create(dashboardQuestionDto, []);
35
+
36
+ // TODO: decide on some shape to return hre...
37
+ return {
38
+ seedingRequired: false,
39
+ serverRebooting: false,
40
+ }
41
+ }
42
+
43
+ }
@@ -0,0 +1,44 @@
1
+ import { Injectable } from "@nestjs/common";
2
+ import { plainToInstance } from "class-transformer";
3
+ import { CreateDashboardVariableDto } from "src/dtos/create-dashboard-variable.dto";
4
+ import { AiInteraction } from "src/entities/ai-interaction.entity";
5
+ import { DashboardVariableService } from "src/services/dashboard-variable.service";
6
+ import { IMcpToolResponseHandler } from "../../../interfaces";
7
+
8
+ @Injectable()
9
+ export class SolidAddVariableToDashboardMcpHandler implements IMcpToolResponseHandler {
10
+
11
+ constructor(
12
+ private readonly dashboardVariableService: DashboardVariableService,
13
+ ) {
14
+ }
15
+
16
+ async apply(aiInteraction: AiInteraction) {
17
+ const escapedMessage = aiInteraction.message.replace(/\\'/g, "'");
18
+ const aiResponseMessage = JSON.parse(escapedMessage);
19
+
20
+ const {data} = aiResponseMessage;
21
+ const { dashboardUserKey, schema} = data;
22
+
23
+ //FIXME: Replace \' with ' in the response, since the AI response seems to contain \' which is invalid JSON.
24
+ // This is a workaround for now, until we find a better solution.
25
+ // const aiResponseMessageReplaced = aiResponseMessage['message'].replace(/\\'/g, "'");
26
+ // const dashboardUserKey = aiResponseMessageReplaced['dashboardUserKey'];
27
+ // if (!dashboardUserKey) {
28
+ // throw new Error("Dashboard User Key is required to create a Dashboard Question.");
29
+ // }
30
+ const dashboardVariableDto = plainToInstance(CreateDashboardVariableDto, schema);
31
+ dashboardVariableDto['selectionStaticValues'] = JSON.stringify(dashboardVariableDto['selectionStaticValues'] || []);
32
+ dashboardVariableDto['defaultValue'] = JSON.stringify(dashboardVariableDto['defaultValue'] || []);
33
+ dashboardVariableDto['dashboardUserKey'] = dashboardUserKey;
34
+
35
+ const dashboardVariable = await this.dashboardVariableService.create(dashboardVariableDto, []);
36
+
37
+ // TODO: decide on some shape to return hre...
38
+ return {
39
+ seedingRequired: false,
40
+ serverRebooting: false,
41
+ }
42
+ }
43
+
44
+ }
@@ -13,7 +13,7 @@ import { ModuleMetadataService } from "../../module-metadata.service";
13
13
  import { RoleMetadataService } from "../../role-metadata.service";
14
14
 
15
15
  @Injectable()
16
- export class SolidCreateDashboardMcpHandler implements IMcpToolResponseHandler {
16
+ export class SolidCreateDashboardWithWidgetsMcpHandler implements IMcpToolResponseHandler {
17
17
 
18
18
  constructor(
19
19
  private readonly dashboardService: DashboardService,
@@ -28,8 +28,9 @@ export class SolidCreateDashboardMcpHandler implements IMcpToolResponseHandler {
28
28
  async apply(aiInteraction: AiInteraction) {
29
29
  const escapedMessage = aiInteraction.message.replace(/\\'/g, "'");
30
30
  const aiResponseMessage = JSON.parse(escapedMessage);
31
-
32
- const { dashboardDto, dashboard } = await this.createDashboard(aiResponseMessage);
31
+ const { data } = aiResponseMessage;
32
+ const { schema } = data;
33
+ const { dashboardDto, dashboard } = await this.createDashboard(schema);
33
34
 
34
35
  const { moduleUserKey, actionMetadataEntity } = await this.createActionMetadataEntry(dashboardDto, dashboard);
35
36
 
@@ -901,12 +901,12 @@ export class ModelMetadataService {
901
901
  children: [
902
902
  {
903
903
  type: "column",
904
- attrs: { name: "group-1", label: "", className: "col-6" },
904
+ attrs: { name: "group-1", label: "", className: "col-12 sm:col-12 md:col-6 lg:col-6" },
905
905
  children: column1Fields
906
906
  },
907
907
  {
908
908
  type: "column",
909
- attrs: { name: "group-2", label: "", className: "col-6" },
909
+ attrs: { name: "group-2", label: "", className: "col-12 sm:col-12 md:col-6 lg:col-6" },
910
910
  children: column2Fields
911
911
  }
912
912
  ]
@@ -1014,12 +1014,12 @@ export class ModelMetadataService {
1014
1014
  children: [
1015
1015
  {
1016
1016
  type: "column",
1017
- attrs: { name: "group-1", label: "", className: "col-6" },
1017
+ attrs: { name: "group-1", label: "", className: "col-12 sm:col-12 md:col-6 lg:col-6" },
1018
1018
  children: firstHalf
1019
1019
  },
1020
1020
  {
1021
1021
  type: "column",
1022
- attrs: { name: "group-2", label: "", className: "col-6" },
1022
+ attrs: { name: "group-2", label: "", className: "col-12 sm:col-12 md:col-6 lg:col-6" },
1023
1023
  children: secondHalf
1024
1024
  }
1025
1025
  ]
@@ -76,7 +76,8 @@ export class SettingService extends CRUDService<Setting> {
76
76
  solidXGenAiCodeBuilderConfig: JSON.stringify({
77
77
  defaultProvider: "",
78
78
  availableProviders: []
79
- })
79
+ }),
80
+ showNameFieldsForRegistration:this.iamConfiguration.showNameFieldsForRegistration
80
81
  };
81
82
 
82
83
  const existingSettings = await this.repo.find();
@@ -187,7 +188,8 @@ export class SettingService extends CRUDService<Setting> {
187
188
  defaultProvider: "",
188
189
  availableProviders: []
189
190
  }),
190
- iamAutoGeneratedPassword:this.iamConfiguration.iamAutoGeneratedPassword
191
+ iamAutoGeneratedPassword:this.iamConfiguration.iamAutoGeneratedPassword,
192
+ showNameFieldsForRegistration:this.iamConfiguration.showNameFieldsForRegistration
191
193
  };
192
194
  }
193
195
 
@@ -3,6 +3,7 @@ import { Injectable, Logger } from "@nestjs/common";
3
3
  import { join, dirname, normalize, isAbsolute, basename } from "node:path";
4
4
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
5
5
  import { Project, Node, ObjectLiteralExpression, ArrayLiteralExpression, QuoteKind, IndentationText } from "ts-morph";
6
+ import { MethodDeclarationStructure, StructureKind } from "ts-morph";
6
7
 
7
8
  type Bucket = "providers" | "exports";
8
9
 
@@ -260,4 +261,40 @@ export class SolidTsMorphService {
260
261
  this.logger.log(`Staged provider registration in: ${this.rel(abs)} (${registerIn.join(", ")})`);
261
262
  return { staged: true };
262
263
  }
264
+
265
+
266
+ addMethodToExistingClass(
267
+ filePath: string,
268
+ className: string,
269
+ methodName: string,
270
+ methodCode: string,
271
+ ): { staged: boolean; overwritten: boolean; skipped: boolean } {
272
+ const abs = this.resolveRepoPath(filePath);
273
+ if (!existsSync(abs))
274
+ throw new Error(`addMethodToExistingClass: File not found at ${filePath}`);
275
+
276
+ const existing = this.project.getSourceFile(abs);
277
+ const sourceFile = existing
278
+ ? existing
279
+ : this.project.createSourceFile(abs, readFileSync(abs, "utf8"), { overwrite: true });
280
+
281
+ const targetClass = sourceFile.getClass(className);
282
+ if (!targetClass)
283
+ throw new Error(`addMethodToExistingClass: Class ${className} not found in ${filePath}`);
284
+
285
+ const existingMethod = targetClass.getMethod(methodName);
286
+ if (existingMethod) {
287
+
288
+ this.logger.log(`Skipped adding method '${methodName}' (already exists)`);
289
+ return { staged: false, overwritten: false, skipped: true };
290
+ }
291
+ // Add the LLM-generated method directly
292
+ targetClass.addMember(methodCode);
293
+
294
+
295
+ this.dirtySourceFiles.add(abs);
296
+ this.logger.log(`Staged method '${methodName}' in class ${className} at ${this.rel(abs)}`);
297
+ return { staged: true, overwritten: !!existingMethod, skipped: false };
298
+ }
299
+
263
300
  }
@@ -102,6 +102,7 @@ import { UserSeederService } from './seeders/user-seeder.service';
102
102
  import { AuthenticationService } from './services/authentication.service';
103
103
  import { BcryptService } from './services/bcrypt.service';
104
104
  import { UuidExternalIdComputedFieldProvider } from './services/computed-fields/uuid-external-id-computed-field-provider.service';
105
+ import { UuidExternalIdEntityComputedFieldProvider } from './services/computed-fields/entity/uuid-externalid-entity-computed-field-provider.service';
105
106
  import { EmailTemplateService } from './services/email-template.service';
106
107
  import { FileService } from './services/file.service';
107
108
  import { HashingService } from './services/hashing.service';
@@ -288,12 +289,15 @@ import { SolidCreateModuleMcpHandler } from './services/genai/mcp-handlers/solid
288
289
  import { SolidCreateModelWithFieldsMcpHandler } from './services/genai/mcp-handlers/solid-create-model-with-fields-mcp-handler.service';
289
290
  import { SolidAddFieldsToModelMcpHandler } from './services/genai/mcp-handlers/solid-add-fields-to-model-mcp-handler.service';
290
291
  import { SolidUpdateLayoutMcpHandler } from './services/genai/mcp-handlers/solid-update-layout-mcp-handler.service';
291
- import { SolidCreateDashboardMcpHandler } from './services/genai/mcp-handlers/solid-create-dashboard-mcp-handler.service';
292
+ import { SolidCreateDashboardWithWidgetsMcpHandler } from './services/genai/mcp-handlers/solid-create-dashboard-mcp-handler.service';
292
293
  import { SolidCreateDashboardQuestionMcpHandler } from './services/genai/mcp-handlers/solid-create-dashboard-question-mcp-handler.service';
293
294
  import { SolidCreateDashboardQuestionSqlDatasetConfigMcpHandler } from './services/genai/mcp-handlers/solid-create-dashboard-question-sql-dataset-config-mcp-handler.service';
294
295
  import { SolidCreateDashboardWidgetMcpHandler } from './services/genai/mcp-handlers/solid-create-dashboard-widget-mcp-handler.service';
295
296
  import { SolidCreateComputedProviderMcpHandler } from './services/genai/mcp-handlers/solid-create-computed-provider-mcp-handler.service';
296
297
  import { SolidTsMorphService } from './services/solid-ts-morph.service';
298
+ import { SolidAddVariableToDashboardMcpHandler } from './services/genai/mcp-handlers/solid-add-variable-to-dashboard-mcp-handler.service';
299
+ import { SolidAddQuestionToDashboardMcpHandler } from './services/genai/mcp-handlers/solid-add-question-to-dashboard-mcp-handler.service';
300
+ import { SolidAddCustomServiceMethodMcpHandler } from './services/genai/mcp-handlers/solid-add-custom-service-method-mcp-handler.service';
297
301
 
298
302
 
299
303
  @Global()
@@ -536,6 +540,7 @@ import { SolidTsMorphService } from './services/solid-ts-morph.service';
536
540
  TinyUrlService,
537
541
  PdfService,
538
542
  UuidExternalIdComputedFieldProvider,
543
+ UuidExternalIdEntityComputedFieldProvider,
539
544
  ListOfModelsSelectionProvider,
540
545
  ListOfScheduledJobsSelectionProvider,
541
546
  LocaleListSelectionProvider,
@@ -630,12 +635,16 @@ import { SolidTsMorphService } from './services/solid-ts-morph.service';
630
635
  SolidCreateModelWithFieldsMcpHandler,
631
636
  SolidAddFieldsToModelMcpHandler,
632
637
  SolidUpdateLayoutMcpHandler,
633
-
634
- SolidCreateDashboardMcpHandler,
638
+
639
+ SolidCreateDashboardWithWidgetsMcpHandler,
635
640
  SolidCreateDashboardQuestionMcpHandler,
636
641
  SolidCreateDashboardQuestionSqlDatasetConfigMcpHandler,
637
642
  SolidCreateDashboardWidgetMcpHandler,
638
643
  SolidCreateComputedProviderMcpHandler,
644
+ SolidAddVariableToDashboardMcpHandler,
645
+ SolidAddQuestionToDashboardMcpHandler,
646
+
647
+ SolidAddCustomServiceMethodMcpHandler,
639
648
  SolidTsMorphService,
640
649
 
641
650
  ViewMetadataRepository,