@assetsart/nylon-mesh 1.0.1

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 (49) hide show
  1. package/.github/workflows/release.yml +98 -0
  2. package/Cargo.lock +2965 -0
  3. package/Cargo.toml +33 -0
  4. package/README.md +104 -0
  5. package/bin/nylon-mesh.js +213 -0
  6. package/bun.lock +360 -0
  7. package/docs/content/docs/caching.mdx +85 -0
  8. package/docs/content/docs/configuration.mdx +115 -0
  9. package/docs/content/docs/index.mdx +58 -0
  10. package/docs/content/docs/load-balancing.mdx +69 -0
  11. package/docs/content/docs/meta.json +9 -0
  12. package/docs/next.config.mjs +11 -0
  13. package/docs/package-lock.json +6099 -0
  14. package/docs/package.json +32 -0
  15. package/docs/postcss.config.mjs +7 -0
  16. package/docs/source.config.ts +23 -0
  17. package/docs/src/app/(home)/layout.tsx +6 -0
  18. package/docs/src/app/(home)/page.tsx +125 -0
  19. package/docs/src/app/api/search/route.ts +9 -0
  20. package/docs/src/app/docs/[[...slug]]/page.tsx +46 -0
  21. package/docs/src/app/docs/layout.tsx +11 -0
  22. package/docs/src/app/global.css +7 -0
  23. package/docs/src/app/layout.tsx +31 -0
  24. package/docs/src/app/llms-full.txt/route.ts +10 -0
  25. package/docs/src/app/llms.txt/route.ts +13 -0
  26. package/docs/src/app/og/docs/[...slug]/route.tsx +27 -0
  27. package/docs/src/components/ai/page-actions.tsx +240 -0
  28. package/docs/src/components/architecture-diagram.tsx +88 -0
  29. package/docs/src/components/benchmark.tsx +129 -0
  30. package/docs/src/components/configuration.tsx +107 -0
  31. package/docs/src/components/copy-button.tsx +29 -0
  32. package/docs/src/components/footer.tsx +37 -0
  33. package/docs/src/components/framework-logos.tsx +35 -0
  34. package/docs/src/lib/cn.ts +1 -0
  35. package/docs/src/lib/layout.shared.tsx +23 -0
  36. package/docs/src/lib/source.ts +27 -0
  37. package/docs/src/mdx-components.tsx +9 -0
  38. package/docs/tsconfig.json +46 -0
  39. package/nylon-mesh.yaml +41 -0
  40. package/package.json +23 -0
  41. package/scripts/publish.mjs +18 -0
  42. package/scripts/release.mjs +52 -0
  43. package/src/config.rs +91 -0
  44. package/src/main.rs +214 -0
  45. package/src/proxy/cache.rs +304 -0
  46. package/src/proxy/handlers.rs +76 -0
  47. package/src/proxy/load_balancer.rs +23 -0
  48. package/src/proxy/mod.rs +232 -0
  49. package/src/tls_accept.rs +119 -0
