@solidxai/core 0.1.11-beta.1 → 0.1.11-beta.4

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 (136) hide show
  1. package/.claude/settings.local.json +16 -0
  2. package/CLAUDE.md +26 -0
  3. package/dist/controllers/datasource-introspection.controller.d.ts +38 -1
  4. package/dist/controllers/datasource-introspection.controller.d.ts.map +1 -1
  5. package/dist/controllers/datasource-introspection.controller.js +38 -0
  6. package/dist/controllers/datasource-introspection.controller.js.map +1 -1
  7. package/dist/controllers/service.controller.d.ts +1 -0
  8. package/dist/controllers/service.controller.d.ts.map +1 -1
  9. package/dist/controllers/service.controller.js +2 -2
  10. package/dist/controllers/service.controller.js.map +1 -1
  11. package/dist/dtos/datasource-introspection-mapping.dto.d.ts +4 -0
  12. package/dist/dtos/datasource-introspection-mapping.dto.d.ts.map +1 -1
  13. package/dist/dtos/datasource-introspection-mapping.dto.js +18 -2
  14. package/dist/dtos/datasource-introspection-mapping.dto.js.map +1 -1
  15. package/dist/entities/{legacy-common-with-id.entity.d.ts → legacy-common-with-generated-id.entity.d.ts} +2 -2
  16. package/dist/entities/legacy-common-with-generated-id.entity.d.ts.map +1 -0
  17. package/dist/entities/{legacy-common-with-id.entity.js → legacy-common-with-generated-id.entity.js} +4 -4
  18. package/dist/entities/legacy-common-with-generated-id.entity.js.map +1 -0
  19. package/dist/entities/{legacy-common.entity.d.ts → legacy-common.entity-with-existing-id.entity.d.ts} +1 -1
  20. package/dist/entities/legacy-common.entity-with-existing-id.entity.d.ts.map +1 -0
  21. package/dist/entities/{legacy-common.entity.js → legacy-common.entity-with-existing-id.entity.js} +1 -1
  22. package/dist/entities/legacy-common.entity-with-existing-id.entity.js.map +1 -0
  23. package/dist/helpers/field-crud-managers/IntFieldCrudManager.d.ts.map +1 -1
  24. package/dist/helpers/field-crud-managers/IntFieldCrudManager.js +4 -1
  25. package/dist/helpers/field-crud-managers/IntFieldCrudManager.js.map +1 -1
  26. package/dist/helpers/model-metadata-helper.service.js +3 -3
  27. package/dist/helpers/model-metadata-helper.service.js.map +1 -1
  28. package/dist/helpers/solid-registry.d.ts +2 -1
  29. package/dist/helpers/solid-registry.d.ts.map +1 -1
  30. package/dist/helpers/solid-registry.js.map +1 -1
  31. package/dist/index.d.ts +2 -2
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +2 -2
  34. package/dist/index.js.map +1 -1
  35. package/dist/interfaces/datasource-introspection-provider.interface.d.ts +1 -0
  36. package/dist/interfaces/datasource-introspection-provider.interface.d.ts.map +1 -1
  37. package/dist/interfaces/datasource-introspection-provider.interface.js.map +1 -1
  38. package/dist/seeders/module-metadata-seeder.service.d.ts +5 -1
  39. package/dist/seeders/module-metadata-seeder.service.d.ts.map +1 -1
  40. package/dist/seeders/module-metadata-seeder.service.js +61 -3
  41. package/dist/seeders/module-metadata-seeder.service.js.map +1 -1
  42. package/dist/seeders/seed-data/solid-core-metadata.json +19 -3
  43. package/dist/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.d.ts.map +1 -1
  44. package/dist/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.js +6 -5
  45. package/dist/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.js.map +1 -1
  46. package/dist/services/datasource-introspection/mssql-datasource-introspection-provider.service.d.ts.map +1 -1
  47. package/dist/services/datasource-introspection/mssql-datasource-introspection-provider.service.js +12 -0
  48. package/dist/services/datasource-introspection/mssql-datasource-introspection-provider.service.js.map +1 -1
  49. package/dist/services/datasource-introspection/mysql-datasource-introspection-provider.service.d.ts.map +1 -1
  50. package/dist/services/datasource-introspection/mysql-datasource-introspection-provider.service.js +2 -0
  51. package/dist/services/datasource-introspection/mysql-datasource-introspection-provider.service.js.map +1 -1
  52. package/dist/services/datasource-introspection/postgres-datasource-introspection-provider.service.d.ts.map +1 -1
  53. package/dist/services/datasource-introspection/postgres-datasource-introspection-provider.service.js +28 -15
  54. package/dist/services/datasource-introspection/postgres-datasource-introspection-provider.service.js.map +1 -1
  55. package/dist/services/datasource-introspection.service.d.ts +52 -2
  56. package/dist/services/datasource-introspection.service.d.ts.map +1 -1
  57. package/dist/services/datasource-introspection.service.js +534 -160
  58. package/dist/services/datasource-introspection.service.js.map +1 -1
  59. package/dist/services/locale.service.d.ts +14 -0
  60. package/dist/services/locale.service.d.ts.map +1 -1
  61. package/dist/services/locale.service.js +83 -0
  62. package/dist/services/locale.service.js.map +1 -1
  63. package/dist/services/mediaStorageProviders/file-s3-storage-provider.js +10 -10
  64. package/dist/services/mediaStorageProviders/file-s3-storage-provider.js.map +1 -1
  65. package/dist/services/role-metadata.service.d.ts +1 -0
  66. package/dist/services/role-metadata.service.d.ts.map +1 -1
  67. package/dist/services/role-metadata.service.js +23 -2
  68. package/dist/services/role-metadata.service.js.map +1 -1
  69. package/dist/services/view-metadata.service.d.ts.map +1 -1
  70. package/dist/services/view-metadata.service.js +4 -7
  71. package/dist/services/view-metadata.service.js.map +1 -1
  72. package/dist/subscribers/audit.subscriber.d.ts +2 -0
  73. package/dist/subscribers/audit.subscriber.d.ts.map +1 -1
  74. package/dist/subscribers/audit.subscriber.js +25 -6
  75. package/dist/subscribers/audit.subscriber.js.map +1 -1
  76. package/dist/subscribers/computed-entity-field.subscriber.d.ts.map +1 -1
  77. package/dist/subscribers/computed-entity-field.subscriber.js +1 -0
  78. package/dist/subscribers/computed-entity-field.subscriber.js.map +1 -1
  79. package/dist/subscribers/created-by-updated-by.subscriber.d.ts.map +1 -1
  80. package/dist/subscribers/created-by-updated-by.subscriber.js.map +1 -1
  81. package/dist/subscribers/field-metadata.subscriber.d.ts.map +1 -1
  82. package/dist/subscribers/field-metadata.subscriber.js.map +1 -1
  83. package/package.json +1 -1
  84. package/src/controllers/datasource-introspection.controller.ts +27 -1
  85. package/src/controllers/service.controller.ts +3 -2
  86. package/src/dtos/datasource-introspection-mapping.dto.ts +10 -0
  87. package/src/entities/{legacy-common-with-id.entity.ts → legacy-common-with-generated-id.entity.ts} +1 -1
  88. package/src/helpers/field-crud-managers/IntFieldCrudManager.ts +4 -1
  89. package/src/helpers/model-metadata-helper.service.ts +1 -1
  90. package/src/helpers/solid-registry.ts +7 -1
  91. package/src/index.ts +2 -2
  92. package/src/interfaces/datasource-introspection-provider.interface.ts +1 -0
  93. package/src/seeders/module-metadata-seeder.service.ts +72 -2
  94. package/src/seeders/seed-data/solid-core-metadata.json +19 -3
  95. package/src/services/1.js +6 -0
  96. package/src/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.ts +10 -5
  97. package/src/services/datasource-introspection/mssql-datasource-introspection-provider.service.ts +12 -0
  98. package/src/services/datasource-introspection/mysql-datasource-introspection-provider.service.ts +2 -0
  99. package/src/services/datasource-introspection/postgres-datasource-introspection-provider.service.ts +28 -15
  100. package/src/services/datasource-introspection.service.ts +626 -136
  101. package/src/services/locale.service.ts +111 -3
  102. package/src/services/mediaStorageProviders/file-s3-storage-provider.ts +2 -2
  103. package/src/services/role-metadata.service.ts +26 -2
  104. package/src/services/view-metadata.service.ts +4 -8
  105. package/src/subscribers/audit.subscriber.ts +34 -14
  106. package/src/subscribers/computed-entity-field.subscriber.ts +1 -0
  107. package/src/subscribers/created-by-updated-by.subscriber.ts +3 -0
  108. package/src/subscribers/field-metadata.subscriber.ts +3 -0
  109. package/dist/entities/legacy-common-with-id.entity.d.ts.map +0 -1
  110. package/dist/entities/legacy-common-with-id.entity.js.map +0 -1
  111. package/dist/entities/legacy-common.entity.d.ts.map +0 -1
  112. package/dist/entities/legacy-common.entity.js.map +0 -1
  113. package/dist-tests/api/authenticate.spec.js +0 -119
  114. package/dist-tests/api/authenticate.spec.js.map +0 -1
  115. package/dist-tests/api/crud-service.findOne.cityMaster.spec.js +0 -97
  116. package/dist-tests/api/crud-service.findOne.cityMaster.spec.js.map +0 -1
  117. package/dist-tests/api/ping.spec.js +0 -21
  118. package/dist-tests/api/ping.spec.js.map +0 -1
  119. package/dist-tests/helpers/auth.js +0 -41
  120. package/dist-tests/helpers/auth.js.map +0 -1
  121. package/dist-tests/helpers/env.js +0 -11
  122. package/dist-tests/helpers/env.js.map +0 -1
  123. package/docs/agent-hub-grooming.md +0 -301
  124. package/docs/dashboards/AGENTIC_DASHBOARD_IMPLEMENTATION_PLAN.md +0 -438
  125. package/docs/dashboards/dashboard-curl-smoke-tests.txt +0 -146
  126. package/docs/dashboards/delete-legacy-dashboard-metadata.sql +0 -172
  127. package/docs/datasource-introspection-ddl-analysis.md +0 -326
  128. package/docs/datasource-introspection-implementation-plan.md +0 -306
  129. package/docs/grouping-enhancements.md +0 -89
  130. package/docs/java-spring/README.md +0 -3
  131. package/docs/java-spring/solid-core-module-deep-dive-report.md +0 -1317
  132. package/docs/module-package-import-handoff.md +0 -691
  133. package/docs/seed-changes.md +0 -65
  134. package/docs/test-data-workflow.md +0 -200
  135. package/docs/type-declaration-import-issue.md +0 -24
  136. /package/src/entities/{legacy-common.entity.ts → legacy-common.entity-with-existing-id.entity.ts} +0 -0
