@solidxai/core 0.1.11-beta.0 → 0.1.11-beta.2

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