Socket
Socket
Sign inDemoInstall

@memberjunction/core

Package Overview
Dependencies
Maintainers
4
Versions
213
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@memberjunction/core - npm Package Compare versions

Comparing version 1.4.0 to 1.4.1

dist/generic/baseEngine.d.ts

2

dist/generic/applicationInfo.d.ts

@@ -39,4 +39,4 @@ import { BaseInfo } from './baseInfo';

get ApplicationSettings(): ApplicationSettingInfo[];
constructor(md: IMetadataProvider, initData?: any);
constructor(initData: any, md: IMetadataProvider);
}
//# sourceMappingURL=applicationInfo.d.ts.map

@@ -52,3 +52,3 @@ "use strict";

}
constructor(md, initData = null) {
constructor(initData = null, md) {
super();

@@ -55,0 +55,0 @@ this.Name = null;

import { EntityFieldInfo, EntityInfo, EntityFieldTSType, EntityPermissionType, RecordChange, ValidationResult, EntityRelationshipInfo } from './entityInfo';
import { CompositeKey, EntitySaveOptions, IEntityDataProvider } from './interfaces';
import { EntityDeleteOptions, EntitySaveOptions, IEntityDataProvider } from './interfaces';
import { UserInfo } from './securityInfo';
import { TransactionGroupBase } from './transactionGroup';
import { CompositeKey, FieldValueCollection } from './compositeKey';
import { Subscription } from 'rxjs';
/**
* Represents a field in an entity. This class is used to store the value of the field, dirty state, as well as other run-time information about the field. The class encapsulates the underlying field metadata and exposes some of the more commonly
* Represents a field in an instance of the BaseEntity class. This class is used to store the value of the field, dirty state, as well as other run-time information about the field. The class encapsulates the underlying field metadata and exposes some of the more commonly
* used properties from the entity field metadata.

@@ -83,2 +85,53 @@ */

/**
* Used for storing the result of a Save or Delete or other transactional operation within a BaseEntity
*/
export declare class BaseEntityResult {
/**
* True if successful, false otherwise
*/
Success: boolean;
/**
* The type of operation that was performed
*/
Type: 'create' | 'update' | 'delete';
/**
* A message for an end user
*/
Message: string;
/**
* Optional, a structured error object with additional information
*/
Error?: any;
/**
* A copy of the values of the entity object BEFORE the operation was performed
*/
OriginalValues: {
FieldName: string;
Value: any;
}[];
/**
* A copy of the values of the entity object AFTER the operation was performed
*/
NewValues: {
FieldName: string;
Value: any;
}[];
/**
* Timestamp when the operation started
*/
StartedAt: Date;
/**
* Timestamp when the operation ended
*/
EndedAt: Date;
}
/**
* Event type that is used to raise events and provided structured callbacks for any caller that is interested in registering for events.
*/
export declare class BaseEntityEvent {
type: 'new_record' | 'save' | 'delete' | 'other';
payload: any;
baseEntity: BaseEntity;
}
/**
* Base class used for all entity objects. This class is abstract and is sub-classes for each particular entity using the CodeGen tool. This class provides the basic functionality for loading, saving, and validating entity objects.

@@ -92,4 +145,24 @@ */

private _transactionGroup;
private _eventSubject;
private _resultHistory;
constructor(Entity: EntityInfo);
/**
* This method can be used to register a callback for events that will be raised by the instance of the BaseEntity object. The callback will be called with a
* BaseEntityEvent object that contains the type of event and any payload that is associated with the event. Subclasses of the BaseEntity can define their
* own event types and payloads as needed.
* @param callback
* @returns
*/
RegisterEventHandler(callback: (event: BaseEntityEvent) => void): Subscription;
/**
* Used for raising events within the BaseEntity and can be used by sub-classes to raise events that are specific to the entity.
*/
protected RaiseEvent(type: 'new_record' | 'save' | 'delete' | 'other', payload: any): void;
/**
* This method MUST be called right after the class is instantiated to provide an async/await pair for any asynchronous operations a given entity needs to do when it is first
* created/configured. When you call Metadata/Provider GetEntityObject() this is done automatically for you. In nearly all cases you should go through GetEntityObject() anyway
* and not ever directly instantiate a BaseEntity derived class.
*/
Config(contextUser: UserInfo): Promise<void>;
/**
* Returns true if the record has been saved to the database, false otherwise. This is a useful property to check to determine if the record is a "New Record" or an existing one.

@@ -105,2 +178,10 @@ */

/**
* The result history shows the history of the attempted transactions (Save and Delete) for this particular entity object. This is useful for tracking the results of operations on the entity object.
*/
get ResultHistory(): BaseEntityResult[];
/**
* Returns the most recent result from the result history. If there are no results in the history, this method will return null.
*/
get LatestResult(): BaseEntityResult;
/**
* Access to the underlying metadata for the entity object.

@@ -116,7 +197,6 @@ */

GetFieldByName(fieldName: string): EntityField;
get Dirty(): boolean;
/**
* Returns the primary key field for the entity. If the entity has a composite primary key, this method will return the first primary key field.
* Returns true if the object is Dirty, meaning something has changed since it was last saved to the database, and false otherwise. For new records, this will always return true.
*/
get PrimaryKey(): EntityField;
get Dirty(): boolean;
/**

@@ -127,4 +207,13 @@ * Returns an array of all primary key fields for the entity. If the entity has a composite primary key, this method will return an array of all primary key fields.

get PrimaryKeys(): EntityField[];
get CompositeKey(): CompositeKey;
private _compositeKey;
/**
* Returns the primary key for the record. The CompositeKey class is a multi-valued key that can have any number of key/value pairs within it. Always traverse the full
* set of key/value pairs to get the full primary key for the record.
*/
get PrimaryKey(): CompositeKey;
/**
* Helper method to return just the first Primary Key
*/
get FirstPrimaryKey(): EntityField;
/**
* Returns true if the record has been loaded from the database, false otherwise. This is useful to check to see if the record is in a "New Record" state or not.

@@ -195,5 +284,7 @@ */

* This method will create a new state for the object that is equivalent to a new record including default values.
* @param newValues - optional parameter to set the values of the fields to something other than the default values. The expected parameter is an object that has properties that map to field names in this entity.
* This is the same as creating a NewRecord and then using SetMany(), but it is a convenience/helper approach.
* @returns
*/
NewRecord(): boolean;
NewRecord(newValues?: FieldValueCollection): boolean;
/**

@@ -232,3 +323,2 @@ * Saves the current state of the object to the database. Uses the active provider to handle the actual saving of the record. If the record is new, it will be created, if it already exists, it will be updated.

InnerLoad(CompositeKey: CompositeKey, EntityRelationshipsToLoad?: string[]): Promise<boolean>;
protected ValidateCompositeKey(compositeKey: CompositeKey): void;
/**

@@ -254,3 +344,3 @@ * This method is meant to be used only in situations where you are sure that the data you are loading is current in the database. MAKE SURE YOU ARE PASSING IN ALL FIELDS.

*/
Delete(): Promise<boolean>;
Delete(options?: EntityDeleteOptions): Promise<boolean>;
/**

@@ -257,0 +347,0 @@ * Called before an Action is executed by the AI Engine

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BaseEntity = exports.BaseEntityAIActionParams = exports.DataObjectParams = exports.DataObjectRelatedEntityParam = exports.EntityField = void 0;
exports.BaseEntity = exports.BaseEntityEvent = exports.BaseEntityResult = exports.BaseEntityAIActionParams = exports.DataObjectParams = exports.DataObjectRelatedEntityParam = exports.EntityField = void 0;
const global_1 = require("@memberjunction/global");

@@ -10,4 +10,6 @@ const entityInfo_1 = require("./entityInfo");

const logging_1 = require("./logging");
const compositeKey_1 = require("./compositeKey");
const rxjs_1 = require("rxjs");
/**
* Represents a field in an entity. This class is used to store the value of the field, dirty state, as well as other run-time information about the field. The class encapsulates the underlying field metadata and exposes some of the more commonly
* Represents a field in an instance of the BaseEntity class. This class is used to store the value of the field, dirty state, as well as other run-time information about the field. The class encapsulates the underlying field metadata and exposes some of the more commonly
* used properties from the entity field metadata.

@@ -234,2 +236,24 @@ */

/**
* Used for storing the result of a Save or Delete or other transactional operation within a BaseEntity
*/
class BaseEntityResult {
constructor() {
/**
* A copy of the values of the entity object BEFORE the operation was performed
*/
this.OriginalValues = [];
/**
* A copy of the values of the entity object AFTER the operation was performed
*/
this.NewValues = [];
}
}
exports.BaseEntityResult = BaseEntityResult;
/**
* Event type that is used to raise events and provided structured callbacks for any caller that is interested in registering for events.
*/
class BaseEntityEvent {
}
exports.BaseEntityEvent = BaseEntityEvent;
/**
* Base class used for all entity objects. This class is abstract and is sub-classes for each particular entity using the CodeGen tool. This class provides the basic functionality for loading, saving, and validating entity objects.

@@ -243,2 +267,5 @@ */

this._transactionGroup = null;
this._resultHistory = [];
this._compositeKey = null;
this._eventSubject = new rxjs_1.Subject();
this._EntityInfo = Entity;

@@ -248,7 +275,30 @@ this.init();

/**
* This method can be used to register a callback for events that will be raised by the instance of the BaseEntity object. The callback will be called with a
* BaseEntityEvent object that contains the type of event and any payload that is associated with the event. Subclasses of the BaseEntity can define their
* own event types and payloads as needed.
* @param callback
* @returns
*/
RegisterEventHandler(callback) {
return this._eventSubject.asObservable().subscribe(callback);
}
/**
* Used for raising events within the BaseEntity and can be used by sub-classes to raise events that are specific to the entity.
*/
RaiseEvent(type, payload) {
this._eventSubject.next({ type: type, payload: payload, baseEntity: this });
}
/**
* This method MUST be called right after the class is instantiated to provide an async/await pair for any asynchronous operations a given entity needs to do when it is first
* created/configured. When you call Metadata/Provider GetEntityObject() this is done automatically for you. In nearly all cases you should go through GetEntityObject() anyway
* and not ever directly instantiate a BaseEntity derived class.
*/
async Config(contextUser) {
this.ContextCurrentUser = contextUser;
}
/**
* Returns true if the record has been saved to the database, false otherwise. This is a useful property to check to determine if the record is a "New Record" or an existing one.
*/
get IsSaved() {
const v = this.PrimaryKey?.Value;
return v !== null && v !== undefined; // if the primary key (or first primary key) value is null/undefined, we haven't saved yet
return this.PrimaryKey.HasValue;
}

@@ -266,2 +316,17 @@ /**

/**
* The result history shows the history of the attempted transactions (Save and Delete) for this particular entity object. This is useful for tracking the results of operations on the entity object.
*/
get ResultHistory() {
return this._resultHistory;
}
/**
* Returns the most recent result from the result history. If there are no results in the history, this method will return null.
*/
get LatestResult() {
if (this._resultHistory.length > 0)
return this._resultHistory[this._resultHistory.length - 1];
else
return null;
}
/**
* Access to the underlying metadata for the entity object.

@@ -283,2 +348,5 @@ */

}
/**
* Returns true if the object is Dirty, meaning something has changed since it was last saved to the database, and false otherwise. For new records, this will always return true.
*/
get Dirty() {

@@ -288,13 +356,2 @@ return !this.IsSaved || this.Fields.some(f => f.Dirty);

/**
* Returns the primary key field for the entity. If the entity has a composite primary key, this method will return the first primary key field.
*/
get PrimaryKey() {
const fieldInfo = this.EntityInfo.PrimaryKey;
if (fieldInfo) {
return this.GetFieldByName(fieldInfo.Name);
}
else
return null;
}
/**
* Returns an array of all primary key fields for the entity. If the entity has a composite primary key, this method will return an array of all primary key fields.

@@ -306,8 +363,20 @@ * If the entity has a single primary key, this method will return an array with a single field in it.

}
get CompositeKey() {
const ck = new interfaces_1.CompositeKey();
ck.LoadFromEntityFields(this.PrimaryKeys);
return ck;
/**
* Returns the primary key for the record. The CompositeKey class is a multi-valued key that can have any number of key/value pairs within it. Always traverse the full
* set of key/value pairs to get the full primary key for the record.
*/
get PrimaryKey() {
if (this._compositeKey === null) {
this._compositeKey = new compositeKey_1.CompositeKey();
this._compositeKey.LoadFromEntityFields(this.PrimaryKeys);
}
return this._compositeKey;
}
/**
* Helper method to return just the first Primary Key
*/
get FirstPrimaryKey() {
return this.PrimaryKeys[0];
}
/**
* Returns true if the record has been loaded from the database, false otherwise. This is useful to check to see if the record is in a "New Record" state or not.

@@ -474,2 +543,4 @@ */

init() {
this._compositeKey = null;
this._resultHistory = [];
this._recordLoaded = false;

@@ -519,6 +590,14 @@ this._Fields = [];

* This method will create a new state for the object that is equivalent to a new record including default values.
* @param newValues - optional parameter to set the values of the fields to something other than the default values. The expected parameter is an object that has properties that map to field names in this entity.
* This is the same as creating a NewRecord and then using SetMany(), but it is a convenience/helper approach.
* @returns
*/
NewRecord() {
NewRecord(newValues) {
this.init();
if (newValues) {
newValues.KeyValuePairs.filter(kv => kv.Value !== null && kv.Value !== undefined).forEach(kv => {
this.Set(kv.FieldName, kv.Value);
});
}
this.RaiseEvent('new_record', null);
return true;

@@ -532,28 +611,50 @@ }

async Save(options) {
const _options = options ? options : new interfaces_1.EntitySaveOptions();
const type = this.IsSaved ? entityInfo_1.EntityPermissionType.Update : entityInfo_1.EntityPermissionType.Create;
this.CheckPermissions(type, true); // this will throw an error and exit out if we don't have permission
if (_options.IgnoreDirtyState || this.Dirty) {
if (BaseEntity.Provider == null) {
throw new Error('No provider set');
}
else {
const valResult = this.Validate();
if (valResult.Success) {
const data = await BaseEntity.Provider.Save(this, this.ActiveUser, _options);
if (data) {
this.init(); // wipe out the current data to flush out the DIRTY flags, load the ID as part of this too
this.SetMany(data);
return true;
}
else
return false;
const currentResultCount = this.ResultHistory.length;
const newResult = new BaseEntityResult();
newResult.StartedAt = new Date();
try {
const _options = options ? options : new interfaces_1.EntitySaveOptions();
const type = this.IsSaved ? entityInfo_1.EntityPermissionType.Update : entityInfo_1.EntityPermissionType.Create;
this.CheckPermissions(type, true); // this will throw an error and exit out if we don't have permission
if (_options.IgnoreDirtyState || this.Dirty) {
if (BaseEntity.Provider == null) {
throw new Error('No provider set');
}
else {
throw valResult; // pass this along to the caller
const valResult = this.Validate();
if (valResult.Success) {
const data = await BaseEntity.Provider.Save(this, this.ActiveUser, _options);
if (data) {
this.init(); // wipe out the current data to flush out the DIRTY flags, load the ID as part of this too
this.SetMany(data);
const result = this.LatestResult;
if (result)
result.NewValues = this.Fields.map(f => { return { FieldName: f.CodeName, Value: f.Value }; }); // set the latest values here
this.RaiseEvent('save', null);
return true;
}
else
return false;
}
else {
throw valResult; // pass this along to the caller
}
}
}
else
return true; // nothing to save since we're not dirty
}
else
return true; // nothing to save since we're not dirty
catch (e) {
if (currentResultCount === this.ResultHistory.length) {
// this means that NO new results were added to the history anywhere
// so we need to add a new result to the history here
newResult.Success = false;
newResult.Type = this.IsSaved ? 'update' : 'create';
newResult.Message = e.message;
newResult.OriginalValues = this.Fields.map(f => { return { FieldName: f.CodeName, Value: f.OldValue }; });
newResult.EndedAt = new Date();
this.ResultHistory.push(newResult);
}
return false;
}
}

@@ -631,3 +732,5 @@ /**

const start = new Date().getTime();
this.ValidateCompositeKey(CompositeKey);
const valResult = CompositeKey.Validate();
if (!valResult || !valResult.IsValid)
throw new Error(`Invalid CompositeKey passed to BaseEntity.Load(${this.EntityInfo.Name})`);
this.CheckPermissions(entityInfo_1.EntityPermissionType.Read, true); // this will throw an error and exit out if we don't have permission

@@ -652,29 +755,6 @@ if (!this.IsSaved) {

this._recordLoaded = true;
// const end = new Date().getTime();
// const time = end - start;
// LogStatus(`BaseEntity.Load(${this.EntityInfo.Name}, ID: ${ID}, EntityRelationshipsToLoad.length: ${EntityRelationshipsToLoad ? EntityRelationshipsToLoad.length : 0 }), took ${time}ms`);
this._compositeKey = CompositeKey; // set the composite key to the one we just loaded
return true;
}
}
ValidateCompositeKey(compositeKey) {
// make sure that KeyValuePairs is an array of 1+ objects, and that each object has a FieldName and Value property and that the FieldName is a valid field on the entity that has IsPrimaryKey set to true
if (!compositeKey || !compositeKey.KeyValuePairs || compositeKey.KeyValuePairs.length === 0)
throw new Error('KeyValuePairs cannot be null or empty');
else {
// now loop through the array and make sure each object has a FieldName and Value property
// and that the field name is a valid field on the entity that has IsPrimaryKey set to true
for (let i = 0; i < compositeKey.KeyValuePairs.length; i++) {
const pk = compositeKey.KeyValuePairs[i];
if (!pk.FieldName || pk.FieldName.trim().length === 0)
throw new Error(`KeyValuePairs[${i}].FieldName cannot be null, empty, or whitespace`);
if (pk.Value === null || pk.Value === undefined)
throw new Error(`KeyValuePairs[${i}].Value cannot be null or undefined`);
const field = this.Fields.find(f => f.Name.trim().toLowerCase() === pk.FieldName.trim().toLowerCase());
if (!field)
throw new Error(`KeyValuePairs[${i}].FieldName of ${pk.FieldName} does not exist on ${this.EntityInfo.Name}`);
if (!field.IsPrimaryKey)
throw new Error(`KeyValuePairs[${i}].FieldName of ${pk.FieldName} is not a primary key field on ${this.EntityInfo.Name}`);
}
}
}
/**

@@ -714,16 +794,35 @@ * This method is meant to be used only in situations where you are sure that the data you are loading is current in the database. MAKE SURE YOU ARE PASSING IN ALL FIELDS.

*/
async Delete() {
if (BaseEntity.Provider == null) {
throw new Error('No provider set');
async Delete(options) {
const currentResultCount = this.ResultHistory.length;
const newResult = new BaseEntityResult();
newResult.StartedAt = new Date();
try {
if (BaseEntity.Provider == null) {
throw new Error('No provider set');
}
else {
this.CheckPermissions(entityInfo_1.EntityPermissionType.Delete, true); // this will throw an error and exit out if we don't have permission
if (await BaseEntity.Provider.Delete(this, options, this.ActiveUser)) {
// record deleted correctly
// wipe out the current data to flush out the DIRTY flags by calling NewRecord()
this.RaiseEvent('delete', null);
this.NewRecord(); // will trigger a new record event here too
return true;
}
else // record didn't save, return false, but also don't wipe out the entity like we do if the Delete() worked
return false;
}
}
else {
this.CheckPermissions(entityInfo_1.EntityPermissionType.Delete, true); // this will throw an error and exit out if we don't have permission
if (await BaseEntity.Provider.Delete(this, this.ActiveUser)) {
// record deleted correctly
// wipe out the current data to flush out the DIRTY flags by calling NewRecord()
this.NewRecord();
return true;
catch (e) {
if (currentResultCount === this.ResultHistory.length) {
// this means that NO new results were added to the history anywhere
// so we need to add a new result to the history here
newResult.Success = false;
newResult.Type = 'delete';
newResult.Message = e.message;
newResult.OriginalValues = this.Fields.map(f => { return { FieldName: f.CodeName, Value: f.OldValue }; });
newResult.EndedAt = new Date();
this.ResultHistory.push(newResult);
}
else // record didn't save, return false, but also don't wipe out the entity like we do if the Delete() worked
return false;
return false;
}

@@ -763,3 +862,3 @@ }

if (this.IsSaved) {
return BaseEntity.GetRecordChanges(this.EntityInfo.Name, this.CompositeKey);
return BaseEntity.GetRecordChanges(this.EntityInfo.Name, this.PrimaryKey);
}

@@ -766,0 +865,0 @@ else {

@@ -7,4 +7,6 @@ export declare abstract class BaseInfo {

protected copyInitData(initData: any): void;
protected stripUnicodePrefix(value: string): string;
protected stripSingleQuotes(value: string): string;
protected stripContainingParens(value: string): string;
}
//# sourceMappingURL=baseInfo.d.ts.map

@@ -19,5 +19,9 @@ "use strict";

if (thisKeys.indexOf(keys[j]) >= 0) {
if (keys[j].trim().toLowerCase() === 'defaultvalue' && initData[keys[j]])
// strip parens from default value from the DB, if they exist, for example defaults might be ((1)) or (getdate())
this[keys[j]] = this.stripContainingParens(initData[keys[j]]);
if (keys[j].trim().toLowerCase() === 'defaultvalue' && initData[keys[j]]) {
// strip parens from default value from the DB, if they exist, for example defaults might be ((1)) or (getdate())
// could also be something like (('Pending')) in which case we'll want to remove the SYMMETRIC parens
const noParens = this.stripContainingParens(initData[keys[j]]);
const finalValue = this.stripSingleQuotes(this.stripUnicodePrefix(noParens));
this[keys[j]] = finalValue;
}
else

@@ -29,2 +33,22 @@ this[keys[j]] = initData[keys[j]];

}
stripUnicodePrefix(value) {
if (!value)
return value;
const val = value.trim(); // trim it first
// check to see if the first character is an N and if the character after
// that as well as the last character are single quotes, if so, strip all of those out
if (value && value.toUpperCase().startsWith('N') &&
value.length > 1 && value.charAt(1) === '\'' &&
value.charAt(value.length - 1) === '\'') {
return value.substring(2, value.length - 1); // strip out the N and the single quotes for example N'Active' becomes Active
}
}
stripSingleQuotes(value) {
if (!value)
return value;
const val = value.trim(); // trim it first
// now check for symmetrical single quotes and remove them
// this is for cases like 'Pending' or 'Active' which are stored in the DB as ('Pending') or ('Active')
return val.startsWith("'") && val.endsWith("'") ? val.substring(1, val.length - 1) : val;
}
stripContainingParens(value) {

@@ -31,0 +55,0 @@ if (value.startsWith('(') && value.endsWith(')')) {

@@ -5,3 +5,3 @@ import { BaseInfo } from "./baseInfo";

import { RowLevelSecurityFilterInfo, UserInfo } from "./securityInfo";
import { CompositeKey } from "./interfaces";
import { CompositeKey } from "./compositeKey";
/**

@@ -273,11 +273,3 @@ * The possible status values for a record change

}
export declare function CodeNameFromString(input: string): string;
/**
* Primary Key Value object is used to pass in a primary key field/value pairs to BaseEntity.Load() and other methods that need to load a record by primary key
*/
export declare class KeyValuePair {
FieldName: string;
Value: any;
}
/**
* 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.

@@ -293,27 +285,2 @@ */

/**
* Entity Behavior Type Info object has information about the behavior types that can be applied to an entity
*/
export declare class EntityBehaviorTypeInfo extends BaseInfo {
Name: string;
Description: string;
CreatedAt: Date;
UpdatedAt: Date;
constructor(initData?: any);
}
/**
* Contains information about a specific behavior that has been applied to an entity
*/
export declare class EntityBehaviorInfo extends BaseInfo {
EntityID: number;
BehaviorTypeID: number;
Description: string;
RegenerateCode: boolean;
Code: string;
CodeExplanation: string;
CodeGenerated: boolean;
CreatedAt: Date;
UpdatedAt: Date;
constructor(initData?: any);
}
/**
* Settings allow you to store key/value pairs of information that can be used to configure the behavior of the entity.

@@ -390,3 +357,2 @@ */

private _Permissions;
private _Behaviors;
private _Settings;

@@ -399,6 +365,6 @@ _hasIdField: boolean;

/**
* Returns the primary key for the entity. For entities with a composite primary key, use the PrimaryKeys property which returns all.
* Returns the primary key field for the entity. For entities with a composite primary key, use the PrimaryKeys property which returns all.
* In the case of a composite primary key, the PrimaryKey property will return the first field in the sequence of the primary key fields.
*/
get PrimaryKey(): EntityFieldInfo;
get FirstPrimaryKey(): EntityFieldInfo;
/**

@@ -413,5 +379,8 @@ * 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.

get Permissions(): EntityPermissionInfo[];
get Behaviors(): EntityBehaviorInfo[];
get Settings(): EntitySettingInfo[];
/**
* @returns The BaseTable but with spaces inbetween capital letters
* */
get DisplayName(): string;
/**
* 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.

@@ -457,2 +426,7 @@ * If no fields match, if there is a field called "Name", that is returned. If there is no field called "Name", null is returned.

static BuildRelationshipViewParams(record: BaseEntity, relationship: EntityRelationshipInfo, filter?: string, maxRecords?: number): RunViewParams;
/**
* 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.
* 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
*/
static BuildRelationshipNewRecordValues(record: BaseEntity, relationship: EntityRelationshipInfo): any;
constructor(initData?: any);

@@ -459,0 +433,0 @@ private prepareSpecialFields;

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RecordMergeResult = exports.RecordMergeDetailResult = exports.RecordMergeRequest = exports.RecordDependency = exports.EntityDependency = exports.ValidationResult = exports.ValidationErrorInfo = exports.ValidationErrorType = exports.EntityInfo = exports.EntitySettingInfo = exports.EntityBehaviorInfo = exports.EntityBehaviorTypeInfo = exports.EntityDocumentTypeInfo = exports.KeyValuePair = exports.CodeNameFromString = 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;
exports.RecordMergeResult = exports.RecordMergeDetailResult = exports.RecordMergeRequest = exports.RecordDependency = exports.EntityDependency = exports.ValidationResult = exports.ValidationErrorInfo = exports.ValidationErrorType = 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;
const baseInfo_1 = require("./baseInfo");

@@ -251,3 +251,3 @@ const metadata_1 = require("./metadata");

if (this._codeName === null) {
this._codeName = CodeNameFromString(this.Name);
this._codeName = (0, util_1.CodeNameFromString)(this.Name);
}

@@ -413,20 +413,3 @@ return this._codeName;

exports.EntityFieldInfo = EntityFieldInfo;
function CodeNameFromString(input) {
// the code below replaces characters invalid for SQL or TypeScript identifiers with _ and stashes the result in a private variable so we only do this once
// Replace all invalid characters with _
let codeName = input.replace(/[^a-zA-Z0-9_]/g, "_");
// Prepend an underscore if the first character is a number
if (/^[0-9]/.test(codeName)) {
codeName = "_" + codeName;
}
return codeName;
}
exports.CodeNameFromString = CodeNameFromString;
/**
* Primary Key Value object is used to pass in a primary key field/value pairs to BaseEntity.Load() and other methods that need to load a record by primary key
*/
class KeyValuePair {
}
exports.KeyValuePair = KeyValuePair;
/**
* 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.

@@ -446,35 +429,2 @@ */

/**
* Entity Behavior Type Info object has information about the behavior types that can be applied to an entity
*/
class EntityBehaviorTypeInfo extends baseInfo_1.BaseInfo {
constructor(initData = null) {
super();
this.Name = null;
this.Description = null;
this.CreatedAt = null;
this.UpdatedAt = null;
this.copyInitData(initData);
}
}
exports.EntityBehaviorTypeInfo = EntityBehaviorTypeInfo;
/**
* Contains information about a specific behavior that has been applied to an entity
*/
class EntityBehaviorInfo extends baseInfo_1.BaseInfo {
constructor(initData = null) {
super();
this.EntityID = null;
this.BehaviorTypeID = null;
this.Description = null;
this.RegenerateCode = null;
this.Code = null;
this.CodeExplanation = null;
this.CodeGenerated = null;
this.CreatedAt = null;
this.UpdatedAt = null;
this.copyInitData(initData);
}
}
exports.EntityBehaviorInfo = EntityBehaviorInfo;
/**
* Settings allow you to store key/value pairs of information that can be used to configure the behavior of the entity.

@@ -500,6 +450,6 @@ */

/**
* Returns the primary key for the entity. For entities with a composite primary key, use the PrimaryKeys property which returns all.
* Returns the primary key field for the entity. For entities with a composite primary key, use the PrimaryKeys property which returns all.
* In the case of a composite primary key, the PrimaryKey property will return the first field in the sequence of the primary key fields.
*/
get PrimaryKey() {
get FirstPrimaryKey() {
return this.Fields.find((f) => f.IsPrimaryKey);

@@ -528,5 +478,2 @@ }

}
get Behaviors() {
return this._Behaviors;
}
get Settings() {

@@ -536,2 +483,8 @@ return this._Settings;

/**
* @returns The BaseTable but with spaces inbetween capital letters
* */
get DisplayName() {
return this.BaseTable.replace(/([A-Z])/g, ' $1').trim();
}
/**
* 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.

@@ -697,4 +650,6 @@ * If no fields match, if there is a field called "Name", that is returned. If there is no field called "Name", null is returned.

else {
keyValue = record.PrimaryKey.Value;
quotes = record.PrimaryKey.NeedsQuotes ? "'" : '';
// currently we only support a single value for FOREIGN KEYS, so we can just grab the first value in the primary key
const firstKey = record.FirstPrimaryKey;
keyValue = firstKey.Value;
quotes = firstKey.NeedsQuotes ? "'" : '';
}

@@ -723,2 +678,17 @@ if (relationship.Type.trim().toLowerCase() === 'one to many') {

}
/**
* 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.
* 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
*/
static BuildRelationshipNewRecordValues(record, relationship) {
// we want to build a simple javascript object that will pre-populate a new record in the related entity with values that link
// abck to the current record. 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
const obj = {};
if (record && relationship) {
const keyField = relationship.EntityKeyField && relationship.EntityKeyField.trim().length > 0 ? relationship.EntityKeyField : record.FirstPrimaryKey.Name;
obj[relationship.RelatedEntityJoinField] = record.Get(keyField);
}
return obj;
}
constructor(initData = null) {

@@ -804,8 +774,2 @@ super();

}
// copy the Entity Behaviors
this._Behaviors = [];
const eb = initData.EntityBehaviors || initData._Behaviors;
if (eb) {
eb.map((b) => this._Behaviors.push(new EntityBehaviorInfo(b)));
}
// copy the Entity settings

@@ -812,0 +776,0 @@ this._Settings = [];

@@ -1,3 +0,3 @@

import { BaseEntity, EntityField } from "./baseEntity";
import { EntityDependency, EntityInfo, KeyValuePair, RecordChange, RecordDependency, RecordMergeRequest, RecordMergeResult } from "./entityInfo";
import { BaseEntity } from "./baseEntity";
import { EntityDependency, EntityInfo, RecordChange, RecordDependency, RecordMergeRequest, RecordMergeResult } from "./entityInfo";
import { ApplicationInfo } from "./applicationInfo";

@@ -10,2 +10,4 @@ import { RunViewParams } from "../views/runView";

import { RunQueryParams } from "./runQuery";
import { LibraryInfo } from "./libraryInfo";
import { CompositeKey } from "./compositeKey";
export declare class ProviderConfigDataBase {

@@ -32,77 +34,2 @@ private _includeSchemas;

export type ProviderType = typeof ProviderType[keyof typeof ProviderType];
export declare class CompositeKey {
KeyValuePairs: KeyValuePair[];
constructor(keyValuePairs?: KeyValuePair[]);
/**
* returns the value of the key value pair for the specified field name
* @param fieldName the field name to get the value for
* @returns the value of the key value pair for the specified field name
*/
GetValueByFieldName(fieldName: string): any;
/**
* returns the value of the key value pair at the specified index
* @param index the index of the key value pair to get the value for
* @returns the value of the key value pair at the specified index
*/
GetValueByIndex(index: number): any;
/**
* @returns a string representation of the primary key values in the format "FieldName=Value"
* @example "ID=1 AND Name=John"
* @param useIsNull if true, will return "FieldName IS NULL" for any key value pair that has a null or undefined value
*/
ToString(useIsNull?: boolean): string;
/**
* @returns a copy of the KeyValuePairs array but with the Value properties as type string
*/
ValuesAsString(): KeyValuePair[];
/**
* Utility function to return a copy of the CompositeKey with the Value properties as string
* @returns a copy of the KeyValuePairs array but with the Value properties as string
*/
Copy(): CompositeKey;
/**
* @returns the KeyValuePairs as a list of strings in the format "FieldName=Value"
* @param delimiter the delimiter to use between the field name and value. Defaults to '='
* @example ["ID=1", "Name=John"]
*/
ToList(delimiter?: string): string[];
/**
* @returns the value of each key value pair in the format "Value1, Value2, Value3"
* @param delimiter - the delimiter to use between the values. Defaults to ', '
* @example "1, John"
*/
Values(delimiter?: string): string;
/**
* Utility function to compare the key primary key of this object to another sets to see if they are the same or not
* @param kvPairs the primary key values to compare against
* @returns true if the primary key values are the same, false if they are different
*/
EqualsKey(kvPairs: KeyValuePair[]): boolean;
/**
* Utility function to compare this composite key to another
* @param compositeKey the composite key to compare against
* @returns true if the primary key values are the same, false if they are different
*/
Equals(compositeKey: CompositeKey): boolean;
LoadFromEntityFields(fields: EntityField[]): void;
LoadFromEntityInfoAndRecord(entity: EntityInfo, entityRecord: any): void;
/**
* Loads the KeyValuePairs from a list of strings in the format "FieldName=Value"
* @param list - the list of strings to load from
* @param delimiter - the delimiter to use between the field name and value. Defaults to '='
* @example ["ID=1", "Name=John"]
*/
LoadFromList(list: string[], delimiter?: string): void;
ToURLSegment(segment?: string): string;
LoadFromURLSegment(entity: EntityInfo, routeSegment: string, segment?: string): void;
/**
* Helper method to check if the underlying key value pairs are valid or not
* i.e. if any of the key value pairs are null or undefined
* @returns true if all key value pairs are valid, false if any are null or undefined
*/
Validate(): {
IsValid: boolean;
ErrorMessage: string;
};
}
export declare class PotentialDuplicate extends CompositeKey {

@@ -153,9 +80,35 @@ ProbabilityScore: number;

Save(entity: BaseEntity, user: UserInfo, options: EntitySaveOptions): Promise<{}>;
Delete(entity: BaseEntity, user: UserInfo): Promise<boolean>;
Delete(entity: BaseEntity, options: EntityDeleteOptions, user: UserInfo): Promise<boolean>;
GetRecordChanges(entityName: string, CompositeKey: CompositeKey): Promise<RecordChange[]>;
}
/**
* Save options used when saving an entity record
*/
export declare class EntitySaveOptions {
/**
* If set to true, the record will be saved to the database even if nothing is detected to be "dirty" or changed since the prior load.
*/
IgnoreDirtyState: boolean;
/**
* If set to true, an AI actions associated with the entity will be skipped during the save operation
*/
SkipEntityAIActions?: boolean;
/**
* If set to true, any Entity Actions associated with invocation types of Create or Update will be skipped during the save operation
*/
SkipEntityActions?: boolean;
}
/**
* Options used when deleting an entity record
*/
export declare class EntityDeleteOptions {
/**
* If set to true, an AI actions associated with the entity will be skipped during the delete operation
*/
SkipEntityAIActions?: boolean;
/**
* If set to true, any Entity Actions associated with invocation types of Delete will be skipped during the delete operation
*/
SkipEntityActions?: boolean;
}
export declare class EntityRecordNameInput {

@@ -191,2 +144,3 @@ EntityName: string;

get QueryPermissions(): QueryPermissionInfo[];
get Libraries(): LibraryInfo[];
get LatestRemoteMetadata(): MetadataInfo[];

@@ -324,3 +278,3 @@ get LatestLocalMetadata(): MetadataInfo[];

*/
export type RunViewResult = {
export type RunViewResult<T = any> = {
/**

@@ -333,3 +287,3 @@ * Was the view run successful or not

*/
Results: any[];
Results: Array<T>;
/**

@@ -360,3 +314,3 @@ * The newly created UserViews.ID value - only provided if RunViewParams.SaveViewResults=true

Config(configData: ProviderConfigDataBase): Promise<boolean>;
RunView(params: RunViewParams, contextUser?: UserInfo): Promise<RunViewResult>;
RunView<T = any>(params: RunViewParams, contextUser?: UserInfo): Promise<RunViewResult<T>>;
}

@@ -363,0 +317,0 @@ export type RunQueryResult = {

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.EntityRecordNameResult = exports.EntityRecordNameInput = exports.EntitySaveOptions = exports.PotentialDuplicateResponse = exports.PotentialDuplicateResult = exports.PotentialDuplicateRequest = exports.PotentialDuplicate = exports.CompositeKey = exports.ProviderType = exports.MetadataInfo = exports.ProviderConfigDataBase = void 0;
const entityInfo_1 = require("./entityInfo");
exports.EntityRecordNameResult = exports.EntityRecordNameInput = exports.EntityDeleteOptions = exports.EntitySaveOptions = exports.PotentialDuplicateResponse = exports.PotentialDuplicateResult = exports.PotentialDuplicateRequest = exports.PotentialDuplicate = exports.ProviderType = exports.MetadataInfo = exports.ProviderConfigDataBase = void 0;
const compositeKey_1 = require("./compositeKey");
class ProviderConfigDataBase {

@@ -38,183 +38,4 @@ get Data() {

};
class CompositeKey {
constructor(keyValuePairs) {
this.KeyValuePairs = keyValuePairs || [];
}
/**
* returns the value of the key value pair for the specified field name
* @param fieldName the field name to get the value for
* @returns the value of the key value pair for the specified field name
*/
GetValueByFieldName(fieldName) {
let key = this.KeyValuePairs.find((keyValue) => {
return keyValue.FieldName === fieldName;
});
return key ? key.Value : null;
}
/**
* returns the value of the key value pair at the specified index
* @param index the index of the key value pair to get the value for
* @returns the value of the key value pair at the specified index
*/
GetValueByIndex(index) {
if (index >= 0 && index < this.KeyValuePairs.length) {
return this.KeyValuePairs[index].Value;
}
return null;
}
/**
* @returns a string representation of the primary key values in the format "FieldName=Value"
* @example "ID=1 AND Name=John"
* @param useIsNull if true, will return "FieldName IS NULL" for any key value pair that has a null or undefined value
*/
ToString(useIsNull) {
return this.KeyValuePairs.map((keyValue) => {
if (useIsNull && (keyValue.Value === null || keyValue.Value === undefined)) {
return `${keyValue.FieldName} IS NULL`;
}
return `${keyValue.FieldName}=${keyValue.Value}`;
}).join(" AND ");
}
/**
* @returns a copy of the KeyValuePairs array but with the Value properties as type string
*/
ValuesAsString() {
return this.KeyValuePairs.map((keyValue) => {
return {
FieldName: keyValue.FieldName,
Value: keyValue.Value.toString()
};
});
}
/**
* Utility function to return a copy of the CompositeKey with the Value properties as string
* @returns a copy of the KeyValuePairs array but with the Value properties as string
*/
Copy() {
let copy = new CompositeKey();
copy.KeyValuePairs = this.ValuesAsString();
return copy;
}
/**
* @returns the KeyValuePairs as a list of strings in the format "FieldName=Value"
* @param delimiter the delimiter to use between the field name and value. Defaults to '='
* @example ["ID=1", "Name=John"]
*/
ToList(delimiter) {
return this.KeyValuePairs.map((pk) => {
return delimiter ? `${pk.FieldName}${delimiter}${pk.Value}` : `${pk.FieldName}=${pk.Value}`;
});
}
/**
* @returns the value of each key value pair in the format "Value1, Value2, Value3"
* @param delimiter - the delimiter to use between the values. Defaults to ', '
* @example "1, John"
*/
Values(delimiter) {
return this.KeyValuePairs.map((keyValue) => {
return keyValue.Value;
}).join(delimiter || ", ");
}
/**
* Utility function to compare the key primary key of this object to another sets to see if they are the same or not
* @param kvPairs the primary key values to compare against
* @returns true if the primary key values are the same, false if they are different
*/
EqualsKey(kvPairs) {
if (!kvPairs || kvPairs.length === 0) {
return false;
}
if (kvPairs.length !== this.KeyValuePairs.length) {
return false;
}
for (const [index, kvPair] of kvPairs.entries()) {
const sourcekvPair = this.KeyValuePairs[index];
if (kvPair.FieldName !== sourcekvPair.FieldName || kvPair.Value !== sourcekvPair.Value) {
return false;
}
}
return true;
}
/**
* Utility function to compare this composite key to another
* @param compositeKey the composite key to compare against
* @returns true if the primary key values are the same, false if they are different
*/
Equals(compositeKey) {
if (!compositeKey) {
return false;
}
return this.EqualsKey(compositeKey.KeyValuePairs);
}
LoadFromEntityFields(fields) {
this.KeyValuePairs = fields.map((field) => {
return {
FieldName: field.Name,
Value: field.Value
};
});
}
LoadFromEntityInfoAndRecord(entity, entityRecord) {
this.KeyValuePairs = entity.PrimaryKeys.map((pk) => {
return {
FieldName: pk.Name,
Value: entityRecord[pk.Name]
};
});
}
/**
* Loads the KeyValuePairs from a list of strings in the format "FieldName=Value"
* @param list - the list of strings to load from
* @param delimiter - the delimiter to use between the field name and value. Defaults to '='
* @example ["ID=1", "Name=John"]
*/
LoadFromList(list, delimiter) {
this.KeyValuePairs = list.map((pk) => {
let keyValue = delimiter ? pk.split(delimiter) : pk.split("=");
if (keyValue.length === 2) {
let keyValuePair = new entityInfo_1.KeyValuePair();
keyValuePair.FieldName = keyValue[0];
keyValuePair.Value = keyValue[1];
return keyValuePair;
}
return;
});
}
ToURLSegment(segment) {
return this.KeyValuePairs.map((pk) => {
return `${pk.FieldName}|${pk.Value}`;
}).join(segment || "||");
}
LoadFromURLSegment(entity, routeSegment, segment) {
if (!routeSegment.includes('|')) {
// If not, return a single element array with a default field name
this.KeyValuePairs = [{ FieldName: entity.PrimaryKey.Name, Value: routeSegment }];
}
else {
const parts = segment ? routeSegment.split(segment) : routeSegment.split('||');
const pkVals = [];
for (let p of parts) {
const kv = p.split('|');
pkVals.push({ FieldName: kv[0], Value: kv[1] });
}
this.KeyValuePairs = pkVals;
}
}
/**
* Helper method to check if the underlying key value pairs are valid or not
* i.e. if any of the key value pairs are null or undefined
* @returns true if all key value pairs are valid, false if any are null or undefined
*/
Validate() {
for (let j = 0; j < this.KeyValuePairs.length; j++) {
if (!this.KeyValuePairs[j] || !this.KeyValuePairs[j].Value) {
return { IsValid: false, ErrorMessage: 'CompositeKey.Validate: KeyValuePair cannot contain null values. FieldName: ' + this.KeyValuePairs[j]?.FieldName };
}
}
return { IsValid: true, ErrorMessage: '' };
}
class PotentialDuplicate extends compositeKey_1.CompositeKey {
}
exports.CompositeKey = CompositeKey;
class PotentialDuplicate extends CompositeKey {
}
exports.PotentialDuplicate = PotentialDuplicate;

@@ -231,9 +52,38 @@ class PotentialDuplicateRequest {

exports.PotentialDuplicateResponse = PotentialDuplicateResponse;
/**
* Save options used when saving an entity record
*/
class EntitySaveOptions {
constructor() {
/**
* If set to true, the record will be saved to the database even if nothing is detected to be "dirty" or changed since the prior load.
*/
this.IgnoreDirtyState = false;
/**
* If set to true, an AI actions associated with the entity will be skipped during the save operation
*/
this.SkipEntityAIActions = false;
/**
* If set to true, any Entity Actions associated with invocation types of Create or Update will be skipped during the save operation
*/
this.SkipEntityActions = false;
}
}
exports.EntitySaveOptions = EntitySaveOptions;
/**
* Options used when deleting an entity record
*/
class EntityDeleteOptions {
constructor() {
/**
* If set to true, an AI actions associated with the entity will be skipped during the delete operation
*/
this.SkipEntityAIActions = false;
/**
* If set to true, any Entity Actions associated with invocation types of Delete will be skipped during the delete operation
*/
this.SkipEntityActions = false;
}
}
exports.EntityDeleteOptions = EntityDeleteOptions;
class EntityRecordNameInput {

@@ -240,0 +90,0 @@ }

@@ -5,2 +5,45 @@ export declare function LogError(message: any, logToFileName?: string, ...args: any[]): void;

export declare function SetProductionStatus(isProduction: boolean): void;
export declare function FormatConsoleMessage(message: string, serverity: SeverityType): string;
export declare function FormatFileMessage(message: string, serverity: SeverityType): string;
export declare const SeverityType: {
readonly Trace: "Trace";
readonly Debug: "Debug";
readonly Info: "Info";
readonly Warning: "Warning";
readonly Critical: "Critical";
};
export type SeverityType = typeof SeverityType[keyof typeof SeverityType];
export declare const colors: {
reset: string;
bright: string;
dim: string;
underscore: string;
blink: string;
reverse: string;
hidden: string;
fg: {
black: string;
red: string;
green: string;
yellow: string;
blue: string;
magenta: string;
cyan: string;
white: string;
gray: string;
crimson: string;
};
bg: {
black: string;
red: string;
green: string;
yellow: string;
blue: string;
magenta: string;
cyan: string;
white: string;
gray: string;
crimson: string;
};
};
//# sourceMappingURL=logging.d.ts.map
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SetProductionStatus = exports.GetProductionStatus = exports.LogStatus = exports.LogError = void 0;
exports.colors = exports.SeverityType = exports.FormatFileMessage = exports.FormatConsoleMessage = exports.SetProductionStatus = exports.GetProductionStatus = exports.LogStatus = exports.LogError = void 0;
let fs;

@@ -69,2 +69,74 @@ if (runningOnNode()) {

}
function FormatConsoleMessage(message, serverity) {
switch (serverity) {
case 'Trace':
case 'Debug':
case 'Info':
return `${exports.colors.fg.white}${message}${exports.colors.reset}`;
case 'Warning':
return `${exports.colors.fg.yellow}${message}${exports.colors.reset}`;
case 'Critical':
return `${exports.colors.fg.red}${message}${exports.colors.reset}`;
default:
return message;
}
}
exports.FormatConsoleMessage = FormatConsoleMessage;
function FormatFileMessage(message, serverity) {
switch (serverity) {
case 'Trace':
return `[Trace] ${message}`;
case 'Debug':
return `[Debug] ${message}`;
case 'Info':
return `[Info] ${message}`;
case 'Warning':
return `[Warning] ${message}`;
case 'Critical':
return `[Critical] ${message}`;
default:
return message;
}
}
exports.FormatFileMessage = FormatFileMessage;
exports.SeverityType = {
Trace: 'Trace',
Debug: 'Debug',
Info: 'Info',
Warning: 'Warning',
Critical: 'Critical'
};
exports.colors = {
reset: "\x1b[0m",
bright: "\x1b[1m",
dim: "\x1b[2m",
underscore: "\x1b[4m",
blink: "\x1b[5m",
reverse: "\x1b[7m",
hidden: "\x1b[8m",
fg: {
black: "\x1b[30m",
red: "\x1b[31m",
green: "\x1b[32m",
yellow: "\x1b[33m",
blue: "\x1b[34m",
magenta: "\x1b[35m",
cyan: "\x1b[36m",
white: "\x1b[37m",
gray: "\x1b[90m",
crimson: "\x1b[38m" // Scarlet
},
bg: {
black: "\x1b[40m",
red: "\x1b[41m",
green: "\x1b[42m",
yellow: "\x1b[43m",
blue: "\x1b[44m",
magenta: "\x1b[45m",
cyan: "\x1b[46m",
white: "\x1b[47m",
gray: "\x1b[100m",
crimson: "\x1b[48m"
}
};
//# sourceMappingURL=logging.js.map

@@ -1,2 +0,2 @@

import { DatasetItemFilterType, DatasetResultType, CompositeKey, DatasetStatusResultType, EntityRecordNameInput, EntityRecordNameResult, ILocalStorageProvider, IMetadataProvider, PotentialDuplicateRequest, PotentialDuplicateResponse, ProviderConfigDataBase, ProviderType } from "./interfaces";
import { DatasetItemFilterType, DatasetResultType, DatasetStatusResultType, EntityRecordNameInput, EntityRecordNameResult, ILocalStorageProvider, IMetadataProvider, PotentialDuplicateRequest, PotentialDuplicateResponse, ProviderConfigDataBase, ProviderType } from "./interfaces";
import { EntityDependency, EntityInfo, RecordDependency, RecordMergeRequest, RecordMergeResult } from "./entityInfo";

@@ -8,2 +8,4 @@ import { ApplicationInfo } from "./applicationInfo";

import { QueryCategoryInfo, QueryFieldInfo, QueryInfo, QueryPermissionInfo } from "./queryInfo";
import { LibraryInfo } from "./libraryInfo";
import { CompositeKey } from "./compositeKey";
/**

@@ -28,2 +30,13 @@ * Class used to access a wide array of MemberJunction metadata, to instantiate derived classes of BaseEntity for record access and manipulation and more. This class uses a provider model where different providers transparently plug-in to implement the functionality needed based on where the code is running. The provider in use is generally not of any importance to users of the class and code can be written indepdenent of tier/provider.

get Entities(): EntityInfo[];
/**
* Helper method to find an entity by name in a case insensitive manner.
* @param entityName
*/
EntityByName(entityName: string): EntityInfo;
/**
* Helper method to find an entity by ID
* @param entityID
* @returns
*/
EntityByID(entityID: number): EntityInfo;
get Queries(): QueryInfo[];

@@ -40,2 +53,3 @@ get QueryFields(): QueryFieldInfo[];

get Authorizations(): AuthorizationInfo[];
get Libraries(): LibraryInfo[];
/**

@@ -54,9 +68,14 @@ * Helper function to return an Entity Name from a given Entity ID.

/**
* Helper function to return an EntityInfo from an Entity ID
* @param entityID
*/
EntityFromEntityID(entityID: number): EntityInfo | null;
/**
* Returns true if the combination of userId/entityName/KeyValuePairs has a favorite status on (meaning the user has marked the record as a "favorite" for easy access)
* @param userId
* @param entityName
* @param KeyValuePairs
* @param primaryKey
* @returns
*/
GetRecordFavoriteStatus(userId: number, entityName: string, CompositeKey: CompositeKey): Promise<boolean>;
GetRecordFavoriteStatus(userId: number, entityName: string, primaryKey: CompositeKey): Promise<boolean>;
/**

@@ -66,7 +85,7 @@ * Sets the favorite status for a given user for a specific entityName/KeyValuePairs

* @param entityName
* @param KeyValuePairs
* @param primaryKey
* @param isFavorite
* @param contextUser
*/
SetRecordFavoriteStatus(userId: number, entityName: string, CompositeKey: CompositeKey, isFavorite: boolean, contextUser?: UserInfo): Promise<void>;
SetRecordFavoriteStatus(userId: number, entityName: string, primaryKey: CompositeKey, isFavorite: boolean, contextUser?: UserInfo): Promise<void>;
/**

@@ -78,5 +97,5 @@ * Returns a list of dependencies - records that are linked to the specified Entity/Primary Key Value combination. A dependency is as defined by the relationships in the database. The MemberJunction metadata that is used

* @param entityName the name of the entity to check
* @param KeyValuePair the primary key value to check
* @param primaryKey the primary key value to check
*/
GetRecordDependencies(entityName: string, CompositeKey: CompositeKey): Promise<RecordDependency[]>;
GetRecordDependencies(entityName: string, primaryKey: CompositeKey): Promise<RecordDependency[]>;
/**

@@ -123,6 +142,6 @@ * Returns a list of record IDs that are possible duplicates of the specified record.

* @param entityName
* @param KeyValuePairs
* @param primaryKey
* @returns the name of the record
*/
GetEntityRecordName(entityName: string, compositeKey: CompositeKey): Promise<string>;
GetEntityRecordName(entityName: string, primaryKey: CompositeKey): Promise<string>;
/**

@@ -129,0 +148,0 @@ * Returns one or more record names using the same logic as GetEntityRecordName, but for multiple records at once - more efficient to use this method if you need to get multiple record names at once

@@ -5,2 +5,3 @@ "use strict";

const global_1 = require("@memberjunction/global");
const logging_1 = require("./logging");
/**

@@ -44,2 +45,17 @@ * Class used to access a wide array of MemberJunction metadata, to instantiate derived classes of BaseEntity for record access and manipulation and more. This class uses a provider model where different providers transparently plug-in to implement the functionality needed based on where the code is running. The provider in use is generally not of any importance to users of the class and code can be written indepdenent of tier/provider.

}
/**
* Helper method to find an entity by name in a case insensitive manner.
* @param entityName
*/
EntityByName(entityName) {
return this.Entities.find(e => e.Name.toLowerCase().trim() === entityName.toLowerCase().trim());
}
/**
* Helper method to find an entity by ID
* @param entityID
* @returns
*/
EntityByID(entityID) {
return this.Entities.find(e => e.ID === entityID);
}
get Queries() {

@@ -72,2 +88,5 @@ return Metadata.Provider.Queries;

}
get Libraries() {
return Metadata.Provider.Libraries;
}
/**

@@ -92,16 +111,33 @@ * Helper function to return an Entity Name from a given Entity ID.

let entity = this.Entities.find(e => e.ID == entityID);
if (entity != null)
if (entity) {
return entity.Name;
else
throw new Error(`Entity ID: ${entityID} not found`);
}
else {
(0, logging_1.LogError)(`Entity ID: ${entityID} not found`);
return null;
}
}
/**
* Helper function to return an EntityInfo from an Entity ID
* @param entityID
*/
EntityFromEntityID(entityID) {
let entity = this.Entities.find(e => e.ID == entityID);
if (entity) {
return entity;
}
else {
(0, logging_1.LogError)(`Entity ID: ${entityID} not found`);
return null;
}
}
/**
* Returns true if the combination of userId/entityName/KeyValuePairs has a favorite status on (meaning the user has marked the record as a "favorite" for easy access)
* @param userId
* @param entityName
* @param KeyValuePairs
* @param primaryKey
* @returns
*/
async GetRecordFavoriteStatus(userId, entityName, CompositeKey) {
return await Metadata.Provider.GetRecordFavoriteStatus(userId, entityName, CompositeKey);
async GetRecordFavoriteStatus(userId, entityName, primaryKey) {
return await Metadata.Provider.GetRecordFavoriteStatus(userId, entityName, primaryKey);
}

@@ -112,8 +148,8 @@ /**

* @param entityName
* @param KeyValuePairs
* @param primaryKey
* @param isFavorite
* @param contextUser
*/
async SetRecordFavoriteStatus(userId, entityName, CompositeKey, isFavorite, contextUser = null) {
await Metadata.Provider.SetRecordFavoriteStatus(userId, entityName, CompositeKey, isFavorite, contextUser);
async SetRecordFavoriteStatus(userId, entityName, primaryKey, isFavorite, contextUser = null) {
await Metadata.Provider.SetRecordFavoriteStatus(userId, entityName, primaryKey, isFavorite, contextUser);
}

@@ -126,6 +162,6 @@ /**

* @param entityName the name of the entity to check
* @param KeyValuePair the primary key value to check
* @param primaryKey the primary key value to check
*/
async GetRecordDependencies(entityName, CompositeKey) {
return await Metadata.Provider.GetRecordDependencies(entityName, CompositeKey);
async GetRecordDependencies(entityName, primaryKey) {
return await Metadata.Provider.GetRecordDependencies(entityName, primaryKey);
}

@@ -181,11 +217,11 @@ /**

* @param entityName
* @param KeyValuePairs
* @param primaryKey
* @returns the name of the record
*/
async GetEntityRecordName(entityName, compositeKey) {
let result = compositeKey.Validate();
async GetEntityRecordName(entityName, primaryKey) {
let result = primaryKey.Validate();
if (!result.IsValid) {
throw new Error(result.ErrorMessage);
}
return await Metadata.Provider.GetEntityRecordName(entityName, compositeKey);
return await Metadata.Provider.GetEntityRecordName(entityName, primaryKey);
}

@@ -192,0 +228,0 @@ /**

import { BaseEntity } from "./baseEntity";
import { EntityBehaviorTypeInfo, EntityDependency, EntityDocumentTypeInfo, EntityInfo, RecordDependency, RecordMergeRequest, RecordMergeResult } from "./entityInfo";
import { IMetadataProvider, ProviderConfigDataBase, MetadataInfo, CompositeKey, ILocalStorageProvider, DatasetResultType, DatasetStatusResultType, DatasetItemFilterType, EntityRecordNameInput, EntityRecordNameResult, ProviderType, PotentialDuplicateRequest, PotentialDuplicateResponse } from "./interfaces";
import { EntityDependency, EntityDocumentTypeInfo, EntityInfo, RecordDependency, RecordMergeRequest, RecordMergeResult } from "./entityInfo";
import { IMetadataProvider, ProviderConfigDataBase, MetadataInfo, ILocalStorageProvider, DatasetResultType, DatasetStatusResultType, DatasetItemFilterType, EntityRecordNameInput, EntityRecordNameResult, ProviderType, PotentialDuplicateRequest, PotentialDuplicateResponse } from "./interfaces";
import { ApplicationInfo } from "../generic/applicationInfo";

@@ -8,6 +8,11 @@ import { AuditLogTypeInfo, AuthorizationInfo, RoleInfo, RowLevelSecurityFilterInfo, UserInfo } from "./securityInfo";

import { QueryCategoryInfo, QueryFieldInfo, QueryInfo, QueryPermissionInfo } from "./queryInfo";
export type AllMetadata = {
import { LibraryInfo } from "./libraryInfo";
import { CompositeKey } from "./compositeKey";
/**
* AllMetadata is used to pass all metadata around in a single object for convenience and type safety.
*/
export declare class AllMetadata {
CurrentUser: UserInfo;
AllEntities: EntityInfo[];
AllApplications: ApplicationInfo[];
CurrentUser: UserInfo;
AllRoles: RoleInfo[];

@@ -22,4 +27,21 @@ AllRowLevelSecurityFilters: RowLevelSecurityFilterInfo[];

AllEntityDocumentTypes: EntityDocumentTypeInfo[];
AllEntityBehaviorTypes: EntityBehaviorTypeInfo[];
};
AllLibraries: LibraryInfo[];
static FromSimpleObject(data: any, md: IMetadataProvider): AllMetadata;
}
/**
* This is a list of all metadata classes that are used in the AllMetadata class. This is used to automatically determine the class type when deserializing the metadata and otherwise whenever we need to iterate through all of the elements.
*/
export declare const AllMetadataArrays: ({
key: string;
class: typeof ApplicationInfo;
} | {
key: string;
class: typeof AuthorizationInfo;
} | {
key: string;
class: typeof QueryPermissionInfo;
} | {
key: string;
class: typeof EntityDocumentTypeInfo;
})[];
export declare abstract class ProviderBase implements IMetadataProvider {

@@ -29,15 +51,3 @@ private _ConfigData;

private _latestRemoteMetadataTimestamps;
private _entities;
private _applications;
private _currentUser;
private _roles;
private _rowLevelSecurityFilters;
private _auditLogTypes;
private _authorizations;
private _queries;
private _queryCategories;
private _queryFields;
private _queryPermissions;
private _entityBehaviorTypes;
private _entityDocumentTypes;
private _localMetadata;
private _refresh;

@@ -57,3 +67,3 @@ /******** ABSTRACT SECTION ****************************************************************** */

protected abstract GetCurrentUser(): Promise<UserInfo>;
protected PostProcessEntityMetadata(entities: any[], fields: any[], fieldValues: any[], permissions: any[], relationships: any[], behaviors: any[], settings: any[]): any[];
protected PostProcessEntityMetadata(entities: any[], fields: any[], fieldValues: any[], permissions: any[], relationships: any[], settings: any[]): any[];
get ConfigData(): ProviderConfigDataBase;

@@ -71,2 +81,3 @@ get Entities(): EntityInfo[];

get QueryPermissions(): QueryPermissionInfo[];
get Libraries(): LibraryInfo[];
Refresh(): Promise<boolean>;

@@ -183,15 +194,3 @@ IsRefreshNeeded(): Promise<boolean>;

private static localStorageTimestampsKey;
private static localStorageEntitiesKey;
private static localStorageApplicationsKey;
private static localStorageCurrentUserKey;
private static localStorageRolesKey;
private static localStorageRowLevelSecurityFiltersKey;
private static localStorageAuditLogTypesKey;
private static localStorageAuthorizationsKey;
private static localStorageQueriesKey;
private static localStorageQueryCategoriesKey;
private static localStorageQueryFieldsKey;
private static localStorageQueryPermissionsKey;
private static localStorageEntityBehaviorTypesKey;
private static localStorageEntityDocumentTypesKey;
private static localStorageAllMetadataKey;
private static localStorageKeys;

@@ -198,0 +197,0 @@ SaveLocalMetadataToStorage(): Promise<void>;

"use strict";
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ProviderBase = void 0;
exports.ProviderBase = exports.AllMetadataArrays = exports.AllMetadata = void 0;
const baseEntity_1 = require("./baseEntity");

@@ -12,16 +12,62 @@ const entityInfo_1 = require("./entityInfo");

const queryInfo_1 = require("./queryInfo");
const libraryInfo_1 = require("./libraryInfo");
/**
* AllMetadata is used to pass all metadata around in a single object for convenience and type safety.
*/
class AllMetadata {
constructor() {
this.CurrentUser = null;
// Arrays of Metadata below
this.AllEntities = [];
this.AllApplications = [];
this.AllRoles = [];
this.AllRowLevelSecurityFilters = [];
this.AllAuditLogTypes = [];
this.AllAuthorizations = [];
this.AllQueryCategories = [];
this.AllQueries = [];
this.AllQueryFields = [];
this.AllQueryPermissions = [];
this.AllEntityDocumentTypes = [];
this.AllLibraries = [];
}
// Create a new instance of AllMetadata from a simple object
static FromSimpleObject(data, md) {
try {
const newObject = new AllMetadata();
newObject.CurrentUser = data.CurrentUser ? new securityInfo_1.UserInfo(md, data.CurrentUser) : null;
// we now have to loop through the AllMetadataArray and use that info to build the metadata object with proper strongly typed object instances
for (let m of exports.AllMetadataArrays) {
if (data.hasOwnProperty(m.key)) {
newObject[m.key] = data[m.key].map((d) => new m.class(d, md));
}
}
return newObject;
}
catch (e) {
(0, logging_1.LogError)(e);
}
}
}
exports.AllMetadata = AllMetadata;
/**
* This is a list of all metadata classes that are used in the AllMetadata class. This is used to automatically determine the class type when deserializing the metadata and otherwise whenever we need to iterate through all of the elements.
*/
exports.AllMetadataArrays = [
{ key: 'AllEntities', class: entityInfo_1.EntityInfo },
{ key: 'AllApplications', class: applicationInfo_1.ApplicationInfo },
{ key: 'AllRoles', class: securityInfo_1.RoleInfo },
{ key: 'AllRowLevelSecurityFilters', class: securityInfo_1.RowLevelSecurityFilterInfo },
{ key: 'AllAuditLogTypes', class: securityInfo_1.AuditLogTypeInfo },
{ key: 'AllAuthorizations', class: securityInfo_1.AuthorizationInfo },
{ key: 'AllQueryCategories', class: queryInfo_1.QueryCategoryInfo },
{ key: 'AllQueries', class: queryInfo_1.QueryInfo },
{ key: 'AllQueryFields', class: queryInfo_1.QueryFieldInfo },
{ key: 'AllQueryPermissions', class: queryInfo_1.QueryPermissionInfo },
{ key: 'AllEntityDocumentTypes', class: entityInfo_1.EntityDocumentTypeInfo },
{ key: 'AllLibraries', class: libraryInfo_1.LibraryInfo }
];
class ProviderBase {
constructor() {
this._entities = [];
this._applications = [];
this._roles = [];
this._rowLevelSecurityFilters = [];
this._auditLogTypes = [];
this._authorizations = [];
this._queries = [];
this._queryCategories = [];
this._queryFields = [];
this._queryPermissions = [];
this._entityBehaviorTypes = [];
this._entityDocumentTypes = [];
this._localMetadata = new AllMetadata();
this._refresh = false;

@@ -32,6 +78,3 @@ }

this._ConfigData = data;
this._entities = []; // make sure to clear the array first - we could get this from a hard refresh
this._applications = []; // make sure to clear the array first - we could get this from a hard refresh
this._queries = []; // make sure to clear the array first - we could get this from a hard refresh
this._queryCategories = []; // make sure to clear the array first - we could get this from a hard refresh
this._localMetadata = new AllMetadata(); // start with fresh metadata
if (this._refresh || await this.IsRefreshNeeded()) {

@@ -49,3 +92,3 @@ // either a hard refresh flag was set within Refresh(), or LocalMetadata is Obsolete

this._latestLocalMetadataTimestamps = this._latestRemoteMetadataTimestamps; // update this since we just used server to get all the stuff
this.SaveLocalMetadataToStorage();
await this.SaveLocalMetadataToStorage();
}

@@ -90,37 +133,37 @@ }

const d = await this.GetDatasetByName(_a._mjMetadataDatasetName, f.length > 0 ? f : null);
//const end1 = new Date().getTime();
//LogStatus(`GetAllMetadata - GetDatasetByName took ${end1 - start1}ms`)
//const start2 = new Date().getTime();
const u = await this.GetCurrentUser();
//const end2 = new Date().getTime();
//LogStatus(`GetAllMetadata - GetCurrentUser took ${end2 - start2}ms`)
if (d && d.Success) {
// got the results, let's build our response in the format we need
const allMetadata = {};
const simpleMetadata = {};
for (let r of d.Results) {
allMetadata[r.Code] = r.Results;
simpleMetadata[r.Code] = r.Results;
}
// update the entities to include the fields, permissions and relationships
allMetadata.AllEntities = this.PostProcessEntityMetadata(allMetadata.Entities, allMetadata.EntityFields, allMetadata.EntityFieldValues, allMetadata.EntityPermissions, allMetadata.EntityRelationships, allMetadata.EntityBehaviors, allMetadata.EntitySettings);
// update the applications to include applicationentities/ApplicationSettings
allMetadata.AllApplications = allMetadata.Applications.map((a) => {
a.ApplicationEntities = allMetadata.ApplicationEntities.filter((ae) => ae.ApplicationName.trim().toLowerCase() === a.Name.trim().toLowerCase());
a.ApplicationSettings = allMetadata.ApplicationSettings.filter((as) => as.ApplicationName.trim().toLowerCase() === a.Name.trim().toLowerCase());
return new applicationInfo_1.ApplicationInfo(this, a);
// Post Process Entities because there's some special handling of the sub-objects
simpleMetadata.AllEntities = this.PostProcessEntityMetadata(simpleMetadata.Entities, simpleMetadata.EntityFields, simpleMetadata.EntityFieldValues, simpleMetadata.EntityPermissions, simpleMetadata.EntityRelationships, simpleMetadata.EntitySettings);
// Post Process the Applications, because we want to handle the sub-objects properly.
simpleMetadata.AllApplications = simpleMetadata.Applications.map((a) => {
a.ApplicationEntities = simpleMetadata.ApplicationEntities.filter((ae) => ae.ApplicationName.trim().toLowerCase() === a.Name.trim().toLowerCase());
a.ApplicationSettings = simpleMetadata.ApplicationSettings.filter((as) => as.ApplicationName.trim().toLowerCase() === a.Name.trim().toLowerCase());
return new applicationInfo_1.ApplicationInfo(a, this);
});
return {
AllEntities: allMetadata.AllEntities,
AllApplications: allMetadata.AllApplications,
AllRoles: allMetadata.Roles.map((r) => new securityInfo_1.RoleInfo(r)),
CurrentUser: u,
AllRowLevelSecurityFilters: allMetadata.RowLevelSecurityFilters.map((r) => new securityInfo_1.RowLevelSecurityFilterInfo(r)),
AllAuditLogTypes: allMetadata.AuditLogTypes.map((a) => new securityInfo_1.AuditLogTypeInfo(a)),
AllAuthorizations: allMetadata.Authorizations.map((a) => new securityInfo_1.AuthorizationInfo(a)),
AllQueries: allMetadata.Queries ? allMetadata.Queries.map((q) => new queryInfo_1.QueryInfo(q)) : [],
AllQueryFields: allMetadata.QueryFields ? allMetadata.QueryFields.map((qf) => new queryInfo_1.QueryFieldInfo(qf)) : [],
AllQueryPermissions: allMetadata.QueryPermissions ? allMetadata.QueryPermissions.map((qp) => new queryInfo_1.QueryPermissionInfo(qp)) : [],
AllQueryCategories: allMetadata.QueryCategories ? allMetadata.QueryCategories.map((qc) => new queryInfo_1.QueryCategoryInfo(qc)) : [],
AllEntityBehaviorTypes: allMetadata.EntityBehaviorTypes ? allMetadata.EntityBehaviorTypes.map((eb) => new entityInfo_1.EntityBehaviorTypeInfo(eb)) : [],
AllEntityDocumentTypes: allMetadata.EntityDocumentTypes ? allMetadata.EntityDocumentTypes.map((ed) => new entityInfo_1.EntityDocumentTypeInfo(ed)) : []
};
// now we need to construct our return type. The way the return type works, which is an instance of AllMetadata, we have to
// construst each item so it contains an array of the correct type. This is because the AllMetadata class has an array of each type of metadata
// rather than just plain JavaScript objects that we have in the allMetadata object.
// build the base return type
const returnMetadata = new AllMetadata();
returnMetadata.CurrentUser = await this.GetCurrentUser(); // set the current user
// now iterate through the AllMetadataMapping array and construct the return type
for (let m of exports.AllMetadataArrays) {
let simpleKey = m.key;
if (!simpleMetadata.hasOwnProperty(simpleKey)) {
simpleKey = simpleKey.substring(3); // remove the All prefix
}
if (simpleMetadata.hasOwnProperty(simpleKey)) {
// at this point, only do this particular property if we have a match, it is either prefixed with All or not
// for example in our strongly typed AllMetadata class we have AllQueryCategories, but in the simple allMetadata object we have QueryCategories
// so we need to check for both which is what the above is doing.
// Build the array of the correct type and initialize with the simple object
returnMetadata[m.key] = simpleMetadata[simpleKey].map((d) => new m.class(d, this));
}
}
return returnMetadata;
}

@@ -135,3 +178,3 @@ else {

}
PostProcessEntityMetadata(entities, fields, fieldValues, permissions, relationships, behaviors, settings) {
PostProcessEntityMetadata(entities, fields, fieldValues, permissions, relationships, settings) {
const result = [];

@@ -147,3 +190,2 @@ if (fieldValues && fieldValues.length > 0)

e.EntityRelationships = relationships.filter(r => r.EntityID === e.ID);
e.EntityBehaviors = behaviors.filter(b => b.EntityID === e.ID);
e.EntitySettings = settings.filter(s => s.EntityID === e.ID);

@@ -158,34 +200,37 @@ result.push(new entityInfo_1.EntityInfo(e));

get Entities() {
return this._entities;
return this._localMetadata.AllEntities;
}
get Applications() {
return this._applications;
return this._localMetadata.AllApplications;
}
get CurrentUser() {
return this._currentUser;
return this._localMetadata.CurrentUser;
}
get Roles() {
return this._roles;
return this._localMetadata.AllRoles;
}
get RowLevelSecurityFilters() {
return this._rowLevelSecurityFilters;
return this._localMetadata.AllRowLevelSecurityFilters;
}
get AuditLogTypes() {
return this._auditLogTypes;
return this._localMetadata.AllAuditLogTypes;
}
get Authorizations() {
return this._authorizations;
return this._localMetadata.AllAuthorizations;
}
get Queries() {
return this._queries;
return this._localMetadata.AllQueries;
}
get QueryCategories() {
return this._queryCategories;
return this._localMetadata.AllQueryCategories;
}
get QueryFields() {
return this._queryFields;
return this._localMetadata.AllQueryFields;
}
get QueryPermissions() {
return this._queryPermissions;
return this._localMetadata.AllQueryPermissions;
}
get Libraries() {
return this._localMetadata.AllLibraries;
}
async Refresh() {

@@ -223,4 +268,3 @@ // do nothing here, but set a _refresh flag for next time things are requested

const newObject = global_1.MJGlobal.Instance.ClassFactory.CreateInstance(baseEntity_1.BaseEntity, entityName, entity);
if (contextUser)
newObject.ContextCurrentUser = contextUser;
await newObject.Config(contextUser);
return newObject;

@@ -481,79 +525,3 @@ }

UpdateLocalMetadata(res) {
if (res.AllEntities) {
this._entities = [];
for (let i = 0; i < res.AllEntities.length; i++) {
this._entities.push(new entityInfo_1.EntityInfo(res.AllEntities[i]));
}
}
if (res.AllApplications) {
this._applications = [];
for (let i = 0; i < res.AllApplications.length; i++) {
const a = new applicationInfo_1.ApplicationInfo(this, res.AllApplications[i]);
this._applications.push(a);
}
}
if (res.AllRoles) {
this._roles = [];
for (let i = 0; i < res.AllRoles.length; i++) {
const r = new securityInfo_1.RoleInfo(res.AllRoles[i]);
this._roles.push(r);
}
}
if (res.AllRowLevelSecurityFilters) {
this._rowLevelSecurityFilters = [];
for (let i = 0; i < res.AllRowLevelSecurityFilters.length; i++) {
const rls = new securityInfo_1.RowLevelSecurityFilterInfo(res.AllRowLevelSecurityFilters[i]);
this._rowLevelSecurityFilters.push(rls);
}
}
if (res.AllAuditLogTypes) {
this._auditLogTypes = [];
for (let i = 0; i < res.AllAuditLogTypes.length; i++) {
const alt = new securityInfo_1.AuditLogTypeInfo(res.AllAuditLogTypes[i]);
this._auditLogTypes.push(alt);
}
}
if (res.AllAuthorizations) {
this._authorizations = [];
for (let i = 0; i < res.AllAuthorizations.length; i++) {
const ai = new securityInfo_1.AuthorizationInfo(this, res.AllAuthorizations[i]);
this._authorizations.push(ai);
}
}
if (res.AllQueries) {
this._queries = [];
for (let i = 0; i < res.AllQueries.length; i++) {
const q = new queryInfo_1.QueryInfo(res.AllQueries[i]);
this._queries.push(q);
}
}
if (res.AllQueryCategories) {
this._queryCategories = [];
for (let i = 0; i < res.AllQueryCategories.length; i++) {
const qc = new queryInfo_1.QueryCategoryInfo(res.AllQueryCategories[i]);
this._queryCategories.push(qc);
}
}
if (res.AllQueryFields) {
this._queryFields = [];
for (let i = 0; i < res.AllQueryFields.length; i++) {
const qf = new queryInfo_1.QueryFieldInfo(res.AllQueryFields[i]);
this._queryFields.push(qf);
}
}
if (res.AllQueryPermissions) {
this._queryPermissions = [];
for (let i = 0; i < res.AllQueryPermissions.length; i++) {
const qp = new queryInfo_1.QueryPermissionInfo(res.AllQueryPermissions[i]);
this._queryPermissions.push(qp);
}
}
if (res.AllEntityBehaviorTypes) {
this._entityBehaviorTypes = res.AllEntityBehaviorTypes.map(ebt => new entityInfo_1.EntityBehaviorTypeInfo(ebt));
}
if (res.AllEntityDocumentTypes) {
this._entityDocumentTypes = res.AllEntityDocumentTypes.map(edt => new entityInfo_1.EntityDocumentTypeInfo(edt));
}
if (res.CurrentUser)
this._currentUser = new securityInfo_1.UserInfo(this, res.CurrentUser);
this._localMetadata = res;
}

@@ -566,30 +534,8 @@ async LoadLocalMetadataFromStorage() {

this._latestLocalMetadataTimestamps = JSON.parse(await ls.getItem(_a.localStorageTimestampsKey));
const e = JSON.parse(await ls.getItem(_a.localStorageEntitiesKey));
const a = JSON.parse(await ls.getItem(_a.localStorageApplicationsKey));
const cu = JSON.parse(await ls.getItem(_a.localStorageCurrentUserKey));
const r = JSON.parse(await ls.getItem(_a.localStorageRolesKey));
const rls = JSON.parse(await ls.getItem(_a.localStorageRowLevelSecurityFiltersKey));
const alt = JSON.parse(await ls.getItem(_a.localStorageAuditLogTypesKey));
const ai = JSON.parse(await ls.getItem(_a.localStorageAuthorizationsKey));
const queries = JSON.parse(await ls.getItem(_a.localStorageQueriesKey));
const qcs = JSON.parse(await ls.getItem(_a.localStorageQueryCategoriesKey));
const qf = JSON.parse(await ls.getItem(_a.localStorageQueryFieldsKey));
const qp = JSON.parse(await ls.getItem(_a.localStorageQueryPermissionsKey));
const ebt = JSON.parse(await ls.getItem(_a.localStorageEntityBehaviorTypesKey));
const edt = JSON.parse(await ls.getItem(_a.localStorageEntityDocumentTypesKey));
this.UpdateLocalMetadata({
AllEntities: e,
AllApplications: a,
CurrentUser: cu,
AllRoles: r,
AllRowLevelSecurityFilters: rls,
AllAuditLogTypes: alt,
AllAuthorizations: ai,
AllQueries: queries,
AllQueryCategories: qcs,
AllQueryFields: qf,
AllQueryPermissions: qp,
AllEntityBehaviorTypes: ebt,
AllEntityDocumentTypes: edt
});
const temp = JSON.parse(await ls.getItem(_a.localStorageAllMetadataKey)); // we now have a simple object for all the metadata
if (temp) {
// we have local metadata
const metadata = AllMetadata.FromSimpleObject(temp, this); // create a new object to start this up
this.UpdateLocalMetadata(metadata);
}
}

@@ -607,15 +553,4 @@ }

await ls.setItem(_a.localStorageTimestampsKey, JSON.stringify(this._latestLocalMetadataTimestamps));
await ls.setItem(_a.localStorageEntitiesKey, JSON.stringify(this._entities));
await ls.setItem(_a.localStorageApplicationsKey, JSON.stringify(this._applications));
await ls.setItem(_a.localStorageCurrentUserKey, JSON.stringify(this._currentUser));
await ls.setItem(_a.localStorageRolesKey, JSON.stringify(this._roles));
await ls.setItem(_a.localStorageRowLevelSecurityFiltersKey, JSON.stringify(this._rowLevelSecurityFilters));
await ls.setItem(_a.localStorageAuditLogTypesKey, JSON.stringify(this._auditLogTypes));
await ls.setItem(_a.localStorageAuthorizationsKey, JSON.stringify(this._authorizations));
await ls.setItem(_a.localStorageQueriesKey, JSON.stringify(this._queries));
await ls.setItem(_a.localStorageQueryCategoriesKey, JSON.stringify(this._queryCategories));
await ls.setItem(_a.localStorageQueryFieldsKey, JSON.stringify(this._queryFields));
await ls.setItem(_a.localStorageQueryPermissionsKey, JSON.stringify(this._queryPermissions));
await ls.setItem(_a.localStorageEntityBehaviorTypesKey, JSON.stringify(this._entityBehaviorTypes));
await ls.setItem(_a.localStorageEntityDocumentTypesKey, JSON.stringify(this._entityDocumentTypes));
// now persist the AllMetadata object
await ls.setItem(_a.localStorageAllMetadataKey, JSON.stringify(this._localMetadata));
}

@@ -646,31 +581,7 @@ }

ProviderBase.localStorageTimestampsKey = _a.localStorageRootKey + '_Timestamps';
ProviderBase.localStorageEntitiesKey = _a.localStorageRootKey + '_Entities';
ProviderBase.localStorageApplicationsKey = _a.localStorageRootKey + '_Applications';
ProviderBase.localStorageCurrentUserKey = _a.localStorageRootKey + '_CurrentUser';
ProviderBase.localStorageRolesKey = _a.localStorageRootKey + '_Roles';
ProviderBase.localStorageRowLevelSecurityFiltersKey = _a.localStorageRootKey + '_RowLevelSecurityFilters';
ProviderBase.localStorageAuditLogTypesKey = _a.localStorageRootKey + '_AuditLogTypes';
ProviderBase.localStorageAuthorizationsKey = _a.localStorageRootKey + '_Authorizations';
ProviderBase.localStorageQueriesKey = _a.localStorageRootKey + '_Queries';
ProviderBase.localStorageQueryCategoriesKey = _a.localStorageRootKey + '_QueryCategories';
ProviderBase.localStorageQueryFieldsKey = _a.localStorageRootKey + '_QueryFields';
ProviderBase.localStorageQueryPermissionsKey = _a.localStorageRootKey + '_QueryPermissions';
ProviderBase.localStorageEntityBehaviorTypesKey = _a.localStorageRootKey + '_EntityBehaviorTypes';
ProviderBase.localStorageEntityDocumentTypesKey = _a.localStorageRootKey + '_EntityDocumentTypes';
ProviderBase.localStorageAllMetadataKey = _a.localStorageRootKey + '_AllMetadata';
ProviderBase.localStorageKeys = [
_a.localStorageTimestampsKey,
_a.localStorageEntitiesKey,
_a.localStorageApplicationsKey,
_a.localStorageCurrentUserKey,
_a.localStorageRolesKey,
_a.localStorageRowLevelSecurityFiltersKey,
_a.localStorageAuditLogTypesKey,
_a.localStorageAuthorizationsKey,
_a.localStorageQueriesKey,
_a.localStorageQueryCategoriesKey,
_a.localStorageQueryFieldsKey,
_a.localStorageQueryPermissionsKey,
_a.localStorageEntityBehaviorTypesKey,
_a.localStorageEntityDocumentTypesKey
_a.localStorageAllMetadataKey,
];
//# sourceMappingURL=providerBase.js.map

@@ -0,1 +1,5 @@

import { BaseEntity } from "./baseEntity";
/**
* Internal class used by TransactionGroupBase and sub-classes to manage individual transactions
*/
export declare class TransactionItem {

@@ -6,2 +10,3 @@ private _instruction;

private _extraData;
private _baseEntity;
get Vars(): any;

@@ -11,17 +16,49 @@ get ExtraData(): any;

get CallBack(): Function;
constructor(instruction: string, vars: any, extraData: any, callBack: Function);
get BaseEntity(): BaseEntity;
constructor(baseEntity: BaseEntity, instruction: string, vars: any, extraData: any, callBack: Function);
}
/**
* Tracks the individual transactions within a transaction group and their commit results
*/
export declare class TransactionResult {
Transaction: TransactionItem;
Result: any;
/**
* True if the transaction was successful, false if it failed. If it failed, check the TransactionItem's BaseEntity.ResultHistory and BaseEntity.LatestResult
*/
Success: boolean;
constructor(transaction: TransactionItem, result: any, success: boolean);
}
/**
* TransactionGroup is a class that handles the bundling of multiple transactions into a single request. The provider handles
* the implementation details. If a transaction group is provided to the baseEntity object before either Save() or Delete() is called
* instead of just immediately executing its SQL or GQL, it provides the instructions to the TransactionGroup object instead.
*
* Then, whenever the TransactionGroup object instance has its Submit() method called, all of the requests will be bundled into a single
* request and handled. For example in the case of the GraphQLDataProvider, we queue up all of the GQL statements for all of the
* mutations and send them across as a single GraphQL request. The GraphQL server handles the actual DB transaction stuff.
*
* TransactionGroup will call a callback function, if provided, after the transaction has either completed succesfully or failed.
* If it is succesful, for Save() method calls, the latest data for that record will be provided back.
* For Delete() method calls, the callback will be called with no data.
*
* This class is the base class for managing a group of transactions and submitting it to the provider so it can be handled as an ATOMic transaction
*/
export declare abstract class TransactionGroupBase {
private _pendingTransactions;
protected PendingTransactions(): TransactionItem[];
/**
* This is used by the BaseEntity/Provider objects to manage transactions on your behalf. Do not directly interact with this method. Instead use the TransactionGroup property on
* the @BaseEntity class to make an entity object part of a transaction group.
* @param transaction
*/
AddTransaction(transaction: TransactionItem): void;
protected abstract HandleSubmit(item: TransactionItem[]): Promise<TransactionResult[]>;
/**
* Submits the transaction group to the provider for handling. The provider will handle the actual transaction and call the callback functions
* @returns true if the transaction was successful, false if it failed. If the method fails, check each of the individual BaseEntity objects within
* the TransactionGroup for their result histories using BaseEntity.ResultHistory and BaseEntity.LatestResult
*/
Submit(): Promise<boolean>;
}
//# sourceMappingURL=transactionGroup.d.ts.map
"use strict";
/* TransactionGroup is a class that handles the bundling of multiple transactions into a single request. The provider handles
the implementation details. If a transaction group is provided to the baseEntity object before either Save() or Delete() is called
instead of just immediately executing its SQL or GQL, it provides the instructions to the TransactionGroup object instead.
Then, whenever the TransactionGroup object instance has its Submit() method called, all of the requests will be bundled into a single
request and handled. For example in the case of the GraphQLDataProvider, we queue up all of the GQL statements for all of the
mutations and send them across as a single GraphQL request. The GraphQL server handles the actual DB transaction stuff.
TransactionGroup will call a callback function, if provided, after the transaction has either completed succesfully or failed.
If it is succesful, for Save() method calls, the latest data for that record will be provided back.
For Delete() method calls, the callback will be called with no data.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.TransactionGroupBase = exports.TransactionResult = exports.TransactionItem = void 0;
/**
* Internal class used by TransactionGroupBase and sub-classes to manage individual transactions
*/
class TransactionItem {

@@ -30,3 +20,7 @@ get Vars() {

}
constructor(instruction, vars, extraData, callBack) {
get BaseEntity() {
return this._baseEntity;
}
constructor(baseEntity, instruction, vars, extraData, callBack) {
this._baseEntity = baseEntity;
this._instruction = instruction;

@@ -39,2 +33,5 @@ this._vars = vars;

exports.TransactionItem = TransactionItem;
/**
* Tracks the individual transactions within a transaction group and their commit results
*/
class TransactionResult {

@@ -48,2 +45,17 @@ constructor(transaction, result, success) {

exports.TransactionResult = TransactionResult;
/**
* TransactionGroup is a class that handles the bundling of multiple transactions into a single request. The provider handles
* the implementation details. If a transaction group is provided to the baseEntity object before either Save() or Delete() is called
* instead of just immediately executing its SQL or GQL, it provides the instructions to the TransactionGroup object instead.
*
* Then, whenever the TransactionGroup object instance has its Submit() method called, all of the requests will be bundled into a single
* request and handled. For example in the case of the GraphQLDataProvider, we queue up all of the GQL statements for all of the
* mutations and send them across as a single GraphQL request. The GraphQL server handles the actual DB transaction stuff.
*
* TransactionGroup will call a callback function, if provided, after the transaction has either completed succesfully or failed.
* If it is succesful, for Save() method calls, the latest data for that record will be provided back.
* For Delete() method calls, the callback will be called with no data.
*
* This class is the base class for managing a group of transactions and submitting it to the provider so it can be handled as an ATOMic transaction
*/
class TransactionGroupBase {

@@ -56,5 +68,15 @@ constructor() {

}
/**
* This is used by the BaseEntity/Provider objects to manage transactions on your behalf. Do not directly interact with this method. Instead use the TransactionGroup property on
* the @BaseEntity class to make an entity object part of a transaction group.
* @param transaction
*/
AddTransaction(transaction) {
this._pendingTransactions.push(transaction);
}
/**
* Submits the transaction group to the provider for handling. The provider will handle the actual transaction and call the callback functions
* @returns true if the transaction was successful, false if it failed. If the method fails, check each of the individual BaseEntity objects within
* the TransactionGroup for their result histories using BaseEntity.ResultHistory and BaseEntity.LatestResult
*/
async Submit() {

@@ -69,2 +91,4 @@ try {

}
// now, see if there are any false values for results[x].Success, if so, we have to return false
return results.every((r) => r.Success);
}

@@ -71,0 +95,0 @@ return true;

@@ -17,2 +17,6 @@ export declare function TypeScriptTypeFromSQLType(sqlType: string): string;

export declare function StripStopWords(inputString: string): string;
/**
* Returns a system-wide standard CodeName which is a programmatically acceptable identifier for a class, variable, etc using a standard replacement strategy for characters that are not acceptable in that context from a regular name
*/
export declare function CodeNameFromString(input: string): string;
//# sourceMappingURL=util.d.ts.map
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.StripStopWords = exports.CommonStopWords = exports.SQLMaxLength = exports.SQLFullType = exports.FormatValue = exports.TypeScriptTypeFromSQLType = void 0;
exports.CodeNameFromString = exports.StripStopWords = exports.CommonStopWords = exports.SQLMaxLength = exports.SQLFullType = exports.FormatValue = exports.TypeScriptTypeFromSQLType = void 0;
const logging_1 = require("./logging");

@@ -151,2 +151,16 @@ function TypeScriptTypeFromSQLType(sqlType) {

exports.StripStopWords = StripStopWords;
/**
* Returns a system-wide standard CodeName which is a programmatically acceptable identifier for a class, variable, etc using a standard replacement strategy for characters that are not acceptable in that context from a regular name
*/
function CodeNameFromString(input) {
// the code below replaces characters invalid for SQL or TypeScript identifiers with _ and stashes the result in a private variable so we only do this once
// Replace all invalid characters with _
let codeName = input.replace(/[^a-zA-Z0-9_]/g, "_");
// Prepend an underscore if the first character is a number
if (/^[0-9]/.test(codeName)) {
codeName = "_" + codeName;
}
return codeName;
}
exports.CodeNameFromString = CodeNameFromString;
//# sourceMappingURL=util.js.map
export * from "./generic/metadata";
export * from "./generic/baseInfo";
export * from "./generic/baseEngine";
export * from "./views/runView";

@@ -16,3 +17,4 @@ export * from "./generic/runReport";

export * from "./generic/queryInfo";
export * from "./generic/compositeKey";
export declare function SetProvider(provider: any): void;
//# sourceMappingURL=index.d.ts.map

@@ -24,2 +24,3 @@ "use strict";

__exportStar(require("./generic/baseInfo"), exports);
__exportStar(require("./generic/baseEngine"), exports);
__exportStar(require("./views/runView"), exports);

@@ -38,2 +39,3 @@ __exportStar(require("./generic/runReport"), exports);

__exportStar(require("./generic/queryInfo"), exports);
__exportStar(require("./generic/compositeKey"), exports);
function SetProvider(provider) {

@@ -40,0 +42,0 @@ metadata_1.Metadata.Provider = provider;

@@ -112,7 +112,13 @@ import { IRunViewProvider, RunViewResult } from '../generic/interfaces';

*/
RunView(params: RunViewParams, contextUser?: UserInfo): Promise<RunViewResult>;
RunView<T = any>(params: RunViewParams, contextUser?: UserInfo): Promise<RunViewResult<T>>;
private static _globalProviderKey;
static get Provider(): IRunViewProvider;
static set Provider(value: IRunViewProvider);
/**
* Utility method that calculates the entity name for a given RunViewParams object by looking at the EntityName property as well as the ViewID/ViewName/ViewEntity properties as needed.
* @param params
* @returns
*/
static GetEntityNameFromRunViewParams(params: RunViewParams): Promise<string>;
}
//# sourceMappingURL=runView.d.ts.map

@@ -38,3 +38,3 @@ "use strict";

for (const item of result.Results) {
const entity = await md.GetEntityObject(params.EntityName);
const entity = await md.GetEntityObject(params.EntityName, contextUser);
entity.LoadFromData(item);

@@ -61,2 +61,32 @@ newItems.push(entity);

}
/**
* Utility method that calculates the entity name for a given RunViewParams object by looking at the EntityName property as well as the ViewID/ViewName/ViewEntity properties as needed.
* @param params
* @returns
*/
static async GetEntityNameFromRunViewParams(params) {
if (params.EntityName)
return params.EntityName;
else if (params.ViewEntity) {
const entityID = params.ViewEntity.Get('EntityID'); // using weak typing because this is MJCore and we don't want to use the sub-classes from core-entities as that would create a circular dependency
const md = new metadata_1.Metadata();
const entity = md.Entities.find(e => e.ID === entityID);
if (entity)
return entity.Name;
}
else if (params.ViewID || params.ViewName) {
// we don't have a view entity loaded, so load it up now
const rv = new RunView();
const result = await rv.RunView({
EntityName: "User Views",
ExtraFilter: params.ViewID ? `ID = ${params.ViewID}` : `Name = '${params.ViewName}'`,
ResultType: 'entity_object'
});
if (result && result.Success && result.Results.length > 0) {
return result.Results[0].Entity; // virtual field in the User Views entity called Entity
}
}
else
return null;
}
}

@@ -63,0 +93,0 @@ exports.RunView = RunView;

{
"name": "@memberjunction/core",
"version": "1.4.0",
"version": "1.4.1",
"description": "MemberJunction: Core Library including Metadata, Application, Entity Retrieval and Manipulation, and Utilities",

@@ -22,4 +22,5 @@ "main": "dist/index.js",

"dependencies": {
"@memberjunction/global": "~1.4.0"
"@memberjunction/global": "~1.4.1",
"rxjs": "^7.8.1"
}
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc