srvx 0.10.1 → 0.11.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.
@@ -0,0 +1,292 @@
1
+ import { r as wrapFetch, t as errorPlugin } from "../_chunks/_plugins.mjs";
2
+ function awsRequest(event, context) {
3
+ const req = new Request(awsEventURL(event), {
4
+ method: awsEventMethod(event),
5
+ headers: awsEventHeaders(event),
6
+ body: awsEventBody(event)
7
+ });
8
+ req.runtime = {
9
+ name: "aws-lambda",
10
+ awsLambda: {
11
+ event,
12
+ context
13
+ }
14
+ };
15
+ req.ip = awsEventIP(event);
16
+ return req;
17
+ }
18
+ function awsEventMethod(event) {
19
+ return event.httpMethod || event.requestContext?.http?.method || "GET";
20
+ }
21
+ function awsEventIP(event) {
22
+ return event.requestContext?.http?.sourceIp || event.requestContext?.identity?.sourceIp;
23
+ }
24
+ function awsEventURL(event) {
25
+ const hostname = event.headers.host || event.headers.Host || event.requestContext?.domainName || ".";
26
+ const path = event.path || event.rawPath;
27
+ const query = awsEventQuery(event);
28
+ const protocol = (event.headers["X-Forwarded-Proto"] || event.headers["x-forwarded-proto"]) === "http" ? "http" : "https";
29
+ return new URL(`${path}${query ? `?${query}` : ""}`, `${protocol}://${hostname}`);
30
+ }
31
+ function awsEventQuery(event) {
32
+ if (typeof event.rawQueryString === "string") return event.rawQueryString;
33
+ return stringifyQuery({
34
+ ...event.queryStringParameters,
35
+ ...event.multiValueQueryStringParameters
36
+ });
37
+ }
38
+ function awsEventHeaders(event) {
39
+ const headers = new Headers();
40
+ for (const [key, value] of Object.entries(event.headers)) if (value) headers.set(key, value);
41
+ if ("cookies" in event && event.cookies) for (const cookie of event.cookies) headers.append("cookie", cookie);
42
+ return headers;
43
+ }
44
+ function awsEventBody(event) {
45
+ if (!event.body) return;
46
+ if (event.isBase64Encoded) return Buffer.from(event.body || "", "base64");
47
+ return event.body;
48
+ }
49
+ function awsResponseHeaders(response, event) {
50
+ const headers = Object.create(null);
51
+ for (const [key, value] of response.headers) if (value) headers[key] = Array.isArray(value) ? value.join(",") : String(value);
52
+ const cookies = response.headers.getSetCookie();
53
+ if (cookies.length === 0) return { headers };
54
+ return event?.version === "2.0" || !!event?.requestContext?.http ? {
55
+ headers,
56
+ cookies
57
+ } : {
58
+ headers,
59
+ cookies,
60
+ multiValueHeaders: { "set-cookie": cookies }
61
+ };
62
+ }
63
+ async function awsResponseBody(response) {
64
+ if (!response.body) return { body: "" };
65
+ const buffer = await toBuffer(response.body);
66
+ return isTextType(response.headers.get("content-type") || "") ? { body: buffer.toString("utf8") } : {
67
+ body: buffer.toString("base64"),
68
+ isBase64Encoded: true
69
+ };
70
+ }
71
+ async function awsStreamResponse(response, responseStream, event) {
72
+ const metadata = {
73
+ statusCode: response.status,
74
+ ...awsResponseHeaders(response, event)
75
+ };
76
+ if (!metadata.headers["transfer-encoding"]) metadata.headers["transfer-encoding"] = "chunked";
77
+ const writer = globalThis.awslambda.HttpResponseStream.from(responseStream, metadata);
78
+ if (!response.body) {
79
+ writer.end();
80
+ return;
81
+ }
82
+ try {
83
+ await streamToNodeStream(response.body, writer);
84
+ } finally {
85
+ writer.end();
86
+ }
87
+ }
88
+ async function streamToNodeStream(body, writer) {
89
+ const reader = body.getReader();
90
+ try {
91
+ let result = await reader.read();
92
+ while (!result.done) {
93
+ if (!writer.write(result.value)) await new Promise((resolve) => writer.once("drain", resolve));
94
+ result = await reader.read();
95
+ }
96
+ } finally {
97
+ reader.releaseLock();
98
+ }
99
+ }
100
+ function isTextType(contentType = "") {
101
+ return /^text\/|\/(javascript|json|xml)|utf-?8/i.test(contentType);
102
+ }
103
+ function toBuffer(data) {
104
+ return new Promise((resolve, reject) => {
105
+ const chunks = [];
106
+ data.pipeTo(new WritableStream({
107
+ write(chunk) {
108
+ chunks.push(chunk);
109
+ },
110
+ close() {
111
+ resolve(Buffer.concat(chunks));
112
+ },
113
+ abort(reason) {
114
+ reject(reason);
115
+ }
116
+ })).catch(reject);
117
+ });
118
+ }
119
+ function stringifyQuery(obj) {
120
+ const params = new URLSearchParams();
121
+ for (const [key, value] of Object.entries(obj)) {
122
+ if (value == null) continue;
123
+ if (Array.isArray(value)) for (const v of value) params.append(key, String(v));
124
+ else params.append(key, String(value));
125
+ }
126
+ return params.toString();
127
+ }
128
+ async function requestToAwsEvent(request) {
129
+ const url = new URL(request.url);
130
+ const headers = {};
131
+ const cookies = [];
132
+ for (const [key, value] of request.headers) {
133
+ if (key.toLowerCase() === "cookie") cookies.push(value);
134
+ headers[key] = value;
135
+ }
136
+ let body;
137
+ let isBase64Encoded = false;
138
+ if (request.body) {
139
+ const buffer = await toBuffer(request.body);
140
+ if (isTextType(request.headers.get("content-type") || "")) body = buffer.toString("utf8");
141
+ else {
142
+ body = buffer.toString("base64");
143
+ isBase64Encoded = true;
144
+ }
145
+ }
146
+ const now = Date.now();
147
+ return {
148
+ httpMethod: request.method,
149
+ path: url.pathname,
150
+ resource: url.pathname,
151
+ queryStringParameters: Object.fromEntries(url.searchParams),
152
+ multiValueQueryStringParameters: parseMultiValueQuery(url.searchParams),
153
+ pathParameters: void 0,
154
+ stageVariables: void 0,
155
+ multiValueHeaders: Object.fromEntries([...request.headers].map(([k, v]) => [k, [v]])),
156
+ version: "2.0",
157
+ rawPath: url.pathname,
158
+ rawQueryString: url.search.slice(1),
159
+ cookies: cookies.length > 0 ? cookies : void 0,
160
+ routeKey: `${request.method} ${url.pathname}`,
161
+ headers,
162
+ body: body ?? null,
163
+ isBase64Encoded,
164
+ requestContext: {
165
+ accountId: "000000000000",
166
+ apiId: "local",
167
+ resourceId: "local",
168
+ stage: "$default",
169
+ requestId: crypto.randomUUID(),
170
+ identity: {
171
+ sourceIp: "127.0.0.1",
172
+ userAgent: request.headers.get("user-agent") || "",
173
+ accessKey: null,
174
+ accountId: null,
175
+ apiKey: null,
176
+ apiKeyId: null,
177
+ caller: null,
178
+ clientCert: null,
179
+ cognitoAuthenticationProvider: null,
180
+ cognitoAuthenticationType: null,
181
+ cognitoIdentityId: null,
182
+ cognitoIdentityPoolId: null,
183
+ principalOrgId: null,
184
+ user: null,
185
+ userArn: null
186
+ },
187
+ resourcePath: url.pathname,
188
+ httpMethod: request.method,
189
+ path: url.pathname,
190
+ protocol: "HTTP/1.1",
191
+ requestTimeEpoch: now,
192
+ authorizer: void 0,
193
+ domainName: url.hostname,
194
+ http: {
195
+ method: request.method,
196
+ path: url.pathname,
197
+ protocol: "HTTP/1.1",
198
+ sourceIp: "127.0.0.1",
199
+ userAgent: request.headers.get("user-agent") || ""
200
+ },
201
+ routeKey: `${request.method} ${url.pathname}`,
202
+ time: new Date(now).toISOString(),
203
+ timeEpoch: now,
204
+ domainPrefix: url.hostname.split(".")[0]
205
+ }
206
+ };
207
+ }
208
+ function parseMultiValueQuery(params) {
209
+ const result = {};
210
+ for (const [key, value] of params) {
211
+ if (!result[key]) result[key] = [];
212
+ result[key].push(value);
213
+ }
214
+ return result;
215
+ }
216
+ function awsResultToResponse(result) {
217
+ if (typeof result === "string") return new Response(result, { status: 200 });
218
+ const headers = new Headers();
219
+ if (result.headers) {
220
+ for (const [key, value] of Object.entries(result.headers)) if (value !== void 0) headers.set(key, String(value));
221
+ }
222
+ if ("multiValueHeaders" in result && result.multiValueHeaders) {
223
+ for (const [key, values] of Object.entries(result.multiValueHeaders)) if (values) for (const value of values) headers.append(key, String(value));
224
+ }
225
+ if ("cookies" in result && result.cookies) for (const cookie of result.cookies) headers.append("set-cookie", cookie);
226
+ let body;
227
+ if (typeof result.body === "string") if (result.isBase64Encoded) body = Buffer.from(result.body, "base64");
228
+ else body = result.body;
229
+ const statusCode = typeof result.statusCode === "number" ? result.statusCode : 200;
230
+ return new Response(body, {
231
+ status: statusCode,
232
+ headers
233
+ });
234
+ }
235
+ function createMockContext() {
236
+ const id = crypto.randomUUID();
237
+ return {
238
+ callbackWaitsForEmptyEventLoop: true,
239
+ functionName: "local",
240
+ functionVersion: "$LATEST",
241
+ invokedFunctionArn: `arn:aws:lambda:us-east-1:000000000000:function:local`,
242
+ memoryLimitInMB: "128",
243
+ awsRequestId: id,
244
+ logGroupName: "/aws/lambda/local",
245
+ logStreamName: `${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}/[$LATEST]${id}`,
246
+ getRemainingTimeInMillis: () => 3e4,
247
+ done: () => {},
248
+ fail: () => {},
249
+ succeed: () => {}
250
+ };
251
+ }
252
+ function toLambdaHandler(options) {
253
+ const server = new AWSLambdaServer(options);
254
+ return (event, context) => server.fetch(event, context);
255
+ }
256
+ async function handleLambdaEvent(fetchHandler, event, context) {
257
+ const response = await fetchHandler(awsRequest(event, context));
258
+ return {
259
+ statusCode: response.status,
260
+ ...awsResponseHeaders(response, event),
261
+ ...await awsResponseBody(response)
262
+ };
263
+ }
264
+ async function handleLambdaEventWithStream(fetchHandler, event, responseStream, context) {
265
+ await awsStreamResponse(await fetchHandler(awsRequest(event, context)), responseStream, event);
266
+ }
267
+ async function invokeLambdaHandler(handler, request) {
268
+ return awsResultToResponse(await handler(await requestToAwsEvent(request), createMockContext()));
269
+ }
270
+ var AWSLambdaServer = class {
271
+ runtime = "aws-lambda";
272
+ options;
273
+ fetch;
274
+ constructor(options) {
275
+ this.options = {
276
+ ...options,
277
+ middleware: [...options.middleware || []]
278
+ };
279
+ for (const plugin of options.plugins || []) plugin(this);
280
+ errorPlugin(this);
281
+ const fetchHandler = wrapFetch(this);
282
+ this.fetch = (event, context) => handleLambdaEvent(fetchHandler, event, context);
283
+ }
284
+ serve() {}
285
+ ready() {
286
+ return Promise.resolve().then(() => this);
287
+ }
288
+ close() {
289
+ return Promise.resolve();
290
+ }
291
+ };
292
+ export { handleLambdaEvent, handleLambdaEventWithStream, invokeLambdaHandler, toLambdaHandler };
@@ -1,4 +1,4 @@
1
- import { g as Server, t as BunFetchHandler, y as ServerOptions } from "../_chunks/types.mjs";
1
+ import { BunFetchHandler, Server, ServerOptions } from "../types.mjs";
2
2
  import { t as FastURL } from "../_chunks/_url.mjs";
