Eric Bower
·
2025-06-06
types.ts
1import type { Operation, Result } from "effection";
2import type {
3 Action,
4 ActionWithPayload,
5 LoaderItemState,
6 LoaderPayload,
7 Next,
8 Payload,
9} from "../types.js";
10
11type IfAny<T, Y, N> = 0 extends 1 & T ? Y : N;
12
13export interface ThunkCtx<P = any> extends Payload<P> {
14 name: string;
15 key: string;
16 action: ActionWithPayload<CreateActionPayload<P>>;
17 actionFn: IfAny<
18 P,
19 CreateAction<ThunkCtx>,
20 CreateActionWithPayload<ThunkCtx<P>, P>
21 >;
22 result: Result<void>;
23}
24
25export interface ThunkCtxWLoader extends ThunkCtx {
26 loader: Omit<LoaderPayload<any>, "id"> | null;
27}
28
29export interface LoaderCtx<P = unknown> extends ThunkCtx<P> {
30 loader: Partial<LoaderItemState> | null;
31}
32
33export type ApiFetchResult<ApiSuccess = any, ApiError = any> =
34 | {
35 ok: true;
36 value: ApiSuccess;
37 }
38 | {
39 ok: false;
40 error: ApiError;
41 };
42
43export type ApiRequest = Partial<{ url: string } & RequestInit>;
44export type RequiredApiRequest = {
45 url: string;
46 headers: HeadersInit;
47} & Partial<RequestInit>;
48
49export interface FetchCtx<P = any> extends ThunkCtx<P> {
50 request: ApiRequest | null;
51 req: (r?: ApiRequest) => RequiredApiRequest;
52 response: Response | null;
53 bodyType: "arrayBuffer" | "blob" | "formData" | "json" | "text";
54}
55
56export interface FetchJson<ApiSuccess = any, ApiError = any> {
57 json: ApiFetchResult<ApiSuccess, ApiError>;
58}
59
60export interface FetchJsonCtx<P = any, ApiSuccess = any, ApiError = any>
61 extends FetchCtx<P>,
62 FetchJson<ApiSuccess, ApiError> {}
63
64export interface ApiCtx<Payload = any, ApiSuccess = any, ApiError = any>
65 extends FetchJsonCtx<Payload, ApiSuccess, ApiError> {
66 actions: Action[];
67 loader: Omit<LoaderPayload<any>, "id"> | null;
68 // should we cache ctx.json?
69 cache: boolean;
70 // should we use mdw.stub?
71 stub: boolean;
72 // previously cached data
73 cacheData: any;
74 _success: ApiSuccess;
75 _error: ApiError;
76}
77
78export interface PerfCtx<P = unknown> extends ThunkCtx<P> {
79 performance: number;
80}
81
82export type Middleware<Ctx extends ThunkCtx = ThunkCtx> = (
83 ctx: Ctx,
84 next: Next,
85) => Operation<any>;
86export type MiddlewareCo<Ctx extends ThunkCtx = ThunkCtx> =
87 | Middleware<Ctx>
88 | Middleware<Ctx>[];
89
90export type MiddlewareApi<Ctx extends ApiCtx = ApiCtx> = (
91 ctx: Ctx,
92 next: Next,
93) => Operation<any>;
94export type MiddlewareApiCo<Ctx extends ApiCtx = ApiCtx> =
95 | Middleware<Ctx>
96 | Middleware<Ctx>[];
97
98export interface CreateActionPayload<P = any, ApiSuccess = any> {
99 name: string;
100 key: string;
101 options: P;
102 _result: ApiSuccess;
103}
104
105export type CreateActionFn<ApiSuccess = any> = () => ActionWithPayload<
106 CreateActionPayload<Record<string | number | symbol, never>, ApiSuccess>
107>;
108
109export interface CreateAction<Ctx extends ThunkCtx = ThunkCtx, ApiSuccess = any>
110 extends CreateActionFn<ApiSuccess> {
111 run: (
112 p?: ActionWithPayload<
113 CreateActionPayload<Record<string | number | symbol, never>, ApiSuccess>
114 >,
115 ) => Operation<Ctx>;
116 use: (mdw: Middleware<Ctx>) => void;
117}
118
119export type CreateActionFnWithPayload<P = any, ApiSuccess = any> = (
120 p: P,
121) => ActionWithPayload<CreateActionPayload<P, ApiSuccess>>;
122
123export interface CreateActionWithPayload<
124 Ctx extends ThunkCtx,
125 P,
126 ApiSuccess = any,
127> extends CreateActionFnWithPayload<P, ApiSuccess> {
128 run: (
129 a: ActionWithPayload<CreateActionPayload<P, ApiSuccess>> | P,
130 ) => Operation<Ctx>;
131 use: (mdw: Middleware<Ctx>) => void;
132}
133
134export type ThunkAction<P = any, ApiSuccess = any> = ActionWithPayload<
135 CreateActionPayload<P, ApiSuccess>
136>;
137
138export type Supervisor<T = unknown> = (
139 pattern: string,
140 op: (action: Action) => Operation<T>,
141) => Operation<T>;