@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.
Files changed (115) hide show
  1. package/README.md +310 -24
  2. package/bin/zap +0 -0
  3. package/bin/zap-codegen +0 -0
  4. package/dist/cli/commands/build.d.ts +11 -0
  5. package/dist/cli/commands/build.js +282 -0
  6. package/dist/cli/commands/codegen.d.ts +8 -0
  7. package/dist/cli/commands/codegen.js +95 -0
  8. package/dist/cli/commands/dev.d.ts +20 -0
  9. package/dist/cli/commands/dev.js +78 -0
  10. package/dist/cli/commands/new.d.ts +9 -0
  11. package/dist/cli/commands/new.js +307 -0
  12. package/dist/cli/commands/routes-old.d.ts +9 -0
  13. package/dist/cli/commands/routes-old.js +106 -0
  14. package/dist/cli/commands/routes.d.ts +11 -0
  15. package/dist/cli/commands/routes.js +280 -0
  16. package/dist/cli/commands/serve.d.ts +17 -0
  17. package/dist/cli/commands/serve.js +386 -0
  18. package/dist/cli/index.d.ts +2 -0
  19. package/dist/cli/index.js +76 -0
  20. package/dist/cli/utils/index.d.ts +2 -0
  21. package/dist/cli/utils/index.js +2 -0
  22. package/dist/cli/utils/logger.d.ts +84 -0
  23. package/dist/cli/utils/logger.js +181 -0
  24. package/dist/cli/utils/port-finder.d.ts +8 -0
  25. package/dist/cli/utils/port-finder.js +48 -0
  26. package/dist/dev-server/codegen-runner.d.ts +41 -0
  27. package/dist/dev-server/codegen-runner.js +172 -0
  28. package/dist/dev-server/hot-reload.d.ts +72 -0
  29. package/dist/dev-server/hot-reload.js +280 -0
  30. package/dist/dev-server/index.d.ts +8 -0
  31. package/dist/dev-server/index.js +8 -0
  32. package/dist/dev-server/route-scanner.d.ts +71 -0
  33. package/dist/dev-server/route-scanner.js +114 -0
  34. package/dist/dev-server/rust-builder.d.ts +66 -0
  35. package/dist/dev-server/rust-builder.js +286 -0
  36. package/dist/dev-server/server.d.ts +147 -0
  37. package/dist/dev-server/server.js +658 -0
  38. package/dist/dev-server/vite-proxy.d.ts +56 -0
  39. package/dist/dev-server/vite-proxy.js +212 -0
  40. package/dist/dev-server/watcher.d.ts +48 -0
  41. package/dist/dev-server/watcher.js +127 -0
  42. package/dist/router/codegen-enhanced.d.ts +5 -0
  43. package/dist/router/codegen-enhanced.js +275 -0
  44. package/dist/router/codegen.d.ts +17 -0
  45. package/dist/router/codegen.js +654 -0
  46. package/dist/router/index.d.ts +16 -0
  47. package/dist/router/index.js +19 -0
  48. package/dist/router/scanner.d.ts +86 -0
  49. package/dist/router/scanner.js +689 -0
  50. package/dist/router/ssg.d.ts +115 -0
  51. package/dist/router/ssg.js +202 -0
  52. package/dist/router/types.d.ts +124 -0
  53. package/dist/router/types.js +9 -0
  54. package/dist/router/watch.d.ts +38 -0
  55. package/dist/router/watch.js +135 -0
  56. package/dist/runtime/csrf.d.ts +146 -0
  57. package/dist/runtime/csrf.js +166 -0
  58. package/dist/runtime/error-boundary.d.ts +129 -0
  59. package/dist/runtime/error-boundary.js +287 -0
  60. package/dist/runtime/hooks.d.ts +83 -0
  61. package/dist/runtime/hooks.js +96 -0
  62. package/dist/runtime/index.d.ts +229 -0
  63. package/dist/runtime/index.js +449 -0
  64. package/dist/runtime/ipc-client.d.ts +144 -0
  65. package/dist/runtime/ipc-client.js +621 -0
  66. package/dist/runtime/logger.d.ts +71 -0
  67. package/dist/runtime/logger.js +164 -0
  68. package/dist/runtime/middleware.d.ts +66 -0
  69. package/dist/runtime/middleware.js +114 -0
  70. package/dist/runtime/process-manager.d.ts +51 -0
  71. package/dist/runtime/process-manager.js +207 -0
  72. package/dist/runtime/router-simple.d.ts +98 -0
  73. package/dist/runtime/router-simple.js +330 -0
  74. package/dist/runtime/router.d.ts +103 -0
  75. package/dist/runtime/router.js +435 -0
  76. package/dist/runtime/rpc-client.d.ts +35 -0
  77. package/dist/runtime/rpc-client.js +140 -0
  78. package/dist/runtime/streaming-utils.d.ts +86 -0
  79. package/dist/runtime/streaming-utils.js +150 -0
  80. package/dist/runtime/types.d.ts +465 -0
  81. package/dist/runtime/types.js +60 -0
  82. package/dist/runtime/websockets-utils.d.ts +50 -0
  83. package/dist/runtime/websockets-utils.js +92 -0
  84. package/package.json +30 -20
  85. package/index.js +0 -29
  86. package/internal/cli/package.json +0 -46
  87. package/internal/cli/tsconfig.tsbuildinfo +0 -1
  88. package/internal/dev-server/node_modules/ora/index.d.ts +0 -332
  89. package/internal/dev-server/node_modules/ora/index.js +0 -416
  90. package/internal/dev-server/node_modules/ora/license +0 -9
  91. package/internal/dev-server/node_modules/ora/node_modules/string-width/index.d.ts +0 -36
  92. package/internal/dev-server/node_modules/ora/node_modules/string-width/index.js +0 -65
  93. package/internal/dev-server/node_modules/ora/node_modules/string-width/license +0 -9
  94. package/internal/dev-server/node_modules/ora/node_modules/string-width/node_modules/emoji-regex/LICENSE-MIT.txt +0 -20
  95. package/internal/dev-server/node_modules/ora/node_modules/string-width/node_modules/emoji-regex/README.md +0 -107
  96. package/internal/dev-server/node_modules/ora/node_modules/string-width/node_modules/emoji-regex/index.d.ts +0 -3
  97. package/internal/dev-server/node_modules/ora/node_modules/string-width/node_modules/emoji-regex/index.js +0 -4
  98. package/internal/dev-server/node_modules/ora/node_modules/string-width/node_modules/emoji-regex/index.mjs +0 -4
  99. package/internal/dev-server/node_modules/ora/node_modules/string-width/node_modules/emoji-regex/package.json +0 -46
  100. package/internal/dev-server/node_modules/ora/node_modules/string-width/package.json +0 -60
  101. package/internal/dev-server/node_modules/ora/node_modules/string-width/readme.md +0 -62
  102. package/internal/dev-server/node_modules/ora/package.json +0 -66
  103. package/internal/dev-server/node_modules/ora/readme.md +0 -325
  104. package/internal/dev-server/package.json +0 -41
  105. package/internal/router/package.json +0 -28
  106. package/internal/runtime/package.json +0 -41
  107. package/internal/runtime/src/error-boundary.tsx +0 -476
  108. package/internal/runtime/src/router-simple.tsx +0 -640
  109. package/internal/runtime/src/router.tsx +0 -771
  110. package/internal/runtime/tsconfig.tsbuildinfo +0 -1
  111. package/src/errors.js +0 -33
  112. package/src/logger.js +0 -10
  113. package/src/middleware.js +0 -32
  114. package/src/router.js +0 -41
  115. package/src/types.js +0 -39
