rez_core 6.5.75 → 6.5.77

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 (185) hide show
  1. package/dist/constant/db-data-type.constant.d.ts +30 -0
  2. package/dist/constant/db-data-type.constant.js +59 -0
  3. package/dist/constant/db-data-type.constant.js.map +1 -0
  4. package/dist/constant/storage-type.constant.d.ts +4 -0
  5. package/dist/constant/storage-type.constant.js +9 -0
  6. package/dist/constant/storage-type.constant.js.map +1 -0
  7. package/dist/module/eav/controller/eav.controller.d.ts +21 -0
  8. package/dist/module/eav/controller/eav.controller.js +127 -0
  9. package/dist/module/eav/controller/eav.controller.js.map +1 -0
  10. package/dist/module/eav/dto/eav-operation.dto.d.ts +20 -0
  11. package/dist/module/eav/dto/eav-operation.dto.js +75 -0
  12. package/dist/module/eav/dto/eav-operation.dto.js.map +1 -0
  13. package/dist/module/eav/eav.module.d.ts +2 -0
  14. package/dist/module/eav/eav.module.js +84 -0
  15. package/dist/module/eav/eav.module.js.map +1 -0
  16. package/dist/module/eav/entity/eav-boolean.entity.d.ts +9 -0
  17. package/dist/module/eav/entity/eav-boolean.entity.js +48 -0
  18. package/dist/module/eav/entity/eav-boolean.entity.js.map +1 -0
  19. package/dist/module/eav/entity/eav-date.entity.d.ts +9 -0
  20. package/dist/module/eav/entity/eav-date.entity.js +48 -0
  21. package/dist/module/eav/entity/eav-date.entity.js.map +1 -0
  22. package/dist/module/eav/entity/eav-decimal.entity.d.ts +9 -0
  23. package/dist/module/eav/entity/eav-decimal.entity.js +48 -0
  24. package/dist/module/eav/entity/eav-decimal.entity.js.map +1 -0
  25. package/dist/module/eav/entity/eav-int.entity.d.ts +9 -0
  26. package/dist/module/eav/entity/eav-int.entity.js +48 -0
  27. package/dist/module/eav/entity/eav-int.entity.js.map +1 -0
  28. package/dist/module/eav/entity/eav-json.entity.d.ts +9 -0
  29. package/dist/module/eav/entity/eav-json.entity.js +48 -0
  30. package/dist/module/eav/entity/eav-json.entity.js.map +1 -0
  31. package/dist/module/eav/entity/eav-text.entity.d.ts +9 -0
  32. package/dist/module/eav/entity/eav-text.entity.js +48 -0
  33. package/dist/module/eav/entity/eav-text.entity.js.map +1 -0
  34. package/dist/module/eav/entity/eav-time.entity.d.ts +9 -0
  35. package/dist/module/eav/entity/eav-time.entity.js +48 -0
  36. package/dist/module/eav/entity/eav-time.entity.js.map +1 -0
  37. package/dist/module/eav/entity/eav-timestamp.entity.d.ts +9 -0
  38. package/dist/module/eav/entity/eav-timestamp.entity.js +48 -0
  39. package/dist/module/eav/entity/eav-timestamp.entity.js.map +1 -0
  40. package/dist/module/eav/entity/eav-varchar.entity.d.ts +9 -0
  41. package/dist/module/eav/entity/eav-varchar.entity.js +48 -0
  42. package/dist/module/eav/entity/eav-varchar.entity.js.map +1 -0
  43. package/dist/module/eav/interface/eav-strategy.interface.d.ts +8 -0
  44. package/dist/module/eav/interface/eav-strategy.interface.js +3 -0
  45. package/dist/module/eav/interface/eav-strategy.interface.js.map +1 -0
  46. package/dist/module/eav/repository/eav-boolean.repository.d.ts +13 -0
  47. package/dist/module/eav/repository/eav-boolean.repository.js +57 -0
  48. package/dist/module/eav/repository/eav-boolean.repository.js.map +1 -0
  49. package/dist/module/eav/repository/eav-date.repository.d.ts +13 -0
  50. package/dist/module/eav/repository/eav-date.repository.js +57 -0
  51. package/dist/module/eav/repository/eav-date.repository.js.map +1 -0
  52. package/dist/module/eav/repository/eav-decimal.repository.d.ts +13 -0
  53. package/dist/module/eav/repository/eav-decimal.repository.js +57 -0
  54. package/dist/module/eav/repository/eav-decimal.repository.js.map +1 -0
  55. package/dist/module/eav/repository/eav-int.repository.d.ts +13 -0
  56. package/dist/module/eav/repository/eav-int.repository.js +57 -0
  57. package/dist/module/eav/repository/eav-int.repository.js.map +1 -0
  58. package/dist/module/eav/repository/eav-json.repository.d.ts +13 -0
  59. package/dist/module/eav/repository/eav-json.repository.js +57 -0
  60. package/dist/module/eav/repository/eav-json.repository.js.map +1 -0
  61. package/dist/module/eav/repository/eav-text.repository.d.ts +13 -0
  62. package/dist/module/eav/repository/eav-text.repository.js +57 -0
  63. package/dist/module/eav/repository/eav-text.repository.js.map +1 -0
  64. package/dist/module/eav/repository/eav-time.repository.d.ts +13 -0
  65. package/dist/module/eav/repository/eav-time.repository.js +57 -0
  66. package/dist/module/eav/repository/eav-time.repository.js.map +1 -0
  67. package/dist/module/eav/repository/eav-timestamp.repository.d.ts +13 -0
  68. package/dist/module/eav/repository/eav-timestamp.repository.js +57 -0
  69. package/dist/module/eav/repository/eav-timestamp.repository.js.map +1 -0
  70. package/dist/module/eav/repository/eav-varchar.repository.d.ts +13 -0
  71. package/dist/module/eav/repository/eav-varchar.repository.js +57 -0
  72. package/dist/module/eav/repository/eav-varchar.repository.js.map +1 -0
  73. package/dist/module/eav/service/eav-boolean.service.d.ts +12 -0
  74. package/dist/module/eav/service/eav-boolean.service.js +59 -0
  75. package/dist/module/eav/service/eav-boolean.service.js.map +1 -0
  76. package/dist/module/eav/service/eav-date.service.d.ts +12 -0
  77. package/dist/module/eav/service/eav-date.service.js +59 -0
  78. package/dist/module/eav/service/eav-date.service.js.map +1 -0
  79. package/dist/module/eav/service/eav-decimal.service.d.ts +12 -0
  80. package/dist/module/eav/service/eav-decimal.service.js +59 -0
  81. package/dist/module/eav/service/eav-decimal.service.js.map +1 -0
  82. package/dist/module/eav/service/eav-factory.service.d.ts +26 -0
  83. package/dist/module/eav/service/eav-factory.service.js +81 -0
  84. package/dist/module/eav/service/eav-factory.service.js.map +1 -0
  85. package/dist/module/eav/service/eav-int.service.d.ts +12 -0
  86. package/dist/module/eav/service/eav-int.service.js +59 -0
  87. package/dist/module/eav/service/eav-int.service.js.map +1 -0
  88. package/dist/module/eav/service/eav-json.service.d.ts +12 -0
  89. package/dist/module/eav/service/eav-json.service.js +59 -0
  90. package/dist/module/eav/service/eav-json.service.js.map +1 -0
  91. package/dist/module/eav/service/eav-text.service.d.ts +12 -0
  92. package/dist/module/eav/service/eav-text.service.js +59 -0
  93. package/dist/module/eav/service/eav-text.service.js.map +1 -0
  94. package/dist/module/eav/service/eav-time.service.d.ts +12 -0
  95. package/dist/module/eav/service/eav-time.service.js +59 -0
  96. package/dist/module/eav/service/eav-time.service.js.map +1 -0
  97. package/dist/module/eav/service/eav-timestamp.service.d.ts +12 -0
  98. package/dist/module/eav/service/eav-timestamp.service.js +59 -0
  99. package/dist/module/eav/service/eav-timestamp.service.js.map +1 -0
  100. package/dist/module/eav/service/eav-varchar.service.d.ts +12 -0
  101. package/dist/module/eav/service/eav-varchar.service.js +59 -0
  102. package/dist/module/eav/service/eav-varchar.service.js.map +1 -0
  103. package/dist/module/eav/service/eav.service.d.ts +14 -0
  104. package/dist/module/eav/service/eav.service.js +65 -0
  105. package/dist/module/eav/service/eav.service.js.map +1 -0
  106. package/dist/module/enterprise/entity/brand.entity.d.ts +0 -0
  107. package/dist/module/enterprise/entity/brand.entity.js +1 -0
  108. package/dist/module/enterprise/entity/brand.entity.js.map +1 -0
  109. package/dist/module/enterprise/entity/school.entity.d.ts +0 -0
  110. package/dist/module/enterprise/entity/school.entity.js +1 -0
  111. package/dist/module/enterprise/entity/school.entity.js.map +1 -0
  112. package/dist/module/enterprise/repository/brand.repository.d.ts +0 -0
  113. package/dist/module/enterprise/repository/brand.repository.js +1 -0
  114. package/dist/module/enterprise/repository/brand.repository.js.map +1 -0
  115. package/dist/module/meta/entity/brand-profile.entity.d.ts +3 -0
  116. package/dist/module/meta/entity/brand-profile.entity.js +18 -0
  117. package/dist/module/meta/entity/brand-profile.entity.js.map +1 -0
  118. package/dist/module/meta/entity/dynamic.entity.d.ts +3 -0
  119. package/dist/module/meta/entity/dynamic.entity.js +8 -0
  120. package/dist/module/meta/entity/dynamic.entity.js.map +1 -0
  121. package/dist/module/meta/entity/field-group.entity.d.ts +0 -0
  122. package/dist/module/meta/entity/field-group.entity.js +1 -0
  123. package/dist/module/meta/entity/field-group.entity.js.map +1 -0
  124. package/dist/module/meta/entity/school.entity.d.ts +8 -0
  125. package/dist/module/meta/entity/school.entity.js +44 -0
  126. package/dist/module/meta/entity/school.entity.js.map +1 -0
  127. package/dist/module/meta/entity/schoolAddress.entity.d.ts +9 -0
  128. package/dist/module/meta/entity/schoolAddress.entity.js +48 -0
  129. package/dist/module/meta/entity/schoolAddress.entity.js.map +1 -0
  130. package/dist/module/meta/entity/section-master.entity.d.ts +0 -0
  131. package/dist/module/meta/entity/section-master.entity.js +1 -0
  132. package/dist/module/meta/entity/section-master.entity.js.map +1 -0
  133. package/dist/module/meta/entity/user-app-mapping.entity.d.ts +0 -0
  134. package/dist/module/meta/entity/user-app-mapping.entity.js +1 -0
  135. package/dist/module/meta/entity/user-app-mapping.entity.js.map +1 -0
  136. package/dist/resources/dev.properties.yaml +31 -0
  137. package/dist/resources/local.properties.yaml +27 -0
  138. package/dist/resources/uat.properties.yaml +31 -0
  139. package/dist/table.config.d.ts +3 -3
  140. package/dist/tsconfig.build.tsbuildinfo +1 -1
  141. package/package.json +1 -1
  142. package/src/app.module.ts +3 -1
  143. package/src/constant/db-data-type.constant.ts +81 -0
  144. package/src/constant/storage-type.constant.ts +4 -0
  145. package/src/module/eav/EAV_USAGE_GUIDE.md +351 -0
  146. package/src/module/eav/controller/eav.controller.ts +119 -0
  147. package/src/module/eav/dto/eav-operation.dto.ts +62 -0
  148. package/src/module/eav/eav.module.ts +80 -0
  149. package/src/module/eav/entity/eav-boolean.entity.ts +26 -0
  150. package/src/module/eav/entity/eav-date.entity.ts +25 -0
  151. package/src/module/eav/entity/eav-decimal.entity.ts +25 -0
  152. package/src/module/eav/entity/eav-int.entity.ts +25 -0
  153. package/src/module/eav/entity/eav-json.entity.ts +25 -0
  154. package/src/module/eav/entity/eav-text.entity.ts +25 -0
  155. package/src/module/eav/entity/eav-time.entity.ts +25 -0
  156. package/src/module/eav/entity/eav-timestamp.entity.ts +25 -0
  157. package/src/module/eav/entity/eav-varchar.entity.ts +25 -0
  158. package/src/module/eav/interface/eav-strategy.interface.ts +32 -0
  159. package/src/module/eav/repository/eav-boolean.repository.ts +67 -0
  160. package/src/module/eav/repository/eav-date.repository.ts +67 -0
  161. package/src/module/eav/repository/eav-decimal.repository.ts +67 -0
  162. package/src/module/eav/repository/eav-int.repository.ts +67 -0
  163. package/src/module/eav/repository/eav-json.repository.ts +67 -0
  164. package/src/module/eav/repository/eav-text.repository.ts +67 -0
  165. package/src/module/eav/repository/eav-time.repository.ts +67 -0
  166. package/src/module/eav/repository/eav-timestamp.repository.ts +67 -0
  167. package/src/module/eav/repository/eav-varchar.repository.ts +67 -0
  168. package/src/module/eav/service/eav-boolean.service.ts +64 -0
  169. package/src/module/eav/service/eav-date.service.ts +64 -0
  170. package/src/module/eav/service/eav-decimal.service.ts +64 -0
  171. package/src/module/eav/service/eav-factory.service.ts +93 -0
  172. package/src/module/eav/service/eav-int.service.ts +64 -0
  173. package/src/module/eav/service/eav-json.service.ts +64 -0
  174. package/src/module/eav/service/eav-text.service.ts +64 -0
  175. package/src/module/eav/service/eav-time.service.ts +64 -0
  176. package/src/module/eav/service/eav-timestamp.service.ts +64 -0
  177. package/src/module/eav/service/eav-varchar.service.ts +65 -0
  178. package/src/module/eav/service/eav.service.ts +116 -0
  179. package/src/module/listmaster/service/list-master-item.service.ts +11 -61
  180. package/src/module/meta/controller/entity.controller.ts +2 -10
  181. package/src/module/meta/entity/base-entity.entity.ts +3 -0
  182. package/src/module/meta/entity/dynamic.entity.ts +4 -0
  183. package/src/module/meta/entity/entity-master.entity.ts +16 -52
  184. package/src/module/meta/service/entity-master.service.ts +135 -6
  185. package/src/module/meta/service/media-data.service.ts +0 -206
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rez_core",
3
- "version": "6.5.75",
3
+ "version": "6.5.77",
4
4
  "description": "",
5
5
  "author": "",
6
6
  "private": false,
package/src/app.module.ts CHANGED
@@ -29,6 +29,7 @@ import { LinkedAttributesModule } from './module/linked_attributes/linked_attrib
29
29
  import { EntityJSONModule } from './module/entity_json/entity_json.module';
30
30
  import { ExportModule } from './module/export/export.module';
31
31
  import { AppMasterModule } from './module/app_master/app-master.module';
32
+ import { EAVModule } from './module/eav/eav.module';
32
33
 
33
34
  @Module({
34
35
  imports: [
@@ -64,7 +65,8 @@ import { AppMasterModule } from './module/app_master/app-master.module';
64
65
  EntityJSONModule,
65
66
  ExportModule,
66
67
  EntityModule,
67
- AppMasterModule
68
+ AppMasterModule,
69
+ EAVModule
68
70
  ],
69
71
  })
70
72
  export class AppModule { }
@@ -0,0 +1,81 @@
1
+ /**
2
+ * EAV Data Type Enum
3
+ * Defines all supported data types for Entity-Attribute-Value storage
4
+ */
5
+ export enum EavDataType {
6
+ // String types
7
+ VARCHAR = 'varchar',
8
+ STRING = 'string', // Alias for VARCHAR
9
+
10
+ // Numeric types
11
+ INT = 'int',
12
+ INTEGER = 'integer', // Alias for INT
13
+ DECIMAL = 'decimal',
14
+ FLOAT = 'float', // Alias for DECIMAL
15
+
16
+ // Boolean type
17
+ BOOLEAN = 'boolean',
18
+ BOOL = 'bool', // Alias for BOOLEAN
19
+
20
+ // Text types
21
+ TEXT = 'text',
22
+ JSON = 'json',
23
+
24
+ // Date/Time types
25
+ DATE = 'date',
26
+ TIME = 'time',
27
+ TIMESTAMP = 'timestamp',
28
+ DATETIME = 'datetime', // Alias for TIMESTAMP
29
+ }
30
+
31
+ /**
32
+ * Primary EAV Data Types (without aliases)
33
+ * Use this for mapping to actual database tables
34
+ */
35
+ export enum EavPrimaryDataType {
36
+ VARCHAR = 'varchar',
37
+ INT = 'int',
38
+ DECIMAL = 'decimal',
39
+ BOOLEAN = 'boolean',
40
+ TEXT = 'text',
41
+ JSON = 'json',
42
+ DATE = 'date',
43
+ TIME = 'time',
44
+ TIMESTAMP = 'timestamp',
45
+ }
46
+
47
+ /**
48
+ * Map of data type aliases to their primary types
49
+ */
50
+ export const EAV_DATA_TYPE_ALIAS_MAP: Record<string, EavPrimaryDataType> = {
51
+ [EavDataType.VARCHAR]: EavPrimaryDataType.VARCHAR,
52
+ [EavDataType.STRING]: EavPrimaryDataType.VARCHAR,
53
+ [EavDataType.INT]: EavPrimaryDataType.INT,
54
+ [EavDataType.INTEGER]: EavPrimaryDataType.INT,
55
+ [EavDataType.DECIMAL]: EavPrimaryDataType.DECIMAL,
56
+ [EavDataType.FLOAT]: EavPrimaryDataType.DECIMAL,
57
+ [EavDataType.BOOLEAN]: EavPrimaryDataType.BOOLEAN,
58
+ [EavDataType.BOOL]: EavPrimaryDataType.BOOLEAN,
59
+ [EavDataType.TEXT]: EavPrimaryDataType.TEXT,
60
+ [EavDataType.JSON]: EavPrimaryDataType.JSON,
61
+ [EavDataType.DATE]: EavPrimaryDataType.DATE,
62
+ [EavDataType.TIME]: EavPrimaryDataType.TIME,
63
+ [EavDataType.TIMESTAMP]: EavPrimaryDataType.TIMESTAMP,
64
+ [EavDataType.DATETIME]: EavPrimaryDataType.TIMESTAMP,
65
+ };
66
+
67
+ /**
68
+ * Get the primary data type from an alias or primary type
69
+ */
70
+ export function getPrimaryDataType(dataType: string): EavPrimaryDataType | null {
71
+ const normalized = dataType.toLowerCase().trim();
72
+ return EAV_DATA_TYPE_ALIAS_MAP[normalized] || null;
73
+ }
74
+
75
+ /**
76
+ * Check if a data type is supported
77
+ */
78
+ export function isValidEavDataType(dataType: string): boolean {
79
+ const normalized = dataType.toLowerCase().trim();
80
+ return normalized in EAV_DATA_TYPE_ALIAS_MAP;
81
+ }
@@ -0,0 +1,4 @@
1
+ export enum StorageType {
2
+ SELF = 'SELF',
3
+ DYNAMIC = 'DYNAMIC'
4
+ }
@@ -0,0 +1,351 @@
1
+ # EAV Module Usage Guide
2
+
3
+ ## Overview
4
+
5
+ The EAV (Entity-Attribute-Value) module provides a flexible way to store dynamic attributes for entities using different data types. It implements the **Strategy Pattern** and **Factory Pattern** for clean, maintainable code.
6
+
7
+ ## Architecture
8
+
9
+ ```mermaid
10
+ graph TD
11
+ A[EavService - Orchestrator] --> B[EavFactoryService]
12
+ B --> C[IEavStrategy Interface]
13
+ C --> D[EavVarcharService]
14
+ C --> E[EavIntService]
15
+ C --> F[EavBooleanService]
16
+ C --> G[EavDecimalService]
17
+ C --> H[EavTextService]
18
+ C --> I[EavJsonService]
19
+ C --> J[EavDateService]
20
+ C --> K[EavTimeService]
21
+ C --> L[EavTimestampService]
22
+ ```
23
+
24
+ ## Supported Data Types
25
+
26
+ - `varchar` / `string` - String values
27
+ - `int` / `integer` - Integer values
28
+ - `boolean` / `bool` - Boolean values
29
+ - `decimal` / `float` - Decimal/Float values
30
+ - `text` - Large text values
31
+ - `json` - JSON objects
32
+ - `date` - Date values
33
+ - `time` - Time values
34
+ - `timestamp` / `datetime` - Timestamp values
35
+
36
+ ## Basic Usage
37
+
38
+ ### 1. Import the Module
39
+
40
+ ```typescript
41
+ import { Module } from '@nestjs/common';
42
+ import { EavModule } from './module/eav/eav.module';
43
+
44
+ @Module({
45
+ imports: [EavModule],
46
+ })
47
+ export class AppModule {}
48
+ ```
49
+
50
+ ### 2. Inject the Service
51
+
52
+ ```typescript
53
+ import { Injectable } from '@nestjs/common';
54
+ import { EavService } from './module/eav/service/eav.service';
55
+
56
+ @Injectable()
57
+ export class YourService {
58
+ constructor(private readonly eavService: EavService) {}
59
+ }
60
+ ```
61
+
62
+ ### 3. Perform CRUD Operations
63
+
64
+ #### Create a Record
65
+
66
+ ```typescript
67
+ // Create a varchar attribute
68
+ const result = await this.eavService.create('varchar', {
69
+ entity_type: 'user',
70
+ entity_id: 123,
71
+ key: 'nickname',
72
+ value: 'JohnDoe',
73
+ }, 1); // modifiedBy user ID
74
+
75
+ // Create an integer attribute
76
+ await this.eavService.create('int', {
77
+ entity_type: 'product',
78
+ entity_id: 456,
79
+ key: 'stock_quantity',
80
+ value: 100,
81
+ });
82
+
83
+ // Create a JSON attribute
84
+ await this.eavService.create('json', {
85
+ entity_type: 'user',
86
+ entity_id: 123,
87
+ key: 'preferences',
88
+ value: { theme: 'dark', language: 'en' },
89
+ });
90
+ ```
91
+
92
+ #### Find One Record
93
+
94
+ ```typescript
95
+ const attribute = await this.eavService.findOne('varchar', {
96
+ entity_type: 'user',
97
+ entity_id: 123,
98
+ key: 'nickname',
99
+ });
100
+
101
+ console.log(attribute.value); // 'JohnDoe'
102
+ ```
103
+
104
+ #### Find All Records
105
+
106
+ ```typescript
107
+ // Find all attributes for a specific entity
108
+ const userAttributes = await this.eavService.findAll('varchar', {
109
+ entity_type: 'user',
110
+ entity_id: 123,
111
+ });
112
+
113
+ // Find all attributes of a type for an entity type
114
+ const allUserVarchars = await this.eavService.findAll('varchar', {
115
+ entity_type: 'user',
116
+ });
117
+ ```
118
+
119
+ #### Update a Record
120
+
121
+ ```typescript
122
+ const updated = await this.eavService.update(
123
+ 'varchar',
124
+ {
125
+ entity_type: 'user',
126
+ entity_id: 123,
127
+ key: 'nickname',
128
+ },
129
+ {
130
+ value: 'JaneDoe',
131
+ },
132
+ 1, // modifiedBy user ID
133
+ );
134
+ ```
135
+
136
+ #### Delete a Record
137
+
138
+ ```typescript
139
+ const deleted = await this.eavService.delete('varchar', {
140
+ entity_type: 'user',
141
+ entity_id: 123,
142
+ key: 'nickname',
143
+ });
144
+
145
+ console.log(deleted); // true if deleted, false otherwise
146
+ ```
147
+
148
+ #### Upsert (Create or Update)
149
+
150
+ ```typescript
151
+ // Will create if doesn't exist, update if exists
152
+ const result = await this.eavService.upsert('varchar', {
153
+ entity_type: 'user',
154
+ entity_id: 123,
155
+ key: 'nickname',
156
+ value: 'UpdatedNickname',
157
+ }, 1);
158
+ ```
159
+
160
+ ## Advanced Usage
161
+
162
+ ### Using the Factory Directly
163
+
164
+ If you need more control, you can inject the factory service:
165
+
166
+ ```typescript
167
+ import { EavFactoryService } from './module/eav/service/eav-factory.service';
168
+
169
+ @Injectable()
170
+ export class YourService {
171
+ constructor(private readonly eavFactory: EavFactoryService) {}
172
+
173
+ async customOperation() {
174
+ // Get the service for a specific type
175
+ const varcharService = this.eavFactory.getService('varchar');
176
+
177
+ // Use the service directly
178
+ const result = await varcharService.create({
179
+ entity_type: 'custom',
180
+ entity_id: 999,
181
+ key: 'custom_key',
182
+ value: 'custom_value',
183
+ });
184
+ }
185
+ }
186
+ ```
187
+
188
+ ### Type Checking
189
+
190
+ ```typescript
191
+ // Check if a type is supported
192
+ const isSupported = this.eavService.isTypeSupported('varchar'); // true
193
+ const notSupported = this.eavService.isTypeSupported('unknown'); // false
194
+
195
+ // Get all supported types
196
+ const types = this.eavService.getSupportedTypes();
197
+ console.log(types); // ['varchar', 'string', 'int', 'integer', ...]
198
+ ```
199
+
200
+ ## REST API Examples (Using the Controller)
201
+
202
+ ### Create
203
+ ```bash
204
+ POST /eav/varchar?modifiedBy=1
205
+ Content-Type: application/json
206
+
207
+ {
208
+ "entity_type": "user",
209
+ "entity_id": 123,
210
+ "key": "nickname",
211
+ "value": "JohnDoe"
212
+ }
213
+ ```
214
+
215
+ ### Find One
216
+ ```bash
217
+ GET /eav/varchar/find-one?entity_type=user&entity_id=123&key=nickname
218
+ ```
219
+
220
+ ### Find All
221
+ ```bash
222
+ GET /eav/varchar?entity_type=user&entity_id=123
223
+ ```
224
+
225
+ ### Update
226
+ ```bash
227
+ PUT /eav/varchar?entity_type=user&entity_id=123&key=nickname&modifiedBy=1
228
+ Content-Type: application/json
229
+
230
+ {
231
+ "value": "JaneDoe"
232
+ }
233
+ ```
234
+
235
+ ### Delete
236
+ ```bash
237
+ DELETE /eav/varchar?entity_type=user&entity_id=123&key=nickname
238
+ ```
239
+
240
+ ### Upsert
241
+ ```bash
242
+ POST /eav/varchar/upsert?modifiedBy=1
243
+ Content-Type: application/json
244
+
245
+ {
246
+ "entity_type": "user",
247
+ "entity_id": 123,
248
+ "key": "nickname",
249
+ "value": "UpdatedNickname"
250
+ }
251
+ ```
252
+
253
+ ### Get Supported Types
254
+ ```bash
255
+ GET /eav/meta/supported-types
256
+ ```
257
+
258
+ ## Design Pattern Benefits
259
+
260
+ ### Strategy Pattern
261
+ - Each data type has its own service implementing `IEavStrategy`
262
+ - Easy to add new data types without modifying existing code
263
+ - Each service is independently testable
264
+
265
+ ### Factory Pattern
266
+ - `EavFactoryService` resolves the correct service based on data type
267
+ - Centralizes service selection logic
268
+ - Supports type aliases (e.g., 'string' → 'varchar')
269
+
270
+ ### Facade Pattern
271
+ - `EavService` provides a simple, unified interface
272
+ - Hides complexity of service resolution
273
+ - Makes it easy for consumers to use the module
274
+
275
+ ## Error Handling
276
+
277
+ The factory will throw a `BadRequestException` if an unsupported data type is provided:
278
+
279
+ ```typescript
280
+ try {
281
+ await this.eavService.create('unsupported_type', {...});
282
+ } catch (error) {
283
+ // BadRequestException: Unsupported data type: unsupported_type
284
+ }
285
+ ```
286
+
287
+ ## Best Practices
288
+
289
+ 1. **Always specify the correct data type** - Use the appropriate type for your data
290
+ 2. **Use upsert when appropriate** - Simplifies create-or-update logic
291
+ 3. **Track modifications** - Pass `modifiedBy` to track who made changes
292
+ 4. **Validate input** - The DTOs include validation decorators
293
+ 5. **Handle errors** - Always wrap calls in try-catch for production code
294
+
295
+ ## Example: Complete User Preferences System
296
+
297
+ ```typescript
298
+ @Injectable()
299
+ export class UserPreferencesService {
300
+ constructor(private readonly eavService: EavService) {}
301
+
302
+ async setPreference(userId: number, key: string, value: any, type: string) {
303
+ return await this.eavService.upsert(type, {
304
+ entity_type: 'user_preferences',
305
+ entity_id: userId,
306
+ key,
307
+ value,
308
+ }, userId);
309
+ }
310
+
311
+ async getPreference(userId: number, key: string, type: string) {
312
+ return await this.eavService.findOne(type, {
313
+ entity_type: 'user_preferences',
314
+ entity_id: userId,
315
+ key,
316
+ });
317
+ }
318
+
319
+ async getAllPreferences(userId: number) {
320
+ // Get preferences from different types
321
+ const varchars = await this.eavService.findAll('varchar', {
322
+ entity_type: 'user_preferences',
323
+ entity_id: userId,
324
+ });
325
+
326
+ const booleans = await this.eavService.findAll('boolean', {
327
+ entity_type: 'user_preferences',
328
+ entity_id: userId,
329
+ });
330
+
331
+ const jsons = await this.eavService.findAll('json', {
332
+ entity_type: 'user_preferences',
333
+ entity_id: userId,
334
+ });
335
+
336
+ return {
337
+ strings: varchars,
338
+ flags: booleans,
339
+ objects: jsons,
340
+ };
341
+ }
342
+
343
+ async deletePreference(userId: number, key: string, type: string) {
344
+ return await this.eavService.delete(type, {
345
+ entity_type: 'user_preferences',
346
+ entity_id: userId,
347
+ key,
348
+ });
349
+ }
350
+ }
351
+ ```
@@ -0,0 +1,119 @@
1
+ import {
2
+ Controller,
3
+ Get,
4
+ Post,
5
+ Put,
6
+ Delete,
7
+ Body,
8
+ Param,
9
+ Query,
10
+ HttpCode,
11
+ HttpStatus,
12
+ } from '@nestjs/common';
13
+ import { EAVService } from '../service/eav.service';
14
+ import { CreateEAVDto, UpdateEAVDto, EAVQueryDto } from '../dto/eav-operation.dto';
15
+
16
+ /**
17
+ * Example EAV Controller
18
+ * Demonstrates how to use the EAV service for CRUD operations
19
+ */
20
+ @Controller('eav')
21
+ export class EavController {
22
+ constructor(private readonly eavService: EAVService) { }
23
+
24
+ /**
25
+ * Create a new EAV record
26
+ * POST /eav/:dataType
27
+ * Body: { entity_type, entity_id, key, value }
28
+ */
29
+ @Post(':dataType')
30
+ @HttpCode(HttpStatus.CREATED)
31
+ async create(
32
+ @Param('dataType') dataType: string,
33
+ @Body() createDto: CreateEAVDto,
34
+ @Query('modifiedBy') modifiedBy?: number,
35
+ ) {
36
+ return await this.eavService.create(dataType, createDto, modifiedBy);
37
+ }
38
+
39
+ /**
40
+ * Find a single EAV record
41
+ * GET /eav/:dataType/find-one?entity_type=xxx&entity_id=xxx&key=xxx
42
+ */
43
+ @Get(':dataType/find-one')
44
+ async findOne(@Param('dataType') dataType: string, @Query() query: EAVQueryDto) {
45
+ return await this.eavService.findOne(dataType, query);
46
+ }
47
+
48
+ /**
49
+ * Find all EAV records matching the query
50
+ * GET /eav/:dataType?entity_type=xxx&entity_id=xxx
51
+ */
52
+ @Get(':dataType')
53
+ async findAll(@Param('dataType') dataType: string, @Query() query: Partial<EAVQueryDto>) {
54
+ return await this.eavService.findAll(dataType, query);
55
+ }
56
+
57
+ /**
58
+ * Update an existing EAV record
59
+ * PUT /eav/:dataType?entity_type=xxx&entity_id=xxx&key=xxx
60
+ * Body: { value }
61
+ */
62
+ @Put(':dataType')
63
+ async update(
64
+ @Param('dataType') dataType: string,
65
+ @Query() query: EAVQueryDto,
66
+ @Body() updateDto: UpdateEAVDto,
67
+ @Query('modifiedBy') modifiedBy?: number,
68
+ ) {
69
+ return await this.eavService.update(dataType, query, updateDto, modifiedBy);
70
+ }
71
+
72
+ /**
73
+ * Delete an EAV record
74
+ * DELETE /eav/:dataType?entity_type=xxx&entity_id=xxx&key=xxx
75
+ */
76
+ @Delete(':dataType')
77
+ @HttpCode(HttpStatus.NO_CONTENT)
78
+ async delete(@Param('dataType') dataType: string, @Query() query: EAVQueryDto) {
79
+ const deleted = await this.eavService.delete(dataType, query);
80
+ return { deleted };
81
+ }
82
+
83
+ /**
84
+ * Upsert (create or update) an EAV record
85
+ * POST /eav/:dataType/upsert
86
+ * Body: { entity_type, entity_id, key, value }
87
+ */
88
+ @Post(':dataType/upsert')
89
+ async upsert(
90
+ @Param('dataType') dataType: string,
91
+ @Body() createDto: CreateEAVDto,
92
+ @Query('modifiedBy') modifiedBy?: number,
93
+ ) {
94
+ return await this.eavService.upsert(dataType, createDto, modifiedBy);
95
+ }
96
+
97
+ /**
98
+ * Get all supported data types
99
+ * GET /eav/meta/supported-types
100
+ */
101
+ @Get('meta/supported-types')
102
+ getSupportedTypes() {
103
+ return {
104
+ supportedTypes: this.eavService.getSupportedTypes(),
105
+ };
106
+ }
107
+
108
+ /**
109
+ * Check if a data type is supported
110
+ * GET /eav/meta/is-supported/:dataType
111
+ */
112
+ @Get('meta/is-supported/:dataType')
113
+ isTypeSupported(@Param('dataType') dataType: string) {
114
+ return {
115
+ dataType,
116
+ isSupported: this.eavService.isTypeSupported(dataType),
117
+ };
118
+ }
119
+ }
@@ -0,0 +1,62 @@
1
+ import { IsNotEmpty, IsString, IsOptional, IsNumber } from 'class-validator';
2
+
3
+ /**
4
+ * DTO for creating EAV records
5
+ */
6
+ export class CreateEAVDto {
7
+ @IsNotEmpty()
8
+ @IsString()
9
+ entity_type: string;
10
+
11
+ @IsNotEmpty()
12
+ entity_id: string | number;
13
+
14
+ @IsNotEmpty()
15
+ @IsString()
16
+ key: string;
17
+
18
+ @IsNotEmpty()
19
+ value: any;
20
+ }
21
+
22
+ /**
23
+ * DTO for updating EAV records
24
+ */
25
+ export class UpdateEAVDto {
26
+ @IsNotEmpty()
27
+ value: any;
28
+ }
29
+
30
+ /**
31
+ * DTO for querying EAV records
32
+ */
33
+ export class EAVQueryDto {
34
+ @IsNotEmpty()
35
+ @IsString()
36
+ entity_type: string;
37
+
38
+ @IsNotEmpty()
39
+ entity_id: string | number;
40
+
41
+ @IsNotEmpty()
42
+ @IsString()
43
+ key: string;
44
+ }
45
+
46
+ /**
47
+ * DTO for EAV operations with data type
48
+ */
49
+ export class EavOperationDto extends CreateEAVDto {
50
+ @IsNotEmpty()
51
+ @IsString()
52
+ data_type: string;
53
+ }
54
+
55
+ /**
56
+ * DTO for EAV query with data type
57
+ */
58
+ export class EavQueryWithTypeDto extends EAVQueryDto {
59
+ @IsNotEmpty()
60
+ @IsString()
61
+ data_type: string;
62
+ }