@dynamatix/cat-shared 0.0.65 → 0.0.67

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/README.md CHANGED
@@ -1,7 +1,7 @@
1
- This is the shared library for Catura Services.
2
- # Purpose
3
-
4
- The purposes of this repository are to include:
5
- - All the models of Catura
6
- - Shared services in Catura
1
+ This is the shared library for Catura Services.
2
+ # Purpose
3
+
4
+ The purposes of this repository are to include:
5
+ - All the models of Catura
6
+ - Shared services in Catura
7
7
  - Shared middlewares in Catura
package/index.js CHANGED
@@ -1,3 +1,3 @@
1
- export * from './models/index.js';
2
- export * from './middlewares/index.js';
1
+ export * from './models/index.js';
2
+ export * from './middlewares/index.js';
3
3
  export * from './services/index.js';
@@ -1,111 +1,111 @@
1
- import AuditConfigModel from '../models/audit-config.model.js';
2
- import AuditLog from '../models/audit.model.js';
3
- import ValueReferenceMap from '../models/value-reference-map.model.js';
4
- import { getContext } from '../services/request-context.service.js';
5
- import mongoose from 'mongoose';
6
-
7
- let onAuditLogCreated = null;
8
-
9
- // Generic resolver: fetch display values using ValueReferenceMap
10
- async function resolveAuditValues(field, oldValue, newValue) {
11
- const map = await ValueReferenceMap.findOne({ field });
12
- if (!map || (!oldValue && !newValue)) return { oldValue, newValue };
13
-
14
- const Model = mongoose.models[map.model];
15
- if (!Model) return { oldValue, newValue };
16
-
17
- const [oldDoc, newDoc] = await Promise.all([
18
- oldValue ? Model.findById(oldValue).lean() : null,
19
- newValue ? Model.findById(newValue).lean() : null
20
- ]);
21
-
22
- return {
23
- oldValue: oldDoc?.[map.displayField] || oldValue,
24
- newValue: newDoc?.[map.displayField] || newValue
25
- };
26
- }
27
-
28
- function applyAuditMiddleware(schema, collectionName) {
29
- // Handle creation audit
30
- schema.post('save', async function (doc) {
31
- const auditConfig = await AuditConfigModel.findOne({ collectionName });
32
- if (!auditConfig?.trackCreation) return;
33
-
34
- const context = getContext();
35
- const userId = context?.userId || 'anonymous';
36
- const contextId = context?.contextId;
37
-
38
- const log = {
39
- name: `${collectionName} created`,
40
- recordId: doc._id,
41
- oldValue: null,
42
- newValue: 'Document created',
43
- createdBy: userId,
44
- contextId
45
- };
46
-
47
- await AuditLog.create(log);
48
-
49
- if (onAuditLogCreated) {
50
- await onAuditLogCreated([log], contextId);
51
- }
52
- });
53
-
54
- // Capture the original doc before update
55
- schema.pre(['findOneAndUpdate', 'findByIdAndUpdate'], async function (next) {
56
- this._originalDoc = await this.model.findOne(this.getQuery()).lean();
57
- next();
58
- });
59
-
60
- // Handle update audits
61
- schema.post(['findOneAndUpdate', 'findByIdAndUpdate'], async function (result) {
62
- if (!result || !this._originalDoc) return;
63
-
64
- const auditConfig = await AuditConfigModel.findOne({ collectionName });
65
- if (!auditConfig?.fields?.length) return;
66
-
67
- const update = this.getUpdate();
68
- const logs = [];
69
- const context = getContext();
70
- const userId = context?.userId || 'anonymous';
71
- const contextId = context?.contextId;
72
-
73
- for (const field of auditConfig.fields) {
74
- const hasChanged =
75
- update?.$set?.hasOwnProperty(field) || update?.hasOwnProperty(field);
76
-
77
- if (hasChanged) {
78
- const newValue = update?.$set?.[field] ?? update?.[field];
79
- const oldValue = this._originalDoc[field];
80
-
81
- if (oldValue !== newValue) {
82
- // Resolve human-readable values
83
- const { oldValue: resolvedOld, newValue: resolvedNew } =
84
- await resolveAuditValues(field, oldValue, newValue);
85
-
86
- logs.push({
87
- name: `${collectionName}.${field}`,
88
- recordId: result._id,
89
- oldValue: resolvedOld,
90
- newValue: resolvedNew,
91
- createdBy: userId,
92
- contextId
93
- });
94
- }
95
- }
96
- }
97
-
98
- if (logs.length) {
99
- await AuditLog.insertMany(logs);
100
- if (onAuditLogCreated) {
101
- await onAuditLogCreated(logs, contextId);
102
- }
103
- }
104
- });
105
- }
106
-
107
- export function registerAuditHook(callback) {
108
- onAuditLogCreated = callback;
109
- }
110
-
111
- export default applyAuditMiddleware;
1
+ import AuditConfigModel from '../models/audit-config.model.js';
2
+ import AuditLog from '../models/audit.model.js';
3
+ import ValueReferenceMap from '../models/value-reference-map.model.js';
4
+ import { getContext } from '../services/request-context.service.js';
5
+ import mongoose from 'mongoose';
6
+
7
+ let onAuditLogCreated = null;
8
+
9
+ // Generic resolver: fetch display values using ValueReferenceMap
10
+ async function resolveAuditValues(field, oldValue, newValue) {
11
+ const map = await ValueReferenceMap.findOne({ field });
12
+ if (!map || (!oldValue && !newValue)) return { oldValue, newValue };
13
+
14
+ const Model = mongoose.models[map.model];
15
+ if (!Model) return { oldValue, newValue };
16
+
17
+ const [oldDoc, newDoc] = await Promise.all([
18
+ oldValue ? Model.findById(oldValue).lean() : null,
19
+ newValue ? Model.findById(newValue).lean() : null
20
+ ]);
21
+
22
+ return {
23
+ oldValue: oldDoc?.[map.displayField] || oldValue,
24
+ newValue: newDoc?.[map.displayField] || newValue
25
+ };
26
+ }
27
+
28
+ function applyAuditMiddleware(schema, collectionName) {
29
+ // Handle creation audit
30
+ schema.post('save', async function (doc) {
31
+ const auditConfig = await AuditConfigModel.findOne({ collectionName });
32
+ if (!auditConfig?.trackCreation) return;
33
+
34
+ const context = getContext();
35
+ const userId = context?.userId || 'anonymous';
36
+ const contextId = context?.contextId;
37
+
38
+ const log = {
39
+ name: `${collectionName} created`,
40
+ recordId: doc._id,
41
+ oldValue: null,
42
+ newValue: 'Document created',
43
+ createdBy: userId,
44
+ contextId
45
+ };
46
+
47
+ await AuditLog.create(log);
48
+
49
+ if (onAuditLogCreated) {
50
+ await onAuditLogCreated([log], contextId);
51
+ }
52
+ });
53
+
54
+ // Capture the original doc before update
55
+ schema.pre(['findOneAndUpdate', 'findByIdAndUpdate'], async function (next) {
56
+ this._originalDoc = await this.model.findOne(this.getQuery()).lean();
57
+ next();
58
+ });
59
+
60
+ // Handle update audits
61
+ schema.post(['findOneAndUpdate', 'findByIdAndUpdate'], async function (result) {
62
+ if (!result || !this._originalDoc) return;
63
+
64
+ const auditConfig = await AuditConfigModel.findOne({ collectionName });
65
+ if (!auditConfig?.fields?.length) return;
66
+
67
+ const update = this.getUpdate();
68
+ const logs = [];
69
+ const context = getContext();
70
+ const userId = context?.userId || 'anonymous';
71
+ const contextId = context?.contextId;
72
+
73
+ for (const field of auditConfig.fields) {
74
+ const hasChanged =
75
+ update?.$set?.hasOwnProperty(field) || update?.hasOwnProperty(field);
76
+
77
+ if (hasChanged) {
78
+ const newValue = update?.$set?.[field] ?? update?.[field];
79
+ const oldValue = this._originalDoc[field];
80
+
81
+ if (oldValue !== newValue) {
82
+ // Resolve human-readable values
83
+ const { oldValue: resolvedOld, newValue: resolvedNew } =
84
+ await resolveAuditValues(field, oldValue, newValue);
85
+
86
+ logs.push({
87
+ name: `${collectionName}.${field}`,
88
+ recordId: result._id,
89
+ oldValue: resolvedOld,
90
+ newValue: resolvedNew,
91
+ createdBy: userId,
92
+ contextId
93
+ });
94
+ }
95
+ }
96
+ }
97
+
98
+ if (logs.length) {
99
+ await AuditLog.insertMany(logs);
100
+ if (onAuditLogCreated) {
101
+ await onAuditLogCreated(logs, contextId);
102
+ }
103
+ }
104
+ });
105
+ }
106
+
107
+ export function registerAuditHook(callback) {
108
+ onAuditLogCreated = callback;
109
+ }
110
+
111
+ export default applyAuditMiddleware;
@@ -1,2 +1,2 @@
1
- export {default as applyAuditMiddleware} from './audit.middleware.js';
2
- export { registerAuditHook } from './audit.middleware.js';
1
+ export {default as applyAuditMiddleware} from './audit.middleware.js';
2
+ export { registerAuditHook } from './audit.middleware.js';
@@ -1,11 +1,12 @@
1
- import mongoose from 'mongoose';
2
-
3
- const auditConfigSchema = new mongoose.Schema({
4
- collectionName: String,
5
- fields: [String],
6
- trackCreation: { type: Boolean, default: false }
7
- });
8
-
9
- const AuditConfigModel = mongoose.model('AuditConfig', auditConfigSchema);
10
-
11
- export default AuditConfigModel;
1
+ import mongoose from 'mongoose';
2
+
3
+ const auditConfigSchema = new mongoose.Schema({
4
+ collectionName: String,
5
+ fields: [String],
6
+ trackCreation: { type: Boolean, default: false },
7
+ descriptionResolutorForExternalData: { type: String, default: null },
8
+ });
9
+
10
+ const AuditConfigModel = mongoose.model('AuditConfig', auditConfigSchema);
11
+
12
+ export default AuditConfigModel;
@@ -1,16 +1,16 @@
1
- import mongoose from 'mongoose';
2
-
3
- const auditSchema = new mongoose.Schema({
4
- name: String,
5
- recordId: mongoose.Schema.Types.ObjectId,
6
- contextId: mongoose.Schema.Types.ObjectId,
7
- oldValue: mongoose.Schema.Types.Mixed,
8
- newValue: mongoose.Schema.Types.Mixed,
9
- timestamp: { type: Date, default: Date.now },
10
- createdBy: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
11
- externalData: mongoose.Schema.Types.Mixed
12
- });
13
-
14
- const AuditLog = mongoose.model('AuditLog', auditSchema);
15
-
16
- export default AuditLog;
1
+ import mongoose from 'mongoose';
2
+
3
+ const auditSchema = new mongoose.Schema({
4
+ name: String,
5
+ recordId: mongoose.Schema.Types.ObjectId,
6
+ contextId: mongoose.Schema.Types.ObjectId,
7
+ oldValue: mongoose.Schema.Types.Mixed,
8
+ newValue: mongoose.Schema.Types.Mixed,
9
+ timestamp: { type: Date, default: Date.now },
10
+ createdBy: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
11
+ externalData: mongoose.Schema.Types.Mixed
12
+ });
13
+
14
+ const AuditLog = mongoose.model('AuditLog', auditSchema);
15
+
16
+ export default AuditLog;
@@ -1,255 +1,257 @@
1
- import mongoose from 'mongoose';
2
-
3
- const optionSchema = new mongoose.Schema({
4
- label: { type: mongoose.Schema.Types.Mixed },
5
- value: { type: mongoose.Schema.Types.Mixed }
6
- }, { _id: false });
7
-
8
- const formfieldSchema = new mongoose.Schema({
9
- isFutureDateBlocked: {
10
- type: Boolean,
11
- },
12
- addToPayload: {
13
- type: Boolean,
14
- default: false
15
- },
16
- fieldName: {
17
- type: String,
18
- required: true,
19
- trim: true
20
- },
21
- isHidden: {
22
- type: Boolean,
23
- default: false
24
- },
25
- isEditable: {
26
- type: Boolean,
27
- default: true
28
- },
29
- size: {
30
- type: Number,
31
- default: 6,
32
- enum: [3, 4, 6, 8, 10, 12],
33
- },
34
- layout: {
35
- type: String,
36
- enum: ['horizontal', 'vertical'],
37
- },
38
- label: {
39
- type: String,
40
- required: true,
41
- trim: true
42
- },
43
- dataType: {
44
- type: String,
45
- required: true,
46
- enum: ['text-area', 'string', 'number', 'boolean-check', 'boolean-radio', 'percentage', 'date', 'array', 'object', 'select', 'radio', 'drop-down', 'sort-code', 'post-code', 'pound', 'lookup', 'multi-select', 'email', 'phone', 'internationalPhone'] // Added common form field types
47
- },
48
- isRequired: {
49
- type: Boolean,
50
- default: false
51
- },
52
- helpText: {
53
- type: String,
54
- default: null
55
- },
56
- isForceUpdate: {
57
- type: Boolean,
58
- default: false
59
- },
60
- requiredErrorMessage: {
61
- type: String,
62
- default: 'Field is required'
63
- },
64
- defaultValue: {
65
- type: mongoose.Schema.Types.Mixed
66
- },
67
- validationRules: [{
68
- type: mongoose.Schema.Types.Mixed,
69
- default: {}
70
- }],
71
- visibilityCondition: { // (LendingType=='BTL' || ApplicationType=='Company')
72
- type: mongoose.Schema.Types.Mixed,
73
- default: null
74
- },
75
- options: [optionSchema],
76
- section: {
77
- type: String,
78
- default: null
79
- },
80
- // Ex: sort-code, post-code, pound, drop-down, lookup
81
- uiHint: {
82
- type: String
83
- },
84
- list: {
85
- name: { // Lookup.BusinessType, DocumentType(collection)
86
- type: String
87
- },
88
- label: { // name
89
- type: String
90
- },
91
- value: { // _id
92
- type: String
93
- },
94
- listFilterQuery: { // MongoDB query ex: applicationId:applicationId
95
- type: mongoose.Schema.Types.Mixed,
96
- default: null
97
- },
98
- dynamicSource: {
99
- sourceMapping: [{
100
- sourceField: {
101
- type: String,
102
- default: null
103
- },
104
- sourceValue: { type: mongoose.Schema.Types.Mixed },
105
- listName: { type: String }, // The collection name to use when source field has this value
106
- fixedValue: { type: mongoose.Schema.Types.Mixed } // It's not req , and it can be a number like 0 , or a string etc.
107
- }]
108
- }
109
- },
110
- isSyncEnabled: { // Fixed typo (was isSyncEnabed)
111
- type: Boolean,
112
- default: true
113
- },
114
- dataElement: { //<collectionName>.<fieldName>
115
- type: String,
116
- default: null
117
- },
118
- syncTargetDataElement: { //<collectionName>.<fieldName> of Apprivo
119
- type: String,
120
- default: null
121
- },
122
- syncMapping: mongoose.Schema.Types.Mixed, // Ex: {true:'Checked', false: ''}
123
- order: {
124
- type: Number,
125
- default: 0
126
- },
127
- maxLength: {
128
- type: Number,
129
- default: null,
130
- min: 0
131
- },
132
- maxValue: { // this is not required used only when given else ignore ex- 100% max
133
- type: mongoose.Schema.Types.Mixed
134
- },
135
- minValue: { // this is not required used only when given else ignore ex- 0% min
136
- type: Number
137
- },
138
- isReadOnly: {
139
- type: Boolean,
140
- default: false
141
- },
142
- collectionName: { // name of collection for field if field doesnt belong to main collection
143
- type: String,
144
- default: null
145
- },
146
- foreignReferenceField: { // Ex: when field is from forieng collection then foreignReferenceField could be applicationId(which refers to the application)
147
- type: String,
148
- default: null
149
- },
150
- shouldfilterOptionsAfterAdd: {
151
- type : Boolean,
152
- default : false
153
- },
154
- shouldfilterOptionsAfterDelete: {
155
- type : Boolean,
156
- default : false
157
- }
158
- }, { timestamps: true, _id: false });
159
-
160
- const formConfigurationSchema = new mongoose.Schema({
161
- formName: {
162
- type: String,
163
- required: true,
164
- trim: true,
165
- unique: true // Consider making form names unique
166
- },
167
- collectionName: {
168
- type: String,
169
- required: true
170
- },
171
- sectionLayout: {
172
- type: String,
173
- trim: true
174
- },
175
- parentKey: String,
176
- populations: [Object],
177
- visibilityCondition: {
178
- type: mongoose.Schema.Types.Mixed,
179
- default: null
180
- },
181
- sections: [{
182
- sectionName: {
183
- type: String,
184
- trim: true
185
- },
186
- sectionLabel: {
187
- type: String,
188
- trim: true
189
- },
190
- isArray: {
191
- type: Boolean,
192
- default: false
193
- },
194
- isTable: {
195
- type: Boolean,
196
- default: false
197
- },
198
- dataFromSectionName: {
199
- type: Boolean,
200
- default: false
201
- },
202
- fields: [formfieldSchema],
203
- order: {
204
- type: Number,
205
- default: 0
206
- },
207
- visibilityCondition: { // Added section-level visibility
208
- type: mongoose.Schema.Types.Mixed,
209
- default: null
210
- },
211
- sections: [{
212
- sectionName: {
213
- type: String,
214
- trim: true
215
- },
216
- sectionLabel: {
217
- type: String,
218
- trim: true
219
- },
220
- fields: [formfieldSchema],
221
- order: {
222
- type: Number,
223
- default: 0
224
- },
225
- isTable: {
226
- type: Boolean,
227
- default: false
228
- },
229
- visibilityCondition: { // Added section-level visibility
230
- type: mongoose.Schema.Types.Mixed,
231
- default: null
232
- }
233
- }]
234
- }],
235
- isActive: { // Consider adding status flag
236
- type: Boolean,
237
- default: true
238
- },
239
- isDeleteApprivoSync: {
240
- type: Boolean,
241
- default: true
242
- },
243
- isCreateApprivoSync: {
244
- type: Boolean,
245
- default: true
246
- },
247
- version: { // Consider adding versioning
248
- type: Number,
249
- default: 1
250
- }
251
- }, { timestamps: true });
252
-
253
- const FormConfigurationModel = mongoose.model('FormConfiguration', formConfigurationSchema);
254
-
255
- export default FormConfigurationModel;
1
+ import mongoose from 'mongoose';
2
+
3
+ const optionSchema = new mongoose.Schema({
4
+ label: { type: mongoose.Schema.Types.Mixed },
5
+ value: { type: mongoose.Schema.Types.Mixed },
6
+ text: { type: mongoose.Schema.Types.Mixed }
7
+
8
+ }, { _id: false });
9
+
10
+ const formfieldSchema = new mongoose.Schema({
11
+ isFutureDateBlocked: {
12
+ type: Boolean,
13
+ },
14
+ addToPayload: {
15
+ type: Boolean,
16
+ default: false
17
+ },
18
+ fieldName: {
19
+ type: String,
20
+ required: true,
21
+ trim: true
22
+ },
23
+ isHidden: {
24
+ type: Boolean,
25
+ default: false
26
+ },
27
+ isEditable: {
28
+ type: Boolean,
29
+ default: true
30
+ },
31
+ size: {
32
+ type: Number,
33
+ default: 6,
34
+ enum: [3, 4, 6, 8, 10, 12],
35
+ },
36
+ layout: {
37
+ type: String,
38
+ enum: ['horizontal', 'vertical'],
39
+ },
40
+ label: {
41
+ type: String,
42
+ required: true,
43
+ trim: true
44
+ },
45
+ dataType: {
46
+ type: String,
47
+ required: true,
48
+ enum: ['text-area', 'string', 'number', 'boolean-check', 'boolean-radio', 'percentage', 'date', 'array', 'object', 'select', 'radio', 'drop-down', 'sort-code', 'post-code', 'pound', 'lookup', 'multi-select', 'email', 'phone', 'internationalPhone'] // Added common form field types
49
+ },
50
+ isRequired: {
51
+ type: Boolean,
52
+ default: false
53
+ },
54
+ helpText: {
55
+ type: String,
56
+ default: null
57
+ },
58
+ isForceUpdate: {
59
+ type: Boolean,
60
+ default: false
61
+ },
62
+ requiredErrorMessage: {
63
+ type: String,
64
+ default: 'Field is required'
65
+ },
66
+ defaultValue: {
67
+ type: mongoose.Schema.Types.Mixed
68
+ },
69
+ validationRules: [{
70
+ type: mongoose.Schema.Types.Mixed,
71
+ default: {}
72
+ }],
73
+ visibilityCondition: { // (LendingType=='BTL' || ApplicationType=='Company')
74
+ type: mongoose.Schema.Types.Mixed,
75
+ default: null
76
+ },
77
+ options: [optionSchema],
78
+ section: {
79
+ type: String,
80
+ default: null
81
+ },
82
+ // Ex: sort-code, post-code, pound, drop-down, lookup
83
+ uiHint: {
84
+ type: String
85
+ },
86
+ list: {
87
+ name: { // Lookup.BusinessType, DocumentType(collection)
88
+ type: String
89
+ },
90
+ label: { // name
91
+ type: String
92
+ },
93
+ value: { // _id
94
+ type: String
95
+ },
96
+ listFilterQuery: { // MongoDB query ex: applicationId:applicationId
97
+ type: mongoose.Schema.Types.Mixed,
98
+ default: null
99
+ },
100
+ dynamicSource: {
101
+ sourceMapping: [{
102
+ sourceField: {
103
+ type: String,
104
+ default: null
105
+ },
106
+ sourceValue: { type: mongoose.Schema.Types.Mixed },
107
+ listName: { type: String }, // The collection name to use when source field has this value
108
+ fixedValue: { type: mongoose.Schema.Types.Mixed } // It's not req , and it can be a number like 0 , or a string etc.
109
+ }]
110
+ }
111
+ },
112
+ isSyncEnabled: { // Fixed typo (was isSyncEnabed)
113
+ type: Boolean,
114
+ default: true
115
+ },
116
+ dataElement: { //<collectionName>.<fieldName>
117
+ type: String,
118
+ default: null
119
+ },
120
+ syncTargetDataElement: { //<collectionName>.<fieldName> of Apprivo
121
+ type: String,
122
+ default: null
123
+ },
124
+ syncMapping: mongoose.Schema.Types.Mixed, // Ex: {true:'Checked', false: ''}
125
+ order: {
126
+ type: Number,
127
+ default: 0
128
+ },
129
+ maxLength: {
130
+ type: Number,
131
+ default: null,
132
+ min: 0
133
+ },
134
+ maxValue: { // this is not required used only when given else ignore ex- 100% max
135
+ type: mongoose.Schema.Types.Mixed
136
+ },
137
+ minValue: { // this is not required used only when given else ignore ex- 0% min
138
+ type: Number
139
+ },
140
+ isReadOnly: {
141
+ type: Boolean,
142
+ default: false
143
+ },
144
+ collectionName: { // name of collection for field if field doesnt belong to main collection
145
+ type: String,
146
+ default: null
147
+ },
148
+ foreignReferenceField: { // Ex: when field is from forieng collection then foreignReferenceField could be applicationId(which refers to the application)
149
+ type: String,
150
+ default: null
151
+ },
152
+ shouldfilterOptionsAfterAdd: {
153
+ type : Boolean,
154
+ default : false
155
+ },
156
+ shouldfilterOptionsAfterDelete: {
157
+ type : Boolean,
158
+ default : false
159
+ }
160
+ }, { timestamps: true, _id: false });
161
+
162
+ const formConfigurationSchema = new mongoose.Schema({
163
+ formName: {
164
+ type: String,
165
+ required: true,
166
+ trim: true,
167
+ unique: true // Consider making form names unique
168
+ },
169
+ collectionName: {
170
+ type: String,
171
+ required: true
172
+ },
173
+ sectionLayout: {
174
+ type: String,
175
+ trim: true
176
+ },
177
+ parentKey: String,
178
+ populations: [Object],
179
+ visibilityCondition: {
180
+ type: mongoose.Schema.Types.Mixed,
181
+ default: null
182
+ },
183
+ sections: [{
184
+ sectionName: {
185
+ type: String,
186
+ trim: true
187
+ },
188
+ sectionLabel: {
189
+ type: String,
190
+ trim: true
191
+ },
192
+ isArray: {
193
+ type: Boolean,
194
+ default: false
195
+ },
196
+ isTable: {
197
+ type: Boolean,
198
+ default: false
199
+ },
200
+ dataFromSectionName: {
201
+ type: Boolean,
202
+ default: false
203
+ },
204
+ fields: [formfieldSchema],
205
+ order: {
206
+ type: Number,
207
+ default: 0
208
+ },
209
+ visibilityCondition: { // Added section-level visibility
210
+ type: mongoose.Schema.Types.Mixed,
211
+ default: null
212
+ },
213
+ sections: [{
214
+ sectionName: {
215
+ type: String,
216
+ trim: true
217
+ },
218
+ sectionLabel: {
219
+ type: String,
220
+ trim: true
221
+ },
222
+ fields: [formfieldSchema],
223
+ order: {
224
+ type: Number,
225
+ default: 0
226
+ },
227
+ isTable: {
228
+ type: Boolean,
229
+ default: false
230
+ },
231
+ visibilityCondition: { // Added section-level visibility
232
+ type: mongoose.Schema.Types.Mixed,
233
+ default: null
234
+ }
235
+ }]
236
+ }],
237
+ isActive: { // Consider adding status flag
238
+ type: Boolean,
239
+ default: true
240
+ },
241
+ isDeleteApprivoSync: {
242
+ type: Boolean,
243
+ default: true
244
+ },
245
+ isCreateApprivoSync: {
246
+ type: Boolean,
247
+ default: true
248
+ },
249
+ version: { // Consider adding versioning
250
+ type: Number,
251
+ default: 1
252
+ }
253
+ }, { timestamps: true });
254
+
255
+ const FormConfigurationModel = mongoose.model('FormConfiguration', formConfigurationSchema);
256
+
257
+ export default FormConfigurationModel;
package/models/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export { default as AuditConfigModel } from './audit-config.model.js';
2
- export { default as AuditModel } from './audit.model.js';
3
- export { default as ValueReferenceMapModel } from './value-reference-map.model.js';
1
+ export { default as AuditConfigModel } from './audit-config.model.js';
2
+ export { default as AuditModel } from './audit.model.js';
3
+ export { default as ValueReferenceMapModel } from './value-reference-map.model.js';
4
4
  export { default as FormConfigurationModel } from './form-configuration.model.js';
@@ -1,12 +1,12 @@
1
- import mongoose from 'mongoose';
2
-
3
- const valueReferenceMapSchema = new mongoose.Schema({
4
- field: String, // e.g. 'documentTypeId', 'createdBy', 'status'
5
- model: String, // e.g. 'DocumentType', 'User', 'ApplicationStatus'
6
- displayField: String, // e.g. 'name', 'fullName', 'label'
7
- });
8
-
9
- valueReferenceMapSchema.index({ field: 1 }, { unique: true });
10
-
11
- const ValueReferenceMapModel = mongoose.model('ValueReferenceMap', valueReferenceMapSchema);
12
- export default ValueReferenceMapModel;
1
+ import mongoose from 'mongoose';
2
+
3
+ const valueReferenceMapSchema = new mongoose.Schema({
4
+ field: String, // e.g. 'documentTypeId', 'createdBy', 'status'
5
+ model: String, // e.g. 'DocumentType', 'User', 'ApplicationStatus'
6
+ displayField: String, // e.g. 'name', 'fullName', 'label'
7
+ });
8
+
9
+ valueReferenceMapSchema.index({ field: 1 }, { unique: true });
10
+
11
+ const ValueReferenceMapModel = mongoose.model('ValueReferenceMap', valueReferenceMapSchema);
12
+ export default ValueReferenceMapModel;
package/package.json CHANGED
@@ -1,21 +1,21 @@
1
- {
2
- "name": "@dynamatix/cat-shared",
3
- "version": "0.0.65",
4
- "main": "index.js",
5
- "scripts": {
6
- "test": "echo \"Error: no test specified\" && exit 1"
7
- },
8
- "author": "",
9
- "license": "ISC",
10
- "type": "module",
11
- "description": "",
12
- "exports": {
13
- "./models": "./models/index.js",
14
- "./middlewares": "./middlewares/index.js",
15
- "./services": "./services/index.js"
16
- },
17
- "dependencies": {
18
- "dotenv": "^16.4.7",
19
- "mongoose": "^8.13.1"
20
- }
21
- }
1
+ {
2
+ "name": "@dynamatix/cat-shared",
3
+ "version": "0.0.67",
4
+ "main": "index.js",
5
+ "scripts": {
6
+ "test": "echo \"Error: no test specified\" && exit 1"
7
+ },
8
+ "author": "",
9
+ "license": "ISC",
10
+ "type": "module",
11
+ "description": "",
12
+ "exports": {
13
+ "./models": "./models/index.js",
14
+ "./middlewares": "./middlewares/index.js",
15
+ "./services": "./services/index.js"
16
+ },
17
+ "dependencies": {
18
+ "dotenv": "^16.4.7",
19
+ "mongoose": "^8.13.1"
20
+ }
21
+ }
@@ -1,66 +1,66 @@
1
- import mongoose, { model } from 'mongoose';
2
- import dotenv from 'dotenv';
3
- import ValueReferenceMapModel from '../models/value-reference-map.model.js';
4
-
5
- dotenv.config();
6
-
7
- const MONGO_URI = 'mongodb+srv://qa-user:vw4sIy3lZpyTPoX0@gatehouse-testing.e08r2.mongodb.net/gatehouse-qa?retryWrites=true&w=majority';
8
-
9
- // Grouped definition (DRY)
10
- const groupedMappings = [
11
- {
12
- model: 'DocumentType',
13
- displayField: 'name',
14
- fields: ['documentTypeId']
15
- },
16
- {
17
- model: 'User',
18
- displayField: 'fullName',
19
- fields: ['createdBy', 'updatedBy', 'ownerId','documentOwnerId']
20
- },
21
- {
22
- model: 'Applicant',
23
- displayField: 'firstName',
24
- fields: ['documentOwnerId']
25
- }
26
- ];
27
-
28
- // Flatten the mappings
29
- const referenceMappings = groupedMappings.flatMap(group =>
30
- group.fields.map(field => ({
31
- field,
32
- model: group.model,
33
- displayField: group.displayField
34
- }))
35
- );
36
-
37
- async function seed() {
38
- try {
39
- console.log(MONGO_URI);
40
- await mongoose.connect(MONGO_URI);
41
- console.log('āœ… Connected to MongoDB');
42
-
43
- for (const mapping of referenceMappings) {
44
- const existing = await ValueReferenceMapModel.findOne({ field: mapping.field });
45
- if (existing) {
46
- await ValueReferenceMapModel.updateOne(
47
- { field: mapping.field },
48
- { $set: mapping }
49
- );
50
- console.log(`šŸ”„ Updated mapping for '${mapping.field}'`);
51
- } else {
52
- await ValueReferenceMapModel.create(mapping);
53
- console.log(`āž• Inserted mapping for '${mapping.field}'`);
54
- }
55
- }
56
-
57
- console.log('\n🌱 Seeding complete āœ…');
58
- } catch (err) {
59
- console.error('āŒ Seeding failed', err);
60
- } finally {
61
- await mongoose.disconnect();
62
- process.exit();
63
- }
64
- }
65
-
66
- seed();
1
+ import mongoose, { model } from 'mongoose';
2
+ import dotenv from 'dotenv';
3
+ import ValueReferenceMapModel from '../models/value-reference-map.model.js';
4
+
5
+ dotenv.config();
6
+
7
+ const MONGO_URI = 'mongodb+srv://qa-user:vw4sIy3lZpyTPoX0@gatehouse-testing.e08r2.mongodb.net/gatehouse-qa?retryWrites=true&w=majority';
8
+
9
+ // Grouped definition (DRY)
10
+ const groupedMappings = [
11
+ {
12
+ model: 'DocumentType',
13
+ displayField: 'name',
14
+ fields: ['documentTypeId']
15
+ },
16
+ {
17
+ model: 'User',
18
+ displayField: 'fullName',
19
+ fields: ['createdBy', 'updatedBy', 'ownerId','documentOwnerId']
20
+ },
21
+ {
22
+ model: 'Applicant',
23
+ displayField: 'firstName',
24
+ fields: ['documentOwnerId', 'applicantId']
25
+ }
26
+ ];
27
+
28
+ // Flatten the mappings
29
+ const referenceMappings = groupedMappings.flatMap(group =>
30
+ group.fields.map(field => ({
31
+ field,
32
+ model: group.model,
33
+ displayField: group.displayField
34
+ }))
35
+ );
36
+
37
+ async function seed() {
38
+ try {
39
+ console.log(MONGO_URI);
40
+ await mongoose.connect(MONGO_URI);
41
+ console.log('āœ… Connected to MongoDB');
42
+
43
+ for (const mapping of referenceMappings) {
44
+ const existing = await ValueReferenceMapModel.findOne({ field: mapping.field });
45
+ if (existing) {
46
+ await ValueReferenceMapModel.updateOne(
47
+ { field: mapping.field },
48
+ { $set: mapping }
49
+ );
50
+ console.log(`šŸ”„ Updated mapping for '${mapping.field}'`);
51
+ } else {
52
+ await ValueReferenceMapModel.create(mapping);
53
+ console.log(`āž• Inserted mapping for '${mapping.field}'`);
54
+ }
55
+ }
56
+
57
+ console.log('\n🌱 Seeding complete āœ…');
58
+ } catch (err) {
59
+ console.error('āŒ Seeding failed', err);
60
+ } finally {
61
+ await mongoose.disconnect();
62
+ process.exit();
63
+ }
64
+ }
65
+
66
+ seed();
@@ -1,2 +1,2 @@
1
-
2
-
1
+
2
+
package/services/index.js CHANGED
@@ -1 +1 @@
1
- export { getContext, setContext } from './request-context.service.js';
1
+ export { getContext, setContext } from './request-context.service.js';
@@ -1,8 +1,8 @@
1
- // utils/request-context.js
2
- import { AsyncLocalStorage } from 'node:async_hooks';
3
-
4
- const asyncLocalStorage = new AsyncLocalStorage();
5
-
6
- export const setContext = (data) => asyncLocalStorage.enterWith(data);
7
-
8
- export const getContext = () => asyncLocalStorage.getStore();
1
+ // utils/request-context.js
2
+ import { AsyncLocalStorage } from 'node:async_hooks';
3
+
4
+ const asyncLocalStorage = new AsyncLocalStorage();
5
+
6
+ export const setContext = (data) => asyncLocalStorage.enterWith(data);
7
+
8
+ export const getContext = () => asyncLocalStorage.getStore();