@@ -0,0 +1,146 @@
1
+ /**
2
+ * CSRF (Cross-Site Request Forgery) Protection Utilities
3
+ *
4
+ * Provides client-side utilities for working with CSRF tokens:
5
+ * - Reading tokens from cookies
6
+ * - Including tokens in fetch requests
7
+ * - Form components with automatic token injection
8
+ */
9
+ /**
10
+ * CSRF configuration
11
+ */
12
+ export interface CsrfConfig {
13
+ /** Cookie name for CSRF token (default: "csrf_token") */
14
+ cookieName?: string;
15
+ /** Header name for CSRF token (default: "X-CSRF-Token") */
16
+ headerName?: string;
17
+ /** Form field name for CSRF token (default: "_csrf") */
18
+ formFieldName?: string;
19
+ }
20
+ /**
21
+ * Get CSRF token from cookie
22
+ */
23
+ export declare function getCsrfToken(config?: CsrfConfig): string | null;
24
+ /**
25
+ * React hook to get CSRF token
26
+ *
27
+ * @example
28
+ * ```tsx
29
+ * function MyComponent() {
30
+ * const csrfToken = useCsrfToken();
31
+ *
32
+ * const handleSubmit = async () => {
33
+ * await fetch('/api/data', {
34
+ * method: 'POST',
35
+ * headers: {
36
+ * 'X-CSRF-Token': csrfToken || '',
37
+ * 'Content-Type': 'application/json',
38
+ * },
39
+ * body: JSON.stringify({ data: 'value' }),
40
+ * });
41
+ * };
42
+ * }
43
+ * ```
44
+ */
45
+ export declare function useCsrfToken(config?: CsrfConfig): string | null;
46
+ /**
47
+ * Create a fetch wrapper that automatically includes CSRF token
48
+ *
49
+ * @example
50
+ * ```tsx
51
+ * const csrfFetch = createCsrfFetch();
52
+ *
53
+ * // Token is automatically included in POST/PUT/DELETE/PATCH requests
54
+ * await csrfFetch('/api/data', {
55
+ * method: 'POST',
56
+ * body: JSON.stringify({ data: 'value' }),
57
+ * });
58
+ * ```
59
+ */
60
+ export declare function createCsrfFetch(config?: CsrfConfig): typeof fetch;
61
+ /**
62
+ * CSRF token input component for forms
63
+ *
64
+ * @example
65
+ * ```tsx
66
+ * function MyForm() {
67
+ * return (
68
+ * <form method="POST" action="/api/submit">
69
+ * <CsrfTokenInput />
70
+ * <input name="username" />
71
+ * <button type="submit">Submit</button>
72
+ * </form>
73
+ * );
74
+ * }
75
+ * ```
76
+ */
77
+ export interface CsrfTokenInputProps {
78
+ /** Configuration for CSRF token retrieval */
79
+ config?: CsrfConfig;
80
+ }
81
+ export declare function CsrfTokenInput({ config }: CsrfTokenInputProps): import("react/jsx-runtime").JSX.Element | null;
82
+ /**
83
+ * Enhanced form component with automatic CSRF protection
84
+ *
85
+ * @example
86
+ * ```tsx
87
+ * function MyPage() {
88
+ * const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
89
+ * e.preventDefault();
90
+ * const formData = new FormData(e.currentTarget);
91
+ * await fetch('/api/submit', {
92
+ * method: 'POST',
93
+ * body: formData,
94
+ * });
95
+ * };
96
+ *
97
+ * return (
98
+ * <CsrfForm onSubmit={handleSubmit}>
99
+ * <input name="username" />
100
+ * <button type="submit">Submit</button>
101
+ * </CsrfForm>
102
+ * );
103
+ * }
104
+ * ```
105
+ */
106
+ export interface CsrfFormProps extends React.FormHTMLAttributes<HTMLFormElement> {
107
+ /** Configuration for CSRF token retrieval */
108
+ config?: CsrfConfig;
109
+ /** Child elements */
110
+ children: React.ReactNode;
111
+ }
112
+ export declare function CsrfForm({ config, children, ...formProps }: CsrfFormProps): import("react/jsx-runtime").JSX.Element;
113
+ /**
114
+ * Utility to manually add CSRF token to FormData
115
+ *
116
+ * @example
117
+ * ```tsx
118
+ * const formData = new FormData();
119
+ * formData.append('username', 'john');
120
+ * addCsrfToFormData(formData);
121
+ *
122
+ * await fetch('/api/submit', {
123
+ * method: 'POST',
124
+ * body: formData,
125
+ * });
126
+ * ```
127
+ */
128
+ export declare function addCsrfToFormData(formData: FormData, config?: CsrfConfig): void;
129
+ /**
130
+ * Utility to get headers object with CSRF token
131
+ *
132
+ * @example
133
+ * ```tsx
134
+ * const headers = {
135
+ * 'Content-Type': 'application/json',
136
+ * ...getCsrfHeaders(),
137
+ * };
138
+ *
139
+ * await fetch('/api/data', {
140
+ * method: 'POST',
141
+ * headers,
142
+ * body: JSON.stringify({ data: 'value' }),
143
+ * });
144
+ * ```
145
+ */
146
+ export declare function getCsrfHeaders(config?: CsrfConfig): Record<string, string>;
@@ -0,0 +1,166 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * CSRF (Cross-Site Request Forgery) Protection Utilities
4
+ *
5
+ * Provides client-side utilities for working with CSRF tokens:
6
+ * - Reading tokens from cookies
7
+ * - Including tokens in fetch requests
8
+ * - Form components with automatic token injection
9
+ */
10
+ import { useState, useEffect } from 'react';
11
+ const DEFAULT_CONFIG = {
12
+ cookieName: 'csrf_token',
13
+ headerName: 'X-CSRF-Token',
14
+ formFieldName: '_csrf',
15
+ };
16
+ /**
17
+ * Get CSRF token from cookie
18
+ */
19
+ export function getCsrfToken(config = {}) {
20
+ const { cookieName } = { ...DEFAULT_CONFIG, ...config };
21
+ if (typeof document === 'undefined') {
22
+ return null;
23
+ }
24
+ const cookies = document.cookie.split(';');
25
+ for (const cookie of cookies) {
26
+ const [name, value] = cookie.trim().split('=');
27
+ if (name === cookieName) {
28
+ return value;
29
+ }
30
+ }
31
+ return null;
32
+ }
33
+ /**
34
+ * React hook to get CSRF token
35
+ *
36
+ * @example
37
+ * ```tsx
38
+ * function MyComponent() {
39
+ * const csrfToken = useCsrfToken();
40
+ *
41
+ * const handleSubmit = async () => {
42
+ * await fetch('/api/data', {
43
+ * method: 'POST',
44
+ * headers: {
45
+ * 'X-CSRF-Token': csrfToken || '',
46
+ * 'Content-Type': 'application/json',
47
+ * },
48
+ * body: JSON.stringify({ data: 'value' }),
49
+ * });
50
+ * };
51
+ * }
52
+ * ```
53
+ */
54
+ export function useCsrfToken(config = {}) {
55
+ const [token, setToken] = useState(() => getCsrfToken(config));
56
+ useEffect(() => {
57
+ // Update token if cookie changes
58
+ const interval = setInterval(() => {
59
+ const newToken = getCsrfToken(config);
60
+ if (newToken !== token) {
61
+ setToken(newToken);
62
+ }
63
+ }, 1000);
64
+ return () => clearInterval(interval);
65
+ }, [config, token]);
66
+ return token;
67
+ }
68
+ /**
69
+ * Create a fetch wrapper that automatically includes CSRF token
70
+ *
71
+ * @example
72
+ * ```tsx
73
+ * const csrfFetch = createCsrfFetch();
74
+ *
75
+ * // Token is automatically included in POST/PUT/DELETE/PATCH requests
76
+ * await csrfFetch('/api/data', {
77
+ * method: 'POST',
78
+ * body: JSON.stringify({ data: 'value' }),
79
+ * });
80
+ * ```
81
+ */
82
+ export function createCsrfFetch(config = {}) {
83
+ const { headerName } = { ...DEFAULT_CONFIG, ...config };
84
+ return async (input, init) => {
85
+ const token = getCsrfToken(config);
86
+ // Only add token for state-changing methods
87
+ const method = init?.method?.toUpperCase() || 'GET';
88
+ const needsToken = ['POST', 'PUT', 'DELETE', 'PATCH'].includes(method);
89
+ if (needsToken && token) {
90
+ const headers = new Headers(init?.headers);
91
+ if (!headers.has(headerName)) {
92
+ headers.set(headerName, token);
93
+ }
94
+ return fetch(input, {
95
+ ...init,
96
+ headers,
97
+ });
98
+ }
99
+ return fetch(input, init);
100
+ };
101
+ }
102
+ export function CsrfTokenInput({ config = {} }) {
103
+ const token = useCsrfToken(config);
104
+ const { formFieldName } = { ...DEFAULT_CONFIG, ...config };
105
+ if (!token) {
106
+ console.warn('CSRF token not found. Form submission may fail.');
107
+ return null;
108
+ }
109
+ return _jsx("input", { type: "hidden", name: formFieldName, value: token });
110
+ }
111
+ export function CsrfForm({ config, children, ...formProps }) {
112
+ return (_jsxs("form", { ...formProps, children: [_jsx(CsrfTokenInput, { config: config }), children] }));
113
+ }
114
+ /**
115
+ * Utility to manually add CSRF token to FormData
116
+ *
117
+ * @example
118
+ * ```tsx
119
+ * const formData = new FormData();
120
+ * formData.append('username', 'john');
121
+ * addCsrfToFormData(formData);
122
+ *
123
+ * await fetch('/api/submit', {
124
+ * method: 'POST',
125
+ * body: formData,
126
+ * });
127
+ * ```
128
+ */
129
+ export function addCsrfToFormData(formData, config = {}) {
130
+ const token = getCsrfToken(config);
131
+ const { formFieldName } = { ...DEFAULT_CONFIG, ...config };
132
+ if (token) {
133
+ formData.append(formFieldName, token);
134
+ }
135
+ else {
136
+ console.warn('CSRF token not found. FormData submission may fail.');
137
+ }
138
+ }
139
+ /**
140
+ * Utility to get headers object with CSRF token
141
+ *
142
+ * @example
143
+ * ```tsx
144
+ * const headers = {
145
+ * 'Content-Type': 'application/json',
146
+ * ...getCsrfHeaders(),
147
+ * };
148
+ *
149
+ * await fetch('/api/data', {
150
+ * method: 'POST',
151
+ * headers,
152
+ * body: JSON.stringify({ data: 'value' }),
153
+ * });
154
+ * ```
155
+ */
156
+ export function getCsrfHeaders(config = {}) {
157
+ const token = getCsrfToken(config);
158
+ const { headerName } = { ...DEFAULT_CONFIG, ...config };
159
+ if (!token) {
160
+ console.warn('CSRF token not found. Request may fail.');
161
+ return {};
162
+ }
163
+ return {
164
+ [headerName]: token,
165
+ };
166
+ }
@@ -0,0 +1,129 @@
1
+ /**
2
+ * ZapJS Error Boundary
3
+ *
4
+ * TanStack Router style error boundary with explicit errorComponent prop.
5
+ * Provides structured error handling with server error correlation.
6
+ */
7
+ import React, { Component, type ReactNode, type ErrorInfo } from 'react';
8
+ /**
9
+ * Structured route error with full context
10
+ *
11
+ * Matches the ErrorResponse from Rust server for consistency.
12
+ */
13
+ export interface ZapRouteError {
14
+ /** Human-readable error message */
15
+ message: string;
16
+ /** Stack trace (development only) */
17
+ stack?: string;
18
+ /** Unique error identifier for log correlation (from server) */
19
+ digest?: string;
20
+ /** Machine-readable error code (e.g., "HANDLER_ERROR", "VALIDATION_ERROR") */
21
+ code?: string;
22
+ /** HTTP status code */
23
+ status?: number;
24
+ /** Additional error-specific details */
25
+ details?: Record<string, unknown>;
26
+ }
27
+ /**
28
+ * Props for error component
29
+ */
30
+ export interface ErrorComponentProps {
31
+ /** The error that was caught */
32
+ error: ZapRouteError;
33
+ /** Reset function to retry rendering */
34
+ reset: () => void;
35
+ }
36
+ /**
37
+ * Error component type (TanStack style)
38
+ */
39
+ export type ErrorComponent = React.ComponentType<ErrorComponentProps>;
40
+ interface RouteErrorContextValue {
41
+ error: ZapRouteError;
42
+ reset: () => void;
43
+ }
44
+ /**
45
+ * Context for accessing error state in error components
46
+ */
47
+ export declare const RouteErrorContext: React.Context<RouteErrorContextValue | null>;
48
+ interface ErrorBoundaryProps {
49
+ /** The content to render when no error */
50
+ children: ReactNode;
51
+ /** Custom error component (TanStack style) */
52
+ errorComponent?: ErrorComponent;
53
+ /** Fallback when no errorComponent provided */
54
+ fallback?: ReactNode;
55
+ /** Callback when an error is caught */
56
+ onError?: (error: ZapRouteError, errorInfo: ErrorInfo) => void;
57
+ /** Reset keys - when these change, the boundary resets */
58
+ resetKeys?: unknown[];
59
+ }
60
+ interface ErrorBoundaryState {
61
+ hasError: boolean;
62
+ error: ZapRouteError | null;
63
+ }
64
+ /**
65
+ * Error Boundary with TanStack Router style errorComponent prop
66
+ *
67
+ * @example
68
+ * ```tsx
69
+ * // Route file: routes/users.$id.tsx
70
+ * export default function UserPage() {
71
+ * // ... component
72
+ * }
73
+ *
74
+ * export function errorComponent({ error, reset }: ErrorComponentProps) {
75
+ * return (
76
+ * <div>
77
+ * <h1>Failed to load user</h1>
78
+ * <p>{error.message}</p>
79
+ * {error.digest && <small>Error ID: {error.digest}</small>}
80
+ * <button onClick={reset}>Try Again</button>
81
+ * </div>
82
+ * );
83
+ * }
84
+ * ```
85
+ */
86
+ export declare class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
87
+ constructor(props: ErrorBoundaryProps);
88
+ static getDerivedStateFromError(error: Error): ErrorBoundaryState;
89
+ componentDidCatch(error: Error, errorInfo: ErrorInfo): void;
90
+ componentDidUpdate(prevProps: ErrorBoundaryProps): void;
91
+ /**
92
+ * Reset the error boundary state
93
+ */
94
+ reset: () => void;
95
+ render(): ReactNode;
96
+ }
97
+ /**
98
+ * Default error fallback UI
99
+ *
100
+ * Shows:
101
+ * - Error message
102
+ * - Error code (if available)
103
+ * - Error digest (for server errors)
104
+ * - Stack trace (development only)
105
+ * - "Try Again" button
106
+ */
107
+ export declare function DefaultErrorComponent({ error, reset }: ErrorComponentProps): JSX.Element;
108
+ /**
109
+ * Create a ZapRouteError from server error response
110
+ */
111
+ export declare function createRouteError(options: {
112
+ message: string;
113
+ code?: string;
114
+ status?: number;
115
+ digest?: string;
116
+ details?: Record<string, unknown>;
117
+ }): ZapRouteError;
118
+ /**
119
+ * Wrap an Error with ZapRouteError metadata
120
+ */
121
+ export declare class ZapError extends Error {
122
+ code?: string;
123
+ status?: number;
124
+ digest?: string;
125
+ details?: Record<string, unknown>;
126
+ constructor(message: string, options?: Omit<ZapRouteError, 'message' | 'stack'>);
127
+ toRouteError(): ZapRouteError;
128
+ }
129
+ export {};