@overture-stack/lyric
Version:
Data Submission system
251 lines (250 loc) • 15.9 kB
TypeScript
import { type DataRecord, Dictionary as SchemasDictionary, DictionaryValidationError, Schema, TestResult } from '@overture-stack/lectern-client';
import { SubmissionData, type SubmissionDeleteData, type SubmissionErrors, type SubmissionInsertData, type SubmissionUpdateData, type SubmittedData } from '@overture-stack/lyric-data-model/models';
import type { SchemaChildNode } from './dictionarySchemaRelations.js';
import type { FilenameEntityPair } from './schemas.js';
import { type BatchError, type DataRecordReference, type EditSubmittedDataReference, type FileSchemaMap as FileSchemaMap, type NewSubmittedDataReference, type SubmissionActionType, type SubmissionDataDetailsRepositoryRecord, type SubmissionDataSummaryRepositoryRecord, type SubmissionDetailsResponse, type SubmissionStatus, type SubmissionSummary, SubmittedDataReference } from './types.js';
export declare const inProcessSubmissionStatus: readonly ["VALIDATING", "COMMITTING"];
export type InProcessSubmissionStatus = typeof inProcessSubmissionStatus;
export declare const openSubmissionStatus: readonly ["OPEN", "VALID", "INVALID"];
export type OpenSubmissionStatus = typeof openSubmissionStatus;
/** Determines if a Submission status is considered active based on its status
* @param {SubmissionStatus} status Status of a Submission
* @returns {boolean}
*/
export declare const isSubmissionActive: (status: SubmissionStatus) => status is OpenSubmissionStatus[number];
/**
* Checks if each file contains all required fields defined by its schema
* @param {FileSchemaMap} entityFileMap Files mapped to their resolved entity name and schema
* @returns a list of valid files and a list of errors
*/
export declare const checkEntityFieldNames: (entityFileMap: FileSchemaMap) => Promise<{
checkedEntities: FileSchemaMap;
fieldNameErrors: BatchError[];
}>;
/**
* For each file, determine the schema that will be used to validate it, or create an error record
* describing why it cannot be mapped to a Schema.
* @param {Express.Multer.File[]} files An array of files
* @param {Schema[]} schemas Schemas in the dictionary
* @param {FilenameEntityPair[]} fileEntityMap Optional mapping of filenames to entity names
* @returns A list of valid files mapped by schema/entity names
*/
export declare const resolveFileEntities: (files: Express.Multer.File[], schemas: Schema[], fileEntityMap?: FilenameEntityPair[]) => Promise<{
validFileEntity: FileSchemaMap;
batchErrors: BatchError[];
}>;
/**
* Checks if object is a Submission or a SubmittedData
* @param {SubmittedDataReference | NewSubmittedDataReference | EditSubmittedDataReference} toBeDetermined
* @returns {boolean}
*/
export declare const determineIfIsSubmission: (reference: SubmittedDataReference | NewSubmittedDataReference | EditSubmittedDataReference) => reference is NewSubmittedDataReference | EditSubmittedDataReference;
/**
* Creates a Record type of DataRecord[] grouped by Entity names
* @param {Record<string, DataRecordReference[]>} mergeDataRecordsByEntityName
* @returns {Record<string, DataRecord[]>}
*/
export declare const extractSchemaDataFromMergedDataRecords: (mergeDataRecordsByEntityName: Record<string, DataRecordReference[]>) => Record<string, DataRecord[]>;
/**
* Checks whether a record exists within a collection of submitted data records marked for update.
* The lookup is performed by matching the given 'entityName' and 'systemId'.
*
* @Returns true if found, false otherwise
*/
export declare const findEditSubmittedData: (entityName: string, systemId: string, dataByEntityName: Record<string, DataRecordReference[]>) => boolean;
/**
* Finds and returns a list of invalid records based on a provided schema name.
*
* This function checks if the validation results are marked as invalid, and if so,
* filters the validation errors to return those related to a specific schema name.
*
* @param results - The validation results containing details of validation errors.
* @param entityName - The name of the schema to filter the invalid records by.
*
* @returns An array of invalid records for the specified schema, or an empty array if none are found.
*/
export declare const findInvalidRecordErrorsBySchemaName: (results: TestResult<DictionaryValidationError[]>, entityName: string) => import("@overture-stack/lectern-client").SchemaRecordError<import("@overture-stack/lectern-client").DictionaryValidationRecordErrorDetails>[];
/**
* Generalized function to filter out conflicting records between two data sets based on `systemId`.
*
* This function can be used to either filter updates from deletes or deletes from updates, depending on the provided parameters.
* It removes records from the `sourceData` that have a matching `systemId` in the `conflictData`.
*
* @param sourceData - A record of the primary data (e.g., updates or deletes) to be filtered, grouped by entity name.
* @param conflictData - A record of data that might conflict (e.g., deletes or updates), grouped by entity name.
* @param entitySelector - A function to select the `systemId` from the source records.
* @param conflictSelector - A function to select the `systemId` from the conflict records.
* @returns A record of filtered source data, excluding records that conflict based on `systemId`.
*/
export declare const filterRecordsByConflicts: <SourceData, ConflictData>(sourceData: Record<string, SourceData[]>, conflictData: Record<string, ConflictData[]>, entitySelector: (item: SourceData) => string, conflictSelector: (item: ConflictData) => string) => Record<string, SourceData[]>;
/**
* Filters updates from the provided `submissionUpdateData` based on conflicts found in the `submissionDeleteData`.
* Conflicts are determined by matching the `systemId` of the items in both records.
*
* @param submissionUpdateData - A record containing arrays of `SubmissionUpdateData` to be filtered.
* @param submissionDeleteData - A record containing arrays of `SubmissionDeleteData` that defines the conflicts.
* @returns A filtered record of `SubmissionUpdateData[]` where no items conflict with those in `submissionDeleteData`.
*/
export declare const filterUpdatesFromDeletes: (submissionUpdateData: Record<string, SubmissionUpdateData[]>, submissionDeleteData: Record<string, SubmissionDeleteData[]>) => Record<string, SubmissionUpdateData[]>;
/**
* Filters deletes from the provided `submissionDeleteData` based on conflicts found in the `submissionUpdateData`.
* Conflicts are determined by matching the `systemId` of the items in both records.
*
* @param submissionDeleteData - A record containing arrays of `SubmissionDeleteData` to be filtered.
* @param submissionUpdateData - A record containing arrays of `SubmissionUpdateData` that defines the conflicts.
* @returns A filtered record of `SubmissionDeleteData[]` where no items conflict with those in `submissionUpdateData`.
*/
export declare const filterDeletesFromUpdates: (submissionDeleteData: Record<string, SubmissionDeleteData[]>, submissionUpdateData: Record<string, SubmissionUpdateData[]>) => Record<string, SubmissionDeleteData[]>;
/**
* Returns a filter to query the database used to find dependents records when the update record involves changes of an primary ID field
*
* @param schemaRelations An array of `SchemaChildNode` representing the schema relations for the entity. Each node contains information about parent-child relationships.
* @param updateRecord The update record containing old and new data. The function checks the `old` data to identify fields involved in the relationship.
* @returns
*/
export declare const filterRelationsForPrimaryIdUpdate: (schemaRelations: SchemaChildNode[], updateRecord: SubmissionUpdateData) => {
entityName: string;
dataField: string;
dataValue: string | undefined;
}[];
/**
* Returns only the schema errors corresponding to the Active Submission.
* Schema errors are grouped by Entity name.
* @param {object} input
* @param {TestResult<DictionaryValidationError[]>} input.resultValidation
* @param {Record<string, DataRecordReference[]>} input.dataValidated
* @returns {SubmissionErrors}
*/
export declare const groupSchemaErrorsByEntity: (input: {
resultValidation: TestResult<DictionaryValidationError[]>;
dataValidated: Record<string, DataRecordReference[]>;
}) => SubmissionErrors;
/**
* This function extracts the Schema Data from the Active Submission
* and maps it to it's original reference Id
* The result mapping is used to perform the cross schema validation
* @param {number} activeSubmissionId
* @param {Record<string, SubmissionInsertData>} activeSubmissionInsertDataEntities
* @returns {Record<string, DataRecordReference[]>}
*/
export declare const mapInsertDataToRecordReferences: (activeSubmissionId: number, activeSubmissionInsertDataEntities: Record<string, SubmissionInsertData>) => Record<string, DataRecordReference[]>;
/**
* This function takes a collection of dependent data grouped by entity name, applies a filter to each entity,
* and creates a mapping of `SubmissionUpdateData` based on the specified filter and new data values.
*
* @param params
* @param param.dependentData A record where each key is an entity name and each value is an array of `SubmittedData` objects.
* @param param.filterEntity An array of filter criteria where each entry contains an `entityName`, `dataField`, and `dataValue` to filter.
* @param param.newDataRecord A record containing new data values to be applied to the filtered entities.
* @returns
*/
export declare const mapGroupedUpdateSubmissionData: ({ dependentData, filterEntity, newDataRecord, }: {
dependentData: Record<string, SubmittedData[]>;
filterEntity: {
entityName: string;
dataField: string;
dataValue: string | undefined;
}[];
newDataRecord: DataRecord;
}) => Record<string, SubmissionUpdateData[]>;
/**
* Combines **Active Submission** and the **Submitted Data** recevied as arguments.
* Then, the Schema Data is extracted and mapped with its internal reference ID.
* The returned Object is a collection of the raw Schema Data with it's reference ID grouped by entity name.
* @param {number} submissionId ID of the Active Submission
* @param {Object} submissionData
* @param {Record<string, SubmissionInsertData>} submissionData.insertData Collection of Data records of the Active Submission
* @param {Record<string, SubmissionUpdateData[]>} submissionData.updateData Collection of Data records of the Active Submission
* @param {Record<string, SubmissionDeleteData[]>} submissionData.deleteData Collection of Data records of the Active Submission
* @param {SubmittedData[]} submittedData An array of Submitted Data
* @returns {Record<string, DataRecordReference[]>}
*/
export declare const mergeAndReferenceEntityData: ({ submissionId, submissionData, submittedData, }: {
submissionId: number;
submissionData: SubmissionData;
submittedData: SubmittedData[];
}) => Record<string, DataRecordReference[]>;
/**
* Merges multiple `Record<string, SubmissionInsertData>` objects into a single object.
* If there are duplicate keys between the objects, the `records` arrays of `SubmissionInsertData`
* are concatenated for the matching keys, ensuring no duplicates.
*
* @param objects An array of objects where each object is a `Record<string, SubmissionInsertData>`.
* Each key represents the entityName, and the value is an object of type `SubmissionInsertData`.
*
* @returns A new `Record<string, SubmissionInsertData>` where:
* - If a key is unique across all objects, its value is directly included.
* - If a key appears in multiple objects, the `records` arrays are concatenated for that key, avoiding duplicates.
*/
export declare const mergeInsertsRecords: (...objects: Record<string, SubmissionInsertData>[]) => Record<string, SubmissionInsertData>;
/**
* Merges multiple `Record<string, SubmissionDeleteData[]>` objects into a single object.
* For each key, the `SubmissionDeleteData[]` arrays are concatenated, ensuring no duplicate
* `SubmissionDeleteData` objects based on the `systemId` field.
*
* @param objects Multiple `Record<string, SubmissionDeleteData[]>` objects to be merged.
* Each key represents an identifier, and the value is an array of `SubmissionDeleteData`.
*
* @returns
*/
export declare const mergeDeleteRecords: (...objects: Record<string, SubmissionDeleteData[]>[]) => Record<string, SubmissionDeleteData[]>;
/**
* Merge Active Submission data with incoming TSV file data processed
*
* @param objects
* @returns An arbitrary number of arrays of Record<string, SubmissionUpdateData[]>
*/
export declare const mergeUpdatesBySystemId: (...objects: Record<string, SubmissionUpdateData[]>[]) => Record<string, SubmissionUpdateData[]>;
/**
* Utility to convert a raw Submission record to a Response type
* @param {SubmissionDataDetailsRepositoryRecord} submission
* @returns {SubmissionDetailsResponse}
*/
export declare const createSubmissionDetailsResponse: (submission: SubmissionDataDetailsRepositoryRecord) => SubmissionDetailsResponse;
/**
* Utility to convert the raw SubmissionDataSummaryRepositoryRecord into a SubmissionSummaryResponse.
* It includes a `total` value representing the sum of changes of each `data` and `errors`
* @param {SubmissionDataSummaryRepositoryRecord} submission
* @returns {SubmissionSummary}
*/
export declare const createSubmissionSummaryResponse: (submission: SubmissionDataSummaryRepositoryRecord) => SubmissionSummary;
export declare const pluralizeSchemaName: (schemaName: string) => string;
export declare const removeItemsFromSubmission: (submissionData: SubmissionData, filter: {
actionType: SubmissionActionType;
entityName: string;
index: number | null;
}) => SubmissionData;
/**
* Processes the `foundDependentUpdates` array and segregates the updates based on
* whether they involve ID fields (dependent fields) or non-ID fields.
*
* @param foundDependentUpdates - Array of updates to be processed.
* @param filesDataProcessed - Record where the key is a string (representing an entity name) and
* each value is an array of `SubmissionUpdateData`. These are the processed data files to match against.
* @returns An object containing two records:
* - `idFieldChangeRecord`: A record of updates involving ID fields.
* - `nonIdFieldChangeRecord`: A record of updates involving non-ID fields.
*/
export declare const segregateFieldChangeRecords: (submissionUpdateRecords: Record<string, SubmissionUpdateData[]>, dictionaryRelations: Record<string, SchemaChildNode[]>) => {
idFieldChangeRecord: Record<string, SubmissionUpdateData[]>;
nonIdFieldChangeRecord: Record<string, SubmissionUpdateData[]>;
};
/**
* Construct a SubmissionInsertData object per each file returning a Record type based on entityName
* @param {FileSchemaMap} fileSchemaPairs
* @returns {Promise<Record<string, SubmissionInsertData>>}
*/
export declare const submissionInsertDataFromFiles: (fileSchemaMap: FileSchemaMap) => Promise<Record<string, SubmissionInsertData>>;
/**
* Validate a full set of Schema Data using a Dictionary
* @param {SchemasDictionary & {id: number }} dictionary
* @param {Record<string, DataRecord[]>} schemasData
* @returns A TestResult object representing the outcome of a test applied to some data.
* If a test is valid, no additional data is added to the result. If it is invalid, then the
* reason (or array of reasons) for why the test failed should be given.
*/
export declare const validateSchemas: (dictionary: SchemasDictionary & {
id: number;
}, schemasData: Record<string, DataRecord[]>) => TestResult<DictionaryValidationError[]>;
export declare const parseToSchema: (schema: Schema) => (record: Record<string, string>) => DataRecord;
export declare const parseSubmissionActionTypes: (values: unknown) => SubmissionActionType[];