Created
November 29, 2022 09:36
-
-
Save pigoz/2bf6bea2ddbb6e6a8e5066adac044f47 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as E from '@fp-ts/data/Either'; | |
import * as Z from '@effect/io/Effect'; | |
import * as Context from '@fp-ts/data/Context'; | |
import { pipe } from '@fp-ts/data/Function'; | |
import { | |
DataFunctionArgs as DataFunctionArgs_, | |
// LoaderFunction, | |
// TypedResponse, | |
// AppLoadContext, | |
json, | |
LoaderArgs, | |
ActionArgs, | |
redirect, | |
} from '@remix-run/node'; | |
import { useActionData, useLoaderData } from '@remix-run/react'; | |
// import { Params } from 'react-router-dom'; | |
/* | |
export declare type TypedResponse<T extends unknown = unknown> = Response & { | |
json(): Promise<T>; | |
}; | |
import type { Params } from "react-router-dom"; | |
An object of unknown type for route loaders and actions provided by the | |
server's `getLoadContext()` function. | |
export interface AppLoadContext { | |
[key: string]: unknown; | |
} | |
export interface DataFunctionArgs { | |
request: Request; | |
context: AppLoadContext; | |
params: Params; | |
} | |
*/ | |
export type DataFunctionArgs = DataFunctionArgs_; | |
export const DataFunctionArgs = Context.Tag<DataFunctionArgs>(); | |
export type ServerEffect<E, A extends unknown = unknown> = Z.Effect< | |
DataFunctionArgs, | |
E, | |
A | |
>; | |
// TODO: provide a json/useLoaderData pair that extends superjson and handles | |
// transparent network serialization of all @fp-ts/core types that can | |
// be serialized (Either and Option for sure) | |
export const remixrun = | |
<E, A extends unknown = unknown>(args: DataFunctionArgs_) => | |
(effect: ServerEffect<E, A>) => | |
pipe(effect, Z.provideService(DataFunctionArgs)(args), Z.unsafeRunPromise); | |
/////////////////////////////////////////////////////////////////////////////// | |
// examples | |
export const zloadersucc = Z.sync(() => json({ b: 2 })); | |
export const zloader = pipe( | |
Z.service(DataFunctionArgs), | |
Z.map(({ request, params }) => { | |
console.log('request', request); | |
console.log('params', params); | |
console.log('context', params); | |
return json({ a: 1 }); | |
}), | |
); | |
// XXX handle formData parsing with zod and fp-ts/codec | |
export const formData = pipe( | |
Z.service(DataFunctionArgs), | |
Z.flatMap(({ request }) => | |
Z.tryCatchPromise( | |
() => request.formData(), | |
() => 'formData error' as const, | |
), | |
), | |
); | |
export const zaction = pipe( | |
formData, | |
Z.map(fd => | |
fd.has('foo') ? E.right(redirect('/done')) : E.left(json({ error: 'aa' })), | |
), | |
Z.flatMap(Z.fromEither), | |
); | |
export const loader = (args: LoaderArgs) => pipe(zloader, remixrun(args)); | |
export const action = (args: ActionArgs) => pipe(zaction, remixrun(args)); | |
export function Page() { | |
const ldata = useLoaderData<typeof loader>(); | |
const adata = useActionData<typeof action>(); | |
ldata.a; // number | |
adata; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment