@zap-js/server 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/index.js +18 -14
- package/package.json +4 -9
- package/src/bin/zap.rs +0 -154
- package/src/config.rs +0 -253
- package/src/connection_pool.rs +0 -404
- package/src/error.rs +0 -380
- package/src/handler.rs +0 -89
- package/src/ipc.js +0 -10
- package/src/ipc.rs +0 -499
- package/src/lib.rs +0 -433
- package/src/metrics.rs +0 -264
- package/src/proxy.rs +0 -436
- package/src/reliability.rs +0 -917
- package/src/request.rs +0 -60
- package/src/request_id.rs +0 -97
- package/src/response.rs +0 -182
- package/src/rpc.js +0 -14
- package/src/server.rs +0 -597
- package/src/static.rs +0 -572
- package/src/types.js +0 -21
- package/src/utils.rs +0 -18
- package/src/websocket.rs +0 -429
package/index.js
CHANGED
|
@@ -1,21 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @zap-js/server
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
4
|
* ZapJS server communication utilities
|
|
5
|
+
* Re-exports from @zap-js/client
|
|
5
6
|
*/
|
|
6
7
|
|
|
7
|
-
//
|
|
8
|
-
import rpc from './src/rpc.js';
|
|
8
|
+
// Namespace exports (Clean API)
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
/**
|
|
11
|
+
* RPC namespace - Remote Procedure Call utilities
|
|
12
|
+
* Usage: import { rpc } from '@zap-js/server'
|
|
13
|
+
* Then: rpc.call('functionName', args)
|
|
14
|
+
*/
|
|
15
|
+
import { rpcCall } from '@zap-js/client';
|
|
16
|
+
export const rpc = {
|
|
17
|
+
call: rpcCall,
|
|
18
|
+
};
|
|
15
19
|
|
|
16
|
-
|
|
17
|
-
export
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
/**
|
|
21
|
+
* Types namespace - re-export from client
|
|
22
|
+
* Usage: import { types } from '@zap-js/server'
|
|
23
|
+
*/
|
|
24
|
+
import { types as clientTypes } from '@zap-js/client';
|
|
25
|
+
export const types = clientTypes;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zap-js/server",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "High-performance fullstack React framework - Server package with Rust-powered backend",
|
|
5
5
|
"homepage": "https://github.com/saint0x/zapjs",
|
|
6
6
|
"repository": {
|
|
@@ -16,15 +16,10 @@
|
|
|
16
16
|
".": "./index.js"
|
|
17
17
|
},
|
|
18
18
|
"files": [
|
|
19
|
-
"index.js"
|
|
20
|
-
"src",
|
|
21
|
-
"internal",
|
|
22
|
-
"!internal/*/src/**/*.rs",
|
|
23
|
-
"!internal/*/Cargo.toml"
|
|
19
|
+
"index.js"
|
|
24
20
|
],
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"clean": "rm -rf dist"
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"@zap-js/client": "^0.0.4"
|
|
28
23
|
},
|
|
29
24
|
"keywords": [
|
|
30
25
|
"zap",
|
package/src/bin/zap.rs
DELETED
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
//! Zap HTTP Server - High-Performance Rust-Based Server
|
|
2
|
-
//!
|
|
3
|
-
//! Ultra-fast HTTP server with SIMD optimizations and Unix socket IPC
|
|
4
|
-
//! for TypeScript handler invocation.
|
|
5
|
-
|
|
6
|
-
use clap::Parser;
|
|
7
|
-
use std::path::PathBuf;
|
|
8
|
-
use tokio::signal;
|
|
9
|
-
use tracing::{error, info};
|
|
10
|
-
use tracing_subscriber::EnvFilter;
|
|
11
|
-
|
|
12
|
-
use zap_server::config::ZapConfig;
|
|
13
|
-
use zap_server::error::ZapResult;
|
|
14
|
-
use zap_server::Zap;
|
|
15
|
-
|
|
16
|
-
#[derive(Parser, Debug)]
|
|
17
|
-
#[command(name = "Zap")]
|
|
18
|
-
#[command(version = "1.0.0")]
|
|
19
|
-
#[command(about = "Ultra-fast HTTP server for Node.js/Bun", long_about = None)]
|
|
20
|
-
struct Args {
|
|
21
|
-
/// Path to JSON configuration file
|
|
22
|
-
#[arg(short, long)]
|
|
23
|
-
config: PathBuf,
|
|
24
|
-
|
|
25
|
-
/// Override HTTP server port
|
|
26
|
-
#[arg(short, long)]
|
|
27
|
-
port: Option<u16>,
|
|
28
|
-
|
|
29
|
-
/// Override HTTP server hostname
|
|
30
|
-
#[arg(long)]
|
|
31
|
-
hostname: Option<String>,
|
|
32
|
-
|
|
33
|
-
/// Unix socket path for IPC with TypeScript wrapper
|
|
34
|
-
#[arg(short, long)]
|
|
35
|
-
socket: Option<String>,
|
|
36
|
-
|
|
37
|
-
/// Log level (trace, debug, info, warn, error)
|
|
38
|
-
#[arg(long, default_value = "info")]
|
|
39
|
-
log_level: String,
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
#[tokio::main]
|
|
43
|
-
async fn main() -> ZapResult<()> {
|
|
44
|
-
let args = Args::parse();
|
|
45
|
-
|
|
46
|
-
// Initialize logging
|
|
47
|
-
init_logging(&args.log_level)?;
|
|
48
|
-
|
|
49
|
-
info!("🚀 Starting Zap HTTP server v1.0.0");
|
|
50
|
-
|
|
51
|
-
// Load configuration from JSON file
|
|
52
|
-
let mut config = ZapConfig::from_file(args.config.to_str().unwrap())?;
|
|
53
|
-
|
|
54
|
-
info!(
|
|
55
|
-
"📋 Configuration loaded from {}",
|
|
56
|
-
args.config.display()
|
|
57
|
-
);
|
|
58
|
-
|
|
59
|
-
// Apply CLI argument overrides
|
|
60
|
-
if let Some(port) = args.port {
|
|
61
|
-
info!("⚙️ Overriding port: {}", port);
|
|
62
|
-
config.port = port;
|
|
63
|
-
}
|
|
64
|
-
if let Some(hostname) = args.hostname {
|
|
65
|
-
info!("⚙️ Overriding hostname: {}", hostname);
|
|
66
|
-
config.hostname = hostname;
|
|
67
|
-
}
|
|
68
|
-
if let Some(socket) = args.socket {
|
|
69
|
-
info!("⚙️ Overriding IPC socket: {}", socket);
|
|
70
|
-
config.ipc_socket_path = socket;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Validate configuration
|
|
74
|
-
config.validate().await?;
|
|
75
|
-
|
|
76
|
-
info!(
|
|
77
|
-
"📡 Server will listen on http://{}:{}",
|
|
78
|
-
config.hostname, config.port
|
|
79
|
-
);
|
|
80
|
-
info!("🔌 IPC socket: {}", config.ipc_socket_path);
|
|
81
|
-
info!("📊 Routes: {}", config.routes.len());
|
|
82
|
-
info!("📁 Static files: {}", config.static_files.len());
|
|
83
|
-
|
|
84
|
-
// Create and start the server
|
|
85
|
-
let app = Zap::from_config(config).await?;
|
|
86
|
-
|
|
87
|
-
info!("✅ Zap server initialized successfully");
|
|
88
|
-
|
|
89
|
-
// Run the server (blocks until signal)
|
|
90
|
-
// Note: listen() takes ownership and runs indefinitely
|
|
91
|
-
tokio::select! {
|
|
92
|
-
result = app.listen() => {
|
|
93
|
-
if let Err(e) = result {
|
|
94
|
-
error!("Server error: {}", e);
|
|
95
|
-
return Err(e);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
_ = setup_signal_handlers() => {
|
|
99
|
-
info!("📛 Received shutdown signal");
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
info!("👋 Zap server shut down successfully");
|
|
104
|
-
Ok(())
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/// Initialize structured logging with configurable level
|
|
108
|
-
fn init_logging(level: &str) -> ZapResult<()> {
|
|
109
|
-
let env_filter = level.parse::<EnvFilter>().map_err(|e| {
|
|
110
|
-
zap_server::error::ZapError::config(format!(
|
|
111
|
-
"Invalid log level '{}': {}",
|
|
112
|
-
level, e
|
|
113
|
-
))
|
|
114
|
-
})?;
|
|
115
|
-
|
|
116
|
-
tracing_subscriber::fmt()
|
|
117
|
-
.with_env_filter(env_filter)
|
|
118
|
-
.with_target(true)
|
|
119
|
-
.with_file(true)
|
|
120
|
-
.with_line_number(true)
|
|
121
|
-
.with_ansi(true)
|
|
122
|
-
.init();
|
|
123
|
-
|
|
124
|
-
Ok(())
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/// Setup Unix signal handlers for graceful shutdown
|
|
128
|
-
async fn setup_signal_handlers() {
|
|
129
|
-
#[cfg(unix)]
|
|
130
|
-
{
|
|
131
|
-
let mut sigterm = signal::unix::signal(signal::unix::SignalKind::terminate())
|
|
132
|
-
.expect("Failed to setup SIGTERM handler");
|
|
133
|
-
let mut sigint = signal::unix::signal(signal::unix::SignalKind::interrupt())
|
|
134
|
-
.expect("Failed to setup SIGINT handler");
|
|
135
|
-
|
|
136
|
-
tokio::select! {
|
|
137
|
-
_ = sigterm.recv() => {
|
|
138
|
-
info!("Received SIGTERM signal");
|
|
139
|
-
}
|
|
140
|
-
_ = sigint.recv() => {
|
|
141
|
-
info!("Received SIGINT signal");
|
|
142
|
-
}
|
|
143
|
-
_ = signal::ctrl_c() => {
|
|
144
|
-
info!("Received Ctrl+C");
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
#[cfg(not(unix))]
|
|
150
|
-
{
|
|
151
|
-
let _ = signal::ctrl_c().await;
|
|
152
|
-
info!("Received Ctrl+C");
|
|
153
|
-
}
|
|
154
|
-
}
|
package/src/config.rs
DELETED
|
@@ -1,253 +0,0 @@
|
|
|
1
|
-
//! Server configuration
|
|
2
|
-
//!
|
|
3
|
-
//! Comprehensive configuration system supporting:
|
|
4
|
-
//! - JSON config files
|
|
5
|
-
//! - Environment variables
|
|
6
|
-
//! - CLI argument overrides
|
|
7
|
-
|
|
8
|
-
use serde::{Deserialize, Serialize};
|
|
9
|
-
use std::time::Duration;
|
|
10
|
-
use crate::error::{ZapError, ZapResult};
|
|
11
|
-
|
|
12
|
-
/// Complete Zap server configuration
|
|
13
|
-
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
14
|
-
pub struct ZapConfig {
|
|
15
|
-
/// HTTP server port
|
|
16
|
-
pub port: u16,
|
|
17
|
-
|
|
18
|
-
/// HTTP server hostname
|
|
19
|
-
pub hostname: String,
|
|
20
|
-
|
|
21
|
-
/// Unix domain socket path for IPC with TypeScript
|
|
22
|
-
pub ipc_socket_path: String,
|
|
23
|
-
|
|
24
|
-
/// Maximum request body size in bytes (default: 16MB)
|
|
25
|
-
#[serde(default = "default_max_body_size")]
|
|
26
|
-
pub max_request_body_size: usize,
|
|
27
|
-
|
|
28
|
-
/// Request timeout in seconds
|
|
29
|
-
#[serde(default = "default_request_timeout")]
|
|
30
|
-
pub request_timeout_secs: u64,
|
|
31
|
-
|
|
32
|
-
/// Keep-alive timeout in seconds
|
|
33
|
-
#[serde(default = "default_keepalive_timeout")]
|
|
34
|
-
pub keepalive_timeout_secs: u64,
|
|
35
|
-
|
|
36
|
-
/// Route configurations
|
|
37
|
-
#[serde(default)]
|
|
38
|
-
pub routes: Vec<RouteConfig>,
|
|
39
|
-
|
|
40
|
-
/// Static file configurations
|
|
41
|
-
#[serde(default)]
|
|
42
|
-
pub static_files: Vec<StaticFileConfig>,
|
|
43
|
-
|
|
44
|
-
/// Middleware settings
|
|
45
|
-
#[serde(default)]
|
|
46
|
-
pub middleware: MiddlewareConfig,
|
|
47
|
-
|
|
48
|
-
/// Health check endpoint path
|
|
49
|
-
#[serde(default = "default_health_path")]
|
|
50
|
-
pub health_check_path: String,
|
|
51
|
-
|
|
52
|
-
/// Metrics endpoint path
|
|
53
|
-
#[serde(default)]
|
|
54
|
-
pub metrics_path: Option<String>,
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/// Route configuration
|
|
58
|
-
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
59
|
-
pub struct RouteConfig {
|
|
60
|
-
/// HTTP method: GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS
|
|
61
|
-
pub method: String,
|
|
62
|
-
|
|
63
|
-
/// URL path pattern: /api/users/:id
|
|
64
|
-
pub path: String,
|
|
65
|
-
|
|
66
|
-
/// Handler ID: handler_0, handler_1, etc.
|
|
67
|
-
pub handler_id: String,
|
|
68
|
-
|
|
69
|
-
/// Is this a TypeScript handler (needs IPC), or Rust native?
|
|
70
|
-
#[serde(default = "default_is_typescript")]
|
|
71
|
-
pub is_typescript: bool,
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/// Static file serving configuration
|
|
75
|
-
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
76
|
-
pub struct StaticFileConfig {
|
|
77
|
-
/// URL prefix: /static
|
|
78
|
-
pub prefix: String,
|
|
79
|
-
|
|
80
|
-
/// Directory path: ./public
|
|
81
|
-
pub directory: String,
|
|
82
|
-
|
|
83
|
-
/// Additional options
|
|
84
|
-
#[serde(default)]
|
|
85
|
-
pub options: StaticFileOptions,
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/// Static file serving options
|
|
89
|
-
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
|
90
|
-
pub struct StaticFileOptions {
|
|
91
|
-
/// Cache control header value
|
|
92
|
-
#[serde(default)]
|
|
93
|
-
pub cache_control: Option<String>,
|
|
94
|
-
|
|
95
|
-
/// Enable gzip compression
|
|
96
|
-
#[serde(default)]
|
|
97
|
-
pub enable_gzip: bool,
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/// Middleware configuration
|
|
101
|
-
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
|
102
|
-
pub struct MiddlewareConfig {
|
|
103
|
-
/// Enable CORS middleware
|
|
104
|
-
#[serde(default)]
|
|
105
|
-
pub enable_cors: bool,
|
|
106
|
-
|
|
107
|
-
/// Enable request logging middleware
|
|
108
|
-
#[serde(default)]
|
|
109
|
-
pub enable_logging: bool,
|
|
110
|
-
|
|
111
|
-
/// Enable response compression
|
|
112
|
-
#[serde(default)]
|
|
113
|
-
pub enable_compression: bool,
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
impl Default for ZapConfig {
|
|
117
|
-
fn default() -> Self {
|
|
118
|
-
Self {
|
|
119
|
-
port: 3000,
|
|
120
|
-
hostname: "127.0.0.1".to_string(),
|
|
121
|
-
ipc_socket_path: "/tmp/zap.sock".to_string(),
|
|
122
|
-
max_request_body_size: 16 * 1024 * 1024, // 16MB
|
|
123
|
-
request_timeout_secs: 30,
|
|
124
|
-
keepalive_timeout_secs: 75,
|
|
125
|
-
routes: Vec::new(),
|
|
126
|
-
static_files: Vec::new(),
|
|
127
|
-
middleware: MiddlewareConfig::default(),
|
|
128
|
-
health_check_path: "/health".to_string(),
|
|
129
|
-
metrics_path: None,
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
impl ZapConfig {
|
|
135
|
-
/// Create a new config with defaults
|
|
136
|
-
pub fn new() -> Self {
|
|
137
|
-
Self::default()
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/// Load configuration from a JSON file
|
|
141
|
-
pub fn from_file(path: &str) -> ZapResult<Self> {
|
|
142
|
-
let content = std::fs::read_to_string(path)
|
|
143
|
-
.map_err(|e| ZapError::config(format!("Failed to read config file: {}", e)))?;
|
|
144
|
-
|
|
145
|
-
let config = serde_json::from_str(&content)
|
|
146
|
-
.map_err(|e| ZapError::config(format!("Failed to parse config JSON: {}", e)))?;
|
|
147
|
-
|
|
148
|
-
Ok(config)
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/// Validate configuration
|
|
152
|
-
pub async fn validate(&self) -> ZapResult<()> {
|
|
153
|
-
if self.port == 0 {
|
|
154
|
-
return Err(ZapError::config("Port must be > 0"));
|
|
155
|
-
}
|
|
156
|
-
if self.hostname.is_empty() {
|
|
157
|
-
return Err(ZapError::config("Hostname cannot be empty"));
|
|
158
|
-
}
|
|
159
|
-
if self.ipc_socket_path.is_empty() {
|
|
160
|
-
return Err(ZapError::config("IPC socket path cannot be empty"));
|
|
161
|
-
}
|
|
162
|
-
if self.request_timeout_secs == 0 {
|
|
163
|
-
return Err(ZapError::config("Request timeout must be > 0"));
|
|
164
|
-
}
|
|
165
|
-
Ok(())
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/// Get socket address as string
|
|
169
|
-
pub fn socket_addr(&self) -> String {
|
|
170
|
-
format!("{}:{}", self.hostname, self.port)
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
/// Get request timeout as Duration
|
|
174
|
-
pub fn request_timeout(&self) -> Duration {
|
|
175
|
-
Duration::from_secs(self.request_timeout_secs)
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
/// Get keep-alive timeout as Duration
|
|
179
|
-
pub fn keepalive_timeout(&self) -> Duration {
|
|
180
|
-
Duration::from_secs(self.keepalive_timeout_secs)
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
// Default function values for serde
|
|
185
|
-
fn default_max_body_size() -> usize { 16 * 1024 * 1024 }
|
|
186
|
-
fn default_request_timeout() -> u64 { 30 }
|
|
187
|
-
fn default_keepalive_timeout() -> u64 { 75 }
|
|
188
|
-
fn default_health_path() -> String { "/health".to_string() }
|
|
189
|
-
fn default_is_typescript() -> bool { true }
|
|
190
|
-
|
|
191
|
-
/// Legacy ServerConfig for compatibility
|
|
192
|
-
#[derive(Debug, Clone)]
|
|
193
|
-
pub struct ServerConfig {
|
|
194
|
-
pub port: u16,
|
|
195
|
-
pub hostname: String,
|
|
196
|
-
pub keep_alive_timeout: Duration,
|
|
197
|
-
pub max_request_body_size: usize,
|
|
198
|
-
pub max_headers: usize,
|
|
199
|
-
pub request_timeout: Duration,
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
impl Default for ServerConfig {
|
|
203
|
-
fn default() -> Self {
|
|
204
|
-
Self {
|
|
205
|
-
port: 3000,
|
|
206
|
-
hostname: "127.0.0.1".to_string(),
|
|
207
|
-
keep_alive_timeout: Duration::from_secs(75),
|
|
208
|
-
max_request_body_size: 16 * 1024 * 1024,
|
|
209
|
-
max_headers: 100,
|
|
210
|
-
request_timeout: Duration::from_secs(30),
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
impl ServerConfig {
|
|
216
|
-
pub fn new() -> Self {
|
|
217
|
-
Self::default()
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
pub fn port(mut self, port: u16) -> Self {
|
|
221
|
-
self.port = port;
|
|
222
|
-
self
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
pub fn hostname<S: Into<String>>(mut self, hostname: S) -> Self {
|
|
226
|
-
self.hostname = hostname.into();
|
|
227
|
-
self
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
pub fn keep_alive_timeout(mut self, timeout: Duration) -> Self {
|
|
231
|
-
self.keep_alive_timeout = timeout;
|
|
232
|
-
self
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
pub fn max_request_body_size(mut self, size: usize) -> Self {
|
|
236
|
-
self.max_request_body_size = size;
|
|
237
|
-
self
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
pub fn max_headers(mut self, count: usize) -> Self {
|
|
241
|
-
self.max_headers = count;
|
|
242
|
-
self
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
pub fn request_timeout(mut self, timeout: Duration) -> Self {
|
|
246
|
-
self.request_timeout = timeout;
|
|
247
|
-
self
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
pub fn socket_addr(&self) -> String {
|
|
251
|
-
format!("{}:{}", self.hostname, self.port)
|
|
252
|
-
}
|
|
253
|
-
}
|