Files
openstapps/src/guards.ts
2022-08-17 16:09:45 +02:00

133 lines
4.0 KiB
TypeScript

/*
* Copyright (C) 2019-2022 Open StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* unknown WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {SCTranslations} from './general/i18n';
import {SCBulkResponse} from './protocol/routes/bulk-request';
import {SCSearchResponse} from './protocol/routes/search';
import {SCMultiSearchResponse} from './protocol/routes/search-multi';
import {
SCThing,
SCThingTranslatableProperties,
SCThingType,
SCThingWithoutReferences,
} from './things/abstract/thing';
/**
* Type guard to check if something is a SCThing
*
* @param something Something to check
*/
export function isThing(something: unknown): something is SCThing {
if (typeof something !== 'object' || something === null) {
return false;
}
if (!('type' in something)) {
return false;
}
const type = (something as {type: unknown}).type;
if (typeof type !== 'string') {
return false;
}
return Object.values(SCThingType).includes(type as SCThingType);
}
/**
* Type guard to check if translations exist
*
* @param thing Thing to check
*/
export function isThingWithTranslations(
thing: SCThingWithoutReferences,
): thing is SCThingWithoutReferences & {translations: SCTranslations<SCThingTranslatableProperties>} {
return typeof thing.translations !== 'undefined';
}
/**
* Type guard to check if something is a bulk response
*
* @param something Something to check
*/
export function isBulkResponse(something: unknown): something is SCBulkResponse {
if (typeof something !== 'object' || something === null) {
return false;
}
if (
!('expiration' in something) ||
!('source' in something) ||
!('state' in something) ||
!('type' in something) ||
!('uid' in something)
) {
return false;
}
const {expiration, source, state, type, uid} = something as {
expiration: unknown;
source: unknown;
state: unknown;
type: unknown;
uid: unknown;
};
return (
typeof expiration === 'string' &&
typeof source === 'string' &&
typeof state === 'string' &&
typeof type === 'string' &&
typeof uid === 'string'
);
}
/**
* Type guard to check if something is a search response
*
* @param something Something to check
*/
export function isSearchResponse(something: unknown): something is SCSearchResponse {
if (!(typeof something === 'object') || something === null) {
return false;
}
const somethingObject = something as {[key: string]: {[key: string]: string}};
return (
Array.isArray(somethingObject.data) &&
Array.isArray(somethingObject.facets) &&
typeof somethingObject.pagination !== 'undefined' &&
typeof somethingObject.pagination.count === 'number' &&
typeof somethingObject.pagination.offset === 'number' &&
typeof somethingObject.pagination.total === 'number' &&
typeof somethingObject.stats !== 'undefined' &&
typeof somethingObject.stats.time === 'number'
);
}
/**
* Type guard to check if something is a multi search response
*
* @param something Something to check
*/
export function isMultiSearchResponse(something: unknown): something is SCMultiSearchResponse {
const initialValue = Object.keys(something as {[key: string]: string}).length > 0 ? true : false;
// eslint-disable-next-line unicorn/no-array-reduce
return Object.keys(something as {[key: string]: string}).reduce((previousOnesAreSearchResponses, key) => {
return previousOnesAreSearchResponses && isSearchResponse((something as {[key: string]: string})[key]);
}, initialValue as boolean);
}