bxo 0.0.10-dev.2 ā 0.0.10-dev.3
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/example/deployment-examples.ts +136 -0
- package/example/hostname-example.ts +127 -0
- package/example/websocket-example.ts +20 -4
- package/package.json +1 -1
- package/src/index.ts +8 -5
- package/test-default-content-type.ts +0 -75
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import BXO from "../src";
|
|
2
|
+
|
|
3
|
+
// Example configurations for different deployment scenarios
|
|
4
|
+
|
|
5
|
+
// 1. Development - Local only
|
|
6
|
+
export const developmentConfig = new BXO({
|
|
7
|
+
serve: {
|
|
8
|
+
hostname: "127.0.0.1", // Only localhost
|
|
9
|
+
port: 3000,
|
|
10
|
+
development: true
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
// 2. Local Network - Accessible from other devices on same network
|
|
15
|
+
export const localNetworkConfig = new BXO({
|
|
16
|
+
serve: {
|
|
17
|
+
hostname: "0.0.0.0", // All interfaces
|
|
18
|
+
port: 3000,
|
|
19
|
+
development: true
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
// 3. Production - External access with security
|
|
24
|
+
export const productionConfig = new BXO({
|
|
25
|
+
serve: {
|
|
26
|
+
hostname: "0.0.0.0", // All interfaces
|
|
27
|
+
port: 8080,
|
|
28
|
+
development: false
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// 4. Docker Container - Internal network
|
|
33
|
+
export const dockerConfig = new BXO({
|
|
34
|
+
serve: {
|
|
35
|
+
hostname: "0.0.0.0", // All interfaces (required for Docker)
|
|
36
|
+
port: 3000,
|
|
37
|
+
development: false
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// 5. Cloud Deployment (AWS, GCP, Azure)
|
|
42
|
+
export const cloudConfig = new BXO({
|
|
43
|
+
serve: {
|
|
44
|
+
hostname: "0.0.0.0", // All interfaces
|
|
45
|
+
port: process.env.PORT || 8080, // Use environment port
|
|
46
|
+
development: false
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// 6. Specific IP binding
|
|
51
|
+
export const specificIPConfig = new BXO({
|
|
52
|
+
serve: {
|
|
53
|
+
hostname: "192.168.1.100", // Specific IP
|
|
54
|
+
port: 3000
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// 7. Domain binding (if you have a specific domain)
|
|
59
|
+
export const domainConfig = new BXO({
|
|
60
|
+
serve: {
|
|
61
|
+
hostname: "api.yourdomain.com", // Specific domain
|
|
62
|
+
port: 80
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Example usage function
|
|
67
|
+
async function runExample() {
|
|
68
|
+
console.log("š BXO Deployment Configuration Examples\n");
|
|
69
|
+
|
|
70
|
+
// Choose which configuration to use
|
|
71
|
+
const app = localNetworkConfig; // Change this to test different configs
|
|
72
|
+
|
|
73
|
+
// Add some routes
|
|
74
|
+
app.get("/", (ctx) => {
|
|
75
|
+
return ctx.json({
|
|
76
|
+
message: "BXO Server Running",
|
|
77
|
+
hostname: app.server?.hostname || "default",
|
|
78
|
+
port: app.server?.port,
|
|
79
|
+
environment: process.env.NODE_ENV || "development",
|
|
80
|
+
accessible: app.server?.hostname === "0.0.0.0" ? "External networks" : "Local only"
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
app.get("/health", (ctx) => {
|
|
85
|
+
return ctx.json({
|
|
86
|
+
status: "healthy",
|
|
87
|
+
timestamp: new Date().toISOString(),
|
|
88
|
+
hostname: app.server?.hostname,
|
|
89
|
+
port: app.server?.port
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// WebSocket example with hostname info
|
|
94
|
+
app.ws("/ws", {
|
|
95
|
+
open(ws) {
|
|
96
|
+
const data = ws.data;
|
|
97
|
+
console.log(`š WebSocket connected from ${data.ip} to hostname: ${app.server?.hostname}`);
|
|
98
|
+
ws.send(`Connected to server on ${app.server?.hostname}:${app.server?.port}`);
|
|
99
|
+
},
|
|
100
|
+
|
|
101
|
+
message(ws, message) {
|
|
102
|
+
const data = ws.data;
|
|
103
|
+
console.log(`š¬ Message from ${data.ip}: ${message}`);
|
|
104
|
+
ws.send(`Echo from ${app.server?.hostname}: ${message}`);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
app.start();
|
|
109
|
+
|
|
110
|
+
console.log(`ā
Server started successfully!`);
|
|
111
|
+
console.log(`š Hostname: ${app.server?.hostname}`);
|
|
112
|
+
console.log(`š Port: ${app.server?.port}`);
|
|
113
|
+
console.log(`š Access URLs:`);
|
|
114
|
+
|
|
115
|
+
if (app.server?.hostname === "0.0.0.0") {
|
|
116
|
+
console.log(` ⢠http://localhost:${app.server.port}`);
|
|
117
|
+
console.log(` ⢠http://127.0.0.1:${app.server.port}`);
|
|
118
|
+
console.log(` ⢠http://your-server-ip:${app.server.port}`);
|
|
119
|
+
console.log(` ⢠http://your-domain.com:${app.server.port}`);
|
|
120
|
+
} else if (app.server?.hostname === "127.0.0.1") {
|
|
121
|
+
console.log(` ⢠http://localhost:${app.server.port}`);
|
|
122
|
+
console.log(` ⢠http://127.0.0.1:${app.server.port}`);
|
|
123
|
+
} else {
|
|
124
|
+
console.log(` ⢠http://${app.server?.hostname}:${app.server?.port}`);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
console.log(`\nš Configuration Guide:`);
|
|
128
|
+
console.log(` ⢠Development: hostname: "127.0.0.1" (localhost only)`);
|
|
129
|
+
console.log(` ⢠Local Network: hostname: "0.0.0.0" (all interfaces)`);
|
|
130
|
+
console.log(` ⢠Production: hostname: "0.0.0.0" + reverse proxy`);
|
|
131
|
+
console.log(` ⢠Docker: hostname: "0.0.0.0" (required for container networking)`);
|
|
132
|
+
console.log(` ⢠Cloud: hostname: "0.0.0.0" + environment port`);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Run the example
|
|
136
|
+
runExample().catch(console.error);
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import BXO from "../src";
|
|
2
|
+
|
|
3
|
+
async function main() {
|
|
4
|
+
console.log("š BXO Hostname Configuration Examples\n");
|
|
5
|
+
|
|
6
|
+
// Example 1: Serve on all interfaces (0.0.0.0) - accessible from external networks
|
|
7
|
+
console.log("1. Serving on all interfaces (0.0.0.0) - accessible from external networks");
|
|
8
|
+
const app1 = new BXO({
|
|
9
|
+
serve: {
|
|
10
|
+
hostname: "0.0.0.0", // Listen on all network interfaces
|
|
11
|
+
port: 3000
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
app1.get("/", (ctx) => {
|
|
16
|
+
return ctx.json({
|
|
17
|
+
message: "Hello from BXO!",
|
|
18
|
+
hostname: "0.0.0.0",
|
|
19
|
+
accessible: "From any network interface",
|
|
20
|
+
examples: [
|
|
21
|
+
"http://localhost:3000",
|
|
22
|
+
"http://127.0.0.1:3000",
|
|
23
|
+
"http://your-server-ip:3000",
|
|
24
|
+
"http://your-domain.com:3000"
|
|
25
|
+
]
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
// Example 2: Serve on specific hostname/IP
|
|
30
|
+
console.log("2. Serving on specific hostname/IP");
|
|
31
|
+
const app2 = new BXO({
|
|
32
|
+
serve: {
|
|
33
|
+
hostname: "127.0.0.1", // Only localhost
|
|
34
|
+
port: 3001
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
app2.get("/", (ctx) => {
|
|
39
|
+
return ctx.json({
|
|
40
|
+
message: "Hello from BXO!",
|
|
41
|
+
hostname: "127.0.0.1",
|
|
42
|
+
accessible: "Only from localhost",
|
|
43
|
+
examples: [
|
|
44
|
+
"http://localhost:3001",
|
|
45
|
+
"http://127.0.0.1:3001"
|
|
46
|
+
]
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// Example 3: Production configuration with external access
|
|
51
|
+
console.log("3. Production configuration with external access");
|
|
52
|
+
const app3 = new BXO({
|
|
53
|
+
serve: {
|
|
54
|
+
hostname: "0.0.0.0", // Listen on all interfaces
|
|
55
|
+
port: 8080,
|
|
56
|
+
// Additional production options
|
|
57
|
+
development: false,
|
|
58
|
+
// You can add more Bun.serve options here
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
app3.get("/", (ctx) => {
|
|
63
|
+
return ctx.json({
|
|
64
|
+
message: "Production BXO Server",
|
|
65
|
+
hostname: "0.0.0.0",
|
|
66
|
+
port: 8080,
|
|
67
|
+
accessible: "From external networks",
|
|
68
|
+
deployment: "Production ready"
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// Example 4: Custom hostname for specific deployment
|
|
73
|
+
console.log("4. Custom hostname for specific deployment");
|
|
74
|
+
const app4 = new BXO({
|
|
75
|
+
serve: {
|
|
76
|
+
hostname: "192.168.1.100", // Specific IP address
|
|
77
|
+
port: 4000
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
app4.get("/", (ctx) => {
|
|
82
|
+
return ctx.json({
|
|
83
|
+
message: "BXO on specific IP",
|
|
84
|
+
hostname: "192.168.1.100",
|
|
85
|
+
accessible: "From network 192.168.1.x",
|
|
86
|
+
examples: [
|
|
87
|
+
"http://192.168.1.100:4000"
|
|
88
|
+
]
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// Start the server you want to test
|
|
93
|
+
const selectedApp = app1; // Change this to app1, app2, app3, or app4
|
|
94
|
+
|
|
95
|
+
selectedApp.start();
|
|
96
|
+
|
|
97
|
+
console.log(`š Server started!`);
|
|
98
|
+
console.log(`š Hostname: ${selectedApp.server?.hostname || 'default'}`);
|
|
99
|
+
console.log(`š Port: ${selectedApp.server?.port}`);
|
|
100
|
+
console.log(`š Accessible at:`);
|
|
101
|
+
|
|
102
|
+
if (selectedApp === app1) {
|
|
103
|
+
console.log(` ⢠http://localhost:3000`);
|
|
104
|
+
console.log(` ⢠http://127.0.0.1:3000`);
|
|
105
|
+
console.log(` ⢠http://your-server-ip:3000`);
|
|
106
|
+
console.log(` ⢠http://your-domain.com:3000`);
|
|
107
|
+
} else if (selectedApp === app2) {
|
|
108
|
+
console.log(` ⢠http://localhost:3001`);
|
|
109
|
+
console.log(` ⢠http://127.0.0.1:3001`);
|
|
110
|
+
} else if (selectedApp === app3) {
|
|
111
|
+
console.log(` ⢠http://localhost:8080`);
|
|
112
|
+
console.log(` ⢠http://your-server-ip:8080`);
|
|
113
|
+
console.log(` ⢠http://your-domain.com:8080`);
|
|
114
|
+
} else if (selectedApp === app4) {
|
|
115
|
+
console.log(` ⢠http://192.168.1.100:4000`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
console.log(`\nš Configuration Options:`);
|
|
119
|
+
console.log(` ⢠hostname: "0.0.0.0" - Listen on all interfaces (external access)`);
|
|
120
|
+
console.log(` ⢠hostname: "127.0.0.1" - Only localhost access`);
|
|
121
|
+
console.log(` ⢠hostname: "192.168.1.100" - Specific IP address`);
|
|
122
|
+
console.log(` ⢠hostname: "your-domain.com" - Specific domain`);
|
|
123
|
+
console.log(` ⢠port: 3000 - Custom port number`);
|
|
124
|
+
console.log(` ⢠development: false - Production mode`);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
main().catch(console.error);
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import BXO from "../src";
|
|
2
2
|
|
|
3
3
|
async function main() {
|
|
4
|
-
|
|
4
|
+
// Configure hostname for external access
|
|
5
|
+
const app = new BXO({
|
|
6
|
+
serve: {
|
|
7
|
+
hostname: "0.0.0.0", // Listen on all interfaces for external access
|
|
8
|
+
port: 3000
|
|
9
|
+
}
|
|
10
|
+
});
|
|
5
11
|
|
|
6
12
|
// HTTP routes
|
|
7
13
|
app.get("/", (ctx) => {
|
|
@@ -252,9 +258,19 @@ async function main() {
|
|
|
252
258
|
});
|
|
253
259
|
|
|
254
260
|
app.start();
|
|
255
|
-
console.log(`š Server is running
|
|
256
|
-
console.log(
|
|
257
|
-
console.log(
|
|
261
|
+
console.log(`š Server is running:`);
|
|
262
|
+
console.log(`š Hostname: ${app.server?.hostname || 'default'}`);
|
|
263
|
+
console.log(`š Port: ${app.server?.port}`);
|
|
264
|
+
console.log(`š HTTP: http://localhost:${app.server?.port}`);
|
|
265
|
+
console.log(`š WebSocket: ws://localhost:${app.server?.port}/ws`);
|
|
266
|
+
console.log(`š¬ Chat WebSocket: ws://localhost:${app.server?.port}/chat/:room`);
|
|
267
|
+
|
|
268
|
+
if (app.server?.hostname === "0.0.0.0") {
|
|
269
|
+
console.log(`\nš External Access Available:`);
|
|
270
|
+
console.log(` ⢠http://your-server-ip:${app.server.port}`);
|
|
271
|
+
console.log(` ⢠http://your-domain.com:${app.server.port}`);
|
|
272
|
+
console.log(` ⢠ws://your-server-ip:${app.server.port}/ws`);
|
|
273
|
+
}
|
|
258
274
|
console.log(`\nš Features demonstrated:`);
|
|
259
275
|
console.log(` ⢠ws.data.id - Short, unique client identifier`);
|
|
260
276
|
console.log(` ⢠ws.data.connectionId - Detailed connection ID`);
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -195,11 +195,14 @@ function parseQuery<T extends z.ZodTypeAny>(searchParams: URLSearchParams, schem
|
|
|
195
195
|
function parseQuery(searchParams: URLSearchParams, schema?: z.ZodTypeAny): any {
|
|
196
196
|
const out: QueryObject = {};
|
|
197
197
|
for (const [k, v] of searchParams.entries()) {
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
198
|
+
// Handle array notation like fields[] -> fields
|
|
199
|
+
const key = k.endsWith('[]') ? k.slice(0, -2) : k;
|
|
200
|
+
|
|
201
|
+
if (key in out) {
|
|
202
|
+
const existing = out[key];
|
|
203
|
+
if (Array.isArray(existing)) out[key] = [...existing, v];
|
|
204
|
+
else out[key] = [existing as string, v];
|
|
205
|
+
} else out[key] = v;
|
|
203
206
|
}
|
|
204
207
|
if (schema) {
|
|
205
208
|
return (schema as any).parse ? (schema as any).parse(out) : out;
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import BXO from "./src";
|
|
2
|
-
|
|
3
|
-
async function testDefaultContentType() {
|
|
4
|
-
const bxo = new BXO({ serve: { port: 0 } });
|
|
5
|
-
|
|
6
|
-
// Test route that returns a string without explicit content type
|
|
7
|
-
bxo.get("/test-string", (ctx) => {
|
|
8
|
-
return "Hello World";
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
// Test route that returns a string with explicit content type
|
|
12
|
-
bxo.get("/test-string-explicit", (ctx) => {
|
|
13
|
-
return new Response("Hello World", {
|
|
14
|
-
headers: { "Content-Type": "text/plain" }
|
|
15
|
-
});
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
// Test route that uses ctx.json (should be application/json)
|
|
19
|
-
bxo.get("/test-json", (ctx) => {
|
|
20
|
-
return ctx.json({ message: "Hello World" });
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
// Test route that uses ctx.text (should be text/plain)
|
|
24
|
-
bxo.get("/test-text", (ctx) => {
|
|
25
|
-
return ctx.text("Hello World");
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
bxo.start();
|
|
29
|
-
|
|
30
|
-
const baseUrl = `http://localhost:${bxo.server?.port}`;
|
|
31
|
-
|
|
32
|
-
console.log("Testing default content type...");
|
|
33
|
-
|
|
34
|
-
// Test 1: String response should default to text/html
|
|
35
|
-
try {
|
|
36
|
-
const response1 = await fetch(`${baseUrl}/test-string`);
|
|
37
|
-
const contentType1 = response1.headers.get('Content-Type');
|
|
38
|
-
console.log(`ā String response Content-Type: ${contentType1} (should be text/html)`);
|
|
39
|
-
} catch (error) {
|
|
40
|
-
console.error("ā Error testing string response:", error);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Test 2: Explicit content type should be preserved
|
|
44
|
-
try {
|
|
45
|
-
const response2 = await fetch(`${baseUrl}/test-string-explicit`);
|
|
46
|
-
const contentType2 = response2.headers.get('Content-Type');
|
|
47
|
-
console.log(`ā Explicit Content-Type: ${contentType2} (should be text/plain)`);
|
|
48
|
-
} catch (error) {
|
|
49
|
-
console.error("ā Error testing explicit content type:", error);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// Test 3: ctx.json should be application/json
|
|
53
|
-
try {
|
|
54
|
-
const response3 = await fetch(`${baseUrl}/test-json`);
|
|
55
|
-
const contentType3 = response3.headers.get('Content-Type');
|
|
56
|
-
console.log(`ā ctx.json Content-Type: ${contentType3} (should be application/json)`);
|
|
57
|
-
} catch (error) {
|
|
58
|
-
console.error("ā Error testing ctx.json:", error);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// Test 4: ctx.text should be text/plain
|
|
62
|
-
try {
|
|
63
|
-
const response4 = await fetch(`${baseUrl}/test-text`);
|
|
64
|
-
const contentType4 = response4.headers.get('Content-Type');
|
|
65
|
-
console.log(`ā ctx.text Content-Type: ${contentType4} (should be text/plain)`);
|
|
66
|
-
} catch (error) {
|
|
67
|
-
console.error("ā Error testing ctx.text:", error);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// Close the server
|
|
71
|
-
bxo.server?.stop();
|
|
72
|
-
console.log("Test completed!");
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
testDefaultContentType().catch(console.error);
|