Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | 150x 209x 209x 150x | import { ArkErrors } from 'arktype';
import type * as DB from '$lib/database';
import { MetadataRuntimeValue, type RuntimeValue } from '$lib/schemas/metadata';
export type TypedMetadataValue<Type extends DB.MetadataType = DB.MetadataType> = Omit<
DB.MetadataValue,
'value'
> & { value: RuntimeValue<Type> };
export type RuntimeValuesPerType = { [K in DB.MetadataType]: RuntimeValue<K> };
type TypeswitchReturnTypes<R> = { [T in DB.MetadataType]: R };
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type TypeswitchCases<ReturnTypes extends TypeswitchReturnTypes<any>> = {
[T in DB.MetadataType]: (...values: RuntimeValue<T>[]) => ReturnTypes[T];
};
type TypeswitchValues = RuntimeValue | [RuntimeValue, RuntimeValue] | RuntimeValue[];
/**
* Run different code depending on metadata value's type.
* Return types for the branches can be specified in two ways:
* - by specifying R: a common return type for all branches
* - by specifying RT: a mapping of return types per metadata type. For example, RuntimeValuesPerType if you want each branch to preserve its own runtime type. When specifying RT, you can set R to `any` to avoid TS errors.
*/
export function switchOnMetadataType<
R,
RT extends TypeswitchReturnTypes<R> = TypeswitchReturnTypes<R>
>(type: DB.MetadataType, value: TypeswitchValues, cases: TypeswitchCases<RT>): RT[DB.MetadataType];
export function switchOnMetadataType<
R,
RT extends TypeswitchReturnTypes<R> = TypeswitchReturnTypes<R>
>(
type: DB.MetadataType,
value: TypeswitchValues,
cases: TypeswitchCases<RT>,
fallback: undefined,
error?: (...values: ArkErrors[]) => RT[DB.MetadataType]
): RT[DB.MetadataType];
export function switchOnMetadataType<
R,
RT extends TypeswitchReturnTypes<R> = TypeswitchReturnTypes<R>
>(
type: DB.MetadataType,
value: TypeswitchValues,
cases: Partial<TypeswitchCases<RT>>,
fallback: (...values: RuntimeValue[]) => RT[DB.MetadataType],
error?: (...values: ArkErrors[]) => RT[DB.MetadataType]
): RT[DB.MetadataType];
export function switchOnMetadataType<
R,
RT extends TypeswitchReturnTypes<R> = TypeswitchReturnTypes<R>
>(
type: DB.MetadataType,
value: TypeswitchValues,
cases: Partial<TypeswitchCases<RT>>,
fallback?: (...values: RuntimeValue[]) => RT[DB.MetadataType],
error?: (...values: ArkErrors[]) => RT[DB.MetadataType]
): RT[DB.MetadataType] {
const values = Array.isArray(value) ? value : [value];
const typeds = values.map((v) => MetadataRuntimeValue[type](v));
Iif (typeds.some((v) => v instanceof ArkErrors)) {
if (error) return error(...(typeds.filter((v) => v instanceof ArkErrors) as ArkErrors[]));
throw new Error(
`Invalid metadata value for type ${type}: ${typeds
.filter((v) => v instanceof ArkErrors)
.map((v) => v.toString())
.join('; ')}`
);
}
// @ts-expect-error typescript can't link the type of value and type parameter
return (cases[type] ?? fallback)(...typeds);
}
export function hasRuntimeType<Type extends DB.MetadataType>(
type: Type,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
value: any
): value is RuntimeValue<Type> {
return MetadataRuntimeValue[type].allows(value);
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function assertIs<Type extends DB.MetadataType>(type: Type, value: any): RuntimeValue<Type> {
if (!hasRuntimeType(type, value))
throw new Error(`La valeur n'est pas de type ${type}: ${JSON.stringify(value)}`);
return value;
}
/**
* Get a strongly-typed metadata value from an image (Image ONLY, not Observation).
*/
export function getMetadataValue<Type extends DB.MetadataType>(
image: DB.Image,
type: Type,
metadataId: string
): TypedMetadataValue<Type> | undefined {
const value = image.metadata[metadataId];
if (value === undefined) return undefined;
return {
...value,
value: assertIs(type, value.value)
};
}
|