sockress 0.2.5 → 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 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,6 +1,6 @@
1
1
  {
2
2
  "name": "sockress",
3
- "version": "0.2.5",
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",
@@ -28,6 +28,7 @@
28
28
  "bugs": {
29
29
  "url": "https://github.com/alsocoders/sockress/issues"
30
30
  },
31
+ "license": "PROPRIETARY",
31
32
  "keywords": [
32
33
  "sockress",
33
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
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}