@memberjunction/global 2.111.0 → 2.112.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Core.d.ts +29 -0
- package/dist/Core.d.ts.map +1 -0
- package/dist/Core.js +58 -0
- package/dist/Core.js.map +1 -0
- package/dist/generic/QueryCache.d.ts +85 -0
- package/dist/generic/QueryCache.d.ts.map +1 -0
- package/dist/generic/QueryCache.js +198 -0
- package/dist/generic/QueryCache.js.map +1 -0
- package/dist/generic/QueryCacheConfig.d.ts +72 -0
- package/dist/generic/QueryCacheConfig.d.ts.map +1 -0
- package/dist/generic/QueryCacheConfig.js +3 -0
- package/dist/generic/QueryCacheConfig.js.map +1 -0
- package/dist/generic/applicationInfo.d.ts +138 -0
- package/dist/generic/applicationInfo.d.ts.map +1 -0
- package/dist/generic/applicationInfo.js +177 -0
- package/dist/generic/applicationInfo.js.map +1 -0
- package/dist/generic/authEvaluator.d.ts +25 -0
- package/dist/generic/authEvaluator.d.ts.map +1 -0
- package/dist/generic/authEvaluator.js +49 -0
- package/dist/generic/authEvaluator.js.map +1 -0
- package/dist/generic/authTypes.d.ts +193 -0
- package/dist/generic/authTypes.d.ts.map +1 -0
- package/dist/generic/authTypes.js +19 -0
- package/dist/generic/authTypes.js.map +1 -0
- package/dist/generic/baseEngine.d.ts +260 -0
- package/dist/generic/baseEngine.d.ts.map +1 -0
- package/dist/generic/baseEngine.js +510 -0
- package/dist/generic/baseEngine.js.map +1 -0
- package/dist/generic/baseEntity.d.ts +691 -0
- package/dist/generic/baseEntity.d.ts.map +1 -0
- package/dist/generic/baseEntity.js +1688 -0
- package/dist/generic/baseEntity.js.map +1 -0
- package/dist/generic/baseInfo.d.ts +24 -0
- package/dist/generic/baseInfo.d.ts.map +1 -0
- package/dist/generic/baseInfo.js +53 -0
- package/dist/generic/baseInfo.js.map +1 -0
- package/dist/generic/compositeKey.d.ts +206 -0
- package/dist/generic/compositeKey.d.ts.map +1 -0
- package/dist/generic/compositeKey.js +412 -0
- package/dist/generic/compositeKey.js.map +1 -0
- package/dist/generic/databaseProviderBase.d.ts +46 -0
- package/dist/generic/databaseProviderBase.d.ts.map +1 -0
- package/dist/generic/databaseProviderBase.js +14 -0
- package/dist/generic/databaseProviderBase.js.map +1 -0
- package/dist/generic/entityInfo.d.ts +983 -0
- package/dist/generic/entityInfo.d.ts.map +1 -0
- package/dist/generic/entityInfo.js +1401 -0
- package/dist/generic/entityInfo.js.map +1 -0
- package/dist/generic/explorerNavigationItem.d.ts +20 -0
- package/dist/generic/explorerNavigationItem.d.ts.map +1 -0
- package/dist/generic/explorerNavigationItem.js +29 -0
- package/dist/generic/explorerNavigationItem.js.map +1 -0
- package/dist/generic/interfaces.d.ts +610 -0
- package/dist/generic/interfaces.d.ts.map +1 -0
- package/dist/generic/interfaces.js +211 -0
- package/dist/generic/interfaces.js.map +1 -0
- package/dist/generic/libraryInfo.d.ts +40 -0
- package/dist/generic/libraryInfo.d.ts.map +1 -0
- package/dist/generic/libraryInfo.js +56 -0
- package/dist/generic/libraryInfo.js.map +1 -0
- package/dist/generic/logging.d.ts +179 -0
- package/dist/generic/logging.d.ts.map +1 -0
- package/dist/generic/logging.js +382 -0
- package/dist/generic/logging.js.map +1 -0
- package/dist/generic/metadata.d.ts +305 -0
- package/dist/generic/metadata.d.ts.map +1 -0
- package/dist/generic/metadata.js +454 -0
- package/dist/generic/metadata.js.map +1 -0
- package/dist/generic/metadataUtil.d.ts +8 -0
- package/dist/generic/metadataUtil.d.ts.map +1 -0
- package/dist/generic/metadataUtil.js +36 -0
- package/dist/generic/metadataUtil.js.map +1 -0
- package/dist/generic/providerBase.d.ts +546 -0
- package/dist/generic/providerBase.d.ts.map +1 -0
- package/dist/generic/providerBase.js +999 -0
- package/dist/generic/providerBase.js.map +1 -0
- package/dist/generic/queryInfo.d.ts +460 -0
- package/dist/generic/queryInfo.d.ts.map +1 -0
- package/dist/generic/queryInfo.js +633 -0
- package/dist/generic/queryInfo.js.map +1 -0
- package/dist/generic/querySQLFilters.d.ts +54 -0
- package/dist/generic/querySQLFilters.d.ts.map +1 -0
- package/dist/generic/querySQLFilters.js +84 -0
- package/dist/generic/querySQLFilters.js.map +1 -0
- package/dist/generic/runQuery.d.ts +96 -0
- package/dist/generic/runQuery.d.ts.map +1 -0
- package/dist/generic/runQuery.js +66 -0
- package/dist/generic/runQuery.js.map +1 -0
- package/dist/generic/runQuerySQLFilterImplementations.d.ts +51 -0
- package/dist/generic/runQuerySQLFilterImplementations.d.ts.map +1 -0
- package/dist/generic/runQuerySQLFilterImplementations.js +238 -0
- package/dist/generic/runQuerySQLFilterImplementations.js.map +1 -0
- package/dist/generic/runReport.d.ts +25 -0
- package/dist/generic/runReport.d.ts.map +1 -0
- package/dist/generic/runReport.js +42 -0
- package/dist/generic/runReport.js.map +1 -0
- package/dist/generic/securityInfo.d.ts +355 -0
- package/dist/generic/securityInfo.d.ts.map +1 -0
- package/dist/generic/securityInfo.js +425 -0
- package/dist/generic/securityInfo.js.map +1 -0
- package/dist/generic/transactionGroup.d.ts +184 -0
- package/dist/generic/transactionGroup.d.ts.map +1 -0
- package/dist/generic/transactionGroup.js +357 -0
- package/dist/generic/transactionGroup.js.map +1 -0
- package/dist/generic/util.d.ts +81 -0
- package/dist/generic/util.d.ts.map +1 -0
- package/dist/generic/util.js +301 -0
- package/dist/generic/util.js.map +1 -0
- package/dist/views/runView.d.ts +150 -0
- package/dist/views/runView.d.ts.map +1 -0
- package/dist/views/runView.js +100 -0
- package/dist/views/runView.js.map +1 -0
- package/dist/views/viewInfo.d.ts +121 -0
- package/dist/views/viewInfo.d.ts.map +1 -0
- package/dist/views/viewInfo.js +182 -0
- package/dist/views/viewInfo.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,1401 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RecordMergeResult = exports.RecordMergeDetailResult = exports.RecordMergeRequest = exports.RecordDependency = exports.EntityDependency = exports.EntityInfo = exports.EntitySettingInfo = exports.EntityDocumentTypeInfo = exports.EntityFieldInfo = exports.GeneratedFormSectionType = exports.EntityFieldValueInfo = exports.EntityFieldValueListType = exports.EntityFieldGraphQLType = exports.EntityFieldTSType = exports.EntityPermissionInfo = exports.EntityUserPermissionInfo = exports.EntityPermissionType = exports.EntityRelationshipInfo = exports.RecordChange = exports.RecordChangeStatus = void 0;
|
|
4
|
+
const baseInfo_1 = require("./baseInfo");
|
|
5
|
+
const metadata_1 = require("./metadata");
|
|
6
|
+
const util_1 = require("./util");
|
|
7
|
+
const logging_1 = require("./logging");
|
|
8
|
+
/**
|
|
9
|
+
* The possible status values for a record change
|
|
10
|
+
*/
|
|
11
|
+
exports.RecordChangeStatus = {
|
|
12
|
+
Pending: 'Pending',
|
|
13
|
+
Complete: 'Complete',
|
|
14
|
+
Error: 'Error',
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Record Change object has information on a change to a record in the Record Changes entity
|
|
18
|
+
*/
|
|
19
|
+
class RecordChange extends baseInfo_1.BaseInfo {
|
|
20
|
+
get StatusValue() {
|
|
21
|
+
return exports.RecordChangeStatus[this.Status?.trim()];
|
|
22
|
+
}
|
|
23
|
+
get Changes() {
|
|
24
|
+
return JSON.parse(this.ChangesJSON);
|
|
25
|
+
}
|
|
26
|
+
get FullRecord() {
|
|
27
|
+
return JSON.parse(this.FullRecordJSON);
|
|
28
|
+
}
|
|
29
|
+
constructor(initData) {
|
|
30
|
+
super();
|
|
31
|
+
this.ID = null;
|
|
32
|
+
this.EntityID = null;
|
|
33
|
+
this.RecordID = null;
|
|
34
|
+
this.ChangedAt = null;
|
|
35
|
+
this.ChangesJSON = null;
|
|
36
|
+
this.ChangesDescription = null;
|
|
37
|
+
this.FullRecordJSON = null;
|
|
38
|
+
this.Status = null;
|
|
39
|
+
this.copyInitData(initData);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
exports.RecordChange = RecordChange;
|
|
43
|
+
/**
|
|
44
|
+
* Information about the Entity Relationship between the Entity and the Related Entity - this class
|
|
45
|
+
* maps to information in the Entity Relationships metadata entity.
|
|
46
|
+
*/
|
|
47
|
+
/**
|
|
48
|
+
* Metadata about relationships between entities including display preferences for the UI.
|
|
49
|
+
* Defines foreign key relationships and how they should be represented in the user interface.
|
|
50
|
+
*/
|
|
51
|
+
class EntityRelationshipInfo extends baseInfo_1.BaseInfo {
|
|
52
|
+
constructor(initData) {
|
|
53
|
+
super();
|
|
54
|
+
this.ID = null;
|
|
55
|
+
this.EntityID = null;
|
|
56
|
+
this.Sequence = null;
|
|
57
|
+
this.RelatedEntityID = null;
|
|
58
|
+
this.BundleInAPI = null;
|
|
59
|
+
this.IncludeInParentAllQuery = null;
|
|
60
|
+
this.Type = null;
|
|
61
|
+
this.EntityKeyField = null;
|
|
62
|
+
this.RelatedEntityJoinField = null;
|
|
63
|
+
this.JoinView = null;
|
|
64
|
+
this.JoinEntityJoinField = null;
|
|
65
|
+
this.JoinEntityInverseJoinField = null;
|
|
66
|
+
this.DisplayInForm = null;
|
|
67
|
+
this.DisplayLocation = 'After Field Tabs';
|
|
68
|
+
this.DisplayName = null;
|
|
69
|
+
this.DisplayIconType = 'Related Entity Icon';
|
|
70
|
+
this.DisplayIcon = null;
|
|
71
|
+
this.DisplayUserViewID = null;
|
|
72
|
+
this.DisplayComponentID = null;
|
|
73
|
+
this.DisplayComponentConfiguration = null;
|
|
74
|
+
this.__mj_CreatedAt = null;
|
|
75
|
+
this.__mj_UpdatedAt = null;
|
|
76
|
+
/**
|
|
77
|
+
* * Field Name: AutoUpdateFromSchema
|
|
78
|
+
* * Display Name: Auto Update From Schema
|
|
79
|
+
* * SQL Data Type: bit
|
|
80
|
+
* * Default Value: true
|
|
81
|
+
* * Description: Indicates whether this relationship should be automatically updated by CodeGen. When set to 0, the record will not be modified by CodeGen. Defaults to true.
|
|
82
|
+
*/
|
|
83
|
+
this.AutoUpdateFromSchema = true;
|
|
84
|
+
// virtual fields - returned by the database VIEW
|
|
85
|
+
this.Entity = null;
|
|
86
|
+
this.EntityBaseTable = null;
|
|
87
|
+
this.EntityBaseView = null;
|
|
88
|
+
this.RelatedEntity = null;
|
|
89
|
+
this.RelatedEntityBaseTable = null;
|
|
90
|
+
this.RelatedEntityBaseView = null;
|
|
91
|
+
this.RelatedEntityCodeName = null;
|
|
92
|
+
this.RelatedEntityClassName = null;
|
|
93
|
+
this.RelatedEntityBaseTableCodeName = null;
|
|
94
|
+
this.DisplayUserViewName = null;
|
|
95
|
+
this.DisplayComponent = null;
|
|
96
|
+
this.copyInitData(initData);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
exports.EntityRelationshipInfo = EntityRelationshipInfo;
|
|
100
|
+
exports.EntityPermissionType = {
|
|
101
|
+
Read: 'Read',
|
|
102
|
+
Create: 'Create',
|
|
103
|
+
Update: 'Update',
|
|
104
|
+
Delete: 'Delete',
|
|
105
|
+
};
|
|
106
|
+
class EntityUserPermissionInfo {
|
|
107
|
+
constructor() {
|
|
108
|
+
this.ID = null;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
exports.EntityUserPermissionInfo = EntityUserPermissionInfo;
|
|
112
|
+
/**
|
|
113
|
+
* Security settings for each entity.
|
|
114
|
+
* Controls which roles can perform create, read, update, and delete operations.
|
|
115
|
+
*/
|
|
116
|
+
class EntityPermissionInfo extends baseInfo_1.BaseInfo {
|
|
117
|
+
get CreateRLSFilterObject() {
|
|
118
|
+
return this.RLSFilter(exports.EntityPermissionType.Create);
|
|
119
|
+
}
|
|
120
|
+
get ReadRLSFilterObject() {
|
|
121
|
+
return this.RLSFilter(exports.EntityPermissionType.Read);
|
|
122
|
+
}
|
|
123
|
+
get UpdateRLSFilterObject() {
|
|
124
|
+
return this.RLSFilter(exports.EntityPermissionType.Update);
|
|
125
|
+
}
|
|
126
|
+
get DeleteRLSFilterObject() {
|
|
127
|
+
return this.RLSFilter(exports.EntityPermissionType.Delete);
|
|
128
|
+
}
|
|
129
|
+
RLSFilter(type) {
|
|
130
|
+
let fID = '';
|
|
131
|
+
switch (type) {
|
|
132
|
+
case exports.EntityPermissionType.Read:
|
|
133
|
+
fID = this.ReadRLSFilterID;
|
|
134
|
+
break;
|
|
135
|
+
case exports.EntityPermissionType.Create:
|
|
136
|
+
fID = this.CreateRLSFilterID;
|
|
137
|
+
break;
|
|
138
|
+
case exports.EntityPermissionType.Update:
|
|
139
|
+
fID = this.UpdateRLSFilterID;
|
|
140
|
+
break;
|
|
141
|
+
case exports.EntityPermissionType.Delete:
|
|
142
|
+
fID = this.DeleteRLSFilterID;
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
if (fID && fID.length > 0)
|
|
146
|
+
return metadata_1.Metadata.Provider.RowLevelSecurityFilters.find((f) => f.ID === fID);
|
|
147
|
+
}
|
|
148
|
+
constructor(initData) {
|
|
149
|
+
super();
|
|
150
|
+
this.ID = null;
|
|
151
|
+
this.EntityID = null;
|
|
152
|
+
this.RoleID = null;
|
|
153
|
+
this.CanCreate = null;
|
|
154
|
+
this.CanRead = null;
|
|
155
|
+
this.CanUpdate = null;
|
|
156
|
+
this.CanDelete = null;
|
|
157
|
+
this.ReadRLSFilterID = null;
|
|
158
|
+
this.CreateRLSFilterID = null;
|
|
159
|
+
this.UpdateRLSFilterID = null;
|
|
160
|
+
this.DeleteRLSFilterID = null;
|
|
161
|
+
this.__mj_CreatedAt = null;
|
|
162
|
+
this.__mj_UpdatedAt = null;
|
|
163
|
+
// virtual fields - returned by the database VIEW
|
|
164
|
+
this.Entity = null;
|
|
165
|
+
this.Role = null;
|
|
166
|
+
this.RoleSQLName = null;
|
|
167
|
+
this.ReadRLSFilter = null;
|
|
168
|
+
this.CreateRLSFilter = null;
|
|
169
|
+
this.UpdateRLSFilter = null;
|
|
170
|
+
this.DeleteRLSFilter = null;
|
|
171
|
+
this.copyInitData(initData);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
exports.EntityPermissionInfo = EntityPermissionInfo;
|
|
175
|
+
exports.EntityFieldTSType = {
|
|
176
|
+
String: 'string',
|
|
177
|
+
Number: 'number',
|
|
178
|
+
Date: 'Date',
|
|
179
|
+
Boolean: 'boolean',
|
|
180
|
+
};
|
|
181
|
+
exports.EntityFieldGraphQLType = {
|
|
182
|
+
Int: 'Int',
|
|
183
|
+
Float: 'Float',
|
|
184
|
+
String: 'String',
|
|
185
|
+
Boolean: 'Boolean',
|
|
186
|
+
Timestamp: 'Timestamp',
|
|
187
|
+
};
|
|
188
|
+
exports.EntityFieldValueListType = {
|
|
189
|
+
None: 'None',
|
|
190
|
+
List: 'List',
|
|
191
|
+
ListOrUserEntry: 'ListOrUserEntry',
|
|
192
|
+
};
|
|
193
|
+
/**
|
|
194
|
+
* Defines allowed values for entity fields with value lists.
|
|
195
|
+
* Supports dropdowns, validations, and data integrity constraints.
|
|
196
|
+
*/
|
|
197
|
+
class EntityFieldValueInfo extends baseInfo_1.BaseInfo {
|
|
198
|
+
constructor(initData) {
|
|
199
|
+
super();
|
|
200
|
+
this.ID = null;
|
|
201
|
+
this.EntityFieldID = null; // EntityFieldID is a uniqueidentifier column
|
|
202
|
+
this.Sequence = null;
|
|
203
|
+
this.Value = null;
|
|
204
|
+
this.Code = null;
|
|
205
|
+
this.Description = null;
|
|
206
|
+
this.__mj_CreatedAt = null;
|
|
207
|
+
this.__mj_UpdatedAt = null;
|
|
208
|
+
this.copyInitData(initData);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
exports.EntityFieldValueInfo = EntityFieldValueInfo;
|
|
212
|
+
exports.GeneratedFormSectionType = {
|
|
213
|
+
Top: 'Top',
|
|
214
|
+
Details: 'Details',
|
|
215
|
+
Category: 'Category',
|
|
216
|
+
};
|
|
217
|
+
/**
|
|
218
|
+
* Field information within an entity - object models data from the Entity Fields entity in the metadata
|
|
219
|
+
*/
|
|
220
|
+
/**
|
|
221
|
+
* List of all fields within each entity with metadata about each field.
|
|
222
|
+
* Includes data types, relationships, defaults, and UI display preferences.
|
|
223
|
+
*/
|
|
224
|
+
class EntityFieldInfo extends baseInfo_1.BaseInfo {
|
|
225
|
+
get EntityFieldValues() {
|
|
226
|
+
return this._EntityFieldValues;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Returns the ValueListType using the EntityFieldValueListType enum.
|
|
230
|
+
*/
|
|
231
|
+
get ValueListTypeEnum() {
|
|
232
|
+
if (this.ValueListType == null)
|
|
233
|
+
return exports.EntityFieldValueListType.None;
|
|
234
|
+
else {
|
|
235
|
+
// iterate through list of possibilities from enum and compare lcase
|
|
236
|
+
for (let enumMember in exports.EntityFieldValueListType) {
|
|
237
|
+
if (typeof exports.EntityFieldValueListType[enumMember] === 'string' &&
|
|
238
|
+
enumMember.toLowerCase().trim() === this.ValueListType.toLowerCase().trim()) {
|
|
239
|
+
return exports.EntityFieldValueListType[enumMember];
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
get GeneratedFormSectionType() {
|
|
245
|
+
return exports.GeneratedFormSectionType[this.GeneratedFormSection];
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Provides the TypeScript type for a given Entity Field. This is useful to map
|
|
249
|
+
* a wide array of database types to a narrower set of TypeScript types.
|
|
250
|
+
*/
|
|
251
|
+
get TSType() {
|
|
252
|
+
switch ((0, util_1.TypeScriptTypeFromSQLType)(this.Type).toLowerCase()) {
|
|
253
|
+
case 'number':
|
|
254
|
+
return exports.EntityFieldTSType.Number;
|
|
255
|
+
case 'boolean':
|
|
256
|
+
return exports.EntityFieldTSType.Boolean;
|
|
257
|
+
case 'date':
|
|
258
|
+
return exports.EntityFieldTSType.Date;
|
|
259
|
+
default:
|
|
260
|
+
return exports.EntityFieldTSType.String;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Returns true if the field type is a binary type such as binary, varbinary, or image.
|
|
265
|
+
*/
|
|
266
|
+
get IsBinaryFieldType() {
|
|
267
|
+
switch (this.Type.trim().toLowerCase()) {
|
|
268
|
+
case 'binary':
|
|
269
|
+
case 'varbinary':
|
|
270
|
+
case 'image':
|
|
271
|
+
return true;
|
|
272
|
+
default:
|
|
273
|
+
return false;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Returns the Unicode prefix (N) if the field type requires it, otherwise returns an empty string.
|
|
278
|
+
*/
|
|
279
|
+
get UnicodePrefix() {
|
|
280
|
+
if (this.RequiredUnicodePrefix) {
|
|
281
|
+
return 'N';
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
return '';
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Returns true if the field type requires a Unicode prefix (N) when used in a SQL statement.
|
|
289
|
+
*/
|
|
290
|
+
get RequiredUnicodePrefix() {
|
|
291
|
+
switch (this.Type.trim().toLowerCase()) {
|
|
292
|
+
case 'nchar':
|
|
293
|
+
case 'nvarchar':
|
|
294
|
+
case 'ntext':
|
|
295
|
+
return true;
|
|
296
|
+
default:
|
|
297
|
+
return false;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Returns true if the field type requires quotes around the value when used in a SQL statement
|
|
302
|
+
*/
|
|
303
|
+
get NeedsQuotes() {
|
|
304
|
+
switch (this.TSType) {
|
|
305
|
+
case exports.EntityFieldTSType.Number:
|
|
306
|
+
case exports.EntityFieldTSType.Boolean:
|
|
307
|
+
return false;
|
|
308
|
+
default:
|
|
309
|
+
return true;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
get CodeName() {
|
|
313
|
+
if (this._codeName === null) {
|
|
314
|
+
this._codeName = (0, util_1.CodeNameFromString)(this.Name);
|
|
315
|
+
}
|
|
316
|
+
return this._codeName;
|
|
317
|
+
}
|
|
318
|
+
get GraphQLType() {
|
|
319
|
+
switch ((0, util_1.TypeScriptTypeFromSQLType)(this.Type).toLowerCase()) {
|
|
320
|
+
case 'number':
|
|
321
|
+
// either an int or float if not an int
|
|
322
|
+
switch (this.Type.toLowerCase().trim()) {
|
|
323
|
+
case 'int':
|
|
324
|
+
case 'smallint':
|
|
325
|
+
case 'tinyint':
|
|
326
|
+
case 'bigint':
|
|
327
|
+
return exports.EntityFieldGraphQLType.Int;
|
|
328
|
+
default:
|
|
329
|
+
return exports.EntityFieldGraphQLType.Float;
|
|
330
|
+
}
|
|
331
|
+
case 'boolean':
|
|
332
|
+
return exports.EntityFieldGraphQLType.Boolean;
|
|
333
|
+
case 'date':
|
|
334
|
+
return exports.EntityFieldGraphQLType.Timestamp;
|
|
335
|
+
default:
|
|
336
|
+
return exports.EntityFieldGraphQLType.String;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Returns a string with the full SQL data type that combines, as appropriate, Type, Length, Precision and Scale where these attributes are relevant to the Type
|
|
341
|
+
*/
|
|
342
|
+
get SQLFullType() {
|
|
343
|
+
return (0, util_1.SQLFullType)(this.Type, this.Length, this.Precision, this.Scale);
|
|
344
|
+
}
|
|
345
|
+
get MaxLength() {
|
|
346
|
+
return (0, util_1.SQLMaxLength)(this.Type, this.Length);
|
|
347
|
+
}
|
|
348
|
+
get ReadOnly() {
|
|
349
|
+
return this.IsVirtual || !this.AllowUpdateAPI || this.IsPrimaryKey || this.IsSpecialDateField;
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Helper method that returns true if the field is one of the special reserved MJ date fields for tracking CreatedAt and UpdatedAt timestamps as well as the DeletedAt timestamp used for entities that
|
|
353
|
+
* have DeleteType=Soft. This is only used when the entity has TrackRecordChanges=1 or for entities where DeleteType=Soft
|
|
354
|
+
*/
|
|
355
|
+
get IsSpecialDateField() {
|
|
356
|
+
return this.IsCreatedAtField || this.IsUpdatedAtField || this.IsDeletedAtField;
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Returns true if the field is the CreatedAt field, a special field that is used to track the creation date of a record. This is only used when the entity has TrackRecordChanges=1
|
|
360
|
+
*/
|
|
361
|
+
get IsCreatedAtField() {
|
|
362
|
+
return this.Name.trim().toLowerCase() === EntityInfo.CreatedAtFieldName.trim().toLowerCase();
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Returns true if the field is the UpdatedAt field, a special field that is used to track the last update date of a record. This is only used when the entity has TrackRecordChanges=1
|
|
366
|
+
*/
|
|
367
|
+
get IsUpdatedAtField() {
|
|
368
|
+
return this.Name.trim().toLowerCase() === EntityInfo.UpdatedAtFieldName.trim().toLowerCase();
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Returns true if the field is the DeletedAt field, a special field that is used to track the deletion date of a record. This is only used when the entity has DeleteType=Soft
|
|
372
|
+
*/
|
|
373
|
+
get IsDeletedAtField() {
|
|
374
|
+
return this.Name.trim().toLowerCase() === EntityInfo.DeletedAtFieldName.trim().toLowerCase();
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Returns true if the field is a uniqueidentifier in the database.
|
|
378
|
+
*/
|
|
379
|
+
get IsUniqueIdentifier() {
|
|
380
|
+
return this.Type.trim().toLowerCase() === 'uniqueidentifier';
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Returns true if the field has a default value set
|
|
384
|
+
*/
|
|
385
|
+
get HasDefaultValue() {
|
|
386
|
+
return this.DefaultValue && this.DefaultValue.trim().length > 0;
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Returns true if the field is a "special" field (see list below) and is handled inside the DB layer and should be ignored in validation by the BaseEntity architecture
|
|
390
|
+
* Also, we skip validation if we have a field that is:
|
|
391
|
+
* - the primary key
|
|
392
|
+
* - an autoincrement field
|
|
393
|
+
* - the field is virtual
|
|
394
|
+
* - the field is readonly
|
|
395
|
+
* - the field is a special date field
|
|
396
|
+
*/
|
|
397
|
+
get SkipValidation() {
|
|
398
|
+
const name = this.Name.toLowerCase().trim();
|
|
399
|
+
return this.IsSpecialDateField || this.IsPrimaryKey || this.AutoIncrement === true || this.IsVirtual === true || this.ReadOnly === true;
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* Returns the DisplayName if it exists, otherwise returns the Name.
|
|
403
|
+
*/
|
|
404
|
+
get DisplayNameOrName() {
|
|
405
|
+
return this.DisplayName ? this.DisplayName : this.Name;
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* Formats a value based on the parameters passed in. This is a wrapper utility method that already know the SQL type from the entity field definition and simply calls the generic FormatValue() function that is also exported by @memberjunction/core
|
|
409
|
+
* @param value - Value to format
|
|
410
|
+
* @param decimals Number of decimals to show, defaults to 2
|
|
411
|
+
* @param currency Currency to use when formatting, defaults to USD
|
|
412
|
+
* @param maxLength Maximum length of the string to return, if the formatted value is longer than this length then the string will be truncated and the trailingChars will be appended to the end of the string
|
|
413
|
+
* @param trailingChars Only used if maxLength is > 0 and the string being formatted is > maxLength, this is the string that will be appended to the end of the string to indicate that it was truncated, defaults to "..."
|
|
414
|
+
* @returns either the original string value or a formatted version. If the format cannot be applied an an exception occurs it is captured and the error is put to the log, and the original value is returned
|
|
415
|
+
*/
|
|
416
|
+
FormatValue(value, decimals = 2, currency = 'USD', maxLength = 0, trailingChars = '...') {
|
|
417
|
+
return (0, util_1.FormatValue)(this.Type, value, decimals, currency, maxLength, trailingChars);
|
|
418
|
+
}
|
|
419
|
+
constructor(initData = null) {
|
|
420
|
+
super();
|
|
421
|
+
this.ID = null;
|
|
422
|
+
/**
|
|
423
|
+
* Foreign key to the Entities entity.
|
|
424
|
+
*/
|
|
425
|
+
this.EntityID = null;
|
|
426
|
+
/**
|
|
427
|
+
* The sequence of the field within the entity, typically the intended display order
|
|
428
|
+
*/
|
|
429
|
+
this.Sequence = null;
|
|
430
|
+
this.Name = null;
|
|
431
|
+
/**
|
|
432
|
+
* Optional property that provides the display name for the field, if null, use the Name property.
|
|
433
|
+
* The DisplayNameOrName() method is a helper function that does this for you with a single method call.
|
|
434
|
+
*/
|
|
435
|
+
this.DisplayName = null;
|
|
436
|
+
this.Description = null;
|
|
437
|
+
/**
|
|
438
|
+
* If true, the field is the primary key for the entity. There must be one primary key field per entity.
|
|
439
|
+
*/
|
|
440
|
+
this.IsPrimaryKey = null;
|
|
441
|
+
/**
|
|
442
|
+
* If true, the field is a unique key for the entity. There can be zero to many unique key fields per entity.
|
|
443
|
+
*/
|
|
444
|
+
this.IsUnique = null;
|
|
445
|
+
this.Category = null;
|
|
446
|
+
this.Type = null;
|
|
447
|
+
this.Length = null;
|
|
448
|
+
this.Precision = null;
|
|
449
|
+
this.Scale = null;
|
|
450
|
+
this.AllowsNull = null;
|
|
451
|
+
this.DefaultValue = null;
|
|
452
|
+
this.AutoIncrement = null;
|
|
453
|
+
this.ValueListType = null;
|
|
454
|
+
this.ExtendedType = null;
|
|
455
|
+
this.DefaultInView = null;
|
|
456
|
+
this.ViewCellTemplate = null;
|
|
457
|
+
this.DefaultColumnWidth = null;
|
|
458
|
+
this.AllowUpdateAPI = null;
|
|
459
|
+
this.AllowUpdateInView = null;
|
|
460
|
+
this.IncludeInUserSearchAPI = null;
|
|
461
|
+
this.FullTextSearchEnabled = false;
|
|
462
|
+
this.UserSearchParamFormatAPI = null;
|
|
463
|
+
this.IncludeInGeneratedForm = null;
|
|
464
|
+
this.GeneratedFormSection = null;
|
|
465
|
+
this.IsVirtual = null;
|
|
466
|
+
this.IsNameField = null;
|
|
467
|
+
this.RelatedEntityID = null;
|
|
468
|
+
this.RelatedEntityFieldName = null;
|
|
469
|
+
this.IncludeRelatedEntityNameFieldInBaseView = null;
|
|
470
|
+
this.RelatedEntityNameFieldMap = null;
|
|
471
|
+
this.RelatedEntityDisplayType = null;
|
|
472
|
+
this.EntityIDFieldName = null;
|
|
473
|
+
this.__mj_CreatedAt = null;
|
|
474
|
+
this.__mj_UpdatedAt = null;
|
|
475
|
+
/**
|
|
476
|
+
* * Field Name: ScopeDefault
|
|
477
|
+
* * Display Name: Scope Default
|
|
478
|
+
* * SQL Data Type: nvarchar(100)
|
|
479
|
+
* * Description: A comma-delimited string indicating the default scope for field visibility. Options include Users, Admins, AI, and All. Defaults to All when NULL. This is used for a simple method of filtering field defaults for visibility, not security enforcement.
|
|
480
|
+
*/
|
|
481
|
+
this.ScopeDefault = null;
|
|
482
|
+
/**
|
|
483
|
+
* * Field Name: AutoUpdateRelatedEntityInfo
|
|
484
|
+
* * Display Name: Auto Update Related Entity Info
|
|
485
|
+
* * SQL Data Type: bit
|
|
486
|
+
* * Default Value: 1
|
|
487
|
+
* * Description: Indicates whether the related entity information should be automatically updated from the database schema. When set to 0, relationships not part of the database schema can be manually defined at the application and AI agent level. Defaults to 1.
|
|
488
|
+
*/
|
|
489
|
+
this.AutoUpdateRelatedEntityInfo = true;
|
|
490
|
+
/**
|
|
491
|
+
* * Field Name: ValuesToPackWithSchema
|
|
492
|
+
* * Display Name: Values To Pack With Schema
|
|
493
|
+
* * SQL Data Type: nvarchar(10)
|
|
494
|
+
* * Default Value: Auto
|
|
495
|
+
* * Value List Type: List
|
|
496
|
+
* * Possible Values
|
|
497
|
+
* * Auto
|
|
498
|
+
* * None
|
|
499
|
+
* * All
|
|
500
|
+
* * Description: Determines whether values for the field should be included when the schema is packed. Options: Auto (include manually set or auto-derived values), None (exclude all values), All (include all distinct values from the table). Defaults to Auto.
|
|
501
|
+
*/
|
|
502
|
+
this.ValuesToPackWithSchema = 'Auto';
|
|
503
|
+
/**
|
|
504
|
+
* * Field Name: GeneratedValidationFunctionName
|
|
505
|
+
* * Display Name: Generated Validation Function Name
|
|
506
|
+
* * SQL Data Type: nvarchar(255)
|
|
507
|
+
* * Default Value: null
|
|
508
|
+
* * Description: Contains the name of the generated field validation function, if it exists, null otherwise.
|
|
509
|
+
*/
|
|
510
|
+
this.GeneratedValidationFunctionName = null;
|
|
511
|
+
/**
|
|
512
|
+
* * Field Name: GeneratedValidationFunctionDescription
|
|
513
|
+
* * Display Name: Generated Validation Function Description
|
|
514
|
+
* * SQL Data Type: nvarchar(max)
|
|
515
|
+
* * Default Value: null
|
|
516
|
+
* * Description: Contains a description for business users of what the validation function for this field does, if it exists.
|
|
517
|
+
*/
|
|
518
|
+
this.GeneratedValidationFunctionDescription = null;
|
|
519
|
+
/**
|
|
520
|
+
* * Field Name: GeneratedValidationFunctionCode
|
|
521
|
+
* * Display Name: Generated Validation Function Code
|
|
522
|
+
* * SQL Data Type: nvarchar(max)
|
|
523
|
+
* * Default Value: null
|
|
524
|
+
* * Description: Contains the generated code for the field validation function, if it exists, null otherwise.
|
|
525
|
+
*/
|
|
526
|
+
this.GeneratedValidationFunctionCode = null;
|
|
527
|
+
/**
|
|
528
|
+
* * Field Name: GeneratedValidationFunctionCheckConstraint
|
|
529
|
+
* * Display Name: Generated Validation Function Check Constraint
|
|
530
|
+
* * SQL Data Type: nvarchar(max)
|
|
531
|
+
* * Default Value: null
|
|
532
|
+
* * Description: If a generated validation function was generated previously, this stores the text from the source CHECK constraint in the database. This is stored so that regeneration of the validation function will only occur when the source CHECK constraint changes.
|
|
533
|
+
*/
|
|
534
|
+
this.GeneratedValidationFunctionCheckConstraint = null;
|
|
535
|
+
/**
|
|
536
|
+
* * Field Name: Status
|
|
537
|
+
* * Display Name: Status
|
|
538
|
+
* * SQL Data Type: nvarchar(25)
|
|
539
|
+
* * Default Value: Active
|
|
540
|
+
* * Value List Type: List
|
|
541
|
+
* * Possible Values
|
|
542
|
+
* * Active
|
|
543
|
+
* * Deprecated
|
|
544
|
+
* * Disabled
|
|
545
|
+
* * Description: Current status of the entity field - Active fields are available for use, Deprecated fields are discouraged but still functional, Disabled fields are not available for use
|
|
546
|
+
*/
|
|
547
|
+
this.Status = 'Active';
|
|
548
|
+
// virtual fields - returned by the database VIEW
|
|
549
|
+
this.FieldCodeName = null;
|
|
550
|
+
this.Entity = null;
|
|
551
|
+
this.SchemaName = null;
|
|
552
|
+
this.BaseTable = null;
|
|
553
|
+
this.BaseView = null;
|
|
554
|
+
this.EntityCodeName = null;
|
|
555
|
+
this.EntityClassName = null;
|
|
556
|
+
this.RelatedEntity = null;
|
|
557
|
+
this.RelatedEntitySchemaName = null;
|
|
558
|
+
this.RelatedEntityBaseTable = null;
|
|
559
|
+
this.RelatedEntityBaseView = null;
|
|
560
|
+
this.RelatedEntityCodeName = null;
|
|
561
|
+
this.RelatedEntityClassName = null;
|
|
562
|
+
/**
|
|
563
|
+
* For fields in the database that have characters invalid for SQL identifiers in them, we need to replace those characters with _ in order to create variables for stored procedures.
|
|
564
|
+
* This property returns a consistent CodeName you can use everywhere to refer to the field when generated variable names
|
|
565
|
+
*/
|
|
566
|
+
this._codeName = null;
|
|
567
|
+
if (initData) {
|
|
568
|
+
this.copyInitData(initData);
|
|
569
|
+
// do some special handling to create class instances instead of just data objects
|
|
570
|
+
// copy the Entity Field Values
|
|
571
|
+
this._EntityFieldValues = [];
|
|
572
|
+
const efv = initData.EntityFieldValues || initData._EntityFieldValues;
|
|
573
|
+
if (efv) {
|
|
574
|
+
for (let j = 0; j < efv.length; j++) {
|
|
575
|
+
this._EntityFieldValues.push(new EntityFieldValueInfo(efv[j]));
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
/**
|
|
581
|
+
* This static factory method is used to check to see if the entity field in question is active or not
|
|
582
|
+
* If it is not active, it will throw an exception or log a warning depending on the status of the entity field being
|
|
583
|
+
* either Deprecated or Disabled.
|
|
584
|
+
* @param entityField - the EntityFieldInfo object to check the status of
|
|
585
|
+
* @param callerName - the name of the caller that is calling this method, used for logging purposes such as EntityField::constructor as an example.
|
|
586
|
+
*/
|
|
587
|
+
static AssertEntityFieldActiveStatus(entityField, callerName) {
|
|
588
|
+
if (!entityField) {
|
|
589
|
+
throw new Error(`Entity must be provided to call AssertEntityFieldActiveStatus. Caller: ${callerName}`);
|
|
590
|
+
}
|
|
591
|
+
if (entityField.Status === 'Active') {
|
|
592
|
+
return; // no need to check further, the field is active
|
|
593
|
+
}
|
|
594
|
+
if (entityField.Status?.trim().toLowerCase() === 'deprecated') {
|
|
595
|
+
// warning
|
|
596
|
+
console.warn(`${callerName}: Entity Field ${entityField.Entity}.${entityField.Name} is deprecated and should not be used as it could be removed in the future.`);
|
|
597
|
+
}
|
|
598
|
+
else if (entityField.Status?.trim().toLowerCase() === 'disabled') {
|
|
599
|
+
// console.error and throw the exception
|
|
600
|
+
const exceptionString = `${callerName}: Entity Field ${entityField.Entity}.${entityField.Name} is disabled and cannot be used.`;
|
|
601
|
+
(0, logging_1.LogError)(exceptionString);
|
|
602
|
+
throw new Error(exceptionString);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
/**
|
|
606
|
+
* Checks if a default value is a SQL Server function that returns the current date/time
|
|
607
|
+
* @param defaultValue - The default value to check
|
|
608
|
+
* @returns true if the default value is a SQL current date/time function, false otherwise
|
|
609
|
+
*/
|
|
610
|
+
static IsDefaultValueSQLCurrentDateFunction(defaultValue) {
|
|
611
|
+
if (!defaultValue) {
|
|
612
|
+
return false;
|
|
613
|
+
}
|
|
614
|
+
// Trim and lowercase the value for comparison
|
|
615
|
+
const normalizedValue = defaultValue.trim().toLowerCase();
|
|
616
|
+
// Check if the normalized value contains any of our known current date functions
|
|
617
|
+
// Using includes() because the value might be wrapped in parentheses like (getdate())
|
|
618
|
+
return EntityFieldInfo.SQL_CURRENT_DATE_FUNCTIONS.some((func) => normalizedValue.includes(func));
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
exports.EntityFieldInfo = EntityFieldInfo;
|
|
622
|
+
/**
|
|
623
|
+
* Readonly array of SQL Server date/time functions that return the current date/time
|
|
624
|
+
*/
|
|
625
|
+
EntityFieldInfo.SQL_CURRENT_DATE_FUNCTIONS = [
|
|
626
|
+
'getdate()',
|
|
627
|
+
'getutcdate()',
|
|
628
|
+
'sysdatetimeoffset()',
|
|
629
|
+
'current_timestamp',
|
|
630
|
+
'sysdatetime()',
|
|
631
|
+
'sysutcdatetime()',
|
|
632
|
+
];
|
|
633
|
+
/**
|
|
634
|
+
* Entity Document Type Info object has information about the document types that exist across all entities. When Entity Documents are created they are associated with a document type.
|
|
635
|
+
*/
|
|
636
|
+
/**
|
|
637
|
+
* Defines types of documents that can be generated from entity data.
|
|
638
|
+
* Supports various output formats for entity records.
|
|
639
|
+
*/
|
|
640
|
+
class EntityDocumentTypeInfo extends baseInfo_1.BaseInfo {
|
|
641
|
+
constructor(initData = null) {
|
|
642
|
+
super();
|
|
643
|
+
this.ID = null;
|
|
644
|
+
this.Name = null;
|
|
645
|
+
this.Description = null;
|
|
646
|
+
this.__mj_CreatedAt = null;
|
|
647
|
+
this.__mj_UpdatedAt = null;
|
|
648
|
+
this.copyInitData(initData);
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
exports.EntityDocumentTypeInfo = EntityDocumentTypeInfo;
|
|
652
|
+
/**
|
|
653
|
+
* Settings allow you to store key/value pairs of information that can be used to configure the behavior of the entity.
|
|
654
|
+
*/
|
|
655
|
+
/**
|
|
656
|
+
* Stores entity-specific configuration settings.
|
|
657
|
+
* Allows customization of how entities function within the system.
|
|
658
|
+
*/
|
|
659
|
+
class EntitySettingInfo extends baseInfo_1.BaseInfo {
|
|
660
|
+
constructor(initData = null) {
|
|
661
|
+
super();
|
|
662
|
+
this.ID = null;
|
|
663
|
+
this.EntityID = null;
|
|
664
|
+
this.Name = null;
|
|
665
|
+
this.Value = null;
|
|
666
|
+
this.Comments = null;
|
|
667
|
+
this.__mj_CreatedAt = null;
|
|
668
|
+
this.__mj_UpdatedAt = null;
|
|
669
|
+
this.copyInitData(initData);
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
exports.EntitySettingInfo = EntitySettingInfo;
|
|
673
|
+
/**
|
|
674
|
+
* Catalog of all entities across all schemas.
|
|
675
|
+
* Contains comprehensive metadata about each entity including its database mappings, security settings, and UI preferences.
|
|
676
|
+
*/
|
|
677
|
+
class EntityInfo extends baseInfo_1.BaseInfo {
|
|
678
|
+
/**
|
|
679
|
+
* Returns the primary key field for the entity. For entities with a composite primary key, use the PrimaryKeys property which returns all.
|
|
680
|
+
* In the case of a composite primary key, the PrimaryKey property will return the first field in the sequence of the primary key fields.
|
|
681
|
+
*/
|
|
682
|
+
get FirstPrimaryKey() {
|
|
683
|
+
return this.Fields.find((f) => f.IsPrimaryKey);
|
|
684
|
+
}
|
|
685
|
+
/**
|
|
686
|
+
* Returns an array of all fields that are part of the primary key for the entity. If the entity has a single primary key, the array will have a single element.
|
|
687
|
+
*/
|
|
688
|
+
get PrimaryKeys() {
|
|
689
|
+
return this.Fields.filter((f) => f.IsPrimaryKey);
|
|
690
|
+
}
|
|
691
|
+
/**
|
|
692
|
+
* Returns an array of all fields that have unique constraints on them.
|
|
693
|
+
* @returns {EntityFieldInfo[]} Array of fields with unique constraints
|
|
694
|
+
*/
|
|
695
|
+
get UniqueKeys() {
|
|
696
|
+
return this.Fields.filter((f) => f.IsUnique);
|
|
697
|
+
}
|
|
698
|
+
/**
|
|
699
|
+
* Returns an array of all fields that are foreign keys to other entities.
|
|
700
|
+
* @returns {EntityFieldInfo[]} Array of foreign key fields
|
|
701
|
+
*/
|
|
702
|
+
get ForeignKeys() {
|
|
703
|
+
return this.Fields.filter((f) => f.RelatedEntityID && f.RelatedEntityID.length > 0);
|
|
704
|
+
}
|
|
705
|
+
/**
|
|
706
|
+
* Gets all fields for this entity with their complete metadata.
|
|
707
|
+
* @returns {EntityFieldInfo[]} Array of all entity fields
|
|
708
|
+
*/
|
|
709
|
+
get Fields() {
|
|
710
|
+
return this._Fields;
|
|
711
|
+
}
|
|
712
|
+
/**
|
|
713
|
+
* Gets all relationships where other entities reference this entity.
|
|
714
|
+
* @returns {EntityRelationshipInfo[]} Array of entity relationships
|
|
715
|
+
*/
|
|
716
|
+
get RelatedEntities() {
|
|
717
|
+
return this._RelatedEntities;
|
|
718
|
+
}
|
|
719
|
+
/**
|
|
720
|
+
* Gets the security permissions for this entity by role.
|
|
721
|
+
* @returns {EntityPermissionInfo[]} Array of permission settings
|
|
722
|
+
*/
|
|
723
|
+
get Permissions() {
|
|
724
|
+
return this._Permissions;
|
|
725
|
+
}
|
|
726
|
+
/**
|
|
727
|
+
* Gets custom configuration settings for this entity.
|
|
728
|
+
* @returns {EntitySettingInfo[]} Array of entity-specific settings
|
|
729
|
+
*/
|
|
730
|
+
get Settings() {
|
|
731
|
+
return this._Settings;
|
|
732
|
+
}
|
|
733
|
+
/**
|
|
734
|
+
* Returns the name of the special reserved field that is used to store the CreatedAt timestamp across all of MJ. This is only used when an entity has TrackRecordChanges turned on
|
|
735
|
+
*/
|
|
736
|
+
static get CreatedAtFieldName() {
|
|
737
|
+
return EntityInfo.__createdAtFieldName;
|
|
738
|
+
}
|
|
739
|
+
/**
|
|
740
|
+
* Returns the name of the special reserved field that is used to store the UpdatedAt timestamp across all of MJ. This is only used when an entity has TrackRecordChanges turned on
|
|
741
|
+
*/
|
|
742
|
+
static get UpdatedAtFieldName() {
|
|
743
|
+
return EntityInfo.__updatedAtFieldName;
|
|
744
|
+
}
|
|
745
|
+
/**
|
|
746
|
+
* Returns the name of the special reserved field that is used to store the DeletedAt timestamp across all of MJ. This is only used when an entity has DeleteType=Soft
|
|
747
|
+
*/
|
|
748
|
+
static get DeletedAtFieldName() {
|
|
749
|
+
return EntityInfo.__deletedAtFieldName;
|
|
750
|
+
}
|
|
751
|
+
/**
|
|
752
|
+
* This static factory method is used to check to see if the entity in question is active or not
|
|
753
|
+
* If it is not active, it will throw an exception or log a warning depending on the status of the entity being
|
|
754
|
+
* either Deprecated or Disabled.
|
|
755
|
+
* @param entity - the EntityInfo object to check the status of
|
|
756
|
+
* @param callerName - the name of the caller that is calling this method, used for logging purposes such as BaseEntity::constructor as an example.
|
|
757
|
+
*/
|
|
758
|
+
static AssertEntityActiveStatus(entity, callerName) {
|
|
759
|
+
if (!entity) {
|
|
760
|
+
throw new Error(`Entity must be provided to call AssertEntityActiveStatus. Caller: ${callerName}`);
|
|
761
|
+
}
|
|
762
|
+
if (entity.Status?.trim().toLowerCase() === 'deprecated') {
|
|
763
|
+
// warning
|
|
764
|
+
console.warn(`${callerName}: Entity ${entity.Name} is deprecated and should not be used as it could be removed in the future.`);
|
|
765
|
+
}
|
|
766
|
+
else if (entity.Status?.trim().toLowerCase() === 'disabled') {
|
|
767
|
+
// console.error and throw the exception
|
|
768
|
+
const exceptionString = `${callerName}: Entity ${entity.Name} is disabled and cannot be used.`;
|
|
769
|
+
(0, logging_1.LogError)(exceptionString);
|
|
770
|
+
throw new Error(exceptionString);
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
/**
|
|
774
|
+
* @returns The BaseTable but with spaces inbetween capital letters
|
|
775
|
+
* */
|
|
776
|
+
get BaseTableDisplayName() {
|
|
777
|
+
return this.BaseTable.replace(/([A-Z])/g, ' $1').trim();
|
|
778
|
+
}
|
|
779
|
+
/**
|
|
780
|
+
* Returns the DisplayName if it exists, otherwise returns the Name.
|
|
781
|
+
*/
|
|
782
|
+
get DisplayNameOrName() {
|
|
783
|
+
return this.DisplayName ? this.DisplayName : this.Name;
|
|
784
|
+
}
|
|
785
|
+
/**
|
|
786
|
+
* Returns the EntityField object for the Field that has IsNameField set to true. If multiple fields have IsNameField on, the function will return the first field (by sequence) that matches.
|
|
787
|
+
* If no fields match, if there is a field called "Name", that is returned. If there is no field called "Name", null is returned.
|
|
788
|
+
*/
|
|
789
|
+
get NameField() {
|
|
790
|
+
for (let j = 0; j < this.Fields.length; j++) {
|
|
791
|
+
const ef = this.Fields[j];
|
|
792
|
+
if (ef.IsNameField)
|
|
793
|
+
return ef;
|
|
794
|
+
}
|
|
795
|
+
// at this point, we return the first field called "Name" if it exists, and the below line will return NULL if we can't find a field called "Name"
|
|
796
|
+
return this.Fields.find((f) => f.Name.toLowerCase() === 'name');
|
|
797
|
+
}
|
|
798
|
+
/**
|
|
799
|
+
* Returns the Permissions for this entity for a given user, based on the roles the user is part of
|
|
800
|
+
* @param user
|
|
801
|
+
* @returns
|
|
802
|
+
*/
|
|
803
|
+
GetUserPermisions(user) {
|
|
804
|
+
try {
|
|
805
|
+
const permissionList = [];
|
|
806
|
+
for (let j = 0; j < this.Permissions.length; j++) {
|
|
807
|
+
const ep = this.Permissions[j];
|
|
808
|
+
const roleMatch = user.UserRoles.find((r) => r.RoleID === ep.RoleID);
|
|
809
|
+
if (roleMatch)
|
|
810
|
+
// user has this role
|
|
811
|
+
permissionList.push(ep);
|
|
812
|
+
}
|
|
813
|
+
// now that we have matched any number of EntityPermissions to the current user, aggregate the permissions
|
|
814
|
+
const userPermission = new EntityUserPermissionInfo();
|
|
815
|
+
userPermission.CanCreate = false;
|
|
816
|
+
userPermission.CanDelete = false;
|
|
817
|
+
userPermission.CanRead = false;
|
|
818
|
+
userPermission.CanUpdate = false;
|
|
819
|
+
for (let j = 0; j < permissionList.length; j++) {
|
|
820
|
+
const ep = permissionList[j];
|
|
821
|
+
userPermission.CanCreate = userPermission.CanCreate || ep.CanCreate;
|
|
822
|
+
userPermission.CanRead = userPermission.CanRead || ep.CanRead;
|
|
823
|
+
userPermission.CanUpdate = userPermission.CanUpdate || ep.CanUpdate;
|
|
824
|
+
userPermission.CanDelete = userPermission.CanDelete || ep.CanDelete;
|
|
825
|
+
}
|
|
826
|
+
userPermission.Entity = this;
|
|
827
|
+
userPermission.User = user;
|
|
828
|
+
return userPermission;
|
|
829
|
+
}
|
|
830
|
+
catch (err) {
|
|
831
|
+
console.log(err);
|
|
832
|
+
return null;
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
/**
|
|
836
|
+
* Determines if a given user, for a given permission type, is exempt from RowLevelSecurity or not
|
|
837
|
+
* @param user
|
|
838
|
+
* @param type
|
|
839
|
+
* @returns
|
|
840
|
+
*/
|
|
841
|
+
UserExemptFromRowLevelSecurity(user, type) {
|
|
842
|
+
for (let j = 0; j < this.Permissions.length; j++) {
|
|
843
|
+
const ep = this.Permissions[j];
|
|
844
|
+
const roleMatch = user.UserRoles.find((r) => r.RoleID === ep.RoleID);
|
|
845
|
+
if (roleMatch) {
|
|
846
|
+
// user has this role
|
|
847
|
+
switch (type) {
|
|
848
|
+
case exports.EntityPermissionType.Create:
|
|
849
|
+
if (!ep.CreateRLSFilterID)
|
|
850
|
+
return true;
|
|
851
|
+
break;
|
|
852
|
+
case exports.EntityPermissionType.Read:
|
|
853
|
+
if (!ep.ReadRLSFilterID)
|
|
854
|
+
return true;
|
|
855
|
+
break;
|
|
856
|
+
case exports.EntityPermissionType.Update:
|
|
857
|
+
if (!ep.UpdateRLSFilterID)
|
|
858
|
+
return true;
|
|
859
|
+
break;
|
|
860
|
+
case exports.EntityPermissionType.Delete:
|
|
861
|
+
if (!ep.DeleteRLSFilterID)
|
|
862
|
+
return true;
|
|
863
|
+
break;
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
return false; // if we get here, the user is NOT exempt from RLS for this Permission Type
|
|
868
|
+
}
|
|
869
|
+
/**
|
|
870
|
+
* Returns RLS security info attributes for a given user and permission type
|
|
871
|
+
* @param user
|
|
872
|
+
* @param type
|
|
873
|
+
* @returns
|
|
874
|
+
*/
|
|
875
|
+
GetUserRowLevelSecurityInfo(user, type) {
|
|
876
|
+
const rlsList = [];
|
|
877
|
+
for (let j = 0; j < this.Permissions.length; j++) {
|
|
878
|
+
const ep = this.Permissions[j];
|
|
879
|
+
const roleMatch = user.UserRoles.find((r) => r.RoleID === ep.RoleID);
|
|
880
|
+
if (roleMatch) {
|
|
881
|
+
// user has this role
|
|
882
|
+
let matchObject = null;
|
|
883
|
+
switch (type) {
|
|
884
|
+
case exports.EntityPermissionType.Create:
|
|
885
|
+
if (ep.CreateRLSFilterID)
|
|
886
|
+
matchObject = ep.CreateRLSFilterObject;
|
|
887
|
+
break;
|
|
888
|
+
case exports.EntityPermissionType.Read:
|
|
889
|
+
if (ep.ReadRLSFilterID)
|
|
890
|
+
matchObject = ep.ReadRLSFilterObject;
|
|
891
|
+
break;
|
|
892
|
+
case exports.EntityPermissionType.Update:
|
|
893
|
+
if (ep.UpdateRLSFilterID)
|
|
894
|
+
matchObject = ep.UpdateRLSFilterObject;
|
|
895
|
+
break;
|
|
896
|
+
case exports.EntityPermissionType.Delete:
|
|
897
|
+
if (ep.DeleteRLSFilterID)
|
|
898
|
+
matchObject = ep.DeleteRLSFilterObject;
|
|
899
|
+
break;
|
|
900
|
+
}
|
|
901
|
+
if (matchObject) {
|
|
902
|
+
// we have a match, so add it to the list if it isn't already there
|
|
903
|
+
const existingMatch = rlsList.find((r) => r.ID === matchObject.ID);
|
|
904
|
+
if (!existingMatch)
|
|
905
|
+
rlsList.push(matchObject);
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
return rlsList;
|
|
910
|
+
}
|
|
911
|
+
/**
|
|
912
|
+
* Generates a where clause for SQL filtering for a given entity for a given user and permission type. If there is no RLS for a given entity or the user is exempt from RLS for the entity, a blank string is returned.
|
|
913
|
+
* @param user
|
|
914
|
+
* @param type
|
|
915
|
+
* @param returnPrefix
|
|
916
|
+
* @returns
|
|
917
|
+
*/
|
|
918
|
+
GetUserRowLevelSecurityWhereClause(user, type, returnPrefix) {
|
|
919
|
+
const userRLS = this.GetUserRowLevelSecurityInfo(user, type);
|
|
920
|
+
if (userRLS && userRLS.length > 0) {
|
|
921
|
+
// userRLS has all of the objects that apply to this user. The user is NOT exempt from RLS, so we need to OR together all of the RLS object filters
|
|
922
|
+
let sRLSSQL = '';
|
|
923
|
+
userRLS.forEach((rls) => {
|
|
924
|
+
if (sRLSSQL.length > 0)
|
|
925
|
+
sRLSSQL += ' OR ';
|
|
926
|
+
sRLSSQL += `(${rls.MarkupFilterText(user)})`;
|
|
927
|
+
});
|
|
928
|
+
return sRLSSQL.length > 0 ? `${returnPrefix && returnPrefix.length > 0 ? returnPrefix + ' ' : ''}${sRLSSQL}` : '';
|
|
929
|
+
}
|
|
930
|
+
else
|
|
931
|
+
return '';
|
|
932
|
+
}
|
|
933
|
+
/**
|
|
934
|
+
* Returns a RunViewParams object that is setup to filter the related entity for the provided record
|
|
935
|
+
* @param record
|
|
936
|
+
* @param relationship
|
|
937
|
+
* @param filter
|
|
938
|
+
* @returns
|
|
939
|
+
*/
|
|
940
|
+
static BuildRelationshipViewParams(record, relationship, filter, maxRecords) {
|
|
941
|
+
const params = {};
|
|
942
|
+
let quotes = '';
|
|
943
|
+
let keyValue = '';
|
|
944
|
+
if (relationship.EntityKeyField && relationship.EntityKeyField.length > 0) {
|
|
945
|
+
keyValue = record.Get(relationship.EntityKeyField);
|
|
946
|
+
quotes = record.EntityInfo.Fields.find((f) => f.Name.trim().toLowerCase() === relationship.EntityKeyField.trim().toLowerCase())
|
|
947
|
+
.NeedsQuotes
|
|
948
|
+
? "'"
|
|
949
|
+
: '';
|
|
950
|
+
}
|
|
951
|
+
else {
|
|
952
|
+
// currently we only support a single value for FOREIGN KEYS, so we can just grab the first value in the primary key
|
|
953
|
+
const firstKey = record.FirstPrimaryKey;
|
|
954
|
+
keyValue = firstKey.Value;
|
|
955
|
+
//When creating a new record, the keyValue is null and the quotes are not needed
|
|
956
|
+
quotes = keyValue && firstKey.NeedsQuotes ? "'" : '';
|
|
957
|
+
}
|
|
958
|
+
if (relationship.Type.trim().toLowerCase() === 'one to many') {
|
|
959
|
+
// one to many
|
|
960
|
+
params.ExtraFilter = `[${relationship.RelatedEntityJoinField}] = ${quotes}${keyValue}${quotes}`;
|
|
961
|
+
}
|
|
962
|
+
else {
|
|
963
|
+
// many to many
|
|
964
|
+
params.ExtraFilter = `[${relationship.RelatedEntityJoinField}] IN (SELECT [${relationship.JoinEntityInverseJoinField}] FROM [${relationship.JoinView}] WHERE [${relationship.JoinEntityJoinField}] = ${quotes}${keyValue}${quotes})`;
|
|
965
|
+
}
|
|
966
|
+
if (filter && filter.length > 0)
|
|
967
|
+
params.ExtraFilter = `(${params.ExtraFilter}) AND (${filter})`; // caller provided their own filter, so AND it in with the relationship filter we have here
|
|
968
|
+
if (relationship.DisplayUserViewID && relationship.DisplayUserViewID.length > 0) {
|
|
969
|
+
// we have been given a specific view to run, use it
|
|
970
|
+
params.ViewID = relationship.DisplayUserViewID;
|
|
971
|
+
}
|
|
972
|
+
else {
|
|
973
|
+
// no view specified, so specify the entity instead
|
|
974
|
+
params.EntityName = relationship.RelatedEntity;
|
|
975
|
+
}
|
|
976
|
+
if (maxRecords && maxRecords > 0)
|
|
977
|
+
params.MaxRows = maxRecords;
|
|
978
|
+
return params;
|
|
979
|
+
}
|
|
980
|
+
/**
|
|
981
|
+
* Builds a simple javascript object that will pre-populate a new record in the related entity with values that link back to the specified record.
|
|
982
|
+
* This is useful, for example, when creating a new contact from an account, we want to pre-populate the account ID in the new contact record
|
|
983
|
+
*/
|
|
984
|
+
static BuildRelationshipNewRecordValues(record, relationship) {
|
|
985
|
+
// we want to build a simple javascript object that will pre-populate a new record in the related entity with values that link
|
|
986
|
+
// abck to the current record. This is useful for example when creating a new contact from an account, we want to pre-populate the
|
|
987
|
+
// account ID in the new contact record
|
|
988
|
+
const obj = {};
|
|
989
|
+
if (record && relationship) {
|
|
990
|
+
const keyField = relationship.EntityKeyField && relationship.EntityKeyField.trim().length > 0
|
|
991
|
+
? relationship.EntityKeyField
|
|
992
|
+
: record.FirstPrimaryKey.Name;
|
|
993
|
+
obj[relationship.RelatedEntityJoinField] = record.Get(keyField);
|
|
994
|
+
}
|
|
995
|
+
return obj;
|
|
996
|
+
}
|
|
997
|
+
constructor(initData = null) {
|
|
998
|
+
super();
|
|
999
|
+
/**
|
|
1000
|
+
* Unique identifier for the entity
|
|
1001
|
+
*/
|
|
1002
|
+
this.ID = null;
|
|
1003
|
+
/**
|
|
1004
|
+
* Reserved for future use - parent entity for hierarchical relationships
|
|
1005
|
+
*/
|
|
1006
|
+
this.ParentID = null;
|
|
1007
|
+
/**
|
|
1008
|
+
* Unique name of the entity used throughout the system
|
|
1009
|
+
*/
|
|
1010
|
+
this.Name = null;
|
|
1011
|
+
/**
|
|
1012
|
+
* Optional display name for the entity. If not provided, the entity Name will be used for display purposes.
|
|
1013
|
+
*/
|
|
1014
|
+
this.DisplayName = null;
|
|
1015
|
+
/**
|
|
1016
|
+
* Optional suffix appended to entity names for display purposes
|
|
1017
|
+
*/
|
|
1018
|
+
this.NameSuffix = null;
|
|
1019
|
+
/**
|
|
1020
|
+
* Detailed description of the entity's purpose and contents
|
|
1021
|
+
*/
|
|
1022
|
+
this.Description = null;
|
|
1023
|
+
/**
|
|
1024
|
+
* The underlying database table name this entity maps to
|
|
1025
|
+
*/
|
|
1026
|
+
this.BaseTable = null;
|
|
1027
|
+
/**
|
|
1028
|
+
* The database view used as a "wrapper" for accessing this entity's data
|
|
1029
|
+
*/
|
|
1030
|
+
this.BaseView = null;
|
|
1031
|
+
/**
|
|
1032
|
+
* Whether the base view is generated by CodeGen (true) or manually created (false)
|
|
1033
|
+
*/
|
|
1034
|
+
this.BaseViewGenerated = null;
|
|
1035
|
+
/**
|
|
1036
|
+
* Database schema that contains this entity's table and view
|
|
1037
|
+
*/
|
|
1038
|
+
this.SchemaName = null;
|
|
1039
|
+
/**
|
|
1040
|
+
* If true, this is a virtual entity not backed by a physical database table
|
|
1041
|
+
*/
|
|
1042
|
+
this.VirtualEntity = null;
|
|
1043
|
+
/**
|
|
1044
|
+
* Whether to track all changes to records in the RecordChange table
|
|
1045
|
+
*/
|
|
1046
|
+
this.TrackRecordChanges = null;
|
|
1047
|
+
/**
|
|
1048
|
+
* Whether to audit when users access records from this entity
|
|
1049
|
+
*/
|
|
1050
|
+
this.AuditRecordAccess = null;
|
|
1051
|
+
/**
|
|
1052
|
+
* Whether to audit when views are run against this entity
|
|
1053
|
+
*/
|
|
1054
|
+
this.AuditViewRuns = null;
|
|
1055
|
+
/**
|
|
1056
|
+
* Whether this entity is available through the GraphQL API
|
|
1057
|
+
*/
|
|
1058
|
+
this.IncludeInAPI = false;
|
|
1059
|
+
/**
|
|
1060
|
+
* If true, allows querying all rows without pagination limits via API
|
|
1061
|
+
*/
|
|
1062
|
+
this.AllowAllRowsAPI = false;
|
|
1063
|
+
/**
|
|
1064
|
+
* Global flag controlling whether records can be updated via API
|
|
1065
|
+
*/
|
|
1066
|
+
this.AllowUpdateAPI = false;
|
|
1067
|
+
/**
|
|
1068
|
+
* Global flag controlling whether records can be created via API
|
|
1069
|
+
*/
|
|
1070
|
+
this.AllowCreateAPI = false;
|
|
1071
|
+
/**
|
|
1072
|
+
* Global flag controlling whether records can be deleted via API
|
|
1073
|
+
*/
|
|
1074
|
+
this.AllowDeleteAPI = false;
|
|
1075
|
+
/**
|
|
1076
|
+
* If true, uses a custom resolver for GraphQL operations instead of standard CRUD
|
|
1077
|
+
*/
|
|
1078
|
+
this.CustomResolverAPI = false;
|
|
1079
|
+
/**
|
|
1080
|
+
* Whether users can search this entity through the search API
|
|
1081
|
+
*/
|
|
1082
|
+
this.AllowUserSearchAPI = false;
|
|
1083
|
+
/**
|
|
1084
|
+
* Whether full-text search is enabled for this entity
|
|
1085
|
+
*/
|
|
1086
|
+
this.FullTextSearchEnabled = false;
|
|
1087
|
+
/**
|
|
1088
|
+
* Name of the SQL Server full-text catalog used for searching
|
|
1089
|
+
*/
|
|
1090
|
+
this.FullTextCatalog = null;
|
|
1091
|
+
/**
|
|
1092
|
+
* Whether the full-text catalog is generated by CodeGen
|
|
1093
|
+
*/
|
|
1094
|
+
this.FullTextCatalogGenerated = true;
|
|
1095
|
+
/**
|
|
1096
|
+
* Name of the full-text index on this entity
|
|
1097
|
+
*/
|
|
1098
|
+
this.FullTextIndex = null;
|
|
1099
|
+
/**
|
|
1100
|
+
* Whether the full-text index is generated by CodeGen
|
|
1101
|
+
*/
|
|
1102
|
+
this.FullTextIndexGenerated = true;
|
|
1103
|
+
/**
|
|
1104
|
+
* Name of the function used for full-text searching
|
|
1105
|
+
*/
|
|
1106
|
+
this.FullTextSearchFunction = null;
|
|
1107
|
+
/**
|
|
1108
|
+
* Whether the full-text search function is generated by CodeGen
|
|
1109
|
+
*/
|
|
1110
|
+
this.FullTextSearchFunctionGenerated = true;
|
|
1111
|
+
/**
|
|
1112
|
+
* Maximum number of rows to return in user views to prevent performance issues
|
|
1113
|
+
*/
|
|
1114
|
+
this.UserViewMaxRows = null;
|
|
1115
|
+
/**
|
|
1116
|
+
* Name of the stored procedure for creating records
|
|
1117
|
+
*/
|
|
1118
|
+
this.spCreate = null;
|
|
1119
|
+
/**
|
|
1120
|
+
* Name of the stored procedure for updating records
|
|
1121
|
+
*/
|
|
1122
|
+
this.spUpdate = null;
|
|
1123
|
+
/**
|
|
1124
|
+
* Name of the stored procedure for deleting records
|
|
1125
|
+
*/
|
|
1126
|
+
this.spDelete = null;
|
|
1127
|
+
/**
|
|
1128
|
+
* Whether the create stored procedure is generated by CodeGen
|
|
1129
|
+
*/
|
|
1130
|
+
this.spCreateGenerated = null;
|
|
1131
|
+
/**
|
|
1132
|
+
* Whether the update stored procedure is generated by CodeGen
|
|
1133
|
+
*/
|
|
1134
|
+
this.spUpdateGenerated = null;
|
|
1135
|
+
/**
|
|
1136
|
+
* Whether the delete stored procedure is generated by CodeGen
|
|
1137
|
+
*/
|
|
1138
|
+
this.spDeleteGenerated = null;
|
|
1139
|
+
/**
|
|
1140
|
+
* Whether to automatically delete related records when a parent is deleted
|
|
1141
|
+
*/
|
|
1142
|
+
this.CascadeDeletes = null;
|
|
1143
|
+
/**
|
|
1144
|
+
* Type of delete operation: Hard (physical delete) or Soft (mark as deleted)
|
|
1145
|
+
*/
|
|
1146
|
+
this.DeleteType = 'Hard';
|
|
1147
|
+
/**
|
|
1148
|
+
* Whether records in this entity can be merged together
|
|
1149
|
+
*/
|
|
1150
|
+
this.AllowRecordMerge = null;
|
|
1151
|
+
/**
|
|
1152
|
+
* Name of the stored procedure used for matching/duplicate detection
|
|
1153
|
+
*/
|
|
1154
|
+
this.spMatch = null;
|
|
1155
|
+
/**
|
|
1156
|
+
* Default display type for relationships: Search (type-ahead) or Dropdown
|
|
1157
|
+
*/
|
|
1158
|
+
this.RelationshipDefaultDisplayType = null;
|
|
1159
|
+
/**
|
|
1160
|
+
* Whether the user form for this entity is generated by CodeGen
|
|
1161
|
+
*/
|
|
1162
|
+
this.UserFormGenerated = null;
|
|
1163
|
+
/**
|
|
1164
|
+
* Name of the TypeScript subclass for this entity if custom behavior is needed
|
|
1165
|
+
*/
|
|
1166
|
+
this.EntityObjectSubclassName = null;
|
|
1167
|
+
/**
|
|
1168
|
+
* Import statement for the entity's TypeScript subclass
|
|
1169
|
+
*/
|
|
1170
|
+
this.EntityObjectSubclassImport = null;
|
|
1171
|
+
/**
|
|
1172
|
+
* Field name that contains the preferred communication method (email, phone, etc.)
|
|
1173
|
+
*/
|
|
1174
|
+
this.PreferredCommunicationField = null;
|
|
1175
|
+
/**
|
|
1176
|
+
* CSS class or icon identifier for displaying this entity in the UI
|
|
1177
|
+
*/
|
|
1178
|
+
this.Icon = null;
|
|
1179
|
+
/**
|
|
1180
|
+
* Date and time when this entity was created
|
|
1181
|
+
*/
|
|
1182
|
+
this.__mj_CreatedAt = null;
|
|
1183
|
+
/**
|
|
1184
|
+
* Date and time when this entity was last updated
|
|
1185
|
+
*/
|
|
1186
|
+
this.__mj_UpdatedAt = null;
|
|
1187
|
+
/**
|
|
1188
|
+
* * Field Name: ScopeDefault
|
|
1189
|
+
* * Display Name: Scope Default
|
|
1190
|
+
* * SQL Data Type: nvarchar(100)
|
|
1191
|
+
* * Description: Optional, comma-delimited string indicating the default scope for entity visibility. Options include Users, Admins, AI, and All. Defaults to All when NULL. This is used for simple defaults for filtering entity visibility, not security enforcement.
|
|
1192
|
+
*/
|
|
1193
|
+
this.ScopeDefault = null;
|
|
1194
|
+
/**
|
|
1195
|
+
* * Field Name: RowsToPackWithSchema
|
|
1196
|
+
* * Display Name: Rows To Pack With Schema
|
|
1197
|
+
* * SQL Data Type: nvarchar(20)
|
|
1198
|
+
* * Default Value: None
|
|
1199
|
+
* * Value List Type: List
|
|
1200
|
+
* * Possible Values
|
|
1201
|
+
* * None
|
|
1202
|
+
* * Sample
|
|
1203
|
+
* * All
|
|
1204
|
+
* * Description: Determines how entity rows should be packaged for external use. Options include None, Sample, and All. Defaults to None.
|
|
1205
|
+
*/
|
|
1206
|
+
this.RowsToPackWithSchema = 'None';
|
|
1207
|
+
/**
|
|
1208
|
+
* * Field Name: RowsToPackSampleMethod
|
|
1209
|
+
* * Display Name: Rows To Pack Sample Method
|
|
1210
|
+
* * SQL Data Type: nvarchar(20)
|
|
1211
|
+
* * Default Value: random
|
|
1212
|
+
* * Value List Type: List
|
|
1213
|
+
* * Possible Values
|
|
1214
|
+
* * random
|
|
1215
|
+
* * top n
|
|
1216
|
+
* * bottom n
|
|
1217
|
+
* * Description: Defines the sampling method for row packing when RowsToPackWithSchema is set to Sample. Options include random, top n, and bottom n. Defaults to random.
|
|
1218
|
+
*/
|
|
1219
|
+
this.RowsToPackSampleMethod = 'random';
|
|
1220
|
+
/**
|
|
1221
|
+
* * Field Name: RowsToPackSampleCount
|
|
1222
|
+
* * Display Name: Rows To Pack Sample Count
|
|
1223
|
+
* * SQL Data Type: int
|
|
1224
|
+
* * Default Value: 0
|
|
1225
|
+
* * Description: The number of rows to pack when RowsToPackWithSchema is set to Sample, based on the designated sampling method. Defaults to 0.
|
|
1226
|
+
*/
|
|
1227
|
+
this.RowsToPackSampleCount = 0;
|
|
1228
|
+
/**
|
|
1229
|
+
* * Field Name: RowsToPackSampleOrder
|
|
1230
|
+
* * Display Name: Rows To Pack Sample Order
|
|
1231
|
+
* * SQL Data Type: nvarchar(MAX)
|
|
1232
|
+
* * Description: An optional ORDER BY clause for row packing when RowsToPackWithSchema is set to Sample. Allows custom ordering for selected entity data when using top n and bottom n.
|
|
1233
|
+
*/
|
|
1234
|
+
this.RowsToPackSampleOrder = null;
|
|
1235
|
+
/**
|
|
1236
|
+
* * Field Name: AutoRowCountFrequency
|
|
1237
|
+
* * Display Name: Auto Row Count Frequency
|
|
1238
|
+
* * SQL Data Type: int
|
|
1239
|
+
* * Description: Frequency in hours for automatically performing row counts on this entity. If NULL, automatic row counting is disabled. If greater than 0, schedules recurring SELECT COUNT(*) queries at the specified interval.
|
|
1240
|
+
*/
|
|
1241
|
+
this.AutoRowCountFrequency = null;
|
|
1242
|
+
/**
|
|
1243
|
+
* * Field Name: RowCount
|
|
1244
|
+
* * Display Name: Row Count
|
|
1245
|
+
* * SQL Data Type: bigint
|
|
1246
|
+
* * Description: Cached row count for this entity, populated by automatic row count processes when AutoRowCountFrequency is configured.
|
|
1247
|
+
*/
|
|
1248
|
+
this.RowCount = null;
|
|
1249
|
+
/**
|
|
1250
|
+
* * Field Name: RowCountRunAt
|
|
1251
|
+
* * Display Name: Row Count Run At
|
|
1252
|
+
* * SQL Data Type: datetimeoffset
|
|
1253
|
+
* * Description: Timestamp indicating when the last automatic row count was performed for this entity.
|
|
1254
|
+
*/
|
|
1255
|
+
this.RowCountRunAt = null;
|
|
1256
|
+
/**
|
|
1257
|
+
* * Field Name: Status
|
|
1258
|
+
* * Display Name: Status
|
|
1259
|
+
* * SQL Data Type: nvarchar(25)
|
|
1260
|
+
* * Default Value: Active
|
|
1261
|
+
* * Description: Status of the entity. Active: fully functional; Deprecated: functional but generates console warnings when used; Disabled: not available for use even though metadata and physical table remain.
|
|
1262
|
+
*/
|
|
1263
|
+
this.Status = 'Active';
|
|
1264
|
+
// virtual fields - returned by the database VIEW
|
|
1265
|
+
/**
|
|
1266
|
+
* CodeName is a unique name that can be used for various programatic purposes, singular version of the entity name but modified from entity name in some cases to remove whitespace and prefix with _ in the event that the entity name begins with a number or other non-alpha character
|
|
1267
|
+
*/
|
|
1268
|
+
this.CodeName = null;
|
|
1269
|
+
this.ClassName = null;
|
|
1270
|
+
this.BaseTableCodeName = null;
|
|
1271
|
+
this.ParentEntity = null;
|
|
1272
|
+
this.ParentBaseTable = null;
|
|
1273
|
+
this.ParentBaseView = null;
|
|
1274
|
+
this._hasIdField = false;
|
|
1275
|
+
this._virtualCount = 0;
|
|
1276
|
+
this._manyToManyCount = 0;
|
|
1277
|
+
this._oneToManyCount = 0;
|
|
1278
|
+
this._floatCount = 0;
|
|
1279
|
+
if (initData) {
|
|
1280
|
+
this.copyInitData(initData);
|
|
1281
|
+
// do some special handling to create class instances instead of just data objects
|
|
1282
|
+
// copy the Entity Fields
|
|
1283
|
+
this._Fields = [];
|
|
1284
|
+
const ef = initData.EntityFields || initData._Fields;
|
|
1285
|
+
if (ef) {
|
|
1286
|
+
for (let j = 0; j < ef.length; j++) {
|
|
1287
|
+
this._Fields.push(new EntityFieldInfo(ef[j]));
|
|
1288
|
+
}
|
|
1289
|
+
}
|
|
1290
|
+
// copy the Entity Permissions
|
|
1291
|
+
this._Permissions = [];
|
|
1292
|
+
const ep = initData.EntityPermissions || initData._Permissions;
|
|
1293
|
+
if (ep) {
|
|
1294
|
+
for (let j = 0; j < ep.length; j++) {
|
|
1295
|
+
this._Permissions.push(new EntityPermissionInfo(ep[j]));
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
// copy the Entity settings
|
|
1299
|
+
this._Settings = [];
|
|
1300
|
+
const es = initData.EntitySettings || initData._Settings;
|
|
1301
|
+
if (es) {
|
|
1302
|
+
es.map((s) => this._Settings.push(new EntitySettingInfo(s)));
|
|
1303
|
+
}
|
|
1304
|
+
// copy the Related Entities
|
|
1305
|
+
this._RelatedEntities = [];
|
|
1306
|
+
const er = initData.EntityRelationships || initData._RelatedEntities;
|
|
1307
|
+
if (er) {
|
|
1308
|
+
// check to see if ANY of the records in the er array have a non-null or non-zero sequence value. The reason is
|
|
1309
|
+
// if we have any sequence values populated we want to sort by that sequence, and we want to consider null to be a high number
|
|
1310
|
+
// so that it sorts to the end of the list
|
|
1311
|
+
let bHasSequence = false;
|
|
1312
|
+
for (const j of er) {
|
|
1313
|
+
if (j.Sequence !== null && j.Sequence !== undefined && j.Sequence !== 0) {
|
|
1314
|
+
bHasSequence = true;
|
|
1315
|
+
break;
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
if (bHasSequence) {
|
|
1319
|
+
// sort by sequence if we have any populated sequence values
|
|
1320
|
+
er.sort((a, b) => {
|
|
1321
|
+
const aSeq = a.Sequence !== null && a.Sequence !== undefined ? a.Sequence : 999999;
|
|
1322
|
+
const bSeq = b.Sequence !== null && b.Sequence !== undefined ? b.Sequence : 999999;
|
|
1323
|
+
return aSeq - bSeq;
|
|
1324
|
+
});
|
|
1325
|
+
}
|
|
1326
|
+
// now that we have prepared the er array by sorting it, if needed, let's load up the related entities
|
|
1327
|
+
for (let j = 0; j < er.length; j++) {
|
|
1328
|
+
this._RelatedEntities.push(new EntityRelationshipInfo(er[j]));
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
this.prepareSpecialFields();
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
prepareSpecialFields() {
|
|
1335
|
+
try {
|
|
1336
|
+
let virtualCount = 0;
|
|
1337
|
+
let manyToManyCount = 0;
|
|
1338
|
+
let oneToManyCount = 0;
|
|
1339
|
+
let floatCount = 0;
|
|
1340
|
+
let hasIdField = false;
|
|
1341
|
+
for (let j = 0; j < this.Fields.length; ++j) {
|
|
1342
|
+
const f = this.Fields[j];
|
|
1343
|
+
if (f.Name.trim().toUpperCase() === 'ID')
|
|
1344
|
+
hasIdField = true;
|
|
1345
|
+
virtualCount += f.IsVirtual ? 1 : 0;
|
|
1346
|
+
floatCount += f.IsFloat ? 1 : 0;
|
|
1347
|
+
}
|
|
1348
|
+
this._hasIdField = hasIdField;
|
|
1349
|
+
this._floatCount = floatCount;
|
|
1350
|
+
this._virtualCount = virtualCount;
|
|
1351
|
+
// now see if there are any relationships and count the one to many and many to many
|
|
1352
|
+
for (let j = 0; j < this.RelatedEntities.length; ++j) {
|
|
1353
|
+
const r = this.RelatedEntities[j];
|
|
1354
|
+
if (r.Type.trim().toUpperCase() === 'ONE TO MANY')
|
|
1355
|
+
oneToManyCount++;
|
|
1356
|
+
else
|
|
1357
|
+
manyToManyCount++;
|
|
1358
|
+
}
|
|
1359
|
+
this._manyToManyCount = manyToManyCount;
|
|
1360
|
+
this._oneToManyCount = oneToManyCount;
|
|
1361
|
+
}
|
|
1362
|
+
catch (e) {
|
|
1363
|
+
(0, logging_1.LogError)(e);
|
|
1364
|
+
}
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1367
|
+
exports.EntityInfo = EntityInfo;
|
|
1368
|
+
EntityInfo.__createdAtFieldName = '__mj_CreatedAt';
|
|
1369
|
+
EntityInfo.__updatedAtFieldName = '__mj_UpdatedAt';
|
|
1370
|
+
EntityInfo.__deletedAtFieldName = '__mj_DeletedAt';
|
|
1371
|
+
/**
|
|
1372
|
+
* Information about the link between two entities
|
|
1373
|
+
*/
|
|
1374
|
+
class EntityDependency {
|
|
1375
|
+
}
|
|
1376
|
+
exports.EntityDependency = EntityDependency;
|
|
1377
|
+
/**
|
|
1378
|
+
* Information about the link between two records
|
|
1379
|
+
*/
|
|
1380
|
+
class RecordDependency {
|
|
1381
|
+
}
|
|
1382
|
+
exports.RecordDependency = RecordDependency;
|
|
1383
|
+
/**
|
|
1384
|
+
* Information about a merge request including the entity, the surviving record and the records to merge into the surviving record. Additionally, there is an optional field map that can be used to override field values in the surviving record to values specified.
|
|
1385
|
+
*/
|
|
1386
|
+
class RecordMergeRequest {
|
|
1387
|
+
}
|
|
1388
|
+
exports.RecordMergeRequest = RecordMergeRequest;
|
|
1389
|
+
/**
|
|
1390
|
+
* The result of a merge request for a single record
|
|
1391
|
+
*/
|
|
1392
|
+
class RecordMergeDetailResult {
|
|
1393
|
+
}
|
|
1394
|
+
exports.RecordMergeDetailResult = RecordMergeDetailResult;
|
|
1395
|
+
/**
|
|
1396
|
+
* The result of a merge request
|
|
1397
|
+
*/
|
|
1398
|
+
class RecordMergeResult {
|
|
1399
|
+
}
|
|
1400
|
+
exports.RecordMergeResult = RecordMergeResult;
|
|
1401
|
+
//# sourceMappingURL=entityInfo.js.map
|