shokupan 0.6.1 → 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 +55 -2
- package/dist/{openapi-analyzer-Bei1sVWp.cjs → analyzer-Bei1sVWp.cjs} +1 -1
- package/dist/analyzer-Bei1sVWp.cjs.map +1 -0
- package/dist/{openapi-analyzer-Ce_7JxZh.js → analyzer-Ce_7JxZh.js} +1 -1
- package/dist/analyzer-Ce_7JxZh.js.map +1 -0
- package/dist/cli.cjs +2 -2
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/context.d.ts +58 -23
- package/dist/{server-adapter-DFhwlK8e.cjs → http-server-BEMPIs33.cjs} +4 -2
- package/dist/http-server-BEMPIs33.cjs.map +1 -0
- package/dist/{server-adapter-0xH174zz.js → http-server-CCeagTyU.js} +4 -2
- package/dist/http-server-CCeagTyU.js.map +1 -0
- package/dist/index.cjs +1940 -917
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +18 -17
- package/dist/index.js +1948 -925
- package/dist/index.js.map +1 -1
- package/dist/middleware.d.ts +1 -1
- package/dist/plugins/{auth.d.ts → application/auth.d.ts} +72 -3
- package/dist/plugins/application/cluster.d.ts +33 -0
- package/dist/plugins/{failed-request-recorder.d.ts → application/dashboard/failed-request-recorder.d.ts} +1 -1
- package/dist/plugins/application/dashboard/metrics-collector.d.ts +12 -0
- package/dist/plugins/application/dashboard/plugin.d.ts +42 -0
- package/dist/plugins/application/dashboard/static/charts.js +328 -0
- package/dist/plugins/application/dashboard/static/failures.js +85 -0
- package/dist/plugins/application/dashboard/static/graph.mjs +523 -0
- package/dist/plugins/application/dashboard/static/poll.js +146 -0
- package/dist/plugins/application/dashboard/static/reactflow.css +18 -0
- package/dist/plugins/application/dashboard/static/registry.css +131 -0
- package/dist/plugins/application/dashboard/static/registry.js +269 -0
- package/dist/plugins/application/dashboard/static/requests.js +118 -0
- package/dist/plugins/application/dashboard/static/scrollbar.css +24 -0
- package/dist/plugins/application/dashboard/static/styles.css +175 -0
- package/dist/plugins/application/dashboard/static/tables.js +92 -0
- package/dist/plugins/application/dashboard/static/tabs.js +113 -0
- package/dist/plugins/application/dashboard/static/tabulator.css +66 -0
- package/dist/plugins/application/dashboard/template.eta +246 -0
- package/dist/plugins/{server-adapter.d.ts → application/http-server.d.ts} +1 -1
- package/dist/plugins/{idempotency → application/idempotency}/plugin.d.ts +7 -1
- package/dist/plugins/{openapi.d.ts → application/openapi/openapi.d.ts} +2 -2
- package/dist/plugins/application/scalar.d.ts +36 -0
- package/dist/plugins/application/socket-io.d.ts +14 -0
- package/dist/plugins/middleware/compression.d.ts +17 -0
- package/dist/plugins/middleware/cors.d.ts +34 -0
- package/dist/plugins/{express.d.ts → middleware/express.d.ts} +1 -1
- package/dist/plugins/{openapi-validator.d.ts → middleware/openapi-validator.d.ts} +2 -2
- package/dist/plugins/middleware/proxy.d.ts +37 -0
- package/dist/plugins/middleware/rate-limit.d.ts +58 -0
- package/dist/plugins/{security-headers.d.ts → middleware/security-headers.d.ts} +51 -1
- package/dist/plugins/{serve-static.d.ts → middleware/serve-static.d.ts} +1 -1
- package/dist/plugins/{session.d.ts → middleware/session.d.ts} +89 -3
- package/dist/plugins/{validation.d.ts → middleware/validation.d.ts} +6 -1
- package/dist/router.d.ts +17 -5
- package/dist/shokupan.d.ts +31 -5
- package/dist/util/async-hooks.d.ts +8 -2
- package/dist/util/datastore.d.ts +4 -3
- package/dist/{decorators.d.ts → util/decorators.d.ts} +6 -1
- package/dist/util/http-error.d.ts +38 -0
- package/dist/util/http-status.d.ts +32 -0
- package/dist/util/instrumentation.d.ts +1 -1
- package/dist/{request.d.ts → util/request.d.ts} +1 -1
- package/dist/util/symbol.d.ts +34 -0
- package/dist/{router → util}/trie.d.ts +1 -1
- package/dist/{types.d.ts → util/types.d.ts} +38 -2
- package/package.json +9 -6
- package/dist/openapi-analyzer-Bei1sVWp.cjs.map +0 -1
- package/dist/openapi-analyzer-Ce_7JxZh.js.map +0 -1
- package/dist/plugins/compression.d.ts +0 -5
- package/dist/plugins/cors.d.ts +0 -11
- package/dist/plugins/debugview/plugin.d.ts +0 -29
- package/dist/plugins/proxy.d.ts +0 -11
- package/dist/plugins/rate-limit.d.ts +0 -15
- package/dist/plugins/scalar.d.ts +0 -15
- package/dist/server-adapter-0xH174zz.js.map +0 -1
- package/dist/server-adapter-DFhwlK8e.cjs.map +0 -1
- package/dist/symbol.d.ts +0 -15
- /package/dist/{analysis/openapi-analyzer.d.ts → plugins/application/openapi/analyzer.d.ts} +0 -0
- /package/dist/{di.d.ts → util/di.d.ts} +0 -0
- /package/dist/{response.d.ts → util/response.d.ts} +0 -0
package/dist/context.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { BodyInit, Server } from 'bun';
|
|
2
|
-
import {
|
|
3
|
-
import { ShokupanResponse } from './response';
|
|
1
|
+
import { BodyInit, Server, ServerWebSocket } from 'bun';
|
|
2
|
+
import { Socket, Server as SocketServer } from 'socket.io';
|
|
4
3
|
import { Shokupan } from './shokupan';
|
|
5
|
-
import {
|
|
6
|
-
|
|
4
|
+
import { ShokupanRequest } from './util/request';
|
|
5
|
+
import { ShokupanResponse } from './util/response';
|
|
6
|
+
import { $bodyParsed, $bodyParseError, $bodyType, $cachedBody, $cachedHost, $cachedHostname, $cachedOrigin, $cachedProtocol, $cachedQuery, $debug, $finalResponse, $io, $rawBody, $requestId, $routeMatched, $socket, $url, $ws } from './util/symbol';
|
|
7
|
+
import { CookieOptions, HeadersInit, JSXRenderer } from './util/types';
|
|
7
8
|
export interface HandlerStackItem {
|
|
8
9
|
name: string;
|
|
9
10
|
file: string;
|
|
@@ -88,19 +89,30 @@ export declare class ShokupanContext<State extends Record<string, any> = Record<
|
|
|
88
89
|
state: State;
|
|
89
90
|
handlerStack: HandlerStackItem[];
|
|
90
91
|
readonly response: ShokupanResponse;
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
private
|
|
95
|
-
private
|
|
96
|
-
private
|
|
97
|
-
private
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
private
|
|
101
|
-
private
|
|
102
|
-
private
|
|
103
|
-
private
|
|
92
|
+
[$debug]?: DebugCollector;
|
|
93
|
+
[$finalResponse]?: Response;
|
|
94
|
+
[$rawBody]?: string | ArrayBuffer | Uint8Array;
|
|
95
|
+
private [$url]?;
|
|
96
|
+
private [$cachedBody]?;
|
|
97
|
+
private [$bodyType]?;
|
|
98
|
+
private [$bodyParsed];
|
|
99
|
+
private [$bodyParseError]?;
|
|
100
|
+
[$routeMatched]: boolean;
|
|
101
|
+
private [$cachedHostname]?;
|
|
102
|
+
private [$cachedProtocol]?;
|
|
103
|
+
private [$cachedHost]?;
|
|
104
|
+
private [$cachedOrigin]?;
|
|
105
|
+
private [$cachedQuery]?;
|
|
106
|
+
private [$ws]?;
|
|
107
|
+
private [$socket]?;
|
|
108
|
+
private [$io]?;
|
|
109
|
+
/**
|
|
110
|
+
* JSX Rendering Function
|
|
111
|
+
*/
|
|
112
|
+
private renderer?;
|
|
113
|
+
setRenderer(renderer: JSXRenderer): void;
|
|
114
|
+
private [$requestId];
|
|
115
|
+
get requestId(): string;
|
|
104
116
|
constructor(request: ShokupanRequest<any>, server?: Server, state?: State, app?: Shokupan, signal?: AbortSignal, // Optional as it might not be provided in tests or simple creates
|
|
105
117
|
enableMiddlewareTracking?: boolean);
|
|
106
118
|
get url(): URL;
|
|
@@ -157,12 +169,34 @@ export declare class ShokupanContext<State extends Record<string, any> = Record<
|
|
|
157
169
|
* Base response object
|
|
158
170
|
*/
|
|
159
171
|
get res(): ShokupanResponse;
|
|
172
|
+
/**
|
|
173
|
+
* Raw WebSocket connection
|
|
174
|
+
*/
|
|
175
|
+
get ws(): ServerWebSocket<undefined>;
|
|
176
|
+
/**
|
|
177
|
+
* Socket.io socket
|
|
178
|
+
*/
|
|
179
|
+
get socket(): Socket<import('socket.io').DefaultEventsMap, import('socket.io').DefaultEventsMap, import('socket.io').DefaultEventsMap, any>;
|
|
180
|
+
/**
|
|
181
|
+
* Socket.io server
|
|
182
|
+
*/
|
|
183
|
+
get io(): SocketServer<import('socket.io').DefaultEventsMap, import('socket.io').DefaultEventsMap, import('socket.io').DefaultEventsMap, any>;
|
|
160
184
|
/**
|
|
161
185
|
* Helper to set a header on the response
|
|
162
186
|
* @param key Header key
|
|
163
187
|
* @param value Header value
|
|
164
188
|
*/
|
|
165
189
|
set(key: string, value: string): this;
|
|
190
|
+
isUpgraded: boolean;
|
|
191
|
+
/**
|
|
192
|
+
* Upgrades the request to a WebSocket connection.
|
|
193
|
+
* @param options Upgrade options
|
|
194
|
+
* @returns true if upgraded, false otherwise
|
|
195
|
+
*/
|
|
196
|
+
upgrade(options?: {
|
|
197
|
+
data?: any;
|
|
198
|
+
headers?: HeadersInit;
|
|
199
|
+
}): boolean;
|
|
166
200
|
/**
|
|
167
201
|
* Set a cookie
|
|
168
202
|
* @param name Cookie name
|
|
@@ -195,6 +229,12 @@ export declare class ShokupanContext<State extends Record<string, any> = Record<
|
|
|
195
229
|
* @returns Response
|
|
196
230
|
*/
|
|
197
231
|
send(body?: BodyInit, options?: ResponseInit): Response;
|
|
232
|
+
/**
|
|
233
|
+
* Emit an event to the client (WebSocket only)
|
|
234
|
+
* @param event Event name
|
|
235
|
+
* @param data Event data (Must be JSON serializable)
|
|
236
|
+
*/
|
|
237
|
+
emit(event: string, data?: any): void;
|
|
198
238
|
/**
|
|
199
239
|
* Respond with a JSON object
|
|
200
240
|
*/
|
|
@@ -220,10 +260,6 @@ export declare class ShokupanContext<State extends Record<string, any> = Record<
|
|
|
220
260
|
* Respond with a file
|
|
221
261
|
*/
|
|
222
262
|
file(path: string, fileOptions?: BlobPropertyBag, responseOptions?: ResponseInit): Promise<Response>;
|
|
223
|
-
/**
|
|
224
|
-
* JSX Rendering Function
|
|
225
|
-
*/
|
|
226
|
-
renderer?: JSXRenderer;
|
|
227
263
|
/**
|
|
228
264
|
* Render a JSX element
|
|
229
265
|
* @param element JSX Element
|
|
@@ -232,4 +268,3 @@ export declare class ShokupanContext<State extends Record<string, any> = Record<
|
|
|
232
268
|
*/
|
|
233
269
|
jsx(element: any, args?: Parameters<JSXRenderer>[1], status?: number, headers?: HeadersInit): Promise<Response>;
|
|
234
270
|
}
|
|
235
|
-
export {};
|
|
@@ -70,7 +70,9 @@ function createHttpServer() {
|
|
|
70
70
|
requestIP: (req) => null,
|
|
71
71
|
publish: () => 0,
|
|
72
72
|
subscriberCount: () => 0,
|
|
73
|
-
url: new URL(`http://${options.hostname}:${options.port}`)
|
|
73
|
+
url: new URL(`http://${options.hostname}:${options.port}`),
|
|
74
|
+
// Expose the raw Node.js server for generic socket/websocket support (e.g. Socket.IO)
|
|
75
|
+
nodeServer: server
|
|
74
76
|
};
|
|
75
77
|
return new Promise((resolve) => {
|
|
76
78
|
server.listen(options.port, options.hostname, () => {
|
|
@@ -80,4 +82,4 @@ function createHttpServer() {
|
|
|
80
82
|
};
|
|
81
83
|
}
|
|
82
84
|
exports.createHttpServer = createHttpServer;
|
|
83
|
-
//# sourceMappingURL=server-
|
|
85
|
+
//# sourceMappingURL=http-server-BEMPIs33.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-server-BEMPIs33.cjs","sources":["../src/plugins/application/http-server.ts"],"sourcesContent":["import type { Server } from \"bun\";\nimport * as http from \"node:http\";\nimport * as https from \"node:https\";\nimport type { ServerFactory } from \"../../util/types\";\n\n/**\n * Creates a server factory that uses the standard Node.js `http` module.\n * @returns A ServerFactory compatible with Shokupan.\n */\nexport function createHttpServer(): ServerFactory {\n return async (options: any): Promise<Server> => {\n const server = http.createServer(async (req, res) => {\n const url = new URL(req.url!, `http://${req.headers.host}`);\n const request = new Request(url.toString(), {\n method: req.method,\n headers: req.headers as any,\n body: ['GET', 'HEAD'].includes(req.method!) ? undefined : new ReadableStream({\n start(controller) {\n req.on('data', chunk => controller.enqueue(chunk));\n req.on('end', () => controller.close());\n req.on('error', err => controller.error(err));\n }\n }) as any,\n // Required for Node.js undici when sending a body\n duplex: 'half'\n } as any);\n\n const response = await options.fetch(request, fauxServer);\n\n res.statusCode = response.status;\n response.headers.forEach((v, k) => res.setHeader(k, v));\n\n if (response.body) {\n // Optimize: Use arrayBuffer for direct conversion instead of async iteration\n const buffer = await response.arrayBuffer();\n res.end(Buffer.from(buffer));\n } else {\n res.end();\n }\n });\n\n const fauxServer: Server = {\n stop: () => {\n server.close();\n return Promise.resolve(); // Bun.Server stop usually returns void but in type definition it might vary.\n },\n upgrade(req, options) {\n return false;\n },\n reload(options) {\n return fauxServer as any;\n },\n get port() {\n const addr = server.address();\n if (typeof addr === 'object' && addr !== null) {\n return addr.port;\n }\n return options.port;\n },\n hostname: options.hostname,\n development: options.development,\n pendingRequests: 0,\n requestIP: (req) => null,\n publish: () => 0,\n subscriberCount: () => 0,\n url: new URL(`http://${options.hostname}:${options.port}`),\n // Expose the raw Node.js server for generic socket/websocket support (e.g. Socket.IO)\n nodeServer: server\n } as unknown as Server;\n\n return new Promise((resolve) => {\n server.listen(options.port, options.hostname, () => {\n resolve(fauxServer);\n });\n });\n };\n}\n\n/**\n * Creates a server factory that uses the standard Node.js `https` module.\n * @param sslOptions - Node.js HTTPS options (key, cert, etc.)\n * @returns A ServerFactory compatible with Shokupan.\n */\nexport function createHttpsServer(sslOptions: https.ServerOptions): ServerFactory {\n return async (options: any): Promise<Server> => {\n const server = https.createServer(sslOptions, async (req, res) => {\n const url = new URL(req.url!, `https://${req.headers.host}`);\n const request = new Request(url.toString(), {\n method: req.method,\n headers: req.headers as any,\n body: ['GET', 'HEAD'].includes(req.method!) ? undefined : new ReadableStream({\n start(controller) {\n req.on('data', chunk => controller.enqueue(chunk));\n req.on('end', () => controller.close());\n req.on('error', err => controller.error(err));\n }\n }) as any,\n // Required for Node.js undici when sending a body\n duplex: 'half'\n } as any);\n\n const response = await options.fetch(request, fauxServer);\n\n res.statusCode = response.status;\n response.headers.forEach((v, k) => res.setHeader(k, v));\n\n if (response.body) {\n // Optimize: Use arrayBuffer for direct conversion instead of async iteration\n const buffer = await response.arrayBuffer();\n res.end(Buffer.from(buffer));\n } else {\n res.end();\n }\n });\n\n const fauxServer: Server = {\n stop: () => {\n server.close();\n },\n upgrade(req, options) {\n return false;\n },\n reload(options) {\n return fauxServer as any;\n },\n get port() {\n const addr = server.address();\n if (typeof addr === 'object' && addr !== null) {\n return addr.port;\n }\n return options.port;\n },\n hostname: options.hostname,\n development: options.development,\n pendingRequests: 0,\n requestIP: (req) => null,\n publish: () => 0,\n subscriberCount: () => 0,\n url: new URL(`https://${options.hostname}:${options.port}`),\n // Expose the raw Node.js server for generic socket/websocket support\n nodeServer: server\n } as unknown as Server;\n\n return new Promise((resolve) => {\n server.listen(options.port, options.hostname, () => {\n resolve(fauxServer);\n });\n });\n };\n}\n"],"names":["http","options"],"mappings":";;;;;;;;;;;;;;;;;;;;;AASO,SAAS,mBAAkC;AAC9C,SAAO,OAAO,YAAkC;AAC5C,UAAM,SAASA,gBAAK,aAAa,OAAO,KAAK,QAAQ;AACjD,YAAM,MAAM,IAAI,IAAI,IAAI,KAAM,UAAU,IAAI,QAAQ,IAAI,EAAE;AAC1D,YAAM,UAAU,IAAI,QAAQ,IAAI,YAAY;AAAA,QACxC,QAAQ,IAAI;AAAA,QACZ,SAAS,IAAI;AAAA,QACb,MAAM,CAAC,OAAO,MAAM,EAAE,SAAS,IAAI,MAAO,IAAI,SAAY,IAAI,eAAe;AAAA,UACzE,MAAM,YAAY;AACd,gBAAI,GAAG,QAAQ,CAAA,UAAS,WAAW,QAAQ,KAAK,CAAC;AACjD,gBAAI,GAAG,OAAO,MAAM,WAAW,OAAO;AACtC,gBAAI,GAAG,SAAS,CAAA,QAAO,WAAW,MAAM,GAAG,CAAC;AAAA,UAChD;AAAA,QAAA,CACH;AAAA;AAAA,QAED,QAAQ;AAAA,MAAA,CACJ;AAER,YAAM,WAAW,MAAM,QAAQ,MAAM,SAAS,UAAU;AAExD,UAAI,aAAa,SAAS;AAC1B,eAAS,QAAQ,QAAQ,CAAC,GAAG,MAAM,IAAI,UAAU,GAAG,CAAC,CAAC;AAEtD,UAAI,SAAS,MAAM;AAEf,cAAM,SAAS,MAAM,SAAS,YAAA;AAC9B,YAAI,IAAI,OAAO,KAAK,MAAM,CAAC;AAAA,MAC/B,OAAO;AACH,YAAI,IAAA;AAAA,MACR;AAAA,IACJ,CAAC;AAED,UAAM,aAAqB;AAAA,MACvB,MAAM,MAAM;AACR,eAAO,MAAA;AACP,eAAO,QAAQ,QAAA;AAAA,MACnB;AAAA,MACA,QAAQ,KAAKC,UAAS;AAClB,eAAO;AAAA,MACX;AAAA,MACA,OAAOA,UAAS;AACZ,eAAO;AAAA,MACX;AAAA,MACA,IAAI,OAAO;AACP,cAAM,OAAO,OAAO,QAAA;AACpB,YAAI,OAAO,SAAS,YAAY,SAAS,MAAM;AAC3C,iBAAO,KAAK;AAAA,QAChB;AACA,eAAO,QAAQ;AAAA,MACnB;AAAA,MACA,UAAU,QAAQ;AAAA,MAClB,aAAa,QAAQ;AAAA,MACrB,iBAAiB;AAAA,MACjB,WAAW,CAAC,QAAQ;AAAA,MACpB,SAAS,MAAM;AAAA,MACf,iBAAiB,MAAM;AAAA,MACvB,KAAK,IAAI,IAAI,UAAU,QAAQ,QAAQ,IAAI,QAAQ,IAAI,EAAE;AAAA;AAAA,MAEzD,YAAY;AAAA,IAAA;AAGhB,WAAO,IAAI,QAAQ,CAAC,YAAY;AAC5B,aAAO,OAAO,QAAQ,MAAM,QAAQ,UAAU,MAAM;AAChD,gBAAQ,UAAU;AAAA,MACtB,CAAC;AAAA,IACL,CAAC;AAAA,EACL;AACJ;;"}
|
|
@@ -51,7 +51,9 @@ function createHttpServer() {
|
|
|
51
51
|
requestIP: (req) => null,
|
|
52
52
|
publish: () => 0,
|
|
53
53
|
subscriberCount: () => 0,
|
|
54
|
-
url: new URL(`http://${options.hostname}:${options.port}`)
|
|
54
|
+
url: new URL(`http://${options.hostname}:${options.port}`),
|
|
55
|
+
// Expose the raw Node.js server for generic socket/websocket support (e.g. Socket.IO)
|
|
56
|
+
nodeServer: server
|
|
55
57
|
};
|
|
56
58
|
return new Promise((resolve) => {
|
|
57
59
|
server.listen(options.port, options.hostname, () => {
|
|
@@ -63,4 +65,4 @@ function createHttpServer() {
|
|
|
63
65
|
export {
|
|
64
66
|
createHttpServer
|
|
65
67
|
};
|
|
66
|
-
//# sourceMappingURL=server-
|
|
68
|
+
//# sourceMappingURL=http-server-CCeagTyU.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-server-CCeagTyU.js","sources":["../src/plugins/application/http-server.ts"],"sourcesContent":["import type { Server } from \"bun\";\nimport * as http from \"node:http\";\nimport * as https from \"node:https\";\nimport type { ServerFactory } from \"../../util/types\";\n\n/**\n * Creates a server factory that uses the standard Node.js `http` module.\n * @returns A ServerFactory compatible with Shokupan.\n */\nexport function createHttpServer(): ServerFactory {\n return async (options: any): Promise<Server> => {\n const server = http.createServer(async (req, res) => {\n const url = new URL(req.url!, `http://${req.headers.host}`);\n const request = new Request(url.toString(), {\n method: req.method,\n headers: req.headers as any,\n body: ['GET', 'HEAD'].includes(req.method!) ? undefined : new ReadableStream({\n start(controller) {\n req.on('data', chunk => controller.enqueue(chunk));\n req.on('end', () => controller.close());\n req.on('error', err => controller.error(err));\n }\n }) as any,\n // Required for Node.js undici when sending a body\n duplex: 'half'\n } as any);\n\n const response = await options.fetch(request, fauxServer);\n\n res.statusCode = response.status;\n response.headers.forEach((v, k) => res.setHeader(k, v));\n\n if (response.body) {\n // Optimize: Use arrayBuffer for direct conversion instead of async iteration\n const buffer = await response.arrayBuffer();\n res.end(Buffer.from(buffer));\n } else {\n res.end();\n }\n });\n\n const fauxServer: Server = {\n stop: () => {\n server.close();\n return Promise.resolve(); // Bun.Server stop usually returns void but in type definition it might vary.\n },\n upgrade(req, options) {\n return false;\n },\n reload(options) {\n return fauxServer as any;\n },\n get port() {\n const addr = server.address();\n if (typeof addr === 'object' && addr !== null) {\n return addr.port;\n }\n return options.port;\n },\n hostname: options.hostname,\n development: options.development,\n pendingRequests: 0,\n requestIP: (req) => null,\n publish: () => 0,\n subscriberCount: () => 0,\n url: new URL(`http://${options.hostname}:${options.port}`),\n // Expose the raw Node.js server for generic socket/websocket support (e.g. Socket.IO)\n nodeServer: server\n } as unknown as Server;\n\n return new Promise((resolve) => {\n server.listen(options.port, options.hostname, () => {\n resolve(fauxServer);\n });\n });\n };\n}\n\n/**\n * Creates a server factory that uses the standard Node.js `https` module.\n * @param sslOptions - Node.js HTTPS options (key, cert, etc.)\n * @returns A ServerFactory compatible with Shokupan.\n */\nexport function createHttpsServer(sslOptions: https.ServerOptions): ServerFactory {\n return async (options: any): Promise<Server> => {\n const server = https.createServer(sslOptions, async (req, res) => {\n const url = new URL(req.url!, `https://${req.headers.host}`);\n const request = new Request(url.toString(), {\n method: req.method,\n headers: req.headers as any,\n body: ['GET', 'HEAD'].includes(req.method!) ? undefined : new ReadableStream({\n start(controller) {\n req.on('data', chunk => controller.enqueue(chunk));\n req.on('end', () => controller.close());\n req.on('error', err => controller.error(err));\n }\n }) as any,\n // Required for Node.js undici when sending a body\n duplex: 'half'\n } as any);\n\n const response = await options.fetch(request, fauxServer);\n\n res.statusCode = response.status;\n response.headers.forEach((v, k) => res.setHeader(k, v));\n\n if (response.body) {\n // Optimize: Use arrayBuffer for direct conversion instead of async iteration\n const buffer = await response.arrayBuffer();\n res.end(Buffer.from(buffer));\n } else {\n res.end();\n }\n });\n\n const fauxServer: Server = {\n stop: () => {\n server.close();\n },\n upgrade(req, options) {\n return false;\n },\n reload(options) {\n return fauxServer as any;\n },\n get port() {\n const addr = server.address();\n if (typeof addr === 'object' && addr !== null) {\n return addr.port;\n }\n return options.port;\n },\n hostname: options.hostname,\n development: options.development,\n pendingRequests: 0,\n requestIP: (req) => null,\n publish: () => 0,\n subscriberCount: () => 0,\n url: new URL(`https://${options.hostname}:${options.port}`),\n // Expose the raw Node.js server for generic socket/websocket support\n nodeServer: server\n } as unknown as Server;\n\n return new Promise((resolve) => {\n server.listen(options.port, options.hostname, () => {\n resolve(fauxServer);\n });\n });\n };\n}\n"],"names":["options"],"mappings":";;AASO,SAAS,mBAAkC;AAC9C,SAAO,OAAO,YAAkC;AAC5C,UAAM,SAAS,KAAK,aAAa,OAAO,KAAK,QAAQ;AACjD,YAAM,MAAM,IAAI,IAAI,IAAI,KAAM,UAAU,IAAI,QAAQ,IAAI,EAAE;AAC1D,YAAM,UAAU,IAAI,QAAQ,IAAI,YAAY;AAAA,QACxC,QAAQ,IAAI;AAAA,QACZ,SAAS,IAAI;AAAA,QACb,MAAM,CAAC,OAAO,MAAM,EAAE,SAAS,IAAI,MAAO,IAAI,SAAY,IAAI,eAAe;AAAA,UACzE,MAAM,YAAY;AACd,gBAAI,GAAG,QAAQ,CAAA,UAAS,WAAW,QAAQ,KAAK,CAAC;AACjD,gBAAI,GAAG,OAAO,MAAM,WAAW,OAAO;AACtC,gBAAI,GAAG,SAAS,CAAA,QAAO,WAAW,MAAM,GAAG,CAAC;AAAA,UAChD;AAAA,QAAA,CACH;AAAA;AAAA,QAED,QAAQ;AAAA,MAAA,CACJ;AAER,YAAM,WAAW,MAAM,QAAQ,MAAM,SAAS,UAAU;AAExD,UAAI,aAAa,SAAS;AAC1B,eAAS,QAAQ,QAAQ,CAAC,GAAG,MAAM,IAAI,UAAU,GAAG,CAAC,CAAC;AAEtD,UAAI,SAAS,MAAM;AAEf,cAAM,SAAS,MAAM,SAAS,YAAA;AAC9B,YAAI,IAAI,OAAO,KAAK,MAAM,CAAC;AAAA,MAC/B,OAAO;AACH,YAAI,IAAA;AAAA,MACR;AAAA,IACJ,CAAC;AAED,UAAM,aAAqB;AAAA,MACvB,MAAM,MAAM;AACR,eAAO,MAAA;AACP,eAAO,QAAQ,QAAA;AAAA,MACnB;AAAA,MACA,QAAQ,KAAKA,UAAS;AAClB,eAAO;AAAA,MACX;AAAA,MACA,OAAOA,UAAS;AACZ,eAAO;AAAA,MACX;AAAA,MACA,IAAI,OAAO;AACP,cAAM,OAAO,OAAO,QAAA;AACpB,YAAI,OAAO,SAAS,YAAY,SAAS,MAAM;AAC3C,iBAAO,KAAK;AAAA,QAChB;AACA,eAAO,QAAQ;AAAA,MACnB;AAAA,MACA,UAAU,QAAQ;AAAA,MAClB,aAAa,QAAQ;AAAA,MACrB,iBAAiB;AAAA,MACjB,WAAW,CAAC,QAAQ;AAAA,MACpB,SAAS,MAAM;AAAA,MACf,iBAAiB,MAAM;AAAA,MACvB,KAAK,IAAI,IAAI,UAAU,QAAQ,QAAQ,IAAI,QAAQ,IAAI,EAAE;AAAA;AAAA,MAEzD,YAAY;AAAA,IAAA;AAGhB,WAAO,IAAI,QAAQ,CAAC,YAAY;AAC5B,aAAO,OAAO,QAAQ,MAAM,QAAQ,UAAU,MAAM;AAChD,gBAAQ,UAAU;AAAA,MACtB,CAAC;AAAA,IACL,CAAC;AAAA,EACL;AACJ;"}
|