public async validateRelationshipsByIds()

in source/packages/services/assetlibrary/src/types/schemaValidator.full.service.ts [261:400]


    public async validateRelationshipsByIds(
        template: TypeModel,
        groups: DirectionToRelatedEntityArrayMap,
        devices: DirectionToRelatedEntityArrayMap
    ): Promise<ValidateRelationshipsByIdsResult> {
        logger.debug(
            `schemaValidator.full.service validateRelationshipsByIds: in: template:${JSON.stringify(
                template
            )}, groups:${JSON.stringify(groups)}, devices:${JSON.stringify(devices)}`
        );

        ow(template, ow.object.nonEmpty);

        // extrapolate the entity ids from the rels parameter to make our lives easier...
        const extrapolateIds = (rels: RelatedEntityArrayMap, ids: string[]) => {
            if ((Object.keys(rels || {}).length ?? 0) > 0) {
                Object.values(rels).forEach((entities) =>
                    entities.forEach((entity) => ids.push(entity.id.toLowerCase()))
                );
            }
        };
        const groupPaths: string[] = [];
        extrapolateIds(groups?.in, groupPaths);
        extrapolateIds(groups?.out, groupPaths);
        const deviceIds: string[] = [];
        extrapolateIds(devices?.in, deviceIds);
        extrapolateIds(devices?.out, deviceIds);

        let isValid = true;

        // retrieve the labels of entities to link, along with allowed relations
        const groupLabelsFuture = this.groupsDao.getLabels(groupPaths);
        const deviceLabelsFuture = this.devicesDao.getLabels(deviceIds);
        const [groupLabels, deviceLabels] = await Promise.all([
            groupLabelsFuture,
            deviceLabelsFuture,
        ]);

        // ensure the provided entity ids are valid
        const validatedGroupPaths = Object.keys(groupLabels || {});
        const invalidGroupPaths = groupPaths.filter((path) => !validatedGroupPaths.includes(path));
        if (invalidGroupPaths.length > 0) {
            isValid = false;
        }

        const validatedDeviceIds = Object.keys(deviceLabels || {});
        const invalidDeviceIds = deviceIds.filter((id) => !validatedDeviceIds.includes(id));
        if (invalidDeviceIds.length > 0) {
            isValid = false;
        }

        // verify that the attempted relationships are valid
        const invalidRelations: { [relation: string]: string[] } = {};
        const validateIncomingRelations = (
            rels: RelatedEntityArrayMap,
            labels: EntityTypeMap
        ): void => {
            if (Object.keys(rels || {}).length === 0) return;
            for (const [relation, entities] of Object.entries(rels)) {
                for (const entity of entities) {
                    const label = labels[entity.id.toLowerCase()]?.filter(
                        (label) => label !== 'group' && label !== 'device'
                    )?.[0];
                    if (
                        label === undefined ||
                        !template.schema.relations.incomingIncludes(relation, label)
                    ) {
                        if (invalidRelations[relation] === undefined) {
                            invalidRelations[relation] = [];
                        }
                        invalidRelations[relation].push(label);
                        isValid = false;
                    }
                }
            }
        };
        const validateOutgoingRelations = (
            rels: RelatedEntityArrayMap,
            labels: EntityTypeMap
        ): void => {
            if (Object.keys(rels || {}).length === 0) return;
            for (const [relation, entities] of Object.entries(rels)) {
                logger.debug(
                    `schemaValidator.full.service validateRelationshipsByIds: ***: relation: ${relation}, entities: ${JSON.stringify(
                        entities
                    )}`
                );
                for (const entity of entities) {
                    logger.debug(
                        `schemaValidator.full.service validateRelationshipsByIds: ***: entity: ${JSON.stringify(
                            entity
                        )}`
                    );
                    const label = labels[entity.id.toLowerCase()]?.filter(
                        (label) => label !== 'group' && label !== 'device'
                    )?.[0];
                    logger.debug(
                        `schemaValidator.full.service validateRelationshipsByIds: ***: label: ${JSON.stringify(
                            label
                        )}`
                    );
                    if (
                        label === undefined ||
                        !template.schema.relations.outgoingIncludes(relation, label)
                    ) {
                        if (invalidRelations[relation] === undefined) {
                            invalidRelations[relation] = [];
                        }
                        invalidRelations[relation].push(label);
                        isValid = false;
                        logger.debug(
                            `schemaValidator.full.service validateRelationshipsByIds: ***: updated invalidRelations: ${JSON.stringify(
                                invalidRelations
                            )}`
                        );
                    }
                }
            }
        };

        validateIncomingRelations(groups?.in, groupLabels);
        validateOutgoingRelations(groups?.out, groupLabels);
        validateIncomingRelations(devices?.in, deviceLabels);
        validateOutgoingRelations(devices?.out, deviceLabels);

        const response = {
            groupLabels,
            deviceLabels,
            invalidGroupPaths,
            invalidDeviceIds,
            invalidRelations,
            isValid,
        };
        logger.debug(
            `schemaValidator.full.service validateRelationshipsByIds: exit: ${JSON.stringify(
                response
            )}`
        );
        return response;
    }