package/Cargo.toml ADDED
@@ -0,0 +1,33 @@
1
+ [package]
2
+ name = "nylon-mesh"
3
+ version = "1.0.1"
4
+ edition = "2024"
5
+
6
+ [dependencies]
7
+ mimalloc = { version = "0.1", default-features = false, features = ["secure"] }
8
+ async-trait = "0.1"
9
+ bytes = "1.11.1"
10
+ http = "1.4.0"
11
+ moka = { version = "0.12.13", features = ["future", "sync"] }
12
+ once_cell = "1.19"
13
+ pingora = { version = "0.7.0", features = ["openssl"] }
14
+ pingora-core = { version = "0.7.0", features = ["openssl"] }
15
+ pingora-proxy = "0.7.0"
16
+ pingora-cache = "0.7.0"
17
+ pingora-load-balancing = "0.7.0"
18
+ redis = { version = "1.0.4", features = ["tokio-comp"] }
19
+ serde = { version = "1.0", features = ["derive"] }
20
+ serde_yaml = "0.9"
21
+ tokio = { version = "1.40", features = ["full"] }
22
+ tracing = "0.1"
23
+ tracing-subscriber = "0.3"
24
+ openssl = { version = "0.10", default-features = false }
25
+ serde_json = "1.0.149"
26
+
27
+ [profile.release]
28
+ overflow-checks = true
29
+ strip = true
30
+ opt-level = "z"
31
+ lto = true
32
+ codegen-units = 1
33
+ panic = "abort"
package/README.md ADDED
@@ -0,0 +1,104 @@
1
+ <div align="center">
2
+
3
+ # 🕸️ Nylon Mesh
4
+
5
+ **Cache Everything. Scale Instantly.**
6
+
7
+ [![Rust](https://img.shields.io/badge/Rust-000000?style=flat-square&logo=rust&logoColor=white)](https://www.rust-lang.org/)
8
+ [![License](https://img.shields.io/badge/License-MIT-green)](#)
9
+
10
+ *A blazing-fast edge proxy built to solve the headaches of caching for modern SSR frameworks.*
11
+
12
+ [Why Nylon Mesh?](#why-nylon-mesh) • [Features](#key-features) • [Quick Start](#installation) • [Configuration](#configuration-example-nylon-meshyaml)
13
+
14
+ </div>
15
+
16
+
17
+
18
+ ## Why Nylon Mesh?
19
+
20
+ Frameworks like **Next.js, Nuxt, React (SSR), Angular, and Vue** are powerful—but server-side rendering is computationally expensive. Running Node.js under heavy traffic without a dedicated caching layer leads to:
21
+
22
+ - High CPU usage and slow Time to First Byte (TTFB)
23
+ - Potential crashes under traffic spikes
24
+ - Complex custom caching logic inside your app
25
+
26
+ **Nylon Mesh sits in front of your app.** It intercepts HTTP requests, caches the expensive SSR-generated HTML in RAM (Tier 1) and Redis (Tier 2), and serves subsequent users instantly—dropping your backend load to near zero.
27
+
28
+ ## Key Features
29
+
30
+ - ⚡️ **Blazing Fast**: Built in Rust on top of Pingora.
31
+ - 🚀 **Two-Tier Caching**: Uses a lightning-fast in-memory RAM cache (Tier-1) and falls back to Redis (Tier-2).
32
+ - ⚖️ **Load Balancing**: Built-in support for Round Robin and Weighted routing to multiple upstream servers.
33
+ - đź›  **Zero-Code Integration**: Works with any backend by just placing it in front of your existing app. No SDKs needed.
34
+ - ⚙️ **Simple Configuration**: Easy to set up using a single YAML file.
35
+
36
+ ## Installation
37
+
38
+ Nylon Mesh is written in **Rust** for maximum performance. You can compile and run it directly:
39
+
40
+ ```bash
41
+ cargo build --release
42
+ ```
43
+
44
+ Or install it via Bun into your Node.js project:
45
+
46
+ ```bash
47
+ bun add nylon-mesh
48
+ ```
49
+
50
+ ## Initialization
51
+
52
+ Generate a ready-to-use configuration file in your project:
53
+
54
+ ```bash
55
+ bunx nylon-mesh init
56
+ ```
57
+
58
+ This creates a `nylon-mesh.yaml` in your project folder. **No code changes are required in your application.**
59
+
60
+ ## Running the Proxy
61
+
62
+ Start by pointing the proxy at your generated config file:
63
+
64
+ ```bash
65
+ cargo run --release -- nylon-mesh.yaml
66
+ ```
67
+
68
+ Or via the CLI wrapper if installed via package manager:
69
+
70
+ ```bash
71
+ bunx nylon-mesh start nylon-mesh.yaml
72
+ ```
73
+
74
+ Traffic hitting port `3000` (default) is now being cached and routed to your backend efficiently!
75
+
76
+ ## Configuration Example (`nylon-mesh.yaml`)
77
+
78
+ ```yaml
79
+ listen: "0.0.0.0:3000"
80
+ upstreams:
81
+ - "127.0.0.1:3001"
82
+ load_balancer_algo: "round_robin"
83
+ redis_url: "redis://localhost:6379"
84
+
85
+ cache:
86
+ tier1_capacity: 10000
87
+ tier1_ttl_seconds: 3
88
+ tier2_ttl_seconds: 60
89
+ status: [200, 404]
90
+ content_types:
91
+ - "text/html"
92
+
93
+ bypass:
94
+ paths:
95
+ - "/_next/"
96
+ - "/api/"
97
+ extensions:
98
+ - ".ico"
99
+ - ".png"
100
+ ```
101
+
102
+ ## License
103
+
104
+ This project is licensed under the MIT License - see the LICENSE file for details.
@@ -0,0 +1,213 @@
1
+ #!/usr/bin/env node
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+ const { spawnSync } = require('child_process');
5
+ const https = require('https');
6
+
7
+ const args = process.argv.slice(2);
8
+ const command = args[0] || 'start';
9
+
10
+ const REPO = 'AssetsArt/nylon-mesh';
11
+ const BINARY_NAME = 'nylon-mesh';
12
+
13
+ const DEFAULT_YAML = `# threads: 10
14
+ # liveness_path: "/_health/live"
15
+ # readiness_path: "/_health/ready"
16
+ # grace_period_seconds: 0
17
+ # graceful_shutdown_timeout_seconds: 0
18
+ listen: "0.0.0.0:3000"
19
+ # tls:
20
+ # listen: "0.0.0.0:443"
21
+ # certs:
22
+ # - host: "default"
23
+ # cert_path: "cert.pem"
24
+ # key_path: "key.pem"
25
+ upstreams:
26
+ - "127.0.0.1:3001"
27
+ # - address: "127.0.0.1:3002"
28
+ # weight: 5
29
+ load_balancer_algo: "round_robin"
30
+ redis_url: "redis://localhost:6379"
31
+ cache:
32
+ tier1_capacity: 10000
33
+ tier1_ttl_seconds: 3
34
+ tier2_ttl_seconds: 60
35
+ status:
36
+ - 200
37
+ content_types:
38
+ - "text/html"
39
+ bypass:
40
+ paths:
41
+ - "/_next/"
42
+ - "/api/"
43
+ extensions:
44
+ - ".ico"
45
+ - ".png"
46
+ # cache_control:
47
+ # - value: "public, max-age=31536000, immutable"
48
+ # paths:
49
+ # - "/_next/static/"
50
+ # extensions:
51
+ # - ".ico"
52
+ # - ".png"
53
+ # - ".jpg"
54
+ `;
55
+
56
+ function getPlatformString() {
57
+ const platform = process.platform;
58
+ const arch = process.arch;
59
+
60
+ let osStr = '';
61
+ switch (platform) {
62
+ case 'win32': osStr = 'windows'; break;
63
+ case 'darwin': osStr = 'macos'; break;
64
+ case 'linux': osStr = 'linux-gnu'; break; // Default to gnu, musl support can be added if statically linked or specify manually
65
+ default: throw new Error(`Unsupported platform: ${platform}`);
66
+ }
67
+
68
+ let archStr = '';
69
+ switch (arch) {
70
+ case 'x64': archStr = 'x86_64'; break;
71
+ case 'arm64': archStr = 'aarch64'; break;
72
+ default: throw new Error(`Unsupported architecture: ${arch}`);
73
+ }
74
+
75
+ // Windows suffix
76
+ const ext = platform === 'win32' ? '.exe' : '';
77
+
78
+ // Format: nylon-mesh-{platform}-{arch}{ext}
79
+ return `nylon-mesh-${osStr}-${archStr}${ext}`;
80
+ }
81
+
82
+ function httpsGet(url, options = {}) {
83
+ return new Promise((resolve, reject) => {
84
+ https.get(url, { headers: { 'User-Agent': 'nylon-mesh-cli' }, ...options }, (res) => {
85
+ if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
86
+ resolve(httpsGet(res.headers.location, options));
87
+ } else if (res.statusCode === 200) {
88
+ resolve(res);
89
+ } else {
90
+ reject(new Error(`Failed with status code: ${res.statusCode}`));
91
+ }
92
+ }).on('error', reject);
93
+ });
94
+ }
95
+
96
+ async function getLatestReleaseVersion() {
97
+ try {
98
+ const res = await httpsGet(`https://api.github.com/repos/${REPO}/releases/latest`);
99
+ let data = '';
100
+ for await (const chunk of res) { data += chunk; }
101
+ const release = JSON.parse(data);
102
+ return release.tag_name;
103
+ } catch (err) {
104
+ console.error('Failed to fetch latest release from GitHub API.', err.message);
105
+ return null;
106
+ }
107
+ }
108
+
109
+ async function downloadBinary(targetPath) {
110
+ const version = await getLatestReleaseVersion();
111
+ if (!version) {
112
+ console.error('Could not determine latest version. Please build from source using `cargo build --release`.');
113
+ process.exit(1);
114
+ }
115
+
116
+ let platformName;
117
+ try {
118
+ platformName = getPlatformString();
119
+ } catch (e) {
120
+ console.error(e.message);
121
+ process.exit(1);
122
+ }
123
+
124
+ const downloadUrl = `https://github.com/${REPO}/releases/download/${version}/${platformName}`;
125
+ console.log(`Downloading ${platformName} (${version})...`);
126
+ console.log(`From: ${downloadUrl}`);
127
+
128
+ try {
129
+ const res = await httpsGet(downloadUrl);
130
+ const fileStream = fs.createWriteStream(targetPath);
131
+ await new Promise((resolve, reject) => {
132
+ res.pipe(fileStream);
133
+ res.on('error', reject);
134
+ fileStream.on('finish', () => {
135
+ fileStream.close();
136
+ resolve();
137
+ });
138
+ });
139
+ fs.chmodSync(targetPath, 0o755); // Make it executable
140
+ console.log('Download complete.');
141
+ } catch (err) {
142
+ console.error('Download failed:', err.message);
143
+ process.exit(1);
144
+ }
145
+ }
146
+
147
+ async function main() {
148
+ const localBinDir = path.join(__dirname, '..', 'bin');
149
+ const exeExt = process.platform === 'win32' ? '.exe' : '';
150
+ const downloadedBinaryPath = path.join(localBinDir, `${BINARY_NAME}-bin${exeExt}`);
151
+
152
+ if (command === 'init') {
153
+ const targetPath = path.join(process.cwd(), 'nylon-mesh.yaml');
154
+ if (fs.existsSync(targetPath)) {
155
+ console.error('nylon-mesh.yaml already exists.');
156
+ } else {
157
+ fs.writeFileSync(targetPath, DEFAULT_YAML);
158
+ console.log('Created nylon-mesh.yaml!');
159
+ }
160
+
161
+ if (!fs.existsSync(downloadedBinaryPath)) {
162
+ await downloadBinary(downloadedBinaryPath);
163
+ } else {
164
+ console.log('Binary already downloaded.');
165
+ }
166
+
167
+ console.log('Run `npx nylon-mesh start` to start the proxy.');
168
+ process.exit(0);
169
+ }
170
+
171
+ if (command === 'start') {
172
+ const targetReleasePath = path.join(__dirname, '..', 'target', 'release', `${BINARY_NAME}${exeExt}`);
173
+ const targetDebugPath = path.join(__dirname, '..', 'target', 'debug', `${BINARY_NAME}${exeExt}`);
174
+
175
+ let exeToRun = null;
176
+ if (fs.existsSync(downloadedBinaryPath)) {
177
+ exeToRun = downloadedBinaryPath;
178
+ } else if (fs.existsSync(targetReleasePath)) {
179
+ exeToRun = targetReleasePath;
180
+ } else if (fs.existsSync(targetDebugPath)) {
181
+ exeToRun = targetDebugPath;
182
+ } else {
183
+ console.log('Nylon Mesh binary not found. Downloading...');
184
+ await downloadBinary(downloadedBinaryPath);
185
+ exeToRun = downloadedBinaryPath;
186
+ }
187
+
188
+ let yamlPath = path.join(process.cwd(), 'nylon-mesh.yaml');
189
+ if (args[1]) {
190
+ yamlPath = path.resolve(process.cwd(), args[1]);
191
+ }
192
+
193
+ if (!fs.existsSync(yamlPath)) {
194
+ console.error(`Config file not found at ${yamlPath}. Run \`npx nylon-mesh init\` first.`);
195
+ process.exit(1);
196
+ }
197
+
198
+ console.log(`Starting Nylon Mesh with config: ${yamlPath}`);
199
+ const child = spawnSync(exeToRun, [yamlPath], { stdio: 'inherit' });
200
+ process.exit(child.status || 0);
201
+ }
202
+
203
+ console.error(`Unknown command: ${command}`);
204
+ console.error(`Usage:`);
205
+ console.error(` npx nylon-mesh init - Create a default config file and download binary`);
206
+ console.error(` npx nylon-mesh start - Start the proxy server`);
207
+ process.exit(1);
208
+ }
209
+
210
+ main().catch(err => {
211
+ console.error(err);
212
+ process.exit(1);
213
+ });