@reldens/cms 0.15.0 → 0.16.0

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/lib/installer.js CHANGED
@@ -35,6 +35,7 @@ class Installer
35
35
  this.moduleAdminTemplatesPath = FileHandler.joinPaths(this.moduleAdminPath, 'templates')
36
36
  this.indexTemplatePath = FileHandler.joinPaths(this.defaultTemplatesPath, 'index.js.dist');
37
37
  this.postInstallCallback = sc.get(props, 'postInstallCallback', false);
38
+ this.prismaClient = sc.get(props, 'prismaClient', false);
38
39
  this.entitiesLoader = new EntitiesLoader({projectRoot: this.projectRoot});
39
40
  }
40
41
 
@@ -49,17 +50,21 @@ class Installer
49
50
  Logger.error('Missing app on prepareSetup for Installer.');
50
51
  return false;
51
52
  }
53
+ if(!appServer){
54
+ Logger.error('Missing appServer on prepareSetup for Installer.');
55
+ return false;
56
+ }
52
57
  if(!appServerFactory){
53
58
  Logger.error('Missing appServerFactory on prepareSetup for Installer.');
54
59
  return false;
55
60
  }
56
61
  if(!renderEngine){
57
- Logger.error('Missing renderEngine for Installer.');
62
+ Logger.error('Missing renderEngine on prepareSetup for Installer.');
58
63
  return false;
59
64
  }
60
65
  this.app = app;
61
- this.appServerFactory = appServerFactory;
62
66
  this.appServer = appServer;
67
+ this.appServerFactory = appServerFactory;
63
68
  this.renderEngine = renderEngine;
64
69
  app.use('/install-assets', appServerFactory.applicationFramework.static(this.installerPath, {index: false}));
65
70
  app.use(appServerFactory.session({
@@ -117,7 +122,7 @@ class Installer
117
122
  'configuration-error': 'Configuration error while completing installation.',
118
123
  'already-installed': 'The application is already installed.'
119
124
  };
120
- return errorMessages[errorCode] || 'An unknown error occurred during installation.';
125
+ return sc.get(errorMessages, errorCode, 'An unknown error occurred during installation.');
121
126
  }
122
127
 
123
128
  async executeInstallProcess(req, res)
@@ -145,13 +150,8 @@ class Installer
145
150
  },
146
151
  debug: false
147
152
  };
148
- if('prisma' === selectedDriver){
149
- let generatedPrismaSchema = await this.generatePrismaSchema(dbConfig);
150
- if(!generatedPrismaSchema){
151
- Logger.error('Could not generated Prisma schema.');
152
- return res.redirect('/?error=prisma-schema-generation-error');
153
- }
154
- Logger.info('Generated Prisma schema.');
153
+ if('prisma' === selectedDriver && this.prismaClient){
154
+ dbConfig.prismaClient = this.prismaClient;
155
155
  }
156
156
  let dbDriver = new driverClass(dbConfig);
157
157
  if(!await dbDriver.connect()){
@@ -181,7 +181,7 @@ class Installer
181
181
  return res.redirect(redirectError);
182
182
  }
183
183
  }
184
- let entitiesGenerationResult = await this.generateEntities(dbDriver);
184
+ let entitiesGenerationResult = await this.generateEntities(dbDriver, false, true);
185
185
  if(!entitiesGenerationResult){
186
186
  Logger.error('Entities generation error.');
187
187
  return res.redirect('/?error=installation-entities-generation-failed');
@@ -214,7 +214,7 @@ class Installer
214
214
  if(successFileContent){
215
215
  successContent = this.renderEngine.render(
216
216
  successFileContent,
217
- {adminPath: templateVariables['app-admin-path'], currentYear: new Date().getFullYear()},
217
+ {adminPath: templateVariables['app-admin-path']},
218
218
  );
219
219
  }
220
220
  return res.send(successContent);
@@ -234,7 +234,8 @@ class Installer
234
234
  Logger.error('SQL file "'+fileName+'" not found.');
235
235
  return '/?error=sql-file-not-found&file-name='+fileName;
236
236
  }
