@effectify/react-remix 0.3.0 → 0.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +9 -9
- package/dist/src/index.d.ts +0 -3
- package/dist/src/index.js +0 -3
- package/dist/src/lib/context.d.ts +0 -9
- package/dist/src/lib/context.js +0 -5
- package/dist/src/lib/http-response.d.ts +0 -33
- package/dist/src/lib/http-response.js +0 -14
- package/dist/src/lib/runtime.d.ts +0 -24
- package/dist/src/lib/runtime.js +0 -77
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effectify/react-remix",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.5",
|
|
4
4
|
"description": "Integration of Remix with Effect for React applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -12,9 +12,9 @@
|
|
|
12
12
|
"exports": {
|
|
13
13
|
".": {
|
|
14
14
|
"@effectify/source": "./src/index.ts",
|
|
15
|
-
"types": "./dist/
|
|
16
|
-
"import": "./dist/
|
|
17
|
-
"default": "./dist/
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"import": "./dist/index.js",
|
|
17
|
+
"default": "./dist/index.js"
|
|
18
18
|
}
|
|
19
19
|
},
|
|
20
20
|
"files": [
|
|
@@ -22,11 +22,11 @@
|
|
|
22
22
|
"!**/*.tsbuildinfo"
|
|
23
23
|
],
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@effect/platform": "0.
|
|
26
|
-
"@effect/platform-node": "0.
|
|
27
|
-
"effect": "3.
|
|
28
|
-
"@remix-run/react": "2.17.
|
|
29
|
-
"@remix-run/node": "2.17.
|
|
25
|
+
"@effect/platform": "0.94.0",
|
|
26
|
+
"@effect/platform-node": "0.104.0",
|
|
27
|
+
"effect": "3.19.13",
|
|
28
|
+
"@remix-run/react": "2.17.2",
|
|
29
|
+
"@remix-run/node": "2.17.2"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {},
|
|
32
32
|
"peerDependencies": {},
|
package/dist/src/index.d.ts
DELETED
package/dist/src/index.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { ActionFunctionArgs, LoaderFunctionArgs } from '@remix-run/node';
|
|
2
|
-
import * as Context from 'effect/Context';
|
|
3
|
-
declare const ActionArgsContext_base: Context.TagClass<ActionArgsContext, "ActionArgsContext", ActionFunctionArgs>;
|
|
4
|
-
export declare class ActionArgsContext extends ActionArgsContext_base {
|
|
5
|
-
}
|
|
6
|
-
declare const LoaderArgsContext_base: Context.TagClass<LoaderArgsContext, "LoaderArgsContext", LoaderFunctionArgs>;
|
|
7
|
-
export declare class LoaderArgsContext extends LoaderArgsContext_base {
|
|
8
|
-
}
|
|
9
|
-
export {};
|
package/dist/src/lib/context.js
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import * as Effect from 'effect/Effect';
|
|
2
|
-
declare const HttpResponseSuccess_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => Readonly<A> & {
|
|
3
|
-
readonly _tag: "HttpResponseSuccess";
|
|
4
|
-
};
|
|
5
|
-
export declare class HttpResponseSuccess<T> extends HttpResponseSuccess_base<{
|
|
6
|
-
readonly data: T;
|
|
7
|
-
}> {
|
|
8
|
-
}
|
|
9
|
-
declare const HttpResponseFailure_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => Readonly<A> & {
|
|
10
|
-
readonly _tag: "HttpResponseFailure";
|
|
11
|
-
};
|
|
12
|
-
export declare class HttpResponseFailure<T = unknown> extends HttpResponseFailure_base<{
|
|
13
|
-
readonly cause: T;
|
|
14
|
-
}> {
|
|
15
|
-
}
|
|
16
|
-
declare const HttpResponseRedirect_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => Readonly<A> & {
|
|
17
|
-
readonly _tag: "HttpResponseRedirect";
|
|
18
|
-
};
|
|
19
|
-
export declare class HttpResponseRedirect extends HttpResponseRedirect_base<{
|
|
20
|
-
readonly to: string;
|
|
21
|
-
readonly init?: number | ResponseInit | undefined;
|
|
22
|
-
}> {
|
|
23
|
-
}
|
|
24
|
-
export type HttpResponse<T> = HttpResponseRedirect | HttpResponseSuccess<T> | HttpResponseFailure<unknown>;
|
|
25
|
-
export declare const matchHttpResponse: <T>() => <P extends {
|
|
26
|
-
readonly HttpResponseSuccess: (_: HttpResponseSuccess<T>) => any;
|
|
27
|
-
readonly HttpResponseFailure: (_: HttpResponseFailure<unknown>) => any;
|
|
28
|
-
readonly HttpResponseRedirect: (_: HttpResponseRedirect) => any;
|
|
29
|
-
} & { readonly [Tag in Exclude<keyof P, "HttpResponseSuccess" | "HttpResponseFailure" | "HttpResponseRedirect">]: never; }>(fields: P) => (input: HttpResponse<T>) => import("effect/Unify").Unify<ReturnType<P[keyof P]>>;
|
|
30
|
-
export declare const httpSuccess: <T>(data: T) => Effect.Effect<HttpResponseSuccess<T>, never, never>;
|
|
31
|
-
export declare const httpFailure: <T = unknown>(cause: T) => Effect.Effect<HttpResponseFailure<T>, never, never>;
|
|
32
|
-
export declare const httpRedirect: (to: string, init?: number | ResponseInit) => Effect.Effect<HttpResponseRedirect, never, never>;
|
|
33
|
-
export {};
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import * as Data from 'effect/Data';
|
|
2
|
-
import * as Effect from 'effect/Effect';
|
|
3
|
-
import * as Match from 'effect/Match';
|
|
4
|
-
export class HttpResponseSuccess extends Data.TaggedClass('HttpResponseSuccess') {
|
|
5
|
-
}
|
|
6
|
-
export class HttpResponseFailure extends Data.TaggedClass('HttpResponseFailure') {
|
|
7
|
-
}
|
|
8
|
-
export class HttpResponseRedirect extends Data.TaggedClass('HttpResponseRedirect') {
|
|
9
|
-
}
|
|
10
|
-
export const matchHttpResponse = () => Match.typeTags();
|
|
11
|
-
// Helper functions for better DX
|
|
12
|
-
export const httpSuccess = (data) => Effect.succeed(new HttpResponseSuccess({ data }));
|
|
13
|
-
export const httpFailure = (cause) => Effect.succeed(new HttpResponseFailure({ cause }));
|
|
14
|
-
export const httpRedirect = (to, init) => Effect.succeed(new HttpResponseRedirect({ to, init }));
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { type ActionFunctionArgs, type LoaderFunctionArgs } from '@remix-run/node';
|
|
2
|
-
import * as Effect from 'effect/Effect';
|
|
3
|
-
import type * as Layer from 'effect/Layer';
|
|
4
|
-
import { ActionArgsContext, LoaderArgsContext } from './context.js';
|
|
5
|
-
import { type HttpResponse } from './http-response.js';
|
|
6
|
-
export declare const make: <R, E>(layer: Layer.Layer<R, E, never>) => {
|
|
7
|
-
withLoaderEffect: <A, B>(self: Effect.Effect<HttpResponse<A>, B, R | LoaderArgsContext>) => (args: LoaderFunctionArgs) => Promise<{
|
|
8
|
-
ok: true;
|
|
9
|
-
data: A;
|
|
10
|
-
} | {
|
|
11
|
-
ok: false;
|
|
12
|
-
errors: string[];
|
|
13
|
-
}>;
|
|
14
|
-
withActionEffect: <A, B_1>(self: Effect.Effect<HttpResponse<A>, B_1, R | ActionArgsContext>) => (args: ActionFunctionArgs) => Promise<import("@remix-run/node").TypedResponse<{
|
|
15
|
-
ok: false;
|
|
16
|
-
errors: B_1;
|
|
17
|
-
}> | {
|
|
18
|
-
ok: true;
|
|
19
|
-
response: A;
|
|
20
|
-
} | import("@remix-run/node").TypedResponse<{
|
|
21
|
-
ok: false;
|
|
22
|
-
errors: string[];
|
|
23
|
-
}> | import("@remix-run/node").TypedResponse<never>>;
|
|
24
|
-
};
|
package/dist/src/lib/runtime.js
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import { json, redirect } from '@remix-run/node';
|
|
2
|
-
import * as Effect from 'effect/Effect';
|
|
3
|
-
import * as Exit from 'effect/Exit';
|
|
4
|
-
import { pipe } from 'effect/Function';
|
|
5
|
-
import * as Logger from 'effect/Logger';
|
|
6
|
-
import * as ManagedRuntime from 'effect/ManagedRuntime';
|
|
7
|
-
import { ActionArgsContext, LoaderArgsContext } from './context.js';
|
|
8
|
-
import { matchHttpResponse } from './http-response.js';
|
|
9
|
-
export const make = (layer) => {
|
|
10
|
-
const runtime = ManagedRuntime.make(layer);
|
|
11
|
-
const withLoaderEffect = (self) => (args) => {
|
|
12
|
-
const runnable = pipe(self, Effect.provide(Logger.pretty), Effect.provideService(LoaderArgsContext, args), Effect.tapError((cause) => Effect.logError('Loader effect failed', cause)));
|
|
13
|
-
return runtime.runPromiseExit(runnable).then(Exit.match({
|
|
14
|
-
onFailure: (cause) => {
|
|
15
|
-
if (cause._tag === 'Fail') {
|
|
16
|
-
// Preserve the original error for ErrorBoundary
|
|
17
|
-
const error = cause.error;
|
|
18
|
-
if (error instanceof Response) {
|
|
19
|
-
throw error;
|
|
20
|
-
}
|
|
21
|
-
if (error instanceof Error) {
|
|
22
|
-
throw error;
|
|
23
|
-
}
|
|
24
|
-
// Convert other errors to Response for ErrorBoundary with ok: false
|
|
25
|
-
const errorData = { ok: false, errors: [String(error)] };
|
|
26
|
-
throw new Response(JSON.stringify(errorData), {
|
|
27
|
-
status: 500,
|
|
28
|
-
headers: { 'Content-Type': 'application/json' },
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
// Handle other types of failures (interrupts, defects, etc.)
|
|
32
|
-
const errorData = { ok: false, errors: ['Internal server error'] };
|
|
33
|
-
throw new Response(JSON.stringify(errorData), {
|
|
34
|
-
status: 500,
|
|
35
|
-
headers: { 'Content-Type': 'application/json' },
|
|
36
|
-
});
|
|
37
|
-
},
|
|
38
|
-
onSuccess: matchHttpResponse()({
|
|
39
|
-
HttpResponseSuccess: ({ data: response }) => {
|
|
40
|
-
return { ok: true, data: response };
|
|
41
|
-
},
|
|
42
|
-
HttpResponseFailure: ({ cause }) => {
|
|
43
|
-
// Convert HttpResponseFailure to Response for ErrorBoundary with ok: false
|
|
44
|
-
const errorMessage = typeof cause === 'string' ? cause : String(cause);
|
|
45
|
-
const errorData = { ok: false, errors: [errorMessage] };
|
|
46
|
-
throw new Response(JSON.stringify(errorData), {
|
|
47
|
-
status: 500,
|
|
48
|
-
headers: { 'Content-Type': 'application/json' },
|
|
49
|
-
});
|
|
50
|
-
},
|
|
51
|
-
HttpResponseRedirect: ({ to, init = {} }) => {
|
|
52
|
-
redirect(to, init);
|
|
53
|
-
return { ok: false, errors: ['Redirecting...'] };
|
|
54
|
-
},
|
|
55
|
-
}),
|
|
56
|
-
}));
|
|
57
|
-
};
|
|
58
|
-
// Don't throw the Error requests, handle them in the normal UI. No ErrorBoundary
|
|
59
|
-
const withActionEffect = (self) => (args) => {
|
|
60
|
-
const runnable = pipe(self, Effect.provide(Logger.pretty), Effect.provideService(ActionArgsContext, args), Effect.tapError((cause) => Effect.logError('Action effect failed', cause)), Effect.match({
|
|
61
|
-
onFailure: (errors) => json({ ok: false, errors }, { status: 400 }),
|
|
62
|
-
onSuccess: matchHttpResponse()({
|
|
63
|
-
HttpResponseSuccess: ({ data: response }) => {
|
|
64
|
-
return { ok: true, response };
|
|
65
|
-
},
|
|
66
|
-
HttpResponseFailure: ({ cause }) => {
|
|
67
|
-
return json({ ok: false, errors: [String(cause)] }, { status: 400 });
|
|
68
|
-
},
|
|
69
|
-
HttpResponseRedirect: ({ to, init = {} }) => {
|
|
70
|
-
return redirect(to, init);
|
|
71
|
-
},
|
|
72
|
-
}),
|
|
73
|
-
}));
|
|
74
|
-
return runtime.runPromise(runnable);
|
|
75
|
-
};
|
|
76
|
-
return { withLoaderEffect, withActionEffect };
|
|
77
|
-
};
|