oipage 1.7.0-alpha.4 → 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 +8 -1
- 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/CHANGELOG
CHANGED
|
@@ -1,149 +1,160 @@
|
|
|
1
|
-
v1.0.0:
|
|
2
|
-
date:2025-02-13
|
|
3
|
-
changes:
|
|
4
|
-
- 原v0.x的功能将独立一个分支继续维护:https://github.com/oi-contrib/OIPage/blob/v0.x/CHANGELOG
|
|
5
|
-
(v0.x保持对零碎方法这种形式的支持和维护,此版本开始将作为一个框架或一个系统的工具箱以提供更高效的使用方式,这是一次彻底的非兼容改造)
|
|
6
|
-
- 初始化版本(v1.x)
|
|
7
|
-
1、API功能(浏览器)
|
|
8
|
-
* animation 动画
|
|
9
|
-
* getStyle 获取节点样式
|
|
10
|
-
* setStyle 设置节点样式
|
|
11
|
-
* onReady 加载完毕执行
|
|
12
|
-
* throttle 节流函数
|
|
13
|
-
2、API功能(Node.js)
|
|
14
|
-
* animation 动画
|
|
15
|
-
* deeplog 进度打印
|
|
16
|
-
* linglog 单行打印
|
|
17
|
-
* throttle 节流函数
|
|
18
|
-
3、命令(oipage-cli)
|
|
19
|
-
* serve 开发服务器
|
|
20
|
-
v1.1.0:
|
|
21
|
-
date:2025-02-18
|
|
22
|
-
changes:
|
|
23
|
-
- 修复bug
|
|
24
|
-
1、通过路径类型判断以修复开发服务器无法设置绝对路径问题
|
|
25
|
-
- 优化改造
|
|
26
|
-
1、使用流读取以使开发服务器支持大文件下载
|
|
27
|
-
(同时添加下载进度可查)
|
|
28
|
-
- 新增功能
|
|
29
|
-
1、API功能(Node.js)
|
|
30
|
-
* disk 磁盘相关操作
|
|
31
|
-
(包括:deleteDisk、copyDisk)
|
|
32
|
-
* logform 表单输入
|
|
33
|
-
2、命令(oipage-cli)
|
|
34
|
-
* dist 磁盘操作
|
|
35
|
-
* run 运行多命令
|
|
36
|
-
v1.2.0:
|
|
37
|
-
date:2025-02-25
|
|
38
|
-
changes:
|
|
39
|
-
- 优化改造
|
|
40
|
-
1、优化npm包目录结构等
|
|
41
|
-
- 新增功能
|
|
42
|
-
1、开发服务器
|
|
43
|
-
* 添加配置文件
|
|
44
|
-
(oipage-cli serve --config ./oipage.config.js)
|
|
45
|
-
* 新增对node_modules包引入支持
|
|
46
|
-
v1.2.1:
|
|
47
|
-
date:2025-03-06
|
|
48
|
-
changes:
|
|
49
|
-
- 修复bug
|
|
50
|
-
1、开发服务器
|
|
51
|
-
* 修复路径不存在时未正确同步修改浏览器地址问题
|
|
52
|
-
v1.3.0:(已废弃,请用1.3.1代替)
|
|
53
|
-
date:2025-05-18
|
|
54
|
-
changes:
|
|
55
|
-
- 修复bug
|
|
56
|
-
1、开发服务器
|
|
57
|
-
* 修复服务器根路径判断错误导致node_modules包查找错误问题
|
|
58
|
-
2、修复animation动画types类型定义错误问题
|
|
59
|
-
- 新增功能
|
|
60
|
-
1、API功能(浏览器)
|
|
61
|
-
* reader 文本分析读取器
|
|
62
|
-
* performChunk 空闲执行分片函数
|
|
63
|
-
* strToJson JSON字符串解析
|
|
64
|
-
2、API功能(Node.js)
|
|
65
|
-
* reader 文本分析读取器
|
|
66
|
-
* strToJson JSON字符串解析
|
|
67
|
-
3、开发服务器
|
|
68
|
-
* 新增 devServer.intercept 请求拦截
|
|
69
|
-
* 新增对 if-modified-since和last-modified 之304协商缓存的支持
|
|
70
|
-
v1.3.1:
|
|
71
|
-
date:2025-05-23
|
|
72
|
-
changes:
|
|
73
|
-
- 修复bug
|
|
74
|
-
1、开发服务器
|
|
75
|
-
* 由于是否入口判断导致import语句未正确解析
|
|
76
|
-
* 修复 Last-Modified 格式不规范导致的运行报错
|
|
77
|
-
v1.4.0:
|
|
78
|
-
date:2025-09-02
|
|
79
|
-
changes:
|
|
80
|
-
- 修复bug
|
|
81
|
-
1、修复logform运行报错
|
|
82
|
-
- 新增功能
|
|
83
|
-
1、API功能(浏览器)
|
|
84
|
-
* dateFormat 日期格式化
|
|
85
|
-
* numberFormat 数字格式化
|
|
86
|
-
* XHRIntercept XHR拦截
|
|
87
|
-
2、API功能(Node.js)
|
|
88
|
-
* dateFormat 日期格式化
|
|
89
|
-
* numberFormat 数字格式化
|
|
90
|
-
3、开发服务器
|
|
91
|
-
* 新增 serve.d.ts 以支持作为API在TypeScript中环境
|
|
92
|
-
(仅对内使用,未正式对外暴露API相关文档)
|
|
93
|
-
* 添加304是否启用开关
|
|
94
|
-
* 应用市场(website内置网站)
|
|
95
|
-
v1.4.1:
|
|
96
|
-
date:2025-09-02
|
|
97
|
-
changes:
|
|
98
|
-
- 修复bug
|
|
99
|
-
1、修复开发服务器大文件丢失文件大小问题
|
|
100
|
-
v1.5.0:
|
|
101
|
-
date:2025-11-13
|
|
102
|
-
changes:
|
|
103
|
-
- 修复bug
|
|
104
|
-
1、修复404网站在手机浏览器显示高问题
|
|
105
|
-
2、服务器响应类型由 Content-type 改为 Content-Type
|
|
106
|
-
3、修复dateFormat第二个参数无法缺省报错
|
|
107
|
-
4、修复numberFormat不支持负数问题
|
|
108
|
-
- 优化改造
|
|
109
|
-
1、优化run命令日志打印
|
|
110
|
-
- 新增功能
|
|
111
|
-
1、开发服务器 / 应用市场
|
|
112
|
-
* 群聊天
|
|
113
|
-
* 图片编辑器
|
|
114
|
-
* 图片转PDF
|
|
115
|
-
2、API功能(Node.js)
|
|
116
|
-
* disk 磁盘相关操作
|
|
117
|
-
(包括:moveDisk、listDisk)
|
|
118
|
-
v1.6.0:
|
|
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
|
-
|
|
1
|
+
v1.0.0:
|
|
2
|
+
date:2025-02-13
|
|
3
|
+
changes:
|
|
4
|
+
- 原v0.x的功能将独立一个分支继续维护:https://github.com/oi-contrib/OIPage/blob/v0.x/CHANGELOG
|
|
5
|
+
(v0.x保持对零碎方法这种形式的支持和维护,此版本开始将作为一个框架或一个系统的工具箱以提供更高效的使用方式,这是一次彻底的非兼容改造)
|
|
6
|
+
- 初始化版本(v1.x)
|
|
7
|
+
1、API功能(浏览器)
|
|
8
|
+
* animation 动画
|
|
9
|
+
* getStyle 获取节点样式
|
|
10
|
+
* setStyle 设置节点样式
|
|
11
|
+
* onReady 加载完毕执行
|
|
12
|
+
* throttle 节流函数
|
|
13
|
+
2、API功能(Node.js)
|
|
14
|
+
* animation 动画
|
|
15
|
+
* deeplog 进度打印
|
|
16
|
+
* linglog 单行打印
|
|
17
|
+
* throttle 节流函数
|
|
18
|
+
3、命令(oipage-cli)
|
|
19
|
+
* serve 开发服务器
|
|
20
|
+
v1.1.0:
|
|
21
|
+
date:2025-02-18
|
|
22
|
+
changes:
|
|
23
|
+
- 修复bug
|
|
24
|
+
1、通过路径类型判断以修复开发服务器无法设置绝对路径问题
|
|
25
|
+
- 优化改造
|
|
26
|
+
1、使用流读取以使开发服务器支持大文件下载
|
|
27
|
+
(同时添加下载进度可查)
|
|
28
|
+
- 新增功能
|
|
29
|
+
1、API功能(Node.js)
|
|
30
|
+
* disk 磁盘相关操作
|
|
31
|
+
(包括:deleteDisk、copyDisk)
|
|
32
|
+
* logform 表单输入
|
|
33
|
+
2、命令(oipage-cli)
|
|
34
|
+
* dist 磁盘操作
|
|
35
|
+
* run 运行多命令
|
|
36
|
+
v1.2.0:
|
|
37
|
+
date:2025-02-25
|
|
38
|
+
changes:
|
|
39
|
+
- 优化改造
|
|
40
|
+
1、优化npm包目录结构等
|
|
41
|
+
- 新增功能
|
|
42
|
+
1、开发服务器
|
|
43
|
+
* 添加配置文件
|
|
44
|
+
(oipage-cli serve --config ./oipage.config.js)
|
|
45
|
+
* 新增对node_modules包引入支持
|
|
46
|
+
v1.2.1:
|
|
47
|
+
date:2025-03-06
|
|
48
|
+
changes:
|
|
49
|
+
- 修复bug
|
|
50
|
+
1、开发服务器
|
|
51
|
+
* 修复路径不存在时未正确同步修改浏览器地址问题
|
|
52
|
+
v1.3.0:(已废弃,请用1.3.1代替)
|
|
53
|
+
date:2025-05-18
|
|
54
|
+
changes:
|
|
55
|
+
- 修复bug
|
|
56
|
+
1、开发服务器
|
|
57
|
+
* 修复服务器根路径判断错误导致node_modules包查找错误问题
|
|
58
|
+
2、修复animation动画types类型定义错误问题
|
|
59
|
+
- 新增功能
|
|
60
|
+
1、API功能(浏览器)
|
|
61
|
+
* reader 文本分析读取器
|
|
62
|
+
* performChunk 空闲执行分片函数
|
|
63
|
+
* strToJson JSON字符串解析
|
|
64
|
+
2、API功能(Node.js)
|
|
65
|
+
* reader 文本分析读取器
|
|
66
|
+
* strToJson JSON字符串解析
|
|
67
|
+
3、开发服务器
|
|
68
|
+
* 新增 devServer.intercept 请求拦截
|
|
69
|
+
* 新增对 if-modified-since和last-modified 之304协商缓存的支持
|
|
70
|
+
v1.3.1:
|
|
71
|
+
date:2025-05-23
|
|
72
|
+
changes:
|
|
73
|
+
- 修复bug
|
|
74
|
+
1、开发服务器
|
|
75
|
+
* 由于是否入口判断导致import语句未正确解析
|
|
76
|
+
* 修复 Last-Modified 格式不规范导致的运行报错
|
|
77
|
+
v1.4.0:
|
|
78
|
+
date:2025-09-02
|
|
79
|
+
changes:
|
|
80
|
+
- 修复bug
|
|
81
|
+
1、修复logform运行报错
|
|
82
|
+
- 新增功能
|
|
83
|
+
1、API功能(浏览器)
|
|
84
|
+
* dateFormat 日期格式化
|
|
85
|
+
* numberFormat 数字格式化
|
|
86
|
+
* XHRIntercept XHR拦截
|
|
87
|
+
2、API功能(Node.js)
|
|
88
|
+
* dateFormat 日期格式化
|
|
89
|
+
* numberFormat 数字格式化
|
|
90
|
+
3、开发服务器
|
|
91
|
+
* 新增 serve.d.ts 以支持作为API在TypeScript中环境
|
|
92
|
+
(仅对内使用,未正式对外暴露API相关文档)
|
|
93
|
+
* 添加304是否启用开关
|
|
94
|
+
* 应用市场(website内置网站)
|
|
95
|
+
v1.4.1:
|
|
96
|
+
date:2025-09-02
|
|
97
|
+
changes:
|
|
98
|
+
- 修复bug
|
|
99
|
+
1、修复开发服务器大文件丢失文件大小问题
|
|
100
|
+
v1.5.0:
|
|
101
|
+
date:2025-11-13
|
|
102
|
+
changes:
|
|
103
|
+
- 修复bug
|
|
104
|
+
1、修复404网站在手机浏览器显示高问题
|
|
105
|
+
2、服务器响应类型由 Content-type 改为 Content-Type
|
|
106
|
+
3、修复dateFormat第二个参数无法缺省报错
|
|
107
|
+
4、修复numberFormat不支持负数问题
|
|
108
|
+
- 优化改造
|
|
109
|
+
1、优化run命令日志打印
|
|
110
|
+
- 新增功能
|
|
111
|
+
1、开发服务器 / 应用市场
|
|
112
|
+
* 群聊天
|
|
113
|
+
* 图片编辑器
|
|
114
|
+
* 图片转PDF
|
|
115
|
+
2、API功能(Node.js)
|
|
116
|
+
* disk 磁盘相关操作
|
|
117
|
+
(包括:moveDisk、listDisk)
|
|
118
|
+
v1.6.0:
|
|
119
|
+
(此版本已废弃,请用v1.6.1+代替)
|
|
120
|
+
date:2025-12-14
|
|
121
|
+
changes:
|
|
122
|
+
- 修复bug
|
|
123
|
+
1、修复logform在run下无法正常使用问题
|
|
124
|
+
(关联issue: https://github.com/oi-contrib/OIPage/issues/4 )
|
|
125
|
+
2、修复服务器错误修改XHR等请求数据问题
|
|
126
|
+
- 优化改造
|
|
127
|
+
1、命令行帮助打印更可读
|
|
128
|
+
- 新增功能
|
|
129
|
+
1、命令(oipage-cli)
|
|
130
|
+
* disk
|
|
131
|
+
--link 创建磁盘链接
|
|
132
|
+
--delempty 删除空文件夹
|
|
133
|
+
* network 网络相关
|
|
134
|
+
* run 支持动态参数
|
|
135
|
+
(关联issue: https://github.com/oi-contrib/OIPage/issues/5 )
|
|
136
|
+
2、API功能(Node.js)
|
|
137
|
+
* disk 磁盘相关操作
|
|
138
|
+
(包括:linkDisk)
|
|
139
|
+
v1.6.1:
|
|
140
|
+
date:2025-12-29
|
|
141
|
+
changes:
|
|
142
|
+
- 修复bug
|
|
143
|
+
1、修复run命令在Windows中运行错误
|
|
144
|
+
(关联issue: https://github.com/oi-contrib/OIPage/issues/8 )
|
|
145
|
+
v1.7.0:
|
|
146
|
+
date:
|
|
147
|
+
changes:
|
|
148
|
+
- 优化改造
|
|
149
|
+
1、types定义模块,方便使用时代码提示
|
|
150
|
+
2、使用requestAnimationFrame改造animation
|
|
151
|
+
- 修复bug
|
|
152
|
+
1、修复特殊情况下 “应用市场” 依赖查找错误问题
|
|
153
|
+
2、修复开发服务器错误缓存问题
|
|
154
|
+
3、修改types错误定义(intercept)
|
|
155
|
+
- 新增功能
|
|
156
|
+
1、API功能(Node.js)
|
|
157
|
+
* remote HTTP请求
|
|
158
|
+
(包括:get、post)
|
|
159
|
+
2、开发服务器
|
|
160
|
+
* 转发功能 proxy
|
package/bin/help.js
CHANGED
package/bin/proxy.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
const https = require('https');
|
|
2
|
+
const http = require('http');
|
|
3
|
+
|
|
4
|
+
module.exports = function (args, proxy) {
|
|
5
|
+
|
|
6
|
+
let intercept = [];
|
|
7
|
+
for (let key in proxy) {
|
|
8
|
+
intercept.push({
|
|
9
|
+
test: new RegExp(key),
|
|
10
|
+
handler(request, response) {
|
|
11
|
+
let proxyItem = proxy[key];
|
|
12
|
+
|
|
13
|
+
let throwError = function (err) {
|
|
14
|
+
response.writeHead(500, {
|
|
15
|
+
'Content-Type': "text/plain;charset=utf-8",
|
|
16
|
+
'Access-Control-Allow-Origin': '*',
|
|
17
|
+
'Server': 'Powered by ' + args.name + '\'s proxy'
|
|
18
|
+
});
|
|
19
|
+
response.write(err);
|
|
20
|
+
response.end();
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
let headers = request.headers;
|
|
24
|
+
let url = decodeURIComponent(request.url);
|
|
25
|
+
|
|
26
|
+
if (proxyItem.pathRewrite) {
|
|
27
|
+
for (pathRewrite_key in proxyItem.pathRewrite) {
|
|
28
|
+
url = url.replace(new RegExp(pathRewrite_key), proxyItem.pathRewrite[pathRewrite_key]);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
let fullUrl = proxy[key].target + url;
|
|
33
|
+
|
|
34
|
+
let handler = /^https/.test(url) ? https : http;
|
|
35
|
+
|
|
36
|
+
let execArray = /https*:\/\/([^\/]+)(.+)?/.exec(fullUrl);
|
|
37
|
+
let hostport = execArray[1].split(":");
|
|
38
|
+
|
|
39
|
+
// 创建与目标服务器的连接
|
|
40
|
+
const req = handler.request({
|
|
41
|
+
hostname: hostport[0],
|
|
42
|
+
port: hostport[1] || 80,
|
|
43
|
+
path: execArray[2] || "/",
|
|
44
|
+
method: request.method,
|
|
45
|
+
headers
|
|
46
|
+
}, (res) => {
|
|
47
|
+
|
|
48
|
+
let resHeaders = {
|
|
49
|
+
...res.headers
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// 解决跨域问题
|
|
53
|
+
if (resHeaders['Access-Control-Allow-Origin'] !== '*' && resHeaders['access-control-allow-origin'] !== '*') resHeaders['Access-Control-Allow-Origin'] = '*'
|
|
54
|
+
|
|
55
|
+
// 标记响应服务器
|
|
56
|
+
delete resHeaders["Server"];
|
|
57
|
+
delete resHeaders["server"];
|
|
58
|
+
resHeaders["Server"] = 'Powered by ' + args.name + '\'s proxy';
|
|
59
|
+
|
|
60
|
+
// 设置响应头
|
|
61
|
+
response.writeHead(res.statusCode, resHeaders);
|
|
62
|
+
// 流式传输响应体
|
|
63
|
+
res.pipe(response);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// 错误处理
|
|
67
|
+
req.on('error', (e) => {
|
|
68
|
+
throwError(e.message);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// 将原始请求体传递给目标服务器
|
|
72
|
+
request.pipe(req);
|
|
73
|
+
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return intercept;
|
|
79
|
+
};
|
package/bin/run
CHANGED
|
@@ -23,6 +23,7 @@ if (process.argv[2] === "serve") {
|
|
|
23
23
|
port: 8080,
|
|
24
24
|
baseUrl: "./",
|
|
25
25
|
cache: true,
|
|
26
|
+
proxy: {},
|
|
26
27
|
intercept: []
|
|
27
28
|
},
|
|
28
29
|
module: {
|
|
@@ -30,6 +31,12 @@ if (process.argv[2] === "serve") {
|
|
|
30
31
|
}
|
|
31
32
|
};
|
|
32
33
|
|
|
34
|
+
if (argvObj["--proxy"] && argvObj["--proxy"].length === 2) {
|
|
35
|
+
config.devServer.proxy[argvObj["--proxy"][0]] = {
|
|
36
|
+
target: argvObj["--proxy"][1]
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
33
40
|
// 如果设置了配置文件
|
|
34
41
|
if (argvObj["--config"]) {
|
|
35
42
|
let configPath = join(process.cwd(), argvObj["--config"][0] || "./oipage.config.js");
|
|
@@ -118,4 +125,4 @@ else if (process.argv[2] === "network") {
|
|
|
118
125
|
// 默认,帮助
|
|
119
126
|
else {
|
|
120
127
|
require("./help.js")();
|
|
121
|
-
}
|
|
128
|
+
}
|
package/bin/serve.d.ts
CHANGED
|
@@ -15,6 +15,17 @@ interface DevServerType {
|
|
|
15
15
|
* 是否开启304缓存,默认开启
|
|
16
16
|
*/
|
|
17
17
|
cache: boolean
|
|
18
|
+
|
|
19
|
+
intercept?: Array<InterceptType>
|
|
20
|
+
|
|
21
|
+
proxy?: {
|
|
22
|
+
[key: string]: {
|
|
23
|
+
target: string
|
|
24
|
+
pathRewrite?: {
|
|
25
|
+
[key: string]: string
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
18
29
|
}
|
|
19
30
|
|
|
20
31
|
interface InterceptType {
|
|
@@ -43,8 +54,6 @@ interface ConfigType {
|
|
|
43
54
|
*/
|
|
44
55
|
devServer: DevServerType
|
|
45
56
|
|
|
46
|
-
intercept?: Array<InterceptType>
|
|
47
|
-
|
|
48
57
|
module?: {
|
|
49
58
|
rules: Array<{
|
|
50
59
|
test: RegExp
|
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