k99 0.6.1 → 0.7.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/index.cjs +301 -181
- package/index.d.ts +76 -76
- package/index.js +301 -181
- package/index.min.js +2 -2
- package/index.min.mjs +2 -2
- package/index.mjs +301 -182
- package/package.json +2 -3
- package/services.cjs +5 -3
- package/services.d.ts +7 -6
- package/services.js +5 -3
- package/services.min.js +1 -1
- package/services.min.mjs +1 -1
- package/services.mjs +5 -3
- package/node/index.cjs +0 -149
- package/node/index.d.cts +0 -49
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "k99",
|
|
3
3
|
"description": "前后端均可用的 web 服务器",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.7.0",
|
|
5
5
|
"dependencies": {},
|
|
6
6
|
"keywords": [
|
|
7
7
|
"k99",
|
|
@@ -35,7 +35,6 @@
|
|
|
35
35
|
"module": "./services.mjs",
|
|
36
36
|
"unpkg": "./services.min.js",
|
|
37
37
|
"jsdelivr": "./services.min.js"
|
|
38
|
-
}
|
|
39
|
-
"./node": "./node/index.cjs"
|
|
38
|
+
}
|
|
40
39
|
}
|
|
41
40
|
}
|
package/services.cjs
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* k99 v0.
|
|
2
|
+
* k99 v0.7.0
|
|
3
3
|
* (c) 2019-2025 猛火Fierflame
|
|
4
4
|
* @license MIT
|
|
5
5
|
*/
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
8
|
+
/** @import { Service } from 'k99' */
|
|
8
9
|
/**
|
|
9
10
|
*
|
|
10
11
|
* @param {string} s
|
|
@@ -52,7 +53,7 @@ async function parse(request) {
|
|
|
52
53
|
} catch { }
|
|
53
54
|
return null;
|
|
54
55
|
}
|
|
55
|
-
/** @type {
|
|
56
|
+
/** @type {Service<Promise<any> | null>} */
|
|
56
57
|
const formBodyService = function (ctx) {
|
|
57
58
|
const [mime, charset] = ctx.requestType.replace(/\s/g, '').split(';');
|
|
58
59
|
if (mime !== 'application/x-www-form-urlencoded') { return () => null; }
|
|
@@ -63,7 +64,8 @@ const formBodyService = function (ctx) {
|
|
|
63
64
|
return () => result;
|
|
64
65
|
};
|
|
65
66
|
|
|
66
|
-
/** @
|
|
67
|
+
/** @import { Service } from 'k99' */
|
|
68
|
+
/** @type {Service<Promise<any> | null>} */
|
|
67
69
|
const jsonBodyService = function (ctx) {
|
|
68
70
|
const [mime, charset] = ctx.requestType.replace(/\s/g, '').split(';');
|
|
69
71
|
if (mime !== 'application/json' && mime !== 'text/json') { return () => null; }
|
package/services.d.ts
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* k99 v0.
|
|
2
|
+
* k99 v0.7.0
|
|
3
3
|
* (c) 2019-2025 猛火Fierflame
|
|
4
4
|
* @license MIT
|
|
5
5
|
*/
|
|
6
|
-
import
|
|
6
|
+
import { Service } from 'k99';
|
|
7
7
|
|
|
8
|
-
/** @type {
|
|
9
|
-
declare const formBodyService:
|
|
8
|
+
/** @type {Service<Promise<any> | null>} */
|
|
9
|
+
declare const formBodyService: Service<Promise<any> | null>;
|
|
10
10
|
|
|
11
|
-
/** @
|
|
12
|
-
|
|
11
|
+
/** @import { Service } from 'k99' */
|
|
12
|
+
/** @type {Service<Promise<any> | null>} */
|
|
13
|
+
declare const jsonBodyService: Service<Promise<any> | null>;
|
|
13
14
|
|
|
14
15
|
export { formBodyService, jsonBodyService };
|
package/services.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* k99 v0.
|
|
2
|
+
* k99 v0.7.0
|
|
3
3
|
* (c) 2019-2025 猛火Fierflame
|
|
4
4
|
* @license MIT
|
|
5
5
|
*/
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.k99Services = {}));
|
|
10
10
|
})(this, (function (exports) { 'use strict';
|
|
11
11
|
|
|
12
|
+
/** @import { Service } from 'k99' */
|
|
12
13
|
/**
|
|
13
14
|
*
|
|
14
15
|
* @param {string} s
|
|
@@ -56,7 +57,7 @@
|
|
|
56
57
|
} catch { }
|
|
57
58
|
return null;
|
|
58
59
|
}
|
|
59
|
-
/** @type {
|
|
60
|
+
/** @type {Service<Promise<any> | null>} */
|
|
60
61
|
const formBodyService = function (ctx) {
|
|
61
62
|
const [mime, charset] = ctx.requestType.replace(/\s/g, '').split(';');
|
|
62
63
|
if (mime !== 'application/x-www-form-urlencoded') { return () => null; }
|
|
@@ -67,7 +68,8 @@
|
|
|
67
68
|
return () => result;
|
|
68
69
|
};
|
|
69
70
|
|
|
70
|
-
/** @
|
|
71
|
+
/** @import { Service } from 'k99' */
|
|
72
|
+
/** @type {Service<Promise<any> | null>} */
|
|
71
73
|
const jsonBodyService = function (ctx) {
|
|
72
74
|
const [mime, charset] = ctx.requestType.replace(/\s/g, '').split(';');
|
|
73
75
|
if (mime !== 'application/json' && mime !== 'text/json') { return () => null; }
|
package/services.min.js
CHANGED
package/services.min.mjs
CHANGED
package/services.mjs
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* k99 v0.
|
|
2
|
+
* k99 v0.7.0
|
|
3
3
|
* (c) 2019-2025 猛火Fierflame
|
|
4
4
|
* @license MIT
|
|
5
5
|
*/
|
|
6
|
+
/** @import { Service } from 'k99' */
|
|
6
7
|
/**
|
|
7
8
|
*
|
|
8
9
|
* @param {string} s
|
|
@@ -50,7 +51,7 @@ async function parse(request) {
|
|
|
50
51
|
} catch { }
|
|
51
52
|
return null;
|
|
52
53
|
}
|
|
53
|
-
/** @type {
|
|
54
|
+
/** @type {Service<Promise<any> | null>} */
|
|
54
55
|
const formBodyService = function (ctx) {
|
|
55
56
|
const [mime, charset] = ctx.requestType.replace(/\s/g, '').split(';');
|
|
56
57
|
if (mime !== 'application/x-www-form-urlencoded') { return () => null; }
|
|
@@ -61,7 +62,8 @@ const formBodyService = function (ctx) {
|
|
|
61
62
|
return () => result;
|
|
62
63
|
};
|
|
63
64
|
|
|
64
|
-
/** @
|
|
65
|
+
/** @import { Service } from 'k99' */
|
|
66
|
+
/** @type {Service<Promise<any> | null>} */
|
|
65
67
|
const jsonBodyService = function (ctx) {
|
|
66
68
|
const [mime, charset] = ctx.requestType.replace(/\s/g, '').split(';');
|
|
67
69
|
if (mime !== 'application/json' && mime !== 'text/json') { return () => null; }
|
package/node/index.cjs
DELETED
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* k99 v0.6.1
|
|
3
|
-
* (c) 2019-2025 猛火Fierflame
|
|
4
|
-
* @license MIT
|
|
5
|
-
*/
|
|
6
|
-
'use strict';
|
|
7
|
-
|
|
8
|
-
var node_stream = require('node:stream');
|
|
9
|
-
var node_http2 = require('node:http2');
|
|
10
|
-
|
|
11
|
-
/** @import { IncomingMessage, ServerResponse } from 'node:http' */
|
|
12
|
-
/** @import { Http2ServerRequest, Http2ServerResponse } from 'node:http2' */
|
|
13
|
-
/**
|
|
14
|
-
*
|
|
15
|
-
* @param {IncomingMessage | Http2ServerRequest} req
|
|
16
|
-
* @param {ServerResponse | Http2ServerResponse} [res]
|
|
17
|
-
* @returns {AbortSignal}
|
|
18
|
-
*/
|
|
19
|
-
function createAbortSignal(req, res) {
|
|
20
|
-
const ac = new AbortController();
|
|
21
|
-
/**
|
|
22
|
-
*
|
|
23
|
-
* @param {Error} [err]
|
|
24
|
-
* @returns
|
|
25
|
-
*/
|
|
26
|
-
const end = (err) => {
|
|
27
|
-
res?.off('close', end);
|
|
28
|
-
req.off('error', end);
|
|
29
|
-
ac.abort(err);
|
|
30
|
-
};
|
|
31
|
-
res?.on('close', end);
|
|
32
|
-
req.on('error', end);
|
|
33
|
-
|
|
34
|
-
return ac.signal;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
*
|
|
39
|
-
* @param {IncomingMessage | Http2ServerRequest} req
|
|
40
|
-
* @param {AbortSignal | ServerResponse | Http2ServerResponse} [signalOrRes]
|
|
41
|
-
* @returns {Request}
|
|
42
|
-
*/
|
|
43
|
-
function toWebRequest(req, signalOrRes) {
|
|
44
|
-
const signal = signalOrRes instanceof AbortSignal
|
|
45
|
-
? signalOrRes
|
|
46
|
-
: createAbortSignal(req, signalOrRes);
|
|
47
|
-
const host = req.headers['host'] || '127.0.0.1';
|
|
48
|
-
const url = new URL(req.url || '/', `http://${ host }`);
|
|
49
|
-
const method = (req.method || 'GET').toUpperCase();
|
|
50
|
-
const headers = new Headers();
|
|
51
|
-
for (const [k, v] of Object.entries(req.headers)) {
|
|
52
|
-
for (const it of [v].flat()) {
|
|
53
|
-
headers.append(k.toLowerCase(), String(it));
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
const body = ['GET', 'OPTIONS'].includes(method) ? null : /** @type {any} */(node_stream.Readable.toWeb(req));
|
|
57
|
-
// @ts-ignore
|
|
58
|
-
return new Request(url, { method, headers, signal, body, duplex: 'half'});
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/** @import { ServerResponse } from 'node:http' */
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
*
|
|
65
|
-
* @param {ServerResponse | Http2ServerResponse} res
|
|
66
|
-
* @param {Response} response
|
|
67
|
-
* @param {(e: any) => void} onError
|
|
68
|
-
* @returns
|
|
69
|
-
*/
|
|
70
|
-
async function linkResponse(res, response, onError) {
|
|
71
|
-
res.statusCode = response.status;
|
|
72
|
-
const {headers} = response;
|
|
73
|
-
for (const [k, v] of headers) {
|
|
74
|
-
res.setHeader(k, v);
|
|
75
|
-
}
|
|
76
|
-
const cookies = headers.getSetCookie();
|
|
77
|
-
if (cookies.length) {
|
|
78
|
-
res.setHeader('set-cookie', cookies);
|
|
79
|
-
}
|
|
80
|
-
const {body} = response;
|
|
81
|
-
if (!body) {
|
|
82
|
-
res.end();
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
const readable = node_stream.Readable.fromWeb(/** @type {any} */(body));
|
|
86
|
-
readable.on('error', onError);
|
|
87
|
-
readable.pipe(res instanceof node_http2.Http2ServerResponse ? res.stream : res);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/** @import { IncomingMessage, ServerResponse } from 'node:http' */
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
*
|
|
94
|
-
* @param {any} e
|
|
95
|
-
*/
|
|
96
|
-
function echoError(e) {
|
|
97
|
-
console.error(e);
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* @template {IncomingMessage | Http2ServerRequest} TReq
|
|
101
|
-
* @template {ServerResponse | Http2ServerResponse} TRes
|
|
102
|
-
* @typedef {object} HttpCallbackOptions
|
|
103
|
-
* @property {(req: TReq, res: TRes, next?: () => void) => any} [notFound]
|
|
104
|
-
* @property {(e: any) => void} [onError]
|
|
105
|
-
* @property {boolean} [errorInResponse]
|
|
106
|
-
*/
|
|
107
|
-
/**
|
|
108
|
-
*
|
|
109
|
-
* @template {IncomingMessage | Http2ServerRequest} TReq
|
|
110
|
-
* @template {ServerResponse | Http2ServerResponse} TRes
|
|
111
|
-
* @param {(request: Request) => Promise<Response | null>} run
|
|
112
|
-
* @param {HttpCallbackOptions<TReq, TRes>} [options]
|
|
113
|
-
* @returns {(req: TReq, res: TRes, next?: () => void) => any}
|
|
114
|
-
*/
|
|
115
|
-
function createHttpCallback(run, {
|
|
116
|
-
notFound,
|
|
117
|
-
onError = echoError,
|
|
118
|
-
errorInResponse,
|
|
119
|
-
} = {}) {
|
|
120
|
-
return function httpCallback(req, res, next) {
|
|
121
|
-
return run(toWebRequest(req, res)).then(r => {
|
|
122
|
-
if (r) { return linkResponse(res, r, onError); }
|
|
123
|
-
if (notFound) { return notFound(req, res, next); }
|
|
124
|
-
if (next) { return next(); }
|
|
125
|
-
res.statusCode = 404;
|
|
126
|
-
res.end();
|
|
127
|
-
}, e => {
|
|
128
|
-
res.statusCode = 500;
|
|
129
|
-
onError(e);
|
|
130
|
-
if (!errorInResponse) {
|
|
131
|
-
res.end();
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
|
-
/** @type {import('node:stream').Writable} */
|
|
135
|
-
const stream =
|
|
136
|
-
res instanceof node_http2.Http2ServerResponse ? res.stream : res;
|
|
137
|
-
if (e instanceof Error) {
|
|
138
|
-
stream.write(`${ e.stack || '' }`);
|
|
139
|
-
} else {
|
|
140
|
-
stream.write(String(e));
|
|
141
|
-
}
|
|
142
|
-
res.end();
|
|
143
|
-
});
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
exports.createHttpCallback = createHttpCallback;
|
|
148
|
-
exports.linkResponse = linkResponse;
|
|
149
|
-
exports.toWebRequest = toWebRequest;
|
package/node/index.d.cts
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* k99 v0.6.1
|
|
3
|
-
* (c) 2019-2025 猛火Fierflame
|
|
4
|
-
* @license MIT
|
|
5
|
-
*/
|
|
6
|
-
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
7
|
-
import { Http2ServerRequest, Http2ServerResponse } from 'node:http2';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
*
|
|
11
|
-
* @param {IncomingMessage | Http2ServerRequest} req
|
|
12
|
-
* @param {AbortSignal | ServerResponse | Http2ServerResponse} [signalOrRes]
|
|
13
|
-
* @returns {Request}
|
|
14
|
-
*/
|
|
15
|
-
declare function toWebRequest(req: IncomingMessage | Http2ServerRequest, signalOrRes?: AbortSignal | ServerResponse | Http2ServerResponse): Request;
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
*
|
|
19
|
-
* @param {ServerResponse | Http2ServerResponse} res
|
|
20
|
-
* @param {Response} response
|
|
21
|
-
* @param {(e: any) => void} onError
|
|
22
|
-
* @returns
|
|
23
|
-
*/
|
|
24
|
-
declare function linkResponse(res: ServerResponse | Http2ServerResponse, response: Response, onError: (e: any) => void): Promise<void>;
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* @template {IncomingMessage | Http2ServerRequest} TReq
|
|
28
|
-
* @template {ServerResponse | Http2ServerResponse} TRes
|
|
29
|
-
* @typedef {object} HttpCallbackOptions
|
|
30
|
-
* @property {(req: TReq, res: TRes, next?: () => void) => any} [notFound]
|
|
31
|
-
* @property {(e: any) => void} [onError]
|
|
32
|
-
* @property {boolean} [errorInResponse]
|
|
33
|
-
*/
|
|
34
|
-
/**
|
|
35
|
-
*
|
|
36
|
-
* @template {IncomingMessage | Http2ServerRequest} TReq
|
|
37
|
-
* @template {ServerResponse | Http2ServerResponse} TRes
|
|
38
|
-
* @param {(request: Request) => Promise<Response | null>} run
|
|
39
|
-
* @param {HttpCallbackOptions<TReq, TRes>} [options]
|
|
40
|
-
* @returns {(req: TReq, res: TRes, next?: () => void) => any}
|
|
41
|
-
*/
|
|
42
|
-
declare function createHttpCallback<TReq extends IncomingMessage | Http2ServerRequest, TRes extends ServerResponse | Http2ServerResponse>(run: (request: Request) => Promise<Response | null>, { notFound, onError, errorInResponse, }?: HttpCallbackOptions<TReq, TRes>): (req: TReq, res: TRes, next?: () => void) => any;
|
|
43
|
-
type HttpCallbackOptions<TReq extends IncomingMessage | Http2ServerRequest, TRes extends ServerResponse | Http2ServerResponse> = {
|
|
44
|
-
notFound?: ((req: TReq, res: TRes, next?: () => void) => any) | undefined;
|
|
45
|
-
onError?: ((e: any) => void) | undefined;
|
|
46
|
-
errorInResponse?: boolean | undefined;
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
export { createHttpCallback, linkResponse, toWebRequest };
|