sleepy-serv 0.7.0 → 0.9.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 +20 -4
- package/dist/errors.d.ts +1 -2
- package/dist/errors.d.ts.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/socket.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/errors.ts +2 -5
- package/src/index.ts +39 -28
- package/src/socket.ts +14 -18
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ A directory-driven web server designed for REST-ful applications
|
|
|
5
5
|
## Important Notes
|
|
6
6
|
|
|
7
7
|
- This package requires [`bun.sh`](https://bun.sh) instead of NodeJS to run.
|
|
8
|
-
- This project requires bun v1.
|
|
8
|
+
- This project requires bun v1.3.14 or higher
|
|
9
9
|
|
|
10
10
|
## Getting Started
|
|
11
11
|
|
|
@@ -26,9 +26,25 @@ The parameter for `import.meta.dirname` can be any directory you prefer, but it'
|
|
|
26
26
|
|
|
27
27
|
### Return Value
|
|
28
28
|
|
|
29
|
-
`sleepy-serv` was originally built for NodeJS, but it was ported to `bun` recently (before the initial release). The `createApp()` function merely calls `Bun.serve()` under-the-hood, and returns the `app` object that contains
|
|
29
|
+
`sleepy-serv` was originally built for NodeJS, but it was ported to `bun` recently (before the initial release). The `createApp()` function merely calls `Bun.serve()` under-the-hood, and returns the `app` object that contains these properties:
|
|
30
30
|
- `routes`: Contains a list of all of the routes defined by the file structure. This is useful for debugging.
|
|
31
|
-
- `server`: this is the object that's returned from `Bun.serve()`. The `server` object has an `async` `.stop()` method on it, which
|
|
31
|
+
- `server`: this is the object that's returned from `Bun.serve()`. The `server` object has an `async` `.stop()` method on it, but prefer `app.close()` (see [Shutting Down](#shutting-down)), which stops the server and releases everything else the app holds.
|
|
32
|
+
- `commands`: WebSocket helpers for pushing messages out to connected clients: `send(clientId, event, body)` and `broadcast(event, body)`.
|
|
33
|
+
- `close`: an `async` function that shuts the app down. See [Shutting Down](#shutting-down).
|
|
34
|
+
|
|
35
|
+
### Shutting Down
|
|
36
|
+
|
|
37
|
+
`app.close()` shuts the app down and releases everything it holds:
|
|
38
|
+
|
|
39
|
+
```js
|
|
40
|
+
const app = await createApp(PORT, import.meta.dirname)
|
|
41
|
+
|
|
42
|
+
await app.close()
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
It stops the server, tears down the Ctrl+D shutdown handler, and calls [`onClose`](#onclose). Pass `close(true)` to force-close active connections rather than waiting for in-flight requests to finish. That argument is handed straight to `server.stop()`, so it behaves exactly as it does in `Bun.serve()`.
|
|
46
|
+
|
|
47
|
+
This matters most for tests that start and stop an app per case. Calling `server.stop()` on its own stops the HTTP listener but leaves the Ctrl+D shutdown handler attached to `stdin`, which holds an open handle and can keep the process from exiting. `app.close()` does not have that problem.
|
|
32
48
|
|
|
33
49
|
### Adding Routes
|
|
34
50
|
|
|
@@ -465,7 +481,7 @@ Yields these routes:
|
|
|
465
481
|
|
|
466
482
|
### `onClose`
|
|
467
483
|
|
|
468
|
-
When the app is started, the app can be shutdown gracefully by pressing Ctrl+D in the terminal. The `onClose` hook will be called during that shutdown if it's defined. `onClose` can also be `async` as well.
|
|
484
|
+
When the app is started, the app can be shutdown gracefully by pressing Ctrl+D in the terminal. That handler is only wired up when `stdin` is a TTY, so it's skipped in CI, in test runners, and anywhere `stdin` is piped. The `onClose` hook will be called during that shutdown if it's defined, and it's also called by [`app.close()`](#shutting-down). `onClose` can also be `async` as well.
|
|
469
485
|
|
|
470
486
|
```js
|
|
471
487
|
const app = await createApp(PORT, import.meta.dirname, {
|
package/dist/errors.d.ts
CHANGED
|
@@ -127,8 +127,7 @@ export declare class UnavailableForLegalReasonsError extends RequestError {
|
|
|
127
127
|
}
|
|
128
128
|
export declare class InternalServerError extends RequestError {
|
|
129
129
|
static get status(): StatusCode;
|
|
130
|
-
|
|
131
|
-
constructor(message: string, ctx?: unknown);
|
|
130
|
+
constructor();
|
|
132
131
|
}
|
|
133
132
|
export declare class NotImplementedError extends RequestError {
|
|
134
133
|
static get status(): StatusCode;
|
package/dist/errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAEpC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAE7C,MAAM,MAAM,WAAW,GACnB;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,GACnB,cAAc,EAAE,GAChB,IAAI,CAAA;AAER,qBAAa,YAAa,SAAQ,KAAK;IACrC,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;IAED,IAAI,MAAM,IAAK,WAAW,CAEzB;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAID,qBAAa,eAAgB,SAAQ,YAAY;IAC/C,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,iBAAkB,SAAQ,YAAY;IACjD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,oBAAqB,SAAQ,YAAY;IACpD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,cAAe,SAAQ,YAAY;IAC9C,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,aAAc,SAAQ,YAAY;IAC7C,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;;CAOF;AAED,qBAAa,qBAAsB,SAAQ,YAAY;IACrD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;;CAOF;AAED,qBAAa,kBAAmB,SAAQ,YAAY;IAClD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,gCAAiC,SAAQ,YAAY;IAChE,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,mBAAoB,SAAQ,YAAY;IACnD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,aAAc,SAAQ,YAAY;IAC7C,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,SAAU,SAAQ,YAAY;IACzC,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,mBAAoB,SAAQ,YAAY;IACnD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,uBAAwB,SAAQ,YAAY;IACvD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,oBAAqB,SAAQ,YAAY;IACpD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,eAAgB,SAAQ,YAAY;IAC/C,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,yBAA0B,SAAQ,YAAY;IACzD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,wBAAyB,SAAQ,YAAY;IACxD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,sBAAuB,SAAQ,YAAY;IACtD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,cAAe,SAAQ,YAAY;IAC9C,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,uBAAwB,SAAQ,YAAY;IACvD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,yBAA0B,SAAQ,YAAY;IACzD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;IAED,IAAI,MAAM,IAAK,WAAW,CAEzB;gBAEY,MAAM,EAAE,cAAc,EAAE;CAKtC;AAED,qBAAa,WAAY,SAAQ,YAAY;IAC3C,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,qBAAsB,SAAQ,YAAY;IACrD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,aAAc,SAAQ,YAAY;IAC7C,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,oBAAqB,SAAQ,YAAY;IACpD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,yBAA0B,SAAQ,YAAY;IACzD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,oBAAqB,SAAQ,YAAY;IACpD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,gCAAiC,SAAQ,YAAY;IAChE,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,+BAAgC,SAAQ,YAAY;IAC/D,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAID,qBAAa,mBAAoB,SAAQ,YAAY;IACnD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAEpC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAE7C,MAAM,MAAM,WAAW,GACnB;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,GACnB,cAAc,EAAE,GAChB,IAAI,CAAA;AAER,qBAAa,YAAa,SAAQ,KAAK;IACrC,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;IAED,IAAI,MAAM,IAAK,WAAW,CAEzB;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAID,qBAAa,eAAgB,SAAQ,YAAY;IAC/C,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,iBAAkB,SAAQ,YAAY;IACjD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,oBAAqB,SAAQ,YAAY;IACpD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,cAAe,SAAQ,YAAY;IAC9C,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,aAAc,SAAQ,YAAY;IAC7C,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;;CAOF;AAED,qBAAa,qBAAsB,SAAQ,YAAY;IACrD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;;CAOF;AAED,qBAAa,kBAAmB,SAAQ,YAAY;IAClD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,gCAAiC,SAAQ,YAAY;IAChE,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,mBAAoB,SAAQ,YAAY;IACnD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,aAAc,SAAQ,YAAY;IAC7C,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,SAAU,SAAQ,YAAY;IACzC,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,mBAAoB,SAAQ,YAAY;IACnD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,uBAAwB,SAAQ,YAAY;IACvD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,oBAAqB,SAAQ,YAAY;IACpD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,eAAgB,SAAQ,YAAY;IAC/C,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,yBAA0B,SAAQ,YAAY;IACzD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,wBAAyB,SAAQ,YAAY;IACxD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,sBAAuB,SAAQ,YAAY;IACtD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,cAAe,SAAQ,YAAY;IAC9C,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,uBAAwB,SAAQ,YAAY;IACvD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,yBAA0B,SAAQ,YAAY;IACzD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;IAED,IAAI,MAAM,IAAK,WAAW,CAEzB;gBAEY,MAAM,EAAE,cAAc,EAAE;CAKtC;AAED,qBAAa,WAAY,SAAQ,YAAY;IAC3C,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,qBAAsB,SAAQ,YAAY;IACrD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,aAAc,SAAQ,YAAY;IAC7C,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,oBAAqB,SAAQ,YAAY;IACpD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,yBAA0B,SAAQ,YAAY;IACzD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,oBAAqB,SAAQ,YAAY;IACpD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,gCAAiC,SAAQ,YAAY;IAChE,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,+BAAgC,SAAQ,YAAY;IAC/D,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAID,qBAAa,mBAAoB,SAAQ,YAAY;IACnD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;;CAOF;AAED,qBAAa,mBAAoB,SAAQ,YAAY;IACnD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;;CAOF;AAED,qBAAa,eAAgB,SAAQ,YAAY;IAC/C,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,uBAAwB,SAAQ,YAAY;IACvD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,mBAAoB,SAAQ,YAAY;IACnD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;;CAOF;AAED,qBAAa,4BAA6B,SAAQ,YAAY;IAC5D,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,0BAA2B,SAAQ,YAAY;IAC1D,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,wBAAyB,SAAQ,YAAY;IACxD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,iBAAkB,SAAQ,YAAY;IACjD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,gBAAiB,SAAQ,YAAY;IAChD,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B;AAED,qBAAa,kCAAmC,SAAQ,YAAY;IAClE,MAAM,KAAK,MAAM,IAAK,UAAU,CAE/B;gBAEY,OAAO,EAAE,MAAM;CAK7B"}
|
package/dist/index.d.ts
CHANGED
|
@@ -7,10 +7,12 @@ export type { AppOptions, EndpointRequest, FormattedError, Middleware, NextFn, R
|
|
|
7
7
|
export type { FormatterField, FormatterSchema, ValidationSchemas, } from './middleware';
|
|
8
8
|
export type { SocketCommands } from './socket';
|
|
9
9
|
type OutputRoutes = Record<string, string[]>;
|
|
10
|
+
type CloseFn = (force?: boolean) => Promise<void>;
|
|
10
11
|
export type App = {
|
|
11
12
|
server: Server;
|
|
12
13
|
commands: SocketCommands;
|
|
13
14
|
routes: OutputRoutes;
|
|
15
|
+
close: CloseFn;
|
|
14
16
|
};
|
|
15
17
|
export declare function createApp(port: number, rootPath: string, opts?: AppOptions): Promise<App>;
|
|
16
18
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAIV,UAAU,EACV,MAAM,EACP,MAAM,SAAS,CAAA;AAEhB,OAAO,KAAK,EAGV,cAAc,EACf,MAAM,UAAU,CAAA;AAEjB,cAAc,UAAU,CAAA;AAExB,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,eAAe,GAChB,MAAM,cAAc,CAAA;AAErB,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAEhD,YAAY,EACV,UAAU,EACV,eAAe,EACf,cAAc,EACd,UAAU,EACV,MAAM,EACN,OAAO,EACP,MAAM,EACN,aAAa,EACb,gBAAgB,GACjB,MAAM,SAAS,CAAA;AAEhB,YAAY,EACV,cAAc,EACd,eAAe,EACf,iBAAiB,GAClB,MAAM,cAAc,CAAA;AAErB,YAAY,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAE9C,KAAK,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;AA4C5C,KAAK,OAAO,GAAG,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;AAEjD,MAAM,MAAM,GAAG,GAAG;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,cAAc,CAAA;IACxB,MAAM,EAAE,YAAY,CAAA;IACpB,KAAK,EAAE,OAAO,CAAA;CACf,CAAA;AAoZD,wBAAsB,SAAS,CAC7B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,UAAe,GACpB,OAAO,CAAC,GAAG,CAAC,CAad"}
|
package/dist/socket.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"socket.d.ts","sourceRoot":"","sources":["../src/socket.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"socket.d.ts","sourceRoot":"","sources":["../src/socket.ts"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,KAAK,CAAA;AAE3C,OAAO,KAAK,EACV,UAAU,EACV,OAAO,EAEP,UAAU,EACV,UAAU,EACV,UAAU,EACX,MAAM,SAAS,CAAA;AAShB,MAAM,MAAM,MAAM,GAAG;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,UAAU,CAAA;IAChB,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAA;IAC/B,KAAK,EAAE,MAAM,IAAI,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,EAAE,EAAE,gBAAgB,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,OAAO,GAAG,aAAa,GAAG,eAAe,CAAA;AAErD,MAAM,MAAM,WAAW,GAAG;IACxB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,iBAAiB,EAAE,MAAM,CAAA;IACzB,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC5B,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;IAC1C,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;CAC/C,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,MAAM,EAAE,UAAU,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,KAAK,EAAE,UAAU,EAAE,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,UAAU,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,KAAK,QAAQ,CAAA;CAClD,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IAC9D,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;CAClD,CAAA;AA2SD,wBAAgB,gBAAgB,CAAE,IAAI,GAAE,UAAe,GAAG,WAAW,CAWpE;AAED,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,WAAW,EAAE,EACrB,KAAK,EAAE,WAAW,GACjB,gBAAgB,CAAC,UAAU,CAAC,CAuH9B;AAED,wBAAgB,mBAAmB,CAAE,KAAK,EAAE,WAAW,GAAG,cAAc,EAAE,CAqIzE;AAED,wBAAgB,mBAAmB,CAAE,KAAK,EAAE,WAAW,GAAG,cAAc,CA+BvE"}
|
package/package.json
CHANGED
package/src/errors.ts
CHANGED
|
@@ -384,13 +384,10 @@ export class InternalServerError extends RequestError {
|
|
|
384
384
|
return StatusCode.InternalServerError
|
|
385
385
|
}
|
|
386
386
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
constructor (message: string, ctx?: unknown) {
|
|
390
|
-
super(message)
|
|
387
|
+
constructor () {
|
|
388
|
+
super('An internal server error occurred')
|
|
391
389
|
|
|
392
390
|
this.name = 'InternalServerError'
|
|
393
|
-
this.ctx = ctx
|
|
394
391
|
}
|
|
395
392
|
}
|
|
396
393
|
|
package/src/index.ts
CHANGED
|
@@ -4,7 +4,7 @@ import querystring from 'querystring'
|
|
|
4
4
|
import readline from 'node:readline'
|
|
5
5
|
|
|
6
6
|
import { stdin, stdout } from 'node:process'
|
|
7
|
-
import {
|
|
7
|
+
import { toSegments, executeMiddlewareChain } from './utils'
|
|
8
8
|
|
|
9
9
|
import {
|
|
10
10
|
buildSocketState,
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
RequestError,
|
|
18
18
|
NotFoundError,
|
|
19
19
|
MethodNotAllowedError,
|
|
20
|
+
InternalServerError,
|
|
20
21
|
} from './errors'
|
|
21
22
|
|
|
22
23
|
import type { BunRequest } from 'bun'
|
|
@@ -109,10 +110,13 @@ type AppRoutes = {
|
|
|
109
110
|
socket: SocketRoute[]
|
|
110
111
|
}
|
|
111
112
|
|
|
113
|
+
type CloseFn = (force?: boolean) => Promise<void>
|
|
114
|
+
|
|
112
115
|
export type App = {
|
|
113
116
|
server: Server
|
|
114
117
|
commands: SocketCommands
|
|
115
118
|
routes: OutputRoutes
|
|
119
|
+
close: CloseFn
|
|
116
120
|
}
|
|
117
121
|
|
|
118
122
|
const ALLOWED_FILES_META = ['meta.js', 'meta.ts']
|
|
@@ -132,16 +136,6 @@ const ALLOWED_FILES_METHODS = [
|
|
|
132
136
|
'delete.ts',
|
|
133
137
|
]
|
|
134
138
|
|
|
135
|
-
/* istanbul ignore if */
|
|
136
|
-
if (process.stdin.isTTY) {
|
|
137
|
-
process.stdin.setRawMode(true)
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
const rl = readline.createInterface({
|
|
141
|
-
input: stdin,
|
|
142
|
-
output: stdout,
|
|
143
|
-
})
|
|
144
|
-
|
|
145
139
|
function methodNotAllowedHandler (_req: unknown): never {
|
|
146
140
|
throw new MethodNotAllowedError()
|
|
147
141
|
}
|
|
@@ -382,8 +376,8 @@ function buildSocketRoutes (mergedRoutes: ChainRoute[]): SocketRoute[] {
|
|
|
382
376
|
}))
|
|
383
377
|
}
|
|
384
378
|
|
|
385
|
-
function buildModuleRoutes (
|
|
386
|
-
return
|
|
379
|
+
function buildModuleRoutes (socketRoutes: SocketRoute[]): ModuleRoute[] {
|
|
380
|
+
return socketRoutes.map(route => {
|
|
387
381
|
const handler: EndpointHandler = async (bunReq, server) => {
|
|
388
382
|
const req = buildEndpointRequest(bunReq, server)
|
|
389
383
|
|
|
@@ -477,15 +471,11 @@ function buildServer (
|
|
|
477
471
|
error (err) {
|
|
478
472
|
console.error(err)
|
|
479
473
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
return Response.json(err.output, { status: ctor.status })
|
|
484
|
-
}
|
|
474
|
+
const isRequestError = !(err instanceof RequestError)
|
|
475
|
+
const httpError = isRequestError ? new InternalServerError() : err
|
|
476
|
+
const { status } = httpError.constructor as typeof RequestError
|
|
485
477
|
|
|
486
|
-
return
|
|
487
|
-
status: StatusCode.InternalServerError,
|
|
488
|
-
})
|
|
478
|
+
return Response.json(httpError.output, { status })
|
|
489
479
|
},
|
|
490
480
|
})
|
|
491
481
|
}
|
|
@@ -494,7 +484,7 @@ function processIO (
|
|
|
494
484
|
port: number,
|
|
495
485
|
server: Server,
|
|
496
486
|
opts: AppOptions,
|
|
497
|
-
):
|
|
487
|
+
): CloseFn {
|
|
498
488
|
const onClose = opts.onClose || (() => {})
|
|
499
489
|
|
|
500
490
|
console.info(`Running on port: ${port}`)
|
|
@@ -502,12 +492,33 @@ function processIO (
|
|
|
502
492
|
console.info('Press Ctrl+D to gracefully shutdown')
|
|
503
493
|
console.info('')
|
|
504
494
|
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
await server.stop()
|
|
495
|
+
const shutdown = async (force = false): Promise<void> => {
|
|
496
|
+
await server.stop(force)
|
|
508
497
|
await onClose()
|
|
509
|
-
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
if (!stdin.isTTY) {
|
|
501
|
+
return shutdown
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
const rl = readline.createInterface({
|
|
505
|
+
input: stdin,
|
|
506
|
+
output: stdout,
|
|
510
507
|
})
|
|
508
|
+
|
|
509
|
+
const handleClose = async (): Promise<void> => {
|
|
510
|
+
await shutdown()
|
|
511
|
+
process.exit(0)
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
rl.on('close', handleClose)
|
|
515
|
+
|
|
516
|
+
return async (force = false) => {
|
|
517
|
+
rl.off('close', handleClose)
|
|
518
|
+
rl.close()
|
|
519
|
+
|
|
520
|
+
await shutdown(force)
|
|
521
|
+
}
|
|
511
522
|
}
|
|
512
523
|
|
|
513
524
|
export async function createApp (
|
|
@@ -519,12 +530,12 @@ export async function createApp (
|
|
|
519
530
|
const routes = await buildRoutes(rootPath, state, opts)
|
|
520
531
|
const server = buildServer(port, routes, state, opts)
|
|
521
532
|
const commands = buildSocketCommands(state)
|
|
522
|
-
|
|
523
|
-
processIO(port, server, opts)
|
|
533
|
+
const close = processIO(port, server, opts)
|
|
524
534
|
|
|
525
535
|
return {
|
|
526
536
|
routes: routes.output,
|
|
527
537
|
server,
|
|
528
538
|
commands,
|
|
539
|
+
close,
|
|
529
540
|
}
|
|
530
541
|
}
|
package/src/socket.ts
CHANGED
|
@@ -2,7 +2,11 @@ import Ajv from 'ajv'
|
|
|
2
2
|
import addFormats from 'ajv-formats'
|
|
3
3
|
import crypto from 'node:crypto'
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
MessageType,
|
|
7
|
+
createMessage,
|
|
8
|
+
validateMessage,
|
|
9
|
+
} from './messages'
|
|
6
10
|
|
|
7
11
|
import {
|
|
8
12
|
StatusCode,
|
|
@@ -21,8 +25,8 @@ import {
|
|
|
21
25
|
ServiceUnavailableError,
|
|
22
26
|
} from './errors'
|
|
23
27
|
|
|
24
|
-
import type { WebSocketHandler } from 'bun'
|
|
25
28
|
import type { ValidateFunction } from 'ajv'
|
|
29
|
+
import type { WebSocketHandler } from 'bun'
|
|
26
30
|
|
|
27
31
|
import type {
|
|
28
32
|
HttpMethod,
|
|
@@ -375,25 +379,17 @@ function buildErrorMessage (
|
|
|
375
379
|
err: unknown,
|
|
376
380
|
): ResponseMessage {
|
|
377
381
|
const { id, clientId } = message as Pick<BaseMessage, 'id' | 'clientId'>
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
return createMessage(clientId, MessageType.Response, {
|
|
383
|
-
id,
|
|
384
|
-
status: ctor.status,
|
|
385
|
-
headers: new Headers({
|
|
386
|
-
'content-type': 'application/json;charset=utf-8',
|
|
387
|
-
}),
|
|
388
|
-
body: err.output,
|
|
389
|
-
})
|
|
390
|
-
}
|
|
382
|
+
const isRequestError = err instanceof RequestError
|
|
383
|
+
const httpError = isRequestError ? err : new InternalServerError()
|
|
384
|
+
const { status } = httpError.constructor as typeof RequestError
|
|
391
385
|
|
|
392
386
|
return createMessage(clientId, MessageType.Response, {
|
|
393
387
|
id,
|
|
394
|
-
status
|
|
395
|
-
headers: new Headers(
|
|
396
|
-
|
|
388
|
+
status,
|
|
389
|
+
headers: new Headers({
|
|
390
|
+
'content-type': 'application/json;charset=utf-8',
|
|
391
|
+
}),
|
|
392
|
+
body: httpError.output,
|
|
397
393
|
})
|
|
398
394
|
}
|
|
399
395
|
|