web-listener 0.1.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/LICENSE ADDED
@@ -0,0 +1,45 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 David Evans
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+ The distributable version of this library includes a bundled copy of busboy
24
+ and streamsearch (with minification and tree shaking applied), which are also
25
+ available under the MIT License:
26
+
27
+ Copyright Brian White. All rights reserved.
28
+
29
+ Permission is hereby granted, free of charge, to any person obtaining a copy
30
+ of this software and associated documentation files (the "Software"), to
31
+ deal in the Software without restriction, including without limitation the
32
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
33
+ sell copies of the Software, and to permit persons to whom the Software is
34
+ furnished to do so, subject to the following conditions:
35
+
36
+ The above copyright notice and this permission notice shall be included in
37
+ all copies or substantial portions of the Software.
38
+
39
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
40
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
41
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
42
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
43
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
44
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
45
+ IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,168 @@
1
+ # Web Listener
2
+
3
+ A small server abstraction for creating API and resource endpoints with middleware. Supports
4
+ HTTP/1.1 and upgrade requests.
5
+
6
+ `web-listener` is designed to be tree-shakable so that it provides a minimal framework for those who
7
+ want something simple, while still being able to deliver advanced capabilities for those who need
8
+ them. By removing unused features at build time, `web-listener` is able to have a much smaller
9
+ memory footprint at runtime than alternatives which provide features via object methods.
10
+
11
+ The core API shares concepts with `express`, but uses helper functions rather than adding methods to
12
+ the request and response objects. For example, to define a route with a path parameter:
13
+
14
+ ```js
15
+ import { WebListener, Router, getPathParameter } from 'web-listener';
16
+
17
+ const router = new Router();
18
+
19
+ router.get('/things/:id', (req, res) => {
20
+ const id = getPathParameter(req, 'id');
21
+ res.end(`You asked for item ${id}`);
22
+ });
23
+
24
+ new WebListener(router).listen(3000);
25
+ ```
26
+
27
+ ## Features
28
+
29
+ - Production ready
30
+ - Protected against attacks such as directory traversal, path confusion, and compression bombs
31
+ - Performant techniques used to receive and send data
32
+ - Supports "hardened" runtime environments (e.g. `--disable-proto=throw`, `--no-addons`, and
33
+ `--disallow-code-generation-from-strings`)
34
+ - Comprehensively tested
35
+ - Full support for TypeScript and type safety
36
+ - Written entirely in TypeScript, and full type definitions are included
37
+ - Complex features such as path parameters are correctly typed (including for sub-routers)
38
+ - Small size and memory footprint
39
+ - Existing object prototypes are not modified; all features are available as imported functions
40
+ - Unused features can removed via tree-shaking / dead-code-analysis during the build (via any of
41
+ the major bundlers and minifiers) to reduce runtime size even further
42
+ - No package dependencies (bundles a minified copy of `busboy` for form data handling)
43
+ - Very low runtime memory requirements; only minimal book-keeping is needed to track each request,
44
+ and the standard handlers are designed to have low working-memory requirements. Minified code
45
+ means little runtime memory is occupied by the source code (Node.js keeps a copy of all source
46
+ code in memory for debugging).
47
+ - Flexible and customisable
48
+ - Most parts of the API can be swapped out for alternatives
49
+ - All internal values and timeouts are configurable to support specific needs
50
+ - Default configuration matches Node.js wherever possible to avoid surprises, and
51
+ `web-listener`-specific options have sensible defaults to enable getting started quickly
52
+ - Command-line helper for local development
53
+ - Serve content from a directory
54
+ - Proxy content from another server
55
+ - Serve specific fixtures
56
+ - Run multiple servers from a single command
57
+ - Path routing
58
+ - Path parameters (individual components, sub-components, multiple components)
59
+ - Optional path components
60
+ - Error handling
61
+ - Thrown errors can be caught by later middleware, or handled automatically
62
+ - `HTTPError` and `WebSocketError` make it easy to close the connection at any point with specific
63
+ error codes, and can include custom messages and headers
64
+ - Upgrade handling
65
+ - WebSockets (bring-your-own-library, e.g. `ws`)
66
+ - Custom upgrades
67
+ - Automatic support for `shouldUpgradeCallback` in Node.js 24.9+ to enable support for specific
68
+ upgrade protocols without breaking requests that ask for unrelated protocols
69
+ - Request header helpers
70
+ - Parsers for common headers and header formats
71
+ - Client information (e.g. IP) with support for trusted proxies
72
+ - Request body parsing
73
+ - Raw binary data
74
+ - Compressed requests (deflate, gzip, brotli, zstd)
75
+ - Streaming data
76
+ - Configurable size limits for both raw content and uncompressed data
77
+ - Optional custom `Expect: 100-continue` handling
78
+ - `text/*`
79
+ - `application/json` (including charset detection)
80
+ - `application/x-www-url-encoded`
81
+ - `multipart/form-data`, including file uploads to a temporary location
82
+ - Uses built-in `TextDecoderStream` for character set support, and allows registering additional /
83
+ replacement character sets (bring-your-own-library)
84
+ - Static file serving
85
+ - Compression (via pre-compressed files)
86
+ - Range requests
87
+ - Cache control, etags (strong and weak), and modified times
88
+ - Automatic serving of content in a directory
89
+ - Manual serving of any file with a path or `Readable` (requires byte size and last modified time)
90
+ - Common file extension MIME types handled out-of-the-box, more can be registered if needed
91
+ - Response helpers
92
+ - Server Sent Events helper class
93
+ - JSON, including streaming entities which contain async iterators or streams
94
+ - CSV
95
+ - Request proxying
96
+ - Hooks for templating
97
+ - `onReturn` can be used to integrate templating engines (bring-your-own-library), or used for
98
+ peace-of-mind tasks like automatically closing responses when handlers return.
99
+ - Modern and interoperable APIs
100
+ - Request handlers match `http.Server`'s 'request' event signature
101
+ - Upgrade handlers match `http.Server`'s 'upgrade' event signature
102
+ - Web Streams used for streaming data (also accepts Node.js streams)
103
+ - Promises used and supported in most places
104
+
105
+ ## Install dependency
106
+
107
+ ```sh
108
+ npm install --save web-listener
109
+ ```
110
+
111
+ Or to just serve static content from a directory:
112
+
113
+ ```sh
114
+ npx web-listener . -p 8080
115
+ ```
116
+
117
+ ## Getting Started Examples
118
+
119
+ ```js
120
+ import { WebListener, Router, getPathParameter, HTTPError, CONTINUE } from 'web-listener';
121
+
122
+ const r = new Router();
123
+
124
+ r.get('/things/:id', async (req, res) => {
125
+ const id = getPathParameter(req, 'id');
126
+ const myObject = await loadObject(id);
127
+ res.write(JSON.stringify(myObject)).end();
128
+ });
129
+
130
+ const authCheck = (req, res) => {
131
+ if (req.headers['authorization'] !== 'Please') {
132
+ throw new HTTPError(401, { body: "You didn't say the magic word" });
133
+ }
134
+ return CONTINUE;
135
+ };
136
+
137
+ r.get('/private-things/:id', authCheck, async (req, res) => {
138
+ const id = getPathParameter(req, 'id');
139
+ const myObject = await loadPrivateObject(id);
140
+ res.write(JSON.stringify(myObject)).end();
141
+ });
142
+
143
+ r.get('/{*path}', (req, res) => {
144
+ const path = getPathParameter(req, 'path');
145
+ res.write(`You requested ${path.join('/')}`).end();
146
+ });
147
+
148
+ const weblistener = new WebListener(r);
149
+ const server = await weblistener.listen(8080, 'localhost');
150
+ ```
151
+
152
+ To run with a HTTPS server:
153
+
154
+ ```js
155
+ import { createServer } from 'node:https';
156
+
157
+ // setup weblistener as before
158
+
159
+ const server = createServer({
160
+ /* ... */
161
+ });
162
+ weblistener.attach(server);
163
+ server.listen(8080, 'localhost');
164
+ ```
165
+
166
+ ## API Documentation
167
+
168
+ TODO: write API documentation