import type { ReadonlyBinding } from 'react-bindings'; import { isBinding } from 'react-bindings'; import type { InferOptionalWaitableAndBindingValueTypes } from '../waitable/types/infer-waitable-and-binding-value-types'; import type { Waitable } from '../waitable/types/waitable'; import type { NamedWaitableDependencies, WaitableDependencies } from '../waitable/types/waitable-dependencies'; import { isWaitable } from '../waitable/utils.js'; export const extractOptionalWaitableDependencyValues = ({ dependencies, namedDependencyKeys }: { dependencies: DependenciesT | undefined; namedDependencyKeys: string[] | undefined; }): { allWaitablesAreLoaded: boolean; anyWaitablesHadErrors: boolean; lastError?: FailureT; values: InferOptionalWaitableAndBindingValueTypes; } => { const isArray = Array.isArray(dependencies); const isNonNamed = isArray || isBinding(dependencies) || isWaitable(dependencies); const inout: { allWaitablesAreLoaded: boolean; anyWaitablesHadErrors: boolean; lastError?: FailureT } = { allWaitablesAreLoaded: true, anyWaitablesHadErrors: false, lastError: undefined }; const makeOutput = (values: InferOptionalWaitableAndBindingValueTypes) => ({ ...inout, values }); if (isNonNamed) { if (isArray) { return makeOutput( dependencies.map((dependency) => // eslint-disable-next-line @typescript-eslint/no-unsafe-return extractValue(dependency, inout) ) as InferOptionalWaitableAndBindingValueTypes ); } else { return makeOutput(extractValue(dependencies, inout) as InferOptionalWaitableAndBindingValueTypes); } } else if (namedDependencyKeys !== undefined) { const namedValues: Record = {}; for (const key of namedDependencyKeys) { // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment namedValues[key] = extractValue((dependencies as NamedWaitableDependencies)[key], inout); } return makeOutput(namedValues as InferOptionalWaitableAndBindingValueTypes); } else { return makeOutput(undefined as InferOptionalWaitableAndBindingValueTypes); } }; // Helpers const extractValue = ( dependency: Waitable | ReadonlyBinding | undefined, inout: { allWaitablesAreLoaded: boolean; anyWaitablesHadErrors: boolean; lastError?: FailureT } ): T | undefined => { if (isWaitable(dependency)) { const value = (dependency as Waitable).value.get(); if (value === undefined) { inout.allWaitablesAreLoaded = false; const error = dependency.error.get() as FailureT | undefined; if (error !== undefined) { inout.anyWaitablesHadErrors = true; inout.lastError = error; } } return value; } else if (isBinding(dependency)) { return dependency.get(); } else { return undefined; } };