@@ -50,19 +50,101 @@ const crypto_1 = require("crypto");
50
50
  const fs = __importStar(require("fs/promises"));
51
51
  const path = __importStar(require("path"));
52
52
  const lodash_1 = require("lodash");
53
+ const ts_morph_1 = require("ts-morph");
53
54
  const legacy_table_type_enum_1 = require("../enums/legacy-table-type.enum");
55
+ const string_helper_1 = require("../helpers/string.helper");
54
56
  const module_metadata_helper_service_1 = require("../helpers/module-metadata-helper.service");
55
57
  const model_metadata_helper_service_1 = require("../helpers/model-metadata-helper.service");
56
58
  const model_metadata_repository_1 = require("../repository/model-metadata.repository");
57
59
  const module_metadata_repository_1 = require("../repository/module-metadata.repository");
58
60
  const datasource_management_service_1 = require("./datasource-management.service");
61
+ const command_service_1 = require("../helpers/command.service");
59
62
  const field_metadata_service_1 = require("./field-metadata.service");
60
63
  const model_metadata_service_1 = require("./model-metadata.service");
64
+ const module_metadata_service_1 = require("./module-metadata.service");
61
65
  const mssql_datasource_introspection_provider_service_1 = require("./datasource-introspection/mssql-datasource-introspection-provider.service");
62
66
  const mysql_datasource_introspection_provider_service_1 = require("./datasource-introspection/mysql-datasource-introspection-provider.service");
63
67
  const postgres_datasource_introspection_provider_service_1 = require("./datasource-introspection/postgres-datasource-introspection-provider.service");
