@solidxai/core 0.1.11-beta.0 → 0.1.11-beta.11
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.
- package/.claude/settings.local.json +2 -1
- package/CLAUDE.md +26 -0
- package/dist/commands/migrate-removed-fields.command.d.ts +19 -0
- package/dist/commands/migrate-removed-fields.command.d.ts.map +1 -0
- package/dist/commands/migrate-removed-fields.command.js +77 -0
- package/dist/commands/migrate-removed-fields.command.js.map +1 -0
- package/dist/controllers/datasource-introspection.controller.d.ts +46 -1
- package/dist/controllers/datasource-introspection.controller.d.ts.map +1 -1
- package/dist/controllers/datasource-introspection.controller.js +38 -0
- package/dist/controllers/datasource-introspection.controller.js.map +1 -1
- package/dist/controllers/service.controller.d.ts +1 -0
- package/dist/controllers/service.controller.d.ts.map +1 -1
- package/dist/controllers/service.controller.js +2 -2
- package/dist/controllers/service.controller.js.map +1 -1
- package/dist/dtos/datasource-introspection-mapping.dto.d.ts +5 -0
- package/dist/dtos/datasource-introspection-mapping.dto.d.ts.map +1 -1
- package/dist/dtos/datasource-introspection-mapping.dto.js +24 -2
- package/dist/dtos/datasource-introspection-mapping.dto.js.map +1 -1
- package/dist/entities/{legacy-common-with-id.entity.d.ts → legacy-common-with-generated-id.entity.d.ts} +2 -2
- package/dist/entities/legacy-common-with-generated-id.entity.d.ts.map +1 -0
- package/dist/entities/{legacy-common-with-id.entity.js → legacy-common-with-generated-id.entity.js} +4 -4
- package/dist/entities/legacy-common-with-generated-id.entity.js.map +1 -0
- package/dist/entities/{legacy-common.entity.d.ts → legacy-common.entity-with-existing-id.entity.d.ts} +1 -1
- package/dist/entities/legacy-common.entity-with-existing-id.entity.d.ts.map +1 -0
- package/dist/entities/{legacy-common.entity.js → legacy-common.entity-with-existing-id.entity.js} +1 -1
- package/dist/entities/legacy-common.entity-with-existing-id.entity.js.map +1 -0
- package/dist/helpers/command.service.d.ts +2 -0
- package/dist/helpers/command.service.d.ts.map +1 -1
- package/dist/helpers/command.service.js +6 -2
- package/dist/helpers/command.service.js.map +1 -1
- package/dist/helpers/environment.helper.d.ts +1 -0
- package/dist/helpers/environment.helper.d.ts.map +1 -1
- package/dist/helpers/environment.helper.js +4 -0
- package/dist/helpers/environment.helper.js.map +1 -1
- package/dist/helpers/field-crud-managers/IntFieldCrudManager.d.ts.map +1 -1
- package/dist/helpers/field-crud-managers/IntFieldCrudManager.js +4 -1
- package/dist/helpers/field-crud-managers/IntFieldCrudManager.js.map +1 -1
- package/dist/helpers/model-metadata-helper.service.d.ts +2 -1
- package/dist/helpers/model-metadata-helper.service.d.ts.map +1 -1
- package/dist/helpers/model-metadata-helper.service.js +9 -5
- package/dist/helpers/model-metadata-helper.service.js.map +1 -1
- package/dist/helpers/nodemon-heartbeat.d.ts +5 -0
- package/dist/helpers/nodemon-heartbeat.d.ts.map +1 -0
- package/dist/helpers/nodemon-heartbeat.js +67 -0
- package/dist/helpers/nodemon-heartbeat.js.map +1 -0
- package/dist/helpers/solid-registry.d.ts +2 -1
- package/dist/helpers/solid-registry.d.ts.map +1 -1
- package/dist/helpers/solid-registry.js.map +1 -1
- package/dist/helpers/typeorm-db-helper.d.ts +1 -0
- package/dist/helpers/typeorm-db-helper.d.ts.map +1 -1
- package/dist/helpers/typeorm-db-helper.js +12 -0
- package/dist/helpers/typeorm-db-helper.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/interfaces/datasource-introspection-provider.interface.d.ts +1 -0
- package/dist/interfaces/datasource-introspection-provider.interface.d.ts.map +1 -1
- package/dist/interfaces/datasource-introspection-provider.interface.js.map +1 -1
- package/dist/interfaces.d.ts +1 -0
- package/dist/interfaces.d.ts.map +1 -1
- package/dist/interfaces.js.map +1 -1
- package/dist/repository/scheduled-job.repository.d.ts +5 -2
- package/dist/repository/scheduled-job.repository.d.ts.map +1 -1
- package/dist/repository/scheduled-job.repository.js +66 -3
- package/dist/repository/scheduled-job.repository.js.map +1 -1
- package/dist/repository/security-rule.repository.d.ts +2 -2
- package/dist/repository/security-rule.repository.d.ts.map +1 -1
- package/dist/repository/security-rule.repository.js +6 -3
- package/dist/repository/security-rule.repository.js.map +1 -1
- package/dist/seeders/module-metadata-seeder.service.d.ts +43 -2
- package/dist/seeders/module-metadata-seeder.service.d.ts.map +1 -1
- package/dist/seeders/module-metadata-seeder.service.js +1173 -232
- package/dist/seeders/module-metadata-seeder.service.js.map +1 -1
- package/dist/seeders/seed-data/solid-core-metadata.json +128 -34
- package/dist/services/action-metadata.service.d.ts +7 -0
- package/dist/services/action-metadata.service.d.ts.map +1 -1
- package/dist/services/action-metadata.service.js +76 -3
- package/dist/services/action-metadata.service.js.map +1 -1
- package/dist/services/api-key.service.d.ts.map +1 -1
- package/dist/services/api-key.service.js.map +1 -1
- package/dist/services/authentication.service.d.ts +2 -0
- package/dist/services/authentication.service.d.ts.map +1 -1
- package/dist/services/authentication.service.js +32 -11
- package/dist/services/authentication.service.js.map +1 -1
- package/dist/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.d.ts.map +1 -1
- package/dist/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.js +7 -5
- package/dist/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.js.map +1 -1
- package/dist/services/computed-fields/entity/concat-entity-computed-field-provider.service.d.ts +4 -0
- package/dist/services/computed-fields/entity/concat-entity-computed-field-provider.service.d.ts.map +1 -1
- package/dist/services/computed-fields/entity/concat-entity-computed-field-provider.service.js +18 -1
- package/dist/services/computed-fields/entity/concat-entity-computed-field-provider.service.js.map +1 -1
- package/dist/services/crud-helper.service.d.ts.map +1 -1
- package/dist/services/crud-helper.service.js +25 -12
- package/dist/services/crud-helper.service.js.map +1 -1
- package/dist/services/crud.service.d.ts +1 -0
- package/dist/services/crud.service.d.ts.map +1 -1
- package/dist/services/crud.service.js +27 -0
- package/dist/services/crud.service.js.map +1 -1
- package/dist/services/datasource-introspection/mssql-datasource-introspection-provider.service.d.ts.map +1 -1
- package/dist/services/datasource-introspection/mssql-datasource-introspection-provider.service.js +12 -0
- package/dist/services/datasource-introspection/mssql-datasource-introspection-provider.service.js.map +1 -1
- package/dist/services/datasource-introspection/mysql-datasource-introspection-provider.service.d.ts.map +1 -1
- package/dist/services/datasource-introspection/mysql-datasource-introspection-provider.service.js +2 -0
- package/dist/services/datasource-introspection/mysql-datasource-introspection-provider.service.js.map +1 -1
- package/dist/services/datasource-introspection/postgres-datasource-introspection-provider.service.d.ts.map +1 -1
- package/dist/services/datasource-introspection/postgres-datasource-introspection-provider.service.js +28 -15
- package/dist/services/datasource-introspection/postgres-datasource-introspection-provider.service.js.map +1 -1
- package/dist/services/datasource-introspection.service.d.ts +62 -2
- package/dist/services/datasource-introspection.service.d.ts.map +1 -1
- package/dist/services/datasource-introspection.service.js +654 -186
- package/dist/services/datasource-introspection.service.js.map +1 -1
- package/dist/services/import-transaction.service.d.ts.map +1 -1
- package/dist/services/import-transaction.service.js +3 -0
- package/dist/services/import-transaction.service.js.map +1 -1
- package/dist/services/locale.service.d.ts +14 -0
- package/dist/services/locale.service.d.ts.map +1 -1
- package/dist/services/locale.service.js +83 -0
- package/dist/services/locale.service.js.map +1 -1
- package/dist/services/mediaStorageProviders/file-s3-storage-provider.js +10 -10
- package/dist/services/mediaStorageProviders/file-s3-storage-provider.js.map +1 -1
- package/dist/services/menu-item-metadata.service.d.ts.map +1 -1
- package/dist/services/menu-item-metadata.service.js +1 -0
- package/dist/services/menu-item-metadata.service.js.map +1 -1
- package/dist/services/model-metadata.service.d.ts +3 -0
- package/dist/services/model-metadata.service.d.ts.map +1 -1
- package/dist/services/model-metadata.service.js +78 -0
- package/dist/services/model-metadata.service.js.map +1 -1
- package/dist/services/module-metadata.service.d.ts.map +1 -1
- package/dist/services/module-metadata.service.js +28 -0
- package/dist/services/module-metadata.service.js.map +1 -1
- package/dist/services/removed-field-migration.service.d.ts +30 -0
- package/dist/services/removed-field-migration.service.d.ts.map +1 -0
- package/dist/services/removed-field-migration.service.js +319 -0
- package/dist/services/removed-field-migration.service.js.map +1 -0
- package/dist/services/role-metadata.service.d.ts +5 -0
- package/dist/services/role-metadata.service.d.ts.map +1 -1
- package/dist/services/role-metadata.service.js +95 -33
- package/dist/services/role-metadata.service.js.map +1 -1
- package/dist/services/settings/default-settings-provider.service.d.ts +244 -0
- package/dist/services/settings/default-settings-provider.service.d.ts.map +1 -1
- package/dist/services/settings/default-settings-provider.service.js +120 -0
- package/dist/services/settings/default-settings-provider.service.js.map +1 -1
- package/dist/services/solid-ts-morph.service.d.ts +6 -0
- package/dist/services/solid-ts-morph.service.d.ts.map +1 -1
- package/dist/services/solid-ts-morph.service.js +43 -0
- package/dist/services/solid-ts-morph.service.js.map +1 -1
- package/dist/services/view-metadata.service.d.ts +6 -0
- package/dist/services/view-metadata.service.d.ts.map +1 -1
- package/dist/services/view-metadata.service.js +70 -8
- package/dist/services/view-metadata.service.js.map +1 -1
- package/dist/solid-core.module.d.ts.map +1 -1
- package/dist/solid-core.module.js +4 -0
- package/dist/solid-core.module.js.map +1 -1
- package/dist/subscribers/audit.subscriber.d.ts +5 -1
- package/dist/subscribers/audit.subscriber.d.ts.map +1 -1
- package/dist/subscribers/audit.subscriber.js +76 -12
- package/dist/subscribers/audit.subscriber.js.map +1 -1
- package/dist/subscribers/computed-entity-field.subscriber.d.ts +9 -1
- package/dist/subscribers/computed-entity-field.subscriber.d.ts.map +1 -1
- package/dist/subscribers/computed-entity-field.subscriber.js +45 -11
- package/dist/subscribers/computed-entity-field.subscriber.js.map +1 -1
- package/dist/subscribers/created-by-updated-by.subscriber.d.ts.map +1 -1
- package/dist/subscribers/created-by-updated-by.subscriber.js.map +1 -1
- package/dist/subscribers/field-metadata.subscriber.d.ts.map +1 -1
- package/dist/subscribers/field-metadata.subscriber.js.map +1 -1
- package/dist/subscribers/scheduled-job.subscriber.d.ts.map +1 -1
- package/dist/subscribers/scheduled-job.subscriber.js +3 -2
- package/dist/subscribers/scheduled-job.subscriber.js.map +1 -1
- package/dist/subscribers/security-rule.subscriber.d.ts.map +1 -1
- package/dist/subscribers/security-rule.subscriber.js +5 -3
- package/dist/subscribers/security-rule.subscriber.js.map +1 -1
- package/package.json +1 -1
- package/src/commands/migrate-removed-fields.command.ts +81 -0
- package/src/controllers/datasource-introspection.controller.ts +27 -1
- package/src/controllers/service.controller.ts +3 -2
- package/src/dtos/datasource-introspection-mapping.dto.ts +15 -0
- package/src/entities/{legacy-common-with-id.entity.ts → legacy-common-with-generated-id.entity.ts} +1 -1
- package/src/helpers/command.service.ts +10 -2
- package/src/helpers/environment.helper.ts +11 -0
- package/src/helpers/field-crud-managers/IntFieldCrudManager.ts +4 -1
- package/src/helpers/model-metadata-helper.service.ts +8 -3
- package/src/helpers/nodemon-heartbeat.ts +59 -0
- package/src/helpers/solid-registry.ts +7 -1
- package/src/helpers/typeorm-db-helper.ts +15 -0
- package/src/index.ts +3 -2
- package/src/interfaces/datasource-introspection-provider.interface.ts +1 -0
- package/src/interfaces.ts +1 -0
- package/src/repository/scheduled-job.repository.ts +83 -4
- package/src/repository/security-rule.repository.ts +10 -4
- package/src/seeders/module-metadata-seeder.service.ts +1415 -264
- package/src/seeders/seed-data/solid-core-metadata.json +128 -34
- package/src/services/action-metadata.service.ts +87 -2
- package/src/services/api-key.service.ts +36 -36
- package/src/services/authentication.service.ts +46 -12
- package/src/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.ts +11 -5
- package/src/services/computed-fields/entity/concat-entity-computed-field-provider.service.ts +15 -1
- package/src/services/crud-helper.service.ts +25 -12
- package/src/services/crud.service.ts +36 -11
- package/src/services/datasource-introspection/mssql-datasource-introspection-provider.service.ts +12 -0
- package/src/services/datasource-introspection/mysql-datasource-introspection-provider.service.ts +2 -0
- package/src/services/datasource-introspection/postgres-datasource-introspection-provider.service.ts +28 -15
- package/src/services/datasource-introspection.service.ts +811 -161
- package/src/services/import-transaction.service.ts +5 -0
- package/src/services/locale.service.ts +111 -3
- package/src/services/mediaStorageProviders/file-s3-storage-provider.ts +2 -2
- package/src/services/menu-item-metadata.service.ts +2 -1
- package/src/services/model-metadata.service.ts +109 -1
- package/src/services/module-metadata.service.ts +36 -0
- package/src/services/removed-field-migration.service.ts +334 -0
- package/src/services/role-metadata.service.ts +112 -49
- package/src/services/settings/default-settings-provider.service.ts +120 -0
- package/src/services/solid-ts-morph.service.ts +61 -1
- package/src/services/view-metadata.service.ts +83 -9
- package/src/solid-core.module.ts +4 -0
- package/src/subscribers/audit.subscriber.ts +101 -18
- package/src/subscribers/computed-entity-field.subscriber.ts +81 -28
- package/src/subscribers/created-by-updated-by.subscriber.ts +3 -0
- package/src/subscribers/field-metadata.subscriber.ts +3 -0
- package/src/subscribers/scheduled-job.subscriber.ts +3 -2
- package/src/subscribers/security-rule.subscriber.ts +8 -3
- package/dist/entities/legacy-common-with-id.entity.d.ts.map +0 -1
- package/dist/entities/legacy-common-with-id.entity.js.map +0 -1
- package/dist/entities/legacy-common.entity.d.ts.map +0 -1
- package/dist/entities/legacy-common.entity.js.map +0 -1
- /package/src/entities/{legacy-common.entity.ts → legacy-common.entity-with-existing-id.entity.ts} +0 -0
|
@@ -52,6 +52,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
52
52
|
exports.ModuleMetadataSeederService = void 0;
|
|
53
53
|
const common_1 = require("@nestjs/common");
|
|
54
54
|
const fs = __importStar(require("fs"));
|
|
55
|
+
const os = __importStar(require("os"));
|
|
55
56
|
const path = __importStar(require("path"));
|
|
56
57
|
const security_rule_repository_1 = require("../repository/security-rule.repository");
|
|
57
58
|
const authentication_service_1 = require("../services/authentication.service");
|
|
@@ -64,6 +65,7 @@ const typeorm_1 = require("typeorm");
|
|
|
64
65
|
const module_helper_1 = require("../helpers/module.helper");
|
|
65
66
|
const solid_registry_1 = require("../helpers/solid-registry");
|
|
66
67
|
const action_metadata_service_1 = require("../services/action-metadata.service");
|
|
68
|
+
const api_key_service_1 = require("../services/api-key.service");
|
|
67
69
|
const field_metadata_service_1 = require("../services/field-metadata.service");
|
|
68
70
|
const media_storage_provider_metadata_service_1 = require("../services/media-storage-provider-metadata.service");
|
|
69
71
|
const model_metadata_service_1 = require("../services/model-metadata.service");
|
|
@@ -76,6 +78,7 @@ const action_metadata_entity_1 = require("../entities/action-metadata.entity");
|
|
|
76
78
|
const menu_item_metadata_entity_1 = require("../entities/menu-item-metadata.entity");
|
|
77
79
|
const module_metadata_entity_1 = require("../entities/module-metadata.entity");
|
|
78
80
|
const role_metadata_entity_1 = require("../entities/role-metadata.entity");
|
|
81
|
+
const user_entity_1 = require("../entities/user.entity");
|
|
79
82
|
const create_menu_item_metadata_dto_1 = require("../dtos/create-menu-item-metadata.dto");
|
|
80
83
|
const create_user_dto_1 = require("../dtos/create-user.dto");
|
|
81
84
|
const create_role_metadata_dto_1 = require("../dtos/create-role-metadata.dto");
|
|
@@ -83,7 +86,9 @@ const permission_metadata_repository_1 = require("../repository/permission-metad
|
|
|
83
86
|
const saved_filters_repository_1 = require("../repository/saved-filters.repository");
|
|
84
87
|
const scheduled_job_repository_1 = require("../repository/scheduled-job.repository");
|
|
85
88
|
const setting_repository_1 = require("../repository/setting.repository");
|
|
89
|
+
const user_api_key_repository_1 = require("../repository/user-api-key.repository");
|
|
86
90
|
const model_sequence_repository_1 = require("../repository/model-sequence.repository");
|
|
91
|
+
const locale_repository_1 = require("../repository/locale.repository");
|
|
87
92
|
const model_sequence_entity_1 = require("../entities/model-sequence.entity");
|
|
88
93
|
const saved_filters_entity_1 = require("../entities/saved-filters.entity");
|
|
89
94
|
const scheduled_job_entity_1 = require("../entities/scheduled-job.entity");
|
|
@@ -94,7 +99,7 @@ const model_metadata_entity_1 = require("../entities/model-metadata.entity");
|
|
|
94
99
|
const permission_metadata_entity_1 = require("../entities/permission-metadata.entity");
|
|
95
100
|
const view_metadata_entity_1 = require("../entities/view-metadata.entity");
|
|
96
101
|
let ModuleMetadataSeederService = ModuleMetadataSeederService_1 = class ModuleMetadataSeederService {
|
|
97
|
-
constructor(moduleMetadataService, modelMetadataService, fieldMetadataService, mediaStorageProviderMetadataService, roleService, userService, authenticationService, solidActionService, solidViewService, emailTemplateService, smsTemplateService, listOfValuesService, permissionRepo, solidRegistry, settingService, settingsRepo, securityRuleRepo, systemFieldsSeederService, scheduledJobRepository, savedFiltersRepo, dataSource, modelSequenceRepo) {
|
|
102
|
+
constructor(moduleMetadataService, modelMetadataService, fieldMetadataService, mediaStorageProviderMetadataService, roleService, userService, authenticationService, apiKeyService, solidActionService, solidViewService, emailTemplateService, smsTemplateService, listOfValuesService, userApiKeyRepository, permissionRepo, solidRegistry, settingService, settingsRepo, securityRuleRepo, systemFieldsSeederService, scheduledJobRepository, savedFiltersRepo, dataSource, modelSequenceRepo, localeRepo) {
|
|
98
103
|
this.moduleMetadataService = moduleMetadataService;
|
|
99
104
|
this.modelMetadataService = modelMetadataService;
|
|
100
105
|
this.fieldMetadataService = fieldMetadataService;
|
|
@@ -102,11 +107,13 @@ let ModuleMetadataSeederService = ModuleMetadataSeederService_1 = class ModuleMe
|
|
|
102
107
|
this.roleService = roleService;
|
|
103
108
|
this.userService = userService;
|
|
104
109
|
this.authenticationService = authenticationService;
|
|
110
|
+
this.apiKeyService = apiKeyService;
|
|
105
111
|
this.solidActionService = solidActionService;
|
|
106
112
|
this.solidViewService = solidViewService;
|
|
107
113
|
this.emailTemplateService = emailTemplateService;
|
|
108
114
|
this.smsTemplateService = smsTemplateService;
|
|
109
115
|
this.listOfValuesService = listOfValuesService;
|
|
116
|
+
this.userApiKeyRepository = userApiKeyRepository;
|
|
110
117
|
this.permissionRepo = permissionRepo;
|
|
111
118
|
this.solidRegistry = solidRegistry;
|
|
112
119
|
this.settingService = settingService;
|
|
@@ -117,7 +124,16 @@ let ModuleMetadataSeederService = ModuleMetadataSeederService_1 = class ModuleMe
|
|
|
117
124
|
this.savedFiltersRepo = savedFiltersRepo;
|
|
118
125
|
this.dataSource = dataSource;
|
|
119
126
|
this.modelSequenceRepo = modelSequenceRepo;
|
|
127
|
+
this.localeRepo = localeRepo;
|
|
120
128
|
this.logger = new common_1.Logger(ModuleMetadataSeederService_1.name);
|
|
129
|
+
this.seedTimingTag = 'SEED_TIMING';
|
|
130
|
+
this.permissionSeedBatchSize = 500;
|
|
131
|
+
this.viewComparableFields = ['name', 'displayName', 'type', 'context', 'layout', 'module', 'model'];
|
|
132
|
+
this.actionComparableFields = ['name', 'displayName', 'type', 'domain', 'context', 'customComponent', 'customIsModal', 'serverEndpoint', 'module', 'model', 'view'];
|
|
133
|
+
this.moduleLookupCache = new Map();
|
|
134
|
+
this.modelLookupCache = new Map();
|
|
135
|
+
this.viewLookupCache = new Map();
|
|
136
|
+
this.mediaStorageProviderLookupCache = new Map();
|
|
121
137
|
this.enablePruning = false;
|
|
122
138
|
}
|
|
123
139
|
async seed(conf) {
|
|
@@ -127,105 +143,114 @@ let ModuleMetadataSeederService = ModuleMetadataSeederService_1 = class ModuleMe
|
|
|
127
143
|
const shouldSeedGlobalMetadata = conf?.seedGlobalMetadata !== false;
|
|
128
144
|
try {
|
|
129
145
|
this.enablePruning = Boolean(conf?.pruneMetadata);
|
|
146
|
+
this.resetLookupCaches();
|
|
130
147
|
console.log(this.enablePruning ? '▶ Pruning enabled: metadata not present in JSON will be removed.' : '▶ Pruning disabled: existing metadata will be kept.');
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
else {
|
|
136
|
-
this.logger.log(`Skipping global metadata seeding.`);
|
|
137
|
-
}
|
|
138
|
-
const seedDataFiles = this.seedDataFiles;
|
|
139
|
-
this.logger.debug(`Found seed data for modules: ${seedDataFiles.map(s => s.moduleMetadata?.name)}`);
|
|
140
|
-
currentStep = 'resolveModulesToSeed';
|
|
141
|
-
if (conf && Array.isArray(conf.modulesToSeed)) {
|
|
142
|
-
modulesToSeed = conf.modulesToSeed;
|
|
143
|
-
console.log(`▶ Selective seeding enabled. Modules to seed: ${modulesToSeed.join(', ')}`);
|
|
144
|
-
this.logger.log(`Selective seeding enabled. Modules to seed: ${modulesToSeed.join(', ')}`);
|
|
145
|
-
}
|
|
146
|
-
else {
|
|
147
|
-
console.log(`▶ No modulesToSeed provided. Seeding ALL modules.`);
|
|
148
|
-
this.logger.log(`No modulesToSeed provided. Seeding ALL modules.`);
|
|
149
|
-
}
|
|
150
|
-
const filteredSeedDataFiles = modulesToSeed ? seedDataFiles.filter((file) => modulesToSeed.includes(file.moduleMetadata?.name)) : seedDataFiles;
|
|
151
|
-
if (filteredSeedDataFiles.length === 0) {
|
|
152
|
-
this.logger.warn(`No modules matched the provided modulesToSeed list.`);
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
for (let i = 0; i < filteredSeedDataFiles.length; i++) {
|
|
156
|
-
const overallMetadata = filteredSeedDataFiles[i];
|
|
157
|
-
const moduleMetadata = overallMetadata.moduleMetadata;
|
|
158
|
-
currentModule = moduleMetadata?.name ?? 'unknown';
|
|
159
|
-
if (!moduleMetadata?.name) {
|
|
160
|
-
this.logger.warn(`Skipping seed metadata file because moduleMetadata.name is missing.`);
|
|
161
|
-
continue;
|
|
148
|
+
await this.timeOperation('seed-run', async () => {
|
|
149
|
+
if (shouldSeedGlobalMetadata) {
|
|
150
|
+
currentStep = 'seedGlobalMetadata';
|
|
151
|
+
await this.timeOperation('global-seed', () => this.seedGlobalMetadata(), { moduleName: 'global', component: 'global-metadata' });
|
|
162
152
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
153
|
+
else {
|
|
154
|
+
this.logger.log(`Skipping global metadata seeding.`);
|
|
155
|
+
}
|
|
156
|
+
const seedDataFiles = this.seedDataFiles;
|
|
157
|
+
this.logger.debug(`Found seed data for modules: ${seedDataFiles.map(s => s.moduleMetadata?.name)}`);
|
|
158
|
+
currentStep = 'resolveModulesToSeed';
|
|
159
|
+
if (conf && Array.isArray(conf.modulesToSeed)) {
|
|
160
|
+
modulesToSeed = conf.modulesToSeed;
|
|
161
|
+
console.log(`▶ Selective seeding enabled. Modules to seed: ${modulesToSeed.join(', ')}`);
|
|
162
|
+
this.logger.log(`Selective seeding enabled. Modules to seed: ${modulesToSeed.join(', ')}`);
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
console.log(`▶ No modulesToSeed provided. Seeding ALL modules.`);
|
|
166
|
+
this.logger.log(`No modulesToSeed provided. Seeding ALL modules.`);
|
|
167
|
+
}
|
|
168
|
+
const filteredSeedDataFiles = modulesToSeed ? seedDataFiles.filter((file) => modulesToSeed.includes(file.moduleMetadata?.name)) : seedDataFiles;
|
|
169
|
+
if (filteredSeedDataFiles.length === 0) {
|
|
170
|
+
this.logger.warn(`No modules matched the provided modulesToSeed list.`);
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
for (let i = 0; i < filteredSeedDataFiles.length; i++) {
|
|
174
|
+
const overallMetadata = filteredSeedDataFiles[i];
|
|
175
|
+
const moduleMetadata = overallMetadata.moduleMetadata;
|
|
176
|
+
currentModule = moduleMetadata?.name ?? 'unknown';
|
|
177
|
+
if (!moduleMetadata?.name) {
|
|
178
|
+
this.logger.warn(`Skipping seed metadata file because moduleMetadata.name is missing.`);
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
console.log(`▶ Seeding Metadata for Module: ${moduleMetadata.name}`);
|
|
182
|
+
this.logger.log(`Seeding Metadata for Module: ${moduleMetadata.name}`);
|
|
183
|
+
await this.timeOperation('module-total', async () => {
|
|
184
|
+
currentStep = 'seedMediaStorageProviders';
|
|
185
|
+
this.logger.log(`Seeding Media Storage Providers`);
|
|
186
|
+
const mediaStorageCounts = await this.timeOperation('seed-media-storage-providers', () => this.seedMediaStorageProviders(overallMetadata.mediaStorageProviders), { moduleName: moduleMetadata.name, component: 'media-storage-providers' });
|
|
187
|
+
console.log(`${this.formatSeedResult(moduleMetadata.name, 'Media Storage Providers', mediaStorageCounts)}`);
|
|
188
|
+
currentStep = 'seedModuleModelFields';
|
|
189
|
+
this.logger.log(`Seeding Module / Model / Fields`);
|
|
190
|
+
const moduleModelFieldCounts = await this.timeOperation('seed-module-model-fields', () => this.seedModuleModelFields(moduleMetadata), { moduleName: moduleMetadata.name, component: 'module-model-fields' });
|
|
191
|
+
console.log(`${this.formatSeedResult(moduleMetadata.name, 'Module/Model/Fields', moduleModelFieldCounts)}`);
|
|
192
|
+
currentStep = 'seedLocales';
|
|
193
|
+
this.logger.log(`Seeding Locales`);
|
|
194
|
+
const localeCounts = await this.seedLocales(overallMetadata);
|
|
195
|
+
console.log(`${this.formatSeedResult(moduleMetadata.name, 'Locales', localeCounts)}`);
|
|
196
|
+
currentStep = 'seedPermissions';
|
|
197
|
+
this.logger.log(`Seeding Permissions`);
|
|
198
|
+
const permissionCounts = await this.timeOperation('seed-permissions', () => this.seedPermissions(overallMetadata), { moduleName: moduleMetadata.name, component: 'permissions' });
|
|
199
|
+
console.log(`${this.formatSeedResult(moduleMetadata.name, 'Permissions', permissionCounts)}`);
|
|
200
|
+
currentStep = 'seedRoles';
|
|
201
|
+
this.logger.log(`Seeding Roles`);
|
|
202
|
+
const roleCounts = await this.timeOperation('seed-roles', () => this.seedRoles(overallMetadata), { moduleName: moduleMetadata.name, component: 'roles' });
|
|
203
|
+
console.log(`${this.formatSeedResult(moduleMetadata.name, 'Roles', roleCounts)}`);
|
|
204
|
+
currentStep = 'seedUsers';
|
|
205
|
+
this.logger.log(`Seeding Users`);
|
|
206
|
+
const userCounts = await this.timeOperation('seed-users', () => this.seedUsers(overallMetadata), { moduleName: moduleMetadata.name, component: 'users' });
|
|
207
|
+
console.log(`${this.formatSeedResult(moduleMetadata.name, 'Users', userCounts)}`);
|
|
208
|
+
currentStep = 'seedViews';
|
|
209
|
+
this.logger.log(`Seeding Views`);
|
|
210
|
+
const viewCounts = await this.timeOperation('seed-views', () => this.seedViews(overallMetadata), { moduleName: moduleMetadata.name, component: 'views' });
|
|
211
|
+
console.log(`${this.formatSeedResult(moduleMetadata.name, 'Views', viewCounts)}`);
|
|
212
|
+
currentStep = 'seedActions';
|
|
213
|
+
this.logger.log(`Seeding Actions`);
|
|
214
|
+
const actionCounts = await this.timeOperation('seed-actions', () => this.seedActions(overallMetadata), { moduleName: moduleMetadata.name, component: 'actions' });
|
|
215
|
+
console.log(`${this.formatSeedResult(moduleMetadata.name, 'Actions', actionCounts)}`);
|
|
216
|
+
currentStep = 'seedMenus';
|
|
217
|
+
this.logger.log(`Seeding Menus`);
|
|
218
|
+
const menuCounts = await this.timeOperation('seed-menus', () => this.seedMenus(overallMetadata), { moduleName: moduleMetadata.name, component: 'menus' });
|
|
219
|
+
console.log(`${this.formatSeedResult(moduleMetadata.name, 'Menus', menuCounts)}`);
|
|
220
|
+
currentStep = 'seedEmailTemplates';
|
|
221
|
+
this.logger.log(`Seeding Email Templates`);
|
|
222
|
+
const emailTemplateCounts = await this.timeOperation('seed-email-templates', () => this.seedEmailTemplates(overallMetadata, moduleMetadata.name), { moduleName: moduleMetadata.name, component: 'email-templates' });
|
|
223
|
+
console.log(`${this.formatSeedResult(moduleMetadata.name, 'Email Templates', emailTemplateCounts)}`);
|
|
224
|
+
currentStep = 'seedSmsTemplates';
|
|
225
|
+
this.logger.log(`Seeding Sms Templates`);
|
|
226
|
+
const smsTemplateCounts = await this.timeOperation('seed-sms-templates', () => this.seedSmsTemplates(overallMetadata, moduleMetadata.name), { moduleName: moduleMetadata.name, component: 'sms-templates' });
|
|
227
|
+
console.log(`${this.formatSeedResult(moduleMetadata.name, 'Sms Templates', smsTemplateCounts)}`);
|
|
228
|
+
currentStep = 'seedSecurityRules';
|
|
229
|
+
this.logger.log(`Seeding Security Rules`);
|
|
230
|
+
const securityRuleCounts = await this.timeOperation('seed-security-rules', () => this.seedSecurityRules(overallMetadata), { moduleName: moduleMetadata.name, component: 'security-rules' });
|
|
231
|
+
console.log(`${this.formatSeedResult(moduleMetadata.name, 'Security Rules', securityRuleCounts)}`);
|
|
232
|
+
currentStep = 'seedListOfValues';
|
|
233
|
+
this.logger.log(`Seeding List Of Values`);
|
|
234
|
+
const lovCounts = await this.timeOperation('seed-list-of-values', () => this.seedListOfValues(moduleMetadata, overallMetadata), { moduleName: moduleMetadata.name, component: 'list-of-values' });
|
|
235
|
+
console.log(`${this.formatSeedResult(moduleMetadata.name, 'List Of Values', lovCounts)}`);
|
|
236
|
+
currentStep = 'seedScheduledJobs';
|
|
237
|
+
this.logger.log(`Seeding Scheduled Jobs`);
|
|
238
|
+
const scheduledJobCounts = await this.timeOperation('seed-scheduled-jobs', () => this.seedScheduledJobs(moduleMetadata, overallMetadata), { moduleName: moduleMetadata.name, component: 'scheduled-jobs' });
|
|
239
|
+
console.log(`${this.formatSeedResult(moduleMetadata.name, 'Scheduled Jobs', scheduledJobCounts)}`);
|
|
240
|
+
currentStep = 'seedSavedFilters';
|
|
241
|
+
this.logger.log(`Seeding Saved Filters`);
|
|
242
|
+
const savedFilterCounts = await this.timeOperation('seed-saved-filters', () => this.seedSavedFilters(moduleMetadata, overallMetadata), { moduleName: moduleMetadata.name, component: 'saved-filters' });
|
|
243
|
+
console.log(`${this.formatSeedResult(moduleMetadata.name, 'Saved Filters', savedFilterCounts)}`);
|
|
244
|
+
currentStep = 'seedModelSequences';
|
|
245
|
+
this.logger.log(`Seeding Model Sequences`);
|
|
246
|
+
const modelSequenceCounts = await this.timeOperation('seed-model-sequences', () => this.seedModelSequences(overallMetadata), { moduleName: moduleMetadata.name, component: 'model-sequences' });
|
|
247
|
+
console.log(`${this.formatSeedResult(moduleMetadata.name, 'Model Sequences', modelSequenceCounts)}`);
|
|
248
|
+
}, { moduleName: moduleMetadata.name, component: 'module-seed' });
|
|
249
|
+
}
|
|
250
|
+
currentModule = 'global';
|
|
251
|
+
currentStep = 'setupDefaultRolesWithPermissions';
|
|
252
|
+
await this.timeOperation('setup-default-roles-with-permissions', () => this.setupDefaultRolesWithPermissions(), { moduleName: 'global', component: 'default-roles' });
|
|
253
|
+
}, { moduleName: 'global', component: 'seed-run' });
|
|
229
254
|
console.log(`✔ Seeding completed.`);
|
|
230
255
|
}
|
|
231
256
|
catch (error) {
|
|
@@ -238,117 +263,303 @@ let ModuleMetadataSeederService = ModuleMetadataSeederService_1 = class ModuleMe
|
|
|
238
263
|
throw error;
|
|
239
264
|
}
|
|
240
265
|
}
|
|
266
|
+
buildTimingPrefix(itemTag, options) {
|
|
267
|
+
const parts = [`[${this.seedTimingTag}]`, `[ITEM:${itemTag}]`];
|
|
268
|
+
if (options?.moduleName) {
|
|
269
|
+
parts.push(`[MODULE:${options.moduleName}]`);
|
|
270
|
+
}
|
|
271
|
+
if (options?.component) {
|
|
272
|
+
parts.push(`[COMPONENT:${options.component}]`);
|
|
273
|
+
}
|
|
274
|
+
if (options?.serviceCall) {
|
|
275
|
+
parts.push(`[CALL:${options.serviceCall}]`);
|
|
276
|
+
}
|
|
277
|
+
return parts.join(' ');
|
|
278
|
+
}
|
|
279
|
+
formatDuration(durationMs) {
|
|
280
|
+
return durationMs >= 1000
|
|
281
|
+
? `${(durationMs / 1000).toFixed(2)} s (${durationMs.toFixed(2)} ms)`
|
|
282
|
+
: `${durationMs.toFixed(2)} ms`;
|
|
283
|
+
}
|
|
284
|
+
resetLookupCaches() {
|
|
285
|
+
this.moduleLookupCache.clear();
|
|
286
|
+
this.modelLookupCache.clear();
|
|
287
|
+
this.viewLookupCache.clear();
|
|
288
|
+
this.mediaStorageProviderLookupCache.clear();
|
|
289
|
+
}
|
|
290
|
+
async getModuleByUserKeyCached(moduleUserKey, options) {
|
|
291
|
+
if (!moduleUserKey) {
|
|
292
|
+
return null;
|
|
293
|
+
}
|
|
294
|
+
if (this.moduleLookupCache.has(moduleUserKey)) {
|
|
295
|
+
return this.moduleLookupCache.get(moduleUserKey) ?? null;
|
|
296
|
+
}
|
|
297
|
+
const module = await this.timeOperation('module-find-by-user-key-cache-miss', () => this.moduleMetadataService.findOneByUserKey(moduleUserKey), {
|
|
298
|
+
moduleName: options?.moduleName ?? moduleUserKey,
|
|
299
|
+
component: options?.component,
|
|
300
|
+
serviceCall: 'moduleMetadataService.findOneByUserKey',
|
|
301
|
+
details: options?.details ?? `module=${moduleUserKey}`,
|
|
302
|
+
});
|
|
303
|
+
this.moduleLookupCache.set(moduleUserKey, module ?? null);
|
|
304
|
+
return module ?? null;
|
|
305
|
+
}
|
|
306
|
+
async getModelByUserKeyCached(modelUserKey, options) {
|
|
307
|
+
if (!modelUserKey) {
|
|
308
|
+
return null;
|
|
309
|
+
}
|
|
310
|
+
if (this.modelLookupCache.has(modelUserKey)) {
|
|
311
|
+
return this.modelLookupCache.get(modelUserKey) ?? null;
|
|
312
|
+
}
|
|
313
|
+
const model = await this.timeOperation('model-find-by-user-key-cache-miss', () => this.modelMetadataService.findOneByUserKey(modelUserKey), {
|
|
314
|
+
moduleName: options?.moduleName,
|
|
315
|
+
component: options?.component,
|
|
316
|
+
serviceCall: 'modelMetadataService.findOneByUserKey',
|
|
317
|
+
details: options?.details ?? `model=${modelUserKey}`,
|
|
318
|
+
});
|
|
319
|
+
this.modelLookupCache.set(modelUserKey, model ?? null);
|
|
320
|
+
return model ?? null;
|
|
321
|
+
}
|
|
322
|
+
async getViewByUserKeyCached(viewUserKey, options) {
|
|
323
|
+
if (!viewUserKey) {
|
|
324
|
+
return null;
|
|
325
|
+
}
|
|
326
|
+
if (this.viewLookupCache.has(viewUserKey)) {
|
|
327
|
+
return this.viewLookupCache.get(viewUserKey) ?? null;
|
|
328
|
+
}
|
|
329
|
+
const view = await this.timeOperation('view-find-by-user-key-cache-miss', () => this.solidViewService.findOneByUserKey(viewUserKey), {
|
|
330
|
+
moduleName: options?.moduleName,
|
|
331
|
+
component: options?.component,
|
|
332
|
+
serviceCall: 'solidViewService.findOneByUserKey',
|
|
333
|
+
details: options?.details ?? `view=${viewUserKey}`,
|
|
334
|
+
});
|
|
335
|
+
this.viewLookupCache.set(viewUserKey, view ?? null);
|
|
336
|
+
return view ?? null;
|
|
337
|
+
}
|
|
338
|
+
async getMediaStorageProviderByUserKeyCached(mediaStorageProviderUserKey, options) {
|
|
339
|
+
if (!mediaStorageProviderUserKey) {
|
|
340
|
+
return null;
|
|
341
|
+
}
|
|
342
|
+
if (this.mediaStorageProviderLookupCache.has(mediaStorageProviderUserKey)) {
|
|
343
|
+
return this.mediaStorageProviderLookupCache.get(mediaStorageProviderUserKey) ?? null;
|
|
344
|
+
}
|
|
345
|
+
const mediaStorageProvider = await this.timeOperation('media-storage-provider-find-by-user-key-cache-miss', () => this.mediaStorageProviderMetadataService.findOneByUserKey(mediaStorageProviderUserKey), {
|
|
346
|
+
moduleName: options?.moduleName,
|
|
347
|
+
component: options?.component,
|
|
348
|
+
serviceCall: 'mediaStorageProviderMetadataService.findOneByUserKey',
|
|
349
|
+
details: options?.details ?? `provider=${mediaStorageProviderUserKey}`,
|
|
350
|
+
});
|
|
351
|
+
this.mediaStorageProviderLookupCache.set(mediaStorageProviderUserKey, mediaStorageProvider ?? null);
|
|
352
|
+
return mediaStorageProvider ?? null;
|
|
353
|
+
}
|
|
354
|
+
async timeOperation(itemTag, operation, options) {
|
|
355
|
+
const prefix = this.buildTimingPrefix(itemTag, options);
|
|
356
|
+
const detailSuffix = options?.details ? ` ${options.details}` : '';
|
|
357
|
+
const start = process.hrtime.bigint();
|
|
358
|
+
try {
|
|
359
|
+
const result = await operation();
|
|
360
|
+
const durationMs = Number(process.hrtime.bigint() - start) / 1_000_000;
|
|
361
|
+
this.logger.debug(`${prefix} done in ${this.formatDuration(durationMs)}${detailSuffix}`);
|
|
362
|
+
return result;
|
|
363
|
+
}
|
|
364
|
+
catch (error) {
|
|
365
|
+
const durationMs = Number(process.hrtime.bigint() - start) / 1_000_000;
|
|
366
|
+
this.logger.debug(`${prefix} failed after ${this.formatDuration(durationMs)}${detailSuffix}`);
|
|
367
|
+
throw error;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
241
370
|
async seedScheduledJobs(moduleMetadata, overallMetadata) {
|
|
242
|
-
this.logger.debug(`[Start] Processing scheduled jobs for ${moduleMetadata.name}`);
|
|
243
371
|
const scheduledJobs = this.getSeedArray(overallMetadata?.scheduledJobs);
|
|
244
|
-
const pruned = this.enablePruning ? await this.pruneScheduledJobs(scheduledJobs, moduleMetadata.name)
|
|
372
|
+
const pruned = this.enablePruning ? await this.timeOperation('prune-scheduled-jobs', () => this.pruneScheduledJobs(scheduledJobs, moduleMetadata.name), {
|
|
373
|
+
moduleName: moduleMetadata.name,
|
|
374
|
+
component: 'scheduled-jobs',
|
|
375
|
+
serviceCall: 'pruneScheduledJobs',
|
|
376
|
+
}) : 0;
|
|
245
377
|
if (scheduledJobs.length > 0) {
|
|
246
|
-
await this.handleSeedScheduledJobs(scheduledJobs)
|
|
378
|
+
await this.timeOperation('handle-scheduled-jobs', () => this.handleSeedScheduledJobs(scheduledJobs), {
|
|
379
|
+
moduleName: moduleMetadata.name,
|
|
380
|
+
component: 'scheduled-jobs',
|
|
381
|
+
serviceCall: 'handleSeedScheduledJobs',
|
|
382
|
+
});
|
|
247
383
|
}
|
|
248
|
-
this.logger.debug(`[End] Processing scheduled jobs for ${moduleMetadata.name}`);
|
|
249
384
|
return { pruned, upserted: scheduledJobs.length };
|
|
250
385
|
}
|
|
251
386
|
async seedSavedFilters(moduleMetadata, overallMetadata) {
|
|
252
|
-
this.logger.debug(`[Start] Processing saved filters for ${moduleMetadata.name}`);
|
|
253
387
|
const savedFilters = this.getSeedArray(overallMetadata?.savedFilters);
|
|
254
|
-
const pruned = this.enablePruning ? await this.pruneSavedFilters(savedFilters, moduleMetadata.name)
|
|
388
|
+
const pruned = this.enablePruning ? await this.timeOperation('prune-saved-filters', () => this.pruneSavedFilters(savedFilters, moduleMetadata.name), {
|
|
389
|
+
moduleName: moduleMetadata.name,
|
|
390
|
+
component: 'saved-filters',
|
|
391
|
+
serviceCall: 'pruneSavedFilters',
|
|
392
|
+
}) : 0;
|
|
255
393
|
if (savedFilters.length > 0) {
|
|
256
|
-
await this.handleSeedSavedFilters(savedFilters)
|
|
394
|
+
await this.timeOperation('handle-saved-filters', () => this.handleSeedSavedFilters(savedFilters), {
|
|
395
|
+
moduleName: moduleMetadata.name,
|
|
396
|
+
component: 'saved-filters',
|
|
397
|
+
serviceCall: 'handleSeedSavedFilters',
|
|
398
|
+
});
|
|
257
399
|
}
|
|
258
|
-
this.logger.debug(`[End] Processing saved filters for ${moduleMetadata.name}`);
|
|
259
400
|
return { pruned, upserted: savedFilters.length };
|
|
260
401
|
}
|
|
261
402
|
async seedListOfValues(moduleMetadata, overallMetadata) {
|
|
262
|
-
this.logger.debug(`[Start] Processing List Of Values for ${moduleMetadata.name}`);
|
|
263
403
|
const listOfValues = this.getSeedArray(overallMetadata?.listOfValues);
|
|
264
|
-
const pruned = this.enablePruning ? await this.pruneListOfValues(listOfValues, moduleMetadata.name)
|
|
265
|
-
|
|
266
|
-
|
|
404
|
+
const pruned = this.enablePruning ? await this.timeOperation('prune-list-of-values', () => this.pruneListOfValues(listOfValues, moduleMetadata.name), {
|
|
405
|
+
moduleName: moduleMetadata.name,
|
|
406
|
+
component: 'list-of-values',
|
|
407
|
+
serviceCall: 'pruneListOfValues',
|
|
408
|
+
}) : 0;
|
|
409
|
+
await this.timeOperation('handle-list-of-values', () => this.handleSeedListOfValues(listOfValues), {
|
|
410
|
+
moduleName: moduleMetadata.name,
|
|
411
|
+
component: 'list-of-values',
|
|
412
|
+
serviceCall: 'handleSeedListOfValues',
|
|
413
|
+
});
|
|
267
414
|
return { pruned, upserted: listOfValues.length };
|
|
268
415
|
}
|
|
416
|
+
async seedLocales(overallMetadata) {
|
|
417
|
+
this.logger.debug(`[Start] Processing locales`);
|
|
418
|
+
const locales = this.getSeedArray(overallMetadata?.locales);
|
|
419
|
+
const existingLocales = await this.localeRepo.find();
|
|
420
|
+
if (existingLocales.length > 0) {
|
|
421
|
+
this.solidRegistry.registerlocales(existingLocales);
|
|
422
|
+
this.logger.debug(`[End] Skipping locale seed because locales already exist`);
|
|
423
|
+
return { pruned: 0, upserted: 0 };
|
|
424
|
+
}
|
|
425
|
+
await this.handleSeedLocales(locales);
|
|
426
|
+
this.logger.debug(`[End] Processing locales`);
|
|
427
|
+
return { pruned: 0, upserted: locales.length };
|
|
428
|
+
}
|
|
269
429
|
async setupDefaultRolesWithPermissions() {
|
|
270
430
|
this.logger.debug(`About to add all permissions to the Admin role`);
|
|
271
|
-
await this.roleService.addAllPermissionsToRole(create_role_metadata_dto_1.ADMIN_ROLE_NAME)
|
|
431
|
+
await this.timeOperation('role-add-all-permissions', () => this.roleService.addAllPermissionsToRole(create_role_metadata_dto_1.ADMIN_ROLE_NAME), {
|
|
432
|
+
moduleName: 'global',
|
|
433
|
+
component: 'default-roles',
|
|
434
|
+
serviceCall: 'roleService.addAllPermissionsToRole',
|
|
435
|
+
details: `role=${create_role_metadata_dto_1.ADMIN_ROLE_NAME}`,
|
|
436
|
+
});
|
|
272
437
|
}
|
|
273
438
|
async seedSecurityRules(overallMetadata) {
|
|
274
|
-
this.logger.debug(`[Start] Processing security rules`);
|
|
275
439
|
const securityRules = this.getSeedArray(overallMetadata?.securityRules);
|
|
276
|
-
const pruned = this.enablePruning ? await this.pruneSecurityRules(securityRules, overallMetadata?.moduleMetadata?.name)
|
|
277
|
-
|
|
278
|
-
|
|
440
|
+
const pruned = this.enablePruning ? await this.timeOperation('prune-security-rules', () => this.pruneSecurityRules(securityRules, overallMetadata?.moduleMetadata?.name), {
|
|
441
|
+
moduleName: overallMetadata?.moduleMetadata?.name,
|
|
442
|
+
component: 'security-rules',
|
|
443
|
+
serviceCall: 'pruneSecurityRules',
|
|
444
|
+
}) : 0;
|
|
445
|
+
await this.timeOperation('handle-security-rules', () => this.handleSeedSecurityRules(securityRules), {
|
|
446
|
+
moduleName: overallMetadata?.moduleMetadata?.name,
|
|
447
|
+
component: 'security-rules',
|
|
448
|
+
serviceCall: 'handleSeedSecurityRules',
|
|
449
|
+
});
|
|
279
450
|
return { pruned, upserted: securityRules.length };
|
|
280
451
|
}
|
|
281
452
|
async seedDefaultSettings() {
|
|
282
|
-
this.
|
|
283
|
-
|
|
284
|
-
|
|
453
|
+
await this.timeOperation('seed-default-settings-call', () => this.settingService.seedSystemAdminEditableAndAboveSettings(), {
|
|
454
|
+
moduleName: 'global',
|
|
455
|
+
component: 'settings',
|
|
456
|
+
serviceCall: 'settingService.seedSystemAdminEditableAndAboveSettings',
|
|
457
|
+
});
|
|
285
458
|
}
|
|
286
459
|
async seedSmsTemplates(overallMetadata, moduleName) {
|
|
287
|
-
this.logger.debug(`[Start] Processing sms templates`);
|
|
288
460
|
const smsTemplates = this.getSeedArray(overallMetadata?.smsTemplates);
|
|
289
|
-
await this.handleSeedSmsTemplates(smsTemplates, moduleName)
|
|
290
|
-
|
|
461
|
+
await this.timeOperation('handle-sms-templates', () => this.handleSeedSmsTemplates(smsTemplates, moduleName), {
|
|
462
|
+
moduleName,
|
|
463
|
+
component: 'sms-templates',
|
|
464
|
+
serviceCall: 'handleSeedSmsTemplates',
|
|
465
|
+
});
|
|
291
466
|
return { pruned: 0, upserted: smsTemplates.length };
|
|
292
467
|
}
|
|
293
468
|
async seedEmailTemplates(overallMetadata, moduleName) {
|
|
294
|
-
this.logger.debug(`[Start] Processing email templates`);
|
|
295
469
|
const emailTemplates = this.getSeedArray(overallMetadata?.emailTemplates);
|
|
296
|
-
await this.handleSeedEmailTemplates(emailTemplates, moduleName)
|
|
297
|
-
|
|
470
|
+
await this.timeOperation('handle-email-templates', () => this.handleSeedEmailTemplates(emailTemplates, moduleName), {
|
|
471
|
+
moduleName,
|
|
472
|
+
component: 'email-templates',
|
|
473
|
+
serviceCall: 'handleSeedEmailTemplates',
|
|
474
|
+
});
|
|
298
475
|
return { pruned: 0, upserted: emailTemplates.length };
|
|
299
476
|
}
|
|
300
477
|
async seedMenus(overallMetadata) {
|
|
301
|
-
this.logger.debug(`[Start] Processing menus`);
|
|
302
478
|
const menus = this.getSeedArray(overallMetadata?.menus);
|
|
303
|
-
const pruned = this.enablePruning ? await this.pruneMenus(menus, overallMetadata?.moduleMetadata?.name)
|
|
304
|
-
|
|
305
|
-
|
|
479
|
+
const pruned = this.enablePruning ? await this.timeOperation('prune-menus', () => this.pruneMenus(menus, overallMetadata?.moduleMetadata?.name), {
|
|
480
|
+
moduleName: overallMetadata?.moduleMetadata?.name,
|
|
481
|
+
component: 'menus',
|
|
482
|
+
serviceCall: 'pruneMenus',
|
|
483
|
+
}) : 0;
|
|
484
|
+
await this.timeOperation('handle-menus', () => this.handleSeedMenus(menus), {
|
|
485
|
+
moduleName: overallMetadata?.moduleMetadata?.name,
|
|
486
|
+
component: 'menus',
|
|
487
|
+
serviceCall: 'handleSeedMenus',
|
|
488
|
+
});
|
|
306
489
|
return { pruned, upserted: menus.length };
|
|
307
490
|
}
|
|
308
491
|
async seedActions(overallMetadata) {
|
|
309
|
-
this.logger.debug(`[Start] Processing actions`);
|
|
310
492
|
const actions = this.getSeedArray(overallMetadata?.actions);
|
|
311
|
-
const pruned = this.enablePruning ? await this.pruneActions(actions, overallMetadata?.moduleMetadata?.name)
|
|
312
|
-
|
|
313
|
-
|
|
493
|
+
const pruned = this.enablePruning ? await this.timeOperation('prune-actions', () => this.pruneActions(actions, overallMetadata?.moduleMetadata?.name), {
|
|
494
|
+
moduleName: overallMetadata?.moduleMetadata?.name,
|
|
495
|
+
component: 'actions',
|
|
496
|
+
serviceCall: 'pruneActions',
|
|
497
|
+
}) : 0;
|
|
498
|
+
await this.timeOperation('handle-actions', () => this.handleSeedActions(actions), {
|
|
499
|
+
moduleName: overallMetadata?.moduleMetadata?.name,
|
|
500
|
+
component: 'actions',
|
|
501
|
+
serviceCall: 'handleSeedActions',
|
|
502
|
+
});
|
|
314
503
|
return { pruned, upserted: actions.length };
|
|
315
504
|
}
|
|
316
505
|
async seedViews(overallMetadata) {
|
|
317
|
-
this.logger.debug(`[Start] Processing views`);
|
|
318
506
|
const views = this.getSeedArray(overallMetadata?.views);
|
|
319
|
-
const pruned = this.enablePruning ? await this.pruneViews(views, overallMetadata?.moduleMetadata?.name)
|
|
320
|
-
|
|
321
|
-
|
|
507
|
+
const pruned = this.enablePruning ? await this.timeOperation('prune-views', () => this.pruneViews(views, overallMetadata?.moduleMetadata?.name), {
|
|
508
|
+
moduleName: overallMetadata?.moduleMetadata?.name,
|
|
509
|
+
component: 'views',
|
|
510
|
+
serviceCall: 'pruneViews',
|
|
511
|
+
}) : 0;
|
|
512
|
+
await this.timeOperation('handle-views', () => this.handleSeedViews(views), {
|
|
513
|
+
moduleName: overallMetadata?.moduleMetadata?.name,
|
|
514
|
+
component: 'views',
|
|
515
|
+
serviceCall: 'handleSeedViews',
|
|
516
|
+
});
|
|
322
517
|
return { pruned, upserted: views.length };
|
|
323
518
|
}
|
|
324
519
|
async seedUsers(overallMetadata) {
|
|
325
|
-
this.logger.debug(`[Start] Processing users`);
|
|
326
520
|
const users = this.getSeedArray(overallMetadata?.users);
|
|
327
|
-
await this.handleSeedUsers(users)
|
|
328
|
-
|
|
521
|
+
await this.timeOperation('handle-users', () => this.handleSeedUsers(users), {
|
|
522
|
+
moduleName: overallMetadata?.moduleMetadata?.name,
|
|
523
|
+
component: 'users',
|
|
524
|
+
serviceCall: 'handleSeedUsers',
|
|
525
|
+
});
|
|
329
526
|
return { pruned: 0, upserted: users.length };
|
|
330
527
|
}
|
|
331
528
|
async seedRoles(overallMetadata) {
|
|
332
|
-
this.logger.debug(`[Start] Processing roles`);
|
|
333
529
|
const roles = this.getSeedArray(overallMetadata?.roles);
|
|
334
|
-
await this.roleService.createRolesIfNotExists(roles
|
|
530
|
+
await this.timeOperation('roles-create-if-not-exists', () => this.roleService.createRolesIfNotExists(roles
|
|
335
531
|
.filter((role) => role?.name)
|
|
336
|
-
.map((role) => ({
|
|
532
|
+
.map((role) => ({
|
|
533
|
+
name: role.name,
|
|
534
|
+
moduleId: role.moduleId,
|
|
535
|
+
moduleUserKey: role.moduleUserKey ?? overallMetadata?.moduleMetadata?.name,
|
|
536
|
+
}))), {
|
|
537
|
+
moduleName: overallMetadata?.moduleMetadata?.name,
|
|
538
|
+
component: 'roles',
|
|
539
|
+
serviceCall: 'roleService.createRolesIfNotExists',
|
|
540
|
+
details: `roleCount=${roles.length}`,
|
|
541
|
+
});
|
|
337
542
|
for (const role of roles) {
|
|
338
543
|
if (role.permissions) {
|
|
339
|
-
await this.roleService.addPermissionsToRole(role.name, role.permissions
|
|
544
|
+
await this.timeOperation('role-add-permissions', () => this.roleService.addPermissionsToRole(role.name, role.permissions
|
|
340
545
|
.map((permission) => typeof permission === 'string' ? permission : permission?.name)
|
|
341
|
-
.filter(Boolean))
|
|
546
|
+
.filter(Boolean)), {
|
|
547
|
+
moduleName: overallMetadata?.moduleMetadata?.name,
|
|
548
|
+
component: 'roles',
|
|
549
|
+
serviceCall: 'roleService.addPermissionsToRole',
|
|
550
|
+
details: `role=${role.name} permissionCount=${role.permissions.length}`,
|
|
551
|
+
});
|
|
342
552
|
}
|
|
343
553
|
}
|
|
344
|
-
this.logger.debug(`[End] Processing roles`);
|
|
345
554
|
return { pruned: 0, upserted: roles.length };
|
|
346
555
|
}
|
|
347
556
|
async seedPermissions(overallMetadata) {
|
|
348
|
-
this.logger.debug(`[Start] Processing permissions`);
|
|
349
557
|
const permissions = overallMetadata.permissions ?? [];
|
|
350
|
-
await this.handleSeedPermissions(permissions)
|
|
351
|
-
|
|
558
|
+
await this.timeOperation('handle-permissions', () => this.handleSeedPermissions(permissions), {
|
|
559
|
+
moduleName: overallMetadata?.moduleMetadata?.name,
|
|
560
|
+
component: 'permissions',
|
|
561
|
+
serviceCall: 'handleSeedPermissions',
|
|
562
|
+
});
|
|
352
563
|
return { pruned: 0, upserted: permissions?.length ?? 0 };
|
|
353
564
|
}
|
|
354
565
|
get seedDataFiles() {
|
|
@@ -367,15 +578,28 @@ let ModuleMetadataSeederService = ModuleMetadataSeederService_1 = class ModuleMe
|
|
|
367
578
|
}
|
|
368
579
|
async seedGlobalMetadata() {
|
|
369
580
|
this.logger.log(`Seeding Permissions`);
|
|
370
|
-
await this.seedControllerPermissions()
|
|
581
|
+
await this.timeOperation('seed-controller-permissions', () => this.seedControllerPermissions(), {
|
|
582
|
+
moduleName: 'global',
|
|
583
|
+
component: 'controller-permissions',
|
|
584
|
+
});
|
|
371
585
|
this.logger.log(`Seeding System Fields Metadata`);
|
|
372
|
-
await this.seedDefaultSystemFields()
|
|
586
|
+
await this.timeOperation('seed-default-system-fields', () => this.seedDefaultSystemFields(), {
|
|
587
|
+
moduleName: 'global',
|
|
588
|
+
component: 'system-fields',
|
|
589
|
+
});
|
|
373
590
|
this.logger.log(`Seeding Default Settings`);
|
|
374
|
-
await this.seedDefaultSettings()
|
|
591
|
+
await this.timeOperation('seed-default-settings', () => this.seedDefaultSettings(), {
|
|
592
|
+
moduleName: 'global',
|
|
593
|
+
component: 'settings',
|
|
594
|
+
});
|
|
375
595
|
this.logger.debug(`Global metadata seeding completed`);
|
|
376
596
|
}
|
|
377
597
|
async seedDefaultSystemFields() {
|
|
378
|
-
await this.systemFieldsSeederService.seed()
|
|
598
|
+
await this.timeOperation('system-fields-seed', () => this.systemFieldsSeederService.seed(), {
|
|
599
|
+
moduleName: 'global',
|
|
600
|
+
component: 'system-fields',
|
|
601
|
+
serviceCall: 'systemFieldsSeederService.seed',
|
|
602
|
+
});
|
|
379
603
|
}
|
|
380
604
|
async seedControllerPermissions() {
|
|
381
605
|
const controllers = this.solidRegistry.getControllers();
|
|
@@ -388,55 +612,112 @@ let ModuleMetadataSeederService = ModuleMetadataSeederService_1 = class ModuleMe
|
|
|
388
612
|
const methodName = methods[mId];
|
|
389
613
|
const permissionName = `${controller.name}.${methodName}`;
|
|
390
614
|
permissionNames.push(permissionName);
|
|
391
|
-
await this.createPermissionIfNotExists(permissionName);
|
|
392
615
|
}
|
|
393
616
|
}
|
|
394
617
|
catch (error) {
|
|
395
618
|
this.logger.error(error);
|
|
396
619
|
}
|
|
397
620
|
}
|
|
621
|
+
await this.timeOperation('seed-controller-permissions-bulk', () => this.seedPermissionsInBatches(permissionNames, {
|
|
622
|
+
moduleName: 'global',
|
|
623
|
+
component: 'controller-permissions',
|
|
624
|
+
}), {
|
|
625
|
+
moduleName: 'global',
|
|
626
|
+
component: 'controller-permissions',
|
|
627
|
+
serviceCall: 'seedPermissionsInBatches',
|
|
628
|
+
details: `permissionCount=${permissionNames.length} batchSize=${this.permissionSeedBatchSize}`,
|
|
629
|
+
});
|
|
398
630
|
if (this.enablePruning) {
|
|
399
|
-
await this.prunePermissions(permissionNames)
|
|
631
|
+
await this.timeOperation('prune-controller-permissions', () => this.prunePermissions(permissionNames), {
|
|
632
|
+
moduleName: 'global',
|
|
633
|
+
component: 'controller-permissions',
|
|
634
|
+
serviceCall: 'prunePermissions',
|
|
635
|
+
});
|
|
400
636
|
}
|
|
401
637
|
}
|
|
402
|
-
async
|
|
403
|
-
const
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
638
|
+
async handleSeedPermissions(permissions) {
|
|
639
|
+
const permissionNames = permissions
|
|
640
|
+
.map((permission) => typeof permission === 'string' ? permission : permission?.name)
|
|
641
|
+
.filter(Boolean);
|
|
642
|
+
await this.seedPermissionsInBatches(permissionNames, {
|
|
643
|
+
component: 'permissions',
|
|
407
644
|
});
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
645
|
+
}
|
|
646
|
+
async seedPermissionsInBatches(permissionNames, options) {
|
|
647
|
+
const uniquePermissionNames = this.getUniquePermissionNames(permissionNames);
|
|
648
|
+
if (uniquePermissionNames.length === 0) {
|
|
649
|
+
return;
|
|
650
|
+
}
|
|
651
|
+
for (let index = 0; index < uniquePermissionNames.length; index += this.permissionSeedBatchSize) {
|
|
652
|
+
const batch = uniquePermissionNames.slice(index, index + this.permissionSeedBatchSize);
|
|
653
|
+
const batchNumber = Math.floor(index / this.permissionSeedBatchSize) + 1;
|
|
654
|
+
const existingPermissions = await this.timeOperation('permission-batch-find', () => this.permissionRepo.find({
|
|
655
|
+
where: {
|
|
656
|
+
name: (0, typeorm_1.In)(batch),
|
|
657
|
+
}
|
|
658
|
+
}), {
|
|
659
|
+
moduleName: options?.moduleName,
|
|
660
|
+
component: options?.component ?? 'permissions',
|
|
661
|
+
serviceCall: 'permissionRepo.find',
|
|
662
|
+
details: `batch=${batchNumber} batchSize=${batch.length}`,
|
|
663
|
+
});
|
|
664
|
+
const existingPermissionNames = new Set(existingPermissions.map((permission) => this.normalizePermissionName(permission.name)));
|
|
665
|
+
const missingPermissionNames = batch.filter((name) => !existingPermissionNames.has(this.normalizePermissionName(name)));
|
|
666
|
+
if (missingPermissionNames.length === 0) {
|
|
667
|
+
continue;
|
|
668
|
+
}
|
|
669
|
+
this.logger.log(`Creating ${missingPermissionNames.length} missing permissions in batch ${batchNumber}.`);
|
|
670
|
+
await this.timeOperation('permission-batch-save', () => this.permissionRepo.save(missingPermissionNames.map((name) => this.permissionRepo.create({ name }))), {
|
|
671
|
+
moduleName: options?.moduleName,
|
|
672
|
+
component: options?.component ?? 'permissions',
|
|
673
|
+
serviceCall: 'permissionRepo.save',
|
|
674
|
+
details: `batch=${batchNumber} createCount=${missingPermissionNames.length}`,
|
|
412
675
|
});
|
|
413
|
-
await this.permissionRepo.save(newPermission);
|
|
414
676
|
}
|
|
415
677
|
}
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
678
|
+
getUniquePermissionNames(permissionNames) {
|
|
679
|
+
const normalizedPermissionNames = new Set();
|
|
680
|
+
const uniquePermissionNames = [];
|
|
681
|
+
for (const permissionName of permissionNames) {
|
|
682
|
+
if (!permissionName) {
|
|
683
|
+
continue;
|
|
421
684
|
}
|
|
685
|
+
const normalizedPermissionName = this.normalizePermissionName(permissionName);
|
|
686
|
+
if (normalizedPermissionNames.has(normalizedPermissionName)) {
|
|
687
|
+
continue;
|
|
688
|
+
}
|
|
689
|
+
normalizedPermissionNames.add(normalizedPermissionName);
|
|
690
|
+
uniquePermissionNames.push(permissionName.trim());
|
|
422
691
|
}
|
|
692
|
+
return uniquePermissionNames;
|
|
693
|
+
}
|
|
694
|
+
normalizePermissionName(permissionName) {
|
|
695
|
+
return permissionName.trim().toLowerCase();
|
|
423
696
|
}
|
|
424
697
|
async seedMediaStorageProviders(mediaStorageProviders) {
|
|
425
|
-
this.logger.debug(`[Start] Processing Media Storage Provider`);
|
|
426
698
|
const providers = this.getSeedArray(mediaStorageProviders);
|
|
427
699
|
for (let i = 0; i < providers.length; i++) {
|
|
428
700
|
const mediaStorageProvider = providers[i];
|
|
429
|
-
await this.mediaStorageProviderMetadataService.upsert(mediaStorageProvider)
|
|
701
|
+
await this.timeOperation('media-storage-provider-upsert', () => this.mediaStorageProviderMetadataService.upsert(mediaStorageProvider), {
|
|
702
|
+
component: 'media-storage-providers',
|
|
703
|
+
serviceCall: 'mediaStorageProviderMetadataService.upsert',
|
|
704
|
+
details: `provider=${mediaStorageProvider?.name ?? mediaStorageProvider?.userKey ?? i}`,
|
|
705
|
+
});
|
|
430
706
|
}
|
|
431
|
-
this.logger.debug(`[End] Processing Media Storage Provider`);
|
|
432
707
|
return { pruned: 0, upserted: providers.length };
|
|
433
708
|
}
|
|
434
709
|
async seedModelSequences(overallMetadata) {
|
|
435
|
-
this.logger.debug(`[Start] Processing model sequences`);
|
|
436
710
|
const modelSequences = this.getSeedArray(overallMetadata?.modelSequences);
|
|
437
|
-
const pruned = this.enablePruning ? await this.pruneModelSequences(modelSequences, overallMetadata?.moduleMetadata?.name)
|
|
438
|
-
|
|
439
|
-
|
|
711
|
+
const pruned = this.enablePruning ? await this.timeOperation('prune-model-sequences', () => this.pruneModelSequences(modelSequences, overallMetadata?.moduleMetadata?.name), {
|
|
712
|
+
moduleName: overallMetadata?.moduleMetadata?.name,
|
|
713
|
+
component: 'model-sequences',
|
|
714
|
+
serviceCall: 'pruneModelSequences',
|
|
715
|
+
}) : 0;
|
|
716
|
+
await this.timeOperation('handle-model-sequences', () => this.handleSeedModelSequences(modelSequences), {
|
|
717
|
+
moduleName: overallMetadata?.moduleMetadata?.name,
|
|
718
|
+
component: 'model-sequences',
|
|
719
|
+
serviceCall: 'handleSeedModelSequences',
|
|
720
|
+
});
|
|
440
721
|
return { pruned, upserted: modelSequences.length };
|
|
441
722
|
}
|
|
442
723
|
async handleSeedEmailTemplates(emailTemplates, moduleName) {
|
|
@@ -473,8 +754,18 @@ let ModuleMetadataSeederService = ModuleMetadataSeederService_1 = class ModuleMe
|
|
|
473
754
|
emailTemplate.body = fs.readFileSync(fullPath, 'utf-8').toString();
|
|
474
755
|
}
|
|
475
756
|
}
|
|
476
|
-
await this.emailTemplateService.removeByName(emailTemplate.name)
|
|
477
|
-
|
|
757
|
+
await this.timeOperation('email-template-remove', () => this.emailTemplateService.removeByName(emailTemplate.name), {
|
|
758
|
+
moduleName,
|
|
759
|
+
component: 'email-templates',
|
|
760
|
+
serviceCall: 'emailTemplateService.removeByName',
|
|
761
|
+
details: `template=${emailTemplate.name}`,
|
|
762
|
+
});
|
|
763
|
+
await this.timeOperation('email-template-create', () => this.emailTemplateService.create(emailTemplate), {
|
|
764
|
+
moduleName,
|
|
765
|
+
component: 'email-templates',
|
|
766
|
+
serviceCall: 'emailTemplateService.create',
|
|
767
|
+
details: `template=${emailTemplate.name}`,
|
|
768
|
+
});
|
|
478
769
|
}
|
|
479
770
|
}
|
|
480
771
|
async handleSeedSmsTemplates(smsTemplates, moduleName) {
|
|
@@ -511,32 +802,62 @@ let ModuleMetadataSeederService = ModuleMetadataSeederService_1 = class ModuleMe
|
|
|
511
802
|
smsTemplate.body = fs.readFileSync(fullPath, 'utf-8').toString();
|
|
512
803
|
}
|
|
513
804
|
}
|
|
514
|
-
await this.smsTemplateService.removeByName(smsTemplate.name)
|
|
515
|
-
|
|
805
|
+
await this.timeOperation('sms-template-remove', () => this.smsTemplateService.removeByName(smsTemplate.name), {
|
|
806
|
+
moduleName,
|
|
807
|
+
component: 'sms-templates',
|
|
808
|
+
serviceCall: 'smsTemplateService.removeByName',
|
|
809
|
+
details: `template=${smsTemplate.name}`,
|
|
810
|
+
});
|
|
811
|
+
await this.timeOperation('sms-template-create', () => this.smsTemplateService.create(smsTemplate), {
|
|
812
|
+
moduleName,
|
|
813
|
+
component: 'sms-templates',
|
|
814
|
+
serviceCall: 'smsTemplateService.create',
|
|
815
|
+
details: `template=${smsTemplate.name}`,
|
|
816
|
+
});
|
|
516
817
|
}
|
|
517
818
|
}
|
|
518
819
|
async handleSeedMenus(menus) {
|
|
519
820
|
if (!menus) {
|
|
520
821
|
return;
|
|
521
822
|
}
|
|
522
|
-
await this.dataSource.transaction(async (trx) => {
|
|
823
|
+
await this.timeOperation('menus-transaction', () => this.dataSource.transaction(async (trx) => {
|
|
523
824
|
const menuRepo = trx.getRepository(menu_item_metadata_entity_1.MenuItemMetadata);
|
|
524
825
|
const roleRepo = trx.getRepository(role_metadata_entity_1.RoleMetadata);
|
|
525
826
|
const actionRepo = trx.getRepository(action_metadata_entity_1.ActionMetadata);
|
|
526
827
|
const moduleRepo = trx.getRepository(module_metadata_entity_1.ModuleMetadata);
|
|
527
828
|
for (const m of menus) {
|
|
528
829
|
const action = m.actionUserKey
|
|
529
|
-
? await actionRepo.findOne({ where: { name: m.actionUserKey }, select: ["id"] })
|
|
830
|
+
? await this.timeOperation('menu-action-find-one', () => actionRepo.findOne({ where: { name: m.actionUserKey }, select: ["id"] }), {
|
|
831
|
+
component: 'menus',
|
|
832
|
+
serviceCall: 'actionRepo.findOne',
|
|
833
|
+
details: `action=${m.actionUserKey}`,
|
|
834
|
+
})
|
|
530
835
|
: null;
|
|
531
836
|
const module = m.moduleUserKey
|
|
532
|
-
? await moduleRepo.findOne({ where: { name: m.moduleUserKey }, select: ["id"] })
|
|
837
|
+
? await this.timeOperation('menu-module-find-one', () => moduleRepo.findOne({ where: { name: m.moduleUserKey }, select: ["id"] }), {
|
|
838
|
+
component: 'menus',
|
|
839
|
+
serviceCall: 'moduleRepo.findOne',
|
|
840
|
+
details: `module=${m.moduleUserKey}`,
|
|
841
|
+
})
|
|
533
842
|
: null;
|
|
534
843
|
const parentMenuItem = m.parentMenuItemUserKey
|
|
535
|
-
? await menuRepo.findOne({ where: { name: m.parentMenuItemUserKey }, select: ["id"] })
|
|
844
|
+
? await this.timeOperation('menu-parent-find-one', () => menuRepo.findOne({ where: { name: m.parentMenuItemUserKey }, select: ["id"] }), {
|
|
845
|
+
component: 'menus',
|
|
846
|
+
serviceCall: 'menuRepo.findOne',
|
|
847
|
+
details: `parent=${m.parentMenuItemUserKey}`,
|
|
848
|
+
})
|
|
536
849
|
: null;
|
|
537
|
-
const existing = await menuRepo.findOne({
|
|
850
|
+
const existing = await this.timeOperation('menu-existing-find-one', () => menuRepo.findOne({
|
|
538
851
|
where: { name: m.name },
|
|
539
|
-
|
|
852
|
+
relations: {
|
|
853
|
+
action: true,
|
|
854
|
+
module: true,
|
|
855
|
+
parentMenuItem: true,
|
|
856
|
+
},
|
|
857
|
+
}), {
|
|
858
|
+
component: 'menus',
|
|
859
|
+
serviceCall: 'menuRepo.findOne',
|
|
860
|
+
details: `menu=${m.name}`,
|
|
540
861
|
});
|
|
541
862
|
const base = {
|
|
542
863
|
name: m.name,
|
|
@@ -547,23 +868,51 @@ let ModuleMetadataSeederService = ModuleMetadataSeederService_1 = class ModuleMe
|
|
|
547
868
|
sequenceNumber: m.sequenceNumber,
|
|
548
869
|
iconName: m.iconName,
|
|
549
870
|
};
|
|
871
|
+
const hasChanges = existing
|
|
872
|
+
? existing.displayName !== base.displayName
|
|
873
|
+
|| existing.sequenceNumber !== base.sequenceNumber
|
|
874
|
+
|| existing.iconName !== base.iconName
|
|
875
|
+
|| existing.action?.id !== base.action?.id
|
|
876
|
+
|| existing.module?.id !== base.module?.id
|
|
877
|
+
|| existing.parentMenuItem?.id !== base.parentMenuItem?.id
|
|
878
|
+
: true;
|
|
879
|
+
if (existing && !hasChanges) {
|
|
880
|
+
this.logger.debug(`Skipping menu upsert for ${m.name}; no changes detected.`);
|
|
881
|
+
continue;
|
|
882
|
+
}
|
|
550
883
|
const entity = menuRepo.create(existing ? { id: existing.id, ...base } : base);
|
|
551
|
-
await menuRepo.save(entity)
|
|
884
|
+
await this.timeOperation('menu-save', () => menuRepo.save(entity), {
|
|
885
|
+
component: 'menus',
|
|
886
|
+
serviceCall: 'menuRepo.save',
|
|
887
|
+
details: `menu=${m.name}`,
|
|
888
|
+
});
|
|
552
889
|
}
|
|
553
|
-
const seeded = await menuRepo.find({
|
|
890
|
+
const seeded = await this.timeOperation('menu-seeded-find', () => menuRepo.find({
|
|
554
891
|
where: { name: (0, typeorm_1.In)(menus.map((m) => m.name)) },
|
|
555
892
|
select: ["id", "name"],
|
|
893
|
+
}), {
|
|
894
|
+
component: 'menus',
|
|
895
|
+
serviceCall: 'menuRepo.find',
|
|
896
|
+
details: `count=${menus.length}`,
|
|
556
897
|
});
|
|
557
898
|
const idByName = new Map(seeded.map(s => [s.name, s.id]));
|
|
558
|
-
const admin = await roleRepo.findOne({ where: { name: create_role_metadata_dto_1.ADMIN_ROLE_NAME }, select: ["id", "name"] })
|
|
899
|
+
const admin = await this.timeOperation('menu-admin-role-find-one', () => roleRepo.findOne({ where: { name: create_role_metadata_dto_1.ADMIN_ROLE_NAME }, select: ["id", "name"] }), {
|
|
900
|
+
component: 'menus',
|
|
901
|
+
serviceCall: 'roleRepo.findOne',
|
|
902
|
+
details: `role=${create_role_metadata_dto_1.ADMIN_ROLE_NAME}`,
|
|
903
|
+
});
|
|
559
904
|
const allRoleNames = new Set();
|
|
560
905
|
for (const m of menus)
|
|
561
906
|
(m.roles ?? []).forEach((r) => allRoleNames.add(r));
|
|
562
907
|
if (admin)
|
|
563
908
|
allRoleNames.add(admin.name);
|
|
564
|
-
const roles = await roleRepo.find({
|
|
909
|
+
const roles = await this.timeOperation('menu-roles-find', () => roleRepo.find({
|
|
565
910
|
where: { name: (0, typeorm_1.In)([...allRoleNames]) },
|
|
566
911
|
select: ["id", "name"],
|
|
912
|
+
}), {
|
|
913
|
+
component: 'menus',
|
|
914
|
+
serviceCall: 'roleRepo.find',
|
|
915
|
+
details: `roleCount=${allRoleNames.size}`,
|
|
567
916
|
});
|
|
568
917
|
const roleByName = new Map(roles.map(r => [r.name, r]));
|
|
569
918
|
const joinRows = [];
|
|
@@ -578,57 +927,153 @@ let ModuleMetadataSeederService = ModuleMetadataSeederService_1 = class ModuleMe
|
|
|
578
927
|
}
|
|
579
928
|
const menuIds = [...new Set(joinRows.map(r => r.menuId))];
|
|
580
929
|
if (menuIds.length) {
|
|
581
|
-
await trx
|
|
930
|
+
await this.timeOperation('menu-role-joins-delete', () => trx
|
|
582
931
|
.createQueryBuilder()
|
|
583
932
|
.delete()
|
|
584
933
|
.from(create_menu_item_metadata_dto_1.MENU_ROLE_JOIN_TABLE_NAME)
|
|
585
934
|
.where(`${create_menu_item_metadata_dto_1.MENU_ROLE_JOIN_TABLE_NAME_MENU_COL} IN (:...ids)`, { ids: menuIds })
|
|
586
|
-
.execute()
|
|
935
|
+
.execute(), {
|
|
936
|
+
component: 'menus',
|
|
937
|
+
serviceCall: 'trx.delete.menuRoleJoins',
|
|
938
|
+
details: `menuCount=${menuIds.length}`,
|
|
939
|
+
});
|
|
587
940
|
}
|
|
588
941
|
if (joinRows.length) {
|
|
589
942
|
const values = joinRows.map(r => ({
|
|
590
943
|
[create_menu_item_metadata_dto_1.MENU_ROLE_JOIN_TABLE_NAME_MENU_COL]: r.menuId,
|
|
591
944
|
[create_menu_item_metadata_dto_1.MENU_ROLE_JOIN_TABLE_NAME_ROLE_COL]: r.roleId,
|
|
592
945
|
}));
|
|
593
|
-
await trx
|
|
946
|
+
await this.timeOperation('menu-role-joins-insert', () => trx
|
|
594
947
|
.createQueryBuilder()
|
|
595
948
|
.insert()
|
|
596
949
|
.into(create_menu_item_metadata_dto_1.MENU_ROLE_JOIN_TABLE_NAME)
|
|
597
950
|
.values(values)
|
|
598
|
-
.execute()
|
|
951
|
+
.execute(), {
|
|
952
|
+
component: 'menus',
|
|
953
|
+
serviceCall: 'trx.insert.menuRoleJoins',
|
|
954
|
+
details: `rowCount=${values.length}`,
|
|
955
|
+
});
|
|
599
956
|
}
|
|
600
|
-
});
|
|
957
|
+
}), { component: 'menus', serviceCall: 'dataSource.transaction' });
|
|
601
958
|
}
|
|
602
959
|
async handleSeedActions(actions) {
|
|
603
960
|
if (!actions) {
|
|
604
961
|
return;
|
|
605
962
|
}
|
|
963
|
+
const actionRepo = this.dataSource.getRepository(action_metadata_entity_1.ActionMetadata);
|
|
964
|
+
await this.timeOperation('action-prime-module-cache', () => this.primeModuleLookupCache(actions.map((action) => action?.moduleUserKey)), {
|
|
965
|
+
component: 'actions',
|
|
966
|
+
serviceCall: 'primeModuleLookupCache',
|
|
967
|
+
details: `count=${actions.length}`,
|
|
968
|
+
});
|
|
969
|
+
await this.timeOperation('action-prime-model-cache', () => this.primeModelLookupCache(actions.map((action) => action?.modelUserKey)), {
|
|
970
|
+
component: 'actions',
|
|
971
|
+
serviceCall: 'primeModelLookupCache',
|
|
972
|
+
details: `count=${actions.length}`,
|
|
973
|
+
});
|
|
974
|
+
await this.timeOperation('action-prime-view-cache', () => this.primeViewLookupCache(actions.map((action) => action?.viewUserKey)), {
|
|
975
|
+
component: 'actions',
|
|
976
|
+
serviceCall: 'primeViewLookupCache',
|
|
977
|
+
details: `count=${actions.length}`,
|
|
978
|
+
});
|
|
979
|
+
const existingActionsByName = await this.timeOperation('action-preload-existing', () => this.loadExistingActionsByName(actionRepo, actions.map((action) => action?.name).filter(Boolean)), {
|
|
980
|
+
component: 'actions',
|
|
981
|
+
serviceCall: 'loadExistingActionsByName',
|
|
982
|
+
details: `count=${actions.length}`,
|
|
983
|
+
});
|
|
984
|
+
let created = 0;
|
|
985
|
+
let updated = 0;
|
|
986
|
+
let skipped = 0;
|
|
606
987
|
for (let j = 0; j < actions.length; j++) {
|
|
607
988
|
const actionData = actions[j];
|
|
608
|
-
actionData['module'] = await this.
|
|
989
|
+
actionData['module'] = await this.getModuleByUserKeyCached(actionData.moduleUserKey, {
|
|
990
|
+
moduleName: actionData.moduleUserKey,
|
|
991
|
+
component: 'actions',
|
|
992
|
+
details: `module=${actionData.moduleUserKey}`,
|
|
993
|
+
});
|
|
609
994
|
if (actionData.type === 'solid') {
|
|
610
|
-
actionData['model'] = await this.
|
|
611
|
-
|
|
995
|
+
actionData['model'] = await this.getModelByUserKeyCached(actionData.modelUserKey, {
|
|
996
|
+
moduleName: actionData.moduleUserKey,
|
|
997
|
+
component: 'actions',
|
|
998
|
+
details: `model=${actionData.modelUserKey}`,
|
|
999
|
+
});
|
|
1000
|
+
actionData['view'] = await this.getViewByUserKeyCached(actionData.viewUserKey, {
|
|
1001
|
+
moduleName: actionData.moduleUserKey,
|
|
1002
|
+
component: 'actions',
|
|
1003
|
+
details: `view=${actionData.viewUserKey}`,
|
|
1004
|
+
});
|
|
612
1005
|
}
|
|
613
1006
|
else {
|
|
614
1007
|
if (actionData.modelUserKey) {
|
|
615
|
-
actionData['model'] = await this.
|
|
1008
|
+
actionData['model'] = await this.getModelByUserKeyCached(actionData.modelUserKey, {
|
|
1009
|
+
moduleName: actionData.moduleUserKey,
|
|
1010
|
+
component: 'actions',
|
|
1011
|
+
details: `model=${actionData.modelUserKey}`,
|
|
1012
|
+
});
|
|
616
1013
|
}
|
|
617
1014
|
}
|
|
618
|
-
await this.
|
|
1015
|
+
const result = await this.upsertActionMetadataWithPreloadedExisting(actionRepo, existingActionsByName, actionData);
|
|
1016
|
+
if (result.outcome === 'created') {
|
|
1017
|
+
created += 1;
|
|
1018
|
+
}
|
|
1019
|
+
else if (result.outcome === 'updated') {
|
|
1020
|
+
updated += 1;
|
|
1021
|
+
}
|
|
1022
|
+
else {
|
|
1023
|
+
skipped += 1;
|
|
1024
|
+
}
|
|
619
1025
|
}
|
|
1026
|
+
this.logger.debug(`Action seed summary: created=${created}, updated=${updated}, skipped=${skipped}.`);
|
|
620
1027
|
}
|
|
621
1028
|
async handleSeedViews(views) {
|
|
622
1029
|
if (!views) {
|
|
623
1030
|
return;
|
|
624
1031
|
}
|
|
1032
|
+
const viewRepo = this.dataSource.getRepository(view_metadata_entity_1.ViewMetadata);
|
|
1033
|
+
await this.timeOperation('view-prime-module-cache', () => this.primeModuleLookupCache(views.map((view) => view?.moduleUserKey)), {
|
|
1034
|
+
component: 'views',
|
|
1035
|
+
serviceCall: 'primeModuleLookupCache',
|
|
1036
|
+
details: `count=${views.length}`,
|
|
1037
|
+
});
|
|
1038
|
+
await this.timeOperation('view-prime-model-cache', () => this.primeModelLookupCache(views.map((view) => view?.modelUserKey)), {
|
|
1039
|
+
component: 'views',
|
|
1040
|
+
serviceCall: 'primeModelLookupCache',
|
|
1041
|
+
details: `count=${views.length}`,
|
|
1042
|
+
});
|
|
1043
|
+
const existingViewsByName = await this.timeOperation('view-preload-existing', () => this.loadExistingViewsByName(viewRepo, views.map((view) => view?.name).filter(Boolean)), {
|
|
1044
|
+
component: 'views',
|
|
1045
|
+
serviceCall: 'loadExistingViewsByName',
|
|
1046
|
+
details: `count=${views.length}`,
|
|
1047
|
+
});
|
|
1048
|
+
let created = 0;
|
|
1049
|
+
let updated = 0;
|
|
1050
|
+
let skipped = 0;
|
|
625
1051
|
for (let j = 0; j < views.length; j++) {
|
|
626
1052
|
const viewData = views[j];
|
|
627
1053
|
viewData['layout'] = JSON.stringify(viewData['layout'], null, 2);
|
|
628
|
-
viewData['module'] = await this.
|
|
629
|
-
|
|
630
|
-
|
|
1054
|
+
viewData['module'] = await this.getModuleByUserKeyCached(viewData.moduleUserKey, {
|
|
1055
|
+
moduleName: viewData.moduleUserKey,
|
|
1056
|
+
component: 'views',
|
|
1057
|
+
details: `module=${viewData.moduleUserKey}`,
|
|
1058
|
+
});
|
|
1059
|
+
viewData['model'] = await this.getModelByUserKeyCached(viewData.modelUserKey, {
|
|
1060
|
+
moduleName: viewData.moduleUserKey,
|
|
1061
|
+
component: 'views',
|
|
1062
|
+
details: `model=${viewData.modelUserKey}`,
|
|
1063
|
+
});
|
|
1064
|
+
const result = await this.upsertViewMetadataWithPreloadedExisting(viewRepo, existingViewsByName, viewData);
|
|
1065
|
+
this.viewLookupCache.set(viewData.name, result.entity ?? null);
|
|
1066
|
+
if (result.outcome === 'created') {
|
|
1067
|
+
created += 1;
|
|
1068
|
+
}
|
|
1069
|
+
else if (result.outcome === 'updated') {
|
|
1070
|
+
updated += 1;
|
|
1071
|
+
}
|
|
1072
|
+
else {
|
|
1073
|
+
skipped += 1;
|
|
1074
|
+
}
|
|
631
1075
|
}
|
|
1076
|
+
this.logger.debug(`View seed summary: created=${created}, updated=${updated}, skipped=${skipped}.`);
|
|
632
1077
|
}
|
|
633
1078
|
async handleSeedUsers(users) {
|
|
634
1079
|
if (!users) {
|
|
@@ -636,19 +1081,127 @@ let ModuleMetadataSeederService = ModuleMetadataSeederService_1 = class ModuleMe
|
|
|
636
1081
|
}
|
|
637
1082
|
for (let l = 0; l < users.length; l++) {
|
|
638
1083
|
const user = users[l];
|
|
639
|
-
|
|
1084
|
+
const isSystemAdminUser = user.username === 'sa';
|
|
1085
|
+
let exisitingUser = await this.timeOperation('user-find-by-username', () => this.userService.findOneByUsername(user.username), {
|
|
1086
|
+
component: 'users',
|
|
1087
|
+
serviceCall: 'userService.findOneByUsername',
|
|
1088
|
+
details: `username=${user.username}`,
|
|
1089
|
+
});
|
|
640
1090
|
if (!exisitingUser) {
|
|
641
1091
|
if (user.username === 'sa') {
|
|
642
1092
|
user.password = create_user_dto_1.DEFAULT_SA_PASSWORD;
|
|
643
1093
|
}
|
|
644
|
-
|
|
1094
|
+
if (isSystemAdminUser) {
|
|
1095
|
+
user.isAllowedToGenerateApiKeys = true;
|
|
1096
|
+
}
|
|
1097
|
+
exisitingUser = await this.timeOperation('user-sign-up', () => this.authenticationService.signUp(user), {
|
|
1098
|
+
component: 'users',
|
|
1099
|
+
serviceCall: 'authenticationService.signUp',
|
|
1100
|
+
details: `username=${user.username}`,
|
|
1101
|
+
});
|
|
1102
|
+
if (isSystemAdminUser) {
|
|
1103
|
+
await this.timeOperation('seed-sa-api-key', async () => {
|
|
1104
|
+
const generatedApiKey = await this.apiKeyService.generate(exisitingUser.id, {
|
|
1105
|
+
name: 'Default SA API Key',
|
|
1106
|
+
});
|
|
1107
|
+
await this.writeSolidxAdminApiKeyConfig(generatedApiKey);
|
|
1108
|
+
}, {
|
|
1109
|
+
component: 'users',
|
|
1110
|
+
serviceCall: 'apiKeyService.generate',
|
|
1111
|
+
details: `username=${user.username}`,
|
|
1112
|
+
});
|
|
1113
|
+
}
|
|
645
1114
|
this.logger.log(`Newly created user ${user.username}`);
|
|
646
1115
|
}
|
|
1116
|
+
if (isSystemAdminUser) {
|
|
1117
|
+
await this.ensureSystemAdminApiKey(exisitingUser);
|
|
1118
|
+
}
|
|
647
1119
|
}
|
|
648
1120
|
}
|
|
1121
|
+
async ensureSystemAdminApiKey(existingUser) {
|
|
1122
|
+
if (!existingUser?.id) {
|
|
1123
|
+
return;
|
|
1124
|
+
}
|
|
1125
|
+
if (!existingUser.isAllowedToGenerateApiKeys) {
|
|
1126
|
+
await this.timeOperation('enable-sa-api-key-generation', () => this.userApiKeyRepository.manager.update(user_entity_1.User, { id: existingUser.id }, {
|
|
1127
|
+
isAllowedToGenerateApiKeys: true,
|
|
1128
|
+
}), {
|
|
1129
|
+
component: 'users',
|
|
1130
|
+
serviceCall: 'userRepository.update',
|
|
1131
|
+
details: `username=${existingUser.username}`,
|
|
1132
|
+
});
|
|
1133
|
+
existingUser.isAllowedToGenerateApiKeys = true;
|
|
1134
|
+
}
|
|
1135
|
+
const existingDefaultKey = await this.timeOperation('find-sa-default-api-key', () => this.userApiKeyRepository.findOne({
|
|
1136
|
+
where: {
|
|
1137
|
+
user: { id: existingUser.id },
|
|
1138
|
+
name: 'Default SA API Key',
|
|
1139
|
+
},
|
|
1140
|
+
relations: {
|
|
1141
|
+
user: true,
|
|
1142
|
+
},
|
|
1143
|
+
}), {
|
|
1144
|
+
component: 'users',
|
|
1145
|
+
serviceCall: 'userApiKeyRepository.findOne',
|
|
1146
|
+
details: `username=${existingUser.username}`,
|
|
1147
|
+
});
|
|
1148
|
+
if (existingDefaultKey) {
|
|
1149
|
+
return;
|
|
1150
|
+
}
|
|
1151
|
+
await this.timeOperation('seed-sa-api-key', async () => {
|
|
1152
|
+
const generatedApiKey = await this.apiKeyService.generate(existingUser.id, {
|
|
1153
|
+
name: 'Default SA API Key',
|
|
1154
|
+
});
|
|
1155
|
+
await this.writeSolidxAdminApiKeyConfig(generatedApiKey);
|
|
1156
|
+
}, {
|
|
1157
|
+
component: 'users',
|
|
1158
|
+
serviceCall: 'apiKeyService.generate',
|
|
1159
|
+
details: `username=${existingUser.username}`,
|
|
1160
|
+
});
|
|
1161
|
+
}
|
|
1162
|
+
async writeSolidxAdminApiKeyConfig(generatedApiKey) {
|
|
1163
|
+
const consumingProjectRoot = path.resolve(process.cwd(), '..');
|
|
1164
|
+
const consumingProjectName = path.basename(consumingProjectRoot);
|
|
1165
|
+
const solidxDir = path.join(os.homedir(), '.solidx', consumingProjectName);
|
|
1166
|
+
const configPath = path.join(solidxDir, 'mcp.json');
|
|
1167
|
+
await fs.promises.mkdir(solidxDir, { recursive: true });
|
|
1168
|
+
let existingConfig = {};
|
|
1169
|
+
if (fs.existsSync(configPath)) {
|
|
1170
|
+
const rawConfig = await fs.promises.readFile(configPath, 'utf8');
|
|
1171
|
+
if (rawConfig.trim()) {
|
|
1172
|
+
const parsedConfig = JSON.parse(rawConfig);
|
|
1173
|
+
if (parsedConfig && typeof parsedConfig === 'object' && !Array.isArray(parsedConfig)) {
|
|
1174
|
+
existingConfig = parsedConfig;
|
|
1175
|
+
}
|
|
1176
|
+
else {
|
|
1177
|
+
this.logger.warn(`Expected ${configPath} to contain a JSON object. Overwriting with a new object.`);
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
const nextConfig = {
|
|
1182
|
+
...existingConfig,
|
|
1183
|
+
solidxAdminApiKey: {
|
|
1184
|
+
id: generatedApiKey.record.id,
|
|
1185
|
+
name: generatedApiKey.record.name,
|
|
1186
|
+
apiKey: generatedApiKey.apiKey,
|
|
1187
|
+
maskedKey: generatedApiKey.record.maskedKey,
|
|
1188
|
+
isActive: generatedApiKey.record.isActive,
|
|
1189
|
+
expiresAt: generatedApiKey.record.expiresAt,
|
|
1190
|
+
createdAt: generatedApiKey.record.createdAt,
|
|
1191
|
+
updatedAt: generatedApiKey.record.updatedAt,
|
|
1192
|
+
},
|
|
1193
|
+
};
|
|
1194
|
+
await fs.promises.writeFile(configPath, `${JSON.stringify(nextConfig, null, 2)}\n`, 'utf8');
|
|
1195
|
+
}
|
|
649
1196
|
async seedModuleModelFields(moduleMetadata) {
|
|
650
|
-
this.
|
|
651
|
-
const module = await this.moduleMetadataService.upsert(moduleMetadata)
|
|
1197
|
+
const fieldMetadataRepo = this.dataSource.getRepository(field_metadata_entity_1.FieldMetadata);
|
|
1198
|
+
const module = await this.timeOperation('module-upsert', () => this.moduleMetadataService.upsert(moduleMetadata), {
|
|
1199
|
+
moduleName: moduleMetadata.name,
|
|
1200
|
+
component: 'module-model-fields',
|
|
1201
|
+
serviceCall: 'moduleMetadataService.upsert',
|
|
1202
|
+
details: `module=${moduleMetadata.name}`,
|
|
1203
|
+
});
|
|
1204
|
+
this.moduleLookupCache.set(moduleMetadata.name, module ?? null);
|
|
652
1205
|
let pruned = 0;
|
|
653
1206
|
let upserted = 1;
|
|
654
1207
|
const modelsMetadata = this.getSeedArray(moduleMetadata?.models);
|
|
@@ -658,24 +1211,59 @@ let ModuleMetadataSeederService = ModuleMetadataSeederService_1 = class ModuleMe
|
|
|
658
1211
|
modelMetadata['module'] = module;
|
|
659
1212
|
const { fields: fieldsMetadata, ...modelMetaDataWithoutFields } = modelMetadata;
|
|
660
1213
|
if (modelMetadata.isChild && modelMetadata.parentModelUserKey) {
|
|
661
|
-
const parentModel = await this.
|
|
1214
|
+
const parentModel = await this.getModelByUserKeyCached(modelMetadata.parentModelUserKey, {
|
|
1215
|
+
moduleName: moduleMetadata.name,
|
|
1216
|
+
component: 'module-model-fields',
|
|
1217
|
+
details: `parentModel=${modelMetadata.parentModelUserKey}`,
|
|
1218
|
+
});
|
|
662
1219
|
modelMetaDataWithoutFields['parentModel'] = parentModel;
|
|
663
1220
|
}
|
|
664
|
-
await this.modelMetadataService.upsert(modelMetaDataWithoutFields)
|
|
665
|
-
|
|
1221
|
+
const upsertedModel = await this.timeOperation('model-upsert', () => this.modelMetadataService.upsert(modelMetaDataWithoutFields), {
|
|
1222
|
+
moduleName: moduleMetadata.name,
|
|
1223
|
+
component: 'module-model-fields',
|
|
1224
|
+
serviceCall: 'modelMetadataService.upsert',
|
|
1225
|
+
details: `model=${modelMetadata.singularName}`,
|
|
1226
|
+
});
|
|
1227
|
+
this.modelLookupCache.set(modelMetadata.singularName, upsertedModel ?? null);
|
|
1228
|
+
const model = await this.timeOperation('model-find-by-singular-name', () => this.modelMetadataService.findOneBySingularName(modelMetadata.singularName), {
|
|
1229
|
+
moduleName: moduleMetadata.name,
|
|
1230
|
+
component: 'module-model-fields',
|
|
1231
|
+
serviceCall: 'modelMetadataService.findOneBySingularName',
|
|
1232
|
+
details: `model=${modelMetadata.singularName}`,
|
|
1233
|
+
});
|
|
666
1234
|
if (this.enablePruning) {
|
|
667
|
-
pruned += await this.pruneFieldsForModel(model, fieldsMetadata)
|
|
1235
|
+
pruned += await this.timeOperation('prune-fields-for-model', () => this.pruneFieldsForModel(model, fieldsMetadata), {
|
|
1236
|
+
moduleName: moduleMetadata.name,
|
|
1237
|
+
component: 'module-model-fields',
|
|
1238
|
+
serviceCall: 'pruneFieldsForModel',
|
|
1239
|
+
details: `model=${modelMetadata.singularName}`,
|
|
1240
|
+
});
|
|
668
1241
|
}
|
|
669
1242
|
let userKeyField = null;
|
|
670
1243
|
const userKeyFieldName = modelMetadata.userKeyFieldUserKey;
|
|
1244
|
+
const existingFieldsByName = await this.timeOperation('field-preload-for-model', () => this.loadExistingFieldsByName(fieldMetadataRepo, model.id), {
|
|
1245
|
+
moduleName: moduleMetadata.name,
|
|
1246
|
+
component: 'module-model-fields',
|
|
1247
|
+
serviceCall: 'loadExistingFieldsByName',
|
|
1248
|
+
details: `model=${modelMetadata.singularName}`,
|
|
1249
|
+
});
|
|
671
1250
|
upserted += fieldsMetadata?.length ?? 0;
|
|
672
1251
|
for (let k = 0; k < fieldsMetadata.length; k++) {
|
|
673
1252
|
const fieldMetadata = fieldsMetadata[k];
|
|
674
1253
|
fieldMetadata['model'] = model;
|
|
675
1254
|
if (fieldMetadata.mediaStorageProviderUserKey) {
|
|
676
|
-
fieldMetadata['mediaStorageProvider'] = await this.
|
|
1255
|
+
fieldMetadata['mediaStorageProvider'] = await this.getMediaStorageProviderByUserKeyCached(fieldMetadata.mediaStorageProviderUserKey, {
|
|
1256
|
+
moduleName: moduleMetadata.name,
|
|
1257
|
+
component: 'module-model-fields',
|
|
1258
|
+
details: `provider=${fieldMetadata.mediaStorageProviderUserKey}`,
|
|
1259
|
+
});
|
|
677
1260
|
}
|
|
678
|
-
const affectedField = await this.
|
|
1261
|
+
const affectedField = await this.timeOperation('field-upsert', () => this.upsertFieldMetadataWithPreloadedExisting(fieldMetadataRepo, existingFieldsByName, fieldMetadata), {
|
|
1262
|
+
moduleName: moduleMetadata.name,
|
|
1263
|
+
component: 'module-model-fields',
|
|
1264
|
+
serviceCall: 'upsertFieldMetadataWithPreloadedExisting',
|
|
1265
|
+
details: `field=${fieldMetadata.name} model=${modelMetadata.singularName}`,
|
|
1266
|
+
});
|
|
679
1267
|
if (fieldMetadata.name === userKeyFieldName || fieldMetadata.isUserKey) {
|
|
680
1268
|
const { model, ...fieldData } = affectedField;
|
|
681
1269
|
userKeyField = fieldData;
|
|
@@ -683,25 +1271,285 @@ let ModuleMetadataSeederService = ModuleMetadataSeederService_1 = class ModuleMe
|
|
|
683
1271
|
}
|
|
684
1272
|
if (userKeyField) {
|
|
685
1273
|
modelMetaDataWithoutFields['userKeyField'] = userKeyField;
|
|
686
|
-
await this.modelMetadataService.upsert(modelMetaDataWithoutFields)
|
|
1274
|
+
await this.timeOperation('model-user-key-field-upsert', () => this.modelMetadataService.upsert(modelMetaDataWithoutFields), {
|
|
1275
|
+
moduleName: moduleMetadata.name,
|
|
1276
|
+
component: 'module-model-fields',
|
|
1277
|
+
serviceCall: 'modelMetadataService.upsert',
|
|
1278
|
+
details: `model=${modelMetadata.singularName} userKeyField=${userKeyField?.name ?? 'unknown'}`,
|
|
1279
|
+
});
|
|
687
1280
|
}
|
|
688
1281
|
}
|
|
689
1282
|
if (this.enablePruning) {
|
|
690
|
-
pruned += await this.pruneModels(modelsMetadata, moduleMetadata.name)
|
|
1283
|
+
pruned += await this.timeOperation('prune-models', () => this.pruneModels(modelsMetadata, moduleMetadata.name), {
|
|
1284
|
+
moduleName: moduleMetadata.name,
|
|
1285
|
+
component: 'module-model-fields',
|
|
1286
|
+
serviceCall: 'pruneModels',
|
|
1287
|
+
});
|
|
691
1288
|
}
|
|
692
|
-
this.logger.debug(`[End] Processing module metadata`);
|
|
693
1289
|
return { pruned, upserted };
|
|
694
1290
|
}
|
|
695
1291
|
getSeedArray(value) {
|
|
696
1292
|
return Array.isArray(value) ? value : [];
|
|
697
1293
|
}
|
|
1294
|
+
async loadExistingFieldsByName(fieldMetadataRepo, modelId) {
|
|
1295
|
+
const existingFields = await fieldMetadataRepo.find({
|
|
1296
|
+
where: {
|
|
1297
|
+
model: { id: modelId },
|
|
1298
|
+
},
|
|
1299
|
+
relations: {
|
|
1300
|
+
model: true,
|
|
1301
|
+
mediaStorageProvider: true,
|
|
1302
|
+
},
|
|
1303
|
+
});
|
|
1304
|
+
return new Map(existingFields.map((field) => [field.name, field]));
|
|
1305
|
+
}
|
|
1306
|
+
async primeModuleLookupCache(moduleUserKeys) {
|
|
1307
|
+
const missingModuleUserKeys = [...new Set(moduleUserKeys.filter((moduleUserKey) => Boolean(moduleUserKey) && !this.moduleLookupCache.has(moduleUserKey)))];
|
|
1308
|
+
if (missingModuleUserKeys.length === 0) {
|
|
1309
|
+
return;
|
|
1310
|
+
}
|
|
1311
|
+
const moduleRepo = this.dataSource.getRepository(module_metadata_entity_1.ModuleMetadata);
|
|
1312
|
+
const existingModules = await moduleRepo.find({
|
|
1313
|
+
where: {
|
|
1314
|
+
name: (0, typeorm_1.In)(missingModuleUserKeys),
|
|
1315
|
+
},
|
|
1316
|
+
});
|
|
1317
|
+
const moduleByName = new Map(existingModules.map((module) => [module.name, module]));
|
|
1318
|
+
for (const moduleUserKey of missingModuleUserKeys) {
|
|
1319
|
+
this.moduleLookupCache.set(moduleUserKey, moduleByName.get(moduleUserKey) ?? null);
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
async primeModelLookupCache(modelUserKeys) {
|
|
1323
|
+
const missingModelUserKeys = [...new Set(modelUserKeys.filter((modelUserKey) => Boolean(modelUserKey) && !this.modelLookupCache.has(modelUserKey)))];
|
|
1324
|
+
if (missingModelUserKeys.length === 0) {
|
|
1325
|
+
return;
|
|
1326
|
+
}
|
|
1327
|
+
const modelRepo = this.dataSource.getRepository(model_metadata_entity_1.ModelMetadata);
|
|
1328
|
+
const existingModels = await modelRepo.find({
|
|
1329
|
+
where: {
|
|
1330
|
+
singularName: (0, typeorm_1.In)(missingModelUserKeys),
|
|
1331
|
+
},
|
|
1332
|
+
relations: {
|
|
1333
|
+
module: true,
|
|
1334
|
+
userKeyField: true,
|
|
1335
|
+
},
|
|
1336
|
+
});
|
|
1337
|
+
const modelBySingularName = new Map(existingModels.map((model) => [model.singularName, model]));
|
|
1338
|
+
for (const modelUserKey of missingModelUserKeys) {
|
|
1339
|
+
this.modelLookupCache.set(modelUserKey, modelBySingularName.get(modelUserKey) ?? null);
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
async primeViewLookupCache(viewUserKeys) {
|
|
1343
|
+
const missingViewUserKeys = [...new Set(viewUserKeys.filter((viewUserKey) => Boolean(viewUserKey) && !this.viewLookupCache.has(viewUserKey)))];
|
|
1344
|
+
if (missingViewUserKeys.length === 0) {
|
|
1345
|
+
return;
|
|
1346
|
+
}
|
|
1347
|
+
const viewRepo = this.dataSource.getRepository(view_metadata_entity_1.ViewMetadata);
|
|
1348
|
+
const existingViews = await viewRepo.find({
|
|
1349
|
+
where: {
|
|
1350
|
+
name: (0, typeorm_1.In)(missingViewUserKeys),
|
|
1351
|
+
},
|
|
1352
|
+
relations: {
|
|
1353
|
+
module: true,
|
|
1354
|
+
model: true,
|
|
1355
|
+
},
|
|
1356
|
+
});
|
|
1357
|
+
const viewByName = new Map(existingViews.map((view) => [view.name, view]));
|
|
1358
|
+
for (const viewUserKey of missingViewUserKeys) {
|
|
1359
|
+
this.viewLookupCache.set(viewUserKey, viewByName.get(viewUserKey) ?? null);
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
async loadExistingViewsByName(viewRepo, viewNames) {
|
|
1363
|
+
const uniqueViewNames = [...new Set(viewNames.filter(Boolean))];
|
|
1364
|
+
if (uniqueViewNames.length === 0) {
|
|
1365
|
+
return new Map();
|
|
1366
|
+
}
|
|
1367
|
+
const existingViews = await viewRepo.find({
|
|
1368
|
+
where: {
|
|
1369
|
+
name: (0, typeorm_1.In)(uniqueViewNames),
|
|
1370
|
+
},
|
|
1371
|
+
relations: {
|
|
1372
|
+
module: true,
|
|
1373
|
+
model: true,
|
|
1374
|
+
},
|
|
1375
|
+
});
|
|
1376
|
+
return new Map(existingViews.map((view) => [view.name, view]));
|
|
1377
|
+
}
|
|
1378
|
+
async loadExistingActionsByName(actionRepo, actionNames) {
|
|
1379
|
+
const uniqueActionNames = [...new Set(actionNames.filter(Boolean))];
|
|
1380
|
+
if (uniqueActionNames.length === 0) {
|
|
1381
|
+
return new Map();
|
|
1382
|
+
}
|
|
1383
|
+
const existingActions = await actionRepo.find({
|
|
1384
|
+
where: {
|
|
1385
|
+
name: (0, typeorm_1.In)(uniqueActionNames),
|
|
1386
|
+
},
|
|
1387
|
+
relations: {
|
|
1388
|
+
module: true,
|
|
1389
|
+
model: true,
|
|
1390
|
+
view: true,
|
|
1391
|
+
},
|
|
1392
|
+
});
|
|
1393
|
+
return new Map(existingActions.map((action) => [action.name, action]));
|
|
1394
|
+
}
|
|
1395
|
+
normalizeJsonFieldValue(value) {
|
|
1396
|
+
if (typeof value === 'string') {
|
|
1397
|
+
const trimmedValue = value.trim();
|
|
1398
|
+
if ((trimmedValue.startsWith('{') && trimmedValue.endsWith('}'))
|
|
1399
|
+
|| (trimmedValue.startsWith('[') && trimmedValue.endsWith(']'))) {
|
|
1400
|
+
try {
|
|
1401
|
+
return this.normalizeJsonFieldValue(JSON.parse(trimmedValue));
|
|
1402
|
+
}
|
|
1403
|
+
catch {
|
|
1404
|
+
return value;
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
return value;
|
|
1408
|
+
}
|
|
1409
|
+
if (Array.isArray(value)) {
|
|
1410
|
+
return value.map((item) => this.normalizeJsonFieldValue(item));
|
|
1411
|
+
}
|
|
1412
|
+
if (value && typeof value === 'object') {
|
|
1413
|
+
return Object.keys(value)
|
|
1414
|
+
.sort()
|
|
1415
|
+
.reduce((result, key) => {
|
|
1416
|
+
result[key] = this.normalizeJsonFieldValue(value[key]);
|
|
1417
|
+
return result;
|
|
1418
|
+
}, {});
|
|
1419
|
+
}
|
|
1420
|
+
return value;
|
|
1421
|
+
}
|
|
1422
|
+
getCanonicalJsonFieldString(value) {
|
|
1423
|
+
return JSON.stringify(this.normalizeJsonFieldValue(value) ?? null);
|
|
1424
|
+
}
|
|
1425
|
+
hasViewMetadataChanges(existingView, updateDto) {
|
|
1426
|
+
const relationFields = new Set(['module', 'model']);
|
|
1427
|
+
const jsonFields = new Set(['layout', 'context']);
|
|
1428
|
+
return this.viewComparableFields.some((key) => {
|
|
1429
|
+
const value = updateDto[key];
|
|
1430
|
+
if (typeof value === 'undefined') {
|
|
1431
|
+
return false;
|
|
1432
|
+
}
|
|
1433
|
+
if (relationFields.has(key)) {
|
|
1434
|
+
const relationValue = value;
|
|
1435
|
+
return existingView[key]?.id !== relationValue?.id;
|
|
1436
|
+
}
|
|
1437
|
+
if (jsonFields.has(key)) {
|
|
1438
|
+
return this.getCanonicalJsonFieldString(existingView[key]) !== this.getCanonicalJsonFieldString(value);
|
|
1439
|
+
}
|
|
1440
|
+
return existingView[key] !== value;
|
|
1441
|
+
});
|
|
1442
|
+
}
|
|
1443
|
+
hasActionMetadataChanges(existingAction, updateDto) {
|
|
1444
|
+
const relationFields = new Set(['module', 'model', 'view']);
|
|
1445
|
+
const jsonFields = new Set(['domain', 'context']);
|
|
1446
|
+
return this.actionComparableFields.some((key) => {
|
|
1447
|
+
const value = updateDto[key];
|
|
1448
|
+
if (typeof value === 'undefined') {
|
|
1449
|
+
return false;
|
|
1450
|
+
}
|
|
1451
|
+
if (relationFields.has(key)) {
|
|
1452
|
+
const relationValue = value;
|
|
1453
|
+
return existingAction[key]?.id !== relationValue?.id;
|
|
1454
|
+
}
|
|
1455
|
+
if (jsonFields.has(key)) {
|
|
1456
|
+
return this.getCanonicalJsonFieldString(existingAction[key]) !== this.getCanonicalJsonFieldString(value);
|
|
1457
|
+
}
|
|
1458
|
+
return existingAction[key] !== value;
|
|
1459
|
+
});
|
|
1460
|
+
}
|
|
1461
|
+
async upsertViewMetadataWithPreloadedExisting(viewRepo, existingViewsByName, updateDto) {
|
|
1462
|
+
const existingView = existingViewsByName.get(updateDto.name);
|
|
1463
|
+
if (existingView) {
|
|
1464
|
+
if (!this.hasViewMetadataChanges(existingView, updateDto)) {
|
|
1465
|
+
return { entity: existingView, outcome: 'skipped' };
|
|
1466
|
+
}
|
|
1467
|
+
const updatedView = { ...existingView, ...updateDto };
|
|
1468
|
+
const savedView = await this.timeOperation('view-save', () => viewRepo.save(updatedView), {
|
|
1469
|
+
component: 'views',
|
|
1470
|
+
serviceCall: 'viewRepo.save',
|
|
1471
|
+
details: `view=${updateDto.name}`,
|
|
1472
|
+
});
|
|
1473
|
+
existingViewsByName.set(updateDto.name, savedView);
|
|
1474
|
+
return { entity: savedView, outcome: 'updated' };
|
|
1475
|
+
}
|
|
1476
|
+
const view = viewRepo.create(updateDto);
|
|
1477
|
+
const savedView = await this.timeOperation('view-save', () => viewRepo.save(view), {
|
|
1478
|
+
component: 'views',
|
|
1479
|
+
serviceCall: 'viewRepo.save',
|
|
1480
|
+
details: `view=${updateDto.name}`,
|
|
1481
|
+
});
|
|
1482
|
+
existingViewsByName.set(updateDto.name, savedView);
|
|
1483
|
+
return { entity: savedView, outcome: 'created' };
|
|
1484
|
+
}
|
|
1485
|
+
async upsertActionMetadataWithPreloadedExisting(actionRepo, existingActionsByName, updateDto) {
|
|
1486
|
+
const existingAction = existingActionsByName.get(updateDto.name);
|
|
1487
|
+
if (existingAction) {
|
|
1488
|
+
if (!this.hasActionMetadataChanges(existingAction, updateDto)) {
|
|
1489
|
+
return { entity: existingAction, outcome: 'skipped' };
|
|
1490
|
+
}
|
|
1491
|
+
const updatedAction = { ...existingAction, ...updateDto };
|
|
1492
|
+
const savedAction = await this.timeOperation('action-save', () => actionRepo.save(updatedAction), {
|
|
1493
|
+
component: 'actions',
|
|
1494
|
+
serviceCall: 'actionRepo.save',
|
|
1495
|
+
details: `action=${updateDto.name}`,
|
|
1496
|
+
});
|
|
1497
|
+
existingActionsByName.set(updateDto.name, savedAction);
|
|
1498
|
+
return { entity: savedAction, outcome: 'updated' };
|
|
1499
|
+
}
|
|
1500
|
+
const action = actionRepo.create(updateDto);
|
|
1501
|
+
const savedAction = await this.timeOperation('action-save', () => actionRepo.save(action), {
|
|
1502
|
+
component: 'actions',
|
|
1503
|
+
serviceCall: 'actionRepo.save',
|
|
1504
|
+
details: `action=${updateDto.name}`,
|
|
1505
|
+
});
|
|
1506
|
+
existingActionsByName.set(updateDto.name, savedAction);
|
|
1507
|
+
return { entity: savedAction, outcome: 'created' };
|
|
1508
|
+
}
|
|
1509
|
+
async upsertFieldMetadataWithPreloadedExisting(fieldMetadataRepo, existingFieldsByName, updateDto) {
|
|
1510
|
+
const existingFieldMetadata = existingFieldsByName.get(updateDto.name);
|
|
1511
|
+
if (existingFieldMetadata) {
|
|
1512
|
+
const hasChanges = Object.entries(updateDto).some(([key, value]) => {
|
|
1513
|
+
const relationValue = value;
|
|
1514
|
+
if (key === 'model') {
|
|
1515
|
+
return existingFieldMetadata.model?.id !== relationValue?.id;
|
|
1516
|
+
}
|
|
1517
|
+
if (key === 'mediaStorageProvider') {
|
|
1518
|
+
return existingFieldMetadata.mediaStorageProvider?.id !== relationValue?.id;
|
|
1519
|
+
}
|
|
1520
|
+
const currentValue = existingFieldMetadata[key];
|
|
1521
|
+
if (Array.isArray(currentValue) || Array.isArray(value)) {
|
|
1522
|
+
return JSON.stringify(currentValue ?? null) !== JSON.stringify(value ?? null);
|
|
1523
|
+
}
|
|
1524
|
+
if (value && typeof value === 'object') {
|
|
1525
|
+
return JSON.stringify(currentValue ?? null) !== JSON.stringify(value ?? null);
|
|
1526
|
+
}
|
|
1527
|
+
return currentValue !== value;
|
|
1528
|
+
});
|
|
1529
|
+
if (!hasChanges) {
|
|
1530
|
+
return existingFieldMetadata;
|
|
1531
|
+
}
|
|
1532
|
+
const updatedFieldMetadata = { ...existingFieldMetadata, ...updateDto };
|
|
1533
|
+
const savedFieldMetadata = await fieldMetadataRepo.save(updatedFieldMetadata);
|
|
1534
|
+
existingFieldsByName.set(updateDto.name, savedFieldMetadata);
|
|
1535
|
+
return savedFieldMetadata;
|
|
1536
|
+
}
|
|
1537
|
+
const fieldMetadata = fieldMetadataRepo.create(updateDto);
|
|
1538
|
+
const savedFieldMetadata = await fieldMetadataRepo.save(fieldMetadata);
|
|
1539
|
+
existingFieldsByName.set(updateDto.name, savedFieldMetadata);
|
|
1540
|
+
return savedFieldMetadata;
|
|
1541
|
+
}
|
|
698
1542
|
async handleSeedSecurityRules(rulesDto) {
|
|
699
1543
|
if (!rulesDto || rulesDto.length === 0) {
|
|
700
1544
|
this.logger.debug(`No security rules found to seed`);
|
|
701
1545
|
return;
|
|
702
1546
|
}
|
|
703
1547
|
for (const dto of rulesDto) {
|
|
704
|
-
await this.securityRuleRepo.upsertWithDto({ ...dto, securityRuleConfig: JSON.stringify(dto.securityRuleConfig) })
|
|
1548
|
+
await this.timeOperation('security-rule-upsert', () => this.securityRuleRepo.upsertWithDto({ ...dto, securityRuleConfig: JSON.stringify(dto.securityRuleConfig) }), {
|
|
1549
|
+
component: 'security-rules',
|
|
1550
|
+
serviceCall: 'securityRuleRepo.upsertWithDto',
|
|
1551
|
+
details: `rule=${dto.name}`,
|
|
1552
|
+
});
|
|
705
1553
|
}
|
|
706
1554
|
}
|
|
707
1555
|
async handleSeedListOfValues(listOfValuesDto) {
|
|
@@ -711,8 +1559,16 @@ let ModuleMetadataSeederService = ModuleMetadataSeederService_1 = class ModuleMe
|
|
|
711
1559
|
}
|
|
712
1560
|
for (let j = 0; j < listOfValuesDto.length; j++) {
|
|
713
1561
|
const listOfValueDto = listOfValuesDto[j];
|
|
714
|
-
listOfValueDto['module'] = await this.
|
|
715
|
-
|
|
1562
|
+
listOfValueDto['module'] = await this.getModuleByUserKeyCached(listOfValueDto.moduleUserKey, {
|
|
1563
|
+
moduleName: listOfValueDto.moduleUserKey,
|
|
1564
|
+
component: 'list-of-values',
|
|
1565
|
+
details: `module=${listOfValueDto.moduleUserKey}`,
|
|
1566
|
+
});
|
|
1567
|
+
await this.timeOperation('lov-upsert', () => this.listOfValuesService.upsert(listOfValuesDto[j]), {
|
|
1568
|
+
component: 'list-of-values',
|
|
1569
|
+
serviceCall: 'listOfValuesService.upsert',
|
|
1570
|
+
details: `type=${listOfValueDto.type} value=${listOfValueDto.value}`,
|
|
1571
|
+
});
|
|
716
1572
|
}
|
|
717
1573
|
}
|
|
718
1574
|
async handleSeedScheduledJobs(createScheduledJobDto) {
|
|
@@ -721,7 +1577,11 @@ let ModuleMetadataSeederService = ModuleMetadataSeederService_1 = class ModuleMe
|
|
|
721
1577
|
return;
|
|
722
1578
|
}
|
|
723
1579
|
for (const dto of createScheduledJobDto) {
|
|
724
|
-
await this.scheduledJobRepository.upsertWithDto(dto)
|
|
1580
|
+
await this.timeOperation('scheduled-job-upsert', () => this.scheduledJobRepository.upsertWithDto(dto), {
|
|
1581
|
+
component: 'scheduled-jobs',
|
|
1582
|
+
serviceCall: 'scheduledJobRepository.upsertWithDto',
|
|
1583
|
+
details: `schedule=${dto.scheduleName}`,
|
|
1584
|
+
});
|
|
725
1585
|
}
|
|
726
1586
|
}
|
|
727
1587
|
async handleSeedSavedFilters(createSavedFilterDto) {
|
|
@@ -731,9 +1591,47 @@ let ModuleMetadataSeederService = ModuleMetadataSeederService_1 = class ModuleMe
|
|
|
731
1591
|
}
|
|
732
1592
|
for (const dto of createSavedFilterDto) {
|
|
733
1593
|
this.validateSavedFilterQueryJsonWrapper(dto);
|
|
734
|
-
await this.savedFiltersRepo.upsertWithDto({ ...dto, filterQueryJson: JSON.stringify(dto.filterQueryJson), isSeeded: true })
|
|
1594
|
+
await this.timeOperation('saved-filter-upsert', () => this.savedFiltersRepo.upsertWithDto({ ...dto, filterQueryJson: JSON.stringify(dto.filterQueryJson), isSeeded: true }), {
|
|
1595
|
+
component: 'saved-filters',
|
|
1596
|
+
serviceCall: 'savedFiltersRepo.upsertWithDto',
|
|
1597
|
+
details: `filter=${dto.name}`,
|
|
1598
|
+
});
|
|
735
1599
|
}
|
|
736
1600
|
}
|
|
1601
|
+
async handleSeedLocales(localesDto) {
|
|
1602
|
+
if (!localesDto || localesDto.length === 0) {
|
|
1603
|
+
this.logger.debug(`No locales found to seed`);
|
|
1604
|
+
return;
|
|
1605
|
+
}
|
|
1606
|
+
for (const dto of localesDto) {
|
|
1607
|
+
if (dto.isDefault) {
|
|
1608
|
+
const existingDefaultLocales = await this.localeRepo.find({
|
|
1609
|
+
where: {
|
|
1610
|
+
isDefault: true,
|
|
1611
|
+
},
|
|
1612
|
+
});
|
|
1613
|
+
for (const locale of existingDefaultLocales) {
|
|
1614
|
+
if (locale.locale !== dto.locale) {
|
|
1615
|
+
await this.localeRepo.save({
|
|
1616
|
+
...locale,
|
|
1617
|
+
isDefault: false,
|
|
1618
|
+
});
|
|
1619
|
+
}
|
|
1620
|
+
}
|
|
1621
|
+
}
|
|
1622
|
+
const existingLocale = await this.localeRepo.findOne({
|
|
1623
|
+
where: {
|
|
1624
|
+
locale: dto.locale,
|
|
1625
|
+
},
|
|
1626
|
+
});
|
|
1627
|
+
await this.localeRepo.save(this.localeRepo.create({
|
|
1628
|
+
...existingLocale,
|
|
1629
|
+
...dto,
|
|
1630
|
+
}));
|
|
1631
|
+
}
|
|
1632
|
+
const locales = await this.localeRepo.find();
|
|
1633
|
+
this.solidRegistry.registerlocales(locales);
|
|
1634
|
+
}
|
|
737
1635
|
validateSavedFilterQueryJsonWrapper(dto) {
|
|
738
1636
|
const filterName = dto?.name ?? '<unnamed>';
|
|
739
1637
|
const filterQueryJson = dto?.filterQueryJson;
|
|
@@ -755,7 +1653,11 @@ let ModuleMetadataSeederService = ModuleMetadataSeederService_1 = class ModuleMe
|
|
|
755
1653
|
return;
|
|
756
1654
|
}
|
|
757
1655
|
for (const dto of modelSequencesDto) {
|
|
758
|
-
await this.modelSequenceRepo.upsertWithDto(dto)
|
|
1656
|
+
await this.timeOperation('model-sequence-upsert', () => this.modelSequenceRepo.upsertWithDto(dto), {
|
|
1657
|
+
component: 'model-sequences',
|
|
1658
|
+
serviceCall: 'modelSequenceRepo.upsertWithDto',
|
|
1659
|
+
details: `sequence=${dto.sequenceName}`,
|
|
1660
|
+
});
|
|
759
1661
|
}
|
|
760
1662
|
}
|
|
761
1663
|
async pruneModelSequences(modelSequencesDto, moduleName) {
|
|
@@ -764,7 +1666,11 @@ let ModuleMetadataSeederService = ModuleMetadataSeederService_1 = class ModuleMe
|
|
|
764
1666
|
return 0;
|
|
765
1667
|
}
|
|
766
1668
|
const sequences = modelSequencesDto ?? [];
|
|
767
|
-
const module = await this.
|
|
1669
|
+
const module = await this.getModuleByUserKeyCached(moduleName, {
|
|
1670
|
+
moduleName,
|
|
1671
|
+
component: 'model-sequences',
|
|
1672
|
+
details: `module=${moduleName}`,
|
|
1673
|
+
});
|
|
768
1674
|
if (!module) {
|
|
769
1675
|
this.logger.warn(`Skipping model sequence prune: module not found for ${moduleName}.`);
|
|
770
1676
|
return 0;
|
|
@@ -798,7 +1704,11 @@ let ModuleMetadataSeederService = ModuleMetadataSeederService_1 = class ModuleMe
|
|
|
798
1704
|
return 0;
|
|
799
1705
|
}
|
|
800
1706
|
const savedFilters = savedFiltersDto ?? [];
|
|
801
|
-
const module = await this.
|
|
1707
|
+
const module = await this.getModuleByUserKeyCached(moduleName, {
|
|
1708
|
+
moduleName,
|
|
1709
|
+
component: 'saved-filters',
|
|
1710
|
+
details: `module=${moduleName}`,
|
|
1711
|
+
});
|
|
802
1712
|
if (!module) {
|
|
803
1713
|
this.logger.warn(`Skipping saved filters prune: module not found for ${moduleName}.`);
|
|
804
1714
|
return 0;
|
|
@@ -833,7 +1743,11 @@ let ModuleMetadataSeederService = ModuleMetadataSeederService_1 = class ModuleMe
|
|
|
833
1743
|
return 0;
|
|
834
1744
|
}
|
|
835
1745
|
const scheduledJobs = scheduledJobsDto ?? [];
|
|
836
|
-
const module = await this.
|
|
1746
|
+
const module = await this.getModuleByUserKeyCached(moduleName, {
|
|
1747
|
+
moduleName,
|
|
1748
|
+
component: 'scheduled-jobs',
|
|
1749
|
+
details: `module=${moduleName}`,
|
|
1750
|
+
});
|
|
837
1751
|
if (!module) {
|
|
838
1752
|
this.logger.warn(`Skipping scheduled jobs prune: module not found for ${moduleName}.`);
|
|
839
1753
|
return 0;
|
|
@@ -867,7 +1781,11 @@ let ModuleMetadataSeederService = ModuleMetadataSeederService_1 = class ModuleMe
|
|
|
867
1781
|
return 0;
|
|
868
1782
|
}
|
|
869
1783
|
const securityRules = securityRulesDto ?? [];
|
|
870
|
-
const module = await this.
|
|
1784
|
+
const module = await this.getModuleByUserKeyCached(moduleName, {
|
|
1785
|
+
moduleName,
|
|
1786
|
+
component: 'security-rules',
|
|
1787
|
+
details: `module=${moduleName}`,
|
|
1788
|
+
});
|
|
871
1789
|
if (!module) {
|
|
872
1790
|
this.logger.warn(`Skipping security rules prune: module not found for ${moduleName}.`);
|
|
873
1791
|
return 0;
|
|
@@ -902,7 +1820,11 @@ let ModuleMetadataSeederService = ModuleMetadataSeederService_1 = class ModuleMe
|
|
|
902
1820
|
return 0;
|
|
903
1821
|
}
|
|
904
1822
|
const listOfValues = listOfValuesDto ?? [];
|
|
905
|
-
const module = await this.
|
|
1823
|
+
const module = await this.getModuleByUserKeyCached(moduleName, {
|
|
1824
|
+
moduleName,
|
|
1825
|
+
component: 'list-of-values',
|
|
1826
|
+
details: `module=${moduleName}`,
|
|
1827
|
+
});
|
|
906
1828
|
if (!module) {
|
|
907
1829
|
this.logger.warn(`Skipping list of values prune: module not found for ${moduleName}.`);
|
|
908
1830
|
return 0;
|
|
@@ -944,7 +1866,11 @@ let ModuleMetadataSeederService = ModuleMetadataSeederService_1 = class ModuleMe
|
|
|
944
1866
|
return 0;
|
|
945
1867
|
}
|
|
946
1868
|
const menus = menusDto ?? [];
|
|
947
|
-
const module = await this.
|
|
1869
|
+
const module = await this.getModuleByUserKeyCached(moduleName, {
|
|
1870
|
+
moduleName,
|
|
1871
|
+
component: 'menus',
|
|
1872
|
+
details: `module=${moduleName}`,
|
|
1873
|
+
});
|
|
948
1874
|
if (!module) {
|
|
949
1875
|
this.logger.warn(`Skipping menus prune: module not found for ${moduleName}.`);
|
|
950
1876
|
return 0;
|
|
@@ -986,7 +1912,11 @@ let ModuleMetadataSeederService = ModuleMetadataSeederService_1 = class ModuleMe
|
|
|
986
1912
|
return 0;
|
|
987
1913
|
}
|
|
988
1914
|
const views = viewsDto ?? [];
|
|
989
|
-
const module = await this.
|
|
1915
|
+
const module = await this.getModuleByUserKeyCached(moduleName, {
|
|
1916
|
+
moduleName,
|
|
1917
|
+
component: 'views',
|
|
1918
|
+
details: `module=${moduleName}`,
|
|
1919
|
+
});
|
|
990
1920
|
if (!module) {
|
|
991
1921
|
this.logger.warn(`Skipping views prune: module not found for ${moduleName}.`);
|
|
992
1922
|
return 0;
|
|
@@ -1039,7 +1969,11 @@ let ModuleMetadataSeederService = ModuleMetadataSeederService_1 = class ModuleMe
|
|
|
1039
1969
|
return 0;
|
|
1040
1970
|
}
|
|
1041
1971
|
const actions = actionsDto ?? [];
|
|
1042
|
-
const module = await this.
|
|
1972
|
+
const module = await this.getModuleByUserKeyCached(moduleName, {
|
|
1973
|
+
moduleName,
|
|
1974
|
+
component: 'actions',
|
|
1975
|
+
details: `module=${moduleName}`,
|
|
1976
|
+
});
|
|
1043
1977
|
if (!module) {
|
|
1044
1978
|
this.logger.warn(`Skipping actions prune: module not found for ${moduleName}.`);
|
|
1045
1979
|
return 0;
|
|
@@ -1125,7 +2059,11 @@ let ModuleMetadataSeederService = ModuleMetadataSeederService_1 = class ModuleMe
|
|
|
1125
2059
|
return 0;
|
|
1126
2060
|
}
|
|
1127
2061
|
const models = modelsMetadata ?? [];
|
|
1128
|
-
const module = await this.
|
|
2062
|
+
const module = await this.getModuleByUserKeyCached(moduleName, {
|
|
2063
|
+
moduleName,
|
|
2064
|
+
component: 'module-model-fields',
|
|
2065
|
+
details: `module=${moduleName}`,
|
|
2066
|
+
});
|
|
1129
2067
|
if (!module) {
|
|
1130
2068
|
this.logger.warn(`Skipping models prune: module not found for ${moduleName}.`);
|
|
1131
2069
|
return 0;
|
|
@@ -1241,11 +2179,13 @@ exports.ModuleMetadataSeederService = ModuleMetadataSeederService = ModuleMetada
|
|
|
1241
2179
|
role_metadata_service_1.RoleMetadataService,
|
|
1242
2180
|
user_service_1.UserService,
|
|
1243
2181
|
authentication_service_1.AuthenticationService,
|
|
2182
|
+
api_key_service_1.ApiKeyService,
|
|
1244
2183
|
action_metadata_service_1.ActionMetadataService,
|
|
1245
2184
|
view_metadata_service_1.ViewMetadataService,
|
|
1246
2185
|
email_template_service_1.EmailTemplateService,
|
|
1247
2186
|
sms_template_service_1.SmsTemplateService,
|
|
1248
2187
|
list_of_values_service_1.ListOfValuesService,
|
|
2188
|
+
user_api_key_repository_1.UserApiKeyRepository,
|
|
1249
2189
|
permission_metadata_repository_1.PermissionMetadataRepository,
|
|
1250
2190
|
solid_registry_1.SolidRegistry,
|
|
1251
2191
|
setting_service_1.SettingService,
|
|
@@ -1255,6 +2195,7 @@ exports.ModuleMetadataSeederService = ModuleMetadataSeederService = ModuleMetada
|
|
|
1255
2195
|
scheduled_job_repository_1.ScheduledJobRepository,
|
|
1256
2196
|
saved_filters_repository_1.SavedFiltersRepository,
|
|
1257
2197
|
typeorm_1.DataSource,
|
|
1258
|
-
model_sequence_repository_1.ModelSequenceRepository
|
|
2198
|
+
model_sequence_repository_1.ModelSequenceRepository,
|
|
2199
|
+
locale_repository_1.LocaleRepository])
|
|
1259
2200
|
], ModuleMetadataSeederService);
|
|
1260
2201
|
//# sourceMappingURL=module-metadata-seeder.service.js.map
|