@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.
Files changed (117) hide show
  1. package/dist/Core.d.ts +29 -0
  2. package/dist/Core.d.ts.map +1 -0
  3. package/dist/Core.js +58 -0
  4. package/dist/Core.js.map +1 -0
  5. package/dist/generic/QueryCache.d.ts +85 -0
  6. package/dist/generic/QueryCache.d.ts.map +1 -0
  7. package/dist/generic/QueryCache.js +198 -0
  8. package/dist/generic/QueryCache.js.map +1 -0
  9. package/dist/generic/QueryCacheConfig.d.ts +72 -0
  10. package/dist/generic/QueryCacheConfig.d.ts.map +1 -0
  11. package/dist/generic/QueryCacheConfig.js +3 -0
  12. package/dist/generic/QueryCacheConfig.js.map +1 -0
  13. package/dist/generic/applicationInfo.d.ts +138 -0
  14. package/dist/generic/applicationInfo.d.ts.map +1 -0
  15. package/dist/generic/applicationInfo.js +177 -0
  16. package/dist/generic/applicationInfo.js.map +1 -0
  17. package/dist/generic/authEvaluator.d.ts +25 -0
  18. package/dist/generic/authEvaluator.d.ts.map +1 -0
  19. package/dist/generic/authEvaluator.js +49 -0
  20. package/dist/generic/authEvaluator.js.map +1 -0
  21. package/dist/generic/authTypes.d.ts +193 -0
  22. package/dist/generic/authTypes.d.ts.map +1 -0
  23. package/dist/generic/authTypes.js +19 -0
  24. package/dist/generic/authTypes.js.map +1 -0
  25. package/dist/generic/baseEngine.d.ts +260 -0
  26. package/dist/generic/baseEngine.d.ts.map +1 -0
  27. package/dist/generic/baseEngine.js +510 -0
  28. package/dist/generic/baseEngine.js.map +1 -0
  29. package/dist/generic/baseEntity.d.ts +691 -0
  30. package/dist/generic/baseEntity.d.ts.map +1 -0
  31. package/dist/generic/baseEntity.js +1688 -0
  32. package/dist/generic/baseEntity.js.map +1 -0
  33. package/dist/generic/baseInfo.d.ts +24 -0
  34. package/dist/generic/baseInfo.d.ts.map +1 -0
  35. package/dist/generic/baseInfo.js +53 -0
  36. package/dist/generic/baseInfo.js.map +1 -0
  37. package/dist/generic/compositeKey.d.ts +206 -0
  38. package/dist/generic/compositeKey.d.ts.map +1 -0
  39. package/dist/generic/compositeKey.js +412 -0
  40. package/dist/generic/compositeKey.js.map +1 -0
  41. package/dist/generic/databaseProviderBase.d.ts +46 -0
  42. package/dist/generic/databaseProviderBase.d.ts.map +1 -0
  43. package/dist/generic/databaseProviderBase.js +14 -0
  44. package/dist/generic/databaseProviderBase.js.map +1 -0
  45. package/dist/generic/entityInfo.d.ts +983 -0
  46. package/dist/generic/entityInfo.d.ts.map +1 -0
  47. package/dist/generic/entityInfo.js +1401 -0
  48. package/dist/generic/entityInfo.js.map +1 -0
  49. package/dist/generic/explorerNavigationItem.d.ts +20 -0
  50. package/dist/generic/explorerNavigationItem.d.ts.map +1 -0
  51. package/dist/generic/explorerNavigationItem.js +29 -0
  52. package/dist/generic/explorerNavigationItem.js.map +1 -0
  53. package/dist/generic/interfaces.d.ts +610 -0
  54. package/dist/generic/interfaces.d.ts.map +1 -0
  55. package/dist/generic/interfaces.js +211 -0
  56. package/dist/generic/interfaces.js.map +1 -0
  57. package/dist/generic/libraryInfo.d.ts +40 -0
  58. package/dist/generic/libraryInfo.d.ts.map +1 -0
  59. package/dist/generic/libraryInfo.js +56 -0
  60. package/dist/generic/libraryInfo.js.map +1 -0
  61. package/dist/generic/logging.d.ts +179 -0
  62. package/dist/generic/logging.d.ts.map +1 -0
  63. package/dist/generic/logging.js +382 -0
  64. package/dist/generic/logging.js.map +1 -0
  65. package/dist/generic/metadata.d.ts +305 -0
  66. package/dist/generic/metadata.d.ts.map +1 -0
  67. package/dist/generic/metadata.js +454 -0
  68. package/dist/generic/metadata.js.map +1 -0
  69. package/dist/generic/metadataUtil.d.ts +8 -0
  70. package/dist/generic/metadataUtil.d.ts.map +1 -0
  71. package/dist/generic/metadataUtil.js +36 -0
  72. package/dist/generic/metadataUtil.js.map +1 -0
  73. package/dist/generic/providerBase.d.ts +546 -0
  74. package/dist/generic/providerBase.d.ts.map +1 -0
  75. package/dist/generic/providerBase.js +999 -0
  76. package/dist/generic/providerBase.js.map +1 -0
  77. package/dist/generic/queryInfo.d.ts +460 -0
  78. package/dist/generic/queryInfo.d.ts.map +1 -0
  79. package/dist/generic/queryInfo.js +633 -0
  80. package/dist/generic/queryInfo.js.map +1 -0
  81. package/dist/generic/querySQLFilters.d.ts +54 -0
  82. package/dist/generic/querySQLFilters.d.ts.map +1 -0
  83. package/dist/generic/querySQLFilters.js +84 -0
  84. package/dist/generic/querySQLFilters.js.map +1 -0
  85. package/dist/generic/runQuery.d.ts +96 -0
  86. package/dist/generic/runQuery.d.ts.map +1 -0
  87. package/dist/generic/runQuery.js +66 -0
  88. package/dist/generic/runQuery.js.map +1 -0
  89. package/dist/generic/runQuerySQLFilterImplementations.d.ts +51 -0
  90. package/dist/generic/runQuerySQLFilterImplementations.d.ts.map +1 -0
  91. package/dist/generic/runQuerySQLFilterImplementations.js +238 -0
  92. package/dist/generic/runQuerySQLFilterImplementations.js.map +1 -0
  93. package/dist/generic/runReport.d.ts +25 -0
  94. package/dist/generic/runReport.d.ts.map +1 -0
  95. package/dist/generic/runReport.js +42 -0
  96. package/dist/generic/runReport.js.map +1 -0
  97. package/dist/generic/securityInfo.d.ts +355 -0
  98. package/dist/generic/securityInfo.d.ts.map +1 -0
  99. package/dist/generic/securityInfo.js +425 -0
  100. package/dist/generic/securityInfo.js.map +1 -0
  101. package/dist/generic/transactionGroup.d.ts +184 -0
  102. package/dist/generic/transactionGroup.d.ts.map +1 -0
  103. package/dist/generic/transactionGroup.js +357 -0
  104. package/dist/generic/transactionGroup.js.map +1 -0
  105. package/dist/generic/util.d.ts +81 -0
  106. package/dist/generic/util.d.ts.map +1 -0
  107. package/dist/generic/util.js +301 -0
  108. package/dist/generic/util.js.map +1 -0
  109. package/dist/views/runView.d.ts +150 -0
  110. package/dist/views/runView.d.ts.map +1 -0
  111. package/dist/views/runView.js +100 -0
  112. package/dist/views/runView.js.map +1 -0
  113. package/dist/views/viewInfo.d.ts +121 -0
  114. package/dist/views/viewInfo.d.ts.map +1 -0
  115. package/dist/views/viewInfo.js +182 -0
  116. package/dist/views/viewInfo.js.map +1 -0
  117. 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