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.
- package/README.md +6 -20
- package/bin/srvx.mjs +5 -3
- package/dist/_chunks/_plugins.mjs +2 -9
- package/dist/_chunks/_url.mjs +33 -25
- package/dist/_chunks/_utils.mjs +14 -73
- package/dist/_chunks/_utils2.mjs +70 -0
- package/dist/_chunks/loader.d.mts +74 -0
- package/dist/_chunks/loader.mjs +108 -0
- package/dist/adapters/aws-lambda.d.mts +19 -0
- package/dist/adapters/aws-lambda.mjs +292 -0
- package/dist/adapters/bun.d.mts +1 -1
- package/dist/adapters/bun.mjs +2 -6
- package/dist/adapters/cloudflare.d.mts +1 -1
- package/dist/adapters/cloudflare.mjs +1 -5
- package/dist/adapters/deno.d.mts +1 -1
- package/dist/adapters/deno.mjs +2 -6
- package/dist/adapters/generic.d.mts +1 -1
- package/dist/adapters/generic.mjs +2 -6
- package/dist/adapters/node.d.mts +1 -1
- package/dist/adapters/node.mjs +164 -84
- package/dist/adapters/service-worker.d.mts +1 -1
- package/dist/adapters/service-worker.mjs +1 -5
- package/dist/cli.d.mts +46 -11
- package/dist/cli.mjs +323 -272
- package/dist/loader.d.mts +2 -0
- package/dist/loader.mjs +2 -0
- package/dist/log.d.mts +1 -1
- package/dist/log.mjs +2 -6
- package/dist/static.d.mts +1 -1
- package/dist/static.mjs +4 -8
- package/dist/tracing.d.mts +1 -2
- package/dist/tracing.mjs +1 -25
- package/dist/types.d.mts +302 -1
- package/package.json +37 -34
- package/dist/_chunks/_color.mjs +0 -18
- package/dist/_chunks/_inherit.mjs +0 -31
- package/dist/_chunks/call.mjs +0 -157
- package/dist/_chunks/call2.mjs +0 -3
- package/dist/_chunks/types.d.mts +0 -283
|
@@ -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 };
|
package/dist/adapters/bun.d.mts
CHANGED
package/dist/adapters/bun.mjs
CHANGED
|
@@ -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/
|
|
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,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 };
|
package/dist/adapters/deno.d.mts
CHANGED
package/dist/adapters/deno.mjs
CHANGED
|
@@ -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/
|
|
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,7 +1,5 @@
|
|
|
1
|
-
import { t as createWaitUntil } from "../_chunks/
|
|
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 };
|
package/dist/adapters/node.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
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
|
|