@solidstarters/solid-core 1.2.22 → 1.2.24

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 (33) hide show
  1. package/dist/entities/field-metadata.entity.js +2 -2
  2. package/dist/entities/field-metadata.entity.js.map +1 -1
  3. package/dist/entities/media-storage-provider-metadata.entity.js +1 -1
  4. package/dist/entities/media-storage-provider-metadata.entity.js.map +1 -1
  5. package/dist/entities/permission-metadata.entity.js +2 -2
  6. package/dist/entities/permission-metadata.entity.js.map +1 -1
  7. package/dist/seeders/module-metadata-seeder.service.d.ts.map +1 -1
  8. package/dist/seeders/module-metadata-seeder.service.js +1 -1
  9. package/dist/seeders/module-metadata-seeder.service.js.map +1 -1
  10. package/dist/seeders/seed-data/solid-core-metadata.json +6 -5
  11. package/dist/services/mediaStorageProviders/file-storage-provider.js +1 -1
  12. package/dist/services/mediaStorageProviders/file-storage-provider.js.map +1 -1
  13. package/dist/services/model-metadata.service.d.ts.map +1 -1
  14. package/dist/services/model-metadata.service.js +20 -3
  15. package/dist/services/model-metadata.service.js.map +1 -1
  16. package/dist/services/view-metadata.service.d.ts +1 -0
  17. package/dist/services/view-metadata.service.d.ts.map +1 -1
  18. package/dist/services/view-metadata.service.js +9 -0
  19. package/dist/services/view-metadata.service.js.map +1 -1
  20. package/dist/subscribers/model.subscriber.js +1 -1
  21. package/dist/subscribers/model.subscriber.js.map +1 -1
  22. package/dist/tsconfig.tsbuildinfo +1 -1
  23. package/package.json +2 -1
  24. package/src/entities/field-metadata.entity.ts +2 -2
  25. package/src/entities/media-storage-provider-metadata.entity.ts +1 -1
  26. package/src/entities/mysql-issues +14 -0
  27. package/src/entities/permission-metadata.entity.ts +2 -2
  28. package/src/seeders/module-metadata-seeder.service.ts +8 -5
  29. package/src/seeders/seed-data/solid-core-metadata.json +6 -5
  30. package/src/services/mediaStorageProviders/file-storage-provider.ts +1 -1
  31. package/src/services/model-metadata.service.ts +133 -116
  32. package/src/services/view-metadata.service.ts +13 -0
  33. package/src/subscribers/model.subscriber.ts +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solidstarters/solid-core",
3
- "version": "1.2.22",
3
+ "version": "1.2.24",
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",
@@ -53,6 +53,7 @@
53
53
  "passport-jwt": "^4.0.1",
54
54
  "passport-local": "^1.0.0",
55
55
  "pg": "^8.11.3",
56
+ "mysql2": "^3.13.0",
56
57
  "pluralize": "^8.0.0",
57
58
  "puppeteer": "^23.2.0",
58
59
  "reflect-metadata": "^0.1.13",
