Update selected item color in Pass menu
[ProtonMail-WebClient.git] / packages / pass / store / request / flow.ts
blob92d83b4a92f12d0cba16be0886049259cd8c39f4
1 import { createAction } from '@reduxjs/toolkit';
3 import { type ActionCallback, withCallback } from '@proton/pass/store/actions/enhancers/callback';
4 import { pipe } from '@proton/pass/utils/fp/pipe';
6 import { withRequest, withRequestFailure, withRequestSuccess } from './enhancers';
7 import type { RequestConfig } from './types';
9 type RequestPrepareAction<P extends any[], R> = (...params: P) => R;
10 type Payload<T = any> = { payload: T };
12 export type RequestFlow<I, S, F> = ReturnType<ReturnType<typeof requestActionsFactory<I, S, F>>>;
13 export type RequestIntent<T extends RequestFlow<any, any, any>> = T extends RequestFlow<infer U, any, any> ? U : never;
14 export type RequestSuccess<T extends RequestFlow<any, any, any>> = T extends RequestFlow<any, infer U, any> ? U : never;
16 type CreateRequestActionsOptions<
17     IntentDTO,
18     SuccessDTO,
19     FailureDTO,
20     IntentData extends boolean,
21     SuccessData extends boolean,
22     FailureData extends boolean,
23     IntentPrepared extends Payload,
24     SuccessPrepared extends Payload,
25     FailurePrepared extends Payload,
26 > = {
27     requestId: (dto: IntentDTO) => string;
28     intent?: {
29         config?: RequestConfig<'start', IntentData>;
30         prepare?: RequestPrepareAction<[intent: IntentDTO], IntentPrepared>;
31     };
33     success?: {
34         config?: RequestConfig<'success', SuccessData>;
35         prepare?: RequestPrepareAction<[success: SuccessDTO], SuccessPrepared>;
36     };
38     failure?: {
39         config?: RequestConfig<'failure', FailureData>;
40         prepare?: RequestPrepareAction<[error: unknown, failure: FailureDTO], FailurePrepared>;
41     };
44 /** Creates action creators for each stage of a request sequence:
45  * intent, success, and error. These action creators facilitate the
46  * dispatching of actions to represent the initiation of a request,
47  * successful completion of a request, and handling of errors that
48  * occur during the request process.*/
49 export const requestActionsFactory =
50     <IntentDTO, SuccessDTO, FailureDTO = void>(namespace: string) =>
51     <
52         IntentPrepared extends Payload = Payload<IntentDTO>,
53         SuccessPrepared extends Payload = Payload<SuccessDTO>,
54         FailurePrepared extends Payload = Payload<FailureDTO>,
55         IntentData extends boolean = false,
56         SuccessData extends boolean = false,
57         FailureData extends boolean = false,
58     >(
59         options: CreateRequestActionsOptions<
60             IntentDTO,
61             SuccessDTO,
62             FailureDTO,
63             IntentData,
64             SuccessData,
65             FailureData,
66             IntentPrepared,
67             SuccessPrepared,
68             FailurePrepared
69         >
70     ) => {
71         type IntentPA = RequestPrepareAction<[intent: IntentDTO], IntentPrepared>;
72         type SuccessPA = RequestPrepareAction<[success: SuccessDTO], SuccessPrepared>;
73         type FailurePA = RequestPrepareAction<[error: unknown, failure: FailureDTO], FailurePrepared>;
75         const toPayload = (payload: unknown) => ({ payload });
76         const toPayloadWithError = (error: unknown, payload: unknown) => ({ payload, error });
78         const intentPA = (options.intent?.prepare ?? toPayload) as IntentPA;
79         const successPA = (options.success?.prepare ?? toPayload) as SuccessPA;
80         const failurePA = (options.failure?.prepare ?? toPayloadWithError) as FailurePA;
82         return {
83             intent: createAction(`${namespace}::intent`, (payload: IntentDTO, callback?: ActionCallback) =>
84                 pipe(
85                     withRequest({
86                         status: 'start',
87                         id: options.requestId(payload),
88                         ...(options.intent?.config ?? { data: false as IntentData }),
89                     }),
90                     withCallback(callback)
91                 )(intentPA(payload))
92             ),
93             success: createAction(`${namespace}::success`, withRequestSuccess(successPA, options.success?.config)),
94             failure: createAction(`${namespace}::failure`, withRequestFailure(failurePA, options.failure?.config)),
95         };
96     };