@veloxts/client 0.1.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 VeloxTS Framework Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,263 @@
1
+ # @veloxts/client
2
+
3
+ Type-safe frontend API client for the VeloxTS framework.
4
+
5
+ ## Features
6
+
7
+ - **Zero code generation** - Types inferred directly from backend procedure definitions
8
+ - **Full type safety** - Autocomplete and compile-time type checking
9
+ - **Fetch-based** - Works in both browser and Node.js environments
10
+ - **Error handling** - Typed error classes with full response context
11
+ - **Interceptors** - Request, response, and error hooks
12
+ - **REST integration** - Maps to auto-generated REST endpoints
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install @veloxts/client
18
+ ```
19
+
20
+ ## Usage
21
+
22
+ ### Basic Setup
23
+
24
+ ```typescript
25
+ // Import your backend procedure types
26
+ import type { userProcedures, postProcedures } from '../server/procedures';
27
+ import { createClient } from '@veloxts/client';
28
+
29
+ // Create a typed client
30
+ const api = createClient<{
31
+ users: typeof userProcedures;
32
+ posts: typeof postProcedures;
33
+ }>({
34
+ baseUrl: '/api',
35
+ });
36
+
37
+ // Make fully typed API calls
38
+ const user = await api.users.getUser({ id: '123' });
39
+ // user is typed as User (inferred from backend output schema)
40
+
41
+ const users = await api.users.listUsers({ page: 1, limit: 10 });
42
+ // users is typed as User[] (or whatever your output schema defines)
43
+
44
+ const newUser = await api.users.createUser({
45
+ name: 'Alice',
46
+ email: 'alice@example.com'
47
+ });
48
+ // newUser is typed as User
49
+ ```
50
+
51
+ ### Custom Configuration
52
+
53
+ ```typescript
54
+ const api = createClient<Router>({
55
+ baseUrl: 'https://api.example.com/api',
56
+
57
+ // Add custom headers to all requests
58
+ headers: {
59
+ 'Authorization': 'Bearer token123',
60
+ },
61
+
62
+ // Request interceptor
63
+ onRequest: async (url, options) => {
64
+ console.log(`${options.method} ${url}`);
65
+ },
66
+
67
+ // Response interceptor
68
+ onResponse: async (response) => {
69
+ console.log(`Response: ${response.status}`);
70
+ },
71
+
72
+ // Error interceptor
73
+ onError: async (error) => {
74
+ console.error('API Error:', error.message);
75
+ // You can track errors, show notifications, etc.
76
+ },
77
+ });
78
+ ```
79
+
80
+ ### Error Handling
81
+
82
+ The client provides typed error classes for different error scenarios:
83
+
84
+ ```typescript
85
+ import {
86
+ isVeloxClientError,
87
+ isClientValidationError,
88
+ isClientNotFoundError,
89
+ isServerError,
90
+ isNetworkError,
91
+ } from '@veloxts/client';
92
+
93
+ try {
94
+ const user = await api.users.getUser({ id: 'invalid' });
95
+ } catch (error) {
96
+ if (isClientValidationError(error)) {
97
+ // Handle validation errors (400)
98
+ console.log('Validation failed:', error.fields);
99
+ } else if (isClientNotFoundError(error)) {
100
+ // Handle not found errors (404)
101
+ console.log('Resource not found:', error.resource);
102
+ } else if (isServerError(error)) {
103
+ // Handle server errors (5xx)
104
+ console.log('Server error:', error.statusCode);
105
+ } else if (isNetworkError(error)) {
106
+ // Handle network errors (can't reach server)
107
+ console.log('Network error:', error.message);
108
+ } else if (isVeloxClientError(error)) {
109
+ // Generic client error
110
+ console.log('Error:', error.statusCode, error.message);
111
+ }
112
+ }
113
+ ```
114
+
115
+ ### Using with React
116
+
117
+ ```typescript
118
+ // hooks/useApi.ts
119
+ import { createClient } from '@veloxts/client';
120
+ import type { AppRouter } from '../server/procedures';
121
+
122
+ export const api = createClient<AppRouter>({
123
+ baseUrl: import.meta.env.VITE_API_URL || '/api',
124
+ });
125
+
126
+ // In your component
127
+ import { api } from './hooks/useApi';
128
+ import { useState, useEffect } from 'react';
129
+
130
+ function UserProfile({ userId }: { userId: string }) {
131
+ const [user, setUser] = useState(null);
132
+ const [loading, setLoading] = useState(true);
133
+ const [error, setError] = useState(null);
134
+
135
+ useEffect(() => {
136
+ api.users.getUser({ id: userId })
137
+ .then(setUser)
138
+ .catch(setError)
139
+ .finally(() => setLoading(false));
140
+ }, [userId]);
141
+
142
+ if (loading) return <div>Loading...</div>;
143
+ if (error) return <div>Error: {error.message}</div>;
144
+
145
+ return <div>User: {user.name}</div>;
146
+ }
147
+ ```
148
+
149
+ ### Using with React Query (Recommended)
150
+
151
+ ```typescript
152
+ import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
153
+ import { api } from './hooks/useApi';
154
+
155
+ // Query hook
156
+ function useUser(userId: string) {
157
+ return useQuery({
158
+ queryKey: ['users', userId],
159
+ queryFn: () => api.users.getUser({ id: userId }),
160
+ });
161
+ }
162
+
163
+ // Mutation hook
164
+ function useCreateUser() {
165
+ const queryClient = useQueryClient();
166
+
167
+ return useMutation({
168
+ mutationFn: (data) => api.users.createUser(data),
169
+ onSuccess: () => {
170
+ // Invalidate and refetch
171
+ queryClient.invalidateQueries({ queryKey: ['users'] });
172
+ },
173
+ });
174
+ }
175
+
176
+ // In your component
177
+ function UserList() {
178
+ const { data: users, isLoading, error } = useQuery({
179
+ queryKey: ['users'],
180
+ queryFn: () => api.users.listUsers({}),
181
+ });
182
+
183
+ const createUser = useCreateUser();
184
+
185
+ const handleCreate = () => {
186
+ createUser.mutate({
187
+ name: 'New User',
188
+ email: 'user@example.com'
189
+ });
190
+ };
191
+
192
+ // ... rest of component
193
+ }
194
+ ```
195
+
196
+ ## Type Inference
197
+
198
+ The client uses TypeScript's type system to infer the complete API shape from your backend procedure definitions:
199
+
200
+ ```typescript
201
+ // Backend (procedures.ts)
202
+ export const userProcedures = defineProcedures('users', {
203
+ getUser: procedure()
204
+ .input(z.object({ id: z.string().uuid() }))
205
+ .output(UserSchema)
206
+ .query(async ({ input, ctx }) => {
207
+ return ctx.db.user.findUnique({ where: { id: input.id } });
208
+ }),
209
+ });
210
+
211
+ // Frontend - Types are automatically inferred!
212
+ const client = createClient<{ users: typeof userProcedures }>({ baseUrl: '/api' });
213
+
214
+ // TypeScript knows:
215
+ // - api.users.getUser expects { id: string }
216
+ // - api.users.getUser returns Promise<User>
217
+ // - Invalid inputs will show compile-time errors
218
+ ```
219
+
220
+ ## REST Endpoint Mapping
221
+
222
+ The client automatically maps procedure calls to REST endpoints using the same conventions as the server:
223
+
224
+ | Procedure Name | HTTP Method | Path |
225
+ |---------------|-------------|------|
226
+ | `getUser` | GET | `/users/:id` |
227
+ | `listUsers` | GET | `/users` |
228
+ | `createUser` | POST | `/users` |
229
+ | `updateUser` | PUT | `/users/:id` |
230
+ | `deleteUser` | DELETE | `/users/:id` |
231
+
232
+ ## Browser and Node.js Support
233
+
234
+ The client uses the native `fetch` API, which is available in:
235
+ - All modern browsers
236
+ - Node.js v20+ (native fetch)
237
+ - Earlier Node.js versions with a polyfill
238
+
239
+ For older Node.js versions, provide a custom fetch implementation:
240
+
241
+ ```typescript
242
+ import fetch from 'node-fetch';
243
+
244
+ const api = createClient<Router>({
245
+ baseUrl: 'https://api.example.com',
246
+ fetch: fetch as typeof globalThis.fetch,
247
+ });
248
+ ```
249
+
250
+ ## Related Packages
251
+
252
+ - [@veloxts/core](/packages/core) - Core framework with error classes
253
+ - [@veloxts/router](/packages/router) - Procedure definitions for backend
254
+ - [@veloxts/validation](/packages/validation) - Schema validation with Zod
255
+ - [create-velox-app](/packages/create) - Project scaffolder
256
+
257
+ ## TypeScript Support
258
+
259
+ All exports are fully typed with comprehensive JSDoc documentation. The package includes type definitions and declaration maps for excellent IDE support.
260
+
261
+ ## License
262
+
263
+ MIT
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Type-safe API client implementation
3
+ *
4
+ * Provides a fetch-based client that calls REST endpoints with full type safety
5
+ * inferred from backend procedure definitions.
6
+ *
7
+ * @module client
8
+ */
9
+ import type { ClientConfig, ClientFromRouter } from './types.js';
10
+ /**
11
+ * Creates a type-safe API client for a VeloxTS backend
12
+ *
13
+ * The client uses TypeScript's type system to infer the full API shape from
14
+ * backend procedure definitions, providing autocomplete and compile-time type checking.
15
+ *
16
+ * @template TRouter - The router type (typeof imported procedures)
17
+ * @param config - Client configuration
18
+ * @returns Fully typed API client with namespaced procedures
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * // Import procedure types from backend
23
+ * import type { userProcedures, postProcedures } from '../server/procedures';
24
+ *
25
+ * // Create client with inferred types
26
+ * const api = createClient<{
27
+ * users: typeof userProcedures;
28
+ * posts: typeof postProcedures;
29
+ * }>({
30
+ * baseUrl: 'https://api.example.com/api',
31
+ * });
32
+ *
33
+ * // Fully typed calls
34
+ * const user = await api.users.getUser({ id: '123' });
35
+ * const newPost = await api.posts.createPost({ title: 'Hello', content: '...' });
36
+ * ```
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * // With custom configuration
41
+ * const api = createClient<Router>({
42
+ * baseUrl: '/api',
43
+ * headers: {
44
+ * 'Authorization': 'Bearer token123',
45
+ * },
46
+ * onRequest: async (url, options) => {
47
+ * console.log(`${options.method} ${url}`);
48
+ * },
49
+ * onError: async (error) => {
50
+ * console.error('API Error:', error.message);
51
+ * },
52
+ * });
53
+ * ```
54
+ */
55
+ export declare function createClient<TRouter>(config: ClientConfig): ClientFromRouter<TRouter>;
56
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAA6B,MAAM,YAAY,CAAC;AA4X5F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAYrF"}