sockress 0.2.4 → 0.2.6
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/LICENSE +29 -0
- package/README.md +315 -47
- package/package.json +2 -2
- package/dist/index.d.ts +0 -174
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -900
- package/dist/index.js.map +0 -1
- package/src/index.ts +0 -1141
- package/tsconfig.json +0 -8
package/LICENSE
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
PROPRIETARY LICENSE
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Also Coder. All Rights Reserved.
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS:
|
|
6
|
+
|
|
7
|
+
1. USE PERMISSION:
|
|
8
|
+
You are granted permission to use this software ("Sockress") in your projects,
|
|
9
|
+
applications, and commercial products.
|
|
10
|
+
|
|
11
|
+
2. RESTRICTIONS:
|
|
12
|
+
- You MAY NOT modify, adapt, alter, or create derivative works of this software.
|
|
13
|
+
- You MAY NOT sell, resell, sublicense, or redistribute this software as a standalone product.
|
|
14
|
+
- You MAY NOT create your own repository, fork, or distribution of this software.
|
|
15
|
+
- You MUST use the original repository maintained by Also Coder.
|
|
16
|
+
|
|
17
|
+
3. DISTRIBUTION:
|
|
18
|
+
You may include this software as a dependency in your projects, but you may not
|
|
19
|
+
redistribute the source code or compiled code separately from your project.
|
|
20
|
+
|
|
21
|
+
4. NO WARRANTY:
|
|
22
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
23
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
24
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
25
|
+
|
|
26
|
+
5. CONTACT:
|
|
27
|
+
For licensing inquiries or special permissions, contact: hello@alsocoder.com
|
|
28
|
+
|
|
29
|
+
By using this software, you agree to these terms and conditions.
|
package/README.md
CHANGED
|
@@ -9,12 +9,17 @@ Sockress is a socket-first Node.js framework that mirrors the Express API while
|
|
|
9
9
|
## Features
|
|
10
10
|
|
|
11
11
|
- Express-style routing (`app.get`, `app.post`, `app.put`, `app.patch`, `app.delete`, `app.head`, `app.options`, `app.all`)
|
|
12
|
+
- **Router support** - Modular routing with `sockress.Router()`
|
|
12
13
|
- Unified middleware pipeline for HTTP and WebSocket transports
|
|
13
14
|
- Automatic CORS handling with configurable origins
|
|
14
15
|
- Cookie parsing and setting via `req.cookies` and `res.cookie()`
|
|
15
16
|
- File uploads via `createUploader()` (multer-compatible) that work on both transports
|
|
16
17
|
- Static file serving via `serveStatic()` helper
|
|
17
18
|
- Request context object (`req.context`) for passing data through middleware
|
|
19
|
+
- **Response helpers**: `redirect()`, `sendFile()`, `download()`, `sendStatus()`, `format()`, `location()`, `vary()`
|
|
20
|
+
- **Request helpers**: `accepts()`, `is()`, `param()`, plus `hostname`, `originalUrl`, `baseUrl`, `subdomains`
|
|
21
|
+
- **Parameter middleware** with `app.param()`
|
|
22
|
+
- **Chainable routes** with `app.route()`
|
|
18
23
|
- Graceful shutdown hooks (automatically closes on `beforeExit`, `SIGINT`, `SIGTERM`)
|
|
19
24
|
- Heartbeat management for long-lived WebSocket connections
|
|
20
25
|
|
|
@@ -30,10 +35,10 @@ Sockress supports both ESM and CommonJS:
|
|
|
30
35
|
|
|
31
36
|
```ts
|
|
32
37
|
// ESM
|
|
33
|
-
import { sockress, createUploader, serveStatic } from 'sockress';
|
|
38
|
+
import { sockress, createUploader, serveStatic, Router } from 'sockress';
|
|
34
39
|
|
|
35
40
|
// CommonJS
|
|
36
|
-
const { sockress, createUploader, serveStatic } = require('sockress');
|
|
41
|
+
const { sockress, createUploader, serveStatic, Router } = require('sockress');
|
|
37
42
|
```
|
|
38
43
|
|
|
39
44
|
---
|
|
@@ -103,6 +108,68 @@ app.get('/users/:userId/posts/:postId', (req, res) => {
|
|
|
103
108
|
});
|
|
104
109
|
```
|
|
105
110
|
|
|
111
|
+
### Chainable Routes
|
|
112
|
+
|
|
113
|
+
Use `app.route()` for chainable route handlers:
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
app.route('/users')
|
|
117
|
+
.get((req, res) => {
|
|
118
|
+
res.json({ users: [] });
|
|
119
|
+
})
|
|
120
|
+
.post((req, res) => {
|
|
121
|
+
const { name } = req.body;
|
|
122
|
+
res.json({ id: 1, name });
|
|
123
|
+
})
|
|
124
|
+
.put((req, res) => {
|
|
125
|
+
res.json({ updated: true });
|
|
126
|
+
});
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## Router
|
|
132
|
+
|
|
133
|
+
Create modular routers for better code organization:
|
|
134
|
+
|
|
135
|
+
```ts
|
|
136
|
+
import { sockress, Router } from 'sockress';
|
|
137
|
+
|
|
138
|
+
const app = sockress();
|
|
139
|
+
const userRouter = Router();
|
|
140
|
+
|
|
141
|
+
userRouter.get('/', (req, res) => {
|
|
142
|
+
res.json({ users: [] });
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
userRouter.get('/:id', (req, res) => {
|
|
146
|
+
res.json({ id: req.params.id });
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
userRouter.post('/', (req, res) => {
|
|
150
|
+
res.json({ created: true });
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
app.use('/api/users', userRouter);
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Routers support all the same methods as the main app:
|
|
157
|
+
|
|
158
|
+
```ts
|
|
159
|
+
const apiRouter = Router();
|
|
160
|
+
|
|
161
|
+
apiRouter.use((req, res, next) => {
|
|
162
|
+
req.context.apiVersion = 'v1';
|
|
163
|
+
next();
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
apiRouter.get('/status', (req, res) => {
|
|
167
|
+
res.json({ status: 'ok' });
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
app.use('/api', apiRouter);
|
|
171
|
+
```
|
|
172
|
+
|
|
106
173
|
---
|
|
107
174
|
|
|
108
175
|
## Middleware
|
|
@@ -124,6 +191,30 @@ app.use('/api', (req, res, next) => {
|
|
|
124
191
|
|
|
125
192
|
// Multiple middleware
|
|
126
193
|
app.use('/secure', authMiddleware, validateMiddleware, handler);
|
|
194
|
+
|
|
195
|
+
// Use Router as middleware
|
|
196
|
+
const router = Router();
|
|
197
|
+
router.get('/users', getUsers);
|
|
198
|
+
app.use('/api', router);
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Parameter Middleware
|
|
202
|
+
|
|
203
|
+
Use `app.param()` to add middleware for specific route parameters:
|
|
204
|
+
|
|
205
|
+
```ts
|
|
206
|
+
app.param('userId', async (req, res, next) => {
|
|
207
|
+
const user = await findUser(req.params.userId);
|
|
208
|
+
if (!user) {
|
|
209
|
+
return res.status(404).json({ error: 'User not found' });
|
|
210
|
+
}
|
|
211
|
+
req.context.user = user;
|
|
212
|
+
next();
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
app.get('/users/:userId', (req, res) => {
|
|
216
|
+
res.json({ user: req.context.user });
|
|
217
|
+
});
|
|
127
218
|
```
|
|
128
219
|
|
|
129
220
|
### Error Handling
|
|
@@ -139,6 +230,155 @@ app.use((err, req, res, next) => {
|
|
|
139
230
|
|
|
140
231
|
---
|
|
141
232
|
|
|
233
|
+
## Response Methods
|
|
234
|
+
|
|
235
|
+
### Basic Methods
|
|
236
|
+
|
|
237
|
+
```ts
|
|
238
|
+
res.status(404) // Set status code
|
|
239
|
+
res.set('X-Custom', 'value') // Set header
|
|
240
|
+
res.append('X-Other', 'val') // Append to header
|
|
241
|
+
res.json({ data: 'value' }) // Send JSON
|
|
242
|
+
res.send('Hello') // Send response (auto-detects type)
|
|
243
|
+
res.end() // End response
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### Redirect
|
|
247
|
+
|
|
248
|
+
```ts
|
|
249
|
+
// Simple redirect (302)
|
|
250
|
+
res.redirect('/login');
|
|
251
|
+
|
|
252
|
+
// Redirect with status code
|
|
253
|
+
res.redirect(301, '/new-url');
|
|
254
|
+
|
|
255
|
+
// Or status first
|
|
256
|
+
res.redirect(301, '/permanent-redirect');
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### Send File
|
|
260
|
+
|
|
261
|
+
```ts
|
|
262
|
+
// Send file as response
|
|
263
|
+
await res.sendFile('/path/to/file.pdf');
|
|
264
|
+
|
|
265
|
+
// With options
|
|
266
|
+
await res.sendFile('file.pdf', {
|
|
267
|
+
root: '/uploads',
|
|
268
|
+
headers: { 'X-Custom': 'value' }
|
|
269
|
+
});
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### Download File
|
|
273
|
+
|
|
274
|
+
```ts
|
|
275
|
+
// Download file
|
|
276
|
+
await res.download('/path/to/file.pdf');
|
|
277
|
+
|
|
278
|
+
// With custom filename
|
|
279
|
+
await res.download('/path/to/file.pdf', 'custom-name.pdf');
|
|
280
|
+
|
|
281
|
+
// With options
|
|
282
|
+
await res.download('file.pdf', 'download.pdf', {
|
|
283
|
+
root: '/uploads',
|
|
284
|
+
headers: { 'X-Custom': 'value' }
|
|
285
|
+
});
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Send Status
|
|
289
|
+
|
|
290
|
+
```ts
|
|
291
|
+
// Send status code with default text
|
|
292
|
+
res.sendStatus(404); // Sends "Not Found"
|
|
293
|
+
res.sendStatus(200); // Sends "OK"
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### Content Negotiation
|
|
297
|
+
|
|
298
|
+
```ts
|
|
299
|
+
res.format({
|
|
300
|
+
'text/html': (req, res) => {
|
|
301
|
+
res.send('<h1>HTML</h1>');
|
|
302
|
+
},
|
|
303
|
+
'application/json': (req, res) => {
|
|
304
|
+
res.json({ format: 'json' });
|
|
305
|
+
},
|
|
306
|
+
'default': (req, res) => {
|
|
307
|
+
res.send('Default format');
|
|
308
|
+
}
|
|
309
|
+
}, req);
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### Location Header
|
|
313
|
+
|
|
314
|
+
```ts
|
|
315
|
+
res.location('/new-path');
|
|
316
|
+
res.status(301).end();
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### Vary Header
|
|
320
|
+
|
|
321
|
+
```ts
|
|
322
|
+
res.vary('Accept');
|
|
323
|
+
res.vary('User-Agent');
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
---
|
|
327
|
+
|
|
328
|
+
## Request Methods & Properties
|
|
329
|
+
|
|
330
|
+
### Request Properties
|
|
331
|
+
|
|
332
|
+
```ts
|
|
333
|
+
req.id // unique request ID
|
|
334
|
+
req.method // HTTP method (GET, POST, etc.)
|
|
335
|
+
req.path // request path
|
|
336
|
+
req.query // parsed query string (object)
|
|
337
|
+
req.params // route parameters (object)
|
|
338
|
+
req.headers // request headers (object)
|
|
339
|
+
req.body // parsed request body
|
|
340
|
+
req.cookies // parsed cookies (object)
|
|
341
|
+
req.file // first uploaded file (if any)
|
|
342
|
+
req.files // all uploaded files (object mapping field names to arrays)
|
|
343
|
+
req.type // 'http' or 'socket'
|
|
344
|
+
req.ip // client IP address
|
|
345
|
+
req.protocol // 'http', 'https', 'ws', or 'wss'
|
|
346
|
+
req.secure // boolean indicating if connection is secure
|
|
347
|
+
req.hostname // request hostname
|
|
348
|
+
req.originalUrl // original request URL
|
|
349
|
+
req.baseUrl // base URL for router
|
|
350
|
+
req.subdomains // array of subdomains
|
|
351
|
+
req.context // plain object for passing data through middleware
|
|
352
|
+
req.raw // IncomingMessage (HTTP only)
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### Request Methods
|
|
356
|
+
|
|
357
|
+
```ts
|
|
358
|
+
// Get header value
|
|
359
|
+
const auth = req.get('authorization');
|
|
360
|
+
|
|
361
|
+
// Get route parameter
|
|
362
|
+
const userId = req.param('userId');
|
|
363
|
+
const userIdWithDefault = req.param('userId', 'default');
|
|
364
|
+
|
|
365
|
+
// Content negotiation
|
|
366
|
+
if (req.accepts('json')) {
|
|
367
|
+
res.json({ data: 'value' });
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
const accepted = req.accepts(['json', 'html']); // returns 'json' or 'html' or false
|
|
371
|
+
|
|
372
|
+
// Content type check
|
|
373
|
+
if (req.is('application/json')) {
|
|
374
|
+
// handle JSON
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
const isJson = req.is(['json', 'html']); // returns 'json' or 'html' or false or null
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
---
|
|
381
|
+
|
|
142
382
|
## File Uploads
|
|
143
383
|
|
|
144
384
|
Use `createUploader()` to handle file uploads. It works for both HTTP and WebSocket transports:
|
|
@@ -235,51 +475,6 @@ app.useStatic('/uploads', uploadsDir, { maxAge: 60_000 });
|
|
|
235
475
|
|
|
236
476
|
---
|
|
237
477
|
|
|
238
|
-
## Request Object
|
|
239
|
-
|
|
240
|
-
The `req` object provides:
|
|
241
|
-
|
|
242
|
-
```ts
|
|
243
|
-
req.id // unique request ID
|
|
244
|
-
req.method // HTTP method (GET, POST, etc.)
|
|
245
|
-
req.path // request path
|
|
246
|
-
req.query // parsed query string (object)
|
|
247
|
-
req.params // route parameters (object)
|
|
248
|
-
req.headers // request headers (object)
|
|
249
|
-
req.body // parsed request body
|
|
250
|
-
req.cookies // parsed cookies (object)
|
|
251
|
-
req.file // first uploaded file (if any)
|
|
252
|
-
req.files // all uploaded files (object mapping field names to arrays)
|
|
253
|
-
req.type // 'http' or 'socket'
|
|
254
|
-
req.ip // client IP address
|
|
255
|
-
req.protocol // 'http', 'https', 'ws', or 'wss'
|
|
256
|
-
req.secure // boolean indicating if connection is secure
|
|
257
|
-
req.context // plain object for passing data through middleware
|
|
258
|
-
req.raw // IncomingMessage (HTTP only)
|
|
259
|
-
req.get(field) // get header value by name
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
---
|
|
263
|
-
|
|
264
|
-
## Response Object
|
|
265
|
-
|
|
266
|
-
The `res` object provides:
|
|
267
|
-
|
|
268
|
-
```ts
|
|
269
|
-
res.status(code) // set status code
|
|
270
|
-
res.set(field, value) // set header
|
|
271
|
-
res.append(field, value) // append to header
|
|
272
|
-
res.cookie(name, value, opts) // set cookie
|
|
273
|
-
res.clearCookie(name, opts) // clear cookie
|
|
274
|
-
res.json(payload) // send JSON response
|
|
275
|
-
res.send(payload) // send response (auto-detects type)
|
|
276
|
-
res.end() // end response
|
|
277
|
-
res.isSent() // check if response was sent
|
|
278
|
-
res.raw // ServerResponse (HTTP only)
|
|
279
|
-
```
|
|
280
|
-
|
|
281
|
-
---
|
|
282
|
-
|
|
283
478
|
## Configuration
|
|
284
479
|
|
|
285
480
|
Create a Sockress app with custom options:
|
|
@@ -349,6 +544,79 @@ await app.close();
|
|
|
349
544
|
|
|
350
545
|
---
|
|
351
546
|
|
|
547
|
+
## Complete Example
|
|
548
|
+
|
|
549
|
+
```ts
|
|
550
|
+
import { sockress, Router, createUploader } from 'sockress';
|
|
551
|
+
import path from 'path';
|
|
552
|
+
|
|
553
|
+
const app = sockress();
|
|
554
|
+
const uploader = createUploader({ dest: './uploads' });
|
|
555
|
+
|
|
556
|
+
// Parameter middleware
|
|
557
|
+
app.param('userId', async (req, res, next) => {
|
|
558
|
+
const user = await findUser(req.params.userId);
|
|
559
|
+
if (user) {
|
|
560
|
+
req.context.user = user;
|
|
561
|
+
next();
|
|
562
|
+
} else {
|
|
563
|
+
res.status(404).json({ error: 'User not found' });
|
|
564
|
+
}
|
|
565
|
+
});
|
|
566
|
+
|
|
567
|
+
// Router
|
|
568
|
+
const apiRouter = Router();
|
|
569
|
+
apiRouter.use((req, res, next) => {
|
|
570
|
+
req.context.apiVersion = 'v1';
|
|
571
|
+
next();
|
|
572
|
+
});
|
|
573
|
+
|
|
574
|
+
apiRouter.route('/users/:userId')
|
|
575
|
+
.get((req, res) => {
|
|
576
|
+
res.json({ user: req.context.user });
|
|
577
|
+
})
|
|
578
|
+
.put((req, res) => {
|
|
579
|
+
// Update user
|
|
580
|
+
res.json({ updated: true });
|
|
581
|
+
});
|
|
582
|
+
|
|
583
|
+
app.use('/api', apiRouter);
|
|
584
|
+
|
|
585
|
+
// File upload
|
|
586
|
+
app.post('/avatar', uploader.single('avatar'), (req, res) => {
|
|
587
|
+
if (!req.file) {
|
|
588
|
+
return res.status(400).json({ error: 'No file' });
|
|
589
|
+
}
|
|
590
|
+
res.json({ path: req.file.path });
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
// Redirect
|
|
594
|
+
app.get('/old', (req, res) => {
|
|
595
|
+
res.redirect(301, '/new');
|
|
596
|
+
});
|
|
597
|
+
|
|
598
|
+
// Download
|
|
599
|
+
app.get('/download/:file', async (req, res) => {
|
|
600
|
+
await res.download(`./files/${req.params.file}`);
|
|
601
|
+
});
|
|
602
|
+
|
|
603
|
+
// Content negotiation
|
|
604
|
+
app.get('/data', (req, res) => {
|
|
605
|
+
res.format({
|
|
606
|
+
'text/html': (req, res) => res.send('<h1>HTML</h1>'),
|
|
607
|
+
'application/json': (req, res) => res.json({ format: 'json' }),
|
|
608
|
+
'default': (req, res) => res.send('Default')
|
|
609
|
+
}, req);
|
|
610
|
+
});
|
|
611
|
+
|
|
612
|
+
app.listen(5051, (err, address) => {
|
|
613
|
+
if (err) throw err;
|
|
614
|
+
console.log(`Server on ${address?.url}`);
|
|
615
|
+
});
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
---
|
|
619
|
+
|
|
352
620
|
## Companion Client
|
|
353
621
|
|
|
354
622
|
Pair Sockress with [`sockress-client`](https://www.npmjs.com/package/sockress-client) to get automatic socket transports, FormData serialization, and seamless HTTP fallback:
|
package/package.json
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sockress",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.6",
|
|
4
4
|
"description": "Socket-first Express-compatible server with optional HTTP fallback, built-in WebSocket transport, uploader, and static helpers.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
7
|
-
"type": "module",
|
|
8
7
|
"exports": {
|
|
9
8
|
".": {
|
|
10
9
|
"import": "./dist/index.js",
|
|
@@ -29,6 +28,7 @@
|
|
|
29
28
|
"bugs": {
|
|
30
29
|
"url": "https://github.com/alsocoders/sockress/issues"
|
|
31
30
|
},
|
|
31
|
+
"license": "PROPRIETARY",
|
|
32
32
|
"keywords": [
|
|
33
33
|
"sockress",
|
|
34
34
|
"express",
|
package/dist/index.d.ts
DELETED
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
import http, { IncomingMessage, ServerResponse } from 'http';
|
|
2
|
-
import { AddressInfo } from 'net';
|
|
3
|
-
import { WebSocket } from 'ws';
|
|
4
|
-
import type { CookieSerializeOptions } from 'cookie';
|
|
5
|
-
import { Options as MulterOptions } from 'multer';
|
|
6
|
-
export interface SockressAddress extends AddressInfo {
|
|
7
|
-
hostname: string;
|
|
8
|
-
url: string;
|
|
9
|
-
}
|
|
10
|
-
type ListenCallback = (error: Error | null, address?: SockressAddress) => void;
|
|
11
|
-
type HTTPMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS';
|
|
12
|
-
export type NextFunction = (err?: unknown) => void;
|
|
13
|
-
export type SockressHandler = (req: SockressRequest, res: SockressResponse, next: NextFunction) => unknown;
|
|
14
|
-
export type SockressErrorHandler = (err: unknown, req: SockressRequest, res: SockressResponse, next: NextFunction) => unknown;
|
|
15
|
-
export interface SockressOptions {
|
|
16
|
-
cors?: Partial<CorsOptions>;
|
|
17
|
-
socket?: Partial<SocketOptions>;
|
|
18
|
-
bodyLimit?: number;
|
|
19
|
-
}
|
|
20
|
-
interface SocketOptions {
|
|
21
|
-
path: string;
|
|
22
|
-
heartbeatInterval: number;
|
|
23
|
-
idleTimeout: number;
|
|
24
|
-
}
|
|
25
|
-
interface CorsOptions {
|
|
26
|
-
origin: string | string[];
|
|
27
|
-
credentials: boolean;
|
|
28
|
-
methods: HTTPMethod[];
|
|
29
|
-
allowedHeaders: string[];
|
|
30
|
-
exposedHeaders: string[];
|
|
31
|
-
maxAge: number;
|
|
32
|
-
}
|
|
33
|
-
interface NormalizedOptions {
|
|
34
|
-
cors: CorsOptions;
|
|
35
|
-
socket: SocketOptions;
|
|
36
|
-
bodyLimit: number;
|
|
37
|
-
}
|
|
38
|
-
export interface SockressUploaderOptions {
|
|
39
|
-
dest?: string;
|
|
40
|
-
limits?: MulterOptions['limits'];
|
|
41
|
-
preserveFilename?: boolean;
|
|
42
|
-
}
|
|
43
|
-
export interface SockressUploader {
|
|
44
|
-
single(field: string): SockressHandler;
|
|
45
|
-
array(field: string, maxCount?: number): SockressHandler;
|
|
46
|
-
fields(fields: Array<{
|
|
47
|
-
name: string;
|
|
48
|
-
maxCount?: number;
|
|
49
|
-
}>): SockressHandler;
|
|
50
|
-
any(): SockressHandler;
|
|
51
|
-
}
|
|
52
|
-
export interface StaticOptions {
|
|
53
|
-
index?: string;
|
|
54
|
-
maxAge?: number;
|
|
55
|
-
stripPrefix?: string;
|
|
56
|
-
}
|
|
57
|
-
type RequestMode = {
|
|
58
|
-
kind: 'http';
|
|
59
|
-
req: IncomingMessage;
|
|
60
|
-
res: ServerResponse;
|
|
61
|
-
} | {
|
|
62
|
-
kind: 'socket';
|
|
63
|
-
socket: WebSocket;
|
|
64
|
-
requestId: string;
|
|
65
|
-
};
|
|
66
|
-
export interface SockressUploadedFile {
|
|
67
|
-
fieldName: string;
|
|
68
|
-
name: string;
|
|
69
|
-
type: string;
|
|
70
|
-
size: number;
|
|
71
|
-
buffer: Buffer;
|
|
72
|
-
lastModified?: number;
|
|
73
|
-
path?: string;
|
|
74
|
-
}
|
|
75
|
-
export interface SockressRequest {
|
|
76
|
-
readonly id: string;
|
|
77
|
-
readonly method: HTTPMethod;
|
|
78
|
-
path: string;
|
|
79
|
-
query: Record<string, string | string[]>;
|
|
80
|
-
params: Record<string, string>;
|
|
81
|
-
headers: Record<string, string | string[] | undefined>;
|
|
82
|
-
body: unknown;
|
|
83
|
-
cookies: Record<string, string>;
|
|
84
|
-
file?: SockressUploadedFile;
|
|
85
|
-
files?: Record<string, SockressUploadedFile[]>;
|
|
86
|
-
readonly type: 'http' | 'socket';
|
|
87
|
-
readonly ip: string | undefined;
|
|
88
|
-
readonly protocol: 'http' | 'https' | 'ws' | 'wss';
|
|
89
|
-
readonly secure: boolean;
|
|
90
|
-
context: Record<string, unknown>;
|
|
91
|
-
raw?: IncomingMessage;
|
|
92
|
-
get(field: string): string | undefined;
|
|
93
|
-
}
|
|
94
|
-
export declare class SockressRequestImpl implements SockressRequest {
|
|
95
|
-
readonly id: string;
|
|
96
|
-
readonly method: HTTPMethod;
|
|
97
|
-
path: string;
|
|
98
|
-
query: Record<string, string | string[]>;
|
|
99
|
-
headers: Record<string, string | string[] | undefined>;
|
|
100
|
-
body: unknown;
|
|
101
|
-
cookies: Record<string, string>;
|
|
102
|
-
files: Record<string, SockressUploadedFile[]> | undefined;
|
|
103
|
-
file: SockressUploadedFile | undefined;
|
|
104
|
-
readonly type: 'http' | 'socket';
|
|
105
|
-
readonly ip: string | undefined;
|
|
106
|
-
readonly protocol: 'http' | 'https' | 'ws' | 'wss';
|
|
107
|
-
readonly secure: boolean;
|
|
108
|
-
raw?: IncomingMessage | undefined;
|
|
109
|
-
params: Record<string, string>;
|
|
110
|
-
context: Record<string, unknown>;
|
|
111
|
-
constructor(id: string, method: HTTPMethod, path: string, query: Record<string, string | string[]>, headers: Record<string, string | string[] | undefined>, body: unknown, cookies: Record<string, string>, files: Record<string, SockressUploadedFile[]> | undefined, file: SockressUploadedFile | undefined, type: 'http' | 'socket', ip: string | undefined, protocol: 'http' | 'https' | 'ws' | 'wss', secure: boolean, raw?: IncomingMessage | undefined);
|
|
112
|
-
get(field: string): string | undefined;
|
|
113
|
-
}
|
|
114
|
-
export declare class SockressResponse {
|
|
115
|
-
private readonly mode;
|
|
116
|
-
private readonly cors;
|
|
117
|
-
private readonly allowedOrigin;
|
|
118
|
-
private statusCode;
|
|
119
|
-
private sent;
|
|
120
|
-
private headers;
|
|
121
|
-
private cookies;
|
|
122
|
-
readonly raw?: ServerResponse;
|
|
123
|
-
constructor(mode: RequestMode, cors: CorsOptions, allowedOrigin: string);
|
|
124
|
-
status(code: number): this;
|
|
125
|
-
set(field: string, value: string): this;
|
|
126
|
-
append(field: string, value: string): this;
|
|
127
|
-
cookie(name: string, value: string, options?: CookieSerializeOptions): this;
|
|
128
|
-
clearCookie(name: string, options?: CookieSerializeOptions): this;
|
|
129
|
-
json(payload: unknown): this;
|
|
130
|
-
send(payload?: unknown): this;
|
|
131
|
-
end(): this;
|
|
132
|
-
isSent(): boolean;
|
|
133
|
-
private buildHeaders;
|
|
134
|
-
}
|
|
135
|
-
export declare class SockressApp {
|
|
136
|
-
private readonly config;
|
|
137
|
-
private middlewares;
|
|
138
|
-
private routes;
|
|
139
|
-
private server?;
|
|
140
|
-
private wss?;
|
|
141
|
-
private heartbeatInterval?;
|
|
142
|
-
private shutdownRegistered;
|
|
143
|
-
private shuttingDown;
|
|
144
|
-
constructor(config: NormalizedOptions);
|
|
145
|
-
static create(options?: SockressOptions): SockressApp;
|
|
146
|
-
use(path: string, ...handlers: Array<SockressHandler | SockressErrorHandler>): this;
|
|
147
|
-
use(...handlers: Array<SockressHandler | SockressErrorHandler>): this;
|
|
148
|
-
useStatic(route: string, directory: string, options?: StaticOptions): this;
|
|
149
|
-
private register;
|
|
150
|
-
get(path: string, ...handlers: Array<SockressHandler | SockressErrorHandler>): this;
|
|
151
|
-
post(path: string, ...handlers: Array<SockressHandler | SockressErrorHandler>): this;
|
|
152
|
-
put(path: string, ...handlers: Array<SockressHandler | SockressErrorHandler>): this;
|
|
153
|
-
patch(path: string, ...handlers: Array<SockressHandler | SockressErrorHandler>): this;
|
|
154
|
-
delete(path: string, ...handlers: Array<SockressHandler | SockressErrorHandler>): this;
|
|
155
|
-
head(path: string, ...handlers: Array<SockressHandler | SockressErrorHandler>): this;
|
|
156
|
-
options(path: string, ...handlers: Array<SockressHandler | SockressErrorHandler>): this;
|
|
157
|
-
all(path: string, ...handlers: Array<SockressHandler | SockressErrorHandler>): this;
|
|
158
|
-
listen(port: number, callback?: ListenCallback): http.Server;
|
|
159
|
-
listen(port: number, host: string, callback?: ListenCallback): http.Server;
|
|
160
|
-
close(): Promise<void>;
|
|
161
|
-
private startHeartbeat;
|
|
162
|
-
private registerShutdownHooks;
|
|
163
|
-
private handleHttp;
|
|
164
|
-
private handleSocket;
|
|
165
|
-
private runPipeline;
|
|
166
|
-
private composeStack;
|
|
167
|
-
private renderError;
|
|
168
|
-
}
|
|
169
|
-
export declare function sockress(options?: SockressOptions): SockressApp;
|
|
170
|
-
export declare const createSockress: typeof sockress;
|
|
171
|
-
export declare function createUploader(options?: SockressUploaderOptions): SockressUploader;
|
|
172
|
-
export declare function serveStatic(root: string, options?: StaticOptions): SockressHandler;
|
|
173
|
-
export {};
|
|
174
|
-
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|