@solidstarters/solid-core 1.2.97 → 1.2.99

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 (146) hide show
  1. package/dist/controllers/action-metadata.controller.js +1 -1
  2. package/dist/controllers/action-metadata.controller.js.map +1 -1
  3. package/dist/controllers/export-template.controller.js +1 -1
  4. package/dist/controllers/export-template.controller.js.map +1 -1
  5. package/dist/controllers/export-transaction.controller.js +1 -1
  6. package/dist/controllers/export-transaction.controller.js.map +1 -1
  7. package/dist/controllers/menu-item-metadata.controller.js +1 -1
  8. package/dist/controllers/menu-item-metadata.controller.js.map +1 -1
  9. package/dist/controllers/permission-metadata.controller.js +1 -1
  10. package/dist/controllers/permission-metadata.controller.js.map +1 -1
  11. package/dist/controllers/role-metadata.controller.js +1 -1
  12. package/dist/controllers/role-metadata.controller.js.map +1 -1
  13. package/dist/controllers/service.controller.d.ts +4 -0
  14. package/dist/controllers/service.controller.d.ts.map +1 -1
  15. package/dist/controllers/service.controller.js +30 -2
  16. package/dist/controllers/service.controller.js.map +1 -1
  17. package/dist/controllers/setting.controller.d.ts +1 -1
  18. package/dist/controllers/setting.controller.d.ts.map +1 -1
  19. package/dist/controllers/setting.controller.js +6 -4
  20. package/dist/controllers/setting.controller.js.map +1 -1
  21. package/dist/controllers/test.controller.d.ts +0 -3
  22. package/dist/controllers/test.controller.d.ts.map +1 -1
  23. package/dist/controllers/test.controller.js +0 -24
  24. package/dist/controllers/test.controller.js.map +1 -1
  25. package/dist/controllers/user.controller.js +1 -1
  26. package/dist/controllers/user.controller.js.map +1 -1
  27. package/dist/controllers/view-metadata.controller.js +1 -1
  28. package/dist/controllers/view-metadata.controller.js.map +1 -1
  29. package/dist/dtos/update-settings.dto.d.ts.map +1 -1
  30. package/dist/dtos/update-settings.dto.js +1 -2
  31. package/dist/dtos/update-settings.dto.js.map +1 -1
  32. package/dist/entities/common.entity.d.ts +3 -0
  33. package/dist/entities/common.entity.d.ts.map +1 -1
  34. package/dist/entities/common.entity.js +9 -1
  35. package/dist/entities/common.entity.js.map +1 -1
  36. package/dist/entities/menu-item-metadata.entity.js +1 -1
  37. package/dist/entities/menu-item-metadata.entity.js.map +1 -1
  38. package/dist/helpers/field-crud-managers/PasswordFieldCrudManager.d.ts +1 -0
  39. package/dist/helpers/field-crud-managers/PasswordFieldCrudManager.d.ts.map +1 -1
  40. package/dist/helpers/field-crud-managers/PasswordFieldCrudManager.js +3 -1
  41. package/dist/helpers/field-crud-managers/PasswordFieldCrudManager.js.map +1 -1
  42. package/dist/helpers/model-metadata-helper.service.d.ts +8 -0
  43. package/dist/helpers/model-metadata-helper.service.d.ts.map +1 -0
  44. package/dist/helpers/model-metadata-helper.service.js +118 -0
  45. package/dist/helpers/model-metadata-helper.service.js.map +1 -0
  46. package/dist/helpers/schematic.service.d.ts +4 -1
  47. package/dist/helpers/schematic.service.d.ts.map +1 -1
  48. package/dist/helpers/schematic.service.js +8 -10
  49. package/dist/helpers/schematic.service.js.map +1 -1
  50. package/dist/helpers/solid-registry.d.ts +3 -1
  51. package/dist/helpers/solid-registry.d.ts.map +1 -1
  52. package/dist/helpers/solid-registry.js +4 -0
  53. package/dist/helpers/solid-registry.js.map +1 -1
  54. package/dist/index.d.ts +2 -2
  55. package/dist/index.d.ts.map +1 -1
  56. package/dist/index.js +7 -2
  57. package/dist/index.js.map +1 -1
  58. package/dist/interfaces.d.ts +3 -6
  59. package/dist/interfaces.d.ts.map +1 -1
  60. package/dist/seeders/module-metadata-seeder.service.d.ts.map +1 -1
  61. package/dist/seeders/module-metadata-seeder.service.js +1 -1
  62. package/dist/seeders/module-metadata-seeder.service.js.map +1 -1
  63. package/dist/seeders/system-fields-seeder.service.d.ts +13 -0
  64. package/dist/seeders/system-fields-seeder.service.d.ts.map +1 -0
  65. package/dist/seeders/system-fields-seeder.service.js +56 -0
  66. package/dist/seeders/system-fields-seeder.service.js.map +1 -0
  67. package/dist/services/authentication.service.js +4 -4
  68. package/dist/services/authentication.service.js.map +1 -1
  69. package/dist/services/computed-fields/concat-computed-field-provider.service.d.ts.map +1 -1
  70. package/dist/services/computed-fields/concat-computed-field-provider.service.js +3 -0
  71. package/dist/services/computed-fields/concat-computed-field-provider.service.js.map +1 -1
  72. package/dist/services/crud.service.d.ts +1 -1
  73. package/dist/services/crud.service.d.ts.map +1 -1
  74. package/dist/services/crud.service.js +7 -6
  75. package/dist/services/crud.service.js.map +1 -1
  76. package/dist/services/model-metadata.service.d.ts.map +1 -1
  77. package/dist/services/model-metadata.service.js +3 -0
  78. package/dist/services/model-metadata.service.js.map +1 -1
  79. package/dist/services/module-metadata.service.d.ts.map +1 -1
  80. package/dist/services/module-metadata.service.js +25 -2
  81. package/dist/services/module-metadata.service.js.map +1 -1
  82. package/dist/services/setting.service.d.ts +1 -1
  83. package/dist/services/setting.service.d.ts.map +1 -1
  84. package/dist/services/setting.service.js +27 -1
  85. package/dist/services/setting.service.js.map +1 -1
  86. package/dist/solid-core.module.d.ts.map +1 -1
  87. package/dist/solid-core.module.js +8 -2
  88. package/dist/solid-core.module.js.map +1 -1
  89. package/dist/subscribers/audit.subscriber.d.ts +4 -5
  90. package/dist/subscribers/audit.subscriber.d.ts.map +1 -1
  91. package/dist/subscribers/audit.subscriber.js +12 -12
  92. package/dist/subscribers/audit.subscriber.js.map +1 -1
  93. package/dist/subscribers/created-by-updated-by.subscriber.d.ts +12 -0
  94. package/dist/subscribers/created-by-updated-by.subscriber.d.ts.map +1 -0
  95. package/dist/subscribers/created-by-updated-by.subscriber.js +67 -0
  96. package/dist/subscribers/created-by-updated-by.subscriber.js.map +1 -0
  97. package/dist/subscribers/model.subscriber.d.ts +4 -1
  98. package/dist/subscribers/model.subscriber.d.ts.map +1 -1
  99. package/dist/subscribers/model.subscriber.js +20 -67
  100. package/dist/subscribers/model.subscriber.js.map +1 -1
  101. package/dist/subscribers/{softDeleteAwareEventSubscriber.subscriber.d.ts → soft-delete-aware-event.subscriber.d.ts} +1 -1
  102. package/dist/subscribers/soft-delete-aware-event.subscriber.d.ts.map +1 -0
  103. package/dist/subscribers/{softDeleteAwareEventSubscriber.subscriber.js → soft-delete-aware-event.subscriber.js} +1 -1
  104. package/dist/subscribers/soft-delete-aware-event.subscriber.js.map +1 -0
  105. package/dist/subscribers/view-metadata.subscriber.d.ts.map +1 -1
  106. package/dist/subscribers/view-metadata.subscriber.js +16 -14
  107. package/dist/subscribers/view-metadata.subscriber.js.map +1 -1
  108. package/dist/tsconfig.tsbuildinfo +1 -1
  109. package/package.json +1 -1
  110. package/src/controllers/action-metadata.controller.ts +1 -1
  111. package/src/controllers/export-template.controller.ts +1 -1
  112. package/src/controllers/export-transaction.controller.ts +1 -1
  113. package/src/controllers/menu-item-metadata.controller.ts +1 -1
  114. package/src/controllers/permission-metadata.controller.ts +1 -1
  115. package/src/controllers/role-metadata.controller.ts +1 -1
  116. package/src/controllers/service.controller.ts +20 -1
  117. package/src/controllers/setting.controller.ts +4 -3
  118. package/src/controllers/test.controller.ts +16 -16
  119. package/src/controllers/user.controller.ts +1 -1
  120. package/src/controllers/view-metadata.controller.ts +1 -1
  121. package/src/dtos/update-settings.dto.ts +2 -3
  122. package/src/entities/common.entity.ts +8 -2
  123. package/src/entities/menu-item-metadata.entity.ts +1 -1
  124. package/src/helpers/field-crud-managers/PasswordFieldCrudManager.ts +5 -1
  125. package/src/helpers/model-metadata-helper.service.ts +109 -0
  126. package/src/helpers/schematic.service.ts +10 -11
  127. package/src/helpers/solid-registry.ts +6 -1
  128. package/src/index.ts +2 -2
  129. package/src/interfaces.ts +3 -3
  130. package/src/seeders/module-metadata-seeder.service.ts +3 -1
  131. package/src/seeders/system-fields-seeder.service.ts +53 -0
  132. package/src/services/authentication.service.ts +4 -4
  133. package/src/services/computed-fields/concat-computed-field-provider.service.ts +3 -0
  134. package/src/services/crud.service.ts +7 -6
  135. package/src/services/model-metadata.service.ts +17 -15
  136. package/src/services/module-metadata.service.ts +28 -4
  137. package/src/services/setting.service.ts +30 -1
  138. package/src/solid-core.module.ts +8 -1
  139. package/src/subscribers/audit.subscriber.ts +10 -11
  140. package/src/subscribers/created-by-updated-by.subscriber.ts +54 -0
  141. package/src/subscribers/model.subscriber.ts +16 -70
  142. package/src/subscribers/view-metadata.subscriber.ts +19 -15
  143. package/dist/subscribers/softDeleteAwareEventSubscriber.subscriber.d.ts.map +0 -1
  144. package/dist/subscribers/softDeleteAwareEventSubscriber.subscriber.js.map +0 -1
  145. package/src/services/pending_import_issues +0 -3
  146. /package/src/subscribers/{softDeleteAwareEventSubscriber.subscriber.ts → soft-delete-aware-event.subscriber.ts} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solidstarters/solid-core",
