Mirror of https://github.com/roostorg/coop github.com/roostorg/coop
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at 557ff54b2b435e5f1e789c6a8a4e1bebf2d7deb6 101 lines 3.3 kB view raw
1import { 2 getScalarType, 3 isContainerType, 4 type ContainerType, 5 type Field, 6 type FieldScalarType, 7 type FieldType, 8 type ScalarType, 9 type ScalarTypeRuntimeType, 10 type TaggedScalar, 11} from '@roostorg/types'; 12 13import { hasOwn } from '../../utils/misc.js'; 14import { 15 type FieldRoleToScalarType, 16 type ItemSchema, 17 type SchemaFieldRoles, 18} from '../moderationConfigService/index.js'; 19import { fieldTypeHandlers } from './fieldTypeHandlers.js'; 20import { type NormalizedItemData } from './toNormalizedItemDataOrErrors.js'; 21 22/** 23 * Extracts all the values from all the passed in fields from a given piece of 24 * content, as one merged array. I.e., if one field is a container with 25 * multiple values, all those values will be flattened into the final result. 26 * 27 * NB: the `content` object might not actually have the fields and structure 28 * suggested by `fields`. In that case, the returned values may not be of the 29 * type suggested by `getScalarType(field)`, and some fields might be missing. 30 * 31 * @param data Content object whose field values should be returned 32 * @param fields The fields whose values should be included. 33 */ 34export function getValuesFromFields( 35 data: NormalizedItemData, 36 fields: Field[], 37): TaggedScalar<ScalarType>[] { 38 return fields.flatMap((field) => { 39 const fieldValue = getFieldValueOrValues(data, field); 40 return Array.isArray(fieldValue) 41 ? fieldValue 42 : fieldValue !== undefined 43 ? [fieldValue] 44 : []; 45 }); 46} 47 48export function getFieldValueOrValues<T extends FieldType>( 49 data: NormalizedItemData, 50 field: Field<T>, 51) { 52 const { name, type, container } = field; 53 const values = !hasOwn(data, name) 54 ? [] 55 : // NB: casting to `never` below is unambiguously wrong, but it's needed 56 // because the type that TS infers when trying to generate a single, 57 // callable signature for `getValues` is not correct (and has never as 58 // its argument types). 59 fieldTypeHandlers[type as FieldType] 60 .getValues(data[name] as never, container as never) 61 .map( 62 (value) => 63 // eslint-disable-next-line @typescript-eslint/consistent-type-assertions 64 ({ value, type: getScalarType(field) }) as TaggedScalar<ScalarType>, 65 ); 66 67 return (isContainerType(type) ? values : values[0]) as 68 | (T & ScalarType extends never 69 ? never 70 : TaggedScalar<FieldScalarType<T & ScalarType>>) 71 | (T & ContainerType extends never 72 ? never 73 : TaggedScalar<FieldScalarType<T & ContainerType>>[]) 74 | undefined; 75} 76 77export function getFieldValueForRole< 78 FieldRoles extends SchemaFieldRoles, 79 Role extends keyof FieldRoles, 80>( 81 schema: ItemSchema, 82 schemaFieldRoles: FieldRoles, 83 role: Role, 84 data: NormalizedItemData, 85) { 86 const fieldName = schemaFieldRoles[role]; 87 const field = schema.find((it) => it.name === fieldName); 88 if (field === undefined) { 89 return undefined; 90 } 91 const fieldValue = getFieldValueOrValues(data, field); 92 if (fieldValue === undefined) { 93 return undefined; 94 } 95 if (Array.isArray(fieldValue)) { 96 throw new Error('Unexpected array when getting field value'); 97 } 98 return fieldValue.value satisfies ScalarTypeRuntimeType<ScalarType> as ScalarTypeRuntimeType< 99 FieldRoleToScalarType[Role & keyof FieldRoleToScalarType] 100 >; 101}