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 = Response & { json(): Promise; }; 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(); export type ServerEffect = 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 = (args: DataFunctionArgs_) => (effect: ServerEffect) => 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(); const adata = useActionData(); ldata.a; // number adata; }