@zap-js/client 0.0.2 → 0.0.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/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 +84 -0
- package/dist/dev-server/route-scanner.js +113 -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 +660 -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,449 @@
|
|
|
1
|
+
import { join } from "path";
|
|
2
|
+
import { tmpdir } from "os";
|
|
3
|
+
import { existsSync, readFileSync } from "fs";
|
|
4
|
+
import { ProcessManager } from "./process-manager.js";
|
|
5
|
+
import { IpcServer } from "./ipc-client.js";
|
|
6
|
+
// Re-export type guards
|
|
7
|
+
export { isInvokeHandlerMessage, isHandlerResponseMessage, isErrorMessage, isHealthCheckMessage, isHealthCheckResponseMessage, isRpcResponseMessage, isRpcErrorMessage, isAsyncIterable, } from "./types.js";
|
|
8
|
+
// Re-export internal modules for dev-server usage
|
|
9
|
+
export { ProcessManager } from "./process-manager.js";
|
|
10
|
+
export { IpcServer, IpcClient } from "./ipc-client.js";
|
|
11
|
+
// Re-export error boundary components and hooks (Phase 10.3)
|
|
12
|
+
export { ErrorBoundary, DefaultErrorComponent, RouteErrorContext, createRouteError, ZapError, } from "./error-boundary.js";
|
|
13
|
+
export { useRouteError, useIsErrorState, useErrorState, } from "./hooks.js";
|
|
14
|
+
// Re-export logger (Phase 10.2)
|
|
15
|
+
export { Logger, logger } from "./logger.js";
|
|
16
|
+
// Re-export client router
|
|
17
|
+
export {
|
|
18
|
+
// Provider
|
|
19
|
+
RouterProvider,
|
|
20
|
+
// Hooks
|
|
21
|
+
useRouter, useParams, usePathname, useSearchParams, useRouteMatch, useIsPending,
|
|
22
|
+
// Components
|
|
23
|
+
Link, NavLink, Outlet, Redirect, } from "./router.js";
|
|
24
|
+
// Re-export CSRF protection utilities
|
|
25
|
+
export { getCsrfToken, useCsrfToken, createCsrfFetch, CsrfTokenInput, CsrfForm, addCsrfToFormData, getCsrfHeaders, } from "./csrf.js";
|
|
26
|
+
// Re-export RPC client utilities
|
|
27
|
+
export { rpcCall, } from "./rpc-client.js";
|
|
28
|
+
/**
|
|
29
|
+
* Zap - Ultra-fast HTTP server for Node.js and Bun
|
|
30
|
+
*
|
|
31
|
+
* This is the main API entry point. It manages:
|
|
32
|
+
* 1. Route registration from TypeScript
|
|
33
|
+
* 2. Spawning and managing the Rust binary process
|
|
34
|
+
* 3. IPC communication between TypeScript handlers and Rust server
|
|
35
|
+
*
|
|
36
|
+
* Usage:
|
|
37
|
+
* ```
|
|
38
|
+
* const app = new Zap({ port: 3000 });
|
|
39
|
+
* app.get('/', () => ({ message: 'Hello!' }));
|
|
40
|
+
* app.post('/api/data', (req) => ({ received: req.body }));
|
|
41
|
+
* await app.listen();
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export class Zap {
|
|
45
|
+
constructor(options) {
|
|
46
|
+
this.handlers = new Map();
|
|
47
|
+
this.routes = [];
|
|
48
|
+
this.staticFiles = [];
|
|
49
|
+
this.port = 3000;
|
|
50
|
+
this.hostname = "127.0.0.1";
|
|
51
|
+
this.logLevel = "info";
|
|
52
|
+
this.healthCheckPath = "/health";
|
|
53
|
+
this.metricsPath = null;
|
|
54
|
+
this.enableCors = false;
|
|
55
|
+
this.enableLogging = false;
|
|
56
|
+
this.enableCompression = false;
|
|
57
|
+
this.fileRoutingEnabled = false;
|
|
58
|
+
this.fileRoutingConfig = {};
|
|
59
|
+
// Parse options
|
|
60
|
+
if (options?.port)
|
|
61
|
+
this.port = options.port;
|
|
62
|
+
if (options?.hostname)
|
|
63
|
+
this.hostname = options.hostname;
|
|
64
|
+
if (options?.logLevel)
|
|
65
|
+
this.logLevel = options.logLevel;
|
|
66
|
+
// Create IPC socket path (unique per instance)
|
|
67
|
+
const socketPath = join(tmpdir(), `zap-${Date.now()}-${Math.random().toString(36).substring(7)}.sock`);
|
|
68
|
+
// Initialize managers
|
|
69
|
+
this.processManager = new ProcessManager(undefined, socketPath);
|
|
70
|
+
this.ipcServer = new IpcServer(socketPath);
|
|
71
|
+
}
|
|
72
|
+
// ============================================================================
|
|
73
|
+
// Fluent Configuration API
|
|
74
|
+
// ============================================================================
|
|
75
|
+
/**
|
|
76
|
+
* Set the server port
|
|
77
|
+
*/
|
|
78
|
+
setPort(port) {
|
|
79
|
+
this.port = port;
|
|
80
|
+
return this;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Set the server hostname
|
|
84
|
+
*/
|
|
85
|
+
setHostname(hostname) {
|
|
86
|
+
this.hostname = hostname;
|
|
87
|
+
return this;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Enable CORS middleware
|
|
91
|
+
*/
|
|
92
|
+
cors() {
|
|
93
|
+
this.enableCors = true;
|
|
94
|
+
return this;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Enable request logging middleware
|
|
98
|
+
*/
|
|
99
|
+
logging() {
|
|
100
|
+
this.enableLogging = true;
|
|
101
|
+
return this;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Enable response compression middleware
|
|
105
|
+
*/
|
|
106
|
+
compression() {
|
|
107
|
+
this.enableCompression = true;
|
|
108
|
+
return this;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Set custom health check path
|
|
112
|
+
*/
|
|
113
|
+
healthCheck(path) {
|
|
114
|
+
this.healthCheckPath = path;
|
|
115
|
+
return this;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Set metrics endpoint path
|
|
119
|
+
*/
|
|
120
|
+
metrics(path) {
|
|
121
|
+
this.metricsPath = path;
|
|
122
|
+
return this;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Enable file-based routing (TanStack style)
|
|
126
|
+
*
|
|
127
|
+
* Automatically registers routes from the routes/ directory
|
|
128
|
+
* using the generated route manifest from @zapjs/router
|
|
129
|
+
*/
|
|
130
|
+
useFileRouting(config) {
|
|
131
|
+
this.fileRoutingEnabled = true;
|
|
132
|
+
this.fileRoutingConfig = config || {};
|
|
133
|
+
return this;
|
|
134
|
+
}
|
|
135
|
+
// ============================================================================
|
|
136
|
+
// Route Registration API
|
|
137
|
+
// ============================================================================
|
|
138
|
+
/**
|
|
139
|
+
* Register a GET route
|
|
140
|
+
*/
|
|
141
|
+
get(path, handler) {
|
|
142
|
+
return this.registerRoute("GET", path, handler);
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Register a POST route
|
|
146
|
+
*/
|
|
147
|
+
post(path, handler) {
|
|
148
|
+
return this.registerRoute("POST", path, handler);
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Register a PUT route
|
|
152
|
+
*/
|
|
153
|
+
put(path, handler) {
|
|
154
|
+
return this.registerRoute("PUT", path, handler);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Register a DELETE route
|
|
158
|
+
*/
|
|
159
|
+
delete(path, handler) {
|
|
160
|
+
return this.registerRoute("DELETE", path, handler);
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Register a PATCH route
|
|
164
|
+
*/
|
|
165
|
+
patch(path, handler) {
|
|
166
|
+
return this.registerRoute("PATCH", path, handler);
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Register a HEAD route
|
|
170
|
+
*/
|
|
171
|
+
head(path, handler) {
|
|
172
|
+
return this.registerRoute("HEAD", path, handler);
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Convenience method for GET routes that return JSON
|
|
176
|
+
*/
|
|
177
|
+
getJson(path, handler) {
|
|
178
|
+
return this.get(path, handler);
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Convenience method for POST routes that return JSON
|
|
182
|
+
*/
|
|
183
|
+
postJson(path, handler) {
|
|
184
|
+
return this.post(path, handler);
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Register static file serving
|
|
188
|
+
*/
|
|
189
|
+
static(prefix, directory) {
|
|
190
|
+
this.staticFiles.push({ prefix, directory });
|
|
191
|
+
return this;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Register a route with a handler (internal)
|
|
195
|
+
*/
|
|
196
|
+
registerRoute(method, path, handler) {
|
|
197
|
+
const handlerId = `handler_${this.handlers.size}`;
|
|
198
|
+
this.handlers.set(handlerId, handler);
|
|
199
|
+
this.routes.push({
|
|
200
|
+
method,
|
|
201
|
+
path,
|
|
202
|
+
handler_id: handlerId,
|
|
203
|
+
is_typescript: true,
|
|
204
|
+
});
|
|
205
|
+
return this;
|
|
206
|
+
}
|
|
207
|
+
// ============================================================================
|
|
208
|
+
// Server Lifecycle
|
|
209
|
+
// ============================================================================
|
|
210
|
+
/**
|
|
211
|
+
* Start the server
|
|
212
|
+
*/
|
|
213
|
+
async listen(port) {
|
|
214
|
+
// Allow overriding port in listen()
|
|
215
|
+
if (port !== undefined) {
|
|
216
|
+
this.port = port;
|
|
217
|
+
}
|
|
218
|
+
try {
|
|
219
|
+
// Load file-based routes if enabled
|
|
220
|
+
if (this.fileRoutingEnabled) {
|
|
221
|
+
await this.loadFileRoutes();
|
|
222
|
+
}
|
|
223
|
+
// Start IPC server first
|
|
224
|
+
console.log("[Zap] Starting IPC server...");
|
|
225
|
+
await this.ipcServer.start();
|
|
226
|
+
// Register all handlers with IPC server
|
|
227
|
+
console.log(`[Zap] Registering ${this.handlers.size} handlers...`);
|
|
228
|
+
for (const [handlerId, handler] of this.handlers) {
|
|
229
|
+
this.ipcServer.registerHandler(handlerId, async (req) => {
|
|
230
|
+
const result = await handler(req);
|
|
231
|
+
// Handle different response types
|
|
232
|
+
if (result instanceof Response) {
|
|
233
|
+
// Convert Headers to Record<string, string>
|
|
234
|
+
const headersObj = {};
|
|
235
|
+
result.headers.forEach((value, key) => {
|
|
236
|
+
headersObj[key] = value;
|
|
237
|
+
});
|
|
238
|
+
return {
|
|
239
|
+
status: result.status,
|
|
240
|
+
headers: headersObj,
|
|
241
|
+
body: await result.text(),
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
if (typeof result === "string") {
|
|
245
|
+
return {
|
|
246
|
+
status: 200,
|
|
247
|
+
headers: { "content-type": "text/plain" },
|
|
248
|
+
body: result,
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
// Default to JSON
|
|
252
|
+
return {
|
|
253
|
+
status: 200,
|
|
254
|
+
headers: { "content-type": "application/json" },
|
|
255
|
+
body: JSON.stringify(result),
|
|
256
|
+
};
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
// Build Rust configuration
|
|
260
|
+
const config = {
|
|
261
|
+
port: this.port,
|
|
262
|
+
hostname: this.hostname,
|
|
263
|
+
ipc_socket_path: this.processManager.getSocketPath(),
|
|
264
|
+
routes: this.routes,
|
|
265
|
+
static_files: this.staticFiles,
|
|
266
|
+
middleware: {
|
|
267
|
+
enable_cors: this.enableCors,
|
|
268
|
+
enable_logging: this.enableLogging,
|
|
269
|
+
enable_compression: this.enableCompression,
|
|
270
|
+
},
|
|
271
|
+
health_check_path: this.healthCheckPath,
|
|
272
|
+
metrics_path: this.metricsPath ?? undefined,
|
|
273
|
+
};
|
|
274
|
+
// Start Rust server process
|
|
275
|
+
console.log("[Zap] Starting Rust server process...");
|
|
276
|
+
await this.processManager.start(config, this.logLevel);
|
|
277
|
+
console.log(`[Zap] Server listening on http://${this.hostname}:${this.port}`);
|
|
278
|
+
}
|
|
279
|
+
catch (error) {
|
|
280
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
281
|
+
console.error("[Zap] Failed to start server:", message);
|
|
282
|
+
await this.close();
|
|
283
|
+
throw error;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Close the server gracefully
|
|
288
|
+
*/
|
|
289
|
+
async close() {
|
|
290
|
+
console.log("[Zap] Closing server...");
|
|
291
|
+
try {
|
|
292
|
+
await this.processManager.stop();
|
|
293
|
+
await this.ipcServer.stop();
|
|
294
|
+
console.log("[Zap] Server closed");
|
|
295
|
+
}
|
|
296
|
+
catch (error) {
|
|
297
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
298
|
+
console.error("[Zap] Error closing server:", message);
|
|
299
|
+
throw error;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Check if server is running
|
|
304
|
+
*/
|
|
305
|
+
isRunning() {
|
|
306
|
+
return this.processManager.isRunning();
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Load routes from generated route manifest
|
|
310
|
+
*/
|
|
311
|
+
async loadFileRoutes() {
|
|
312
|
+
const generatedDir = this.fileRoutingConfig.generatedDir || join(process.cwd(), 'src', 'generated');
|
|
313
|
+
const manifestPath = join(generatedDir, 'routeManifest.json');
|
|
314
|
+
if (!existsSync(manifestPath)) {
|
|
315
|
+
console.log("[Zap] No route manifest found. Run route scanner first.");
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
try {
|
|
319
|
+
const manifestContent = readFileSync(manifestPath, 'utf-8');
|
|
320
|
+
const manifest = JSON.parse(manifestContent);
|
|
321
|
+
console.log(`[Zap] Loading ${manifest.apiRoutes?.length ?? 0} API routes from manifest...`);
|
|
322
|
+
// Register API routes
|
|
323
|
+
for (const route of manifest.apiRoutes ?? []) {
|
|
324
|
+
// Convert :param to Rust radix router format
|
|
325
|
+
const rustPath = route.urlPath;
|
|
326
|
+
// Import the route handler module
|
|
327
|
+
const routeFile = join(process.cwd(), 'routes', route.filePath);
|
|
328
|
+
if (existsSync(routeFile.replace(/\.ts$/, '.js')) || existsSync(routeFile)) {
|
|
329
|
+
try {
|
|
330
|
+
const routeModule = await import(routeFile);
|
|
331
|
+
// Register each HTTP method handler
|
|
332
|
+
const methods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'];
|
|
333
|
+
for (const method of methods) {
|
|
334
|
+
const methodHandler = routeModule[method];
|
|
335
|
+
if (methodHandler) {
|
|
336
|
+
this.registerRoute(method, rustPath, methodHandler);
|
|
337
|
+
console.log(`[Zap] ${method} ${rustPath}`);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
catch (err) {
|
|
342
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
343
|
+
console.log(`[Zap] Failed to import ${routeFile}: ${message}`);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
catch (err) {
|
|
349
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
350
|
+
console.error("[Zap] Failed to load route manifest:", message);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
// ============================================================================
|
|
355
|
+
// Namespace Exports (Clean API)
|
|
356
|
+
// ============================================================================
|
|
357
|
+
/**
|
|
358
|
+
* Router namespace - all routing functionality
|
|
359
|
+
* Usage: import { router } from '@zap-js/client'
|
|
360
|
+
*/
|
|
361
|
+
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";
|
|
362
|
+
export const router = {
|
|
363
|
+
RouterProvider,
|
|
364
|
+
useRouter: useRouterFn,
|
|
365
|
+
useParams: useParamsFn,
|
|
366
|
+
usePathname: usePathnameFn,
|
|
367
|
+
useSearchParams: useSearchParamsFn,
|
|
368
|
+
useRouteMatch: useRouteMatchFn,
|
|
369
|
+
useIsPending: useIsPendingFn,
|
|
370
|
+
Link,
|
|
371
|
+
NavLink,
|
|
372
|
+
Outlet,
|
|
373
|
+
Redirect,
|
|
374
|
+
};
|
|
375
|
+
/**
|
|
376
|
+
* Errors namespace - error handling and boundaries
|
|
377
|
+
* Usage: import { errors } from '@zap-js/client'
|
|
378
|
+
*/
|
|
379
|
+
import { ErrorBoundary, DefaultErrorComponent, createRouteError, ZapError, } from "./error-boundary.js";
|
|
380
|
+
import { useRouteError, useIsErrorState, useErrorState, } from "./hooks.js";
|
|
381
|
+
export const errors = {
|
|
382
|
+
ErrorBoundary,
|
|
383
|
+
DefaultErrorComponent,
|
|
384
|
+
createRouteError,
|
|
385
|
+
ZapError,
|
|
386
|
+
useRouteError,
|
|
387
|
+
useIsErrorState,
|
|
388
|
+
useErrorState,
|
|
389
|
+
};
|
|
390
|
+
/**
|
|
391
|
+
* Middleware namespace - route middleware utilities
|
|
392
|
+
* Usage: import { middleware } from '@zap-js/client'
|
|
393
|
+
*/
|
|
394
|
+
import { composeMiddleware, requireAuth, requireRole, routeLogger, preloadData, } from "./middleware.js";
|
|
395
|
+
export const middleware = {
|
|
396
|
+
compose: composeMiddleware,
|
|
397
|
+
requireAuth,
|
|
398
|
+
requireRole,
|
|
399
|
+
logger: routeLogger,
|
|
400
|
+
preloadData,
|
|
401
|
+
};
|
|
402
|
+
/**
|
|
403
|
+
* Types namespace - type definitions and guards
|
|
404
|
+
* Usage: import { types } from '@zap-js/client'
|
|
405
|
+
*/
|
|
406
|
+
import * as TypeGuards from "./types.js";
|
|
407
|
+
export const types = {
|
|
408
|
+
isInvokeHandlerMessage: TypeGuards.isInvokeHandlerMessage,
|
|
409
|
+
isHandlerResponseMessage: TypeGuards.isHandlerResponseMessage,
|
|
410
|
+
isErrorMessage: TypeGuards.isErrorMessage,
|
|
411
|
+
isHealthCheckMessage: TypeGuards.isHealthCheckMessage,
|
|
412
|
+
isHealthCheckResponseMessage: TypeGuards.isHealthCheckResponseMessage,
|
|
413
|
+
isRpcResponseMessage: TypeGuards.isRpcResponseMessage,
|
|
414
|
+
isRpcErrorMessage: TypeGuards.isRpcErrorMessage,
|
|
415
|
+
isAsyncIterable: TypeGuards.isAsyncIterable,
|
|
416
|
+
};
|
|
417
|
+
/**
|
|
418
|
+
* WebSockets namespace - WebSocket utilities and helpers
|
|
419
|
+
* Usage: import { websockets } from '@zap-js/client'
|
|
420
|
+
*/
|
|
421
|
+
import * as WebSocketUtils from "./websockets-utils.js";
|
|
422
|
+
export const websockets = {
|
|
423
|
+
isWsMessage: WebSocketUtils.isWsMessage,
|
|
424
|
+
broadcast: WebSocketUtils.broadcast,
|
|
425
|
+
broadcastExcept: WebSocketUtils.broadcastExcept,
|
|
426
|
+
sendJson: WebSocketUtils.sendJson,
|
|
427
|
+
parseMessage: WebSocketUtils.parseMessage,
|
|
428
|
+
createErrorMessage: WebSocketUtils.createErrorMessage,
|
|
429
|
+
createSuccessMessage: WebSocketUtils.createSuccessMessage,
|
|
430
|
+
};
|
|
431
|
+
/**
|
|
432
|
+
* Streaming namespace - Streaming response utilities
|
|
433
|
+
* Usage: import { streaming } from '@zap-js/client'
|
|
434
|
+
*/
|
|
435
|
+
import * as StreamingUtils from "./streaming-utils.js";
|
|
436
|
+
export const streaming = {
|
|
437
|
+
isAsyncIterable: StreamingUtils.isAsyncIterable,
|
|
438
|
+
createChunk: StreamingUtils.createChunk,
|
|
439
|
+
createStream: StreamingUtils.createStream,
|
|
440
|
+
streamJson: StreamingUtils.streamJson,
|
|
441
|
+
streamSSE: StreamingUtils.streamSSE,
|
|
442
|
+
mapStream: StreamingUtils.mapStream,
|
|
443
|
+
filterStream: StreamingUtils.filterStream,
|
|
444
|
+
batchStream: StreamingUtils.batchStream,
|
|
445
|
+
delayStream: StreamingUtils.delayStream,
|
|
446
|
+
fromReadableStream: StreamingUtils.fromReadableStream,
|
|
447
|
+
intervalStream: StreamingUtils.intervalStream,
|
|
448
|
+
};
|
|
449
|
+
export default Zap;
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { EventEmitter } from "events";
|
|
2
|
+
import type { ZapRequest, ZapHandlerResponse, IpcMessage, StreamChunk, WsHandler } from "./types.js";
|
|
3
|
+
export type { ZapRequest as IpcRequest } from "./types.js";
|
|
4
|
+
/**
|
|
5
|
+
* IPC encoding format
|
|
6
|
+
*/
|
|
7
|
+
export type IpcEncoding = "msgpack" | "json";
|
|
8
|
+
/**
|
|
9
|
+
* Handler function type for IPC server (supports regular and streaming responses)
|
|
10
|
+
*/
|
|
11
|
+
export type HandlerFunction = (req: ZapRequest) => Promise<ZapHandlerResponse> | AsyncIterable<StreamChunk>;
|
|
12
|
+
/**
|
|
13
|
+
* Streaming handler function type
|
|
14
|
+
*/
|
|
15
|
+
export type StreamingHandlerFunction = (req: ZapRequest) => AsyncIterable<StreamChunk>;
|
|
16
|
+
/**
|
|
17
|
+
* WebSocket handler function type
|
|
18
|
+
*/
|
|
19
|
+
export type WsHandlerFunction = WsHandler;
|
|
20
|
+
/**
|
|
21
|
+
* Serialize an IPC message to bytes
|
|
22
|
+
*/
|
|
23
|
+
declare function serializeMessage(msg: IpcMessage, encoding: IpcEncoding): Buffer;
|
|
24
|
+
/**
|
|
25
|
+
* Deserialize an IPC message from bytes (auto-detects encoding)
|
|
26
|
+
*/
|
|
27
|
+
declare function deserializeMessage(data: Buffer): IpcMessage;
|
|
28
|
+
/**
|
|
29
|
+
* FrameReader - reads length-prefixed frames from a socket
|
|
30
|
+
*/
|
|
31
|
+
declare class FrameReader {
|
|
32
|
+
private buffer;
|
|
33
|
+
private onFrame;
|
|
34
|
+
constructor(onFrame: (frame: Buffer) => void);
|
|
35
|
+
/**
|
|
36
|
+
* Process incoming data chunks
|
|
37
|
+
*/
|
|
38
|
+
push(chunk: Buffer): void;
|
|
39
|
+
/**
|
|
40
|
+
* Reset the buffer
|
|
41
|
+
*/
|
|
42
|
+
reset(): void;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* IpcServer
|
|
46
|
+
*
|
|
47
|
+
* Listens on a Unix socket for IPC messages from the Rust backend.
|
|
48
|
+
* The Rust server sends handler invocation requests, which we dispatch
|
|
49
|
+
* to the registered TypeScript handlers and send responses back.
|
|
50
|
+
*
|
|
51
|
+
* Protocol: Length-prefixed MessagePack (default) with JSON fallback
|
|
52
|
+
* Frame format: [4-byte big-endian length][payload]
|
|
53
|
+
*/
|
|
54
|
+
export declare class IpcServer {
|
|
55
|
+
private server;
|
|
56
|
+
private socketPath;
|
|
57
|
+
private handlers;
|
|
58
|
+
private wsHandlers;
|
|
59
|
+
private wsConnections;
|
|
60
|
+
private encoding;
|
|
61
|
+
private currentSocket;
|
|
62
|
+
constructor(socketPath: string, encoding?: IpcEncoding);
|
|
63
|
+
/**
|
|
64
|
+
* Register a handler function for a specific handler ID
|
|
65
|
+
*/
|
|
66
|
+
registerHandler(handlerId: string, handler: HandlerFunction): void;
|
|
67
|
+
/**
|
|
68
|
+
* Register a WebSocket handler for a specific handler ID
|
|
69
|
+
*/
|
|
70
|
+
registerWsHandler(handlerId: string, handler: WsHandlerFunction): void;
|
|
71
|
+
/**
|
|
72
|
+
* Start the IPC server listening on the Unix socket
|
|
73
|
+
*/
|
|
74
|
+
start(): Promise<void>;
|
|
75
|
+
/**
|
|
76
|
+
* Handle a new IPC connection from the Rust server
|
|
77
|
+
*/
|
|
78
|
+
private handleConnection;
|
|
79
|
+
/**
|
|
80
|
+
* Handle a complete frame
|
|
81
|
+
*/
|
|
82
|
+
private handleFrame;
|
|
83
|
+
/**
|
|
84
|
+
* Process an incoming IPC message
|
|
85
|
+
*/
|
|
86
|
+
private processMessage;
|
|
87
|
+
/**
|
|
88
|
+
* Handle a streaming response from a handler
|
|
89
|
+
*/
|
|
90
|
+
private handleStreamingResponse;
|
|
91
|
+
/**
|
|
92
|
+
* Send a message to a WebSocket client via the Rust server
|
|
93
|
+
*/
|
|
94
|
+
sendWsMessage(connectionId: string, data: string, binary: boolean): void;
|
|
95
|
+
/**
|
|
96
|
+
* Close a WebSocket connection via the Rust server
|
|
97
|
+
*/
|
|
98
|
+
closeWsConnection(connectionId: string, code?: number, reason?: string): void;
|
|
99
|
+
/**
|
|
100
|
+
* Stop the IPC server
|
|
101
|
+
*/
|
|
102
|
+
stop(): Promise<void>;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* IpcClient
|
|
106
|
+
*
|
|
107
|
+
* Connects to a Unix socket to communicate with the Rust server.
|
|
108
|
+
* Used for RPC calls from TypeScript to Rust.
|
|
109
|
+
*
|
|
110
|
+
* Protocol: Length-prefixed MessagePack (default) with JSON fallback
|
|
111
|
+
*/
|
|
112
|
+
export declare class IpcClient extends EventEmitter {
|
|
113
|
+
private socket;
|
|
114
|
+
private socketPath;
|
|
115
|
+
private connected;
|
|
116
|
+
private frameReader;
|
|
117
|
+
private encoding;
|
|
118
|
+
constructor(socketPath: string, encoding?: IpcEncoding);
|
|
119
|
+
/**
|
|
120
|
+
* Connect to the Unix socket
|
|
121
|
+
*/
|
|
122
|
+
private connect;
|
|
123
|
+
/**
|
|
124
|
+
* Send a message to the server
|
|
125
|
+
*/
|
|
126
|
+
send(message: IpcMessage): void;
|
|
127
|
+
/**
|
|
128
|
+
* Send a message and wait for response
|
|
129
|
+
*/
|
|
130
|
+
sendRecv(message: IpcMessage): Promise<IpcMessage>;
|
|
131
|
+
/**
|
|
132
|
+
* Close the connection
|
|
133
|
+
*/
|
|
134
|
+
close(): Promise<void>;
|
|
135
|
+
/**
|
|
136
|
+
* Check if connected
|
|
137
|
+
*/
|
|
138
|
+
isConnected(): boolean;
|
|
139
|
+
/**
|
|
140
|
+
* Get the encoding being used
|
|
141
|
+
*/
|
|
142
|
+
getEncoding(): IpcEncoding;
|
|
143
|
+
}
|
|
144
|
+
export { serializeMessage, deserializeMessage, FrameReader };
|