@dangao/bun-server 2.3.0 → 3.0.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/README.md +81 -3
- package/dist/auth/jwt.d.ts.map +1 -1
- package/dist/config/service.d.ts +0 -1
- package/dist/config/service.d.ts.map +1 -1
- package/dist/core/application.d.ts +13 -0
- package/dist/core/application.d.ts.map +1 -1
- package/dist/core/cluster.d.ts.map +1 -1
- package/dist/core/server.d.ts +12 -9
- package/dist/core/server.d.ts.map +1 -1
- package/dist/dashboard/controller.d.ts.map +1 -1
- package/dist/database/connection-pool.d.ts +3 -3
- package/dist/database/connection-pool.d.ts.map +1 -1
- package/dist/database/sql-manager.d.ts +8 -4
- package/dist/database/sql-manager.d.ts.map +1 -1
- package/dist/database/sqlite-adapter.d.ts +7 -3
- package/dist/database/sqlite-adapter.d.ts.map +1 -1
- package/dist/debug/recorder.d.ts +0 -1
- package/dist/debug/recorder.d.ts.map +1 -1
- package/dist/files/static-middleware.d.ts.map +1 -1
- package/dist/files/storage.d.ts.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +40264 -3542
- package/dist/index.node.mjs +17689 -0
- package/dist/middleware/builtin/static-file.d.ts +4 -2
- package/dist/middleware/builtin/static-file.d.ts.map +1 -1
- package/dist/platform/bun/crypto.d.ts +3 -0
- package/dist/platform/bun/crypto.d.ts.map +1 -0
- package/dist/platform/bun/fs.d.ts +3 -0
- package/dist/platform/bun/fs.d.ts.map +1 -0
- package/dist/platform/bun/http.d.ts +15 -0
- package/dist/platform/bun/http.d.ts.map +1 -0
- package/dist/platform/bun/index.d.ts +3 -0
- package/dist/platform/bun/index.d.ts.map +1 -0
- package/dist/platform/bun/parser.d.ts +3 -0
- package/dist/platform/bun/parser.d.ts.map +1 -0
- package/dist/platform/bun/process.d.ts +3 -0
- package/dist/platform/bun/process.d.ts.map +1 -0
- package/dist/platform/detector.d.ts +9 -0
- package/dist/platform/detector.d.ts.map +1 -0
- package/dist/platform/index.d.ts +4 -0
- package/dist/platform/index.d.ts.map +1 -0
- package/dist/platform/node/crypto.d.ts +3 -0
- package/dist/platform/node/crypto.d.ts.map +1 -0
- package/dist/platform/node/fs.d.ts +3 -0
- package/dist/platform/node/fs.d.ts.map +1 -0
- package/dist/platform/node/http.d.ts +3 -0
- package/dist/platform/node/http.d.ts.map +1 -0
- package/dist/platform/node/index.d.ts +3 -0
- package/dist/platform/node/index.d.ts.map +1 -0
- package/dist/platform/node/parser.d.ts +3 -0
- package/dist/platform/node/parser.d.ts.map +1 -0
- package/dist/platform/node/process.d.ts +3 -0
- package/dist/platform/node/process.d.ts.map +1 -0
- package/dist/platform/runtime.d.ts +14 -0
- package/dist/platform/runtime.d.ts.map +1 -0
- package/dist/platform/types.d.ts +139 -0
- package/dist/platform/types.d.ts.map +1 -0
- package/dist/prompt/stores/file-store.d.ts.map +1 -1
- package/dist/rag/service.d.ts.map +1 -1
- package/dist/request/response.d.ts +3 -1
- package/dist/request/response.d.ts.map +1 -1
- package/dist/security/guards/execution-context.d.ts +2 -2
- package/dist/security/guards/execution-context.d.ts.map +1 -1
- package/dist/security/guards/types.d.ts +2 -2
- package/dist/security/guards/types.d.ts.map +1 -1
- package/dist/swagger/generator.d.ts.map +1 -1
- package/dist/websocket/registry.d.ts +4 -4
- package/dist/websocket/registry.d.ts.map +1 -1
- package/docs/deployment.md +31 -7
- package/docs/design/query-interceptor-design.md +381 -0
- package/docs/idle-timeout.md +6 -4
- package/docs/migration.md +43 -0
- package/docs/platform.md +299 -0
- package/docs/testing.md +60 -0
- package/docs/zh/deployment.md +30 -7
- package/docs/zh/idle-timeout.md +6 -4
- package/docs/zh/migration.md +42 -0
- package/docs/zh/platform.md +299 -0
- package/docs/zh/testing.md +60 -0
- package/package.json +24 -6
- package/src/auth/jwt.ts +4 -3
- package/src/config/service.ts +7 -6
- package/src/core/application.ts +19 -1
- package/src/core/cluster.ts +16 -14
- package/src/core/server.ts +48 -35
- package/src/dashboard/controller.ts +3 -2
- package/src/database/connection-pool.ts +32 -20
- package/src/database/database-module.ts +1 -1
- package/src/database/db-proxy.ts +2 -2
- package/src/database/orm/transaction-manager.ts +1 -1
- package/src/database/sql-manager.ts +48 -13
- package/src/database/sqlite-adapter.ts +45 -12
- package/src/debug/recorder.ts +4 -3
- package/src/files/static-middleware.ts +3 -2
- package/src/files/storage.ts +2 -1
- package/src/index.ts +13 -0
- package/src/middleware/builtin/static-file.ts +8 -5
- package/src/platform/bun/crypto.ts +30 -0
- package/src/platform/bun/fs.ts +52 -0
- package/src/platform/bun/http.ts +106 -0
- package/src/platform/bun/index.ts +17 -0
- package/src/platform/bun/parser.ts +19 -0
- package/src/platform/bun/process.ts +37 -0
- package/src/platform/detector.ts +36 -0
- package/src/platform/index.ts +20 -0
- package/src/platform/node/crypto.ts +40 -0
- package/src/platform/node/fs.ts +115 -0
- package/src/platform/node/http.ts +196 -0
- package/src/platform/node/index.ts +17 -0
- package/src/platform/node/parser.ts +34 -0
- package/src/platform/node/process.ts +51 -0
- package/src/platform/runtime.ts +50 -0
- package/src/platform/types.ts +150 -0
- package/src/prompt/stores/file-store.ts +6 -5
- package/src/rag/service.ts +2 -1
- package/src/request/response.ts +7 -4
- package/src/security/guards/execution-context.ts +4 -4
- package/src/security/guards/types.ts +2 -2
- package/src/swagger/generator.ts +2 -1
- package/src/websocket/registry.ts +6 -7
- package/tests/controller/path-combination.test.ts +196 -2
- package/tests/files/static-middleware.test.ts +5 -2
- package/tests/middleware/static-file.test.ts +5 -2
- package/tests/platform/bun/crypto.test.ts +8 -0
- package/tests/platform/bun/database.test.ts +8 -0
- package/tests/platform/bun/fs.test.ts +8 -0
- package/tests/platform/bun/parser.test.ts +8 -0
- package/tests/platform/bun/process.test.ts +8 -0
- package/tests/platform/bun/websocket.test.ts +8 -0
- package/tests/platform/detector.test.ts +57 -0
- package/tests/platform/node/build-smoke.test.ts +92 -0
- package/tests/platform/node/crypto.test.ts +9 -0
- package/tests/platform/node/database.test.ts +9 -0
- package/tests/platform/node/fs.test.ts +9 -0
- package/tests/platform/node/parser.test.ts +9 -0
- package/tests/platform/node/process.test.ts +9 -0
- package/tests/platform/node/websocket.test.ts +9 -0
- package/tests/platform/shared/crypto.cases.ts +49 -0
- package/tests/platform/shared/database.cases.ts +43 -0
- package/tests/platform/shared/fs.cases.ts +82 -0
- package/tests/platform/shared/parser.cases.ts +55 -0
- package/tests/platform/shared/process.cases.ts +26 -0
- package/tests/platform/shared/suite.ts +33 -0
- package/tests/platform/shared/websocket.cases.ts +61 -0
- package/tests/request/response.test.ts +5 -2
- package/tests/router/router-extended.test.ts +53 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { TestSuite } from './suite';
|
|
2
|
+
import type { IPlatform } from '../../../src/platform/types';
|
|
3
|
+
|
|
4
|
+
export function runWebSocketCases(suite: TestSuite, getPlatform: () => IPlatform): void {
|
|
5
|
+
const { test, expect } = suite;
|
|
6
|
+
|
|
7
|
+
test('WebSocket server accepts connection and receives message', async () => {
|
|
8
|
+
const platform = getPlatform();
|
|
9
|
+
const messages: string[] = [];
|
|
10
|
+
let openCalled = false;
|
|
11
|
+
|
|
12
|
+
// Use a promise to track the server-side close event
|
|
13
|
+
let resolveServerClose!: () => void;
|
|
14
|
+
const serverClosePromise = new Promise<void>((r) => { resolveServerClose = r; });
|
|
15
|
+
|
|
16
|
+
const server = await platform.http.serve({
|
|
17
|
+
port: 0,
|
|
18
|
+
fetch: (req, handle) => {
|
|
19
|
+
const upgraded = handle.upgrade?.(req, { data: {} });
|
|
20
|
+
if (upgraded) return undefined as unknown as Response;
|
|
21
|
+
return new Response('not ws', { status: 400 });
|
|
22
|
+
},
|
|
23
|
+
websocket: {
|
|
24
|
+
open: (_ws) => { openCalled = true; },
|
|
25
|
+
message: (ws, msg) => {
|
|
26
|
+
messages.push(msg.toString());
|
|
27
|
+
ws.send('echo: ' + msg.toString());
|
|
28
|
+
},
|
|
29
|
+
close: (_ws) => { resolveServerClose(); },
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const port = server.port;
|
|
34
|
+
|
|
35
|
+
// Connect using native WebSocket (available in both Bun and Node 22+)
|
|
36
|
+
await new Promise<void>((resolve, reject) => {
|
|
37
|
+
const ws = new WebSocket(`ws://localhost:${port}`);
|
|
38
|
+
ws.addEventListener('open', () => {
|
|
39
|
+
ws.send('hello');
|
|
40
|
+
});
|
|
41
|
+
ws.addEventListener('message', (e) => {
|
|
42
|
+
if (e.data === 'echo: hello') {
|
|
43
|
+
ws.close();
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
ws.addEventListener('close', () => {
|
|
47
|
+
resolve();
|
|
48
|
+
});
|
|
49
|
+
ws.addEventListener('error', reject);
|
|
50
|
+
setTimeout(reject, 5000);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// Wait for server-side close handler to fire before asserting
|
|
54
|
+
await serverClosePromise;
|
|
55
|
+
|
|
56
|
+
server.stop();
|
|
57
|
+
|
|
58
|
+
expect(openCalled).toBe(true);
|
|
59
|
+
expect(messages).toContain('hello');
|
|
60
|
+
});
|
|
61
|
+
}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { afterEach, beforeEach, describe, expect, test } from 'bun:test';
|
|
2
|
-
import { mkdtemp, rm } from 'node:fs/promises';
|
|
2
|
+
import { mkdtemp, rm, writeFile } from 'node:fs/promises';
|
|
3
3
|
import { tmpdir } from 'node:os';
|
|
4
4
|
import { join } from 'node:path';
|
|
5
5
|
import { ResponseBuilder } from '../../src/request/response';
|
|
6
|
+
import { initRuntime } from '../../src/platform/runtime';
|
|
7
|
+
|
|
8
|
+
initRuntime('bun');
|
|
6
9
|
|
|
7
10
|
describe('ResponseBuilder', () => {
|
|
8
11
|
let tmpDir: string;
|
|
@@ -71,7 +74,7 @@ describe('ResponseBuilder', () => {
|
|
|
71
74
|
|
|
72
75
|
test('should create file response from path', async () => {
|
|
73
76
|
const filePath = join(tmpDir, 'hello.txt');
|
|
74
|
-
await
|
|
77
|
+
await writeFile(filePath, 'file-content', 'utf-8');
|
|
75
78
|
|
|
76
79
|
const response = ResponseBuilder.file(filePath, {
|
|
77
80
|
fileName: 'download.txt',
|
|
@@ -94,6 +94,42 @@ describe('Router', () => {
|
|
|
94
94
|
const route = router.findRoute('POST', '/users');
|
|
95
95
|
expect(route).toBeUndefined();
|
|
96
96
|
});
|
|
97
|
+
|
|
98
|
+
test('should distinguish GET POST PUT DELETE PATCH on the same dynamic route', () => {
|
|
99
|
+
router.get('/api/:id', async () => new Response('get'));
|
|
100
|
+
router.post('/api/:id', async () => new Response('post'));
|
|
101
|
+
router.put('/api/:id', async () => new Response('put'));
|
|
102
|
+
router.delete('/api/:id', async () => new Response('delete'));
|
|
103
|
+
router.patch('/api/:id', async () => new Response('patch'));
|
|
104
|
+
|
|
105
|
+
const getRoute = router.findRoute('GET', '/api/123');
|
|
106
|
+
const postRoute = router.findRoute('POST', '/api/123');
|
|
107
|
+
const putRoute = router.findRoute('PUT', '/api/123');
|
|
108
|
+
const deleteRoute = router.findRoute('DELETE', '/api/123');
|
|
109
|
+
const patchRoute = router.findRoute('PATCH', '/api/123');
|
|
110
|
+
|
|
111
|
+
expect(getRoute).toBeDefined();
|
|
112
|
+
expect(postRoute).toBeDefined();
|
|
113
|
+
expect(putRoute).toBeDefined();
|
|
114
|
+
expect(deleteRoute).toBeDefined();
|
|
115
|
+
expect(patchRoute).toBeDefined();
|
|
116
|
+
|
|
117
|
+
expect(getRoute?.method).toBe('GET');
|
|
118
|
+
expect(postRoute?.method).toBe('POST');
|
|
119
|
+
expect(putRoute?.method).toBe('PUT');
|
|
120
|
+
expect(deleteRoute?.method).toBe('DELETE');
|
|
121
|
+
expect(patchRoute?.method).toBe('PATCH');
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
test('should not cross-match methods on same dynamic route', () => {
|
|
125
|
+
router.get('/api/:id', async () => new Response('get'));
|
|
126
|
+
router.post('/api/:id', async () => new Response('post'));
|
|
127
|
+
|
|
128
|
+
expect(router.findRoute('GET', '/api/123')).toBeDefined();
|
|
129
|
+
expect(router.findRoute('POST', '/api/123')).toBeDefined();
|
|
130
|
+
expect(router.findRoute('PUT', '/api/123')).toBeUndefined();
|
|
131
|
+
expect(router.findRoute('DELETE', '/api/123')).toBeUndefined();
|
|
132
|
+
});
|
|
97
133
|
});
|
|
98
134
|
|
|
99
135
|
describe('findRouteWithMatch', () => {
|
|
@@ -178,6 +214,23 @@ describe('Router', () => {
|
|
|
178
214
|
expect((context as any).routeHandler.controller).toBe(MyController);
|
|
179
215
|
expect((context as any).routeHandler.method).toBe('testMethod');
|
|
180
216
|
});
|
|
217
|
+
|
|
218
|
+
test('should route each HTTP method to its own handler on the same dynamic path /api/:id', async () => {
|
|
219
|
+
router.get('/api/:id', async () => new Response('get'));
|
|
220
|
+
router.post('/api/:id', async () => new Response('post'));
|
|
221
|
+
router.put('/api/:id', async () => new Response('put'));
|
|
222
|
+
router.delete('/api/:id', async () => new Response('delete'));
|
|
223
|
+
router.patch('/api/:id', async () => new Response('patch'));
|
|
224
|
+
|
|
225
|
+
const methods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'] as const;
|
|
226
|
+
for (const method of methods) {
|
|
227
|
+
const request = new Request('http://localhost/api/123', { method });
|
|
228
|
+
const context = new Context(request, new Container());
|
|
229
|
+
const response = await router.handle(context);
|
|
230
|
+
expect(response).toBeDefined();
|
|
231
|
+
expect(await response?.text()).toBe(method.toLowerCase());
|
|
232
|
+
}
|
|
233
|
+
});
|
|
181
234
|
});
|
|
182
235
|
|
|
183
236
|
describe('preHandle', () => {
|