3
- "version": "1.2.97",
3
+ "version": "1.2.99",
4
4
  "description": "This module is a NestJS module containing all the required core providers required by a Solid application",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -7,7 +7,7 @@ import { UpdateActionMetadataDto } from '../dtos/update-action-metadata.dto';
7
7
  import { SolidRequestContextDto } from 'src/dtos/solid-request-context.dto';
8
8
  import { SolidRequestContextDecorator } from 'src/decorators/solid-request-context.decorator';
9
9
 
10
- @ApiTags('App')
10
+ @ApiTags('App Builder')
11
11
  @Controller('action-metadata') //FIXME: Change this to the model plural name
12
12
  export class ActionMetadataController {
13
13
  constructor(private readonly service: ActionMetadataService) { }
@@ -7,7 +7,7 @@ import { UpdateExportTemplateDto } from '../dtos/update-export-template.dto';
7
7
  import { Response } from 'express';
8
8
  import { StartExportSyncDto } from 'src/dtos/export.dto';
9
9
 
10
- @ApiTags('Solid')
10
+ @ApiTags('Solid Core')
11
11
  @Controller('export-template') //FIXME: Change this to the model plural name
12
12
  export class ExportTemplateController {
13
13
  constructor(private readonly service: ExportTemplateService) {}
@@ -5,7 +5,7 @@ import { ExportTransactionService } from '../services/export-transaction.service
5
5
  import { CreateExportTransactionDto } from '../dtos/create-export-transaction.dto';
6
6
  import { UpdateExportTransactionDto } from '../dtos/update-export-transaction.dto';
7
7
 
8
- @ApiTags('Solid')
8
+ @ApiTags('Solid Core')
9
9
  @Controller('export-transaction') //FIXME: Change this to the model plural name
10
10
  export class ExportTransactionController {
11
11
  constructor(private readonly service: ExportTransactionService) {}
@@ -9,7 +9,7 @@ import { ActiveUserData } from 'src/interfaces/active-user-data.interface';
9
9
  import { SolidRequestContextDto } from 'src/dtos/solid-request-context.dto';
10
10
  import { SolidRequestContextDecorator } from 'src/decorators/solid-request-context.decorator';
11
11
 
12
- @ApiTags('App')
12
+ @ApiTags('App Builder')
13
13
  @Controller('menu-item-metadata') //FIXME: Change this to the model plural name
14
14
  export class MenuItemMetadataController {
15
15
  constructor(private readonly service: MenuItemMetadataService) { }
@@ -7,7 +7,7 @@ import { UpdatePermissionMetadataDto } from '../dtos/update-permission-metadata.
7
7
  import { SolidRequestContextDto } from 'src/dtos/solid-request-context.dto';
8
8
  import { SolidRequestContextDecorator } from 'src/decorators/solid-request-context.decorator';
9
9
 
10
- @ApiTags('Solid')
10
+ @ApiTags('Solid Core')
11
11
  @Controller('permission-metadata') //FIXME: Change this to the model plural name
12
12
  export class PermissionMetadataController {
13
13
  constructor(private readonly service: PermissionMetadataService) { }
@@ -7,7 +7,7 @@ import { UpdateRoleMetadataDto } from '../dtos/update-role-metadata.dto';
7
7
  import { SolidRequestContextDto } from 'src/dtos/solid-request-context.dto';
8
8
  import { SolidRequestContextDecorator } from 'src/decorators/solid-request-context.decorator';
9
9
 
10
- @ApiTags('Solid')
10
+ @ApiTags('Solid Core')
11
11
  @Controller('role-metadata') //FIXME: Change this to the model plural name
12
12
  export class RoleMetadataController {
13
13
  constructor(private readonly service: RoleMetadataService) {}
@@ -1,4 +1,4 @@
1
- import { Controller, Get } from '@nestjs/common';
1
+ import { Body, Controller, Get, Logger, Post } from '@nestjs/common';
2
2
  import { DiscoveryService, MetadataScanner, Reflector } from '@nestjs/core';
3
3
  import { Public } from 'src/decorators/public.decorator';
4
4
  import { SolidRegistry } from '../helpers/solid-registry';
@@ -8,6 +8,8 @@ import { ApiTags } from '@nestjs/swagger';
8
8
  @Controller('')
9
9
  @ApiTags("Common")
10
10
  export class ServiceController {
11
+ private readonly logger = new Logger(ServiceController.name);
12
+
11
13
  constructor(
12
14
  private readonly solidRegistry: SolidRegistry,
13
15
  ) { }
@@ -18,6 +20,23 @@ export class ServiceController {
18
20
  return { pong: 'v1.0.2' };
19
21
  }
20
22
 
23
+ @Public()
24
+ @Post('seed')
25
+ async seedData(@Body() seedData: any) {
26
+ const seeder = this.solidRegistry
27
+ .getSeeders()
28
+ .filter((seeder) => seeder.name === seedData.seeder)
29
+ .map((seeder) => seeder.instance)
30
+ .pop();
31
+ if (!seeder) {
32
+ this.logger.error(`Seeder service ${seedData.seeder} not found. Does your service have a seed() method?`);
33
+ return;
34
+ }
35
+ this.logger.log(`Running the seed() method for seeder :${seeder.constructor.name}`);
36
+ await seeder.seed();
37
+ return { message: `seed data for ${seedData.seeder}` };
38
+ }
39
+
21
40
  // @Public()
22
41
  // @Get('play')
23
42
  // play() {
@@ -8,7 +8,7 @@ import { SolidRequestContextDecorator } from 'src/decorators/solid-request-conte
8
8
  import { SolidRequestContextDto } from 'src/dtos/solid-request-context.dto';
9
9
  import { UpdateSettingsDto } from 'src/dtos/update-settings.dto';
10
10
 
11
- @ApiTags('Solid')
11
+ @ApiTags('Solid Core')
12
12
  @Controller('setting') //FIXME: Change this to the model plural name
13
13
  export class SettingController {
14
14
  constructor(private readonly service: SettingService) {}
@@ -88,7 +88,8 @@ export class SettingController {
88
88
 
89
89
  @ApiBearerAuth("jwt")
90
90
  @Post('/bulk-update')
91
- async updateSettings(@Body() updateSettingsDto: UpdateSettingsDto) {
92
- return this.service.updateSettings(updateSettingsDto.settings);
91
+ @UseInterceptors(AnyFilesInterceptor())
92
+ async updateSettings(@Body() updateSettingsDto: UpdateSettingsDto, @UploadedFiles() files: Array<Express.Multer.File>) {
93
+ return this.service.updateSettings(updateSettingsDto.settings, files);
93
94
  }
94
95
  }
@@ -34,21 +34,21 @@ export class TestController {
34
34
  return { filename: file.originalname };
35
35
  }
36
36
 
37
- @Public()
38
- @Post('seed')
39
- async seedData(@Body() seedData: any) {
40
- const seeder = this.solidRegistry
41
- .getSeeders()
42
- .filter((seeder) => seeder.name === seedData.seeder)
43
- .map((seeder) => seeder.instance)
44
- .pop();
45
- if (!seeder) {
46
- this.logger.error(`Seeder service ${seedData.seeder} not found. Does your service have a seed() method?`);
47
- return;
48
- }
49
- this.logger.log(`Running the seed() method for seeder :${seeder.constructor.name}`);
50
- await seeder.seed();
51
- return { message: `seed data for ${seedData.seeder}` };
52
- }
37
+ // @Public()
38
+ // @Post('seed')
39
+ // async seedData(@Body() seedData: any) {
40
+ // const seeder = this.solidRegistry
41
+ // .getSeeders()
42
+ // .filter((seeder) => seeder.name === seedData.seeder)
43
+ // .map((seeder) => seeder.instance)
44
+ // .pop();
45
+ // if (!seeder) {
46
+ // this.logger.error(`Seeder service ${seedData.seeder} not found. Does your service have a seed() method?`);
47
+ // return;
48
+ // }
49
+ // this.logger.log(`Running the seed() method for seeder :${seeder.constructor.name}`);
50
+ // await seeder.seed();
51
+ // return { message: `seed data for ${seedData.seeder}` };
52
+ // }
53
53
 
54
54
  }
@@ -11,7 +11,7 @@ import { ActiveUserData } from '../interfaces/active-user-data.interface';
11
11
  import { SolidRequestContextDecorator } from 'src/decorators/solid-request-context.decorator';
12
12
  import { SolidRequestContextDto } from 'src/dtos/solid-request-context.dto';
13
13
 
14
- @ApiTags('Solid')
14
+ @ApiTags('Solid Core')
15
15
  @Controller('user') //FIXME: Change this to the model plural name
16
16
  export class UserController {
17
17
  constructor(private readonly service: UserService) { }
@@ -9,7 +9,7 @@ import { SolidRequestContextDto } from 'src/dtos/solid-request-context.dto';
9
9
  import { ActiveUser } from 'src/decorators/active-user.decorator';
10
10
  import { ActiveUserData } from 'src/interfaces/active-user-data.interface';
11
11
 
12
- @ApiTags('App')
12
+ @ApiTags('App Builder')
13
13
  @Controller('view-metadata') //FIXME: Change this to the model plural name
14
14
  export class ViewMetadataController {
15
15
  constructor(private readonly service: ViewMetadataService) { }
@@ -1,7 +1,6 @@
1
- import { IsNotEmpty, IsObject } from 'class-validator';
1
+ import { IsObject, IsOptional } from 'class-validator';
2
2
 
3
3
  export class UpdateSettingsDto {
4
- @IsObject()
5
- @IsNotEmpty()
4
+ @IsOptional()
6
5
  settings: Record<string, any>;
7
6
  }
@@ -1,5 +1,5 @@
1
- import { PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn, DeleteDateColumn, Index, ManyToOne, JoinColumn } from "typeorm"
2
- import { Locale } from "./locale.entity";
1
+ import { Column, CreateDateColumn, DeleteDateColumn, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn } from "typeorm";
2
+ import type { User } from "./user.entity";
3
3
 
4
4
  export abstract class CommonEntity {
5
5
  @PrimaryGeneratedColumn({ type: 'integer' })
@@ -25,4 +25,10 @@ export abstract class CommonEntity {
25
25
 
26
26
  @Column({ type: "int", name: 'default_entity_locale_id', default: null })
27
27
  defaultEntityLocaleId: number;
28
+
29
+ @ManyToOne(() => require('./user.entity').User?.default ?? require('./user.entity').User, { nullable: true })
30
+ createdBy: User;
31
+
32
+ @ManyToOne(() => require('./user.entity').User?.default ?? require('./user.entity').User, { nullable: true })
33
+ updatedBy: User;
28
34
  }
@@ -23,7 +23,7 @@ export class MenuItemMetadata extends CommonEntity {
23
23
  @ManyToOne(() => ActionMetadata, { onDelete: "CASCADE", nullable: true })
24
24
  @JoinColumn({ referencedColumnName: 'id' })
25
25
  action: ActionMetadata;
26
- @ManyToMany(() => RoleMetadata, roleMetadata => roleMetadata.users, { cascade: true })
26
+ @ManyToMany(() => RoleMetadata, roleMetadata => roleMetadata.menuItems, { cascade: true })
27
27
  @JoinTable()
28
28
  roles: RoleMetadata[];
29
29
  @Column({ name: "sequence_number", type: "int", nullable: true })
@@ -9,6 +9,7 @@ export interface PasswordFieldOptions {
9
9
  required: boolean | undefined | null;
10
10
  regexPattern: string | undefined | null;
11
11
  fieldName: string | undefined | null;
12
+ isUpdate: Boolean;
12
13
  }
13
14
 
14
15
  export class PasswordFieldCrudManager implements FieldCrudManager {
@@ -24,7 +25,10 @@ export class PasswordFieldCrudManager implements FieldCrudManager {
24
25
 
25
26
  private applyValidations(fieldValue: any, dto: any): ValidationError[] {
26
27
  const errors: ValidationError[] = [];
27
- this.isApplyRequiredValidation() && isEmpty(fieldValue) ? errors.push({ field: this.options.fieldName, error: `Field: ${this.options.fieldName} is required` }): "no errors";
28
+ if (!this.options?.isUpdate && this.isApplyRequiredValidation() && isEmpty(fieldValue)) {
29
+ errors.push({ field: this.options.fieldName, error: `Field: ${this.options.fieldName} is required` });
30
+ }
31
+ // this.isApplyRequiredValidation() && isEmpty(fieldValue) ? errors.push({ field: this.options.fieldName, error: `Field: ${this.options.fieldName} is required` }): "no errors";
28
32
  if (isNotEmpty(fieldValue)) {
29
33
  errors.push(...this.applyFormatValidations(fieldValue, dto));
30
34
  }
@@ -0,0 +1,109 @@
1
+ // Return the system fields metadata for a model
2
+
3
+ import { Injectable, Logger } from "@nestjs/common";
4
+ import { SolidRegistry } from "./solid-registry";
5
+ import { In } from "typeorm";
6
+
7
+ @Injectable()
8
+ export class ModelMetadataHelperService {
9
+ private readonly logger = new Logger(ModelMetadataHelperService.name);
10
+
11
+ constructor(private readonly registry: SolidRegistry) {
12
+ }
13
+
14
+ getSystemFieldsMetadata(): any[] {
15
+ const systemFieldsMetadata = [
16
+ {
17
+ name: "id",
18
+ displayName: "Id",
19
+ type: "int",
20
+ ormType: "bigint",
21
+ isSystem: true,
22
+ },
23
+ {
24
+ name: "createdAt",
25
+ displayName: "Created At",
26
+ type: "datetime",
27
+ ormType: "timestamp",
28
+ isSystem: true,
29
+ },
30
+ {
31
+ name: "updatedAt",
32
+ displayName: "Updated At",
33
+ type: "datetime",
34
+ ormType: "timestamp",
35
+ isSystem: true,
36
+ },
37
+ {
38
+ name: "deletedAt",
39
+ displayName: "Deleted At",
40
+ type: "datetime",
41
+ ormType: "timestamp",
42
+ isSystem: true,
43
+ },
44
+ {
45
+ name: "deletedTracker",
46
+ displayName: "Deleted Tracker",
47
+ type: "shortText",
48
+ ormType: "varchar",
49
+ isSystem: true,
50
+ },
51
+ {
52
+ name: "publishedAt",
53
+ displayName: "Published At",
54
+ type: "datetime",
55
+ ormType: "timestamp",
56
+ isSystem: true,
57
+ },
58
+ {
59
+ name: "localeName",
60
+ displayName: "Locale",
61
+ type: "shortText",
62
+ ormType: "varchar",
63
+ isSystem: true,
64
+ },
65
+ {
66
+ name: "defaultEntityLocaleId",
67
+ displayName: "Default Entity Locale Id",
68
+ type: "int",
69
+ ormType: "integer",
70
+ isSystem: true,
71
+ },
72
+ {
73
+ name: "createdBy",
74
+ displayName: "Created By",
75
+ type: "relation",
76
+ ormType: "int",
77
+ isSystem: true,
78
+ relationType: "many-to-one",
79
+ relationCoModelSingularName: "user",
80
+ relationCreateInverse: false,
81
+ relationCascade: "restrict",
82
+ relationModelModuleName: "solid-core"
83
+ },
84
+ {
85
+ name: "updatedBy",
86
+ displayName: "Updated By",
87
+ type: "relation",
88
+ ormType: "int",
89
+ isSystem: true,
90
+ relationType: "many-to-one",
91
+ relationCoModelSingularName: "user",
92
+ relationCreateInverse: false,
93
+ relationCascade: "restrict",
94
+ relationModelModuleName: "solid-core"
95
+ },
96
+ ]
97
+
98
+ // Do an additional check and add a warning if the common entity keys and system field metadata keys don't match exactly
99
+ const commonEntityKeys = this.registry.getCommonEntityKeys();
100
+ const systemFieldNames = systemFieldsMetadata.map(field => field.name);
101
+ const missingKeys = commonEntityKeys.filter(key => !systemFieldNames.includes(key));
102
+ if (missingKeys.length > 0) {
103
+ this.logger.warn(`Missing system fields metadata for common entity keys: ${missingKeys.join(', ')}`);
104
+ }
105
+ return systemFieldsMetadata;
106
+ }
107
+
108
+
109
+ }
@@ -1,6 +1,8 @@
1
1
  import { Injectable, Logger } from '@nestjs/common';
2
2
  import { CommandService } from './command.service';
3
3
  import { snakeCase } from "lodash";
4
+ import { CommonEntity } from 'src/entities/common.entity';
5
+ import { SolidRegistry } from './solid-registry';
4
6
 
5
7
  export const ADD_MODULE_COMMAND = 'add-module';
6
8
  export type GenerateModuleOptions = {
@@ -14,25 +16,19 @@ type FieldOptions = {
14
16
  dataSource: string;
15
17
  fields: any[]; //FIXME This type can be improved
16
18
  modelEnableSoftDelete?: boolean;
17
- parentModel?: string;
19
+ parentModel?: string;
18
20
  parentModule?: string;
21
+ draftPublishWorkflowEnabled?: boolean;
19
22
  };
20
23
  export const REMOVE_FIELDS_COMMAND = 'remove-fields';
21
24
  export const REFRESH_MODEL_COMMAND = 'refresh-model';
22
25
 
23
- enum SYSTEM_FIELDS_TO_IGNORE_FOR_CODE_GENERATION {
24
- ID = 'id',
25
- CREATED_AT = 'createdAt',
26
- UPDATED_AT = 'updatedAt',
27
- DELETED_AT = 'deletedAt'
28
- }
29
-
30
26
  //TODO Rename to CodeBuilder service
31
27
  @Injectable()
32
28
  export class SchematicService {
33
29
  private readonly logger = new Logger(SchematicService.name);
34
30
  private readonly SCHEMATIC_PROJECT = '@solidstarters/solid-code-builder';
35
- constructor(private readonly commandService: CommandService) { }
31
+ constructor(private readonly commandService: CommandService, private readonly solidRegistry: SolidRegistry) { }
36
32
 
37
33
  async executeSchematicCommand(
38
34
  command: string,
@@ -79,9 +75,13 @@ export class SchematicService {
79
75
  modelCommand += ` --parent-module=${fieldOptions.parentModule}`;
80
76
  }
81
77
 
78
+ if (fieldOptions.draftPublishWorkflowEnabled) {
79
+ modelCommand += ` --draft-publish-workflow-enabled=${fieldOptions.draftPublishWorkflowEnabled}`;
80
+ }
81
+
82
82
  let fieldCommand = fieldOptions.fields
83
83
  .filter((field) => {
84
- return !Object.values(SYSTEM_FIELDS_TO_IGNORE_FOR_CODE_GENERATION).includes(field.name);
84
+ return !this.solidRegistry.getCommonEntityKeys().includes(field.name);
85
85
  })
86
86
  .map((field) => {
87
87
  return `--fields='${JSON.stringify(field)}'`;
@@ -101,5 +101,4 @@ export class SchematicService {
101
101
  throw new Error('Schematic command not supported.');
102
102
  }
103
103
  }
104
-
105
104
  }
@@ -1,8 +1,9 @@
1
1
  import { Injectable } from '@nestjs/common';
2
2
  import { InstanceWrapper } from '@nestjs/core/injector/instance-wrapper';
3
- import { ISelectionProvider, ISelectionProviderContext } from "../interfaces";
3
+ import { CommonEntity } from 'src/entities/common.entity';
4
4
  import { SecurityRule } from 'src/entities/security-rule.entity';
5
5
  import { EntityManager } from 'typeorm';
6
+ import { ISelectionProvider, ISelectionProviderContext } from "../interfaces";
6
7
  import { Locale } from 'src/entities/locale.entity';
7
8
 
8
9
  type ControllerMetadata = {
@@ -147,4 +148,8 @@ export class SolidRegistry {
147
148
  return entityMetadata.target;
148
149
  }
149
150
 
151
+ getCommonEntityKeys(): (keyof CommonEntity) [] {
152
+ return Reflect.getMetadataKeys(CommonEntity.prototype) as (keyof CommonEntity)[];
153
+ }
154
+
150
155
  }
package/src/index.ts CHANGED
@@ -242,7 +242,7 @@ export * from './repository/field.repository'
242
242
 
243
243
  //softDeleteAwareEventSubscriber.subscriber.ts
244
244
  export * from './subscribers/model.subscriber'
245
- export * from './subscribers/softDeleteAwareEventSubscriber.subscriber' //rename
245
+ export * from './subscribers/soft-delete-aware-event.subscriber' //rename
246
246
  export * from './subscribers/view-metadata.subscriber' //rename
247
247
  export * from './subscribers/audit.subscriber'
248
248
 
@@ -259,4 +259,4 @@ export * from './interfaces'
259
259
  export * from './solid-core.module'
260
260
 
261
261
  export * from './winston.logger'
262
- export * from './transformers/datetime-transformer'
262
+ export { default as datetimeTransformer } from './transformers/datetime-transformer'
package/src/interfaces.ts CHANGED
@@ -43,9 +43,9 @@ export interface ModuleMetadataConfiguration {
43
43
  moduleMetadata?: CreateModuleMetadataDto,
44
44
  roles?: CreateRoleMetadataDto[],
45
45
  users?: SignUpDto[],
46
- actions?: CreateActionMetadataDto[],
47
- menus?: CreateMenuItemMetadataDto[],
48
- views?: CreateViewMetadataDto[],
46
+ actions?: any[],
47
+ menus?: any[],
48
+ views?: any[],
49
49
  emailTemplates?: CreateEmailTemplateDto[],
50
50
  smsTemplates?: CreateSmsTemplateDto[],
51
51
  mediaStorageProviders?: CreateMediaStorageProviderMetadataDto[]
@@ -409,8 +409,10 @@ export class ModuleMetadataSeederService {
409
409
  viewData['model'] = await this.modelMetadataService.findOneByUserKey(viewData.modelUserKey);
410
410
  // await this.solidViewService.upsert(viewData);
411
411
  // First check if module already exists using name
412
- await this.solidViewService.createIfNotPresent(viewData);
413
412
 
413
+ // Changed the below to upsert as now we are saving modifications to the view json to file system also.
414
+ // await this.solidViewService.createIfNotPresent(viewData);
415
+ await this.solidViewService.upsert(viewData);
414
416
  }
415
417
  }
416
418
 
@@ -0,0 +1,53 @@
1
+ // This class will add the system fields in the field-metadata table if they are missing.
2
+ // Fetch all the models and their fields metadata and check if the system fields are present.
3
+
4
+ import { InjectRepository } from "@nestjs/typeorm";
5
+ import { ModelMetadata } from "src/entities/model-metadata.entity";
6
+ import { ModelMetadataHelperService } from "src/helpers/model-metadata-helper.service";
7
+ import { FieldRepository } from "src/repository/field.repository";
8
+ import { Repository } from "typeorm";
9
+
10
+ export class SystemFieldsSeederService {
11
+ // This service is responsible for seeding the system fields metadata for all models.
12
+ // It will check if the system fields are already present in the field-metadata table.
13
+ // If not, it will add them.
14
+ constructor(
15
+ private readonly modelHelperService: ModelMetadataHelperService,
16
+ @InjectRepository(ModelMetadata)
17
+ private readonly modelRepository: Repository<ModelMetadata>, // Replace with actual model repository type
18
+ @InjectRepository(FieldRepository)
19
+ private readonly fieldRepository: Repository<FieldRepository>, // Replace with actual field repository type
20
+ ) {}
21
+
22
+ async seed() {
23
+ // Get the model repo
24
+ const models = await this.modelRepository.find({
25
+ relations: ['fields'], // Assuming 'fields' is the relation to field metadata
26
+ });
27
+
28
+ for (const model of models) {
29
+ // Check if the system fields are already present
30
+ await this.seedMissingSystemFields(model);
31
+ }
32
+ }
33
+
34
+ private async seedMissingSystemFields(model: ModelMetadata) {
35
+ const existingSystemFields = model.fields.filter(field => field.isSystem);
36
+ const systemFieldsMetadata = this.modelHelperService.getSystemFieldsMetadata();
37
+
38
+ // Find out which system fields are missing
39
+ const missingFields = systemFieldsMetadata.filter(
40
+ sysField => !existingSystemFields.some(field => field.name === sysField.name)
41
+ );
42
+
43
+ // If there are missing fields, add them
44
+ if (missingFields.length > 0) {
45
+ const newFields = missingFields.map(field => ({
46
+ ...field,
47
+ model: model, // Associate the field with the current model
48
+ }));
49
+ await this.fieldRepository.save(newFields);
50
+ }
51
+ }
52
+ }
53
+
@@ -362,7 +362,7 @@ export class AuthenticationService {
362
362
  solidAppName: process.env.SOLID_APP_NAME,
363
363
  solidAppWebsiteUrl: process.env.SOLID_APP_WEBSITE_URL,
364
364
  firstName: user.username,
365
- fullName: user.fullName,
365
+ fullName: user.fullName ? user.fullName : user.username,
366
366
  emailVerificationTokenOnRegistration: user.emailVerificationTokenOnRegistration,
367
367
  },
368
368
  this.commonConfiguration.shouldQueueEmails,
@@ -379,7 +379,7 @@ export class AuthenticationService {
379
379
  otp: user.mobileVerificationTokenOnRegistration,
380
380
  mobileVerificationTokenOnRegistration: user.mobileVerificationTokenOnRegistration,
381
381
  firstName: user.username,
382
- fullName: user.fullName,
382
+ fullName: user.fullName ? user.fullName : user.username,
383
383
  }
384
384
  );
385
385
  }
@@ -544,7 +544,7 @@ export class AuthenticationService {
544
544
  solidAppWebsiteUrl: process.env.SOLID_APP_WEBSITE_URL,
545
545
  firstName: user.username,
546
546
  emailVerificationTokenOnLogin: user.emailVerificationTokenOnLogin,
547
- fullName: user.fullName,
547
+ fullName: user.fullName ? user.fullName : user.username,
548
548
  },
549
549
  this.commonConfiguration.shouldQueueEmails,
550
550
  'user',
@@ -560,7 +560,7 @@ export class AuthenticationService {
560
560
  otp: user.mobileVerificationTokenOnLogin,
561
561
  mobileVerificationTokenOnLogin: user.mobileVerificationTokenOnLogin,
562
562
  firstName: user.username,
563
- fullName: user.fullName,
563
+ fullName: user.fullName ? user.fullName : user.username,
564
564
  }
565
565
  );
566
566
  }
@@ -25,6 +25,9 @@ export class ConcatComputedFieldProvider implements IComputedFieldProvider<any>
25
25
  const fields = ctxt.fields;
26
26
  const slugify = ctxt.slugify || false;
27
27
 
28
+ if (!Array.isArray(fields) || fields?.length === 0) {
29
+ return '';
30
+ }
28
31
  let concatenatedString = '';
29
32
  for (let i = 0; i < fields.length; i++) {
30
33
  const field = fields[i];
@@ -109,8 +109,8 @@ export class CRUDService<T> { // Add two generic value i.e Person,CreatePersonDt
109
109
  });
110
110
  }
111
111
 
112
- private async validateAndTransformDto(field: FieldMetadata, dto: any, files: Express.Multer.File[], hasMediaFields: boolean, isPartialUpdate: boolean = false) {
113
- const fieldManager: FieldCrudManager = this.fieldCrudManager(field, this.entityManager, isPartialUpdate);
112
+ private async validateAndTransformDto(field: FieldMetadata, dto: any, files: Express.Multer.File[], hasMediaFields: boolean, isPartialUpdate: boolean = false, isUpdate: boolean = false) {
113
+ const fieldManager: FieldCrudManager = this.fieldCrudManager(field, this.entityManager, isPartialUpdate, isUpdate);
114
114
  const validationErrors = fieldManager.validate(dto, files);
115
115
  const errors = (validationErrors instanceof Promise) ? await validationErrors : validationErrors;
116
116
  if (errors.length > 0) {
@@ -150,10 +150,11 @@ export class CRUDService<T> { // Add two generic value i.e Person,CreatePersonDt
150
150
  }
151
151
 
152
152
  //TODO: Will the updates be partial i.e PATCH or full i.e PUT
153
- async update(id: number, updateDto: any, files: Express.Multer.File[] = [], isPartialUpdate: boolean = false, solidRequestContext: any = {}): Promise<T> {
153
+ async update(id: number, updateDto: any, files: Express.Multer.File[] = [], isPartialUpdate: boolean = false, solidRequestContext: any = {}, isUpdate: boolean = false): Promise<T> {
154
154
  if (!id) {
155
155
  throw new Error('Id is required for update');
156
156
  }
157
+ isUpdate = true;
157
158
  const model = await this.loadModel();
158
159
  // Check wheather user has update permission for model
159
160
  if (solidRequestContext.activeUser) {
@@ -185,7 +186,7 @@ export class CRUDService<T> { // Add two generic value i.e Person,CreatePersonDt
185
186
  // 2. Loop through the fields with a switch statement
186
187
  // 3. Handle the fields based on field type
187
188
  for (const field of fieldsToProcess) {
188
- const transformed = await this.validateAndTransformDto(field, updateDto, files, hasMediaFields, isPartialUpdate);
189
+ const transformed = await this.validateAndTransformDto(field, updateDto, files, hasMediaFields, isPartialUpdate, isUpdate);
189
190
  updateDto = transformed.dto;
190
191
  hasMediaFields = transformed.hasMediaFields;
191
192
  }
@@ -257,8 +258,8 @@ export class CRUDService<T> { // Add two generic value i.e Person,CreatePersonDt
257
258
  }
258
259
  }
259
260
 
260
- private fieldCrudManager(fieldMetadata: FieldMetadata, entityManager: EntityManager, isPartialUpdate: boolean = false): FieldCrudManager {
261
- const commonOptions = { required: fieldMetadata.required && !isPartialUpdate, fieldName: fieldMetadata.name };
261
+ private fieldCrudManager(fieldMetadata: FieldMetadata, entityManager: EntityManager, isPartialUpdate: boolean = false, isUpdate: boolean = false): FieldCrudManager {
262
+ const commonOptions = { required: fieldMetadata.required && !isPartialUpdate, fieldName: fieldMetadata.name, isUpdate};
262
263
  switch (fieldMetadata.type) {
263
264
  case SolidFieldType.shortText: {
264
265
  const options = { ...commonOptions, length: fieldMetadata.max, regexPattern: fieldMetadata.regexPattern };