@@ -67,7 +67,7 @@ export class FieldMetadata extends CommonEntity {
67
67
  @Column({ name: "private", default: false })
68
68
  private: boolean;
69
69
 
70
- @Column("text", { array: true, name: 'media_types', nullable: true })
70
+ @Column("json", { name: 'media_types', nullable: true })
71
71
  mediaTypes: string[];
72
72
 
73
73
  @Column({ name: 'media_max_size_kb', nullable: true })
@@ -111,7 +111,7 @@ export class FieldMetadata extends CommonEntity {
111
111
  @Column({ name: 'selection_static_values', nullable: true, type: 'simple-array' })
112
112
  selectionStaticValues: string[];
113
113
 
114
- @Column({ name: 'selection_value_type', nullable: true, type: 'text', default: 'string' })
114
+ @Column({ name: 'selection_value_type', nullable: true, type: 'text' }) // text type cannot have a default value
115
115
  selectionValueType: string = 'string';
116
116
 
117
117
  // @Column({ name: "computed", default: false })
@@ -4,7 +4,7 @@ import { Column, Entity, Index } from "typeorm";
4
4
  @Entity("ss_media_storage_provider_metadata")
5
5
  export class MediaStorageProviderMetadata extends CommonEntity {
6
6
  @Index({ unique: true })
7
- @Column({ unique: true })
7
+ @Column({ })
8
8
  name: string;
9
9
 
10
10
  @Column()
@@ -0,0 +1,14 @@
1
+ # Issues
2
+ 1. @Column("text", { array: true, name: 'media_types', nullable: true }) // array type not supported. No impact on code generation. not being used
3
+ 2.
4
+ default values not allowed for text,blog // Code generation impact. If we want to support default values for long text/rich text, then changes to be made.
5
+ date value is not supported propertly in mysql
6
+ i.e new Date("2025-02-11T00:00:00.000Z")
7
+ 3. Below type of code cannot exist. // No impact on code generation. Not being used.
8
+ @Index({ unique: true })
9
+ @Column({ unique: true })
10
+ 4. // Impact on code generation. unique index to be generated by using @Index and not @Column.
11
+ @Index({ unique: true })
12
+ @Column({ })
13
+ 5. i.e new Date("2025-02-11T00:00:00.000Z")
14
+ -> Remove the column default value
@@ -4,8 +4,8 @@ import { RoleMetadata } from 'src/entities/role-metadata.entity'
4
4
  @Entity("ss_permission_metadata")
5
5
  export class PermissionMetadata extends CommonEntity {
6
6
 
7
- @Index()
8
- @Column({ name: "name", type: "varchar", unique: true })
7
+ @Index({unique: true})
8
+ @Column({ name: "name", type: "varchar" })
9
9
  name: string;
10
10
 
11
11
  @ManyToMany(() => RoleMetadata, roleMetadata => roleMetadata.permissions, { cascade: ['insert', 'update'] })
@@ -304,16 +304,16 @@ export class ModuleMetadataSeederService {
304
304
  if (smsTemplate.body) {
305
305
  // const smsTemplateFilePath = path.join(process.cwd(), smsTemplate.body);
306
306
  // smsTemplate.body = fs.readFileSync(smsTemplateFilePath, 'utf-8').toString()
307
-
307
+
308
308
  const modulePath = path.dirname(require.resolve('@solidstarters/solid-core'));
309
309
 
310
310
  // Resolve the `src` folder
311
311
  const seedDataPath = path.join(modulePath, '../src/seeders/seed-data/sms-templates');
312
-
312
+
313
313
  // Example usage
314
314
  const filePath = path.join(seedDataPath, smsTemplate.body);
315
-
316
-
315
+
316
+
317
317
  smsTemplate.body = fs.readFileSync(filePath, 'utf-8').toString();
318
318
 
319
319
  }
@@ -376,7 +376,10 @@ export class ModuleMetadataSeederService {
376
376
 
377
377
  viewData['module'] = await this.moduleMetadataService.findOneByUserKey(viewData.moduleUserKey);
378
378
  viewData['model'] = await this.modelMetadataService.findOneByUserKey(viewData.modelUserKey);
379
- await this.solidViewService.upsert(viewData);
379
+ // await this.solidViewService.upsert(viewData);
380
+ // First check if module already exists using name
381
+ await this.solidViewService.createIfNotPresent(viewData);
382
+
380
383
  }
381
384
  }
382
385
 
@@ -2176,7 +2176,7 @@
2176
2176
  "encrypt": false,
2177
2177
  "selectionValueType": "string",
2178
2178
  "selectionDynamicProvider": "ListOfModelsSelectionProvider",
2179
- "selectionDynamicProviderCtxt": {},
2179
+ "selectionDynamicProviderCtxt": "{}",
2180
2180
  "isSystem": true
2181
2181
  },
2182
2182
  {
@@ -2802,7 +2802,7 @@
2802
2802
  {
2803
2803
  "attrs": {
2804
2804
  "className": "pi pi-cog",
2805
- "label": ""
2805
+ "label": "Generate Code"
2806
2806
  },
2807
2807
  "action": {
2808
2808
  "title": "",
@@ -2819,7 +2819,7 @@
2819
2819
  {
2820
2820
  "attrs": {
2821
2821
  "className": "pi pi-cog",
2822
- "label": ""
2822
+ "label": "Generate Code"
2823
2823
  },
2824
2824
  "action": {
2825
2825
  "title": "",
@@ -2987,6 +2987,7 @@
2987
2987
  50
2988
2988
  ],
2989
2989
  "enableGlobalSearch": true,
2990
+ "truncateAfter": 50,
2990
2991
  "create": true,
2991
2992
  "edit": true,
2992
2993
  "delete": true,
@@ -2994,7 +2995,7 @@
2994
2995
  {
2995
2996
  "attrs": {
2996
2997
  "className": "pi pi-cog",
2997
- "label": ""
2998
+ "label": "Generate Code"
2998
2999
  },
2999
3000
  "action": {
3000
3001
  "title": "",
@@ -3011,7 +3012,7 @@
3011
3012
  {
3012
3013
  "attrs": {
3013
3014
  "className": "pi pi-cog",
3014
- "label": ""
3015
+ "label": "Generate Code"
3015
3016
  },
3016
3017
  "action": {
3017
3018
  "title": "",
@@ -67,7 +67,7 @@ export class FileStorageProvider<T> implements MediaStorageProvider<T> {
67
67
  }
68
68
 
69
69
  private getFullFilePath(fileName: string): string {
70
- return `${this.configService.get('app-builder.fileStorageDir')}/${fileName}`;
70
+ return `${process.env.BASE_URL}/${this.configService.get('app-builder.fileStorageDir')}/${fileName}`;
71
71
  }
72
72
 
73
73
  private getFileName(file: Express.Multer.File): string {
@@ -360,6 +360,17 @@ export class ModelMetadataService {
360
360
 
361
361
  }
362
362
  }
363
+ const column1Fields = [];
364
+ const column2Fields = [];
365
+
366
+ // Distribute fields between two columns
367
+ for (let i = 0; i < formViewLayoutFields.length; i++) {
368
+ if (i % 2 === 0) {
369
+ column1Fields.push(formViewLayoutFields[i]);
370
+ } else {
371
+ column2Fields.push(formViewLayoutFields[i]);
372
+ }
373
+ }
363
374
  const action = {
364
375
  displayName: `${model.displayName} List View`,
365
376
  name: `${model.singularName}-list-view`,
@@ -427,11 +438,17 @@ export class ModelMetadataService {
427
438
  {
428
439
  type: "row",
429
440
  attrs: { name: "sheet-1" },
430
- children: [{
431
- type: "column",
432
- attrs: { name: "group-1", label: "", className: "col-6" },
433
- children: formViewLayoutFields
434
- }]
441
+ children: [
442
+ {
443
+ type: "column",
444
+ attrs: { name: "group-1", label: "", className: "col-6" },
445
+ children: column1Fields
446
+ },
447
+ {
448
+ type: "column",
449
+ attrs: { name: "group-1", label: "", className: "col-6" },
450
+ children: column2Fields
451
+ }]
435
452
  },
436
453
  ]
437
454
  }
@@ -493,7 +510,7 @@ export class ModelMetadataService {
493
510
  // Existing field
494
511
  const existingField = existingFields.find((field) => field.id === fieldMetadata.id);
495
512
  if (existingField) {
496
- if (fieldMetadata.mediaStorageProviderId) {
513
+ if (fieldMetadata.mediaStorageProviderId) {
497
514
  fieldMetadata['mediaStorageProvider'] = await this.mediaStorageProviderMetadataService.findOne(fieldMetadata.mediaStorageProviderId);
498
515
  }
499
516
  Object.assign(existingField, fieldMetadata);
@@ -539,28 +556,28 @@ export class ModelMetadataService {
539
556
  const userKeyFields = fieldsMetadata.filter(field => field.isUserKey);
540
557
 
541
558
  if (userKeyFields.length > 0) {
542
- const newUserKeyField = userKeyFields[userKeyFields.length - 1];
543
- const savedUserKeyField = await fieldRepo.findOne({ where: { id: newUserKeyField.id } });
544
-
545
- if (savedUserKeyField) {
546
- finalModel.userKeyField = savedUserKeyField;
547
- await modelRepo.save(finalModel);
548
- }
549
-
550
- const otherUserKeyFields = userKeyFields.filter(field => field.id !== newUserKeyField.id);
551
-
552
- for (const field of otherUserKeyFields) {
553
- const existingField = await fieldRepo.findOne({ where: { id: field.id } });
554
- if (existingField) {
555
- existingField.isUserKey = false;
556
- await fieldRepo.save(existingField);
557
- }
559
+ const newUserKeyField = userKeyFields[userKeyFields.length - 1];
560
+ const savedUserKeyField = await fieldRepo.findOne({ where: { id: newUserKeyField.id } });
561
+
562
+ if (savedUserKeyField) {
563
+ finalModel.userKeyField = savedUserKeyField;
564
+ await modelRepo.save(finalModel);
565
+ }
566
+
567
+ const otherUserKeyFields = userKeyFields.filter(field => field.id !== newUserKeyField.id);
568
+
569
+ for (const field of otherUserKeyFields) {
570
+ const existingField = await fieldRepo.findOne({ where: { id: field.id } });
571
+ if (existingField) {
572
+ existingField.isUserKey = false;
573
+ await fieldRepo.save(existingField);
558
574
  }
575
+ }
559
576
  } else {
560
- if (finalModel.userKeyField) {
561
- finalModel.userKeyField = null;
562
- await modelRepo.save(finalModel);
563
- }
577
+ if (finalModel.userKeyField) {
578
+ finalModel.userKeyField = null;
579
+ await modelRepo.save(finalModel);
580
+ }
564
581
  }
565
582
 
566
583
  return updatedModel;
@@ -684,38 +701,38 @@ export class ModelMetadataService {
684
701
 
685
702
  async generateCode(options: CodeGenerationOptions): Promise<string> {
686
703
  const query = {
687
- populate: ["module", "fields"]
704
+ populate: ["module", "fields"]
688
705
  };
689
706
 
690
- const model = options.modelId
691
- ? await this.findOne(options.modelId, query)
692
- : await this.findOneByUserKey(options.modelUserKey, query.populate);
707
+ const model = options.modelId
708
+ ? await this.findOne(options.modelId, query)
709
+ : await this.findOneByUserKey(options.modelUserKey, query.populate);
693
710
 
694
711
  options.fieldIdsForRemoval = model.fields
695
- .filter(field => field.isMarkedForRemoval)
696
- .map(field => field.id);
712
+ .filter(field => field.isMarkedForRemoval)
713
+ .map(field => field.id);
697
714
 
698
715
  const refreshModelCodeOutput = await this.generateModelCode(options);
699
716
  const removeFieldCodeOuput = await this.generateRemoveFieldsCode(options);
700
717
 
701
718
  const listViewLayout = model.fields.map(field => ({
702
- type: "field",
703
- attrs: {
704
- name: `${field.name}`,
705
- sortable: true,
706
- filterable: true
707
- }
719
+ type: "field",
720
+ attrs: {
721
+ name: `${field.name}`,
722
+ sortable: true,
723
+ filterable: true
724
+ }
708
725
  }));
709
726
 
710
727
  const formViewLayout = model.fields.map(field => ({
711
- type: "field",
712
- attrs: {
713
- name: `${field.name}`
714
- }
728
+ type: "field",
729
+ attrs: {
730
+ name: `${field.name}`
731
+ }
715
732
  }));
716
733
 
717
734
  const resolvedModule = await this.dataSource.getRepository(ModuleMetadata).findOne({
718
- where: { id: model.module.id }
735
+ where: { id: model.module.id }
719
736
  });
720
737
 
721
738
  const viewRepo = this.dataSource.getRepository(ViewMetadata);
@@ -723,82 +740,82 @@ export class ModelMetadataService {
723
740
  const menuRepo = this.dataSource.getRepository(MenuItemMetadata);
724
741
 
725
742
  const modelViews = [
726
- {
727
- name: `${model.singularName}-list-view`,
728
- displayName: `${model.displayName}`,
729
- type: 'list',
730
- context: "{}",
731
- module: resolvedModule,
732
- model: model,
733
- layout: JSON.stringify({
734
- type: "list",
735
- attrs: {
736
- pagination: true,
737
- pageSizeOptions: [10, 25, 50],
738
- enableGlobalSearch: true,
739
- create: true,
740
- edit: true,
741
- delete: true
742
- },
743
- children: listViewLayout
744
- }, null, 3)
745
- },
746
- {
747
- name: `${model.singularName}-form-view`,
748
- displayName: `${model.displayName}`,
749
- type: 'form',
750
- context: "{}",
751
- module: resolvedModule,
752
- model: model,
753
- layout: JSON.stringify({
754
- type: "form",
755
- attrs: { name: "form-1", label: `${model.displayName}`, className: "grid" },
756
- children: [
743
+ {
744
+ name: `${model.singularName}-list-view`,
745
+ displayName: `${model.displayName}`,
746
+ type: 'list',
747
+ context: "{}",
748
+ module: resolvedModule,
749
+ model: model,
750
+ layout: JSON.stringify({
751
+ type: "list",
752
+ attrs: {
753
+ pagination: true,
754
+ pageSizeOptions: [10, 25, 50],
755
+ enableGlobalSearch: true,
756
+ create: true,
757
+ edit: true,
758
+ delete: true
759
+ },
760
+ children: listViewLayout
761
+ }, null, 3)
762
+ },
763
+ {
764
+ name: `${model.singularName}-form-view`,
765
+ displayName: `${model.displayName}`,
766
+ type: 'form',
767
+ context: "{}",
768
+ module: resolvedModule,
769
+ model: model,
770
+ layout: JSON.stringify({
771
+ type: "form",
772
+ attrs: { name: "form-1", label: `${model.displayName}`, className: "grid" },
773
+ children: [
774
+ {
775
+ type: "sheet",
776
+ attrs: { name: "sheet-1" },
777
+ children: [
778
+ {
779
+ type: "row",
780
+ attrs: { name: "group-1", label: "", className: "" },
781
+ children: [
757
782
  {
758
- type: "sheet",
759
- attrs: { name: "sheet-1" },
760
- children: [
761
- {
762
- type: "row",
763
- attrs: { name: "group-1", label: "", className: "" },
764
- children: [
765
- {
766
- type: "column",
767
- attrs: { name: "group-1", label: "", className: "col-6" },
768
- children: formViewLayout
769
- }
770
- ]
771
- }
772
- ]
783
+ type: "column",
784
+ attrs: { name: "group-1", label: "", className: "col-6" },
785
+ children: formViewLayout
773
786
  }
774
- ]
775
- }, null, 3)
776
- }
787
+ ]
788
+ }
789
+ ]
790
+ }
791
+ ]
792
+ }, null, 3)
793
+ }
777
794
  ];
778
795
 
779
796
  for (const view of modelViews) {
780
- const existingView = await viewRepo.findOne({ where: { name: view.name } });
797
+ const existingView = await viewRepo.findOne({ where: { name: view.name } });
781
798
 
782
- if (!existingView) {
783
- const createdView = viewRepo.create(view);
784
- await viewRepo.save(createdView);
785
- }
799
+ if (!existingView) {
800
+ const createdView = viewRepo.create(view);
801
+ await viewRepo.save(createdView);
802
+ }
786
803
  }
787
804
 
788
805
  let view = await viewRepo.findOne({ where: { name: `${model.singularName}-list-view` } });
789
806
 
790
807
  const actionData = {
791
- displayName: `${model.displayName} List View`,
792
- name: `${model.singularName}-list-view`,
793
- type: "solid",
794
- domain: "" as any,
795
- context: "" as any,
796
- customComponent: `/admin/address-master/${model.singularName}/all`,
797
- customIsModal: true,
798
- serverEndpoint: "",
799
- view: view,
800
- module: resolvedModule,
801
- model: model
808
+ displayName: `${model.displayName} List View`,
809
+ name: `${model.singularName}-list-view`,
810
+ type: "solid",
811
+ domain: "" as any,
812
+ context: "" as any,
813
+ customComponent: `/admin/address-master/${model.singularName}/all`,
814
+ customIsModal: true,
815
+ serverEndpoint: "",
816
+ view: view,
817
+ module: resolvedModule,
818
+ model: model
802
819
  };
803
820
 
804
821
  let existingAction = await actionRepo.findOne({ where: { name: actionData.name } });
@@ -811,13 +828,13 @@ export class ModelMetadataService {
811
828
  const adminRole = await this.roleService.findRoleByName('Admin');
812
829
 
813
830
  const menuData = {
814
- displayName: `${model.displayName}`,
815
- name: `${model.singularName}-menu-item`,
816
- sequenceNumber: 1,
817
- action: existingAction,
818
- module: resolvedModule,
819
- roles: [adminRole],
820
- parentMenuItemUserKey: ""
831
+ displayName: `${model.displayName}`,
832
+ name: `${model.singularName}-menu-item`,
833
+ sequenceNumber: 1,
834
+ action: existingAction,
835
+ module: resolvedModule,
836
+ roles: [adminRole],
837
+ parentMenuItemUserKey: ""
821
838
  };
822
839
 
823
840
  let existingMenu = await menuRepo.findOne({ where: { name: menuData.name } });
@@ -946,7 +963,7 @@ export class ModelMetadataService {
946
963
  private async getRelationInverseFields(modelId: number, repo: Repository<FieldMetadata>): Promise<FieldMetadata[]> {
947
964
  return await repo.find({
948
965
  where: {
949
- model : {
966
+ model: {
950
967
  id: modelId
951
968
  },
952
969
  type: SolidFieldType.relation,
@@ -137,6 +137,19 @@ export class ViewMetadataService extends CRUDService<ViewMetadata> {
137
137
  return this.repo.save(viewData);
138
138
  }
139
139
  }
140
+ async createIfNotPresent(updateSolidViewDto: UpdateViewMetadataDto) {
141
+ // First check if module already exists using name
142
+ const existingSolidView = await this.findOneByUserKey(updateSolidViewDto.name);
143
+
144
+ // if found
145
+ if (existingSolidView) {
146
+ }
147
+ // if not found - create new
148
+ else {
149
+ const viewData = this.repo.create(updateSolidViewDto);
150
+ return this.repo.save(viewData);
151
+ }
152
+ }
140
153
 
141
154
  // END: Custom Service Methods
142
155
 
@@ -67,7 +67,7 @@ export class ModelSubscriber implements EntitySubscriberInterface<ModelMetadata>
67
67
  model: event.entity,
68
68
  },
69
69
  ];
70
- transactionManager.save(FieldMetadata, systemFieldsMetadata);
70
+ await transactionManager.save(FieldMetadata, systemFieldsMetadata);
71
71
  // Save to the database.
72
72
  // fieldMetadataRepo.save(systemFieldsMetadata);
73
73