@ereo/client 0.1.6

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/README.md ADDED
@@ -0,0 +1,93 @@
1
+ # @ereo/client
2
+
3
+ Client-side runtime for the EreoJS framework. Includes islands architecture, client-side navigation, prefetching, forms, and error boundaries.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ bun add @ereo/client
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```typescript
14
+ import { initClient, Link, useLoaderData } from '@ereo/client';
15
+
16
+ // Initialize the client runtime
17
+ initClient();
18
+
19
+ // Use loader data in components
20
+ function UserProfile() {
21
+ const { user } = useLoaderData<{ user: { name: string } }>();
22
+ return <h1>{user.name}</h1>;
23
+ }
24
+
25
+ // Client-side navigation with prefetching
26
+ function Nav() {
27
+ return <Link to="/dashboard" prefetch="intent">Dashboard</Link>;
28
+ }
29
+ ```
30
+
31
+ ## Key Features
32
+
33
+ - **Islands Architecture** - Partial hydration with `createIsland` and `hydrateIslands`
34
+ - **Client Navigation** - SPA-like navigation with `navigate`, `goBack`, `goForward`
35
+ - **Prefetching** - Smart prefetching with `prefetch`, hover and viewport strategies
36
+ - **Data Hooks** - `useLoaderData`, `useActionData`, `useNavigation`, `useError`
37
+ - **Link Components** - `Link` and `NavLink` with active state detection
38
+ - **Forms** - Enhanced forms with `Form`, `useSubmit`, `useFetcher`
39
+ - **Error Boundaries** - Graceful error handling with `ErrorBoundary` and `RouteErrorBoundary`
40
+ - **Scroll Restoration** - Automatic scroll position management
41
+
42
+ ## Forms Example
43
+
44
+ ```tsx
45
+ import { Form, useSubmit, useNavigation } from '@ereo/client';
46
+
47
+ function ContactForm() {
48
+ const submit = useSubmit();
49
+ const navigation = useNavigation();
50
+ const isSubmitting = navigation.state === 'submitting';
51
+
52
+ return (
53
+ <Form method="post" action="/contact">
54
+ <input name="email" type="email" required />
55
+ <button disabled={isSubmitting}>
56
+ {isSubmitting ? 'Sending...' : 'Send'}
57
+ </button>
58
+ </Form>
59
+ );
60
+ }
61
+ ```
62
+
63
+ ## Islands
64
+
65
+ ```tsx
66
+ import { createIsland } from '@ereo/client';
67
+ import Chart from './Chart';
68
+
69
+ // Create an island wrapper for selective hydration
70
+ const InteractiveChart = createIsland(Chart, 'Chart');
71
+
72
+ // Use with hydration directives
73
+ function Page() {
74
+ return (
75
+ <div>
76
+ <h1>Dashboard</h1>
77
+ <InteractiveChart client:visible data={chartData} />
78
+ </div>
79
+ );
80
+ }
81
+ ```
82
+
83
+ ## Documentation
84
+
85
+ For full documentation, visit [https://ereojs.dev/docs/client](https://ereojs.dev/docs/client)
86
+
87
+ ## Part of EreoJS
88
+
89
+ This package is part of the [EreoJS](https://github.com/ereojs/ereo) monorepo - a modern full-stack framework built for Bun.
90
+
91
+ ## License
92
+
93
+ MIT
@@ -0,0 +1,215 @@
1
+ /**
2
+ * @ereo/client - Error Boundary Context and Recovery System
3
+ *
4
+ * Provides error boundaries, context, and recovery utilities for the EreoJS framework.
5
+ */
6
+ import { Component, type ReactNode, type ErrorInfo, type ComponentType } from 'react';
7
+ import type { RouteParams, ErrorConfig } from '@ereo/core';
8
+ import { ErrorContext, type ErrorContextValue } from './hooks';
9
+ /**
10
+ * Props for the ErrorBoundary component.
11
+ */
12
+ export interface ErrorBoundaryProps {
13
+ /** Fallback UI when error occurs */
14
+ fallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode);
15
+ /** Called when error is caught */
16
+ onError?: (error: Error, errorInfo: ErrorInfo) => void;
17
+ /** Children to render */
18
+ children: ReactNode;
19
+ }
20
+ /**
21
+ * State for the ErrorBoundary component.
22
+ */
23
+ interface ErrorBoundaryState {
24
+ error: Error | null;
25
+ errorInfo: ErrorInfo | null;
26
+ }
27
+ /**
28
+ * Route error response structure.
29
+ */
30
+ export interface RouteErrorResponse {
31
+ status: number;
32
+ statusText: string;
33
+ data: unknown;
34
+ internal?: boolean;
35
+ }
36
+ /**
37
+ * Props for RouteErrorBoundary component.
38
+ */
39
+ export interface RouteErrorBoundaryProps {
40
+ /** Route identifier */
41
+ routeId: string;
42
+ /** Error configuration from route */
43
+ errorConfig?: ErrorConfig;
44
+ /** Children to render */
45
+ children: ReactNode;
46
+ /** Fallback component from route module */
47
+ fallbackComponent?: ComponentType<{
48
+ error: Error;
49
+ params: RouteParams;
50
+ }>;
51
+ /** Route params */
52
+ params?: RouteParams;
53
+ }
54
+ /**
55
+ * Return type for useErrorBoundary hook.
56
+ */
57
+ export interface UseErrorBoundaryReturn {
58
+ error: Error | undefined;
59
+ reset: () => void;
60
+ showBoundary: (error: Error) => void;
61
+ }
62
+ export { ErrorContext, type ErrorContextValue };
63
+ /**
64
+ * Error boundary component that catches JavaScript errors in child components.
65
+ */
66
+ export declare class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
67
+ constructor(props: ErrorBoundaryProps);
68
+ /**
69
+ * Update state when an error is caught.
70
+ */
71
+ static getDerivedStateFromError(error: Error): Partial<ErrorBoundaryState>;
72
+ /**
73
+ * Log error information and call onError callback.
74
+ */
75
+ componentDidCatch(error: Error, errorInfo: ErrorInfo): void;
76
+ /**
77
+ * Reset the error state.
78
+ */
79
+ reset: () => void;
80
+ render(): ReactNode;
81
+ }
82
+ /**
83
+ * Hook to access error boundary functionality.
84
+ * Provides error state, reset function, and ability to programmatically trigger errors.
85
+ *
86
+ * @returns Object with error state and control functions
87
+ * @throws Error if used outside EreoProvider or ErrorProvider
88
+ *
89
+ * @example
90
+ * ```tsx
91
+ * function MyComponent() {
92
+ * const { error, reset, showBoundary } = useErrorBoundary();
93
+ *
94
+ * const handleAsyncError = async () => {
95
+ * try {
96
+ * await fetchData();
97
+ * } catch (e) {
98
+ * showBoundary(e as Error);
99
+ * }
100
+ * };
101
+ *
102
+ * return <button onClick={handleAsyncError}>Fetch</button>;
103
+ * }
104
+ * ```
105
+ */
106
+ export declare function useErrorBoundary(): UseErrorBoundaryReturn;
107
+ /**
108
+ * Hook to get the current route error.
109
+ * This is a simple implementation that accesses the error from context.
110
+ *
111
+ * @returns The current error or undefined
112
+ *
113
+ * @example
114
+ * ```tsx
115
+ * function ErrorPage() {
116
+ * const error = useRouteError();
117
+ *
118
+ * if (isRouteErrorResponse(error)) {
119
+ * return <div>HTTP Error: {error.status}</div>;
120
+ * }
121
+ *
122
+ * return <div>Unknown error occurred</div>;
123
+ * }
124
+ * ```
125
+ */
126
+ export declare function useRouteError(): unknown;
127
+ /**
128
+ * Error boundary specifically for route-level error handling.
129
+ * Integrates with route configuration and supports error recovery strategies.
130
+ */
131
+ export declare class RouteErrorBoundary extends Component<RouteErrorBoundaryProps, ErrorBoundaryState & {
132
+ retryCount: number;
133
+ }> {
134
+ constructor(props: RouteErrorBoundaryProps);
135
+ static getDerivedStateFromError(error: Error): Partial<ErrorBoundaryState>;
136
+ componentDidCatch(error: Error, errorInfo: ErrorInfo): void;
137
+ /**
138
+ * Reset the error state and optionally retry.
139
+ */
140
+ reset: () => void;
141
+ render(): ReactNode;
142
+ }
143
+ /**
144
+ * Type guard to check if an error is a RouteErrorResponse.
145
+ *
146
+ * @param error - The error to check
147
+ * @returns True if the error is a RouteErrorResponse
148
+ *
149
+ * @example
150
+ * ```tsx
151
+ * const error = useRouteError();
152
+ *
153
+ * if (isRouteErrorResponse(error)) {
154
+ * console.log(error.status); // e.g., 404
155
+ * console.log(error.statusText); // e.g., "Not Found"
156
+ * }
157
+ * ```
158
+ */
159
+ export declare function isRouteErrorResponse(error: unknown): error is RouteErrorResponse;
160
+ /**
161
+ * Create a RouteErrorResponse.
162
+ *
163
+ * @param status - HTTP status code
164
+ * @param statusText - HTTP status text
165
+ * @param data - Additional error data
166
+ * @returns A RouteErrorResponse object
167
+ *
168
+ * @example
169
+ * ```tsx
170
+ * throw createRouteErrorResponse(404, 'Not Found', { message: 'Page not found' });
171
+ * ```
172
+ */
173
+ export declare function createRouteErrorResponse(status: number, statusText: string, data?: unknown): RouteErrorResponse;
174
+ /**
175
+ * Wrap a component with an error boundary.
176
+ *
177
+ * @param WrappedComponent - The component to wrap
178
+ * @param errorBoundaryProps - Props to pass to the error boundary
179
+ * @returns A new component wrapped with an error boundary
180
+ *
181
+ * @example
182
+ * ```tsx
183
+ * const SafeComponent = withErrorBoundary(MyComponent, {
184
+ * fallback: <div>Something went wrong</div>,
185
+ * onError: (error) => console.error(error),
186
+ * });
187
+ * ```
188
+ */
189
+ export declare function withErrorBoundary<P extends object>(WrappedComponent: ComponentType<P>, errorBoundaryProps?: Omit<ErrorBoundaryProps, 'children'>): ComponentType<P>;
190
+ /**
191
+ * Create a custom error for route responses.
192
+ *
193
+ * @example
194
+ * ```tsx
195
+ * // In a loader function
196
+ * export async function loader({ params }: LoaderArgs) {
197
+ * const post = await getPost(params.id);
198
+ * if (!post) {
199
+ * throw new RouteError(404, 'Not Found', { message: 'Post not found' });
200
+ * }
201
+ * return { post };
202
+ * }
203
+ * ```
204
+ */
205
+ export declare class RouteError extends Error {
206
+ status: number;
207
+ statusText: string;
208
+ data: unknown;
209
+ constructor(status: number, statusText: string, data?: unknown);
210
+ /**
211
+ * Convert to RouteErrorResponse.
212
+ */
213
+ toResponse(): RouteErrorResponse;
214
+ }
215
+ //# sourceMappingURL=error-boundary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-boundary.d.ts","sourceRoot":"","sources":["../src/error-boundary.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAc,EACZ,SAAS,EAET,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,aAAa,EACnB,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAM/D;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,oCAAoC;IACpC,QAAQ,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,IAAI,KAAK,SAAS,CAAC,CAAC;IACxE,kCAAkC;IAClC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,KAAK,IAAI,CAAC;IACvD,yBAAyB;IACzB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;GAEG;AACH,UAAU,kBAAkB;IAC1B,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,SAAS,EAAE,SAAS,GAAG,IAAI,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,uBAAuB;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,qCAAqC;IACrC,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,yBAAyB;IACzB,QAAQ,EAAE,SAAS,CAAC;IACpB,2CAA2C;IAC3C,iBAAiB,CAAC,EAAE,aAAa,CAAC;QAAE,KAAK,EAAE,KAAK,CAAC;QAAC,MAAM,EAAE,WAAW,CAAA;KAAE,CAAC,CAAC;IACzE,mBAAmB;IACnB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,KAAK,GAAG,SAAS,CAAC;IACzB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,YAAY,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACtC;AAGD,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,CAAC;AAMhD;;GAEG;AACH,qBAAa,aAAc,SAAQ,SAAS,CAAC,kBAAkB,EAAE,kBAAkB,CAAC;gBACtE,KAAK,EAAE,kBAAkB;IAQrC;;OAEG;IACH,MAAM,CAAC,wBAAwB,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAI1E;;OAEG;IACH,iBAAiB,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,GAAG,IAAI;IAS3D;;OAEG;IACH,KAAK,QAAO,IAAI,CAKd;IAEF,MAAM,IAAI,SAAS;CAgDpB;AAMD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,gBAAgB,IAAI,sBAAsB,CAezD;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,aAAa,IAAI,OAAO,CAGvC;AAMD;;;GAGG;AACH,qBAAa,kBAAmB,SAAQ,SAAS,CAC/C,uBAAuB,EACvB,kBAAkB,GAAG;IAAE,UAAU,EAAE,MAAM,CAAA;CAAE,CAC5C;gBACa,KAAK,EAAE,uBAAuB;IAS1C,MAAM,CAAC,wBAAwB,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAI1E,iBAAiB,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,GAAG,IAAI;IA0B3D;;OAEG;IACH,KAAK,QAAO,IAAI,CAqBd;IAEF,MAAM,IAAI,SAAS;CA2DpB;AAMD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,kBAAkB,CAUhF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,IAAI,GAAE,OAAc,GACnB,kBAAkB,CAOpB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,MAAM,EAChD,gBAAgB,EAAE,aAAa,CAAC,CAAC,CAAC,EAClC,kBAAkB,CAAC,EAAE,IAAI,CAAC,kBAAkB,EAAE,UAAU,CAAC,GACxD,aAAa,CAAC,CAAC,CAAC,CAclB;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAAa,UAAW,SAAQ,KAAK;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,OAAO,CAAC;gBAEF,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO;IAQ9D;;OAEG;IACH,UAAU,IAAI,kBAAkB;CAOjC"}