oipage 1.7.0-alpha.3 → 1.7.0-alpha.5
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/CHANGELOG +160 -149
- package/bin/help.js +1 -0
- package/bin/proxy.js +79 -0
- package/bin/run +128 -116
- package/bin/serve.d.ts +11 -2
- package/bin/serve.js +179 -158
- package/nodejs/animation/index.js +1 -1
- package/nodejs/cmdlog/index.js +1 -1
- package/nodejs/disk/index.js +1 -1
- package/nodejs/format/index.js +1 -1
- package/nodejs/json/index.js +1 -1
- package/nodejs/logform/index.js +1 -1
- package/nodejs/reader/index.js +1 -1
- package/nodejs/remote/index.d.ts +5 -0
- package/nodejs/remote/index.js +29 -39
- package/nodejs/throttle/index.js +1 -1
- package/package.json +4 -2
- package/web/XMLHttpRequest/index.js +1 -1
- package/web/animation/index.js +1 -1
- package/web/format/index.js +1 -1
- package/web/json/index.js +1 -1
- package/web/onReady/index.js +1 -1
- package/web/performChunk/index.js +1 -1
- package/web/reader/index.js +1 -1
- package/web/style/index.js +1 -1
- package/web/throttle/index.js +1 -1
package/bin/serve.js
CHANGED
|
@@ -1,159 +1,180 @@
|
|
|
1
|
-
const { join } = require("path");
|
|
2
|
-
const { existsSync, lstatSync, statSync, createReadStream } = require("fs");
|
|
3
|
-
const { createServer } = require('http');
|
|
4
|
-
const packageValue = require("../package.json");
|
|
5
|
-
const network = require("./tools/network.js");
|
|
6
|
-
const mineTypes = require("./data/mineTypes.json");
|
|
7
|
-
const resolve404 = require("./tools/resolve404.js");
|
|
8
|
-
const resolveImportFactory = require("./tools/resolveImport.js");
|
|
9
|
-
const { doIntercept } = require("./intercept.js");
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
let
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
if (
|
|
89
|
-
let
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
//
|
|
93
|
-
//
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
'
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
1
|
+
const { join } = require("path");
|
|
2
|
+
const { existsSync, lstatSync, statSync, createReadStream } = require("fs");
|
|
3
|
+
const { createServer } = require('http');
|
|
4
|
+
const packageValue = require("../package.json");
|
|
5
|
+
const network = require("./tools/network.js");
|
|
6
|
+
const mineTypes = require("./data/mineTypes.json");
|
|
7
|
+
const resolve404 = require("./tools/resolve404.js");
|
|
8
|
+
const resolveImportFactory = require("./tools/resolveImport.js");
|
|
9
|
+
const { doIntercept } = require("./intercept.js");
|
|
10
|
+
const proxy = require("./proxy.js");
|
|
11
|
+
|
|
12
|
+
const websiteIntercept = require("./website-plugins/intercept/index.js");
|
|
13
|
+
const websiteLoader = require("./website-plugins/loader/index.js");
|
|
14
|
+
|
|
15
|
+
const WebSocketClass = require("./WebSocket/index.js");
|
|
16
|
+
|
|
17
|
+
// 开发服务器
|
|
18
|
+
module.exports = function (config) {
|
|
19
|
+
let startTime = new Date().valueOf();
|
|
20
|
+
|
|
21
|
+
const cache = "cache" in config.devServer ? config.devServer.cache : true;
|
|
22
|
+
const port = +config.devServer.port; // 端口号
|
|
23
|
+
const basePath = (/^\./.test(config.devServer.baseUrl)) ? join(process.cwd(), config.devServer.baseUrl) : config.devServer.baseUrl; // 服务器根路径
|
|
24
|
+
|
|
25
|
+
const name = (config.name || "OIPage") + "-http-server";
|
|
26
|
+
const version = config.version || packageValue.version;
|
|
27
|
+
|
|
28
|
+
const wsHandler = WebSocketClass(port + 1, (config.name || "OIPage") + "-ws-server", version);
|
|
29
|
+
|
|
30
|
+
let Server = createServer(function (request, response) {
|
|
31
|
+
let headers = request.headers;
|
|
32
|
+
let url = decodeURIComponent(request.url);
|
|
33
|
+
|
|
34
|
+
let urlArray = url.split("?");
|
|
35
|
+
url = urlArray[0];
|
|
36
|
+
|
|
37
|
+
// 请求的文件路径
|
|
38
|
+
let filePath;
|
|
39
|
+
|
|
40
|
+
let isWebsite = /^\/_oipage_website_\//.test(url);
|
|
41
|
+
if (isWebsite) {
|
|
42
|
+
filePath = join(__dirname, "./website-htmls/", url.replace(/^\/_oipage_website_\//, ""));
|
|
43
|
+
} else {
|
|
44
|
+
filePath = join(basePath, url == "/" ? "index.html" : url.replace(/^\//, ""));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
let proxyIntercept = proxy({
|
|
48
|
+
name,
|
|
49
|
+
version
|
|
50
|
+
}, config.devServer.proxy || {});
|
|
51
|
+
delete config.devServer.proxy;
|
|
52
|
+
for (let i = 0; i < proxyIntercept.length; i++) {
|
|
53
|
+
config.devServer.intercept.push(proxyIntercept[i]);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// 请求拦截
|
|
57
|
+
if (doIntercept(url.replace(/^\/_oipage_website_/, "").replace(/^\/@modules\//, ""), isWebsite ? websiteIntercept : config.devServer.intercept, request, response, wsHandler)) {
|
|
58
|
+
console.log("<i> \x1b[1m\x1b[32m[" + name + "] intercept: " + url + '\x1b[0m ' + new Date().toLocaleString());
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// 如果存在且是文件
|
|
62
|
+
else if (existsSync(filePath) && !lstatSync(filePath).isDirectory()) {
|
|
63
|
+
|
|
64
|
+
// 判断是否是请求而无需进一步解析
|
|
65
|
+
// 2025年12月5日 于南京
|
|
66
|
+
let isXHR = headers["sec-fetch-dest"] === "empty";
|
|
67
|
+
|
|
68
|
+
let dotName = /\./.test(filePath) ? filePath.match(/\.([^.]+)$/)[1] : "";
|
|
69
|
+
let fileType = mineTypes[dotName]; // 文件类型
|
|
70
|
+
let fileInfo = statSync(filePath);
|
|
71
|
+
|
|
72
|
+
let fileModifiedTime = new Date(fileInfo.mtime).toGMTString();
|
|
73
|
+
|
|
74
|
+
let responseHeader = {
|
|
75
|
+
'Content-Type': (fileType || "text/plain") + ";charset=utf-8",
|
|
76
|
+
'Access-Control-Allow-Origin': '*',
|
|
77
|
+
'Server': 'Powered by ' + name + '@' + version,
|
|
78
|
+
'Cache-Control': 'no-cache',
|
|
79
|
+
// 'Content-Length': fileInfo.size, // 会导致拦截修改的文本内容不对
|
|
80
|
+
|
|
81
|
+
// 与if-modified-since配合使用,做缓存验证
|
|
82
|
+
'Last-Modified': fileModifiedTime,
|
|
83
|
+
|
|
84
|
+
// 与if-none-match配合使用,做缓存验证
|
|
85
|
+
// 'ETag': basePath + "-" + new Date(fileInfo.mtime).toString()
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
if (cache && headers["if-modified-since"]) {
|
|
89
|
+
let ifModifiedSince = new Date(headers["if-modified-since"]).valueOf()
|
|
90
|
+
let lastModified = new Date(fileModifiedTime).valueOf()
|
|
91
|
+
|
|
92
|
+
// 注意这里不能使用<=,否则
|
|
93
|
+
// 1、会出现时区问题
|
|
94
|
+
// 2、作为开发服务器,可能同一个url地址对应的文件不同,被误判为未修改
|
|
95
|
+
// 2025年12月29日 于南京
|
|
96
|
+
// if (lastModified <= ifModifiedSince) {}
|
|
97
|
+
if (lastModified === ifModifiedSince) {
|
|
98
|
+
response.writeHead('304', responseHeader);
|
|
99
|
+
response.end();
|
|
100
|
+
console.log("<i> \x1b[1m\x1b[32m[" + name + "] Cache File: " + url + "\x1b[0m " + new Date().toLocaleString() + "\x1b[33m\x1b[1m 304" + (isXHR ? " 请求" : "") + "\x1b[0m");
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
let sendType = "";
|
|
106
|
+
let entry = headers.accept !== "*/*";
|
|
107
|
+
|
|
108
|
+
// 如果文件小于10M,认为不大,直接读取
|
|
109
|
+
if (fileInfo.size < 10 * 1024 * 1024) {
|
|
110
|
+
let { source, resolveImport } = resolveImportFactory(basePath, filePath, entry, isWebsite ? websiteIntercept : config.devServer.intercept, urlArray[1] === "download", isWebsite)
|
|
111
|
+
|
|
112
|
+
// 只处理非下载文件
|
|
113
|
+
// 过大的也不进行处理
|
|
114
|
+
// (对website无效)
|
|
115
|
+
if (urlArray[1] !== "download") {
|
|
116
|
+
let loaders = isWebsite ? websiteLoader : config.module;
|
|
117
|
+
|
|
118
|
+
for (let i = 0; i < loaders.rules.length; i++) {
|
|
119
|
+
if (loaders.rules[i].test.test(filePath)) {
|
|
120
|
+
source = loaders.rules[i].use.call({
|
|
121
|
+
root: basePath, // 服务器根路径
|
|
122
|
+
path: filePath.replace(basePath, ""), // 文件相对路径
|
|
123
|
+
entry, // 是否是浏览器地址栏直接访问
|
|
124
|
+
setFileType(_fileType) { // 设置文件类型
|
|
125
|
+
fileType = _fileType;
|
|
126
|
+
responseHeader['Content-Type'] = _fileType + ";charset=utf-8";
|
|
127
|
+
}
|
|
128
|
+
}, source);
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
sendType = "Read";
|
|
136
|
+
response.writeHead('200', responseHeader);
|
|
137
|
+
response.write(isXHR ? source : resolveImport(source, fileType !== "application/javascript"));
|
|
138
|
+
response.end();
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// 对于大文件,使用流读取
|
|
142
|
+
else {
|
|
143
|
+
sendType = "Stream";
|
|
144
|
+
|
|
145
|
+
responseHeader['Content-Length'] = fileInfo.size
|
|
146
|
+
|
|
147
|
+
response.writeHead('200', responseHeader);
|
|
148
|
+
createReadStream(filePath).pipe(response);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
console.log("<i> \x1b[1m\x1b[32m[" + name + "] " + sendType + " File: " + url + '\x1b[0m ' + new Date().toLocaleString() + "\x1b[33m\x1b[1m" + (isXHR ? " 请求" : "") + "\x1b[0m");
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// 否则就是404
|
|
155
|
+
else {
|
|
156
|
+
response.writeHead(404, {
|
|
157
|
+
'Content-Type': "text/html;charset=utf-8",
|
|
158
|
+
'Access-Control-Allow-Origin': '*',
|
|
159
|
+
'Server': 'Powered by ' + name + '@' + version
|
|
160
|
+
});
|
|
161
|
+
response.write(resolve404(filePath, url));
|
|
162
|
+
response.end();
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
Server.listen(port);
|
|
168
|
+
|
|
169
|
+
// 获取网络信息
|
|
170
|
+
let networkValue = network();
|
|
171
|
+
|
|
172
|
+
// 打印成功提示
|
|
173
|
+
console.log('<i> \x1b[1m\x1b[32m[' + name + '] Project is running at:\x1b[0m');
|
|
174
|
+
console.log('<i> \x1b[1m\x1b[32m[' + name + '] Loopback: \x1b[36mhttp://localhost:' + port + '/\x1b[0m');
|
|
175
|
+
for (let ipv4Item of networkValue.IPv4) console.log('<i> \x1b[1m\x1b[32m[' + name + '] On Your Network (IPv4):\x1b[36m http://' + ipv4Item.address + ':' + port + '/\x1b[0m');
|
|
176
|
+
for (let ipv6Item of networkValue.IPv6) console.log('<i> \x1b[1m\x1b[32m[' + name + '] On Your Network (IPv6): \x1b[36mhttp://[' + ipv6Item.address + ']:' + port + '/\x1b[0m');
|
|
177
|
+
console.log('<i> \x1b[1m\x1b[32m[' + name + '] Content not from ' + (config.name || "OIPage") + ' is served from \x1b[36m"' + basePath + '" \x1b[0mdirectory');
|
|
178
|
+
if (!cache) console.log('<i> \x1b[1m\x1b[32m[' + name + '] Cancel 304 Cache!\x1b[0m');
|
|
179
|
+
console.log('\n' + (config.name || "OIPage") + ' ' + version + ' compiled \x1b[1m\x1b[32msuccessfully\x1b[0m in ' + (new Date().valueOf() - startTime) + ' ms\n')
|
|
159
180
|
};
|
package/nodejs/cmdlog/index.js
CHANGED
package/nodejs/disk/index.js
CHANGED
package/nodejs/format/index.js
CHANGED
package/nodejs/json/index.js
CHANGED
package/nodejs/logform/index.js
CHANGED
package/nodejs/reader/index.js
CHANGED
package/nodejs/remote/index.d.ts
CHANGED
package/nodejs/remote/index.js
CHANGED
|
@@ -1,47 +1,13 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* remote of OIPage v1.7.0-alpha.
|
|
2
|
+
* remote of OIPage v1.7.0-alpha.5
|
|
3
3
|
* git+https://github.com/oi-contrib/OIPage.git
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
const https = require('https');
|
|
7
7
|
const http = require('http');
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
res.setEncoding('utf8');
|
|
11
|
-
|
|
12
|
-
let data = "";
|
|
13
|
-
res.on('data', (chunk) => {
|
|
14
|
-
data += chunk;
|
|
15
|
-
});
|
|
16
|
-
res.on('end', () => {
|
|
17
|
-
resolve({
|
|
18
|
-
data: data.toString('utf8'),
|
|
19
|
-
headers: res.headers
|
|
20
|
-
});
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// GET请求
|
|
25
|
-
function get(url, headers = {}) {
|
|
26
|
-
return new Promise((resolve, reject) => {
|
|
27
|
-
|
|
28
|
-
let handler = /^https/.test(url) ? https : http;
|
|
29
|
-
|
|
30
|
-
// https://nodejs.org/download/release/v16.8.0/docs/api/http.html#http_http_get_options_callback
|
|
31
|
-
handler.get(url, {
|
|
32
|
-
headers
|
|
33
|
-
}, res => {
|
|
34
|
-
doResolve(res, resolve)
|
|
35
|
-
}).on('error', (e) => {
|
|
36
|
-
reject(e);
|
|
37
|
-
});
|
|
38
|
-
});
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
// POST请求
|
|
42
|
-
function post(url, headers = {}, params = {}) {
|
|
9
|
+
function remote(method, url, headers, param) {
|
|
43
10
|
return new Promise((resolve, reject) => {
|
|
44
|
-
|
|
45
11
|
let handler = /^https/.test(url) ? https : http;
|
|
46
12
|
|
|
47
13
|
let execArray = /https*:\/\/([^\/]+)(.+)?/.exec(url);
|
|
@@ -52,19 +18,43 @@ function post(url, headers = {}, params = {}) {
|
|
|
52
18
|
hostname: hostport[0],
|
|
53
19
|
port: hostport[1] || 80,
|
|
54
20
|
path: execArray[2] || "/",
|
|
55
|
-
method
|
|
21
|
+
method,
|
|
56
22
|
headers
|
|
57
23
|
}, (res) => {
|
|
58
|
-
|
|
24
|
+
res.setEncoding("utf8");
|
|
25
|
+
|
|
26
|
+
let data = "";
|
|
27
|
+
res.on('data', (chunk) => {
|
|
28
|
+
data += chunk;
|
|
29
|
+
});
|
|
30
|
+
res.on('end', () => {
|
|
31
|
+
|
|
32
|
+
resolve({
|
|
33
|
+
status: res.statusCode,
|
|
34
|
+
data: data.toString('utf8'),
|
|
35
|
+
headers: res.headers
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
59
39
|
});
|
|
60
40
|
|
|
61
|
-
req.write(
|
|
41
|
+
if (param) req.write(param);
|
|
62
42
|
|
|
63
43
|
req.on('error', (e) => {
|
|
64
44
|
reject(e);
|
|
65
45
|
});
|
|
66
46
|
req.end();
|
|
67
47
|
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// GET请求
|
|
51
|
+
function get(url, headers = {}) {
|
|
52
|
+
return remote("GET", url, headers)
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// POST请求
|
|
56
|
+
function post(url, headers = {}, params = {}) {
|
|
57
|
+
return remote("POST", url, headers, JSON.stringify(params));
|
|
68
58
|
};
|
|
69
59
|
|
|
70
60
|
exports.get = get;
|
package/nodejs/throttle/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oipage",
|
|
3
|
-
"version": "1.7.0-alpha.
|
|
3
|
+
"version": "1.7.0-alpha.5",
|
|
4
4
|
"description": "前端网页或应用快速开发助手,包括开发服务器、辅助命令、实用API等",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"typings": "./types/index.d.ts",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"dev": "node ./bin/run run \"node ./build/index.js watch\" \"
|
|
8
|
+
"dev": "node ./bin/run run \"node ./build/index.js watch\" \"npm run serve\"",
|
|
9
9
|
"build": "node ./build/index.js",
|
|
10
|
+
"serve": "node ./bin/run serve --config ./oipage.config.js",
|
|
11
|
+
"dev:issue10": "node ./bin/run serve --proxy /docs http://127.0.0.1:20000 --baseUrl ./test",
|
|
10
12
|
"bug:issue5": "node ./bin/run run \"node ./bin/run serve\"",
|
|
11
13
|
"bug:issue4": "node ./bin/run run \"node ./test/logform/index.spec.js\""
|
|
12
14
|
},
|
package/web/animation/index.js
CHANGED
package/web/format/index.js
CHANGED
package/web/json/index.js
CHANGED
package/web/onReady/index.js
CHANGED
package/web/reader/index.js
CHANGED
package/web/style/index.js
CHANGED
package/web/throttle/index.js
CHANGED