@vyriy/server 0.2.1 → 0.3.2
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 +50 -0
- package/index.d.ts +1 -1
- package/index.js +1 -1
- package/listener.d.ts +2 -1
- package/listener.js +14 -1
- package/package.json +5 -5
- package/result.js +10 -7
- package/server.d.ts +2 -1
- package/server.js +2 -1
- package/types.d.ts +10 -4
package/README.md
CHANGED
|
@@ -32,4 +32,54 @@ server(async () => ({
|
|
|
32
32
|
}));
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
+
Use `api(...)` when you want the handler package wrappers. It keeps the same `(event, context)` Lambda handler shape.
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import { api } from '@vyriy/handler';
|
|
39
|
+
import { server } from '@vyriy/server';
|
|
40
|
+
|
|
41
|
+
const handler = api(async (event) => ({
|
|
42
|
+
statusCode: 200,
|
|
43
|
+
body: JSON.stringify({
|
|
44
|
+
ok: true,
|
|
45
|
+
path: event.path,
|
|
46
|
+
}),
|
|
47
|
+
}));
|
|
48
|
+
|
|
49
|
+
server(handler);
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Run a Lambda response streaming handler locally:
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
import { streamServer } from '@vyriy/server';
|
|
56
|
+
|
|
57
|
+
streamServer(async (event, responseStream) => {
|
|
58
|
+
responseStream.setContentType?.('text/plain');
|
|
59
|
+
responseStream.write(`Path: ${event.path}\n`);
|
|
60
|
+
responseStream.end('Done');
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
The stream handler receives the API Gateway-style event first, the response stream second, and the Lambda context third.
|
|
65
|
+
|
|
66
|
+
Use `streamApi(...)` when you want the handler package wrappers. It keeps the same `(event, responseStream, context)` stream handler shape.
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
import { streamApi } from '@vyriy/handler';
|
|
70
|
+
import { streamServer } from '@vyriy/server';
|
|
71
|
+
|
|
72
|
+
const handler = streamApi((event, responseStream) => {
|
|
73
|
+
responseStream.setContentType?.('text/plain');
|
|
74
|
+
responseStream.write(`Path: ${event.path}\n`);
|
|
75
|
+
responseStream.end('Done');
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
streamServer(handler);
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Keep the AWS-specific `awslambda.streamifyResponse(handler)` wrapper in a separate Lambda entrypoint.
|
|
82
|
+
|
|
83
|
+
Static files are intentionally left to the Docker/web-server layer, for example Nginx, Caddy, or the platform serving assets in front of this Node process.
|
|
84
|
+
|
|
35
85
|
The server listens on `PORT` from `@vyriy/env`. The default port is `3000`.
|
package/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { server } from './server.js';
|
|
1
|
+
export { server, streamServer } from './server.js';
|
|
2
2
|
export type * from './types.js';
|
package/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { server } from './server.js';
|
|
1
|
+
export { server, streamServer } from './server.js';
|
package/listener.d.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
import type { LambdaHandler, NativeRequestListener } from './types.js';
|
|
1
|
+
import type { LambdaHandler, LambdaStreamHandler, NativeRequestListener } from './types.js';
|
|
2
2
|
export declare const listener: (handler: LambdaHandler) => NativeRequestListener;
|
|
3
|
+
export declare const streamListener: (handler: LambdaStreamHandler) => NativeRequestListener;
|
package/listener.js
CHANGED
|
@@ -1,10 +1,23 @@
|
|
|
1
1
|
import { mapParams } from './params.js';
|
|
2
2
|
import { error, result } from './result.js';
|
|
3
|
+
const createResponseStream = (response) => {
|
|
4
|
+
response.setContentType = (contentType) => response.setHeader?.('content-type', contentType) ?? response;
|
|
5
|
+
return response;
|
|
6
|
+
};
|
|
3
7
|
export const listener = (handler) => async (request, response) => {
|
|
4
8
|
try {
|
|
5
9
|
const { context, event } = await mapParams(request);
|
|
6
10
|
const value = await handler(event, context);
|
|
7
|
-
result(response, value);
|
|
11
|
+
await result(response, value);
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
error(response);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
export const streamListener = (handler) => async (request, response) => {
|
|
18
|
+
try {
|
|
19
|
+
const { context, event } = await mapParams(request);
|
|
20
|
+
await handler(event, createResponseStream(response), context);
|
|
8
21
|
}
|
|
9
22
|
catch {
|
|
10
23
|
error(response);
|
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vyriy/server",
|
|
3
|
-
"version": "0.2
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Small HTTP server adapter for Lambda-style Vyriy handlers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./index.js",
|
|
7
7
|
"dependencies": {
|
|
8
8
|
"@types/aws-lambda": "^8.10.161",
|
|
9
|
-
"@vyriy/env": "0.2
|
|
10
|
-
"@vyriy/error": "0.2
|
|
11
|
-
"@vyriy/handler": "0.2
|
|
12
|
-
"@vyriy/logger": "0.2
|
|
9
|
+
"@vyriy/env": "0.3.2",
|
|
10
|
+
"@vyriy/error": "0.3.2",
|
|
11
|
+
"@vyriy/handler": "0.3.2",
|
|
12
|
+
"@vyriy/logger": "0.3.2"
|
|
13
13
|
},
|
|
14
14
|
"agents": "./AGENTS.md",
|
|
15
15
|
"license": "MIT",
|
package/result.js
CHANGED
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
import { STATUS_CODES } from 'node:http';
|
|
2
|
+
const notFound = (response) => {
|
|
3
|
+
response
|
|
4
|
+
.writeHead(404, {
|
|
5
|
+
'content-type': 'application/json',
|
|
6
|
+
})
|
|
7
|
+
.end(JSON.stringify({ message: STATUS_CODES[404] }));
|
|
8
|
+
};
|
|
2
9
|
export const result = (response, value) => {
|
|
3
10
|
if (!value) {
|
|
4
|
-
response
|
|
5
|
-
.writeHead(404, {
|
|
6
|
-
'content-type': 'application/json',
|
|
7
|
-
})
|
|
8
|
-
.end(JSON.stringify({ message: STATUS_CODES[404] }));
|
|
11
|
+
notFound(response);
|
|
9
12
|
return;
|
|
10
13
|
}
|
|
11
|
-
const { body, headers, multiValueHeaders, statusCode } = value;
|
|
14
|
+
const { body, headers, isBase64Encoded, multiValueHeaders, statusCode } = value;
|
|
12
15
|
response.writeHead(statusCode, {
|
|
13
16
|
...headers,
|
|
14
17
|
...multiValueHeaders,
|
|
15
18
|
});
|
|
16
|
-
response.end(body);
|
|
19
|
+
response.end(isBase64Encoded ? Buffer.from(body, 'base64') : body);
|
|
17
20
|
};
|
|
18
21
|
export const error = (response) => {
|
|
19
22
|
response
|
package/server.d.ts
CHANGED
package/server.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as http from 'node:http';
|
|
2
|
-
import { listener } from './listener.js';
|
|
2
|
+
import { listener, streamListener } from './listener.js';
|
|
3
3
|
import { listen } from './listen.js';
|
|
4
4
|
export const server = (handler) => listen(http.createServer(listener(handler)));
|
|
5
|
+
export const streamServer = (handler) => listen(http.createServer(streamListener(handler)));
|
package/types.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import type { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from 'aws-lambda';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ResponseStream } from '@vyriy/handler';
|
|
3
3
|
import type { IncomingHttpHeaders, OutgoingHttpHeaders, Server as HttpServer } from 'node:http';
|
|
4
4
|
export type { Context } from 'aws-lambda';
|
|
5
5
|
export type Headers = OutgoingHttpHeaders;
|
|
6
6
|
export type LambdaEvent = APIGatewayProxyEvent;
|
|
7
7
|
export type LambdaResult = APIGatewayProxyResult;
|
|
8
|
-
export type LambdaHandler =
|
|
8
|
+
export type LambdaHandler = (event: LambdaEvent, context: Context) => Promise<LambdaResult>;
|
|
9
|
+
export type LambdaStreamHandler = (event: LambdaEvent, responseStream: ResponseStream, context: Context) => Promise<LambdaResult | void>;
|
|
9
10
|
export type RequestMessage = {
|
|
10
11
|
headers: IncomingHttpHeaders;
|
|
11
12
|
method?: string;
|
|
@@ -18,8 +19,12 @@ export type RequestMessage = {
|
|
|
18
19
|
export type ResponseMessage = {
|
|
19
20
|
end: {
|
|
20
21
|
(): ResponseMessage;
|
|
21
|
-
(chunk: string): ResponseMessage;
|
|
22
|
+
(chunk: string | Buffer | Uint8Array): ResponseMessage;
|
|
22
23
|
};
|
|
24
|
+
writableEnded?: boolean;
|
|
25
|
+
setContentType?: (contentType: string) => ResponseMessage;
|
|
26
|
+
setHeader?(name: string, value: number | string | readonly string[]): ResponseMessage;
|
|
27
|
+
write(chunk: string | Buffer | Uint8Array): boolean;
|
|
23
28
|
writeHead(statusCode: number, headers?: OutgoingHttpHeaders): ResponseMessage;
|
|
24
29
|
};
|
|
25
30
|
export type ErrorEventTarget = {
|
|
@@ -34,6 +39,7 @@ export type MapParams = (request: RequestMessage) => Promise<{
|
|
|
34
39
|
export type Server = HttpServer<typeof import('node:http').IncomingMessage, typeof import('node:http').ServerResponse>;
|
|
35
40
|
export type Listen = (server: Server) => Server;
|
|
36
41
|
export type NormalizeHeaders = (headers: IncomingHttpHeaders) => Record<string, string | undefined>;
|
|
37
|
-
export type WriteResult<Response extends ResponseMessage = ResponseMessage> = (response: Response, result: LambdaResult | void) => void;
|
|
42
|
+
export type WriteResult<Response extends ResponseMessage = ResponseMessage> = (response: Response, result: LambdaResult | void) => Promise<void> | void;
|
|
38
43
|
export type WriteError<Response extends ResponseMessage = ResponseMessage> = (response: Response) => void;
|
|
39
44
|
export type CreateServer = (handler: LambdaHandler) => Server;
|
|
45
|
+
export type CreateStreamServer = (handler: LambdaStreamHandler) => Server;
|