68
+ const DATASOURCE_TYPE_FAMILY_ALIASES = {
69
+ boolean: ["bit", "bool", "boolean"],
70
+ bigint: ["bigint"],
71
+ int: ["int", "integer", "smallint", "tinyint"],
72
+ numeric: ["numeric"],
73
+ decimal: ["decimal", "money", "smallmoney"],
74
+ float: ["float", "double", "real"],
75
+ date: ["date"],
76
+ time: ["time", "time without time zone", "time with time zone"],
77
+ datetime: ["datetime", "datetime2", "smalldatetime", "timestamp", "timestamp without time zone"],
78
+ datetimeWithTimezone: ["timestamptz", "timestamp with time zone"],
79
+ json: ["json", "simple-json", "simplejson"],
80
+ jsonb: ["jsonb"],
81
+ uuid: ["uniqueidentifier", "uuid"],
82
+ longText: ["text", "ntext", "longtext", "clob"],
83
+ mediumText: ["mediumtext"],
84
+ shortText: ["varchar", "char", "citext"],
85
+ unicodeShortText: ["nvarchar", "nchar"],
86
+ };
87
+ const ORM_TYPE_BY_DATASOURCE_FAMILY = {
88
+ mssql: {
89
+ boolean: "bit",
90
+ bigint: "bigint",
91
+ int: "int",
92
+ numeric: "numeric",
93
+ decimal: "decimal",
94
+ float: "decimal",
95
+ date: "date",
96
+ time: "time",
97
+ datetime: "datetime",
98
+ datetimeWithTimezone: "datetime",
99
+ json: "simple-json",
100
+ jsonb: "simple-json",
101
+ uuid: "uniqueidentifier",
102
+ longText: "text",
103
+ mediumText: "text",
104
+ shortText: "varchar",
105
+ unicodeShortText: "nvarchar",
106
+ },
107
+ mysql: {
108
+ boolean: "boolean",
109
+ bigint: "int",
110
+ int: "int",
111
+ numeric: "decimal",
112
+ decimal: "decimal",
113
+ float: "double",
114
+ date: "date",
115
+ time: "time",
116
+ datetime: "datetime",
117
+ datetimeWithTimezone: "datetime",
118
+ json: "json",
119
+ jsonb: "json",
120
+ uuid: "varchar",
121
+ longText: "longtext",
122
+ mediumText: "mediumtext",
123
+ shortText: "varchar",
124
+ unicodeShortText: "varchar",
125
+ },
126
+ postgres: {
127
+ boolean: "boolean",
128
+ bigint: "bigint",
129
+ int: "integer",
130
+ numeric: "decimal",
131
+ decimal: "decimal",
132
+ float: "decimal",
133
+ date: "date",
134
+ time: "time",
135
+ datetime: "timestamp",
136
+ datetimeWithTimezone: "timestamptz",
137
+ json: "json",
138
+ jsonb: "jsonb",
139
+ uuid: "uuid",
140
+ longText: "text",
141
+ mediumText: "text",
142
+ shortText: "varchar",
143
+ unicodeShortText: "varchar",
144
+ },
145
+ };
64
146
  let DatasourceIntrospectionService = class DatasourceIntrospectionService {
65
- constructor(moduleRef, datasourceManagementService, moduleMetadataRepository, modelMetadataRepository, moduleMetadataHelperService, modelMetadataHelperService, fieldMetadataService, modelMetadataService, mssqlProvider, mysqlProvider, postgresProvider) {
147
+ constructor(moduleRef, datasourceManagementService, moduleMetadataRepository, modelMetadataRepository, moduleMetadataHelperService, modelMetadataHelperService, fieldMetadataService, modelMetadataService, moduleMetadataService, commandService, mssqlProvider, mysqlProvider, postgresProvider) {
66
148
  this.moduleRef = moduleRef;
67
149
  this.datasourceManagementService = datasourceManagementService;
68
150
  this.moduleMetadataRepository = moduleMetadataRepository;
@@ -71,6 +153,8 @@ let DatasourceIntrospectionService = class DatasourceIntrospectionService {
71
153
  this.modelMetadataHelperService = modelMetadataHelperService;
72
154
  this.fieldMetadataService = fieldMetadataService;
73
155
  this.modelMetadataService = modelMetadataService;
156
+ this.moduleMetadataService = moduleMetadataService;
157
+ this.commandService = commandService;
74
158
  this.mssqlProvider = mssqlProvider;
75
159
  this.mysqlProvider = mysqlProvider;
76
160
  this.postgresProvider = postgresProvider;
@@ -189,24 +273,98 @@ let DatasourceIntrospectionService = class DatasourceIntrospectionService {
189
273
  const persistedModel = plan.operation === "update" && mappingDto.modelId
190
274
  ? await this.modelMetadataService.update(mappingDto.modelId, plan.modelPayload)
191
275
  : await this.modelMetadataService.create(plan.modelPayload);
276
+ const persistedModelId = mappingDto.modelId ?? persistedModel?.id ?? null;
277
+ return {
278
+ data: {
279
+ modelId: persistedModelId,
280
+ operation: plan.operation,
281
+ metadataJson: plan.metadataJson,
282
+ summary: plan.summary,
283
+ },
284
+ };
285
+ }
286
+ async createMigrationArtifacts(moduleId, mappingDto) {
287
+ const plan = await this.buildMappingPreview(moduleId, mappingDto);
288
+ const module = await this.loadModule(moduleId);
289
+ const datasource = this.requireDatasource(mappingDto.dataSource);
290
+ if (!mappingDto.modelId) {
291
+ throw new common_1.BadRequestException("Persist the model mapping first so the generated entity can be registered before creating migration artifacts.");
292
+ }
192
293
  if (plan.migration.willGenerate && plan.migration.content && plan.migration.filePath) {
193
294
  await fs.mkdir(path.dirname(plan.migration.filePath), { recursive: true });
194
295
  await fs.writeFile(plan.migration.filePath, plan.migration.content, "utf8");
195
296
  }
196
- const persistedModelId = mappingDto.modelId ?? persistedModel?.id ?? null;
297
+ const datasourceFile = await this.syncTypeormDatasourceFile(module.name, datasource, plan.modelPayload.singularName);
197
298
  return {
198
299
  data: {
199
- modelId: persistedModelId,
300
+ modelId: mappingDto.modelId,
200
301
  operation: plan.operation,
201
- metadataJson: plan.metadataJson,
202
302
  migration: {
203
303
  ...plan.migration,
204
304
  written: Boolean(plan.migration.willGenerate && plan.migration.filePath),
205
305
  },
306
+ datasourceFile,
206
307
  summary: plan.summary,
207
308
  },
208
309
  };
209
310
  }
311
+ async generateCode(moduleId) {
312
+ await this.loadModule(moduleId);
313
+ const output = await this.moduleMetadataService.generateCodeViaCtl(moduleId);
314
+ return {
315
+ data: {
316
+ moduleId,
317
+ output,
318
+ message: "Module code generation completed.",
319
+ },
320
+ };
321
+ }
322
+ async runMigration(moduleId, datasourceName) {
323
+ const module = await this.loadModule(moduleId);
324
+ const datasource = this.requireDatasource(datasourceName);
325
+ const cwd = path.join(process.cwd(), "..");
326
+ const outputs = [];
327
+ const migrationOutput = await this.commandService.executeCommandWithArgs({
328
+ command: "npx",
329
+ args: ["-y", "@solidxai/solidctl@latest", "migration", "-d", datasource.name, "run"],
330
+ cwd,
331
+ });
332
+ outputs.push([
333
+ `npx @solidxai/solidctl@latest migration -d ${datasource.name} run`,
334
+ migrationOutput,
335
+ ].filter(Boolean).join("\n"));
336
+ const buildOutput = await this.commandService.executeCommandWithArgs({
337
+ command: "npx",
338
+ args: ["-y", "@solidxai/solidctl@latest", "build"],
339
+ cwd,
340
+ });
341
+ outputs.push([
342
+ "npx @solidxai/solidctl@latest build",
343
+ buildOutput,
344
+ ].filter(Boolean).join("\n"));
345
+ const seedOutput = await this.commandService.executeCommandWithArgs({
346
+ command: "npx",
347
+ args: ["-y", "@solidxai/solidctl@latest", "seed", "--modules-to-seed", module.name],
348
+ cwd,
349
+ });
350
+ outputs.push([
351
+ `npx @solidxai/solidctl@latest seed --modules-to-seed ${module.name}`,
352
+ seedOutput,
353
+ ].filter(Boolean).join("\n"));
354
+ return {
355
+ data: {
356
+ moduleId,
357
+ datasource: datasource.name,
358
+ output: outputs.join("\n\n"),
359
+ command: [
360
+ `npx @solidxai/solidctl@latest migration -d ${datasource.name} run`,
361
+ "npx @solidxai/solidctl@latest build",
362
+ `npx @solidxai/solidctl@latest seed --modules-to-seed ${module.name}`,
363
+ ].join("\n"),
364
+ message: `Migration, build, and seed completed successfully for datasource "${datasource.name}".`,
365
+ },
366
+ };
367
+ }
210
368
  async buildMappingPreview(moduleId, mappingDto) {
211
369
  const module = await this.loadModule(moduleId);
212
370
  const datasource = this.requireDatasource(mappingDto.dataSource);
@@ -252,6 +410,13 @@ let DatasourceIntrospectionService = class DatasourceIntrospectionService {
252
410
  mappedModelId: mappingDto.modelId ?? null,
253
411
  metadataJson,
254
412
  migration,
413
+ datasourceFile: {
414
+ filePath: path.resolve(process.cwd(), "src", `typeorm-${datasource.name}-datasource.ts`),
415
+ created: false,
416
+ updated: false,
417
+ entityRegistered: false,
418
+ migrationGlobRegistered: false,
419
+ },
255
420
  summary: {
256
421
  includedColumnNames,
257
422
  removedColumnNames,
@@ -584,7 +749,7 @@ let DatasourceIntrospectionService = class DatasourceIntrospectionService {
584
749
  ...preserved,
585
750
  ...(column.fieldId ? { id: column.fieldId } : {}),
586
751
  name: column.fieldName,
587
- displayName: preserved.displayName ?? (0, lodash_1.startCase)(column.fieldName),
752
+ displayName: column.displayName?.trim() || preserved.displayName || (0, lodash_1.startCase)(column.fieldName),
588
753
  description: preserved.description ?? "",
589
754
  type: column.solidFieldType,
590
755
  ormType: column.ormType,
@@ -696,23 +861,19 @@ let DatasourceIntrospectionService = class DatasourceIntrospectionService {
696
861
  const generatedIdUniqueName = this.buildMigrationObjectName("UQ", tableNameLiteral, "ss_id");
697
862
  const upColumnStatements = missingSystemColumns.map((definition) => {
698
863
  const columnLiteral = this.renderTableColumnLiteral(definition);
699
- return [
700
- ` if (!(await queryRunner.hasColumn(tableName, ${JSON.stringify(definition.columnName)}))) {`,
701
- ` await queryRunner.addColumn(tableName, new TableColumn(${columnLiteral}));`,
702
- " }",
703
- ].join("\n");
864
+ return ` if (!(await queryRunner.hasColumn(tableName, ${JSON.stringify(definition.columnName)})))\n`
865
+ + ` await queryRunner.addColumn(tableName, new TableColumn(${columnLiteral}));`;
704
866
  }).join("\n\n");
705
867
  const postUpStatements = [];
706
868
  if (missingSystemColumns.some((definition) => definition.columnName === "ss_deleted_at")) {
707
869
  postUpStatements.push([
708
870
  " {",
709
871
  " const table = await queryRunner.getTable(tableName);",
710
- ` if (table && !table.indices.some((index) => index.name === ${JSON.stringify(deletedAtIndexName)})) {`,
711
- " await queryRunner.createIndex(tableName, new TableIndex({",
712
- ` name: ${JSON.stringify(deletedAtIndexName)},`,
713
- " columnNames: [\"ss_deleted_at\"],",
714
- " }));",
715
- " }",
872
+ ` if (table && !table.indices.some((index) => index.name === ${JSON.stringify(deletedAtIndexName)}))`,
873
+ ` await queryRunner.createIndex(tableName, new TableIndex(${this.renderTableIndexLiteral({
874
+ name: deletedAtIndexName,
875
+ columnNames: ["ss_deleted_at"],
876
+ })}));`,
716
877
  " }",
717
878
  ].join("\n"));
718
879
  }
@@ -720,13 +881,12 @@ let DatasourceIntrospectionService = class DatasourceIntrospectionService {
720
881
  postUpStatements.push([
721
882
  " {",
722
883
  " const table = await queryRunner.getTable(tableName);",
723
- ` if (table && !table.indices.some((index) => index.name === ${JSON.stringify(generatedIdUniqueName)})) {`,
724
- " await queryRunner.createIndex(tableName, new TableIndex({",
725
- ` name: ${JSON.stringify(generatedIdUniqueName)},`,
726
- " columnNames: [\"ss_id\"],",
727
- " isUnique: true,",
728
- " }));",
729
- " }",
884
+ ` if (table && !table.indices.some((index) => index.name === ${JSON.stringify(generatedIdUniqueName)}))`,
885
+ ` await queryRunner.createIndex(tableName, new TableIndex(${this.renderTableIndexLiteral({
886
+ name: generatedIdUniqueName,
887
+ columnNames: ["ss_id"],
888
+ isUnique: true,
889
+ })}));`,
730
890
  " }",
731
891
  ].join("\n"));
732
892
  }
@@ -736,9 +896,8 @@ let DatasourceIntrospectionService = class DatasourceIntrospectionService {
736
896
  " {",
737
897
  " const table = await queryRunner.getTable(tableName);",
738
898
  ` const index = table?.indices.find((entry) => entry.name === ${JSON.stringify(generatedIdUniqueName)});`,
739
- " if (index) {",
899
+ " if (index)",
740
900
  " await queryRunner.dropIndex(tableName, index);",
741
- " }",
742
901
  " }",
743
902
  ].join("\n"));
744
903
  }
@@ -747,20 +906,16 @@ let DatasourceIntrospectionService = class DatasourceIntrospectionService {
747
906
  " {",
748
907
  " const table = await queryRunner.getTable(tableName);",
749
908
  ` const index = table?.indices.find((entry) => entry.name === ${JSON.stringify(deletedAtIndexName)});`,
750
- " if (index) {",
909
+ " if (index)",
751
910
  " await queryRunner.dropIndex(tableName, index);",
752
- " }",
753
911
  " }",
754
912
  ].join("\n"));
755
913
  }
756
914
  downStatements.push(...missingSystemColumns
757
915
  .slice()
758
916
  .reverse()
759
- .map((definition) => [
760
- ` if (await queryRunner.hasColumn(tableName, ${JSON.stringify(definition.columnName)})) {`,
761
- ` await queryRunner.dropColumn(tableName, ${JSON.stringify(definition.columnName)});`,
762
- " }",
763
- ].join("\n")));
917
+ .map((definition) => ` if (await queryRunner.hasColumn(tableName, ${JSON.stringify(definition.columnName)}))\n`
918
+ + ` await queryRunner.dropColumn(tableName, ${JSON.stringify(definition.columnName)});`));
764
919
  return [
765
920
  "import { MigrationInterface, QueryRunner, TableColumn, TableIndex } from \"typeorm\";",
766
921
  "",
@@ -783,27 +938,36 @@ let DatasourceIntrospectionService = class DatasourceIntrospectionService {
783
938
  }
784
939
  renderTableColumnLiteral(definition) {
785
940
  const properties = [
786
- `{\n name: ${JSON.stringify(definition.columnName)},`,
787
- ` type: ${JSON.stringify(definition.type)},`,
941
+ `name: ${JSON.stringify(definition.columnName)}`,
942
+ `type: ${JSON.stringify(definition.type)}`,
788
943
  ];
789
944
  if (definition.length) {
790
- properties.push(` length: ${JSON.stringify(definition.length)},`);
945
+ properties.push(`length: ${JSON.stringify(definition.length)}`);
791
946
  }
792
947
  if (typeof definition.isNullable === "boolean") {
793
- properties.push(` isNullable: ${definition.isNullable},`);
948
+ properties.push(`isNullable: ${definition.isNullable}`);
794
949
  }
795
950
  if (definition.defaultExpression) {
796
- properties.push(` default: ${JSON.stringify(definition.defaultExpression)},`);
951
+ properties.push(`default: ${JSON.stringify(definition.defaultExpression)}`);
797
952
  }
798
953
  if (definition.isGenerated) {
799
- properties.push(" isGenerated: true,");
800
- properties.push(" generationStrategy: \"increment\",");
954
+ properties.push("isGenerated: true");
955
+ properties.push("generationStrategy: \"increment\"");
956
+ }
957
+ if (definition.isUnique) {
958
+ properties.push("isUnique: true");
801
959
  }
960
+ return `{ ${properties.join(", ")}, }`;
961
+ }
962
+ renderTableIndexLiteral(definition) {
963
+ const properties = [
964
+ `name: ${JSON.stringify(definition.name)}`,
965
+ `columnNames: ${JSON.stringify(definition.columnNames)}`,
966
+ ];
802
967
  if (definition.isUnique) {
803
- properties.push(" isUnique: true,");
968
+ properties.push("isUnique: true");
804
969
  }
805
- properties.push(" }");
806
- return properties.join("\n");
970
+ return `{ ${properties.join(", ")}, }`;
807
971
  }
808
972
  buildMigrationObjectName(prefix, tableName, columnName) {
809
973
  const hash = (0, crypto_1.createHash)("md5").update(`${tableName}:${columnName}:${prefix}`).digest("hex").slice(0, 24);
@@ -832,12 +996,14 @@ let DatasourceIntrospectionService = class DatasourceIntrospectionService {
832
996
  async buildTableInventory(datasource) {
833
997
  const provider = this.getProvider(datasource.type);
834
998
  const runtimeDataSource = this.resolveDataSourceByName(datasource.name);
835
- const [tables, columns, models] = await Promise.all([
999
+ const [rawTables, rawColumns, models] = await Promise.all([
836
1000
  provider.listTables(runtimeDataSource),
837
1001
  provider.listColumns(runtimeDataSource),
838
1002
  this.modelMetadataRepository.find({ relations: { module: true } }),
839
1003
  ]);
840
- const modelMap = this.buildModelMap(models);
1004
+ const tables = rawTables.filter((table) => !this.isSolidxInternalTableName(table.tableName));
1005
+ const columns = rawColumns.filter((column) => !this.isSolidxInternalTableName(column.tableName));
1006
+ const modelLookup = this.buildModelLookup(models);
841
1007
  const columnsByKey = this.groupColumnsByTable(columns);
842
1008
  const tableKeys = new Set();
843
1009
  for (const table of tables) {
@@ -857,7 +1023,7 @@ let DatasourceIntrospectionService = class DatasourceIntrospectionService {
857
1023
  }
858
1024
  const suggestedLegacyTableType = this.detectLegacyTableType(datasource.type, tableColumns);
859
1025
  const suggestedIdColumn = this.getSuggestedIdColumn(datasource.type, tableColumns, suggestedLegacyTableType);
860
- const mappedModel = modelMap.get(this.toModelMapKey(datasource.name, tableName)) ?? null;
1026
+ const mappedModel = this.resolveMappedModel(modelLookup, datasource.name, tableName);
861
1027
  const physicalColumns = tableColumns.filter((column) => !this.isHandledBySuperclass(column.columnName, suggestedLegacyTableType));
862
1028
  return {
863
1029
  schema,
@@ -892,16 +1058,37 @@ let DatasourceIntrospectionService = class DatasourceIntrospectionService {
892
1058
  columnsByKey,
893
1059
  };
894
1060
  }
895
- buildModelMap(models) {
896
- const map = new Map();
1061
+ buildModelLookup(models) {
1062
+ const byDatasourceAndTable = new Map();
1063
+ const byTableName = new Map();
897
1064
  for (const model of models) {
898
1065
  if (!model.tableName) {
899
1066
  continue;
900
1067
  }
901
- map.set(this.toModelMapKey(model.dataSource, model.tableName), model);
902
- map.set(this.toModelMapKey("*", model.tableName), model);
1068
+ byDatasourceAndTable.set(this.toModelMapKey(model.dataSource, model.tableName), model);
1069
+ const normalizedTableName = model.tableName.trim().toLowerCase();
1070
+ const bucket = byTableName.get(normalizedTableName);
1071
+ if (bucket) {
1072
+ bucket.push(model);
1073
+ continue;
1074
+ }
1075
+ byTableName.set(normalizedTableName, [model]);
1076
+ }
1077
+ return {
1078
+ byDatasourceAndTable,
1079
+ byTableName,
1080
+ };
1081
+ }
1082
+ resolveMappedModel(lookup, datasourceName, tableName) {
1083
+ const exactMatch = lookup.byDatasourceAndTable.get(this.toModelMapKey(datasourceName, tableName));
1084
+ if (exactMatch) {
1085
+ return exactMatch;
1086
+ }
1087
+ const fallbackMatches = lookup.byTableName.get(tableName.trim().toLowerCase()) ?? [];
1088
+ if (fallbackMatches.length === 1) {
1089
+ return fallbackMatches[0];
903
1090
  }
904
- return map;
1091
+ return fallbackMatches[0] ?? null;
905
1092
  }
906
1093
  groupColumnsByTable(columns) {
907
1094
  const grouped = new Map();
@@ -916,6 +1103,9 @@ let DatasourceIntrospectionService = class DatasourceIntrospectionService {
916
1103
  }
917
1104
  return grouped;
918
1105
  }
1106
+ isSolidxInternalTableName(tableName) {
1107
+ return typeof tableName === "string" && tableName.toLowerCase().startsWith("ss_");
1108
+ }
919
1109
  detectLegacyTableType(datasourceType, columns) {
920
1110
  const normalizedDatasourceType = datasourceType.toLowerCase();
921
1111
  const hasExistingGeneratedId = columns.some((column) => column.isAutoGenerated);
@@ -983,12 +1173,16 @@ let DatasourceIntrospectionService = class DatasourceIntrospectionService {
983
1173
  }
984
1174
  toDetailColumnRecord(column, legacyTableType, datasourceType) {
985
1175
  const superclassFieldName = this.getSuperclassFieldName(column.columnName, legacyTableType);
1176
+ const normalizedColumnName = column.columnName.toLowerCase();
986
1177
  const fieldName = legacyTableType === legacy_table_type_enum_1.LegacyTableType.EXISTING_ID && column.isAutoGenerated
987
1178
  ? "id"
988
- : this.toFieldName(column.columnName);
1179
+ : legacyTableType === legacy_table_type_enum_1.LegacyTableType.GENERATED_ID && normalizedColumnName === "id"
1180
+ ? "legacyId"
1181
+ : this.toFieldName(column.columnName);
989
1182
  return {
990
1183
  columnName: column.columnName,
991
1184
  fieldName,
1185
+ displayName: (0, lodash_1.startCase)(fieldName),
992
1186
  dataType: column.dataType,
993
1187
  solidFieldType: this.toSolidFieldType(column),
994
1188
  ormType: this.toOrmFieldType(column, datasourceType),
@@ -999,6 +1193,7 @@ let DatasourceIntrospectionService = class DatasourceIntrospectionService {
999
1193
  numericScale: column.numericScale,
1000
1194
  ordinalPosition: column.ordinalPosition,
1001
1195
  isAutoGenerated: column.isAutoGenerated,
1196
+ isPrimaryKey: column.isPrimaryKey,
1002
1197
  handledBySuperclass: Boolean(superclassFieldName),
1003
1198
  superclassFieldName,
1004
1199
  };
@@ -1033,127 +1228,70 @@ let DatasourceIntrospectionService = class DatasourceIntrospectionService {
1033
1228
  }
1034
1229
  return "LegacyCommonEntityWithExistingId";
1035
1230
  }
1036
- toSolidFieldType(column) {
1037
- const normalized = column.dataType.toLowerCase();
1038
- const charLength = column.characterMaximumLength ?? null;
1039
- if (["bit", "bool", "boolean"].includes(normalized)) {
1040
- return "boolean";
1041
- }
1042
- if (["bigint"].includes(normalized)) {
1043
- return "bigint";
1044
- }
1045
- if (["int", "integer", "smallint", "tinyint"].includes(normalized)) {
1046
- return "int";
1047
- }
1048
- if (["numeric", "decimal", "float", "double", "real", "money", "smallmoney"].includes(normalized)) {
1049
- return "decimal";
1050
- }
1051
- if (["date"].includes(normalized)) {
1052
- return "date";
1053
- }
1054
- if (["time"].includes(normalized)) {
1055
- return "time";
1056
- }
1057
- if (["datetime", "datetime2", "timestamp", "timestamptz", "smalldatetime"].includes(normalized) || normalized.includes("date")) {
1058
- return "datetime";
1231
+ getDatasourceTypeFamily(dataType) {
1232
+ const normalized = dataType.toLowerCase();
1233
+ for (const [family, aliases] of Object.entries(DATASOURCE_TYPE_FAMILY_ALIASES)) {
1234
+ if (aliases.includes(normalized)) {
1235
+ return family;
1236
+ }
1059
1237
  }
1060
- if (["json", "jsonb", "simple-json", "simplejson"].includes(normalized) || normalized.includes("json")) {
1238
+ if (normalized.includes("json")) {
1061
1239
  return "json";
1062
1240
  }
1063
- if (["uniqueidentifier", "uuid"].includes(normalized)) {
1064
- return "uuid";
1065
- }
1066
- if (["text", "ntext", "mediumtext", "longtext", "clob"].includes(normalized)) {
1067
- return "longText";
1068
- }
1069
- if (["varchar", "nvarchar", "char", "nchar", "citext"].includes(normalized)) {
1070
- if (charLength !== null && charLength > 255) {
1071
- return "longText";
1072
- }
1073
- return "shortText";
1241
+ if (normalized.includes("date")) {
1242
+ return "datetime";
1074
1243
  }
1075
- return "shortText";
1244
+ return null;
1076
1245
  }
1077
- toOrmFieldType(column, datasourceType) {
1078
- const normalized = column.dataType.toLowerCase();
1079
- const normalizedDatasourceType = datasourceType.toLowerCase();
1080
- if (normalizedDatasourceType === "mssql") {
1081
- if (["bit", "bool", "boolean"].includes(normalized))
1082
- return "bit";
1083
- if (["bigint"].includes(normalized))
1246
+ toSolidFieldType(column) {
1247
+ const family = this.getDatasourceTypeFamily(column.dataType);
1248
+ const charLength = column.characterMaximumLength ?? null;
1249
+ switch (family) {
1250
+ case "boolean":
1251
+ return "boolean";
1252
+ case "bigint":
1084
1253
  return "bigint";
1085
- if (["int", "integer", "smallint", "tinyint"].includes(normalized))
1086
- return "int";
1087
- if (["numeric"].includes(normalized))
1088
- return "numeric";
1089
- if (["decimal", "float", "double", "real", "money", "smallmoney"].includes(normalized))
1090
- return "decimal";
1091
- if (["date"].includes(normalized))
1092
- return "date";
1093
- if (["time"].includes(normalized))
1094
- return "time";
1095
- if (["datetime2"].includes(normalized))
1096
- return "datetime2";
1097
- if (["datetime", "smalldatetime", "timestamp"].includes(normalized) || normalized.includes("date"))
1098
- return "datetime";
1099
- if (["json", "jsonb", "simple-json", "simplejson"].includes(normalized) || normalized.includes("json"))
1100
- return "simple-json";
1101
- if (["uniqueidentifier", "uuid"].includes(normalized))
1102
- return "uniqueidentifier";
1103
- if (["text", "ntext", "mediumtext", "longtext", "clob"].includes(normalized))
1104
- return "text";
1105
- if (["nvarchar", "nchar"].includes(normalized))
1106
- return "nvarchar";
1107
- return "varchar";
1108
- }
1109
- if (normalizedDatasourceType === "mysql") {
1110
- if (["bigint"].includes(normalized))
1111
- return "int";
1112
- if (["int", "integer", "smallint", "tinyint"].includes(normalized))
1254
+ case "int":
1113
1255
  return "int";
1114
- if (["decimal", "numeric"].includes(normalized))
1256
+ case "numeric":
1257
+ case "decimal":
1258
+ case "float":
1115
1259
  return "decimal";
1116
- if (["float", "double", "real", "money", "smallmoney"].includes(normalized))
1117
- return "double";
1118
- if (["bit", "bool", "boolean"].includes(normalized))
1119
- return "boolean";
1120
- if (["date"].includes(normalized))
1260
+ case "date":
1121
1261
  return "date";
1122
- if (["time"].includes(normalized))
1262
+ case "time":
1123
1263
  return "time";
1124
- if (["datetime", "timestamp", "smalldatetime"].includes(normalized) || normalized.includes("date"))
1264
+ case "datetime":
1265
+ case "datetimeWithTimezone":
1125
1266
  return "datetime";
1126
- if (["json", "jsonb", "simple-json", "simplejson"].includes(normalized) || normalized.includes("json"))
1267
+ case "json":
1268
+ case "jsonb":
1127
1269
  return "json";
1128
- if (["mediumtext"].includes(normalized))
1129
- return "mediumtext";
1130
- if (["longtext", "text", "ntext", "clob"].includes(normalized))
1131
- return "longtext";
1132
- return "varchar";
1133
- }
1134
- if (["bigint"].includes(normalized))
1135
- return "bigint";
1136
- if (["int", "integer", "smallint", "tinyint"].includes(normalized))
1137
- return "integer";
1138
- if (["decimal", "numeric", "float", "double", "real", "money", "smallmoney"].includes(normalized))
1139
- return "decimal";
1140
- if (["bit", "bool", "boolean"].includes(normalized))
1141
- return "boolean";
1142
- if (["date"].includes(normalized))
1143
- return "date";
1144
- if (["time"].includes(normalized))
1145
- return "time";
1146
- if (["timestamptz"].includes(normalized))
1147
- return "timestamptz";
1148
- if (["datetime", "datetime2", "timestamp", "smalldatetime"].includes(normalized) || normalized.includes("date"))
1149
- return "timestamp";
1150
- if (["jsonb"].includes(normalized))
1151
- return "jsonb";
1152
- if (["json", "simple-json", "simplejson"].includes(normalized) || normalized.includes("json"))
1153
- return "json";
1154
- if (["text", "ntext", "mediumtext", "longtext", "clob"].includes(normalized))
1155
- return "text";
1156
- return "varchar";
1270
+ case "uuid":
1271
+ return "uuid";
1272
+ case "mediumText":
1273
+ case "longText":
1274
+ return "longText";
1275
+ case "shortText":
1276
+ case "unicodeShortText":
1277
+ if (charLength !== null && charLength > 255) {
1278
+ return "longText";
1279
+ }
1280
+ return "shortText";
1281
+ default:
1282
+ return "shortText";
1283
+ }
1284
+ }
1285
+ toOrmFieldType(column, datasourceType) {
1286
+ const family = this.getDatasourceTypeFamily(column.dataType);
1287
+ const normalizedDatasourceType = datasourceType.toLowerCase();
1288
+ const ormType = family
1289
+ ? ORM_TYPE_BY_DATASOURCE_FAMILY[normalizedDatasourceType]?.[family]
1290
+ : undefined;
1291
+ if (ormType) {
1292
+ return ormType;
1293
+ }
1294
+ return normalizedDatasourceType === "postgres" ? "varchar" : "varchar";
1157
1295
  }
1158
1296
  toFieldName(columnName) {
1159
1297
  return (0, lodash_1.camelCase)(columnName.replace(/^ss_/, ""));
@@ -1190,6 +1328,240 @@ let DatasourceIntrospectionService = class DatasourceIntrospectionService {
1190
1328
  toModelMapKey(datasourceName, tableName) {
1191
1329
  return `${datasourceName.toLowerCase()}::${tableName.toLowerCase()}`;
1192
1330
  }
1331
+ async syncTypeormDatasourceFile(moduleName, datasource, singularName) {
1332
+ const datasourceFilePath = path.resolve(process.cwd(), "src", `typeorm-${datasource.name}-datasource.ts`);
1333
+ const entityClassName = (0, string_helper_1.classify)(singularName);
1334
+ const entityImportPath = `./${moduleName}/entities/${(0, lodash_1.kebabCase)(singularName)}.entity`;
1335
+ const migrationGlob = `join(__dirname, './${moduleName}/migrations/${datasource.name}/*.{ts,js}')`;
1336
+ const existingContent = await fs.readFile(datasourceFilePath, "utf8").catch(() => null);
1337
+ if (!existingContent) {
1338
+ const rendered = this.renderTypeormDatasourceTemplate({
1339
+ datasource,
1340
+ entityClassName,
1341
+ entityImportPath,
1342
+ migrationGlob,
1343
+ });
1344
+ await fs.writeFile(datasourceFilePath, rendered, "utf8");
1345
+ return {
1346
+ filePath: datasourceFilePath,
1347
+ created: true,
1348
+ updated: false,
1349
+ entityRegistered: true,
1350
+ migrationGlobRegistered: true,
1351
+ };
1352
+ }
1353
+ const project = new ts_morph_1.Project({
1354
+ skipAddingFilesFromTsConfig: true,
1355
+ manipulationSettings: {
1356
+ quoteKind: ts_morph_1.QuoteKind.Single,
1357
+ indentationText: ts_morph_1.IndentationText.FourSpaces,
1358
+ insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: true,
1359
+ },
1360
+ });
1361
+ const sourceFile = project.createSourceFile(datasourceFilePath, existingContent, { overwrite: true });
1362
+ const entityImportDeclaration = sourceFile.getImportDeclarations().find((declaration) => declaration.getModuleSpecifierValue() === entityImportPath);
1363
+ if (entityImportDeclaration) {
1364
+ const alreadyImported = entityImportDeclaration.getNamedImports().some((namedImport) => namedImport.getName() === entityClassName);
1365
+ if (!alreadyImported) {
1366
+ entityImportDeclaration.addNamedImport(entityClassName);
1367
+ }
1368
+ }
1369
+ else {
1370
+ sourceFile.addImportDeclaration({
1371
+ moduleSpecifier: entityImportPath,
1372
+ namedImports: [entityClassName],
1373
+ });
1374
+ }
1375
+ const entitiesArray = sourceFile
1376
+ .getVariableDeclarationOrThrow("entities")
1377
+ .getInitializerIfKindOrThrow(ts_morph_1.SyntaxKind.ArrayLiteralExpression);
1378
+ const entityAlreadyRegistered = this.arrayLiteralContainsValue(entitiesArray, entityClassName);
1379
+ if (!entityAlreadyRegistered) {
1380
+ entitiesArray.addElement(entityClassName);
1381
+ }
1382
+ const dataSourceOptions = this.getTypeormDatasourceOptions(sourceFile);
1383
+ const migrationsArray = this.getObjectPropertyArrayLiteral(dataSourceOptions, "migrations");
1384
+ const migrationAlreadyRegistered = this.arrayLiteralContainsValue(migrationsArray, migrationGlob);
1385
+ if (!migrationAlreadyRegistered) {
1386
+ migrationsArray.addElement(migrationGlob);
1387
+ }
1388
+ sourceFile.organizeImports();
1389
+ sourceFile.formatText();
1390
+ const nextContent = sourceFile.getFullText();
1391
+ const updated = nextContent !== existingContent;
1392
+ if (updated) {
1393
+ await fs.writeFile(datasourceFilePath, nextContent, "utf8");
1394
+ }
1395
+ return {
1396
+ filePath: datasourceFilePath,
1397
+ created: false,
1398
+ updated,
1399
+ entityRegistered: true,
1400
+ migrationGlobRegistered: true,
1401
+ };
1402
+ }
1403
+ renderTypeormDatasourceTemplate(input) {
1404
+ const { datasource, entityClassName, entityImportPath, migrationGlob } = input;
1405
+ const envPrefix = datasource.envPrefix?.toUpperCase?.() || "DEFAULT";
1406
+ const portFallback = datasource.type === "postgres" ? 5432 : datasource.type === "mysql" ? 3306 : 1433;
1407
+ const project = new ts_morph_1.Project({
1408
+ skipAddingFilesFromTsConfig: true,
1409
+ manipulationSettings: {
1410
+ quoteKind: ts_morph_1.QuoteKind.Single,
1411
+ indentationText: ts_morph_1.IndentationText.FourSpaces,
1412
+ insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: true,
1413
+ },
1414
+ });
1415
+ const sourceFile = project.createSourceFile("typeorm-template.ts", "", { overwrite: true });
1416
+ sourceFile.addImportDeclaration({ moduleSpecifier: "reflect-metadata" });
1417
+ sourceFile.addImportDeclaration({ moduleSpecifier: "path", namedImports: ["join"] });
1418
+ sourceFile.addImportDeclaration({
1419
+ moduleSpecifier: "dotenv",
1420
+ namedImports: [{ name: "config", alias: "dotenvConfig" }],
1421
+ });
1422
+ sourceFile.addStatements("dotenvConfig({ path: join(__dirname, '../.env') });");
1423
+ sourceFile.addStatements("");
1424
+ sourceFile.addImportDeclaration({ moduleSpecifier: "typeorm", namedImports: ["DataSource"] });
1425
+ sourceFile.addImportDeclaration({
1426
+ moduleSpecifier: "@solidxai/core",
1427
+ namespaceImport: "SolidCoreModuleExports",
1428
+ });
1429
+ sourceFile.addImportDeclaration({
1430
+ moduleSpecifier: "@solidxai/core",
1431
+ namedImports: ["getDynamicModuleNames", "parseBooleanEnv"],
1432
+ });
1433
+ sourceFile.addImportDeclaration({
1434
+ moduleSpecifier: "typeorm",
1435
+ namedImports: ["getMetadataArgsStorage"],
1436
+ });
1437
+ sourceFile.addImportDeclaration({
1438
+ moduleSpecifier: "typeorm-naming-strategies",
1439
+ namedImports: ["SnakeNamingStrategy"],
1440
+ });
1441
+ sourceFile.addImportDeclaration({
1442
+ moduleSpecifier: entityImportPath,
1443
+ namedImports: [entityClassName],
1444
+ });
1445
+ sourceFile.addFunction({
1446
+ name: "getEntitiesFromExports",
1447
+ parameters: [{ name: "exports", type: "Record<string, any>" }],
1448
+ statements: (writer) => {
1449
+ writer.writeLine("const metadataStorage = getMetadataArgsStorage();");
1450
+ writer.writeLine("return Object.values(exports).filter((item) =>");
1451
+ writer.indent(() => {
1452
+ writer.writeLine("metadataStorage.tables.some((table) => table.target === item),");
1453
+ });
1454
+ writer.write(");");
1455
+ },
1456
+ });
1457
+ sourceFile.addVariableStatement({
1458
+ declarationKind: ts_morph_1.VariableDeclarationKind.Const,
1459
+ declarations: [
1460
+ {
1461
+ name: "coreEntities",
1462
+ initializer: "getEntitiesFromExports(SolidCoreModuleExports)",
1463
+ },
1464
+ ],
1465
+ });
1466
+ sourceFile.addVariableStatement({
1467
+ declarationKind: ts_morph_1.VariableDeclarationKind.Const,
1468
+ declarations: [
1469
+ {
1470
+ name: "dynamicModules",
1471
+ initializer: "getDynamicModuleNames()",
1472
+ },
1473
+ ],
1474
+ });
1475
+ sourceFile.addVariableStatement({
1476
+ declarationKind: ts_morph_1.VariableDeclarationKind.Const,
1477
+ declarations: [
1478
+ {
1479
+ name: "entities",
1480
+ initializer: `[\n ...coreEntities,\n ${entityClassName},\n]`,
1481
+ },
1482
+ ],
1483
+ });
1484
+ sourceFile.addVariableStatement({
1485
+ declarationKind: ts_morph_1.VariableDeclarationKind.Const,
1486
+ declarations: [
1487
+ {
1488
+ name: "logging",
1489
+ initializer: `parseBooleanEnv('${envPrefix}_DATABASE_LOGGING')`,
1490
+ },
1491
+ ],
1492
+ });
1493
+ sourceFile.addStatements("// IMPORTANT: synchronize must be false when using migrations");
1494
+ sourceFile.addVariableStatement({
1495
+ declarationKind: ts_morph_1.VariableDeclarationKind.Const,
1496
+ isExported: true,
1497
+ declarations: [
1498
+ {
1499
+ name: "DefaultDataSource",
1500
+ initializer: (writer) => {
1501
+ writer.write("new DataSource(");
1502
+ writer.inlineBlock(() => {
1503
+ writer.writeLine(`type: '${datasource.type}',`);
1504
+ writer.blankLine();
1505
+ writer.writeLine(`host: process.env.${envPrefix}_DATABASE_HOST,`);
1506
+ writer.writeLine(`port: +(process.env.${envPrefix}_DATABASE_PORT || ${portFallback}),`);
1507
+ writer.writeLine(`username: process.env.${envPrefix}_DATABASE_USER,`);
1508
+ writer.writeLine(`password: process.env.${envPrefix}_DATABASE_PASSWORD,`);
1509
+ writer.writeLine(`database: process.env.${envPrefix}_DATABASE_NAME,`);
1510
+ writer.blankLine();
1511
+ writer.writeLine("entities,");
1512
+ writer.writeLine("migrations: [");
1513
+ writer.indent(() => {
1514
+ writer.writeLine(`${migrationGlob},`);
1515
+ });
1516
+ writer.writeLine("],");
1517
+ writer.writeLine("synchronize: false,");
1518
+ writer.writeLine("logging,");
1519
+ writer.writeLine("namingStrategy: new SnakeNamingStrategy(),");
1520
+ if (datasource.type === "mssql") {
1521
+ writer.writeLine("options: {");
1522
+ writer.indent(() => {
1523
+ writer.writeLine("encrypt: false,");
1524
+ writer.writeLine("trustServerCertificate: true,");
1525
+ });
1526
+ writer.writeLine("},");
1527
+ }
1528
+ });
1529
+ writer.write(")");
1530
+ },
1531
+ },
1532
+ ],
1533
+ });
1534
+ sourceFile.organizeImports();
1535
+ sourceFile.formatText();
1536
+ return sourceFile.getFullText();
1537
+ }
1538
+ arrayLiteralContainsValue(arrayLiteral, rawValue) {
1539
+ const normalizedTarget = rawValue.replace(/\s+/g, "");
1540
+ return arrayLiteral.getElements().some((element) => element.getText().replace(/\s+/g, "") === normalizedTarget);
1541
+ }
1542
+ getTypeormDatasourceOptions(sourceFile) {
1543
+ const defaultDataSourceDeclaration = sourceFile.getVariableDeclarationOrThrow("DefaultDataSource");
1544
+ const initializer = defaultDataSourceDeclaration.getInitializer();
1545
+ if (!initializer || !ts_morph_1.Node.isNewExpression(initializer)) {
1546
+ throw new common_1.BadRequestException("Unable to locate DefaultDataSource initializer in datasource file.");
1547
+ }
1548
+ const options = initializer.getArguments()[0];
1549
+ if (!options || !ts_morph_1.Node.isObjectLiteralExpression(options)) {
1550
+ throw new common_1.BadRequestException("Unable to locate DefaultDataSource options object in datasource file.");
1551
+ }
1552
+ return options;
1553
+ }
1554
+ getObjectPropertyArrayLiteral(objectLiteral, propertyName) {
1555
+ const property = objectLiteral.getProperty(propertyName);
1556
+ if (!property || !ts_morph_1.Node.isPropertyAssignment(property)) {
1557
+ throw new common_1.BadRequestException(`Unable to locate "${propertyName}" property in datasource file.`);
1558
+ }
1559
+ const initializer = property.getInitializer();
1560
+ if (!initializer || !ts_morph_1.Node.isArrayLiteralExpression(initializer)) {
1561
+ throw new common_1.BadRequestException(`Unable to locate "${propertyName}" array in datasource file.`);
1562
+ }
1563
+ return initializer;
1564
+ }
1193
1565
  buildSynchronizeBlockedMessage(datasource) {
1194
1566
  return `Datasource "${datasource.displayName}" has synchronize enabled. Set ${datasource.envPrefix}_DATABASE_SYNCHRONIZE=false before starting legacy table introspection.`;
1195
1567
  }
@@ -1271,6 +1643,8 @@ exports.DatasourceIntrospectionService = DatasourceIntrospectionService = __deco
1271
1643
  model_metadata_helper_service_1.ModelMetadataHelperService,
1272
1644
  field_metadata_service_1.FieldMetadataService,
1273
1645
  model_metadata_service_1.ModelMetadataService,
1646
+ module_metadata_service_1.ModuleMetadataService,
1647
+ command_service_1.CommandService,
1274
1648
  mssql_datasource_introspection_provider_service_1.MssqlDatasourceIntrospectionProviderService,
1275
1649
  mysql_datasource_introspection_provider_service_1.MysqlDatasourceIntrospectionProviderService,
1276
1650
  postgres_datasource_introspection_provider_service_1.PostgresDatasourceIntrospectionProviderService])