237
- if(!await dbDriver.rawQuery(sqlFileContent)){
237
+ let queryExecutionResult = await dbDriver.rawQuery(sqlFileContent);
238
+ if(!queryExecutionResult){
238
239
  Logger.error('SQL file "'+fileName+'" raw execution failed.');
239
240
  return '/?error=sql-file-execution-error&file-name='+fileName;
240
241
  }
@@ -242,23 +243,32 @@ class Installer
242
243
  return '';
243
244
  }
244
245
 
245
- async generateEntities(server, isOverride = false)
246
+ async generateEntities(server, isOverride = false, isInstallationMode = false)
246
247
  {
247
248
  let driverType = sc.get(DriversClassMap, server.constructor.name, '');
248
249
  Logger.debug('Driver type detected: '+driverType+', Server constructor: '+server.constructor.name);
249
- if('prisma' === driverType){
250
+ if('prisma' === driverType && !isInstallationMode){
251
+ Logger.info('Running prisma introspect "npx prisma db pull"...');
250
252
  let dbConfig = this.extractDbConfigFromServer(server);
251
253
  Logger.debug('Extracted DB config:', dbConfig);
252
254
  if(dbConfig){
253
255
  let generatedPrismaSchema = await this.generatePrismaSchema(dbConfig);
254
256
  if(!generatedPrismaSchema){
255
- Logger.error('Could not generate Prisma schema for entities generation.');
257
+ Logger.error('Prisma schema generation failed.');
256
258
  return false;
257
259
  }
258
260
  Logger.info('Generated Prisma schema for entities generation.');
259
261
  }
260
262
  }
261
- let generator = new EntitiesGenerator({server, projectPath: this.projectRoot, isOverride});
263
+ let generatorConfig = {
264
+ server,
265
+ projectPath: this.projectRoot,
266
+ isOverride
267
+ };
268
+ if('prisma' === driverType && this.prismaClient){
269
+ generatorConfig.prismaClient = this.prismaClient;
270
+ }
271
+ let generator = new EntitiesGenerator(generatorConfig);
262
272
  let success = await generator.generate();
263
273
  if(!success){
264
274
  Logger.error('Entities generation failed.');
@@ -303,7 +313,8 @@ class Installer
303
313
  let generator = new PrismaSchemaGenerator({
304
314
  ...connectionData,
305
315
  dataProxy: useDataProxy,
306
- prismaSchemaPath: this.projectRoot+'/prisma'
316
+ clientOutputPath: FileHandler.joinPaths(this.projectRoot, 'prisma', 'client'),
317
+ prismaSchemaPath: FileHandler.joinPaths(this.projectRoot, 'prisma')
307
318
  });
308
319
  let success = await generator.generate();
309
320
  if(!success){
@@ -363,12 +374,22 @@ class Installer
363
374
  async createIndexJsFile(templateVariables)
364
375
  {
365
376
  if(!FileHandler.exists(this.indexTemplatePath)){
366
- Logger.error('Index.js template not found: '+this.indexTemplatePath);
377
+ Logger.error('Index.js template not found: ' + this.indexTemplatePath);
367
378
  return false;
368
379
  }
369
380
  let indexTemplate = FileHandler.readFile(this.indexTemplatePath);
370
381
  let driverKey = templateVariables['db-storage-driver'];
371
- let indexContent = this.renderEngine.render(indexTemplate, {driverKey});
382
+ let templateParams = {driverKey};
383
+ if('prisma' === driverKey){
384
+ let prismaClientPath = FileHandler.joinPaths(this.projectRoot, 'prisma', 'client');
385
+ templateParams.prismaClientImports = 'const { PrismaClient } = require(\'' + prismaClientPath + '\');';
386
+ templateParams.prismaClientParam = ',\n prismaClient: new PrismaClient()';
387
+ }
388
+ if('prisma' !== driverKey){
389
+ templateParams.prismaClientImports = '';
390
+ templateParams.prismaClientParam = '';
391
+ }
392
+ let indexContent = this.renderEngine.render(indexTemplate, templateParams);
372
393
  let indexFilePath = FileHandler.joinPaths(this.projectRoot, 'index.js');
373
394
  if(FileHandler.exists(indexFilePath)){
374
395
  Logger.info('Index.js file already exists, the CMS installer will not override the existent one.');
package/lib/manager.js CHANGED
@@ -14,6 +14,7 @@ const { TemplatesToPathMapper } = require('./templates-to-path-mapper');
14
14
  const { AdminEntitiesGenerator } = require('./admin-entities-generator');
15
15
  const { LoadedEntitiesProcessor } = require('./loaded-entities-processor');
16
16
  const { AdminManager } = require('./admin-manager');
17
+ const { CmsPagesRouteManager } = require('./cms-pages-route-manager');
17
18
  const { Installer } = require('./installer');
18
19
  const { Frontend } = require('./frontend');
19
20
  const { EventsManagerSingleton, Logger, sc } = require('@reldens/utils');
@@ -47,6 +48,7 @@ class Manager
47
48
  this.mimeTypes = sc.get(props, 'mimeTypes', MimeTypes);
48
49
  this.allowedExtensions = sc.get(props, 'allowedExtensions', AllowedExtensions)
49
50
  this.adminRoleId = sc.get(props, 'adminRoleId', 99);
51
+ this.mappedAdminTemplates = TemplatesToPathMapper.map(this.adminTemplatesList, this.projectAdminTemplatesPath);
50
52
  this.stylesFilePath = sc.get(props, 'stylesFilePath', '/css/reldens-admin-client.css');
51
53
  this.scriptsFilePath = sc.get(props, 'scriptsFilePath', '/js/reldens-admin-client.js');
52
54
  this.companyName = sc.get(props, 'companyName', 'Reldens - CMS');
@@ -62,16 +64,22 @@ class Manager
62
64
  this.adminManager = sc.get(props, 'adminManager', false);
63
65
  this.frontend = sc.get(props, 'frontend', false);
64
66
  this.renderEngine = sc.get(props, 'renderEngine', mustache);
67
+ this.prismaClient = sc.get(props, 'prismaClient', false);
65
68
  this.appServerFactory = new AppServerFactory();
66
69
  this.adminEntitiesGenerator = new AdminEntitiesGenerator();
67
70
  this.installer = new Installer({
68
71
  projectRoot: this.projectRoot,
72
+ prismaClient: this.prismaClient,
69
73
  postInstallCallback: this.initializeCmsAfterInstall.bind(this)
70
74
  });
71
75
  this.useProvidedServer = this.validateProvidedServer();
72
76
  this.useProvidedDataServer = this.validateProvidedDataServer();
73
77
  this.useProvidedAdminManager = this.validateProvidedAdminManager();
74
78
  this.useProvidedFrontend = this.validateProvidedFrontend();
79
+ this.cmsPagesRouteManager = new CmsPagesRouteManager({
80
+ dataServer: this.dataServer,
81
+ events: this.events
82
+ });
75
83
  }
76
84
 
77
85
  validateProvidedServer()
@@ -206,8 +214,10 @@ class Manager
206
214
 
207
215
  async initializeServices()
208
216
  {
217
+ this.events.emit('reldens.cmsManagerInitializeServices', {manager: this});
209
218
  if(!this.useProvidedDataServer){
210
219
  if(!await this.initializeDataServer()){
220
+ Logger.debug('Initialize Data Server failed.');
211
221
  return false;
212
222
  }
213
223
  }
@@ -215,32 +225,41 @@ class Manager
215
225
  await this.setupEntityAccess();
216
226
  }
217
227
  if(!this.loadProcessedEntities()){
228
+ Logger.debug('Load Processed Entities for Entities failed.');
218
229
  return false;
219
230
  }
220
231
  if(!await this.generateAdminEntities()){
232
+ Logger.debug('Generate Admin Entities for Entities failed.');
221
233
  return false;
222
234
  }
223
235
  if(!this.useProvidedAdminManager){
224
236
  if(!await this.initializeAdminManager()){
237
+ Logger.debug('Initialize Admin Manager failed.');
225
238
  return false;
226
239
  }
227
240
  }
241
+ if(!await this.initializeCmsPagesRouteManager()){
242
+ Logger.debug('Initialize CMS Pages Route Manager failed.');
243
+ return false;
244
+ }
228
245
  if(!this.useProvidedFrontend){
229
246
  if(!await this.initializeFrontend()){
247
+ Logger.debug('Initialize Frontend failed.');
230
248
  return false;
231
249
  }
232
250
  }
233
251
  if(!this.useProvidedServer){
234
252
  await this.appServer.listen(this.config.port);
235
253
  }
254
+ Logger.debug('Initialize Services successfully.');
236
255
  return true;
237
256
  }
238
257
 
239
258
  async setupEntityAccess()
240
259
  {
241
- let accessEntity = this.dataServer.getEntity('cmsEntityAccess');
260
+ let accessEntity = this.dataServer.getEntity('entitiesAccess');
242
261
  if(!accessEntity){
243
- Logger.warning('Entity access control table not found.');
262
+ Logger.warning('Entities Access not found.');
244
263
  return;
245
264
  }
246
265
  for(let entityName of Object.keys(this.entityAccess)){
@@ -305,12 +324,15 @@ class Manager
305
324
  },
306
325
  rawEntities: this.rawRegisteredEntities
307
326
  };
308
- let DriverClass = DriversMap[this.config.database.driver];
309
- if(!DriverClass){
327
+ let driverClass = DriversMap[this.config.database.driver];
328
+ if(!driverClass){
310
329
  Logger.critical('Invalid database driver: '+this.config.database.driver);
311
330
  return false;
312
331
  }
313
- this.dataServer = new DriverClass(dbConfig);
332
+ if('prisma' === this.config.database.driver && this.prismaClient){
333
+ dbConfig.prismaClient = this.prismaClient;
334
+ }
335
+ this.dataServer = new driverClass(dbConfig);
314
336
  if(!await this.dataServer.connect()){
315
337
  Logger.critical('Failed to connect to database.');
316
338
  return false;
@@ -347,6 +369,14 @@ class Manager
347
369
  return passwordResult;
348
370
  };
349
371
  }
372
+ let adminFilesContents = await AdminTemplatesLoader.fetchAdminFilesContents(this.mappedAdminTemplates);
373
+ let translations = AdminTranslations.appendTranslations(this.entitiesTranslations || {});
374
+ this.events.emit('reldens.manager.initializeAdminManager', {
375
+ manager: this,
376
+ authenticationCallback,
377
+ adminFilesContents,
378
+ translations
379
+ });
350
380
  let adminConfig = {
351
381
  events: this.events,
352
382
  dataServer: this.dataServer,
@@ -358,10 +388,8 @@ class Manager
358
388
  renderCallback: this.renderCallback.bind(this),
359
389
  secret: this.config.adminSecret,
360
390
  rootPath: this.config.adminPath,
361
- translations: AdminTranslations.appendTranslations(this.entitiesTranslations || {}),
362
- adminFilesContents: await AdminTemplatesLoader.fetchAdminFilesContents(
363
- TemplatesToPathMapper.map(this.adminTemplatesList, this.projectAdminTemplatesPath)
364
- ),
391
+ translations: translations,
392
+ adminFilesContents,
365
393
  mimeTypes: this.mimeTypes,
366
394
  allowedExtensions: this.allowedExtensions,
367
395
  adminRoleId: this.adminRoleId,
@@ -381,6 +409,17 @@ class Manager
381
409
  return true;
382
410
  }
383
411
 
412
+ async initializeCmsPagesRouteManager()
413
+ {
414
+ if(!this.dataServer){
415
+ Logger.warning('CmsPagesRouteManager initialization skipped - missing dataServer.');
416
+ return false;
417
+ }
418
+ this.cmsPagesRouteManager.dataServer = this.dataServer;
419
+ Logger.debug('CmsPagesRouteManager initialized successfully');
420
+ return true;
421
+ }
422
+
384
423
  async renderCallback(template, params = {})
385
424
  {
386
425
  if(!template){