@zap-js/client 0.0.2 → 0.0.4
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 +310 -24
- package/bin/zap +0 -0
- package/bin/zap-codegen +0 -0
- package/dist/cli/commands/build.d.ts +11 -0
- package/dist/cli/commands/build.js +282 -0
- package/dist/cli/commands/codegen.d.ts +8 -0
- package/dist/cli/commands/codegen.js +95 -0
- package/dist/cli/commands/dev.d.ts +20 -0
- package/dist/cli/commands/dev.js +78 -0
- package/dist/cli/commands/new.d.ts +9 -0
- package/dist/cli/commands/new.js +307 -0
- package/dist/cli/commands/routes-old.d.ts +9 -0
- package/dist/cli/commands/routes-old.js +106 -0
- package/dist/cli/commands/routes.d.ts +11 -0
- package/dist/cli/commands/routes.js +280 -0
- package/dist/cli/commands/serve.d.ts +17 -0
- package/dist/cli/commands/serve.js +386 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +76 -0
- package/dist/cli/utils/index.d.ts +2 -0
- package/dist/cli/utils/index.js +2 -0
- package/dist/cli/utils/logger.d.ts +84 -0
- package/dist/cli/utils/logger.js +181 -0
- package/dist/cli/utils/port-finder.d.ts +8 -0
- package/dist/cli/utils/port-finder.js +48 -0
- package/dist/dev-server/codegen-runner.d.ts +41 -0
- package/dist/dev-server/codegen-runner.js +172 -0
- package/dist/dev-server/hot-reload.d.ts +72 -0
- package/dist/dev-server/hot-reload.js +280 -0
- package/dist/dev-server/index.d.ts +8 -0
- package/dist/dev-server/index.js +8 -0
- package/dist/dev-server/route-scanner.d.ts +71 -0
- package/dist/dev-server/route-scanner.js +114 -0
- package/dist/dev-server/rust-builder.d.ts +66 -0
- package/dist/dev-server/rust-builder.js +286 -0
- package/dist/dev-server/server.d.ts +147 -0
- package/dist/dev-server/server.js +658 -0
- package/dist/dev-server/vite-proxy.d.ts +56 -0
- package/dist/dev-server/vite-proxy.js +212 -0
- package/dist/dev-server/watcher.d.ts +48 -0
- package/dist/dev-server/watcher.js +127 -0
- package/dist/router/codegen-enhanced.d.ts +5 -0
- package/dist/router/codegen-enhanced.js +275 -0
- package/dist/router/codegen.d.ts +17 -0
- package/dist/router/codegen.js +654 -0
- package/dist/router/index.d.ts +16 -0
- package/dist/router/index.js +19 -0
- package/dist/router/scanner.d.ts +86 -0
- package/dist/router/scanner.js +689 -0
- package/dist/router/ssg.d.ts +115 -0
- package/dist/router/ssg.js +202 -0
- package/dist/router/types.d.ts +124 -0
- package/dist/router/types.js +9 -0
- package/dist/router/watch.d.ts +38 -0
- package/dist/router/watch.js +135 -0
- package/dist/runtime/csrf.d.ts +146 -0
- package/dist/runtime/csrf.js +166 -0
- package/dist/runtime/error-boundary.d.ts +129 -0
- package/dist/runtime/error-boundary.js +287 -0
- package/dist/runtime/hooks.d.ts +83 -0
- package/dist/runtime/hooks.js +96 -0
- package/dist/runtime/index.d.ts +229 -0
- package/dist/runtime/index.js +449 -0
- package/dist/runtime/ipc-client.d.ts +144 -0
- package/dist/runtime/ipc-client.js +621 -0
- package/dist/runtime/logger.d.ts +71 -0
- package/dist/runtime/logger.js +164 -0
- package/dist/runtime/middleware.d.ts +66 -0
- package/dist/runtime/middleware.js +114 -0
- package/dist/runtime/process-manager.d.ts +51 -0
- package/dist/runtime/process-manager.js +207 -0
- package/dist/runtime/router-simple.d.ts +98 -0
- package/dist/runtime/router-simple.js +330 -0
- package/dist/runtime/router.d.ts +103 -0
- package/dist/runtime/router.js +435 -0
- package/dist/runtime/rpc-client.d.ts +35 -0
- package/dist/runtime/rpc-client.js +140 -0
- package/dist/runtime/streaming-utils.d.ts +86 -0
- package/dist/runtime/streaming-utils.js +150 -0
- package/dist/runtime/types.d.ts +465 -0
- package/dist/runtime/types.js +60 -0
- package/dist/runtime/websockets-utils.d.ts +50 -0
- package/dist/runtime/websockets-utils.js +92 -0
- package/package.json +30 -20
- package/index.js +0 -29
- package/internal/cli/package.json +0 -46
- package/internal/cli/tsconfig.tsbuildinfo +0 -1
- package/internal/dev-server/node_modules/ora/index.d.ts +0 -332
- package/internal/dev-server/node_modules/ora/index.js +0 -416
- package/internal/dev-server/node_modules/ora/license +0 -9
- package/internal/dev-server/node_modules/ora/node_modules/string-width/index.d.ts +0 -36
- package/internal/dev-server/node_modules/ora/node_modules/string-width/index.js +0 -65
- package/internal/dev-server/node_modules/ora/node_modules/string-width/license +0 -9
- package/internal/dev-server/node_modules/ora/node_modules/string-width/node_modules/emoji-regex/LICENSE-MIT.txt +0 -20
- package/internal/dev-server/node_modules/ora/node_modules/string-width/node_modules/emoji-regex/README.md +0 -107
- package/internal/dev-server/node_modules/ora/node_modules/string-width/node_modules/emoji-regex/index.d.ts +0 -3
- package/internal/dev-server/node_modules/ora/node_modules/string-width/node_modules/emoji-regex/index.js +0 -4
- package/internal/dev-server/node_modules/ora/node_modules/string-width/node_modules/emoji-regex/index.mjs +0 -4
- package/internal/dev-server/node_modules/ora/node_modules/string-width/node_modules/emoji-regex/package.json +0 -46
- package/internal/dev-server/node_modules/ora/node_modules/string-width/package.json +0 -60
- package/internal/dev-server/node_modules/ora/node_modules/string-width/readme.md +0 -62
- package/internal/dev-server/node_modules/ora/package.json +0 -66
- package/internal/dev-server/node_modules/ora/readme.md +0 -325
- package/internal/dev-server/package.json +0 -41
- package/internal/router/package.json +0 -28
- package/internal/runtime/package.json +0 -41
- package/internal/runtime/src/error-boundary.tsx +0 -476
- package/internal/runtime/src/router-simple.tsx +0 -640
- package/internal/runtime/src/router.tsx +0 -771
- package/internal/runtime/tsconfig.tsbuildinfo +0 -1
- package/src/errors.js +0 -33
- package/src/logger.js +0 -10
- package/src/middleware.js +0 -32
- package/src/router.js +0 -41
- package/src/types.js +0 -39
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* ZapJS Error Boundary
|
|
4
|
+
*
|
|
5
|
+
* TanStack Router style error boundary with explicit errorComponent prop.
|
|
6
|
+
* Provides structured error handling with server error correlation.
|
|
7
|
+
*/
|
|
8
|
+
import { Component, createContext } from 'react';
|
|
9
|
+
/**
|
|
10
|
+
* Context for accessing error state in error components
|
|
11
|
+
*/
|
|
12
|
+
export const RouteErrorContext = createContext(null);
|
|
13
|
+
/**
|
|
14
|
+
* Error Boundary with TanStack Router style errorComponent prop
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```tsx
|
|
18
|
+
* // Route file: routes/users.$id.tsx
|
|
19
|
+
* export default function UserPage() {
|
|
20
|
+
* // ... component
|
|
21
|
+
* }
|
|
22
|
+
*
|
|
23
|
+
* export function errorComponent({ error, reset }: ErrorComponentProps) {
|
|
24
|
+
* return (
|
|
25
|
+
* <div>
|
|
26
|
+
* <h1>Failed to load user</h1>
|
|
27
|
+
* <p>{error.message}</p>
|
|
28
|
+
* {error.digest && <small>Error ID: {error.digest}</small>}
|
|
29
|
+
* <button onClick={reset}>Try Again</button>
|
|
30
|
+
* </div>
|
|
31
|
+
* );
|
|
32
|
+
* }
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export class ErrorBoundary extends Component {
|
|
36
|
+
constructor(props) {
|
|
37
|
+
super(props);
|
|
38
|
+
/**
|
|
39
|
+
* Reset the error boundary state
|
|
40
|
+
*/
|
|
41
|
+
this.reset = () => {
|
|
42
|
+
this.setState({ hasError: false, error: null });
|
|
43
|
+
};
|
|
44
|
+
this.state = { hasError: false, error: null };
|
|
45
|
+
}
|
|
46
|
+
static getDerivedStateFromError(error) {
|
|
47
|
+
// Convert Error to ZapRouteError
|
|
48
|
+
const zapError = normalizeError(error);
|
|
49
|
+
return { hasError: true, error: zapError };
|
|
50
|
+
}
|
|
51
|
+
componentDidCatch(error, errorInfo) {
|
|
52
|
+
const zapError = normalizeError(error);
|
|
53
|
+
// Call onError callback if provided
|
|
54
|
+
if (this.props.onError) {
|
|
55
|
+
this.props.onError(zapError, errorInfo);
|
|
56
|
+
}
|
|
57
|
+
// Log error in development
|
|
58
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
59
|
+
console.error('[ErrorBoundary] Caught error:', error);
|
|
60
|
+
console.error('[ErrorBoundary] Component stack:', errorInfo.componentStack);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
componentDidUpdate(prevProps) {
|
|
64
|
+
// Reset error state when resetKeys change
|
|
65
|
+
if (this.state.hasError && this.props.resetKeys) {
|
|
66
|
+
const prevKeys = prevProps.resetKeys || [];
|
|
67
|
+
const currentKeys = this.props.resetKeys;
|
|
68
|
+
const hasChanged = currentKeys.some((key, index) => key !== prevKeys[index]);
|
|
69
|
+
if (hasChanged) {
|
|
70
|
+
this.reset();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
render() {
|
|
75
|
+
if (this.state.hasError && this.state.error) {
|
|
76
|
+
const { errorComponent: CustomErrorComponent, fallback } = this.props;
|
|
77
|
+
const contextValue = {
|
|
78
|
+
error: this.state.error,
|
|
79
|
+
reset: this.reset,
|
|
80
|
+
};
|
|
81
|
+
// Use custom error component if provided (TanStack style)
|
|
82
|
+
if (CustomErrorComponent) {
|
|
83
|
+
return (_jsx(RouteErrorContext.Provider, { value: contextValue, children: _jsx(CustomErrorComponent, { error: this.state.error, reset: this.reset }) }));
|
|
84
|
+
}
|
|
85
|
+
// Use fallback if provided
|
|
86
|
+
if (fallback) {
|
|
87
|
+
return (_jsx(RouteErrorContext.Provider, { value: contextValue, children: fallback }));
|
|
88
|
+
}
|
|
89
|
+
// Use default error component
|
|
90
|
+
return (_jsx(RouteErrorContext.Provider, { value: contextValue, children: _jsx(DefaultErrorComponent, { error: this.state.error, reset: this.reset }) }));
|
|
91
|
+
}
|
|
92
|
+
return this.props.children;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// ============================================================================
|
|
96
|
+
// Default Error Component
|
|
97
|
+
// ============================================================================
|
|
98
|
+
/**
|
|
99
|
+
* Default error fallback UI
|
|
100
|
+
*
|
|
101
|
+
* Shows:
|
|
102
|
+
* - Error message
|
|
103
|
+
* - Error code (if available)
|
|
104
|
+
* - Error digest (for server errors)
|
|
105
|
+
* - Stack trace (development only)
|
|
106
|
+
* - "Try Again" button
|
|
107
|
+
*/
|
|
108
|
+
export function DefaultErrorComponent({ error, reset }) {
|
|
109
|
+
const isDev = process.env.NODE_ENV !== 'production';
|
|
110
|
+
return (_jsx("div", { style: styles.container, children: _jsxs("div", { style: styles.content, children: [_jsx("div", { style: styles.icon, children: _jsxs("svg", { width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("circle", { cx: "12", cy: "12", r: "10" }), _jsx("line", { x1: "12", y1: "8", x2: "12", y2: "12" }), _jsx("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })] }) }), _jsx("h1", { style: styles.title, children: "Something went wrong" }), _jsx("p", { style: styles.message, children: error.message }), _jsxs("div", { style: styles.metadata, children: [error.code && (_jsx("span", { style: styles.badge, children: error.code })), error.status && (_jsx("span", { style: styles.badge, children: error.status }))] }), error.digest && (_jsxs("p", { style: styles.digest, children: ["Error ID: ", _jsx("code", { style: styles.code, children: error.digest })] })), isDev && error.stack && (_jsxs("details", { style: styles.details, children: [_jsx("summary", { style: styles.summary, children: "Stack Trace" }), _jsx("pre", { style: styles.stackTrace, children: error.stack })] })), _jsx("button", { onClick: reset, style: styles.button, children: "Try Again" })] }) }));
|
|
111
|
+
}
|
|
112
|
+
// ============================================================================
|
|
113
|
+
// Styles
|
|
114
|
+
// ============================================================================
|
|
115
|
+
const styles = {
|
|
116
|
+
container: {
|
|
117
|
+
display: 'flex',
|
|
118
|
+
alignItems: 'center',
|
|
119
|
+
justifyContent: 'center',
|
|
120
|
+
minHeight: '100vh',
|
|
121
|
+
padding: '20px',
|
|
122
|
+
fontFamily: 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
|
|
123
|
+
backgroundColor: '#fafafa',
|
|
124
|
+
color: '#1a1a1a',
|
|
125
|
+
},
|
|
126
|
+
content: {
|
|
127
|
+
maxWidth: '500px',
|
|
128
|
+
width: '100%',
|
|
129
|
+
textAlign: 'center',
|
|
130
|
+
padding: '40px',
|
|
131
|
+
backgroundColor: 'white',
|
|
132
|
+
borderRadius: '12px',
|
|
133
|
+
boxShadow: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
|
|
134
|
+
},
|
|
135
|
+
icon: {
|
|
136
|
+
marginBottom: '24px',
|
|
137
|
+
color: '#ef4444',
|
|
138
|
+
},
|
|
139
|
+
title: {
|
|
140
|
+
margin: '0 0 12px 0',
|
|
141
|
+
fontSize: '24px',
|
|
142
|
+
fontWeight: 600,
|
|
143
|
+
},
|
|
144
|
+
message: {
|
|
145
|
+
margin: '0 0 16px 0',
|
|
146
|
+
fontSize: '16px',
|
|
147
|
+
color: '#666',
|
|
148
|
+
lineHeight: 1.5,
|
|
149
|
+
},
|
|
150
|
+
metadata: {
|
|
151
|
+
display: 'flex',
|
|
152
|
+
gap: '8px',
|
|
153
|
+
justifyContent: 'center',
|
|
154
|
+
marginBottom: '16px',
|
|
155
|
+
},
|
|
156
|
+
badge: {
|
|
157
|
+
display: 'inline-block',
|
|
158
|
+
padding: '4px 8px',
|
|
159
|
+
fontSize: '12px',
|
|
160
|
+
fontWeight: 500,
|
|
161
|
+
backgroundColor: '#f3f4f6',
|
|
162
|
+
borderRadius: '4px',
|
|
163
|
+
color: '#4b5563',
|
|
164
|
+
},
|
|
165
|
+
digest: {
|
|
166
|
+
margin: '0 0 20px 0',
|
|
167
|
+
fontSize: '13px',
|
|
168
|
+
color: '#888',
|
|
169
|
+
},
|
|
170
|
+
code: {
|
|
171
|
+
fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace',
|
|
172
|
+
backgroundColor: '#f3f4f6',
|
|
173
|
+
padding: '2px 6px',
|
|
174
|
+
borderRadius: '4px',
|
|
175
|
+
fontSize: '12px',
|
|
176
|
+
},
|
|
177
|
+
details: {
|
|
178
|
+
textAlign: 'left',
|
|
179
|
+
marginBottom: '20px',
|
|
180
|
+
},
|
|
181
|
+
summary: {
|
|
182
|
+
cursor: 'pointer',
|
|
183
|
+
fontSize: '14px',
|
|
184
|
+
color: '#666',
|
|
185
|
+
marginBottom: '8px',
|
|
186
|
+
},
|
|
187
|
+
stackTrace: {
|
|
188
|
+
fontSize: '12px',
|
|
189
|
+
fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace',
|
|
190
|
+
backgroundColor: '#1a1a1a',
|
|
191
|
+
color: '#f5f5f5',
|
|
192
|
+
padding: '16px',
|
|
193
|
+
borderRadius: '8px',
|
|
194
|
+
overflow: 'auto',
|
|
195
|
+
maxHeight: '200px',
|
|
196
|
+
margin: 0,
|
|
197
|
+
whiteSpace: 'pre-wrap',
|
|
198
|
+
wordBreak: 'break-word',
|
|
199
|
+
},
|
|
200
|
+
button: {
|
|
201
|
+
padding: '12px 24px',
|
|
202
|
+
fontSize: '14px',
|
|
203
|
+
fontWeight: 500,
|
|
204
|
+
color: 'white',
|
|
205
|
+
backgroundColor: '#3b82f6',
|
|
206
|
+
border: 'none',
|
|
207
|
+
borderRadius: '8px',
|
|
208
|
+
cursor: 'pointer',
|
|
209
|
+
transition: 'background-color 0.2s',
|
|
210
|
+
},
|
|
211
|
+
};
|
|
212
|
+
// ============================================================================
|
|
213
|
+
// Helper Functions
|
|
214
|
+
// ============================================================================
|
|
215
|
+
/**
|
|
216
|
+
* Normalize any error to ZapRouteError format
|
|
217
|
+
*/
|
|
218
|
+
function normalizeError(error) {
|
|
219
|
+
// Already a ZapRouteError
|
|
220
|
+
if (isZapRouteError(error)) {
|
|
221
|
+
return error;
|
|
222
|
+
}
|
|
223
|
+
// Standard Error
|
|
224
|
+
if (error instanceof Error) {
|
|
225
|
+
return {
|
|
226
|
+
message: error.message,
|
|
227
|
+
stack: error.stack,
|
|
228
|
+
// Check for extended properties from server errors
|
|
229
|
+
code: error.code,
|
|
230
|
+
status: error.status,
|
|
231
|
+
digest: error.digest,
|
|
232
|
+
details: error.details,
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
// String error
|
|
236
|
+
if (typeof error === 'string') {
|
|
237
|
+
return { message: error };
|
|
238
|
+
}
|
|
239
|
+
// Unknown error type
|
|
240
|
+
return { message: 'An unknown error occurred' };
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Type guard for ZapRouteError
|
|
244
|
+
*/
|
|
245
|
+
function isZapRouteError(error) {
|
|
246
|
+
return (typeof error === 'object' &&
|
|
247
|
+
error !== null &&
|
|
248
|
+
'message' in error &&
|
|
249
|
+
typeof error.message === 'string');
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Create a ZapRouteError from server error response
|
|
253
|
+
*/
|
|
254
|
+
export function createRouteError(options) {
|
|
255
|
+
return {
|
|
256
|
+
message: options.message,
|
|
257
|
+
code: options.code,
|
|
258
|
+
status: options.status,
|
|
259
|
+
digest: options.digest,
|
|
260
|
+
details: options.details,
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Wrap an Error with ZapRouteError metadata
|
|
265
|
+
*/
|
|
266
|
+
export class ZapError extends Error {
|
|
267
|
+
constructor(message, options) {
|
|
268
|
+
super(message);
|
|
269
|
+
this.name = 'ZapError';
|
|
270
|
+
this.code = options?.code;
|
|
271
|
+
this.status = options?.status;
|
|
272
|
+
this.digest = options?.digest;
|
|
273
|
+
this.details = options?.details;
|
|
274
|
+
// Maintain proper prototype chain
|
|
275
|
+
Object.setPrototypeOf(this, ZapError.prototype);
|
|
276
|
+
}
|
|
277
|
+
toRouteError() {
|
|
278
|
+
return {
|
|
279
|
+
message: this.message,
|
|
280
|
+
stack: this.stack,
|
|
281
|
+
code: this.code,
|
|
282
|
+
status: this.status,
|
|
283
|
+
digest: this.digest,
|
|
284
|
+
details: this.details,
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ZapJS React Hooks
|
|
3
|
+
*
|
|
4
|
+
* Custom hooks for error handling and route state management.
|
|
5
|
+
* TanStack Router style API.
|
|
6
|
+
*/
|
|
7
|
+
import { type ZapRouteError } from './error-boundary.js';
|
|
8
|
+
/**
|
|
9
|
+
* Access the current route error state
|
|
10
|
+
*
|
|
11
|
+
* Must be used within an errorComponent rendered by ErrorBoundary.
|
|
12
|
+
* TanStack Router style hook for error component access.
|
|
13
|
+
*
|
|
14
|
+
* @throws Error if used outside of errorComponent context
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```tsx
|
|
18
|
+
* // In your errorComponent
|
|
19
|
+
* export function errorComponent() {
|
|
20
|
+
* const { error, reset } = useRouteError();
|
|
21
|
+
*
|
|
22
|
+
* return (
|
|
23
|
+
* <div>
|
|
24
|
+
* <h1>Error: {error.message}</h1>
|
|
25
|
+
* {error.code && <p>Code: {error.code}</p>}
|
|
26
|
+
* {error.digest && <p>ID: {error.digest}</p>}
|
|
27
|
+
* <button onClick={reset}>Retry</button>
|
|
28
|
+
* </div>
|
|
29
|
+
* );
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export declare function useRouteError(): {
|
|
34
|
+
error: ZapRouteError;
|
|
35
|
+
reset: () => void;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Check if currently in an error state
|
|
39
|
+
*
|
|
40
|
+
* Safe to use anywhere - returns false if not in error context.
|
|
41
|
+
* Useful for conditional rendering based on error state.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```tsx
|
|
45
|
+
* function MyComponent() {
|
|
46
|
+
* const isError = useIsErrorState();
|
|
47
|
+
*
|
|
48
|
+
* if (isError) {
|
|
49
|
+
* return <div>We're showing an error</div>;
|
|
50
|
+
* }
|
|
51
|
+
*
|
|
52
|
+
* return <div>Normal content</div>;
|
|
53
|
+
* }
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
export declare function useIsErrorState(): boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Get error state if available, otherwise null
|
|
59
|
+
*
|
|
60
|
+
* Safe version of useRouteError that doesn't throw.
|
|
61
|
+
* Useful when you want to optionally access error state.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```tsx
|
|
65
|
+
* function MyComponent() {
|
|
66
|
+
* const errorState = useErrorState();
|
|
67
|
+
*
|
|
68
|
+
* return (
|
|
69
|
+
* <div>
|
|
70
|
+
* {errorState && (
|
|
71
|
+
* <Banner type="error">{errorState.error.message}</Banner>
|
|
72
|
+
* )}
|
|
73
|
+
* <MainContent />
|
|
74
|
+
* </div>
|
|
75
|
+
* );
|
|
76
|
+
* }
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export declare function useErrorState(): {
|
|
80
|
+
error: ZapRouteError;
|
|
81
|
+
reset: () => void;
|
|
82
|
+
} | null;
|
|
83
|
+
export type { ZapRouteError, ErrorComponentProps, ErrorComponent } from './error-boundary.js';
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ZapJS React Hooks
|
|
3
|
+
*
|
|
4
|
+
* Custom hooks for error handling and route state management.
|
|
5
|
+
* TanStack Router style API.
|
|
6
|
+
*/
|
|
7
|
+
import { useContext } from 'react';
|
|
8
|
+
import { RouteErrorContext } from './error-boundary.js';
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// Error Handling Hooks
|
|
11
|
+
// ============================================================================
|
|
12
|
+
/**
|
|
13
|
+
* Access the current route error state
|
|
14
|
+
*
|
|
15
|
+
* Must be used within an errorComponent rendered by ErrorBoundary.
|
|
16
|
+
* TanStack Router style hook for error component access.
|
|
17
|
+
*
|
|
18
|
+
* @throws Error if used outside of errorComponent context
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```tsx
|
|
22
|
+
* // In your errorComponent
|
|
23
|
+
* export function errorComponent() {
|
|
24
|
+
* const { error, reset } = useRouteError();
|
|
25
|
+
*
|
|
26
|
+
* return (
|
|
27
|
+
* <div>
|
|
28
|
+
* <h1>Error: {error.message}</h1>
|
|
29
|
+
* {error.code && <p>Code: {error.code}</p>}
|
|
30
|
+
* {error.digest && <p>ID: {error.digest}</p>}
|
|
31
|
+
* <button onClick={reset}>Retry</button>
|
|
32
|
+
* </div>
|
|
33
|
+
* );
|
|
34
|
+
* }
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export function useRouteError() {
|
|
38
|
+
const context = useContext(RouteErrorContext);
|
|
39
|
+
if (!context || !context.error) {
|
|
40
|
+
throw new Error('useRouteError must be used within an errorComponent. ' +
|
|
41
|
+
'Make sure you are using this hook inside a component passed to ErrorBoundary as errorComponent prop.');
|
|
42
|
+
}
|
|
43
|
+
return { error: context.error, reset: context.reset };
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Check if currently in an error state
|
|
47
|
+
*
|
|
48
|
+
* Safe to use anywhere - returns false if not in error context.
|
|
49
|
+
* Useful for conditional rendering based on error state.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```tsx
|
|
53
|
+
* function MyComponent() {
|
|
54
|
+
* const isError = useIsErrorState();
|
|
55
|
+
*
|
|
56
|
+
* if (isError) {
|
|
57
|
+
* return <div>We're showing an error</div>;
|
|
58
|
+
* }
|
|
59
|
+
*
|
|
60
|
+
* return <div>Normal content</div>;
|
|
61
|
+
* }
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
export function useIsErrorState() {
|
|
65
|
+
const context = useContext(RouteErrorContext);
|
|
66
|
+
return context !== null && context.error !== null;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Get error state if available, otherwise null
|
|
70
|
+
*
|
|
71
|
+
* Safe version of useRouteError that doesn't throw.
|
|
72
|
+
* Useful when you want to optionally access error state.
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```tsx
|
|
76
|
+
* function MyComponent() {
|
|
77
|
+
* const errorState = useErrorState();
|
|
78
|
+
*
|
|
79
|
+
* return (
|
|
80
|
+
* <div>
|
|
81
|
+
* {errorState && (
|
|
82
|
+
* <Banner type="error">{errorState.error.message}</Banner>
|
|
83
|
+
* )}
|
|
84
|
+
* <MainContent />
|
|
85
|
+
* </div>
|
|
86
|
+
* );
|
|
87
|
+
* }
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
export function useErrorState() {
|
|
91
|
+
const context = useContext(RouteErrorContext);
|
|
92
|
+
if (!context || !context.error) {
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
return { error: context.error, reset: context.reset };
|
|
96
|
+
}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import type { Handler, FileRouteConfig, ZapOptions } from "./types.js";
|
|
2
|
+
export type { Handler, ZapRequest, ZapHandlerResponse, ZapConfig, RouteConfig, MiddlewareConfig, StaticFileConfig, StaticFileOptions, FileRouteConfig, ZapOptions, IpcMessage, InvokeHandlerMessage, HandlerResponseMessage, ErrorMessage, HealthCheckMessage, HealthCheckResponseMessage, HttpMethod, InternalHandlerFunction, RpcMessage, RpcCallMessage, RpcResponseMessage, RpcErrorMessage, PendingRequest, SecurityConfig, SecurityHeadersConfig, HstsConfig, RateLimitConfig, CorsConfig, ObservabilityConfig, StreamChunk, StreamingHandler, AnyHandler, StreamStartMessage, StreamChunkMessage, StreamEndMessage, StreamMessage, WsConnection, WsHandler, WsConnectMessage, WsMessageMessage, WsCloseMessage, WsSendMessage, WsMessage, } from "./types.js";
|
|
3
|
+
export { isInvokeHandlerMessage, isHandlerResponseMessage, isErrorMessage, isHealthCheckMessage, isHealthCheckResponseMessage, isRpcResponseMessage, isRpcErrorMessage, isAsyncIterable, } from "./types.js";
|
|
4
|
+
export { ProcessManager } from "./process-manager.js";
|
|
5
|
+
export { IpcServer, IpcClient } from "./ipc-client.js";
|
|
6
|
+
export { ErrorBoundary, DefaultErrorComponent, RouteErrorContext, createRouteError, ZapError, type ZapRouteError, type ErrorComponentProps, type ErrorComponent, } from "./error-boundary.js";
|
|
7
|
+
export { useRouteError, useIsErrorState, useErrorState, } from "./hooks.js";
|
|
8
|
+
export { Logger, logger, type LogContext, type LogLevel, type ChildLogger } from "./logger.js";
|
|
9
|
+
export { RouterProvider, useRouter, useParams, usePathname, useSearchParams, useRouteMatch, useIsPending, Link, NavLink, Outlet, Redirect, type Router, type RouteDefinition, type RouteMatch, type RouterState, type NavigateOptions, type LinkProps, } from "./router.js";
|
|
10
|
+
export { getCsrfToken, useCsrfToken, createCsrfFetch, CsrfTokenInput, CsrfForm, addCsrfToFormData, getCsrfHeaders, type CsrfConfig, type CsrfTokenInputProps, type CsrfFormProps, } from "./csrf.js";
|
|
11
|
+
export { rpcCall, } from "./rpc-client.js";
|
|
12
|
+
/**
|
|
13
|
+
* Zap - Ultra-fast HTTP server for Node.js and Bun
|
|
14
|
+
*
|
|
15
|
+
* This is the main API entry point. It manages:
|
|
16
|
+
* 1. Route registration from TypeScript
|
|
17
|
+
* 2. Spawning and managing the Rust binary process
|
|
18
|
+
* 3. IPC communication between TypeScript handlers and Rust server
|
|
19
|
+
*
|
|
20
|
+
* Usage:
|
|
21
|
+
* ```
|
|
22
|
+
* const app = new Zap({ port: 3000 });
|
|
23
|
+
* app.get('/', () => ({ message: 'Hello!' }));
|
|
24
|
+
* app.post('/api/data', (req) => ({ received: req.body }));
|
|
25
|
+
* await app.listen();
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare class Zap {
|
|
29
|
+
private processManager;
|
|
30
|
+
private ipcServer;
|
|
31
|
+
private handlers;
|
|
32
|
+
private routes;
|
|
33
|
+
private staticFiles;
|
|
34
|
+
private port;
|
|
35
|
+
private hostname;
|
|
36
|
+
private logLevel;
|
|
37
|
+
private healthCheckPath;
|
|
38
|
+
private metricsPath;
|
|
39
|
+
private enableCors;
|
|
40
|
+
private enableLogging;
|
|
41
|
+
private enableCompression;
|
|
42
|
+
private fileRoutingEnabled;
|
|
43
|
+
private fileRoutingConfig;
|
|
44
|
+
constructor(options?: ZapOptions);
|
|
45
|
+
/**
|
|
46
|
+
* Set the server port
|
|
47
|
+
*/
|
|
48
|
+
setPort(port: number): this;
|
|
49
|
+
/**
|
|
50
|
+
* Set the server hostname
|
|
51
|
+
*/
|
|
52
|
+
setHostname(hostname: string): this;
|
|
53
|
+
/**
|
|
54
|
+
* Enable CORS middleware
|
|
55
|
+
*/
|
|
56
|
+
cors(): this;
|
|
57
|
+
/**
|
|
58
|
+
* Enable request logging middleware
|
|
59
|
+
*/
|
|
60
|
+
logging(): this;
|
|
61
|
+
/**
|
|
62
|
+
* Enable response compression middleware
|
|
63
|
+
*/
|
|
64
|
+
compression(): this;
|
|
65
|
+
/**
|
|
66
|
+
* Set custom health check path
|
|
67
|
+
*/
|
|
68
|
+
healthCheck(path: string): this;
|
|
69
|
+
/**
|
|
70
|
+
* Set metrics endpoint path
|
|
71
|
+
*/
|
|
72
|
+
metrics(path: string): this;
|
|
73
|
+
/**
|
|
74
|
+
* Enable file-based routing (TanStack style)
|
|
75
|
+
*
|
|
76
|
+
* Automatically registers routes from the routes/ directory
|
|
77
|
+
* using the generated route manifest from @zapjs/router
|
|
78
|
+
*/
|
|
79
|
+
useFileRouting(config?: FileRouteConfig): this;
|
|
80
|
+
/**
|
|
81
|
+
* Register a GET route
|
|
82
|
+
*/
|
|
83
|
+
get<TParams extends Record<string, string> = Record<string, string>>(path: string, handler: Handler<TParams>): this;
|
|
84
|
+
/**
|
|
85
|
+
* Register a POST route
|
|
86
|
+
*/
|
|
87
|
+
post<TParams extends Record<string, string> = Record<string, string>>(path: string, handler: Handler<TParams>): this;
|
|
88
|
+
/**
|
|
89
|
+
* Register a PUT route
|
|
90
|
+
*/
|
|
91
|
+
put<TParams extends Record<string, string> = Record<string, string>>(path: string, handler: Handler<TParams>): this;
|
|
92
|
+
/**
|
|
93
|
+
* Register a DELETE route
|
|
94
|
+
*/
|
|
95
|
+
delete<TParams extends Record<string, string> = Record<string, string>>(path: string, handler: Handler<TParams>): this;
|
|
96
|
+
/**
|
|
97
|
+
* Register a PATCH route
|
|
98
|
+
*/
|
|
99
|
+
patch<TParams extends Record<string, string> = Record<string, string>>(path: string, handler: Handler<TParams>): this;
|
|
100
|
+
/**
|
|
101
|
+
* Register a HEAD route
|
|
102
|
+
*/
|
|
103
|
+
head<TParams extends Record<string, string> = Record<string, string>>(path: string, handler: Handler<TParams>): this;
|
|
104
|
+
/**
|
|
105
|
+
* Convenience method for GET routes that return JSON
|
|
106
|
+
*/
|
|
107
|
+
getJson<TParams extends Record<string, string> = Record<string, string>>(path: string, handler: Handler<TParams>): this;
|
|
108
|
+
/**
|
|
109
|
+
* Convenience method for POST routes that return JSON
|
|
110
|
+
*/
|
|
111
|
+
postJson<TParams extends Record<string, string> = Record<string, string>>(path: string, handler: Handler<TParams>): this;
|
|
112
|
+
/**
|
|
113
|
+
* Register static file serving
|
|
114
|
+
*/
|
|
115
|
+
static(prefix: string, directory: string): this;
|
|
116
|
+
/**
|
|
117
|
+
* Register a route with a handler (internal)
|
|
118
|
+
*/
|
|
119
|
+
private registerRoute;
|
|
120
|
+
/**
|
|
121
|
+
* Start the server
|
|
122
|
+
*/
|
|
123
|
+
listen(port?: number): Promise<void>;
|
|
124
|
+
/**
|
|
125
|
+
* Close the server gracefully
|
|
126
|
+
*/
|
|
127
|
+
close(): Promise<void>;
|
|
128
|
+
/**
|
|
129
|
+
* Check if server is running
|
|
130
|
+
*/
|
|
131
|
+
isRunning(): boolean;
|
|
132
|
+
/**
|
|
133
|
+
* Load routes from generated route manifest
|
|
134
|
+
*/
|
|
135
|
+
private loadFileRoutes;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Router namespace - all routing functionality
|
|
139
|
+
* Usage: import { router } from '@zap-js/client'
|
|
140
|
+
*/
|
|
141
|
+
import { RouterProvider, useRouter as useRouterFn, useParams as useParamsFn, usePathname as usePathnameFn, useSearchParams as useSearchParamsFn, useRouteMatch as useRouteMatchFn, useIsPending as useIsPendingFn, Link, NavLink, Outlet, Redirect } from "./router.js";
|
|
142
|
+
export declare const router: {
|
|
143
|
+
RouterProvider: typeof RouterProvider;
|
|
144
|
+
useRouter: typeof useRouterFn;
|
|
145
|
+
useParams: typeof useParamsFn;
|
|
146
|
+
usePathname: typeof usePathnameFn;
|
|
147
|
+
useSearchParams: typeof useSearchParamsFn;
|
|
148
|
+
useRouteMatch: typeof useRouteMatchFn;
|
|
149
|
+
useIsPending: typeof useIsPendingFn;
|
|
150
|
+
Link: typeof Link;
|
|
151
|
+
NavLink: typeof NavLink;
|
|
152
|
+
Outlet: typeof Outlet;
|
|
153
|
+
Redirect: typeof Redirect;
|
|
154
|
+
};
|
|
155
|
+
/**
|
|
156
|
+
* Errors namespace - error handling and boundaries
|
|
157
|
+
* Usage: import { errors } from '@zap-js/client'
|
|
158
|
+
*/
|
|
159
|
+
import { ErrorBoundary, DefaultErrorComponent, createRouteError, ZapError } from "./error-boundary.js";
|
|
160
|
+
import { useRouteError, useIsErrorState, useErrorState } from "./hooks.js";
|
|
161
|
+
export declare const errors: {
|
|
162
|
+
readonly ErrorBoundary: typeof ErrorBoundary;
|
|
163
|
+
readonly DefaultErrorComponent: typeof DefaultErrorComponent;
|
|
164
|
+
readonly createRouteError: typeof createRouteError;
|
|
165
|
+
readonly ZapError: typeof ZapError;
|
|
166
|
+
readonly useRouteError: typeof useRouteError;
|
|
167
|
+
readonly useIsErrorState: typeof useIsErrorState;
|
|
168
|
+
readonly useErrorState: typeof useErrorState;
|
|
169
|
+
};
|
|
170
|
+
/**
|
|
171
|
+
* Middleware namespace - route middleware utilities
|
|
172
|
+
* Usage: import { middleware } from '@zap-js/client'
|
|
173
|
+
*/
|
|
174
|
+
import { composeMiddleware, requireAuth, requireRole, routeLogger, preloadData } from "./middleware.js";
|
|
175
|
+
export declare const middleware: {
|
|
176
|
+
readonly compose: typeof composeMiddleware;
|
|
177
|
+
readonly requireAuth: typeof requireAuth;
|
|
178
|
+
readonly requireRole: typeof requireRole;
|
|
179
|
+
readonly logger: typeof routeLogger;
|
|
180
|
+
readonly preloadData: typeof preloadData;
|
|
181
|
+
};
|
|
182
|
+
/**
|
|
183
|
+
* Types namespace - type definitions and guards
|
|
184
|
+
* Usage: import { types } from '@zap-js/client'
|
|
185
|
+
*/
|
|
186
|
+
import * as TypeGuards from "./types.js";
|
|
187
|
+
export declare const types: {
|
|
188
|
+
isInvokeHandlerMessage: typeof TypeGuards.isInvokeHandlerMessage;
|
|
189
|
+
isHandlerResponseMessage: typeof TypeGuards.isHandlerResponseMessage;
|
|
190
|
+
isErrorMessage: typeof TypeGuards.isErrorMessage;
|
|
191
|
+
isHealthCheckMessage: typeof TypeGuards.isHealthCheckMessage;
|
|
192
|
+
isHealthCheckResponseMessage: typeof TypeGuards.isHealthCheckResponseMessage;
|
|
193
|
+
isRpcResponseMessage: typeof TypeGuards.isRpcResponseMessage;
|
|
194
|
+
isRpcErrorMessage: typeof TypeGuards.isRpcErrorMessage;
|
|
195
|
+
isAsyncIterable: typeof TypeGuards.isAsyncIterable;
|
|
196
|
+
};
|
|
197
|
+
/**
|
|
198
|
+
* WebSockets namespace - WebSocket utilities and helpers
|
|
199
|
+
* Usage: import { websockets } from '@zap-js/client'
|
|
200
|
+
*/
|
|
201
|
+
import * as WebSocketUtils from "./websockets-utils.js";
|
|
202
|
+
export declare const websockets: {
|
|
203
|
+
readonly isWsMessage: typeof WebSocketUtils.isWsMessage;
|
|
204
|
+
readonly broadcast: typeof WebSocketUtils.broadcast;
|
|
205
|
+
readonly broadcastExcept: typeof WebSocketUtils.broadcastExcept;
|
|
206
|
+
readonly sendJson: typeof WebSocketUtils.sendJson;
|
|
207
|
+
readonly parseMessage: typeof WebSocketUtils.parseMessage;
|
|
208
|
+
readonly createErrorMessage: typeof WebSocketUtils.createErrorMessage;
|
|
209
|
+
readonly createSuccessMessage: typeof WebSocketUtils.createSuccessMessage;
|
|
210
|
+
};
|
|
211
|
+
/**
|
|
212
|
+
* Streaming namespace - Streaming response utilities
|
|
213
|
+
* Usage: import { streaming } from '@zap-js/client'
|
|
214
|
+
*/
|
|
215
|
+
import * as StreamingUtils from "./streaming-utils.js";
|
|
216
|
+
export declare const streaming: {
|
|
217
|
+
readonly isAsyncIterable: typeof TypeGuards.isAsyncIterable;
|
|
218
|
+
readonly createChunk: typeof StreamingUtils.createChunk;
|
|
219
|
+
readonly createStream: typeof StreamingUtils.createStream;
|
|
220
|
+
readonly streamJson: typeof StreamingUtils.streamJson;
|
|
221
|
+
readonly streamSSE: typeof StreamingUtils.streamSSE;
|
|
222
|
+
readonly mapStream: typeof StreamingUtils.mapStream;
|
|
223
|
+
readonly filterStream: typeof StreamingUtils.filterStream;
|
|
224
|
+
readonly batchStream: typeof StreamingUtils.batchStream;
|
|
225
|
+
readonly delayStream: typeof StreamingUtils.delayStream;
|
|
226
|
+
readonly fromReadableStream: typeof StreamingUtils.fromReadableStream;
|
|
227
|
+
readonly intervalStream: typeof StreamingUtils.intervalStream;
|
|
228
|
+
};
|
|
229
|
+
export default Zap;
|