UNPKG

@donverduyn/react-runtime

Version:
177 lines (176 loc) 7.48 kB
import type React from 'react'; import type { Layer, ManagedRuntime } from 'effect'; import type { MergeLeft } from 'effect/Types'; import type { Booleans, Call, Objects, Tuples } from 'hotscript'; import type { IsStringLiteral, Simplify, Tagged } from 'type-fest'; import type { createUse } from '@/hooks/useRuntimeApi/hooks/use'; import type { createFn } from '@/hooks/useRuntimeApi/hooks/useFn'; import type { createRun } from '@/hooks/useRuntimeApi/hooks/useRun'; import type { createPush } from 'hooks/useRuntimeApi/hooks/usePush'; import type { PropService } from 'utils/effect'; export type ScopeId = Tagged<string, 'ScopeId'>; export type InstId = Tagged<string, 'InstId'>; export type DeclId = Tagged<string, 'DeclId'>; export type DeclarationId = Tagged<string, 'DeclarationId'>; export type ComponentId = Tagged<string, 'ComponentId'>; export type RegisterId = Tagged<string, 'RegisterId'>; export type RuntimeKey = symbol; export type RuntimeId = Tagged<string, 'RuntimeId'>; export type ProviderId = Tagged<string, 'ProviderId'>; export type InstanceId = Tagged<string, 'InstanceId'>; export type ComponentMeta = { name: string; }; export declare const ID_PROP = "_id"; export declare const DRYRUN_ID_PROP = "_dryRunId"; export declare const PROVIDERS_PROP = "_providers"; export declare const COMPONENT_PROP = "_component"; export declare const PROPS_PROP = "_props"; export declare const UPSTREAM_PROP = "_upstream"; export declare const ERROR_PROP = "_error"; export type RuntimeApi<R> = { instance: RuntimeInstance<R>['runtime']; use: ReturnType<typeof createUse<R>>; useFn: ReturnType<typeof createFn<R>>; usePush: ReturnType<typeof createPush<R>>; useRun: ReturnType<typeof createRun<R>>; }; export type RuntimeApiFactory<R> = { create: (module: RuntimeContext<R, never, PropService>, instances: Map<RuntimeKey, RuntimeInstance<any>>) => RuntimeApi<R>; createInert: (stub: unknown) => RuntimeApi<R>; }; export type RuntimeConfig = { debug: boolean; postUnmountTTL: number; env: 'prod' | 'dev'; replace: boolean; cleanupPolicy: 'onUnmount' | 'immediate'; }; export type RuntimeContext<R, E = never, A = never> = { key: RuntimeKey; name: string; layer: Layer.Layer<R, E, A>; }; export type RuntimePayload<R, P extends Record<string, unknown>> = { providerId: string; index: number; context: RuntimeContext<R, never, PropService>; config: Partial<RuntimeConfig>; props: P; }; export type RuntimeInstance<R, P = object> = { id: InstanceId; runtime: ManagedRuntime.ManagedRuntime<R, never>; config: RuntimeConfig; propProxy: Subscribable<NoInfer<P>> & P; }; export type IdProp = { readonly id: string; }; export type Extensible<T extends Record<PropertyKey, unknown>> = T & Record<PropertyKey, unknown>; export type SubscribeFn<T> = (value: T) => void; export type UnsubscribeFn = () => void; export type Subscribable<T> = { subscribe: (key: keyof T | PropertyKey, fn: SubscribeFn<T[keyof T]>) => UnsubscribeFn; value: T; }; export type IsPrimitiveString<T> = [T] extends [string] ? IsStringLiteral<T> extends true ? false : true : false; export type SafeKeys<T extends PropertyKey> = IsStringLiteral<T> extends true ? T : never; export type ResultProps<CProps, ExtraProps extends Record<PropertyKey, unknown>> = Readonly<Partial<IdProp & Pick<ExtraProps, keyof CProps>> & Omit<CProps, SafeKeys<keyof ExtraProps>>>; export type ExtensibleProps<CProps> = Extensible<Partial<IdProp & CProps>>; export type UpstreamProviderApi<P> = { inject: <R>(module: RuntimeContext<R, never, PropService>) => RuntimeApi<R>; props: P; }; export type UpstreamProviderFn<CProps, TResult = unknown> = (api: UpstreamProviderApi<MergeLeft<IdProp, CProps>>) => TResult; export type ProviderApi<R, P = object> = { configure: (config?: Partial<RuntimeConfig>) => RuntimeApi<R>; runtime: RuntimeApi<R>; inject: <R>(module: RuntimeContext<R, never, PropService>) => RuntimeApi<R>; props: P; }; export type ProviderFn<R, CProps, TResult = unknown> = (api: ProviderApi<R, MergeLeft<IdProp, CProps>>) => TResult; export type PropsFn<CProps, TResult = unknown> = (props: MergeLeft<IdProp, CProps>) => TResult; export type ProviderEntryType = 'runtime' | 'upstream' | 'props'; export type ProviderEntry<R, C extends React.FC<any>, P = any> = { id: ProviderId; type: 'runtime'; module: RuntimeContext<R, never, PropService>; fn?: ProviderFn<R, C, P> | ProviderFn<R, C, undefined> | undefined; } | { id: ProviderId; type: 'upstream'; module?: RuntimeContext<R, never, PropService> | undefined; fn: ProviderFn<R, C, P> | ProviderFn<R, C>; } | { id: ProviderId; type: 'props'; fn: PropsFn<C, P>; }; export type ResolvedProviderEntry<R, C extends React.FC<any>, P> = ProviderEntry<R, C, P> & { level: number; index: number; }; export type ExtractStaticComponent<T> = T extends { [COMPONENT_PROP]: infer C; } ? C extends (props: infer P) => any ? React.FC<Simplify<P>> : never : T; export type ExtractStaticProviders<T> = T extends { [PROVIDERS_PROP]: infer R; } ? R extends unknown[] ? R : never : []; export type ExtractStaticProps<T> = T extends { [PROPS_PROP]: infer P; } ? P : Record<never, never>; export type ExtractProps<C extends React.FC<any>> = React.ComponentProps<C> & ExtractStaticProps<C>; export type ExtractStaticUpstream<T> = T extends { [UPSTREAM_PROP]: infer U; } ? U extends unknown[] ? U : never : []; export type ExtractStaticError<T> = T extends { [ERROR_PROP]: infer U; } ? U extends unknown[] ? U : never : []; export type UnwrapRuntime<T> = T extends { module: infer R; } ? R : T; type ExtractReference<T> = UnwrapRuntime<T> extends { reference: () => infer R; } ? R : never; declare const UpstreamSymbol: unique symbol; type UpstreamBrand = { readonly [UpstreamSymbol]: never; }; export type Up<T> = T & UpstreamBrand; export type KeepUpstream<T> = Call<Tuples.Filter<Booleans.Extends<{ [UpstreamSymbol]: true; }>>, T>; type DownstreamBrand = { readonly [UpstreamSymbol]: false; }; export type Down<T> = T & DownstreamBrand; export type FilterReference<T> = Call<Tuples.Map<Objects.Get<'type'>>, T>; type ExtractProviders<T> = T extends { [PROVIDERS_PROP]?: infer R; } ? R : never; type Includes<T extends readonly unknown[], V> = T extends [ infer Head, ...infer Rest ] ? [V] extends [Head] ? true : Includes<Rest, V> : false; type PushUnique<T extends readonly unknown[], V> = Includes<T, V> extends true ? T : [...T, V]; type Reverse<T> = Call<Tuples.Reverse, T>; type Unique<T extends any[], Acc extends any[] = []> = T extends [ infer Head, ...infer Tail ] ? Head extends Acc[number] ? Unique<Tail, Acc> : Unique<Tail, [...Acc, Head]> : Acc; export type CollectProviders<Component, Seen extends unknown[] = [], Acc extends unknown[] = []> = ExtractProviders<Component> extends readonly [infer Head, ...infer Tail] ? ExtractReference<Head> extends infer Ref ? Ref extends object ? Ref extends Seen[number] ? CollectProviders<{ [PROVIDERS_PROP]?: Tail; }, Seen, PushUnique<Acc, Head>> : CollectProviders<{ [PROVIDERS_PROP]?: Tail; }, [ ...Seen, Ref ], PushUnique<[ ...Acc, ...CollectProviders<Ref, [...Seen, Ref], Acc> ], Head>> : CollectProviders<{ [PROVIDERS_PROP]?: Tail; }, Seen, PushUnique<Acc, Head>> : Acc : Acc; export type TraverseDeps<T> = Reverse<Unique<CollectProviders<T>>>; export {};