3
3
  import * as bun from "bun";
4
4
 
@@ -1,8 +1,6 @@
1
1
  import { t as FastURL } from "../_chunks/_url.mjs";
2
- import { a as resolveTLSOptions, i as resolvePortAndHost, n as fmtURL, r as printListening, t as createWaitUntil } from "../_chunks/_utils.mjs";
2
+ import { a as resolveTLSOptions, i as resolvePortAndHost, n as fmtURL, r as printListening, t as createWaitUntil } from "../_chunks/_utils2.mjs";
3
3
  import { n as gracefulShutdownPlugin, r as wrapFetch } from "../_chunks/_plugins.mjs";
4
-
5
- //#region src/adapters/bun.ts
6
4
  const FastResponse = Response;
7
5
  function serve(options) {
8
6
  return new BunServer(options);
@@ -77,6 +75,4 @@ var BunServer = class {
77
75
  await Promise.all([this.#wait.wait(), Promise.resolve(this.bun?.server?.stop(closeAll))]);
78
76
  }
79
77
  };
80
-
81
- //#endregion
82
- export { FastResponse, FastURL, serve };
78
+ export { FastResponse, FastURL, serve };
@@ -1,4 +1,4 @@
1
- import { g as Server, y as ServerOptions } from "../_chunks/types.mjs";
1
+ import { Server, ServerOptions } from "../types.mjs";
2
2
  import * as CF from "@cloudflare/workers-types";
3
3
 
4
4
  //#region src/adapters/cloudflare.d.ts
@@ -1,6 +1,4 @@
1
1
  import { r as wrapFetch, t as errorPlugin } from "../_chunks/_plugins.mjs";
2
-
3
- //#region src/adapters/cloudflare.ts
4
2
  const FastURL = URL;
5
3
  const FastResponse = Response;
6
4
  function serve(options) {
@@ -56,6 +54,4 @@ var CloudflareServer = class {
56
54
  return Promise.resolve();
57
55
  }
58
56
  };
59
-
60
- //#endregion
61
- export { FastResponse, FastURL, serve };
57
+ export { FastResponse, FastURL, serve };
@@ -1,4 +1,4 @@
1
- import { g as Server, r as DenoFetchHandler, y as ServerOptions } from "../_chunks/types.mjs";
1
+ import { DenoFetchHandler, Server, ServerOptions } from "../types.mjs";
2
2
  import { t as FastURL } from "../_chunks/_url.mjs";
3
3
 
4
4
  //#region src/adapters/deno.d.ts
@@ -1,8 +1,6 @@
1
1
  import { t as FastURL } from "../_chunks/_url.mjs";
2
- import { a as resolveTLSOptions, i as resolvePortAndHost, n as fmtURL, r as printListening, t as createWaitUntil } from "../_chunks/_utils.mjs";
2
+ import { a as resolveTLSOptions, i as resolvePortAndHost, n as fmtURL, r as printListening, t as createWaitUntil } from "../_chunks/_utils2.mjs";
3
3
  import { n as gracefulShutdownPlugin, r as wrapFetch } from "../_chunks/_plugins.mjs";
4
-
5
- //#region src/adapters/deno.ts
6
4
  const FastResponse = Response;
7
5
  function serve(options) {
8
6
  return new DenoServer(options);
@@ -86,6 +84,4 @@ var DenoServer = class {
86
84
  await Promise.all([this.#wait.wait(), Promise.resolve(this.deno?.server?.shutdown())]);
87
85
  }
88
86
  };
89
-
90
- //#endregion
91
- export { FastResponse, FastURL, serve };
87
+ export { FastResponse, FastURL, serve };
@@ -1,4 +1,4 @@
1
- import { g as Server, y as ServerOptions } from "../_chunks/types.mjs";
1
+ import { Server, ServerOptions } from "../types.mjs";
2
2
 
3
3
  //#region src/adapters/generic.d.ts
4
4
  declare const FastURL: typeof globalThis.URL;
@@ -1,7 +1,5 @@
1
- import { t as createWaitUntil } from "../_chunks/_utils.mjs";
1
+ import { t as createWaitUntil } from "../_chunks/_utils2.mjs";
2
2
  import { r as wrapFetch, t as errorPlugin } from "../_chunks/_plugins.mjs";
3
-
4
- //#region src/adapters/generic.ts
5
3
  const FastURL = URL;
6
4
  const FastResponse = Response;
7
5
  function serve(options) {
@@ -34,6 +32,4 @@ var GenericServer = class {
34
32
  await this.#wait.wait();
35
33
  }
36
34
  };
37
-
38
- //#endregion
39
- export { FastResponse, FastURL, serve };
35
+ export { FastResponse, FastURL, serve };
@@ -1,4 +1,4 @@
1
- import { g as Server, h as NodeServerResponse, m as NodeServerRequest, p as NodeHttpHandler, s as FetchHandler, x as ServerRequest, y as ServerOptions } from "../_chunks/types.mjs";
1
+ import { FetchHandler, NodeHttpHandler, NodeServerRequest, NodeServerResponse, Server, ServerOptions, ServerRequest } from "../types.mjs";
2
2
  import { t as FastURL } from "../_chunks/_url.mjs";
3
3
  import { Readable } from "node:stream";
4
4