@maiyunnet/kebab 2.0.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.
Files changed (114) hide show
  1. package/.VSCodeCounter/2025-02-14_14-46-44/details.md +82 -0
  2. package/.VSCodeCounter/2025-02-14_14-46-44/diff-details.md +15 -0
  3. package/.VSCodeCounter/2025-02-14_14-46-44/diff.csv +2 -0
  4. package/.VSCodeCounter/2025-02-14_14-46-44/diff.md +19 -0
  5. package/.VSCodeCounter/2025-02-14_14-46-44/diff.txt +22 -0
  6. package/.VSCodeCounter/2025-02-14_14-46-44/results.csv +69 -0
  7. package/.VSCodeCounter/2025-02-14_14-46-44/results.json +1 -0
  8. package/.VSCodeCounter/2025-02-14_14-46-44/results.md +48 -0
  9. package/.VSCodeCounter/2025-02-14_14-46-44/results.txt +118 -0
  10. package/.vscode/tasks.json +15 -0
  11. package/LICENSE +201 -0
  12. package/README.md +201 -0
  13. package/bin/kebab.js +2 -0
  14. package/eslint.config.js +22 -0
  15. package/index.js +19 -0
  16. package/index.ts +33 -0
  17. package/lib/buffer.js +108 -0
  18. package/lib/buffer.ts +152 -0
  19. package/lib/captcha/zcool-addict-italic.ttf +0 -0
  20. package/lib/captcha.js +71 -0
  21. package/lib/captcha.ts +63 -0
  22. package/lib/consistent.js +171 -0
  23. package/lib/consistent.ts +219 -0
  24. package/lib/core.js +663 -0
  25. package/lib/core.ts +880 -0
  26. package/lib/crypto.js +256 -0
  27. package/lib/crypto.ts +384 -0
  28. package/lib/db.js +521 -0
  29. package/lib/db.ts +719 -0
  30. package/lib/dns.js +321 -0
  31. package/lib/dns.ts +405 -0
  32. package/lib/fs.js +405 -0
  33. package/lib/fs.ts +527 -0
  34. package/lib/jwt.js +223 -0
  35. package/lib/jwt.ts +276 -0
  36. package/lib/kv.js +1004 -0
  37. package/lib/kv.ts +1489 -0
  38. package/lib/lan.js +99 -0
  39. package/lib/lan.ts +87 -0
  40. package/lib/net/cacert.pem +3480 -0
  41. package/lib/net/formdata.js +137 -0
  42. package/lib/net/formdata.ts +166 -0
  43. package/lib/net/request.js +102 -0
  44. package/lib/net/request.ts +150 -0
  45. package/lib/net/response.js +28 -0
  46. package/lib/net/response.ts +59 -0
  47. package/lib/net.js +462 -0
  48. package/lib/net.ts +662 -0
  49. package/lib/s3.js +180 -0
  50. package/lib/s3.ts +235 -0
  51. package/lib/scan.js +276 -0
  52. package/lib/scan.ts +364 -0
  53. package/lib/session.js +177 -0
  54. package/lib/session.ts +230 -0
  55. package/lib/sql.js +818 -0
  56. package/lib/sql.ts +1151 -0
  57. package/lib/ssh/sftp.js +373 -0
  58. package/lib/ssh/sftp.ts +508 -0
  59. package/lib/ssh/shell.js +109 -0
  60. package/lib/ssh/shell.ts +123 -0
  61. package/lib/ssh.js +171 -0
  62. package/lib/ssh.ts +191 -0
  63. package/lib/text/tld.json +1 -0
  64. package/lib/text.js +452 -0
  65. package/lib/text.ts +607 -0
  66. package/lib/time.js +216 -0
  67. package/lib/time.ts +254 -0
  68. package/lib/ws.js +373 -0
  69. package/lib/ws.ts +523 -0
  70. package/lib/zip.js +381 -0
  71. package/lib/zip.ts +447 -0
  72. package/lib/zlib.js +289 -0
  73. package/lib/zlib.ts +350 -0
  74. package/main.js +51 -0
  75. package/main.ts +27 -0
  76. package/package.json +37 -0
  77. package/sys/child.js +585 -0
  78. package/sys/child.ts +678 -0
  79. package/sys/cmd.js +226 -0
  80. package/sys/cmd.ts +225 -0
  81. package/sys/ctr.js +608 -0
  82. package/sys/ctr.ts +904 -0
  83. package/sys/master.js +314 -0
  84. package/sys/master.ts +355 -0
  85. package/sys/mod.js +1273 -0
  86. package/sys/mod.ts +1871 -0
  87. package/sys/route.js +922 -0
  88. package/sys/route.ts +1113 -0
  89. package/types/index.d.ts +283 -0
  90. package/www/example/ctr/main.js +42 -0
  91. package/www/example/ctr/main.ts +9 -0
  92. package/www/example/ctr/middle.js +57 -0
  93. package/www/example/ctr/middle.ts +26 -0
  94. package/www/example/ctr/test.js +2818 -0
  95. package/www/example/ctr/test.ts +3218 -0
  96. package/www/example/data/locale/en.test.json +8 -0
  97. package/www/example/data/locale/index.html +1 -0
  98. package/www/example/data/locale/ja.test.json +8 -0
  99. package/www/example/data/locale/sc.test.json +8 -0
  100. package/www/example/data/locale/tc.test.json +8 -0
  101. package/www/example/data/test.zip +0 -0
  102. package/www/example/kebab.json +24 -0
  103. package/www/example/mod/test.js +49 -0
  104. package/www/example/mod/test.ts +47 -0
  105. package/www/example/mod/testdata.js +11 -0
  106. package/www/example/mod/testdata.ts +30 -0
  107. package/www/example/route.json +6 -0
  108. package/www/example/view/test.ejs +11 -0
  109. package/www/example/ws/mproxy.js +49 -0
  110. package/www/example/ws/mproxy.ts +16 -0
  111. package/www/example/ws/rproxy.js +47 -0
  112. package/www/example/ws/rproxy.ts +14 -0
  113. package/www/example/ws/test.js +68 -0
  114. package/www/example/ws/test.ts +36 -0
@@ -0,0 +1,3218 @@
1
+ import * as fs from 'fs';
2
+ // --- 库和定义 ---
3
+ import * as lCore from '~/lib/core';
4
+ import * as lNet from '~/lib/net';
5
+ import * as lDb from '~/lib/db';
6
+ import * as lFs from '~/lib/fs';
7
+ import * as lText from '~/lib/text';
8
+ import * as lCrypto from '~/lib/crypto';
9
+ import * as lKv from '~/lib/kv';
10
+ import * as lCaptcha from '~/lib/captcha';
11
+ import * as lTime from '~/lib/time';
12
+ import * as lScan from '~/lib/scan';
13
+ import * as lSql from '~/lib/sql';
14
+ import * as lConsistent from '~/lib/consistent';
15
+ import * as lSsh from '~/lib/ssh';
16
+ import * as lJwt from '~/lib/jwt';
17
+ import * as lWs from '~/lib/ws';
18
+ import * as lS3 from '~/lib/s3';
19
+ import * as lZip from '~/lib/zip';
20
+ import * as lBuffer from '~/lib/buffer';
21
+ import * as lLan from '~/lib/lan';
22
+ import * as sCtr from '~/sys/ctr';
23
+ import * as kebab from '~/index';
24
+ import * as types from '~/types';
25
+ // --- mod ---
26
+ import mTest from '../mod/test';
27
+ import mTestData from '../mod/testdata';
28
+
29
+ export default class extends sCtr.Ctr {
30
+
31
+ private _internalUrl: string = '';
32
+
33
+ public onLoad(): Array<string | number> | boolean {
34
+ if (
35
+ this._config.const.hostname !== '127.0.0.1' && this._config.const.hostname !== '172.17.0.1' &&
36
+ this._config.const.hostname !== 'localhost' && this._config.const.hostname !== 'local-test.brc-app.com' &&
37
+ !this._config.const.hostname.startsWith('192.168.')
38
+ ) {
39
+ return [0, 'Please use 127.0.0.1 or local to access the file (' + this._config.const.host + ').'];
40
+ }
41
+ const realIp = lCore.realIP(this);
42
+ if (
43
+ (this._config.const.hostname === '127.0.0.1' || this._config.const.hostname === 'localhost') &&
44
+ (realIp === '172.17.0.1')
45
+ ) {
46
+ this._internalUrl = 'http' + (this._config.const.https ? 's' : '') + '://' + realIp + this._config.const.urlBase;
47
+ }
48
+ else {
49
+ this._internalUrl = this._config.const.urlFull;
50
+ }
51
+ return true;
52
+ }
53
+
54
+ public onUnload(rtn: string | boolean | types.DbValue[]): string | boolean | types.DbValue[] {
55
+ if (!Array.isArray(rtn)) {
56
+ return rtn;
57
+ }
58
+ if (rtn[0] !== -102) {
59
+ return rtn;
60
+ }
61
+ rtn.push({
62
+ 'test': 'unload'
63
+ });
64
+ return rtn;
65
+ }
66
+
67
+ public notfound(): string {
68
+ // --- Set on route.php ---
69
+ this._httpCode = 404;
70
+ return 'Custom 404 page.';
71
+ }
72
+
73
+ public index(): string {
74
+ const echo: string[] = [
75
+ 'Hello world! Welcome to use <strong>Kebab ' + kebab.VER + '</strong>!',
76
+
77
+ '<br><br>Node Version: ' + process.version,
78
+ '<br>HOST: ' + this._config.const.host,
79
+ '<br>HOSTNAME: ' + this._config.const.hostname,
80
+ '<br>HOSTPORT: ' + this._config.const.hostport.toString(),
81
+ '<br>PATH: ' + this._config.const.path,
82
+ '<br>QS: ' + this._config.const.qs,
83
+ '<br>HTTPS: ' + (this._config.const.https ? 'true' : 'false'),
84
+
85
+ '<br><br>MOBILE: ' + (this._config.const.mobile ? 'true' : 'false'),
86
+ '<br>Real IP: ' + lCore.ip(this),
87
+ '<br>Client IP: ' + lCore.realIP(this),
88
+
89
+ '<br><br>URL_BASE: ' + this._config.const.urlBase,
90
+ '<br>URL_STC: ' + this._config.const.urlStc,
91
+ '<br>URL_FULL: ' + this._config.const.urlFull,
92
+ '<br>STATIC_PATH: ' + this._config.set.staticPath,
93
+ '<br>STATIC_PATH_FULL: ' + this._config.set.staticPathFull,
94
+ '<br>_internalUrl: ' + this._internalUrl,
95
+
96
+ '<br><br>headers: ' + lText.htmlescape(JSON.stringify(this._headers)),
97
+
98
+ '<br><br><b style="color: red;">Tips: The file can be deleted.</b>',
99
+
100
+ '<br><br><b>Route (route.json):</b>',
101
+ `<br><br><a href="${this._config.const.urlBase}article/123">View "article/123"</a>`,
102
+ `<br><a href="${this._config.const.urlBase}article/456">View "article/456"</a>`,
103
+
104
+ '<br><br><b>Query string:</b>',
105
+ `<br><br><a href="${this._config.const.urlBase}test/qs?a=1&b=2">View "test/qs?a=1&b=2"</a>`,
106
+
107
+ '<br><br><b>View:</b>',
108
+ `<br><br><a href="${this._config.const.urlBase}test/view">View "test/view"</a>`,
109
+
110
+ '<br><br><b>Return json:</b>',
111
+ `<br><br><a href="${this._config.const.urlBase}test/json?type=1">View "test/json?type=1"</a>`,
112
+ `<br><a href="${this._config.const.urlBase}test/json?type=2">View "test/json?type=2"</a>`,
113
+ `<br><a href="${this._config.const.urlBase}test/json?type=3">View "test/json?type=3"</a>`,
114
+ `<br><a href="${this._config.const.urlBase}test/json?type=4">View "test/json?type=4"</a>`,
115
+ `<br><a href="${this._config.const.urlBase}test/json?type=5">View "test/json?type=5"</a>`,
116
+ `<br><a href="${this._config.const.urlBase}test/json?type=6">View "test/json?type=6"</a>`,
117
+ `<br><a href="${this._config.const.urlBase}test/json?type=7">View "test/json?type=7"</a>`,
118
+ `<br><a href="${this._config.const.urlBase}test/json?type=8">View "test/json?type=8"</a>`,
119
+ `<br><a href="${this._config.const.urlBase}test/json?type=9">View "test/json?type=9"</a>`,
120
+
121
+ '<br><br><b>Ctr:</b>',
122
+ `<br><br><a href="${this._config.const.urlBase}test/ctr-xsrf">View "test/ctr-xsrf"</a>`,
123
+ `<br><a href="${this._config.const.urlBase}test/ctr-checkinput">View "test/ctr-checkinput"</a>`,
124
+ `<br><a href="${this._config.const.urlBase}test/ctr-locale">View "test/ctr-locale"</a>`,
125
+ `<br><a href="${this._config.const.urlBase}test/ctr-cachettl">View "test/ctr-cachettl"</a>`,
126
+ `<br><a href="${this._config.const.urlBase}test/ctr-httpcode">View "test/ctr-httpcode"</a>`,
127
+ `<br><a href="${this._config.const.urlBase}test/ctr-cross">View "test/ctr-cross"</a>`,
128
+ `<br><a href="${this._config.const.urlBase}test/ctr-readable">View "test/ctr-readable"</a>`,
129
+ `<br><a href="${this._config.const.urlBase}test/ctr-asynctask">View "test/ctr-asynctask"</a>`,
130
+ `<br><a href="${this._config.const.urlBase}test/ctr-timeout">View "test/ctr-timeout"</a>`,
131
+
132
+ '<br><br><b>Middle:</b>',
133
+ `<br><br><a href="${this._config.const.urlBase}test/middle">View "test/middle"</a>`,
134
+
135
+ '<br><br><b>Model test:</b>',
136
+
137
+ '<br><br><b style="color: red;">In a production environment, please delete "mod/test.ts", "mod/testdata.ts" files.</b>',
138
+ `<br><a href="${this._config.const.urlBase}test/mod-test">Click to see an example of a Test model</a>`,
139
+ `<br><a href="${this._config.const.urlBase}test/mod-split">View "test/mod-split"</a>`,
140
+
141
+ '<br><br><b>Library test:</b>',
142
+
143
+ '<br><br><b>Captcha:</b>',
144
+ `<br><br><a href="${this._config.const.urlBase}test/captcha-fastbuild">View "test/captcha-fastbuild"</a>`,
145
+ `<br><a href="${this._config.const.urlBase}test/captcha-base64">View "test/captcha-base64"</a>`,
146
+
147
+ '<br><br><b>Core:</b>',
148
+ `<br><br><a href="${this._config.const.urlBase}test/core-random">View "test/core-random"</a>`,
149
+ `<br><a href="${this._config.const.urlBase}test/core-rand">View "test/core-rand"</a>`,
150
+ `<br><a href="${this._config.const.urlBase}test/core-convert62">View "test/core-convert62"</a>`,
151
+ `<br><a href="${this._config.const.urlBase}test/core-purify">View "test/core-purify"</a>`,
152
+ `<br><a href="${this._config.const.urlBase}test/core-checktype">View "test/core-checktype"</a>`,
153
+ `<br><a href="${this._config.const.urlBase}test/core-muid">View "test/core-muid"</a>`,
154
+ `<br><a href="${this._config.const.urlBase}test/core-getlog">View "test/core-getlog"</a>`,
155
+ `<br><a href="${this._config.const.urlBase}test/core-reload">View "test/core-reload"</a>`,
156
+ `<br><a href="${this._config.const.urlBase}test/core-restart">View "test/core-restart"</a>`,
157
+ `<br><a href="${this._config.const.urlBase}test/core-global">View "test/core-global"</a>`,
158
+ `<br><a href="${this._config.const.urlBase}test/core-updatecode">View "test/core-updatecode"</a>`,
159
+
160
+ '<br><br><b>Crypto:</b>',
161
+ `<br><br><a href="${this._config.const.urlBase}test/crypto">View "test/crypto"</a>`,
162
+
163
+ '<br><br><b>Db:</b>',
164
+ `<br><br><a href="${this._config.const.urlBase}test/db">View "test/db"</a>`,
165
+
166
+ '<br><br><b>Kv:</b>',
167
+ `<br><br><a href="${this._config.const.urlBase}test/kv">View "test/kv"</a>`,
168
+
169
+ '<br><br><b>Net:</b>',
170
+ `<br><br><a href="${this._config.const.urlBase}test/net">View "test/net"</a>`,
171
+ `<br><a href="${this._config.const.urlBase}test/net-pipe">View "test/net-pipe"</a>`,
172
+ `<br><a href="${this._config.const.urlBase}test/net-post">View "test/net-post"</a>`,
173
+ `<br><a href="${this._config.const.urlBase}test/net-post-string">View "test/net-post-string"</a>`,
174
+ `<br><a href="${this._config.const.urlBase}test/net-open">View "test/net-open"</a>`,
175
+ `<br><a href="${this._config.const.urlBase}test/net-form-test">View "test/net-form-test"</a>`,
176
+ `<br><a href="${this._config.const.urlBase}test/net-upload">View "test/net-upload"</a>`,
177
+ `<br><a href="${this._config.const.urlBase}test/net-cookie">View "test/net-cookie"</a>`,
178
+ `<br><a href="${this._config.const.urlBase}test/net-save">View "test/net-save"</a>`,
179
+ `<br><a href="${this._config.const.urlBase}test/net-follow">View "test/net-follow"</a>`,
180
+ `<br><a href="${this._config.const.urlBase}test/net-reuse">View "test/net-reuse"</a>`,
181
+ `<br><a href="${this._config.const.urlBase}test/net-error">View "test/net-error"</a>`,
182
+ `<br><a href="${this._config.const.urlBase}test/net-hosts">View "test/net-hosts"</a>`,
183
+ `<br><a href="${this._config.const.urlBase}test/net-rproxy/dist/core.js">View "test/net-rproxy/dist/core.js"</a> <a href="${this._config.const.urlBase}test/net-rproxy/package.json">View "package.json"</a>`,
184
+ `<br><a href="${this._config.const.urlBase}test/net-mproxy">View "test/net-mproxy"</a>`,
185
+
186
+ '<br><br><b>Scan:</b>',
187
+ `<br><br><a href="${this._config.const.urlBase}test/scan?s=db">View "test/scan?s=db"</a>`,
188
+ `<br><a href="${this._config.const.urlBase}test/scan?s=kv">View "test/scan?s=kv"</a>`,
189
+
190
+ '<br><br><b>Session:</b>',
191
+ `<br><br><a href="${this._config.const.urlBase}test/session?s=db">View "test/session?s=db"</a>`,
192
+ `<br><a href="${this._config.const.urlBase}test/session?s=kv">View "test/session?s=kv"</a>`,
193
+ `<br><a href="${this._config.const.urlBase}test/session?s=db&auth=1">View "test/session?s=db&auth=1" Header Authorization</a>`,
194
+ `<br><a href="${this._config.const.urlBase}test/session?s=kv&auth=1">View "test/session?s=kv&auth=1" Header Authorization</a>`,
195
+
196
+ '<br><br><b>Jwt:</b>',
197
+ `<br><br><a href="${this._config.const.urlBase}test/jwt">View "test/jwt"</a>`,
198
+ `<br><a href="${this._config.const.urlBase}test/jwt?type=kv">View "test/jwt?type=kv"</a>`,
199
+ `<br><a href="${this._config.const.urlBase}test/jwt?type=auth">View "test/jwt?type=auth" Header Authorization</a>`,
200
+
201
+ '<br><br><b>Sql:</b>',
202
+ `<br><br><a href="${this._config.const.urlBase}test/sql?type=insert">View "test/sql?type=insert"</a>`,
203
+ `<br><a href="${this._config.const.urlBase}test/sql?type=select">View "test/sql?type=select"</a>`,
204
+ `<br><a href="${this._config.const.urlBase}test/sql?type=update">View "test/sql?type=update"</a>`,
205
+ `<br><a href="${this._config.const.urlBase}test/sql?type=delete">View "test/sql?type=delete"</a>`,
206
+ `<br><a href="${this._config.const.urlBase}test/sql?type=where">View "test/sql?type=where"</a>`,
207
+ `<br><a href="${this._config.const.urlBase}test/sql?type=having">View "test/sql?type=having"</a>`,
208
+ `<br><a href="${this._config.const.urlBase}test/sql?type=by">View "test/sql?type=by"</a>`,
209
+ `<br><a href="${this._config.const.urlBase}test/sql?type=field">View "test/sql?type=field"</a>`,
210
+
211
+ '<br><br><b>Consistent:</b>',
212
+ `<br><br><a href="${this._config.const.urlBase}test/consistent-hash">View "test/consistent-hash"</a>`,
213
+ `<br><a href="${this._config.const.urlBase}test/consistent-distributed">View "test/consistent-distributed"</a>`,
214
+ `<br><a href="${this._config.const.urlBase}test/consistent-migration">View "test/consistent-migration"</a>`,
215
+ `<br><a href="${this._config.const.urlBase}test/consistent-fast">View "test/consistent-fast"</a>`,
216
+
217
+ '<br><br><b>Text:</b>',
218
+ `<br><br><a href="${this._config.const.urlBase}test/text">View "test/text"</a>`,
219
+
220
+ '<br><br><b>Time:</b>',
221
+ `<br><br><a href="${this._config.const.urlBase}test/time">View "test/time"</a>`,
222
+
223
+ '<br><br><b>Ws:</b>',
224
+ `<br><br><a href="${this._config.const.urlBase}test/ws-server">View "test/ws-server"</a>`,
225
+ `<br><a href="${this._config.const.urlBase}test/ws-server?ac=rproxy">View ws rproxy</a>`,
226
+ `<br><a href="${this._config.const.urlBase}test/ws-client">View "test/ws-client"</a>`,
227
+ `<br><a href="${this._config.const.urlBase}test/ws-client?ac=mproxy">View ws mproxy</a>`,
228
+
229
+ '<br><br><b>Ssh:</b>',
230
+ `<br><br><a href="${this._config.const.urlBase}test/ssh?type=shell">View "test/ssh?type=shell"</a>`,
231
+ `<br><a href="${this._config.const.urlBase}test/ssh?type=sftp">View "test/ssh?type=sftp"</a>`,
232
+
233
+ '<br><br><b>S3:</b>',
234
+ `<br><br><a href="${this._config.const.urlBase}test/s3">View "test/s3"</a>`,
235
+
236
+ '<br><br><b>Zip:</b>',
237
+ `<br><br><a href="${this._config.const.urlBase}test/zip">View "test/zip"</a>`,
238
+
239
+ '<br><br><b>Buffer:</b>',
240
+ `<br><br><a href="${this._config.const.urlBase}test/buffer">View "test/buffer"</a>`,
241
+
242
+ '<br><br><b>Lan:</b>',
243
+ `<br><br><a href="${this._config.const.urlBase}test/lan">View "test/lan"</a>`,
244
+ ];
245
+ echo.push('<br><br>' + this._getEnd());
246
+
247
+ return echo.join('');
248
+ }
249
+
250
+ public article(): string {
251
+ return 'Article ID: ' + lText.htmlescape(this._param[0]) + '<br><br>' + this._getEnd();
252
+ }
253
+
254
+ public qs(): string {
255
+ return 'JSON.stringify(this._get):<br><br>' + lText.htmlescape(JSON.stringify(this._get)) + '<br><br>' + this._getEnd();
256
+ }
257
+
258
+ public view(): Promise<string> {
259
+ return this._loadView('test', {
260
+ 'test': 'ok'
261
+ });
262
+ }
263
+
264
+ public json(): Array<number | string | object> | object {
265
+ switch (this._get.type) {
266
+ case '1':
267
+ return [0];
268
+ case '2':
269
+ return [0, 'Error message.'];
270
+ case '3':
271
+ return [0, { 'line': '2' }];
272
+ case '4':
273
+ return [1, 'Successful!'];
274
+ case '5':
275
+ return [1, { 'list': [{ 'id': '0' }, { 'id': '1' }, { 'id': '2' }], 'total': '3' }];
276
+ case '6':
277
+ return { 'oh': 'yeah', 'sb': 'is me' };
278
+ case '7':
279
+ return [1, 'success', { 'list': [1, 2, 3] }];
280
+ case '8':
281
+ return [-101, 'Test middle onUnload'];
282
+ case '9':
283
+ return [-102, 'Test ctr onUnload'];
284
+ default:
285
+ return [];
286
+ }
287
+ }
288
+
289
+ public ctrXsrf(): string {
290
+ this._enabledXsrf();
291
+ return `XSRF-TOKEN: ${this._xsrf}<br><br>
292
+ <input type="button" value="Post with xsrf token" onclick="document.getElementById('result').innerText='Waiting...';fetch('${this._config.const.urlBase}test/ctr-xsrf1',{method:'POST',headers:{'Content-Type':'application/x-www-form-urlencoded'},body:'key=val&_xsrf=${this._xsrf}'}).then(function(r){return r.text();}).then(function(t){document.getElementById('result').innerText=t;});">
293
+ <input type='button' value="Post without xsrf token" style="margin-left: 10px;" onclick="document.getElementById('result').innerText='Waiting...';fetch('${this._config.const.urlBase}test/ctr-xsrf1',{method:'POST',headers:{'Content-Type':'application/x-www-form-urlencoded'},body:'key=val'}).then(function(r){return r.text();}).then(function(t){document.getElementById('result').innerText=t;});"><br><br>
294
+ Result:<pre id="result">Nothing.</pre>${this._getEnd()}`;
295
+ }
296
+
297
+ public ctrXsrf1(): types.Json[] {
298
+ const retur: types.Json[] = [];
299
+ if (!this._checkXInput(this._post, {}, retur)) {
300
+ return retur;
301
+ }
302
+ return [1, { 'post': this._post }];
303
+ }
304
+
305
+ public ctrCheckinput(): string {
306
+ const echo = [`rule:
307
+ <pre>{
308
+ 'he': ['require', [0, 'The he param does not exist.']],
309
+ 'num': ['> 10', [0, 'The num param must > 10.']],
310
+ 'num2': ['> 0', '<= 100', [0, 'The num2 param must > 0.']],
311
+ 'reg': ['/^[A-CX-Z5-7]+$/', [0, 'The reg param is incorrect.']],
312
+ 'arr': [['a', 'x', 'hehe'], [0, 'The arr param is incorrect.']],
313
+ 'type': [{ 'type': { 'a': 1, 'b': '' } }, [0, 'The reg param is incorrect']],
314
+ 'json': [{ 'type': { 'a': '1', 'b': [ { 'c': 1 } ] } }, [0, 'The type param is incorrect']],
315
+ }</pre>`];
316
+
317
+ const post: any[] = [
318
+ {},
319
+ {
320
+ 'he': 'ok'
321
+ },
322
+ {
323
+ 'he': 'ok',
324
+ 'num': '5'
325
+ },
326
+ {
327
+ 'he': 'ok',
328
+ 'num2': '0'
329
+ },
330
+ {
331
+ 'he': 'ok',
332
+ 'num': '12',
333
+ 'reg': 'Hello'
334
+ },
335
+ {
336
+ 'he': 'ok',
337
+ 'num': '12',
338
+ 'reg': 'BBB6YYY6',
339
+ 'arr': 'heihei'
340
+ },
341
+ {
342
+ 'he': 'ok',
343
+ 'num': '12',
344
+ 'reg': 'BBB6YYY6',
345
+ 'arr': 'hehe'
346
+ },
347
+ {
348
+ 'he': 'ok',
349
+ 'num': '12',
350
+ 'reg': 'BBB6YYY6',
351
+ 'arr': 'hehe',
352
+ 'type': { 'a': false, 'b': '1' }
353
+ },
354
+ {
355
+ 'he': 'ok',
356
+ 'num': '12',
357
+ 'reg': 'BBB6YYY6',
358
+ 'arr': 'hehe',
359
+ 'type': { 'a': 0, 'b': 'ok' }
360
+ },
361
+ {
362
+ 'he': 'ok',
363
+ 'num': '12',
364
+ 'reg': 'BBB6YYY6',
365
+ 'arr': 'hehe',
366
+ 'type': { 'a': 0, 'b': 'ok' },
367
+ 'json': { 'a': 'a', 'b': [] },
368
+ },
369
+ {
370
+ 'he': 'ok',
371
+ 'num': '12',
372
+ 'reg': 'BBB6YYY6',
373
+ 'arr': 'hehe',
374
+ 'type': { 'a': 0, 'b': 'ok' },
375
+ 'json': { 'a': 'a', 'b': [ { 'c': 'a' } ] },
376
+ },
377
+ {
378
+ 'he': 'ok',
379
+ 'num': '12',
380
+ 'reg': 'BBB6YYY6',
381
+ 'arr': 'hehe',
382
+ 'type': { 'a': 0, 'b': 'ok' },
383
+ 'json': { 'a': 'a', 'b': [ { 'c': 1, 'd': 2 } ] },
384
+ },
385
+ {
386
+ 'he': 'ok',
387
+ 'num': '12',
388
+ 'reg': 'BBB6YYY6',
389
+ 'arr': 'hehe',
390
+ 'type': { 'a': 0, 'b': 'ok' },
391
+ 'json': { 'a': 'a', 'b': [ { 'c': 1 } ] },
392
+ }
393
+ ];
394
+ for (const item of post) {
395
+ if (item.type) {
396
+ item.type = JSON.stringify(item.type);
397
+ }
398
+ if (item.json) {
399
+ item.json = JSON.stringify(item.json);
400
+ }
401
+ echo.push(`<input type="button" value="Post '${lText.queryStringify(item, false).replace(/"/g, '&quot;')}'" onclick="post('${lText.queryStringify(item)}')"><br>`);
402
+ }
403
+
404
+ echo.push(`<input type="button" value="Post FormData (fd.append('he', 'ho'))" onclick="postFd()"><br>`);
405
+
406
+ echo.push(`<script>
407
+ function post(p) {
408
+ document.getElementById('result').innerText = 'Waiting...';
409
+ fetch('${this._config.const.urlBase}test/ctr-checkinput1', {
410
+ method: 'POST',
411
+ headers: {
412
+ 'Content-Type': 'application/x-www-form-urlencoded'
413
+ },
414
+ body: p
415
+ }).then(function(r) {
416
+ return r.text();
417
+ }).then(function(t) {
418
+ document.getElementById('result').innerText = t;
419
+ });
420
+ }
421
+
422
+ function postFd() {
423
+ var fd = new FormData();
424
+ fd.append('he', 'ho');
425
+ document.getElementById('result').innerText = 'Waiting...';
426
+ fetch('${this._config.const.urlBase}test/ctr-checkinput1', {
427
+ method: 'POST',
428
+ body: fd
429
+ }).then(function(r) {
430
+ return r.text();
431
+ }).then(function(t) {
432
+ document.getElementById('result').innerText = t;
433
+ });
434
+ }
435
+ </script>
436
+ <br>Result:<pre id="result">Nothing.</pre>`);
437
+
438
+ return echo.join('') + this._getEnd();
439
+ }
440
+
441
+ public async ctrCheckinput1(): Promise<types.Json[]> {
442
+ if (!await this._handleFormData()) {
443
+ return [0];
444
+ }
445
+ const retur: types.Json[] = [];
446
+ if (this._post['type']) {
447
+ this._post['type'] = lText.parseJson(this._post['type']);
448
+ }
449
+ if (this._post['json']) {
450
+ this._post['json'] = lText.parseJson(this._post['json']);
451
+ }
452
+ if (this._post['num2'] !== undefined) {
453
+ this._post['num2'] = parseFloat(this._post['num2']);
454
+ }
455
+ if (!this._checkInput(this._post, {
456
+ 'he': ['require', [0, 'The he param does not exist.']],
457
+ 'num': ['> 10', [0, 'The num param must > 10.']],
458
+ 'num2': ['> 0', '<= 100', [0, 'The num2 param must > 0.']],
459
+ 'reg': ['/^[A-CX-Z5-7]+$/', [0, 'The reg param is incorrect.']],
460
+ 'arr': [['a', 'x', 'hehe'], [0, 'The arr param is incorrect.']],
461
+ 'type': [{ 'type': { 'a': 1, 'b': '' } }, [0, 'The type param is incorrect']],
462
+ 'json': [{ 'type': { 'a': '1', 'b': [ { 'c': 1 } ] } }, [0, 'The type param is incorrect']],
463
+ }, retur)) {
464
+ return retur;
465
+ }
466
+ return [1, { 'post': this._post }];
467
+ }
468
+
469
+ public async ctrLocale(): Promise<types.Json[] | string> {
470
+ const rtn: types.Json[] = [];
471
+ if (!this._checkInput(this._get, {
472
+ 'lang': [['en', 'sc', 'tc', 'ja'], [0, 'Wrong language.']]
473
+ }, rtn)) {
474
+ return rtn;
475
+ }
476
+
477
+ const echo = [
478
+ '<a href="' + this._config.const.urlBase + 'test/ctr-locale">English</a> | ' +
479
+ '<a href="' + this._config.const.urlBase + 'test/ctr-locale?lang=sc">简体中文</a> | ' +
480
+ '<a href="' + this._config.const.urlBase + 'test/ctr-locale?lang=tc">繁體中文</a> | ' +
481
+ '<a href="' + this._config.const.urlBase + 'test/ctr-locale?lang=ja">日本語</a> | ' +
482
+ '<a href="' + this._config.const.urlBase + 'test">Return</a>'
483
+ ];
484
+
485
+ const r = await this._loadLocale(this._get['lang'], 'test');
486
+ echo.push(`<pre>await this._loadLocale(this._get['lang'], 'test');</pre>${r ? 'true' : 'false'}`);
487
+
488
+ echo.push("<pre>l('hello')</pre>" + this._l('hello'));
489
+ echo.push("<pre>l('copy')</pre>" + this._l('copy'));
490
+ echo.push("<pre>l('test', ['a1', 'a2'])</pre>" + this._l('test', ['a1', 'a2']));
491
+
492
+ return echo.join('') + '<br><br>' + this._getEnd();
493
+ }
494
+
495
+ public ctrCachettl(): string {
496
+ this._cacheTTL = 60;
497
+ return 'This page is cache ttl is 60s.';
498
+ }
499
+
500
+ public ctrHttpcode(): string {
501
+ this._httpCode = 404;
502
+ return 'This page is a custom httpcode (404).';
503
+ }
504
+
505
+ public ctrCross(): string {
506
+ return `<input type="button" value="Fetch localhost" onclick="document.getElementById('result').innerText='Waiting...';fetch('http://localhost:${this._config.const.hostport}${this._config.const.urlBase}test/ctr-cross1').then(function(r){return r.text();}).then(function(t){document.getElementById('result').innerText=t;}).catch(()=>{document.getElementById('result').innerText='Failed.';});">
507
+ <input type='button' value="Fetch localhost with cross" style="margin-left: 10px;" onclick="document.getElementById('result').innerText='Waiting...';fetch('http://localhost:${this._config.const.hostport}${this._config.const.urlBase}test/ctr-cross2').then(function(r){return r.text();}).then(function(t){document.getElementById('result').innerText=t;});">
508
+ <input type='button' value="Fetch local-test.brc-app.com with cross" style="margin-left: 10px;" onclick="document.getElementById('result').innerText='Waiting...';fetch('http://local-test.brc-app.com:${this._config.const.hostport}${this._config.const.urlBase}test/ctr-cross2').then(function(r){return r.text();}).then(function(t){document.getElementById('result').innerText=t;});"><br><br>
509
+ Result:<pre id="result">Nothing.</pre>` + this._getEnd();
510
+ }
511
+
512
+ public ctrCross1(): types.Json[] {
513
+ return [1, { 'value': 'done' }];
514
+ }
515
+
516
+ public ctrCross2(): types.Json[] {
517
+ if (!this._cross()) {
518
+ return [0];
519
+ }
520
+ return [1, { 'value': 'done' }];
521
+ }
522
+
523
+ public ctrReadable(): fs.ReadStream {
524
+ this._res.setHeader('content-type', 'text/plain; charset=utf-8');
525
+ return lFs.createReadStream(kebab.SYS_PATH + 'route.js');
526
+ }
527
+
528
+ public ctrAsynctask(): any[] {
529
+ this._asyncTask(async () => {
530
+ lCore.debug('ASYNCTASK IN');
531
+ await lCore.sleep(1000);
532
+ lCore.debug('ASYNCTASK TIME1');
533
+ await lCore.sleep(1000);
534
+ lCore.debug('ASYNCTASK TIME2');
535
+ await lCore.sleep(1000);
536
+ lCore.debug('ASYNCTASK OVER');
537
+ });
538
+ return [1];
539
+ }
540
+
541
+ public async ctrTimeout(): Promise<any[]> {
542
+ this.timeout = 70_000;
543
+ const echo = ['1'];
544
+ await lCore.sleep(15_000);
545
+ echo.push('2');
546
+ await lCore.sleep(15_000);
547
+ echo.push('3');
548
+ await lCore.sleep(15_000);
549
+ echo.push('4');
550
+ await lCore.sleep(15_000);
551
+ echo.push('5');
552
+ return [1, echo];
553
+ }
554
+
555
+ public async modTest(): Promise<types.Json[] | string | boolean> {
556
+ const retur: types.Json[] = [];
557
+ if (!(this._checkInput(this._get, {
558
+ 'action': [['', 'remove'], [0, 'Error']]
559
+ }, retur))) {
560
+ return retur;
561
+ }
562
+
563
+ const echo = ['<b style="color: red;">In a production environment, please delete the "mod/test.ts" file.</b>'];
564
+
565
+ const db = lDb.get(this);
566
+ let stmt = await db.query('SELECT * FROM `m_test` WHERE `token` LIMIT 1;');
567
+
568
+ if (!stmt.rows) {
569
+ return [0, 'Failed("m_test" not found).'];
570
+ }
571
+
572
+ if (this._get['action'] === 'remove') {
573
+ await mTest.removeByWhere(db, [
574
+ ['token', 'LIKE', 'test_%']
575
+ ], {
576
+ 'pre': this
577
+ });
578
+ return this._location('test/mod-test');
579
+ }
580
+ else {
581
+ const time = lTime.stamp();
582
+ const test = mTest.getCreate<mTest>(db, {
583
+ 'ctr': this
584
+ });
585
+ test.set({
586
+ 'point': { 'x': lCore.rand(0, 99), 'y': lCore.rand(0, 99) },
587
+ 'polygon': [
588
+ [
589
+ { 'x': 1, 'y': 1 },
590
+ { 'x': 2, 'y': 2 },
591
+ { 'x': 3, 'y': 3 },
592
+ { 'x': 1, 'y': 1 }
593
+ ]
594
+ ],
595
+ 'json': { 'x': { 'y': 'abc' } },
596
+ 'time_add': time
597
+ });
598
+ const result = await test.create();
599
+
600
+ echo.push(`<pre>const time = lTime.stamp();
601
+ const test = mTest.getCreate<mTest>(db, {
602
+ 'ctr': this
603
+ });
604
+ test.set({
605
+ 'point': { 'x': lCore.rand(0, 99), 'y': lCore.rand(0, 99) },
606
+ 'polygon': [
607
+ [
608
+ { 'x': 1, 'y': 1 },
609
+ { 'x': 2, 'y': 2 },
610
+ { 'x': 3, 'y': 3 },
611
+ { 'x': 1, 'y': 1 }
612
+ ]
613
+ ],
614
+ 'json': { 'x': { 'y': 'abc' } },
615
+ 'time_add': time
616
+ });
617
+ const result = await test.create();
618
+ JSON.stringify(result));</pre>` + JSON.stringify(result));
619
+
620
+ echo.push('<pre>JSON.stringify(test.toArray());</pre>' + lText.htmlescape(JSON.stringify(test.toArray())));
621
+
622
+ echo.push('<br><br>Test table:');
623
+
624
+ stmt = await db.query('SELECT * FROM `m_test` WHERE `token` LIKE \'test_%\' ORDER BY `id` ASC;');
625
+ this._dbTable(stmt, echo);
626
+
627
+ // --- explain ---
628
+
629
+ const ls = mTest.where<mTest>(db, [
630
+ ['time_add', '>', time - 60 * 5]
631
+ ], {
632
+ 'ctr': this
633
+ });
634
+ const r = await ls.explain();
635
+ echo.push(`<pre>const ls = mTest.where<mTest>(db, [
636
+ ['time_add', '>', time - 60 * 5]
637
+ ], {
638
+ 'ctr': this
639
+ });
640
+ const r = await ls.explain();</pre>` + lText.htmlescape(JSON.stringify(r)));
641
+
642
+ const r2 = await ls.explain(true);
643
+ echo.push('<pre>ls->explain(true);</pre>');
644
+ if (r2) {
645
+ echo.push('<table style="width: 100%;">');
646
+ for (const k in r2) {
647
+ const v = r2[k];
648
+ echo.push('<tr><th>' + lText.htmlescape(k) + '</th><td>' + (v === null ? 'null' : lText.htmlescape((typeof v === 'string' || typeof v === 'number') ? v.toString() : '[object]')) + '</td></tr>');
649
+ }
650
+ echo.push('</table>');
651
+ }
652
+ else {
653
+ echo.push('<div>false</div>');
654
+ }
655
+
656
+ let ft = await mTest.one<mTest>(db, [
657
+ ['time_add', '>', '0']
658
+ ], {
659
+ 'ctr': this
660
+ });
661
+ echo.push(`<pre>await mTest.one<mTest>(db, [
662
+ ['time_add', '>', '0']
663
+ ], {
664
+ 'ctr': this
665
+ });</pre>`);
666
+ if (ft) {
667
+ echo.push('<table style="width: 100%;">');
668
+
669
+ echo.push('<tr><th>id</th><td>' + ft.id.toString() + '</td></tr>');
670
+ echo.push('<tr><th>token</th><td>' + ft.token + '</td></tr>');
671
+ echo.push('<tr><th>point</th><td>' + JSON.stringify(ft.point) + '</td></tr>');
672
+ echo.push('<tr><th>polygon</th><td>' + JSON.stringify(ft.polygon) + '</td></tr>');
673
+ echo.push('<tr><th>json</th><td>' + JSON.stringify(ft.json) + '</td></tr>');
674
+ echo.push('<tr><th>time_add</th><td>' + ft.time_add.toString() + '</td></tr>');
675
+
676
+ echo.push('</table>');
677
+
678
+ // --- 修改 point 值 ---
679
+
680
+ ft.set('point', {
681
+ 'x': 20,
682
+ 'y': 20
683
+ });
684
+ await ft.save();
685
+ echo.push(`<pre>ft.set('point', {
686
+ 'x': 20,
687
+ 'y': 20
688
+ });
689
+ await ft.save();</pre>`);
690
+
691
+ ft = await mTest.find<mTest>(db, ft.id, {
692
+ 'ctr': this
693
+ });
694
+ if (!ft) {
695
+ return '';
696
+ }
697
+
698
+ echo.push('<table style="width: 100%;">');
699
+
700
+ echo.push('<tr><th>id</th><td>' + ft.id.toString() + '</td></tr>');
701
+ echo.push('<tr><th>token</th><td>' + ft.token + '</td></tr>');
702
+ echo.push('<tr><th>point</th><td>' + JSON.stringify(ft.point) + '</td></tr>');
703
+ echo.push('<tr><th>polygon</th><td>' + JSON.stringify(ft.polygon) + '</td></tr>');
704
+ echo.push('<tr><th>json</th><td>' + JSON.stringify(ft.json) + '</td></tr>');
705
+ echo.push('<tr><th>time_add</th><td>' + ft.time_add.toString() + '</td></tr>');
706
+
707
+ echo.push('</table>');
708
+
709
+ // --- 再次修改 ---
710
+
711
+ ft.set({
712
+ 'point': {
713
+ 'x': 40,
714
+ 'y': 40
715
+ },
716
+ 'polygon': [
717
+ [
718
+ { 'x': 5, 'y': 1 },
719
+ { 'x': 6, 'y': 2 },
720
+ { 'x': 7, 'y': 3 },
721
+ { 'x': 5, 'y': 1 }
722
+ ]
723
+ ],
724
+ 'json': { 'x': { 'y': 'def' } }
725
+ });
726
+ await ft.save();
727
+ await ft.refresh();
728
+ echo.push(`<pre>ft.set({
729
+ 'point': {
730
+ 'x': 40,
731
+ 'y': 40
732
+ },
733
+ 'polygon': [
734
+ [
735
+ { 'x': 5, 'y': 1 },
736
+ { 'x': 6, 'y': 2 },
737
+ { 'x': 7, 'y': 3 },
738
+ { 'x': 5, 'y': 1 }
739
+ ]
740
+ ],
741
+ 'json': { 'x': { 'y': 'def' } }
742
+ });
743
+ await ft.save();
744
+ await ft.refresh();</pre>`);
745
+
746
+ echo.push('<table style="width: 100%;">');
747
+
748
+ echo.push('<tr><th>id</th><td>' + ft.id.toString() + '</td></tr>');
749
+ echo.push('<tr><th>token</th><td>' + ft.token + '</td></tr>');
750
+ echo.push('<tr><th>point</th><td>' + JSON.stringify(ft.point) + '</td></tr>');
751
+ echo.push('<tr><th>polygon</th><td>' + JSON.stringify(ft.polygon) + '</td></tr>');
752
+ echo.push('<tr><th>json</th><td>' + JSON.stringify(ft.json) + '</td></tr>');
753
+ echo.push('<tr><th>time_add</th><td>' + ft.time_add.toString() + '</td></tr>');
754
+
755
+ echo.push('</table>');
756
+ }
757
+ else {
758
+ echo.push('<div>false</div>');
759
+ }
760
+
761
+ echo.push('<br><a href="' + this._config.const.urlBase + 'test/mod-test?action=remove">Remove all test data</a> | <a href="' + this._config.const.urlBase + 'test">Return</a>');
762
+
763
+ return echo.join('') + '<br><br>' + this._getEnd();
764
+ }
765
+ }
766
+
767
+ public async modSplit(): Promise<string> {
768
+ const echo = ['<b style="color: red;">In a production environment, please delete "mod/test.php" and "mod/testdata.php" files.</b>'];
769
+
770
+ const db = lDb.get(this);
771
+
772
+ echo.push(`<br><br>Test SQL:<pre>CREATE TABLE \`m_test\` (
773
+ \`id\` INT NOT NULL AUTO_INCREMENT,
774
+ \`token\` CHAR(16) NOT NULL COLLATE 'ascii_bin',
775
+ \`point\` POINT NOT NULL,
776
+ \`time_add\` BIGINT NOT NULL,
777
+ PRIMARY KEY (\`id\`) USING BTREE,
778
+ UNIQUE INDEX \`token\` (\`token\`) USING BTREE,
779
+ INDEX \`time_add\` (\`time_add\`) USING BTREE
780
+ ) ENGINE=InnoDB COLLATE=utf8mb4_general_ci;
781
+ CREATE TABLE \`m_test_data_0\` (
782
+ \`id\` bigint NOT NULL AUTO_INCREMENT,
783
+ \`test_id\` bigint NOT NULL,
784
+ \`content\` varchar(128) COLLATE ascii_bin NOT NULL,
785
+ \`time_add\` bigint NOT NULL,
786
+ PRIMARY KEY (\`id\`)
787
+ ) ENGINE=InnoDB DEFAULT CHARSET=ascii COLLATE=ascii_bin;</pre>m_test_data_0 - m_test_data_4<br><br>`);
788
+
789
+ // --- 操作按钮 ---
790
+
791
+ echo.push(`<input type="button" value="Create user" onclick="this.value='Waiting...';fetch('${this._config.const.urlBase}test/mod-split1',{method:'GET',headers:{'Content-Type':'application/x-www-form-urlencoded'}}).then(function(r){window.location.href=window.location.href})">
792
+ <input type="button" value="Random post" onclick="this.value='Waiting...';fetch('${this._config.const.urlBase}test/mod-split2',{method:'GET',headers:{'Content-Type':'application/x-www-form-urlencoded'}}).then(function(r){return r.json()}).then(function(j){alert('TESTID:'+j.id+'\\nTABLEINDEX:'+j.index);window.location.href=window.location.href})">`);
793
+
794
+ // --- 读取 test 和 test_data 表 ---
795
+
796
+ let stmt = await db.query('SELECT * FROM `m_test` ORDER BY `id` DESC LIMIT 0, 20;');
797
+ echo.push('<br><br><b>m_test</b> table:');
798
+ this._dbTable(stmt, echo);
799
+
800
+ for (let i = 0; i < 5; ++i) {
801
+ stmt = await db.query('SELECT * FROM `m_test_data_' + i.toString() + '` ORDER BY `id` DESC LIMIT 0, 20;');
802
+ echo.push('<br><b>m_test_data_' + i.toString() + '</b> table:');
803
+ this._dbTable(stmt, echo);
804
+ }
805
+
806
+ return echo.join('') + '<br>' + this._getEnd();
807
+ }
808
+
809
+ public async modSplit1(): Promise<void> {
810
+ const db = lDb.get(this);
811
+
812
+ const test = mTest.getCreate<mTest>(db, {
813
+ 'ctr': this
814
+ });
815
+ test.set({
816
+ 'token': lCore.random(lCore.rand(8, 32)),
817
+ 'point': {
818
+ 'x': 10,
819
+ 'y': 10
820
+ },
821
+ 'time_add': lTime.stamp()
822
+ });
823
+ await test.create();
824
+ }
825
+
826
+ public async modSplit2(): Promise<types.Json[]> {
827
+ const db = lDb.get(this);
828
+
829
+ const ids: number[] = [];
830
+ const ls = await mTest.select<mTest>(db, ['id'], {
831
+ 'ctr': this
832
+ }).by('time_add').limit(0, 50).all();
833
+ if (ls) {
834
+ for (const item of ls) {
835
+ if (!item.id) {
836
+ continue;
837
+ }
838
+ ids.push(item.id);
839
+ }
840
+ }
841
+ if (ids.length === 0) {
842
+ return [0, 'The "test" table not found.'];
843
+ }
844
+ const id = ids[lCore.rand(0, ids.length - 1)];
845
+
846
+ // --- 一致性 hash ---
847
+ const index = lConsistent.fast(id.toString(), ['0', '1', '2', '3', '4']);
848
+
849
+ const testData = mTestData.getCreate<mTestData>(db, {
850
+ 'ctr': this,
851
+ 'index': index ?? ''
852
+ });
853
+ testData.set({
854
+ 'test_id': id,
855
+ 'content': lCore.random(lCore.rand(8, 32)),
856
+ 'time_add': lTime.stamp()
857
+ });
858
+ await testData.create();
859
+
860
+ return [1, { 'id': id, 'index': index }];
861
+ }
862
+
863
+ public captchaFastbuild(): string {
864
+ return lCaptcha.get(400, 100).getBuffer();
865
+ }
866
+
867
+ public captchaBase64(): string {
868
+ const echo = [`<pre>const cap = lCaptcha.get(400, 100);
869
+ const phrase = cap.getPhrase();
870
+ const base64 = cap.getBase64();</pre>phrase:`];
871
+ const cap = lCaptcha.get(400, 100);
872
+ const phrase = cap.getPhrase();
873
+ const base64 = cap.getBase64();
874
+ echo.push('<pre>' + phrase + '</pre>');
875
+
876
+ echo.push('base64:');
877
+ echo.push('<pre style="white-space: pre-wrap; word-wrap: break-word; overflow-y: auto; max-height: 200px;">' + base64 + '</pre>');
878
+
879
+ echo.push('&lt;img src="&lt;?php echo $base64 ?&gt;" style="width: 200px; height: 50px;"&gt;');
880
+ echo.push('<pre><img alt="captcha" src="' + base64 + '" style="width: 200px; height: 50px;"></pre>');
881
+
882
+ return echo.join('') + this._getEnd();
883
+ }
884
+
885
+ public coreRandom(): string {
886
+ return '<pre>lCore.random(16, lCore.RANDOM_LUNS);</pre>' + lText.htmlescape(lCore.random(16, lCore.RANDOM_LUNS)) +
887
+ '<pre>lCore.random(4, lCore.RANDOM_V);</pre>' + lText.htmlescape(lCore.random(4, lCore.RANDOM_V)) +
888
+ '<pre>lCore.random(8, lCore.RANDOM_N, \'0349\');</pre>' + lText.htmlescape(lCore.random(8, lCore.RANDOM_N, '0349')) +
889
+ '<pre>lCore.random(8, lCore.RANDOM_LNU);</pre>' + lText.htmlescape(lCore.random(8, lCore.RANDOM_LUN)) +
890
+ '<pre>lCore.random(16, lCore.RANDOM_LNU);</pre>' + lText.htmlescape(lCore.random(16, lCore.RANDOM_LUN)) +
891
+ '<br><br>' + this._getEnd();
892
+ }
893
+
894
+ public coreRand(): string {
895
+ return '<pre>lCore.rand(1.2, 7.1, 1);</pre>' + lCore.rand(1.2, 7.1, 1).toString() +
896
+ '<pre>lCore.rand(1.2, 7.1, 5);</pre>' + lCore.rand(1.2, 7.1, 5).toString() +
897
+ '<pre>lCore.rand(1.298, 7.1891, 2);</pre>' + lCore.rand(1.298, 7.1891, 2).toString() +
898
+ '<br><br>' + this._getEnd();
899
+ }
900
+
901
+ public coreConvert62(): string {
902
+ return '<pre>lCore.convert62(10);</pre>' + lCore.convert62(10) +
903
+ '<pre>lCore.convert62(100);</pre>' + lCore.convert62(100) +
904
+ '<pre>lCore.convert62(1992199519982001n);</pre>' + lCore.convert62(1992199519982001n) +
905
+ '<pre>lCore.convert62(9223372036854770000n);</pre>' + lCore.convert62(9223372036854770000n) +
906
+ '<pre>lCore.convert62(9223372036854775807n);</pre>' + lCore.convert62(9223372036854775807n) +
907
+
908
+ '<pre>lCore.unconvert62(\'a\');</pre>' + lCore.unconvert62('a').toString() +
909
+ '<pre>lCore.unconvert62(\'100\');</pre>' + lCore.unconvert62('100').toString() +
910
+ '<pre>lCore.unconvert62(\'zzz\');</pre>' + lCore.unconvert62('zzz').toString() +
911
+ '<pre>lCore.unconvert62(\'ZZZ\');</pre>' + lCore.unconvert62('ZZZ').toString() +
912
+ '<pre>lCore.unconvert62(\'97HMXKQql\');</pre>' + lCore.unconvert62('97HMXKQql').toString() +
913
+ '<pre>lCore.unconvert62(\'aZl8N0y57gs\');</pre>' + lCore.unconvert62('aZl8N0y57gs').toString() +
914
+ '<pre>lCore.unconvert62(\'aZl8N0y58M7\');</pre>' + lCore.unconvert62('aZl8N0y58M7').toString() +
915
+ '<br><br>' + this._getEnd();
916
+ }
917
+
918
+ public corePurify(): string {
919
+ const html = `<html>
920
+ <head>
921
+ <title>Title</title>
922
+ </head>
923
+ <body>
924
+ <!-- h1 -->
925
+ <h1>Hello</h1>
926
+ <h2>World</h2>
927
+ <div>// abc</div>
928
+ <script>
929
+ // --- test ---
930
+ if (a) {
931
+ alert('zzz');
932
+ }
933
+ /* --- test 2 --- */
934
+ if (b) {
935
+ alert('zzz');
936
+ }
937
+ </script>
938
+ </body>
939
+ </html>`;
940
+ return '<pre>lCore.purify(`' + lText.htmlescape(html) + '`);</pre>' + lText.htmlescape(lCore.purify(html)) + '<br><br>' + this._getEnd();
941
+ }
942
+
943
+ public coreChecktype(): string {
944
+ const type1 = {
945
+ 'a': '1',
946
+ 'b': 0,
947
+ 'c': false,
948
+ 'd': {
949
+ 'e': 0,
950
+ 'f': false,
951
+ 'g': [
952
+ {
953
+ 'h': 0
954
+ }
955
+ ]
956
+ }
957
+ };
958
+ const type2 = [
959
+ {
960
+ 'a': '',
961
+ 'b': '1',
962
+ 'c': /^a.c$/
963
+ }
964
+ ];
965
+ const o1 = 0;
966
+ const o2 = {
967
+ 'a': '',
968
+ 'b': ''
969
+ };
970
+ const o3 = [{
971
+ 'a': '',
972
+ 'b': 'ok',
973
+ 'c': 'acd'
974
+ }];
975
+ const o4 = {
976
+ 'a': 'aaa',
977
+ 'b': 21424,
978
+ 'c': true,
979
+ 'd': {
980
+ 'e': 0,
981
+ 'f': false,
982
+ 'g': 'ok'
983
+ }
984
+ };
985
+ const o5 = {
986
+ 'a': 'aaa',
987
+ 'b': 21424,
988
+ 'c': true,
989
+ 'd': {
990
+ 'e': 0,
991
+ 'f': false,
992
+ 'g': [
993
+ {
994
+ 'x': 'ok'
995
+ }
996
+ ]
997
+ }
998
+ };
999
+ const o6 = {
1000
+ 'a': 'aaa',
1001
+ 'b': 21424,
1002
+ 'c': true,
1003
+ 'd': {
1004
+ 'e': 0,
1005
+ 'f': false,
1006
+ 'g': [
1007
+ {
1008
+ 'h': 138
1009
+ }
1010
+ ]
1011
+ }
1012
+ };
1013
+ const o7 = [
1014
+ {
1015
+ 'a': '',
1016
+ 'b': 'ok'
1017
+ },
1018
+ {
1019
+ 'a': '',
1020
+ 'b': 'ok2'
1021
+ },
1022
+ {
1023
+ 'a': '',
1024
+ 'b': 0
1025
+ }
1026
+ ];
1027
+ const o8 = [{
1028
+ 'a': '',
1029
+ 'b': 'ok',
1030
+ 'c': 'abc'
1031
+ }];
1032
+ return `type1:<pre>${JSON.stringify(type1)}</pre>
1033
+ type2:<pre>${JSON.stringify(type2)}</pre>
1034
+ o1:<pre>${JSON.stringify(o1)}</pre>
1035
+ lCore.checkType(o1, type1): ${lCore.checkType(o1, type1)}<br>
1036
+ lCore.checkType(o1, type2): ${lCore.checkType(o1, type2)}<br><br>
1037
+ o2:<pre>${JSON.stringify(o2)}</pre>
1038
+ lCore.checkType(o2, type1): ${lCore.checkType(o2, type1)}<br>
1039
+ lCore.checkType(o2, type2): ${lCore.checkType(o2, type2)}<br><br>
1040
+ o3:<pre>${JSON.stringify(o3)}</pre>
1041
+ lCore.checkType(o3, type1): ${lCore.checkType(o3, type1)}<br>
1042
+ lCore.checkType(o3, type2): ${lCore.checkType(o3, type2)}<br><br>
1043
+ o4:<pre>${JSON.stringify(o4)}</pre>
1044
+ lCore.checkType(o4, type1): ${lCore.checkType(o4, type1)}<br>
1045
+ lCore.checkType(o4, type2): ${lCore.checkType(o4, type2)}<br><br>
1046
+ o5:<pre>${JSON.stringify(o5)}</pre>
1047
+ lCore.checkType(o5, type1): ${lCore.checkType(o5, type1)}<br>
1048
+ lCore.checkType(o5, type2): ${lCore.checkType(o5, type2)}<br><br>
1049
+ o6:<pre>${JSON.stringify(o6)}</pre>
1050
+ lCore.checkType(o6, type1): ${lCore.checkType(o6, type1)}<br>
1051
+ lCore.checkType(o6, type2): ${lCore.checkType(o6, type2)}<br><br>
1052
+ o7:<pre>${JSON.stringify(o7)}</pre>
1053
+ lCore.checkType(o7, type1): ${lCore.checkType(o7, type1)}<br>
1054
+ lCore.checkType(o7, type2): ${lCore.checkType(o7, type2)}<br><br>
1055
+ o8:<pre>${JSON.stringify(o8)}</pre>
1056
+ lCore.checkType(o8, type1): ${lCore.checkType(o8, type1)}<br>
1057
+ lCore.checkType(o8, type2): ${lCore.checkType(o8, type2)}
1058
+ <br><br>${this._getEnd()}`;
1059
+ }
1060
+
1061
+ public coreMuid(): string {
1062
+ const ac = this._get['ac'] ? this._get['ac'] : '';
1063
+
1064
+ const echo = [
1065
+ '<a href="' + this._config.const.urlBase + 'test/core-muid">Default</a> | ' +
1066
+ '<a href="' + this._config.const.urlBase + 'test/core-muid?ac=big">Big</a> | ' +
1067
+ '<a href="' + this._config.const.urlBase + 'test">Return</a>'
1068
+ ];
1069
+
1070
+ if (ac === '') {
1071
+ let muid = lCore.muid(this);
1072
+ echo.push('<pre>lCore.muid(this);</pre>' + muid + ' (' + muid.length.toString() + ')');
1073
+
1074
+ muid = lCore.muid(this);
1075
+ echo.push('<pre>lCore.muid(this);</pre>' + muid + ' (' + muid.length.toString() + ')');
1076
+
1077
+ muid = lCore.muid(this, { 'bin': false });
1078
+ echo.push(`<pre>lCore.muid(this, { 'bin': false });</pre>` + muid + ' (' + muid.length.toString() + ')');
1079
+
1080
+ muid = lCore.muid(this, { 'len': 16 });
1081
+ echo.push(`<pre>lCore.muid(this, { 'len': 16 });</pre>` + muid + ' (' + muid.length.toString() + ')');
1082
+
1083
+ muid = lCore.muid(this, { 'len': 16, 'bin': false });
1084
+ echo.push(`<pre>lCore.muid(this, { 'len': 16, 'bin': false });</pre>` + muid + ' (' + muid.length.toString() + ')');
1085
+
1086
+ muid = lCore.muid(this, { 'insert': 'Aa', 'len': 32 });
1087
+ echo.push(`<pre>lCore.muid(this, { 'insert': 'Aa', 'len': 32 });</pre>` + muid + ' (' + muid.length.toString() + ')');
1088
+
1089
+ muid = lCore.muid(this, { 'key': 'M' });
1090
+ echo.push(`<pre>lCore.muid(this, { 'key': 'M' });</pre>` + muid + ' (' + muid.length.toString() + ')');
1091
+
1092
+ echo.push('<br><br>');
1093
+ }
1094
+ else {
1095
+ const parr: string[] = [];
1096
+ const oarr: string[] = [];
1097
+ for (let i = 0; i < 30000; ++i) {
1098
+ const muid = lCore.muid(this, { 'insert': '0' });
1099
+ const sp = oarr.indexOf(muid);
1100
+ if (sp > -1) {
1101
+ parr.push(muid + '[' + sp.toString() + ']' + oarr[sp]);
1102
+ continue;
1103
+ }
1104
+ oarr.push(muid);
1105
+ }
1106
+ echo.push(`<pre>
1107
+ const parr: string[] = [];
1108
+ const oarr: string[] = [];
1109
+ for (let i = 0; i < 30000; ++i) {
1110
+ const muid = lText.muid(this);
1111
+ const sp = oarr.indexOf(muid);
1112
+ if (sp > -1) {
1113
+ parr.push(muid + '[' + sp.toString() + ']' + oarr[sp]);
1114
+ continue;
1115
+ }
1116
+ oarr.push(muid);
1117
+ }</pre>parr length: ${parr.length}<br>oarr length: ${oarr.length}<br><br>parr:<pre>${JSON.stringify(parr)}</pre>oarr:<pre>${JSON.stringify(oarr.slice(0, 100)).slice(0, -1)}...</pre>`);
1118
+ }
1119
+
1120
+ return echo.join('') + this._getEnd();
1121
+ }
1122
+
1123
+ public async coreGetlog(): Promise<string> {
1124
+ const path = lTime.format(null, 'Y/m/d/H');
1125
+ const list = await lCore.getLog({
1126
+ 'host': this._config.const.hostname,
1127
+ 'path': path,
1128
+ 'fend': '-visit',
1129
+ });
1130
+ const echo: string[] = [];
1131
+ echo.push('<table style="width: 100%;"><tr>');
1132
+ if (list) {
1133
+ for (const row of list) {
1134
+ echo.push('<tr>');
1135
+ for (const item of row) {
1136
+ echo.push('<td>' + lText.htmlescape(item) + '</td>');
1137
+ }
1138
+ echo.push('</tr>');
1139
+ }
1140
+ }
1141
+ else {
1142
+ echo.push('<th>' + JSON.stringify(list) + '</th></tr>');
1143
+ }
1144
+ echo.push('</table>');
1145
+ return echo.join('') + '<br>' + this._getEnd();
1146
+ }
1147
+
1148
+ public async coreUpdatecode(): Promise<string> {
1149
+ const zip = `${this._config.const.dataPath}test.zip`;
1150
+ const to = '';
1151
+ const echo: string[] = [
1152
+ `zip: ${zip}<br>
1153
+ to: ${to}`
1154
+ ];
1155
+ const list = await lCore.updateCode(zip, to);
1156
+ echo.push(`<pre>const list = lCore.updateCode(zip, to);</pre>${JSON.stringify(list)}`);
1157
+ return echo.join('') + '<br><br>' + this._getEnd();
1158
+ }
1159
+
1160
+ public async coreReload(): Promise<string> {
1161
+ await lCore.sendReload();
1162
+ return 'The reload request has been sent, please review the console.<br><br>' + this._getEnd();
1163
+ }
1164
+
1165
+ public async coreRestart(): Promise<string> {
1166
+ await lCore.sendRestart();
1167
+ return 'The restart request has been sent, please review the console.<br><br>' + this._getEnd();
1168
+ }
1169
+
1170
+ public async coreGlobal(): Promise<string> {
1171
+ const ts = lTime.stamp().toString();
1172
+ const echo = [
1173
+ `<pre>lCore.global.tglobal</pre>`,
1174
+ lCore.global.tglobal === undefined ? 'undefined' : JSON.stringify(lCore.global.tglobal),
1175
+ `<pre>lCore.setGlobal('tglobal', 'ts:${ts}');</pre>`
1176
+ ];
1177
+ await lCore.setGlobal('tglobal', 'ts:' + ts);
1178
+ await lCore.sleep(50);
1179
+ echo.push(JSON.stringify(lCore.global.tglobal));
1180
+
1181
+ return echo.join('') + '<br><br>' + this._getEnd();
1182
+ }
1183
+
1184
+ public async crypto(): Promise<string> {
1185
+ const echo = ['<b>AES-256-ECB:</b>'];
1186
+
1187
+ const key = 'testkeyatestkeyatestkeyatestkeya';
1188
+ let text = lCrypto.aesEncrypt('Original text', key);
1189
+ echo.push(`<pre>const key = 'testkeyatestkeyatestkeyatestkeya';
1190
+ const text = lCrypto.aesEncrypt('Original text', key);
1191
+ JSON.stringify(text);</pre>${JSON.stringify(text)}`);
1192
+
1193
+ let orig = lCrypto.aesDecrypt(text || '', key);
1194
+ echo.push(`<pre>let orig = lCrypto.aesDecrypt(text || '', key);
1195
+ JSON.stringify(orig);</pre>${JSON.stringify(orig)}`);
1196
+
1197
+ orig = lCrypto.aesDecrypt(text || '', 'otherKey');
1198
+ echo.push(`<pre>orig = lCrypto.aesDecrypt(text || '', 'otherKey');
1199
+ JSON.stringify(orig);</pre>${JSON.stringify(orig)}`);
1200
+
1201
+ // ----------
1202
+
1203
+ echo.push('<br><br><b>AES-256-CFB:</b>');
1204
+
1205
+ const iv = 'iloveuiloveuilov';
1206
+ text = lCrypto.aesEncrypt('Original text', key, iv);
1207
+ echo.push(`<pre>const iv = 'iloveuiloveuilov';
1208
+ text = lCrypto.aesEncrypt('Original text', key, iv);
1209
+ JSON.stringify(text);</pre>${JSON.stringify(text)}`);
1210
+
1211
+ orig = lCrypto.aesDecrypt(text || '', key, iv);
1212
+ echo.push(`<pre>orig = lCrypto.aesDecrypt(text || '', key, iv);
1213
+ JSON.stringify(orig);</pre>${JSON.stringify(orig)}`);
1214
+
1215
+ orig = lCrypto.aesDecrypt(text || '', key, 'otherIv');
1216
+ echo.push(`<pre>orig = lCrypto.aesDecrypt(text || '', key, 'otherIv');
1217
+ orig ? 'true' : 'false';</pre>${orig ? 'true' : 'false'}`);
1218
+
1219
+ // ----------
1220
+
1221
+ echo.push('<br><br><b>AES-256-CBC:</b>');
1222
+
1223
+ text = lCrypto.aesEncrypt('Original text', key, iv, lCrypto.AES_256_CBC);
1224
+ echo.push(`<pre>const key = 'testkeyatestkeyatestkeyatestkeya';
1225
+ const text = lCrypto.aesEncrypt('Original text', key);
1226
+ text = lCrypto.aesEncrypt('Original text', key, iv, lCrypto.AES_256_CBC);
1227
+ JSON.stringify(text);</pre>${JSON.stringify(text)}`);
1228
+
1229
+ orig = lCrypto.aesDecrypt(text || '', key, iv, lCrypto.AES_256_CBC);
1230
+ echo.push(`<pre>orig = lCrypto.aesDecrypt(text || '', key, iv, lCrypto.AES_256_CBC);
1231
+ JSON.stringify(orig);</pre>${JSON.stringify(orig)}`);
1232
+
1233
+ orig = lCrypto.aesDecrypt(text || '', key, 'otherIv', lCrypto.AES_256_CBC);
1234
+ echo.push(`<pre>orig = lCrypto.aesDecrypt(text || '', key, 'otherIv', lCrypto.AES_256_CBC);
1235
+ JSON.stringify(orig);</pre>${JSON.stringify(orig)}`);
1236
+
1237
+ // ----------
1238
+
1239
+ const res = await lCrypto.generateKeyPair('ec', {
1240
+ 'namedCurve': 'sm2',
1241
+ 'privateKeyEncoding': {
1242
+ 'type': 'sec1'
1243
+ }
1244
+ });
1245
+ echo.push(`<pre>const res = lCrypto.generateKeyPair('ec', {
1246
+ 'namedCurve': 'sm2',
1247
+ 'privateKeyEncoding': {
1248
+ 'type': 'sec1'
1249
+ }
1250
+ });
1251
+ JSON.stringify(res);</pre>${JSON.stringify(res)}`);
1252
+
1253
+ const sign = lCrypto.sign('Hello MAIYUN.NET', res.private, 'base64', 'sm3');
1254
+ echo.push(`<pre>const sign = lCrypto.sign('Hello MAIYUN.NET', res.private, 'base64', 'sm3');
1255
+ JSON.stringify(sign);</pre>${JSON.stringify(sign)}`);
1256
+
1257
+ const r = lCrypto.verify('Hello MAIYUN.NET', res.public, Buffer.from(sign, 'base64'), 'sm3');
1258
+ echo.push(`<pre>const r = lCrypto.verify('Hello MAIYUN.NET', res.public, Buffer.from(sign, 'base64'), 'sm3');
1259
+ JSON.stringify(r);</pre>${JSON.stringify(r)}`);
1260
+
1261
+ return echo.join('') + '<br><br>' + this._getEnd();
1262
+ }
1263
+
1264
+ public async db(): Promise<types.Json> {
1265
+ const echo = [(Math.round(this._getRunTime() * 10000000) / 10000).toString()];
1266
+
1267
+ const db = lDb.get(this);
1268
+
1269
+ // --- 先获取 test 表的情况 ---
1270
+ let stmt = await db.query('SELECT * FROM `m_test` ORDER BY `id` DESC LIMIT 10;');
1271
+ if (!stmt.rows) {
1272
+ return [0, stmt.error ? (stmt.error.message + '(' + stmt.error.errno.toString() + ')') : 'Failed("m_test" not found).'];
1273
+ }
1274
+
1275
+ echo.push(`<pre>const db = lDb.get(this);
1276
+ const stmt = await db.query('SELECT * FROM \`m_test\` ORDER BY \`id\` DESC LIMIT 10;');</pre>`);
1277
+
1278
+ this._dbTable(stmt, echo);
1279
+
1280
+ echo.push('<br>ms: ' + (Math.round(this._getRunTime() * 10000000) / 10000).toString());
1281
+
1282
+ // --- 插入 test-token 的条目 ---
1283
+ const time = lTime.stamp().toString();
1284
+ let exec = await db.execute('INSERT INTO `m_test` (`token`, `point`, `time_add`) VALUES (\'test-token\', ST_POINTFROMTEXT(\'POINT(10 10)\'), \'' + time + '\');');
1285
+ let ms = (Math.round(this._getRunTime() * 10000000) / 10000).toString();
1286
+ let insertId: number = 0;
1287
+ if (exec.error?.errno === 1062) {
1288
+ insertId = (await db.query('SELECT * FROM `m_test` WHERE `token` = \'test-token\';')).rows?.[0].id ?? 0;
1289
+ ms += ', ' + (Math.round(this._getRunTime() * 10000000) / 10000).toString();
1290
+ }
1291
+ else {
1292
+ insertId = exec.packet?.insertId ?? 0;
1293
+ }
1294
+
1295
+ echo.push(`<pre>const time = lTime.stamp().toString();
1296
+ const exec = await db.execute('INSERT INTO \`m_test\` (\`token\`, \`data\`, \`time_update\`, \`time_add\`) VALUES (\\'test-token\\', ST_POINTFROMTEXT(\\'POINT(10 10)\\'), \\'' + time + '\\');');
1297
+ let insertId: number = 0;
1298
+ if (exec.error?.errno === 1062) {
1299
+ insertId = (await db.query('SELECT * FROM \`m_test\` WHERE \`token\` = \\'test-token\\';')).rows?.[0].id ?? 0;
1300
+ }
1301
+ else {
1302
+ insertId = exec.packet?.insertId ?? 0;
1303
+ }</pre>
1304
+ exec: ${JSON.stringify(exec)}<br>
1305
+ insertId: ${JSON.stringify(insertId)}<br>
1306
+ errno: ${JSON.stringify(exec.error?.errno)}<br>
1307
+ error: ${JSON.stringify(exec.error)}<br>
1308
+ ms: ${ms}<br><br>`);
1309
+
1310
+ // --- 获取最近的一条 ---
1311
+ stmt = await db.query('SELECT * FROM `m_test` ORDER BY `id` DESC LIMIT 1;');
1312
+ this._dbTable(stmt, echo);
1313
+
1314
+ // --- 再次插入 test-token 的条目 ---
1315
+ exec = await db.execute('INSERT INTO `m_test` (`token`, `point`, `time_add`) VALUES (\'test-token\', ST_POINTFROMTEXT(\'POINT(10 10)\'), \'' + time + '\');');
1316
+ insertId = exec.packet?.insertId ?? 0;
1317
+ echo.push(`<pre>exec = await db.execute('INSERT INTO \`m_test\` (\`token\`, \`point\`, \`time_add\`) VALUES (\\'test-token\\', ST_POINTFROMTEXT(\\'POINT(10 10)\\'), \\'' + time + '\\');');
1318
+ insertId = exec.packet?.insertId ?? 0;</pre>
1319
+ exec: ${JSON.stringify(exec)}<br>
1320
+ insertId: ${JSON.stringify(insertId)}<br>
1321
+ errno: ${JSON.stringify(exec.error?.errno)}<br>
1322
+ error: ${JSON.stringify(exec.error)}<br>
1323
+ ms: ${(Math.round(this._getRunTime() * 10000000) / 10000).toString()}<br>`);
1324
+
1325
+ // --- 依据唯一键替换值 ---
1326
+ exec = await db.execute('REPLACE INTO `m_test` (`token`, `point`, `time_add`) VALUES (\'test-token\', ST_POINTFROMTEXT(\'POINT(20 20)\'), \'' + time + '\');');
1327
+ insertId = exec.packet?.insertId ?? 0;
1328
+ echo.push(`<pre>exec = await db.execute('REPLACE INTO \`m_session\` (\`token\`, \`point\`, \`time_add\`) VALUES (\\'test-token\\', ST_POINTFROMTEXT(\\'POINT(20 20)\\'), \\'' + time + '\\');');
1329
+ insertId = exec.packet?.insertId ?? 0;</pre>
1330
+ exec: ${JSON.stringify(exec)}<br>
1331
+ insertId: ${JSON.stringify(insertId)}<br>
1332
+ errno: ${JSON.stringify(exec.error?.errno)}<br>
1333
+ error: ${JSON.stringify(exec.error)}<br>
1334
+ ms: ${(Math.round(this._getRunTime() * 10000000) / 10000).toString()}<br><br>`);
1335
+
1336
+ // --- 显示近 10 条 ---
1337
+ stmt = await db.query('SELECT * FROM `m_test` ORDER BY `id` DESC LIMIT 10;');
1338
+ this._dbTable(stmt, echo);
1339
+
1340
+ // --- explain 开始 ---
1341
+ const explain = 'EXPLAIN';
1342
+ stmt = await db.query(explain + ' SELECT * FROM `m_test` LIMIT 10;');
1343
+ echo.push(`<pre>stmt = await db.query('${explain} SELECT * FROM \`m_test\` LIMIT 10;');</pre>`);
1344
+ this._dbTable(stmt, echo);
1345
+
1346
+ echo.push('<br>ms: ' + (Math.round(this._getRunTime() * 10000000) / 10000).toString());
1347
+
1348
+ // --- 删除测试添加的 token ---
1349
+ exec = await db.execute('DELETE FROM `m_test` WHERE `token` = \'test-token\';');
1350
+ echo.push(`<pre>exec = await db.execute('DELETE FROM \`m_test\` WHERE \`token\` = \\'test-token\\';');</pre>
1351
+ exec: ${JSON.stringify(exec)}<br><br>`);
1352
+
1353
+ stmt = await db.query('SELECT * FROM `m_test` ORDER BY `id` DESC LIMIT 10;');
1354
+ this._dbTable(stmt, echo);
1355
+
1356
+ return echo.join('') + '<br>queries: ' + db.getQueries().toString() + '<br>' + this._getEnd();
1357
+ }
1358
+
1359
+ private _dbTable(stmt: lDb.IData, echo: types.Json[]): void {
1360
+ echo.push('<table style="width: 100%;"><tr>');
1361
+ if (stmt.rows) {
1362
+ for (const item of stmt.fields) {
1363
+ echo.push('<th>' + lText.htmlescape(item.name) + '</th>');
1364
+ }
1365
+ echo.push('</tr>');
1366
+
1367
+ for (const row of stmt.rows) {
1368
+ echo.push('<tr>');
1369
+ for (const key in row) {
1370
+ const val = row[key];
1371
+ echo.push('<td>' + (val === null ? 'null' : lText.htmlescape(JSON.stringify(val))) + '</td>');
1372
+ }
1373
+ echo.push('</tr>');
1374
+ }
1375
+ }
1376
+ else {
1377
+ echo.push('<th>No data</th></tr>');
1378
+ }
1379
+ echo.push('</table>');
1380
+ }
1381
+
1382
+ public async kv(): Promise<types.Json> {
1383
+ const kv = lKv.get(this);
1384
+ if (!await kv.ping()) {
1385
+ return [0, 'Failed.'];
1386
+ }
1387
+ const value = this._get['value'] ?? '';
1388
+ const ac = this._get['ac'] ?? '';
1389
+
1390
+ const echo = [`<pre>const kv = lKv.get(this);
1391
+ if (!await kv.ping()) {
1392
+ return [0, 'Failed.'];
1393
+ }
1394
+ JSON.stringify(await kv.ping());</pre>${JSON.stringify(await kv.ping())}`];
1395
+
1396
+ if (ac == 'delete') {
1397
+ echo.push("<pre>JSON.stringify(await kv.get('test'));</pre>" + JSON.stringify(await kv.get('test')));
1398
+
1399
+ echo.push("<pre>JSON.stringify(await kv.del('test'));</pre>" + JSON.stringify(await kv.del('test')));
1400
+
1401
+ echo.push("<pre>JSON.stringify(await kv.get('test'));</pre>" + JSON.stringify(await kv.get('test')));
1402
+ }
1403
+ else if (ac === 'ttl') {
1404
+ echo.push("<pre>JSON.stringify(await kv.ttl('test'));</pre>" + JSON.stringify(await kv.ttl('test')));
1405
+ echo.push("<pre>JSON.stringify(await kv.pttl('test'));</pre>" + JSON.stringify(await kv.pttl('test')));
1406
+ echo.push("<pre>JSON.stringify(await kv.set('test', 'ttl', 10));</pre>" + JSON.stringify(await kv.set('test', 'ttl', 10)));
1407
+ echo.push("<pre>JSON.stringify(await kv.ttl('test'));</pre>" + JSON.stringify(await kv.ttl('test')));
1408
+ echo.push("<pre>JSON.stringify(await kv.pttl('test'));</pre>" + JSON.stringify(await kv.pttl('test')));
1409
+ }
1410
+ else if (ac == 'incr-decr-replace') {
1411
+ echo.push("<pre>JSON.stringify(await kv.del('test'));</pre>" + JSON.stringify(await kv.del('test')));
1412
+
1413
+ echo.push("<pre>JSON.stringify(await kv.replace('test', 'QAQ'));</pre>" + JSON.stringify(await kv.replace('test', 'QAQ')));
1414
+
1415
+ echo.push("<pre>JSON.stringify(await kv.incr('test'));</pre>" + JSON.stringify(await kv.incr('test')));
1416
+
1417
+ echo.push("<pre>JSON.stringify(await kv.get('test'));</pre>" + JSON.stringify(await kv.get('test')));
1418
+
1419
+ echo.push("<pre>JSON.stringify(await kv.set('test', 666));</pre>" + JSON.stringify(await kv.set('test', 666)));
1420
+
1421
+ echo.push("<pre>JSON.stringify(await kv.incr('test'));</pre>" + JSON.stringify(await kv.incr('test')));
1422
+
1423
+ echo.push("<pre>JSON.stringify(await kv.get('test'));</pre>" + JSON.stringify(await kv.get('test')));
1424
+
1425
+ echo.push("<pre>JSON.stringify(await kv.decr('test', 10));</pre>" + JSON.stringify(await kv.decr('test', 10)));
1426
+
1427
+ echo.push("<pre>JSON.stringify(await kv.get('test'));</pre>" + JSON.stringify(await kv.get('test')));
1428
+
1429
+ echo.push("<pre>JSON.stringify(await kv.replace('test', 111));</pre>" + JSON.stringify(await kv.replace('test', 111)));
1430
+
1431
+ echo.push("<pre>JSON.stringify(await kv.get('test'));</pre>" + JSON.stringify(await kv.get('test')));
1432
+
1433
+ echo.push("<pre>JSON.stringify(await kv.replace('test', 'QAQ'));</pre>" + JSON.stringify(await kv.replace('test', 'QAQ')));
1434
+
1435
+ echo.push("<pre>SON.stringify(await kv.incr('test', 10));</pre>" + JSON.stringify(await kv.incr('test', 10)));
1436
+
1437
+ echo.push("<pre>JSON.stringify(await kv.get('test'));</pre>" + JSON.stringify(await kv.get('test')));
1438
+ }
1439
+ else if (ac === 'append-prepend') {
1440
+ echo.push("<pre>SON.stringify(await kv.prepend('test', '0'));</pre>" + JSON.stringify(await kv.prepend('test', '0')));
1441
+
1442
+ echo.push("<pre>JSON.stringify(await kv.get('test'));</pre>" + JSON.stringify(await kv.get('test')));
1443
+
1444
+ echo.push("<pre>JSON.stringify(await kv.set('test', 'bbb'));</pre>" + JSON.stringify(await kv.set('test', 'bbb')));
1445
+
1446
+ echo.push("<pre>JSON.stringify(await kv.append('test', 'end'));</pre>" + JSON.stringify(await kv.append('test', 'end')));
1447
+
1448
+ echo.push("<pre>JSON.stringify(await kv.get('test'));</pre>" + JSON.stringify(await kv.get('test')));
1449
+
1450
+ echo.push("<pre>JSON.stringify(await kv.prepend('test', 'pre'));</pre>" + JSON.stringify(await kv.prepend('test', 'pre')));
1451
+
1452
+ echo.push("<pre>JSON.stringify(await kv.get('test'));</pre>" + JSON.stringify(await kv.get('test')));
1453
+
1454
+ echo.push("<pre>JSON.stringify(await kv.add('test', 'aaa'));</pre>" + JSON.stringify(await kv.add('test', 'aaa')));
1455
+
1456
+ echo.push("<pre>JSON.stringify(await kv.append('tmp_test', 'hehe'));</pre>" + JSON.stringify(await kv.append('tmp_test', 'hehe')));
1457
+
1458
+ echo.push("<pre>JSON.stringify(await kv.get('tmp_test'));</pre>" + JSON.stringify(await kv.get('tmp_test')));
1459
+
1460
+ echo.push("<pre>JSON.stringify(await kv.del('tmp_test'));</pre>" + JSON.stringify(await kv.del('tmp_test')));
1461
+ }
1462
+ else if (ac === 'hash') {
1463
+ echo.push("<pre>JSON.stringify(await kv.hSet('hTest', 'name', 'Cheng Xin'));</pre>" + JSON.stringify(await kv.hSet('hTest', 'name', 'Cheng Xin')));
1464
+
1465
+ echo.push("<pre>JSON.stringify(await kv.hSet('hTest', 'age', '16', 'nx'));</pre>" + JSON.stringify(await kv.hSet('hTest', 'age', '16', 'nx')));
1466
+
1467
+ echo.push(`<pre>JSON.stringify(await kv.hMSet('hTest', {
1468
+ 'age': '16',
1469
+ 'sex': 'female'
1470
+ }));</pre>`);
1471
+ echo.push(JSON.stringify(await kv.hMSet('hTest', {
1472
+ 'age': '16',
1473
+ 'sex': 'female'
1474
+ })));
1475
+
1476
+ echo.push("<pre>JSON.stringify(await kv.hSet('hTest', 'age', '16', 'nx'));</pre>" + JSON.stringify(await kv.hSet('hTest', 'age', '16', 'nx')));
1477
+
1478
+ echo.push("<pre>JSON.stringify(await kv.hGet('hTest', 'name'));</pre>" + JSON.stringify(await kv.hGet('hTest', 'name')));
1479
+
1480
+ echo.push("<pre>JSON.stringify(await kv.hDel('hTest', 'name'));</pre>" + JSON.stringify(await kv.hDel('hTest', 'name')));
1481
+
1482
+ echo.push(`<pre>JSON.stringify(await kv.hMSet('hTest', {
1483
+ 'ok1': 'bye',
1484
+ 'ok2': [
1485
+ '1', '2', '5', '8', '0'
1486
+ ]
1487
+ }));</pre>`);
1488
+ echo.push(JSON.stringify(await kv.hMSet('hTest', {
1489
+ 'ok1': 'bye',
1490
+ 'ok2': [
1491
+ '1', '2', '5', '8', '0'
1492
+ ]
1493
+ })));
1494
+
1495
+ echo.push("<pre>JSON.stringify(await kv.hSet('hTest', 'ok1', ['a', 'b']));</pre>" + JSON.stringify(await kv.hSet('hTest', 'ok1', ['a', 'b'])));
1496
+
1497
+ echo.push("<pre>JSON.stringify(await kv.hGetAll('hTest'));</pre>" + JSON.stringify(await kv.hGetAll('hTest')));
1498
+
1499
+ echo.push("<pre>JSON.stringify(await kv.hGetJson('hTest', 'ok1'));</pre>" + JSON.stringify(await kv.hGetJson('hTest', 'ok1')));
1500
+
1501
+ echo.push("<pre>JSON.stringify(await kv.hKeys('hTest'));</pre>" + JSON.stringify(await kv.hKeys('hTest')));
1502
+
1503
+ echo.push("<pre>JSON.stringify(await kv.hExists('hTest', 'age'));</pre>" + JSON.stringify(await kv.hExists('hTest', 'age')));
1504
+
1505
+ echo.push("<pre>SON.stringify(await kv.hMGet('hTest', ['age', 'sex', 'school']));</pre>" + JSON.stringify(await kv.hMGet('hTest', ['age', 'sex', 'school'])));
1506
+
1507
+ echo.push("<pre>JSON.stringify(await kv.del('hTest'));</pre>" + JSON.stringify(await kv.del('hTest')));
1508
+
1509
+ echo.push("<pre>JSON.stringify(await kv.hGet('hTest', 'name'));</pre>" + JSON.stringify(await kv.hGet('hTest', 'name')));
1510
+
1511
+ echo.push("<pre>JSON.stringify(await kv.hGetAll('hTest'));</pre>" + JSON.stringify(await kv.hGetAll('hTest')));
1512
+ }
1513
+ else if (ac === 'other') {
1514
+ echo.push(`<pre>for (let i = 0; i < 50; ++i) {
1515
+ await kv.add('t' + i.toString(), i, 10);
1516
+ }
1517
+ echo.push('Added.');</pre>`);
1518
+ for (let i = 0; i < 50; ++i) {
1519
+ await kv.add('t' + i.toString(), i, 10);
1520
+ }
1521
+ echo.push('Added.');
1522
+
1523
+ echo.push("<pre>JSON.stringify(await kv.keys('t*'));</pre>" + JSON.stringify(await kv.keys('t*')));
1524
+
1525
+ echo.push('<pre>JSON.stringify(await kv.scan());</pre>' + JSON.stringify(await kv.scan()));
1526
+
1527
+ echo.push(`<pre>let cursor = 0;
1528
+ while (true) {
1529
+ echo.push('WHILE (' + JSON.stringify(cursor) + ')&lt;br&gt;');
1530
+ const r = await kv.scan(cursor, '*2*', 5);
1531
+ if (r === false || r.nextCursor === 0) {
1532
+ echo.push('DONE&lt;br&gt;');
1533
+ break;
1534
+ }
1535
+ echo.push(JSON.stringify(r.items) + '&lt;br&gt;');
1536
+ cursor = r.nextCursor;
1537
+ }
1538
+ echo[echo.length - 1] = echo[echo.length - 1].slice(0, -4);</pre>`);
1539
+ let cursor = 0;
1540
+ while (true) {
1541
+ echo.push('WHILE (' + JSON.stringify(cursor) + ')<br>');
1542
+ const r = await kv.scan(cursor, '*2*', 5);
1543
+ if (r === false || r.nextCursor === 0) {
1544
+ echo.push('DONE<br>');
1545
+ break;
1546
+ }
1547
+ echo.push(JSON.stringify(r.items) + '<br>');
1548
+ cursor = r.nextCursor;
1549
+ }
1550
+ echo[echo.length - 1] = echo[echo.length - 1].slice(0, -4);
1551
+ }
1552
+ else {
1553
+ // --- default ---
1554
+ echo.push("<pre>JSON.stringify(await kv.exists(['test', 'heheda']));</pre>" + JSON.stringify(await kv.exists(['test', 'heheda'])));
1555
+
1556
+ echo.push("<pre>JSON.stringify(await kv.mGet(['test', 'heheda']));</pre>" + JSON.stringify(await kv.mGet(['test', 'heheda'])));
1557
+
1558
+ echo.push("<pre>JSON.stringify(await kv.get('test'));</pre>" + JSON.stringify(await kv.get('test')));
1559
+
1560
+ echo.push("<pre>JSON.stringify(await kv.set('test', $value ? $value : 'ok'));</pre>" + JSON.stringify(await kv.set('test', value ? value : 'ok')));
1561
+
1562
+ echo.push("<pre>JSON.stringify(await kv.get('test'));</pre>" + JSON.stringify(await kv.get('test')));
1563
+ }
1564
+
1565
+ return '<a href="' + this._config.const.urlBase + 'test/kv">Default</a> | ' +
1566
+ '<a href="' + this._config.const.urlBase + 'test/kv?value=aaa">Set "aaa"</a> | ' +
1567
+ '<a href="' + this._config.const.urlBase + 'test/kv?value=bbb">Set "bbb"</a> | ' +
1568
+ '<a href="' + this._config.const.urlBase + 'test/kv?ac=delete">Delete</a> | ' +
1569
+ '<a href="' + this._config.const.urlBase + 'test/kv?ac=ttl">ttl</a> | ' +
1570
+ '<a href="' + this._config.const.urlBase + 'test/kv?ac=incr-decr-replace">Incr/Decr/Replace</a> | ' +
1571
+ '<a href="' + this._config.const.urlBase + 'test/kv?ac=append-prepend">Append/Prepend</a> | ' +
1572
+ '<a href="' + this._config.const.urlBase + 'test/kv?ac=hash">Hash</a> | ' +
1573
+ '<a href="' + this._config.const.urlBase + 'test/kv?ac=other">Other</a> | ' +
1574
+ '<a href="' + this._config.const.urlBase + 'test">Return</a>' + echo.join('') + '<br><br>' + this._getEnd();
1575
+ }
1576
+
1577
+ public async net(): Promise<string> {
1578
+ const echo = [];
1579
+
1580
+ const res = await lNet.get('https://cdn.jsdelivr.net/npm/deskrt@2.0.10/package.json');
1581
+ echo.push(`<pre>Net.get('https://cdn.jsdelivr.net/npm/deskrt@2.0.10/package.json');</pre>
1582
+ headers: <pre>${JSON.stringify(res.headers, null, 4)}</pre>
1583
+ content: <pre>${(await res.getContent())?.toString() ?? 'null'}</pre>
1584
+ error: ${JSON.stringify(res.error)}`);
1585
+
1586
+ return echo.join('') + '<br><br>' + this._getEnd();
1587
+ }
1588
+
1589
+ public async netPipe(): Promise<types.Json> {
1590
+ const echo = [];
1591
+
1592
+ const res = await lNet.get('https://cdn.jsdelivr.net/npm/deskrt@2.0.10/package.json');
1593
+ echo.push(
1594
+ `<pre>Net.get('https://cdn.jsdelivr.net/npm/deskrt@2.0.10/package.json');</pre>
1595
+ headers: <pre>${JSON.stringify(res.headers, null, 4)}</pre>
1596
+ content: <pre>`,
1597
+ res,
1598
+ `</pre>
1599
+ error: ${JSON.stringify(res.error)}
1600
+ <br><br>` + this._getEnd()
1601
+ );
1602
+
1603
+ return echo;
1604
+ }
1605
+
1606
+ public async netPost(): Promise<types.Json> {
1607
+ const echo = [];
1608
+
1609
+ const res = await lNet.post(this._internalUrl + 'test/netPost1', { 'a': '1', 'b': '2', 'c': ['1', '2', '3'] });
1610
+ echo.push(`<pre>lNet.post('${this._internalUrl}test/netPost1', { 'a': '1', 'b': '2', 'c': ['1', '2', '3'] });</pre>
1611
+ headers: <pre>${JSON.stringify(res.headers, null, 4)}</pre>
1612
+ content: <pre>${(await res.getContent())?.toString() ?? 'null'}</pre>
1613
+ error: ${JSON.stringify(res.error)}`);
1614
+
1615
+ return echo.join('') + '<br><br>' + this._getEnd();
1616
+ }
1617
+
1618
+ public netPost1(): string {
1619
+ return `_post:\n\n${JSON.stringify(this._post)}\n\nRequest headers:\n\n${JSON.stringify(this._headers, null, 4)}\n\nIP: ${this._req.socket.remoteAddress ?? ''}`;
1620
+ }
1621
+
1622
+ public async netPostString(): Promise<string> {
1623
+ const echo = [];
1624
+
1625
+ const res = await lNet.post(this._internalUrl + 'test/netPostString1', 'HeiHei');
1626
+ echo.push(`<pre>lNet.post('${this._internalUrl}test/netPostString1', 'HeiHei');</pre>
1627
+ headers: <pre>${JSON.stringify(res.headers, null, 4)}</pre>
1628
+ content: <pre>${(await res.getContent())?.toString() ?? 'null'}</pre>
1629
+ error: ${JSON.stringify(res.error)}`);
1630
+
1631
+ return echo.join('') + '<br><br>' + this._getEnd();
1632
+ }
1633
+
1634
+ public netPostString1(): types.Json[] {
1635
+ return [1, this._input];
1636
+ }
1637
+
1638
+ public async netOpen(): Promise<types.Json> {
1639
+ const echo = [];
1640
+
1641
+ const res = await lNet.open(this._internalUrl + 'test/netPost1').post().data({ 'a': '2', 'b': '0', 'c': ['0', '1', '3'] }).request();
1642
+ echo.push(`<pre>lNet.open('${this._internalUrl}test/netPost1').post().data({ 'a': '2', 'b': '0', 'c': ['0', '1', '3'] }).request();</pre>
1643
+ headers: <pre>${JSON.stringify(res.headers, null, 4)}</pre>
1644
+ content: <pre>${(await res.getContent())?.toString() ?? 'null'}</pre>
1645
+ error: ${JSON.stringify(res.error)}`);
1646
+
1647
+ return echo.join('') + this._getEnd();
1648
+ }
1649
+
1650
+ public async netFormTest(): Promise<string> {
1651
+ if (!await this._handleFormData()) {
1652
+ return '';
1653
+ }
1654
+ const echo = [
1655
+ '<pre>',
1656
+ JSON.stringify(this._post, null, 4),
1657
+ '\n-----\n',
1658
+ JSON.stringify(this._files, null, 4),
1659
+ '</pre>'
1660
+ ];
1661
+ echo.push(`<form enctype="multipart/form-data" method="post">
1662
+ text a: <input type="text" name="a" value="a1"> <input type="text" name="a" value="a2"><br>
1663
+ file b: <input type="file" name="b"><br>
1664
+ file c: <input type="file" name="c"><input type="file" name="c"><br>
1665
+ fi d[]: <input type="file" name="d[]"><input type="file" name="d[]"><br>
1666
+ <input type="submit" value="Upload">
1667
+ </form>
1668
+ <hr>
1669
+ <form method="post">
1670
+ name a: <input type="text" name="a" value="a&1"> <input type="text" name="a" value="a&2"><br>
1671
+ na b[]: <input type="text" name="b[]" value="b1"> <input type="text" name="b[]" value="b2"><br>
1672
+ name d: <input type="text" name="d" value="d"><br>
1673
+ <input type="submit" value="Default post">
1674
+ </form>`);
1675
+
1676
+ return echo.join('') + this._getEnd();
1677
+ }
1678
+
1679
+ public async netUpload(): Promise<string> {
1680
+ const echo = [];
1681
+
1682
+ const fd = lNet.getFormData();
1683
+ fd.putString('a', '1');
1684
+ await fd.putFile('file', kebab.LIB_PATH + 'net/cacert.pem');
1685
+ await fd.putFile('multiple', kebab.LIB_PATH + 'net/cacert.pem');
1686
+ await fd.putFile('multiple', kebab.LIB_PATH + 'net/cacert.pem');
1687
+ const res = await lNet.post(this._internalUrl + 'test/net-upload1', fd);
1688
+ echo.push(`<pre>const fd = lNet.getFormData();
1689
+ fd.putString('a', '1');
1690
+ await fd.putFile('file', def.LIB_PATH + 'net/cacert.pem');
1691
+ await fd.putFile('multiple', def.LIB_PATH + 'net/cacert.pem');
1692
+ await fd.putFile('multiple', def.LIB_PATH + 'net/cacert.pem');
1693
+ lNet.post('${this._internalUrl}test/net-upload1', fd);</pre>
1694
+ headers: <pre>${JSON.stringify(res.headers, null, 4)}</pre>
1695
+ content: <pre>${(await res.getContent())?.toString() ?? 'null'}</pre>
1696
+ error: ${JSON.stringify(res.error)}`);
1697
+
1698
+ return echo.join('') + '<br><br>' + this._getEnd();
1699
+ }
1700
+
1701
+ public async netUpload1(): Promise<string> {
1702
+ if (!await this._handleFormData()) {
1703
+ return '{}';
1704
+ }
1705
+ return JSON.stringify(this._post, null, 4) + '\n\n' + JSON.stringify(this._files, null, 4);
1706
+ }
1707
+
1708
+ public async netCookie(): Promise<string> {
1709
+ const echo = [];
1710
+
1711
+ const cookie = {};
1712
+ let res = await lNet.get(this._internalUrl + 'test/net-cookie1', {
1713
+ 'cookie': cookie
1714
+ });
1715
+ echo.push(`<pre>const cookie = {};
1716
+ lNet.get(this._internalUrl + 'test/net-cookie1', {
1717
+ 'cookie': cookie
1718
+ });</pre>
1719
+ headers: <pre>${JSON.stringify(res.headers, null, 4)}</pre>
1720
+ content: <pre>${(await res.getContent())?.toString() ?? 'null'}</pre>
1721
+ cookie: <pre>${JSON.stringify(cookie, null, 4)}</pre><hr>`);
1722
+
1723
+ res = await lNet.get(this._internalUrl + 'test/net-cookie2', {
1724
+ 'cookie': cookie
1725
+ });
1726
+ echo.push(`<pre>lNet.get(this._internalUrl + 'test/net-cookie2', {
1727
+ 'cookie': cookie
1728
+ });</pre>
1729
+ headers: <pre>${JSON.stringify(res.headers, null, 4)}</pre>
1730
+ content: <pre>${(await res.getContent())?.toString() ?? 'null'}</pre>`);
1731
+
1732
+ lNet.setCookie(cookie, 'custom1', 'abc1', this._config.const.host);
1733
+ lNet.setCookie(cookie, 'custom2', 'abc2', '172.17.0.1');
1734
+ res = await lNet.get(this._internalUrl + 'test/net-cookie2', {
1735
+ 'cookie': cookie
1736
+ });
1737
+ echo.push(`<pre>lNet.setCookie(cookie, 'custom1', 'abc1', ${this._config.const.host});
1738
+ lNet.setCookie(cookie, 'custom2', 'abc2', '172.17.0.1');
1739
+ lNet.get(this._internalUrl + 'test/net-cookie2', {
1740
+ 'cookie': cookie
1741
+ });</pre>
1742
+ headers: <pre>${JSON.stringify(res.headers, null, 4)}</pre>
1743
+ content: <pre>${(await res.getContent())?.toString() ?? 'null'}</pre>`);
1744
+
1745
+ return echo.join('') + this._getEnd();
1746
+ }
1747
+
1748
+ public netCookie1(): string {
1749
+ lCore.setCookie(this, 'test0', 'session');
1750
+ lCore.setCookie(this, 'test1', 'normal', {
1751
+ 'ttl': 10
1752
+ });
1753
+ lCore.setCookie(this, 'test2', 'baidu.com', {
1754
+ 'ttl': 20,
1755
+ 'path': '/',
1756
+ 'domain': 'baidu.com'
1757
+ });
1758
+ lCore.setCookie(this, 'test3', this._config.const.hostname, {
1759
+ 'ttl': 30,
1760
+ 'path': '/',
1761
+ 'domain': this._config.const.hostname
1762
+ });
1763
+ lCore.setCookie(this, 'test4', '/ok/', {
1764
+ 'ttl': 40,
1765
+ 'path': '/ok/'
1766
+ });
1767
+ lCore.setCookie(this, 'test5', 'secure', {
1768
+ 'ttl': 50,
1769
+ 'ssl': true
1770
+ });
1771
+ lCore.setCookie(this, 'test6', '0.1', {
1772
+ 'ttl': 40,
1773
+ 'path': '/',
1774
+ 'domain': '0.1'
1775
+ });
1776
+ lCore.setCookie(this, 'test7', 'localhost', {
1777
+ 'ttl': 30,
1778
+ 'path': '/',
1779
+ 'domain': 'localhost'
1780
+ });
1781
+ lCore.setCookie(this, 'test8', 'com', {
1782
+ 'ttl': 20,
1783
+ 'path': '/',
1784
+ 'domain': 'com'
1785
+ });
1786
+ lCore.setCookie(this, 'test9', 'com.cn', {
1787
+ 'ttl': 10,
1788
+ 'path': '/',
1789
+ 'domain': 'com.cn'
1790
+ });
1791
+ lCore.setCookie(this, 'test10', 'httponly', {
1792
+ 'ttl': 60,
1793
+ 'httponly': true
1794
+ });
1795
+ return `lCore.setCookie(this, 'test0', 'session');
1796
+ lCore.setCookie(this, 'test1', 'normal', {
1797
+ 'ttl': 10
1798
+ });
1799
+ lCore.setCookie(this, 'test2', 'baidu.com', {
1800
+ 'ttl': 20,
1801
+ 'path': '/',
1802
+ 'domain': 'baidu.com'
1803
+ });
1804
+ lCore.setCookie(this, 'test3', this._config.const.hostname, {
1805
+ 'ttl': 30,
1806
+ 'path': '/',
1807
+ 'domain': this._config.const.hostname
1808
+ });
1809
+ lCore.setCookie(this, 'test4', '/ok/', {
1810
+ 'ttl': 40,
1811
+ 'path': '/ok/'
1812
+ });
1813
+ lCore.setCookie(this, 'test5', 'secure', {
1814
+ 'ttl': 50,
1815
+ 'ssl': true
1816
+ });
1817
+ lCore.setCookie(this, 'test6', '0.1', {
1818
+ 'ttl': 40,
1819
+ 'path': '/',
1820
+ 'domain': '0.1'
1821
+ });
1822
+ lCore.setCookie(this, 'test7', 'localhost', {
1823
+ 'ttl': 30,
1824
+ 'path': '/',
1825
+ 'domain': 'localhost'
1826
+ });
1827
+ lCore.setCookie(this, 'test8', 'com', {
1828
+ 'ttl': 20,
1829
+ 'path': '/',
1830
+ 'domain': 'com'
1831
+ });
1832
+ lCore.setCookie(this, 'test9', 'com.cn', {
1833
+ 'ttl': 10,
1834
+ 'path': '/',
1835
+ 'domain': 'com.cn'
1836
+ });
1837
+ lCore.setCookie(this, 'test10', 'httponly', {
1838
+ 'ttl': 60,
1839
+ 'httponly': true
1840
+ });`;
1841
+ }
1842
+
1843
+ public netCookie2(): string {
1844
+ return 'this._cookie: \n\n' + JSON.stringify(this._cookie, null, 4);
1845
+ }
1846
+
1847
+ public async netSave(): Promise<string> {
1848
+ const echo = [];
1849
+
1850
+ const res = await lNet.get('https://cdn.jsdelivr.net/npm/deskrt@2.0.10/package.json', {
1851
+ 'follow': 5,
1852
+ 'save': kebab.LOG_CWD + 'test-must-remove.json'
1853
+ });
1854
+ echo.push(`<pre>lNet.get('https://cdn.jsdelivr.net/npm/deskrt@2.0.10/package.json', {
1855
+ 'follow': 5,
1856
+ 'save': def.LOG_PATH + 'test-must-remove.json'
1857
+ });</pre>
1858
+ headers: <pre>${JSON.stringify(res.headers, null, 4)}</pre>
1859
+ content: <pre>${(await res.getContent())?.toString() ?? 'null'}</pre>
1860
+ error: ${JSON.stringify(res.error)}</pre>`);
1861
+
1862
+ return echo.join('') + this._getEnd();
1863
+ }
1864
+
1865
+ public async netFollow(): Promise<string> {
1866
+ const echo = [];
1867
+
1868
+ const res = await lNet.post(this._internalUrl + 'test/net-follow1', {
1869
+ 'a': '1',
1870
+ 'b': '2'
1871
+ }, {
1872
+ 'follow': 5
1873
+ });
1874
+ echo.push(`<pre>lNet.post(this._internalUrl + 'test/net-follow1', {
1875
+ 'a': '1',
1876
+ 'b': '2'
1877
+ }, {
1878
+ 'follow': 5
1879
+ });</pre>
1880
+ headers: <pre>${JSON.stringify(res.headers, null, 4)}</pre>
1881
+ content: <pre>${(await res.getContent())?.toString() ?? 'null'}</pre>
1882
+ error: ${JSON.stringify(res.error)}</pre>`);
1883
+
1884
+ return echo.join('') + this._getEnd();
1885
+ }
1886
+
1887
+ public netFollow1(): void {
1888
+ this._location('test/net-follow2');
1889
+ }
1890
+
1891
+ public netFollow2(): types.Json {
1892
+ return [1, { 'post': (this._post['a'] as string) + ',' + (this._post['b'] as string) }];
1893
+ }
1894
+
1895
+ public async netReuse(): Promise<string> {
1896
+ const echo = [];
1897
+
1898
+ echo.push('<strong>Reuse:</strong>');
1899
+
1900
+ let time0 = Date.now();
1901
+ await lNet.get('https://cdn.jsdelivr.net/npm/deskrt@2.0.10/package.json');
1902
+ let time1 = Date.now();
1903
+ echo.push("<pre>lNet.get('https://cdn.jsdelivr.net/npm/deskrt@2.0.10/package.json');</pre>" + Math.round(time1 - time0).toString() + 'ms.');
1904
+
1905
+ time0 = Date.now();
1906
+ await lNet.get('https://cdn.jsdelivr.net/npm/deskrt@2.0.10/README.md');
1907
+ time1 = Date.now();
1908
+ echo.push("<pre>lNet.get('https://cdn.jsdelivr.net/npm/deskrt@2.0.10/README.md');</pre>" + Math.round(time1 - time0).toString() + 'ms.');
1909
+
1910
+ time0 = Date.now();
1911
+ await lNet.get('https://cdn.jsdelivr.net/npm/deskrt@2.0.10/LICENSE');
1912
+ time1 = Date.now();
1913
+ echo.push("<pre>lNet.get('https://cdn.jsdelivr.net/npm/deskrt@2.0.10/LICENSE');</pre>" + Math.round(time1 - time0).toString() + 'ms.<hr>');
1914
+
1915
+ return echo.join('') + this._getEnd();
1916
+ }
1917
+
1918
+ public async netError(): Promise<string> {
1919
+ const echo = [];
1920
+
1921
+ const res = await lNet.get('https://192.111.000.222/xxx.zzz');
1922
+ echo.push(`<pre>lNet.get('https://192.111.000.222/xxx.zzz');</pre>
1923
+ headers: <pre>${JSON.stringify(res.headers, null, 4)}</pre>
1924
+ content: <pre>${(await res.getContent())?.toString() ?? 'null'}</pre>
1925
+ error: <pre>${JSON.stringify(res.error, null, 4)}</pre>`);
1926
+
1927
+ return echo.join('') + this._getEnd();
1928
+ }
1929
+
1930
+ public async netHosts(): Promise<string> {
1931
+ const echo = [];
1932
+
1933
+ const res = await lNet.get('http://nodejs.org:' + this._config.const.hostport.toString() + this._config.const.urlBase + 'test', {
1934
+ 'hosts': {
1935
+ 'nodejs.org': '127.0.0.1'
1936
+ }
1937
+ });
1938
+ echo.push(`<pre>lNet.get('http://nodejs.org:${this._config.const.hostport.toString() + this._config.const.urlBase}test', {
1939
+ 'hosts': {
1940
+ 'nodejs.org': '127.0.0.1'
1941
+ }
1942
+ });</pre>
1943
+ headers: <pre>${JSON.stringify(res.headers, null, 4)}</pre>
1944
+ content: <pre>${lText.htmlescape((await res.getContent())?.toString() ?? '')}</pre>
1945
+ error: <pre>${JSON.stringify(res.error, null, 4)}</pre>`);
1946
+
1947
+ return echo.join('') + this._getEnd();
1948
+ }
1949
+
1950
+ public async netRproxy(): Promise<string | boolean> {
1951
+ if (await lNet.rproxy(this, {
1952
+ 'test/net-rproxy/': 'https://cdn.jsdelivr.net/npm/deskrt@2.0.10/'
1953
+ })) {
1954
+ return false;
1955
+ }
1956
+ return 'Nothing';
1957
+ }
1958
+
1959
+ public async netMproxy(): Promise<string | boolean> {
1960
+ const echo = [];
1961
+ const res = await lNet.get('https://cdn.jsdelivr.net/npm/deskrt@2.0.10/package.json', {
1962
+ 'mproxy': {
1963
+ 'url': this._internalUrl + 'test/net-mproxy1',
1964
+ 'auth': '123456',
1965
+ 'data': { 'test': '123' }
1966
+ }
1967
+ });
1968
+ echo.push(`<pre>lNet.get('https://cdn.jsdelivr.net/npm/deskrt@2.0.10/package.json', {
1969
+ 'mproxy': {
1970
+ 'url': '${this._internalUrl}test/net-mproxy1',
1971
+ 'auth': '123456',
1972
+ 'data': { 'test': '123' }
1973
+ }
1974
+ });</pre>
1975
+ headers: <pre>${JSON.stringify(res.headers, null, 4)}</pre>
1976
+ content: <pre>${(await res.getContent())?.toString() ?? 'null'}</pre>
1977
+ error: ${JSON.stringify(res.error)}`);
1978
+
1979
+ return echo.join('') + '<br><br>' + this._getEnd();
1980
+ }
1981
+
1982
+ public async netMproxy1(): Promise<string | boolean> {
1983
+ const data = lNet.mproxyData(this);
1984
+ lCore.debug('Got data', data);
1985
+ const rtn = await lNet.mproxy(this, '123456');
1986
+ if (rtn > 0) {
1987
+ return false;
1988
+ }
1989
+ return 'Nothing(' + rtn + ')';
1990
+ }
1991
+
1992
+ public async scan(): Promise<types.Json> {
1993
+ const link = await this._scanLink();
1994
+ if (!link) {
1995
+ return [0, 'Failed, link can not be connected.'];
1996
+ }
1997
+ const s = this._get['s'] ?? 'db';
1998
+
1999
+ const echo = [];
2000
+ const scan = await lScan.get(link, undefined, { 'ttl': 30, 'sqlPre': this });
2001
+ const token = scan.getToken();
2002
+ echo.push(`<pre>const scan = await lScan.get(this, link, undefined, { 'ttl': 30, 'sqlPre': this });
2003
+ const token = scan.getToken();</pre>
2004
+ token: ${token ?? 'null'}<br><br>
2005
+ Scan status: <b id="status" style="color: red;">Waiting...</b><br>
2006
+ Poll count: <span id="count">0</span>, expiration date: <span id="exp"></span><br><br>
2007
+ Simulated scan URL: http://www.test.simu/scan?token=${token ?? 'null'} (QR Code can be generated)<br><br>
2008
+ <input type="button" value="Visit the simulated URL" onclick="this.disabled=true;document.getElementById('url').innerText='http://www.test.simu/scan?token=${token ?? 'null'}';visit();"><br><br>
2009
+ <div style="border: solid 1px rgba(0,0,0,.3); box-shadow: 0 5px 20px rgba(0, 0, 0, .25); width: 90%; margin: auto;">
2010
+ <div id="url" style="background: rgba(0,0,0,.07); border-bottom: solid 1px rgba(0,0,0,.3); padding: 10px;">about:blank</div>
2011
+ <div id="content" style="height: 200px; font-size: 16px; display: flex; justify-content: center; align-items: center; flex-direction: column;"></div>
2012
+ </div>
2013
+ <script>
2014
+ var token = '${token ?? 'null'}';
2015
+ var count = 0;
2016
+ function poll() {
2017
+ fetch('${this._config.const.urlBase}test/scan1?s=${s}', {
2018
+ method: 'POST',
2019
+ headers: {
2020
+ 'Content-Type': 'application/x-www-form-urlencoded'
2021
+ },
2022
+ body: 'token=${token ?? 'null'}'
2023
+ }).then(function(r) {
2024
+ return r.json();
2025
+ }).then(function(j) {
2026
+ ++count;
2027
+ document.getElementById('status').innerText = j.msg;
2028
+ document.getElementById('count').innerText = count;
2029
+ if (j.result > 0) {
2030
+ document.getElementById('exp').innerText = j.exp;
2031
+ setTimeout(poll, 1000);
2032
+ }
2033
+ }).catch(function(e) {
2034
+ ++count;
2035
+ document.getElementById('status').innerText = 'Network error.';
2036
+ document.getElementById('count').innerText = count;
2037
+ setTimeout(poll, 1000);
2038
+ });
2039
+ }
2040
+ poll();
2041
+
2042
+ function visit() {
2043
+ document.getElementById('content').innerText = 'Loading...';
2044
+ fetch('${this._config.const.urlBase}test/scan2?s=${s}', {
2045
+ method: 'POST',
2046
+ headers: {
2047
+ 'Content-Type': 'application/x-www-form-urlencoded'
2048
+ },
2049
+ body: 'token=${token ?? 'null'}'
2050
+ }).then(function(r) {
2051
+ return r.json();
2052
+ }).then(function(j) {
2053
+ if (j.result > 0) {
2054
+ document.getElementById('content').innerHTML = 'Are you sure logged in the computer?<br><br><button id="confirm" style="padding: 10px 20px;" onclick="this.disabled=true;confirm()">Confirm</button>';
2055
+ }
2056
+ else {
2057
+ document.getElementById('content').innerText = j.msg;
2058
+ }
2059
+ });
2060
+ }
2061
+
2062
+ function confirm() {
2063
+ fetch('${this._config.const.urlBase}test/scan3?s=${s}', {
2064
+ method: 'POST',
2065
+ headers: {
2066
+ 'Content-Type': 'application/x-www-form-urlencoded'
2067
+ },
2068
+ body: 'token=${token ?? 'null'}'
2069
+ }).then(function(r) {
2070
+ return r.json();
2071
+ }).then(function(j) {
2072
+ if (j.result > 0) {
2073
+ document.getElementById('content').innerText = 'Finish the operation!';
2074
+ }
2075
+ else {
2076
+ document.getElementById('content').innerText = j.msg;
2077
+ }
2078
+ });
2079
+ }
2080
+ </script>`);
2081
+
2082
+ return '<a href="' + this._config.const.urlBase + 'test/scan?s=db">db</a> | ' +
2083
+ '<a href="' + this._config.const.urlBase + 'test/scan?s=kv">kv</a> | ' +
2084
+ '<a href="' + this._config.const.urlBase + 'test">Return</a>' + echo.join('') + '<br>' + this._getEnd();
2085
+ }
2086
+
2087
+ public async scan1(): Promise<types.Json> {
2088
+ const link = await this._scanLink();
2089
+ if (!link) {
2090
+ return [0, 'Failed, link can not be connected.'];
2091
+ }
2092
+
2093
+ const scan = await lScan.get(link, this._post['token'], {
2094
+ 'sqlPre': this
2095
+ });
2096
+ const rtn = await scan.poll();
2097
+ switch (rtn) {
2098
+ case -3: {
2099
+ return [0, 'System error.'];
2100
+ }
2101
+ case -2: {
2102
+ return [0, 'Token has expired.'];
2103
+ }
2104
+ case -1: {
2105
+ return [1, 'Waiting...', { 'exp': scan.getTimeLeft() }];
2106
+ }
2107
+ case 0: {
2108
+ return [1, 'Scanned, waiting for confirmation...', { 'exp': scan.getTimeLeft() }];
2109
+ }
2110
+ }
2111
+ return [0, 'Scan result: ' + JSON.stringify(rtn)];
2112
+ }
2113
+
2114
+ public async scan2(): Promise<types.Json> {
2115
+ const link = await this._scanLink();
2116
+ if (!link) {
2117
+ return [0, 'Failed, link can not be connected.'];
2118
+ }
2119
+ if (!await lScan.scanned(link, this._post['token'], {
2120
+ 'sqlPre': this
2121
+ })) {
2122
+ return [0, 'Token has expired.'];
2123
+ }
2124
+ return [1];
2125
+ }
2126
+
2127
+ public async scan3(): Promise<types.Json> {
2128
+ const link = await this._scanLink();
2129
+ if (!link) {
2130
+ return [0, 'Failed, link can not be connected.'];
2131
+ }
2132
+ if (!await lScan.setData(link, this._post['token'], {
2133
+ 'uid': '5'
2134
+ }, {
2135
+ 'sqlPre': this
2136
+ })) {
2137
+ return [0, 'Token has expired.'];
2138
+ }
2139
+ return [1];
2140
+ }
2141
+
2142
+ private async _scanLink(): Promise<types.Json> {
2143
+ const s = this._get['s'] ?? 'db';
2144
+ let link: lDb.Pool | lKv.Pool;
2145
+ if (s === 'db') {
2146
+ const db = lDb.get(this);
2147
+ link = db;
2148
+ }
2149
+ else {
2150
+ const kv = lKv.get(this);
2151
+ if (!await kv.ping()) {
2152
+ return false;
2153
+ }
2154
+ link = kv;
2155
+ }
2156
+ return link;
2157
+ }
2158
+
2159
+ public async session(): Promise<string | types.Json[]> {
2160
+ const retur: types.Json[] = [];
2161
+ if (!(this._checkInput(this._get, {
2162
+ 's': ['require', ['db', 'kv'], [0, 'Object not found.']],
2163
+ 'auth': [['', '1'], [0, 'Bad request.']],
2164
+ 'value': []
2165
+ }, retur))) {
2166
+ return retur;
2167
+ }
2168
+
2169
+ const echo = ['<pre>'];
2170
+
2171
+ let link: lDb.Pool | lKv.Pool;
2172
+ if (this._get['s'] === 'db') {
2173
+ link = lDb.get(this);
2174
+ echo.push('link = lDb.get(this);\n');
2175
+ }
2176
+ else {
2177
+ link = lKv.get(this);
2178
+ if (!await link.ping()) {
2179
+ return [0, 'Failed, Redis can not be connected.'];
2180
+ }
2181
+ echo.push('link = lKv.get(this);\n');
2182
+ }
2183
+
2184
+ if (this._get['auth'] === '') {
2185
+ await this._startSession(link, false, { 'ttl': 60 });
2186
+ echo.push(`await this._startSession(link, false, {'ttl': 60});
2187
+ JSON.stringify(this._session);</pre>` + lText.htmlescape(JSON.stringify(this._session)));
2188
+
2189
+ this._session['value'] = this._get['value'] ? this._get['value'] : 'ok';
2190
+ echo.push(`<pre>this._session['value'] = '${this._get['value'] ? this._get['value'] : 'ok'}';
2191
+ JSON.stringify(this._session);</pre>` + lText.htmlescape(JSON.stringify(this._session)));
2192
+
2193
+ return '<a href="' + this._config.const.urlBase + 'test/session?s=' + this._get['s'] + '">Default</a> | ' +
2194
+ '<a href="' + this._config.const.urlBase + 'test/session?s=' + this._get['s'] + '&value=aaa">Set "aaa"</a> | ' +
2195
+ '<a href="' + this._config.const.urlBase + 'test/session?s=' + this._get['s'] + '&value=bbb">Set "bbb"</a> | ' +
2196
+ '<a href="' + this._config.const.urlBase + 'test">Return</a>' + echo.join('') + '<br><br>' + this._getEnd();
2197
+ }
2198
+ else {
2199
+ // --- AUTH 模式 ---
2200
+ await this._startSession(link, true, { 'ttl': 60 });
2201
+ if (Object.keys(this._post).length > 0) {
2202
+ if (this._session['count'] === undefined) {
2203
+ this._session['count'] = 1;
2204
+ }
2205
+ else {
2206
+ ++this._session['count'];
2207
+ }
2208
+ return [1, { 'txt': 'this._session: ' + JSON.stringify(this._session) + '\nToken: ' + this._sess!.getToken(), 'token': this._sess?.getToken(), '_auth': this._getBasicAuth('token', this._sess!.getToken()) }];
2209
+ }
2210
+ else {
2211
+ echo.push(`await this._startSession(link, true, {'ttl': 60});
2212
+ JSON.stringify(this._session));</pre>` + lText.htmlescape(JSON.stringify(this._session)));
2213
+
2214
+ this._session['value'] = lTime.format(this, 'H:i:s');
2215
+ echo.push(`<pre>this._session['value'] = '${lTime.format(this, 'H:i:s')}';
2216
+ JSON.stringify(this._session);</pre>` + lText.htmlescape(JSON.stringify(this._session)));
2217
+
2218
+ echo.push(`<br><br><input type="button" value="Post with header" onclick="document.getElementById('result').innerText='Waiting...';fetch('${this._config.const.urlBase}test/session?s=${this._get['s']}&auth=1',{method:'POST',credentials:'omit',headers:{'Authorization':document.getElementById('_auth').innerText,'content-type':'application/x-www-form-urlencoded'},body:'key=val'}).then(function(r){return r.json();}).then(function(j){document.getElementById('result').innerText=j.txt;document.getElementById('token').innerText=j.token;document.getElementById('_auth').innerText=j._auth;});"><input type='button' value="Post without header" style="margin-left: 10px;" onclick="document.getElementById('result').innerText='Waiting...';fetch('${this._config.const.urlBase}test/session?s=${this._get['s']}&auth=1',{method:'POST',credentials:'omit',headers:{'content-type':'application/x-www-form-urlencoded'},body:'key=val'}).then(function(r){return r.json();}).then(function(j){document.getElementById('result').innerText=j.txt;});"><br><br>
2219
+ Token: <span id="token">${this._sess!.getToken()}</span><br>
2220
+ Post Authorization header: <span id="_auth">${this._getBasicAuth('token', this._sess!.getToken())}</span><br><br>
2221
+ Result:<pre id="result">Nothing.</pre>`);
2222
+
2223
+ return '<a href="' + this._config.const.urlBase + 'test">Return</a>' + echo.join('') + this._getEnd();
2224
+ }
2225
+ }
2226
+ }
2227
+
2228
+ public async jwt(): Promise<string | types.Json[]> {
2229
+ const retur: types.Json[] = [];
2230
+ if (!(this._checkInput(this._get, {
2231
+ 'type': [['', 'kv', 'auth'], [0, 'Bad request.']]
2232
+ }, retur))) {
2233
+ return retur;
2234
+ }
2235
+
2236
+ const echo: string[] = ['<pre>'];
2237
+ let link: lKv.Pool | undefined = undefined;
2238
+ if (this._get['type'] === 'kv') {
2239
+ link = lKv.get(this);
2240
+ echo.push('link = lKv.get(this);\n');
2241
+ }
2242
+
2243
+ const origin = lJwt.getOrigin(this);
2244
+ echo.push(`const origin = lJwt.getOrigin(this);
2245
+ JSON.stringify(origin);</pre>`);
2246
+ echo.push(JSON.stringify(origin));
2247
+
2248
+ // --- 创建 jwt 对象 ---
2249
+ const jwt = await lJwt.get(this, {}, link);
2250
+ echo.push(`<pre>const jwt = lJwt.get(this, {}, ${link ? 'link' : 'undefined'});
2251
+ JSON.stringify(this._jwt);</pre>`);
2252
+ echo.push(JSON.stringify(this._jwt));
2253
+
2254
+ this._jwt['test'] = 'a';
2255
+ const value = jwt.renew();
2256
+ echo.push(`<pre>this._jwt['test'] = 'a';
2257
+ const value = jwt.renew();
2258
+ JSON.stringify(this._jwt);</pre>`);
2259
+ echo.push(JSON.stringify(this._jwt));
2260
+
2261
+ echo.push(`<pre>JSON.stringify(value);</pre>`);
2262
+ echo.push(JSON.stringify(value));
2263
+
2264
+ const token = this._jwt['token'];
2265
+ const rtn = await jwt.destory();
2266
+ echo.push(`<pre>const token = this._jwt['token'];
2267
+ const rtn = await jwt.destory();
2268
+ JSON.stringify(rtn);</pre>`);
2269
+ echo.push(JSON.stringify(rtn));
2270
+
2271
+ echo.push('<pre>JSON.stringify(this._jwt);</pre>');
2272
+ echo.push(JSON.stringify(this._jwt));
2273
+
2274
+ const rtn2 = await lJwt.decode(this, origin, link);
2275
+ echo.push(`<pre>const rtn2 = await lJwt.decode(this, origin, ${link ? 'link' : 'undefined'});
2276
+ JSON.stringify(rtn2);</pre>`);
2277
+ echo.push(JSON.stringify(rtn2));
2278
+
2279
+ if (this._get['type'] === 'auth') {
2280
+ echo.push(`<br><br><input type="button" value="Post with header" onclick="document.getElementById('result').innerText='Waiting...';fetch('${this._config.const.urlBase}test/jwt1',{method:'POST',credentials:'omit',headers:{'Authorization':document.getElementById('_auth').innerText,'content-type':'application/x-www-form-urlencoded'},body:'key=val'}).then(function(r){return r.json();}).then(function(j){document.getElementById('result').innerText=j.txt;});"><input type='button' value="Post without header" style="margin-left: 10px;" onclick="document.getElementById('result').innerText='Waiting...';fetch('${this._config.const.urlBase}test/jwt1',{method:'POST',credentials:'omit',headers:{'content-type':'application/x-www-form-urlencoded'},body:'key=val'}).then(function(r){return r.json();}).then(function(j){document.getElementById('result').innerText=j.txt;});"><br><br>
2281
+ Token: <span id="token">${token}</span><br>
2282
+ Post Authorization header: <span id="_auth">Bearer ${origin}</span><br><br>
2283
+ Result:<pre id="result">Nothing.</pre>`);
2284
+ }
2285
+ else {
2286
+ echo.push('<br><br>');
2287
+ }
2288
+
2289
+ return echo.join('') + this._getEnd();
2290
+ }
2291
+
2292
+ public async jwt1(): Promise<[number, types.Json]> {
2293
+ await lJwt.get(this, {
2294
+ 'auth': true
2295
+ });
2296
+ return [1, { 'txt': JSON.stringify(this._jwt) }];
2297
+ }
2298
+
2299
+ public sql(): string {
2300
+ const echo: string[] = [];
2301
+ let sql = lSql.get('test_');
2302
+ switch (this._get['type']) {
2303
+ case 'insert': {
2304
+ let s = sql.insert('user').values(['name', 'age'], [
2305
+ ['Ah', '16'],
2306
+ ['Bob', '24']
2307
+ ]).getSql();
2308
+ let sd = sql.getData();
2309
+ echo.push(`<pre>sql.insert('user').values(['name', 'age'], [
2310
+ ['Ah', '16'],
2311
+ ['Bob', '24']
2312
+ ]);</pre>
2313
+ <b>getSql() :</b> ${s}<br>
2314
+ <b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
2315
+ <b>format() :</b> ${sql.format(s, sd)}<hr>`);
2316
+
2317
+ s = sql.insert('user').values(['name', 'age'], ['Ah', '16']).getSql();
2318
+ sd = sql.getData();
2319
+ echo.push(`<pre>sql.insert('user').values(['name', 'age'], ['Ah', '16']);</pre>
2320
+ <b>getSql() :</b> ${s}<br>
2321
+ <b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
2322
+ <b>format() :</b> ${sql.format(s, sd)}<hr>`);
2323
+
2324
+ s = sql.insert('user').values({ 'name': 'Bob', 'age': '24' }).getSql();
2325
+ sd = sql.getData();
2326
+ echo.push(`<pre>sql.insert('user').values({ 'name': 'Bob', 'age': '24' });</pre>
2327
+ <b>getSql() :</b> ${s}<br>
2328
+ <b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
2329
+ <b>format() :</b> ${sql.format(s, sd)}<hr>`);
2330
+
2331
+ s = sql.replace('user').values({ 'token': '20200202', 'name': 'Bob' }).getSql();
2332
+ sd = sql.getData();
2333
+ echo.push(`<pre>sql.replace('user').values({ 'token': '20200202', 'name': 'Bob' });</pre>
2334
+ <b>getSql() :</b> ${s}<br>
2335
+ <b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
2336
+ <b>format() :</b> ${sql.format(s, sd)}<hr>`);
2337
+
2338
+ s = sql.insert('order').notExists('order', { 'name': 'Amy', 'age': '16', 'time_add': lTime.stamp(), 'point': ['POINT(?)', ['20']] }, { 'name': 'Amy' }).getSql();
2339
+ sd = sql.getData();
2340
+ echo.push(`<pre>sql.insert('order').notExists('order', { 'name': 'Amy', 'age': '16', 'time_add': lTime.stamp(), 'point': ['POINT(?)', ['20']] }, { 'name': 'Amy' });</pre>
2341
+ <b>getSql() :</b> ${s}<br>
2342
+ <b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
2343
+ <b>format() :</b> ${sql.format(s, sd)}<hr>`);
2344
+
2345
+ s = sql.insert('verify').values({ 'token': 'abc', 'time_update': '10' }).duplicate({ 'time_update': ['CONCAT(`time_update`, ?)', ['01']] }).getSql();
2346
+ sd = sql.getData();
2347
+ echo.push(`<pre>sql.insert('verify').values({ 'token': 'abc', 'time_update': '10' }).duplicate({ 'time_update': ['CONCAT(\`time_update\`, ?)', ['01']] });</pre>
2348
+ <b>getSql() :</b> ${s}<br>
2349
+ <b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
2350
+ <b>format() :</b> ${sql.format(s, sd)}<hr>`);
2351
+
2352
+ // --- insert 中使用函数 ---
2353
+
2354
+ s = sql.insert('geo').values({ 'point': ['ST_POINTFROMTEXT(?)', ['POINT(122.147775 30.625014)']] }).getSql();
2355
+ sd = sql.getData();
2356
+ echo.push(`<pre>sql.insert('geo').values({ 'point': ['ST_POINTFROMTEXT(?)', ['POINT(122.147775 30.625014)']] });</pre>
2357
+ <b>getSql() :</b> ${s}<br>
2358
+ <b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
2359
+ <b>format() :</b> ${sql.format(s, sd)}<hr>`);
2360
+
2361
+ s = sql.insert('geo').values(['name', 'point', 'point2', 'polygon', 'json'], [
2362
+ [
2363
+ 'POINT A', ['ST_POINTFROMTEXT(?)', ['POINT(122.147775 30.625015)']], { 'x': 1, 'y': 1 }, [
2364
+ [
2365
+ { 'x': 1, 'y': 1 },
2366
+ { 'x': 2, 'y': 2 },
2367
+ { 'x': 3, 'y': 3 },
2368
+ { 'x': 1, 'y': 1 }
2369
+ ],
2370
+ [
2371
+ { 'x': 6, 'y': 1 },
2372
+ { 'x': 7, 'y': 2 },
2373
+ { 'x': 8, 'y': 3 },
2374
+ { 'x': 6, 'y': 1 }
2375
+ ]
2376
+ ],
2377
+ { 'x': { 'y': 'ghi' } }
2378
+ ],
2379
+ [
2380
+ 'POINT B', ['ST_POINTFROMTEXT(?)', ['POINT(123.147775 30.625016)']], { 'x': 1, 'y': 1 }, null, null
2381
+ ]
2382
+ ]).getSql();
2383
+ sd = sql.getData();
2384
+ echo.push(`<pre>sql.insert('geo').values(['name', 'point', 'point2', 'polygon', 'json'], [
2385
+ [
2386
+ 'POINT A', ['ST_POINTFROMTEXT(?)', ['POINT(122.147775 30.625015)']], { 'x': 1, 'y': 1 }, [
2387
+ [
2388
+ { 'x': 1, 'y': 1 },
2389
+ { 'x': 2, 'y': 2 },
2390
+ { 'x': 3, 'y': 3 },
2391
+ { 'x': 1, 'y': 1 }
2392
+ ],
2393
+ [
2394
+ { 'x': 6, 'y': 1 },
2395
+ { 'x': 7, 'y': 2 },
2396
+ { 'x': 8, 'y': 3 },
2397
+ { 'x': 6, 'y': 1 }
2398
+ ]
2399
+ ],
2400
+ { 'x': { 'y': 'ghi' } }
2401
+ ],
2402
+ [
2403
+ 'POINT B', ['ST_POINTFROMTEXT(?)', ['POINT(123.147775 30.625016)']], { 'x': 1, 'y': 1 }, null, null
2404
+ ]
2405
+ ]);</pre>
2406
+ <b>getSql() :</b> ${s}<br>
2407
+ <b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
2408
+ <b>format() :</b> ${sql.format(s, sd)}`);
2409
+ break;
2410
+ }
2411
+ case 'select': {
2412
+ let s = sql.select('*', 'user').getSql();
2413
+ let sd = sql.getData();
2414
+ echo.push(`<pre>sql.select('*', 'user');</pre>
2415
+ <b>getSql() :</b> ${s}<br>
2416
+ <b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
2417
+ <b>format() :</b> ${sql.format(s, sd)}<hr>`);
2418
+
2419
+ s = sql.select(['id', 'name'], 'user').getSql();
2420
+ sd = sql.getData();
2421
+ echo.push(`<pre>sql.select(['id', 'name'], 'user');</pre>
2422
+ <b>getSql() :</b> ${s}<br>
2423
+ <b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
2424
+ <b>format() :</b> ${sql.format(s, sd)}<hr>`);
2425
+
2426
+ s = sql.select('*', ['user', 'order']).getSql();
2427
+ sd = sql.getData();
2428
+ echo.push(`<pre>sql.select('*', ['user', 'order']);</pre>
2429
+ <b>getSql() :</b> ${s}<br>
2430
+ <b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
2431
+ <b>format() :</b> ${sql.format(s, sd)}<hr>`);
2432
+
2433
+ s = sql.select('*', ['db1.user', 'db2.user']).getSql();
2434
+ sd = sql.getData();
2435
+ echo.push(`<pre>sql.select('*', ['db1.user', 'db2.user']);</pre>
2436
+ <b>getSql() :</b> ${s}<br>
2437
+ <b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
2438
+ <b>format() :</b> ${sql.format(s, sd)}<hr>`);
2439
+
2440
+ s = sql.select(['order.no', 'user.nick'], ['order']).leftJoin('user', { 'order.user_id': lSql.column('user.id'), 'state': '1' }).getSql();
2441
+ sd = sql.getData();
2442
+ echo.push(`<pre>sql.select(['order.no', 'user.nick'], ['order']).leftJoin('user', { 'order.user_id': lSql.column('user.id'), 'state': '1' });</pre>
2443
+ <b>getSql() :</b> ${s}<br>
2444
+ <b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
2445
+ <b>format() :</b> ${sql.format(s, sd)}<hr>`);
2446
+
2447
+ s = sql.select(['o.*', 'u.nick as unick'], ['order o']).leftJoin('`user` AS u', { 'o.user_id': lSql.column('u.id'), 'state': '1' }).getSql();
2448
+ sd = sql.getData();
2449
+ echo.push(`<pre>sql.select(['o.*', 'u.nick as unick'], ['order o']).leftJoin('\`user\` AS u', { 'o.user_id': lSql.column('u.id'), 'state': '1' });</pre>
2450
+ <b>getSql() :</b> ${s}<br>
2451
+ <b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
2452
+ <b>format() :</b> ${sql.format(s, sd)}<hr>`);
2453
+
2454
+ s = sql.select(['SUM(user.age) age', 'UTC_TIMESTAMP', 'FROM_UNIXTIME(user.time, \'%Y-%m\') as time'], 'order').leftJoin('user', { 'order.user_id': lSql.column('user.id') }).getSql();
2455
+ sd = sql.getData();
2456
+ echo.push(`<pre>sql.select(['SUM(user.age) age', 'UTC_TIMESTAMP', 'FROM_UNIXTIME(user.time, \\'%Y-%m\\') as time'], 'order').leftJoin('user', { 'order.user_id': lSql.column('user.id') });</pre>
2457
+ <b>getSql() :</b> ${s}<br>
2458
+ <b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
2459
+ <b>format() :</b> ${sql.format(s, sd)}<hr>`);
2460
+
2461
+ s = sql.select('*', 'order').leftJoin('user', { 'order.user_id': lSql.column('user.id') }, '_0').leftJoin('group a', { 'order.group_id': lSql.column('a.id') }, '_0').getSql();
2462
+ sd = sql.getData();
2463
+ echo.push(`<pre>sql.select('*', 'order').leftJoin('user', { 'order.user_id': lSql.column('user.id') }, '_0').leftJoin('group a', { 'order.group_id': lSql.column('a.id') }, '_0');</pre>
2464
+ <b>getSql() :</b> ${s}<br>
2465
+ <b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
2466
+ <b>format() :</b> ${sql.format(s, sd)}<hr>`);
2467
+
2468
+ s = sql.select('*', 'order').where({ 'a': 1, 'b': 2 }).unionAll(sql.copy('abc')).getSql();
2469
+ sd = sql.getData();
2470
+ echo.push(`<pre>sql.select('*', 'order').where({ 'a': 1, 'b': 2 }).unionAll(sql.copy('abc'));</pre>
2471
+ <b>getSql() :</b> ${s}<br>
2472
+ <b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
2473
+ <b>format() :</b> ${sql.format(s, sd)}<hr>`);
2474
+
2475
+ sql = sql.copy('abcd', { 'where': { 'c': 2 } });
2476
+ s = sql.getSql();
2477
+ sd = sql.getData();
2478
+ echo.push(`<pre>sql.copy('abcd', { 'where': { 'c': 2 } });</pre>
2479
+ <b>getSql() :</b> ${s}<br>
2480
+ <b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
2481
+ <b>format() :</b> ${sql.format(s, sd)}`);
2482
+ break;
2483
+ }
2484
+ case 'update': {
2485
+ // --- 1, 2 ---
2486
+
2487
+ let s = sql.update('user', [['age', '+', '1'], ['month', '=', '5'], { 'name': 'Serene', 'nick': lSql.column('name') }, ['year', '+', lSql.column('age')]]).where({ 'name': 'Ah' }).getSql();
2488
+ let sd = sql.getData();
2489
+ echo.push(`<pre>sql.update('user', [['age', '+', '1'], ['month', '=', '5'], { 'name': 'Serene', 'nick': lSql.column('name') }, ['year', '+', lSql.column('age')]]).where({ 'name': 'Ah' });</pre>
2490
+ <b>getSql() :</b> ${s}<br>
2491
+ <b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
2492
+ <b>format() :</b> ${sql.format(s, sd)}<hr>`);
2493
+
2494
+ // --- 3 ---
2495
+
2496
+ s = sql.update('user', { 'name': 'Serene', 'type': ['(CASE `id` WHEN 1 THEN ? WHEN 2 THEN ? END)', ['val1', 'val2']] }).where({ 'name': 'Ah' }).getSql();
2497
+ sd = sql.getData();
2498
+ echo.push(`<pre>sql.update('user', { 'name': 'Serene', 'type': ['(CASE \`id\` WHEN 1 THEN ? WHEN 2 THEN ? END)', ['val1', 'val2']] }).where({ 'name': 'Ah' });</pre>
2499
+ <b>getSql() :</b> ${s}<br>
2500
+ <b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
2501
+ <b>format() :</b> ${sql.format(s, sd)}<hr>`);
2502
+
2503
+ // --- # ---
2504
+
2505
+ s = sql.update('user', { 'age': lSql.column('age_verify'), 'date': '#12', 'he': ['he2'] }).where({ 'date_birth': '2001' }).getSql();
2506
+ sd = sql.getData();
2507
+ echo.push(`<pre>sql.update('user', { 'age': lSql.column('age_verify'), 'date': '#12', 'he': ['he2'] }).where({ 'date_birth': '2001' });</pre>
2508
+ <b>getSql() :</b> ${s}<br>
2509
+ <b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
2510
+ <b>format() :</b> ${sql.format(s, sd)}<hr>`);
2511
+
2512
+ // --- update order limit ---
2513
+
2514
+ s = sql.update('user', { 'he': 'he2' }).where([ ['birth', '>', '2001'] ]).by('birth').limit(0, 10).getSql();
2515
+ sd = sql.getData();
2516
+ echo.push(`<pre>sql.update('user', { 'he': 'he2' }).where([ ['birth', '>', '2001'] ]).by('birth').limit(0, 10);</pre>
2517
+ <b>getSql() :</b> ${s}<br>
2518
+ <b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
2519
+ <b>format() :</b> ${sql.format(s, sd)}`);
2520
+
2521
+ // --- json ---
2522
+
2523
+ s = sql.update('json', { 'json1': { 'key': 'val', 'key2': 'val2' }, 'json2': [ { 'k1': 'v1' }, { 'k2': 'v2' } ], 'json3': { 'x': 1, 'y': 2 }, 'json4': [], 'json5': {} }).where({ 'id': 1 }).getSql();
2524
+ sd = sql.getData();
2525
+ echo.push(`<pre>sql.update('json', { 'json1': { 'key': 'val', 'key2': 'val2' }, 'json2': [ { 'k1': 'v1' }, { 'k2': 'v2' } ], 'json3': { 'x': 1, 'y': 2 }, 'json4': [], 'json5': {} }).where({ 'id': 1 });</pre>
2526
+ <b>getSql() :</b> ${s}<br>
2527
+ <b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
2528
+ <b>format() :</b> ${sql.format(s, sd)}`);
2529
+
2530
+ break;
2531
+ }
2532
+ case 'delete': {
2533
+ const s = sql.delete('user').where({ 'id': '1' }).getSql();
2534
+ const sd = sql.getData();
2535
+ echo.push(`<pre>sql.delete('user').where({ 'id': '1' });</pre>
2536
+ <b>getSql() :</b> ${s}<br>
2537
+ <b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
2538
+ <b>format() :</b> ${sql.format(s, sd)}`);
2539
+ break;
2540
+ }
2541
+ case 'where': {
2542
+ let s = sql.select('*', 'user').where([{ 'city': 'la' }, ['age', '>', '10'], ['level', 'in', ['1', '2', '3']], ['age + age2 + age3 + 10', '>', 20]]).getSql();
2543
+ let sd = sql.getData();
2544
+ echo.push(`<pre>sql.select('*', 'user').where([{ 'city': 'la' }, ['age', '>', '10'], ['level', 'in', ['1', '2', '3']], ['age + age2 + age3 + 10', '>', 20]]);</pre>
2545
+ <b>getSql() :</b> ${s}<br>
2546
+ <b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
2547
+ <b>format() :</b> ${sql.format(s, sd)}<hr>`);
2548
+
2549
+ s = sql.update('order', { 'state': '1' }).where({
2550
+ '$or': [{
2551
+ 'type': '1'
2552
+ }, {
2553
+ 'type': '2'
2554
+ }],
2555
+ '$or-2': [{
2556
+ 'type2': '3'
2557
+ }, {
2558
+ 'type2': '4'
2559
+ }],
2560
+ '$or-other': [{
2561
+ 'type3': '5'
2562
+ }, {
2563
+ 'type3': '6'
2564
+ }]
2565
+ }).getSql();
2566
+ sd = sql.getData();
2567
+ echo.push(`<pre>sql.update('order', { 'state': '1' }).where({
2568
+ '$or': [{
2569
+ 'type': '1'
2570
+ }, {
2571
+ 'type': '2'
2572
+ }],
2573
+ '$or-2': [{
2574
+ 'type2': '3'
2575
+ }, {
2576
+ 'type2': '4'
2577
+ }],
2578
+ '$or-other': [{
2579
+ 'type3': '5'
2580
+ }, {
2581
+ 'type3': '6'
2582
+ }]
2583
+ });</pre>
2584
+ <b>getSql() :</b> ${s}<br>
2585
+ <b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
2586
+ <b>format() :</b> ${sql.format(s, sd)}<hr>`);
2587
+
2588
+ s = sql.update('order', { 'state': '1' }).where({
2589
+ 'user_id': '2',
2590
+ 'state': ['1', '2', '3'],
2591
+ '$or': [{ 'type': '1', 'find': '0' }, { 'type': '2', 'find': '1' }, [['type', '<', '-1']]]
2592
+ }).getSql();
2593
+ sd = sql.getData();
2594
+ echo.push(`<pre>sql.update('order', { 'state': '1' }).where({
2595
+ 'user_id': '2',
2596
+ 'state': ['1', '2', '3'],
2597
+ '$or': [{ 'type': '1', 'find': '0' }, { 'type': '2', 'find': '1' }, [['type', '<', '-1']]]
2598
+ });</pre>
2599
+ <b>getSql() :</b> ${s}<br>
2600
+ <b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
2601
+ <b>format() :</b> ${sql.format(s, sd)}<hr>`);
2602
+
2603
+ s = sql.select('*', 'user').where({
2604
+ 'time_verify': lSql.column('time_add')
2605
+ }).getSql();
2606
+ sd = sql.getData();
2607
+ echo.push(`<pre>sql.select('*', 'user').where({
2608
+ 'time_verify': lSql.column('time_add')
2609
+ });</pre>
2610
+ <b>getSql() :</b> ${s}<br>
2611
+ <b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
2612
+ <b>format() :</b> ${sql.format(s, sd)}<hr>`);
2613
+
2614
+ s = sql.delete('user').where([
2615
+ [['MATCH(name_sc, name_tc) AGAINST(?)', ['search']], '>=', '0.9']
2616
+ ]).getSql();
2617
+ sd = sql.getData();
2618
+ echo.push(`<pre>sql.delete('user').where([
2619
+ [['MATCH(name_sc, name_tc) AGAINST(?)', ['search']], '>=', '0.9']
2620
+ ]);</pre>
2621
+ <b>getSql() :</b> ${s}<br>
2622
+ <b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
2623
+ <b>format() :</b> ${sql.format(s, sd)}<hr>`);
2624
+
2625
+ s = sql.select('*', 'user').where([{ 'city': 'la', 'area': null }, ['age', '>', '10'], ['soft', '<>', null], ['ware', 'IS', null]]).getSql();
2626
+ sd = sql.getData();
2627
+ echo.push(`<pre>sql.select('*', 'user').where([{ 'city': 'la', 'area': null }, ['age', '>', '10'], ['soft', '<>', null], ['ware', 'IS', null]]);</pre>
2628
+ <b>getSql() :</b> ${s}<br>
2629
+ <b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
2630
+ <b>format() :</b> ${sql.format(s, sd)}`);
2631
+ break;
2632
+ }
2633
+ case 'having': {
2634
+ let s = sql.select(['id', 'name', '(6371 * ACOS(COS(RADIANS(31.239845)) * COS(RADIANS(`lat`)) * COS(RADIANS(`lng`) - RADIANS(121.499662)) + SIN(RADIANS(31.239845)) * SIN(RADIANS(`lat`)))) AS distance'], 'location').having([
2635
+ ['distance', '<', '2']
2636
+ ]).getSql();
2637
+ let sd = sql.getData();
2638
+ echo.push(`<pre>sql.select(['id', 'name', '(6371 * ACOS(COS(RADIANS(31.239845)) * COS(RADIANS(\`lat\`)) * COS(RADIANS(\`lng\`) - RADIANS(121.499662)) + SIN(RADIANS(31.239845)) * SIN(RADIANS(\`lat\`)))) AS distance'], 'location').having([
2639
+ ['distance', '<', '2']
2640
+ ]);</pre>
2641
+ <b>getSql() :</b> ${s}<br>
2642
+ <b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
2643
+ <b>format() :</b> ${sql.format(s, sd)}<hr>`);
2644
+
2645
+ s = sql.select(['id', 'name',
2646
+ [
2647
+ '(6371 * ACOS(COS(RADIANS(?)) * COS(RADIANS(`lat`)) * COS(RADIANS(`lng`) - RADIANS(?)) + SIN(RADIANS(?)) * SIN(RADIANS(`lat`)))) AS distance',
2648
+ ['31.239845', '121.499662', '31.239845']
2649
+ ]
2650
+ ], 'location').having([
2651
+ ['distance', '<', '2']
2652
+ ]).getSql();
2653
+ sd = sql.getData();
2654
+ echo.push(`<pre>sql.select(['id', 'name',
2655
+ [
2656
+ '(6371 * ACOS(COS(RADIANS(?)) * COS(RADIANS(\`lat\`)) * COS(RADIANS(\`lng\`) - RADIANS(?)) + SIN(RADIANS(?)) * SIN(RADIANS(\`lat\`)))) AS distance',
2657
+ ['31.239845', '121.499662', '31.239845']
2658
+ ]
2659
+ ], 'location')->having([
2660
+ ['distance', '<', '2']
2661
+ ]);</pre>
2662
+ <b>getSql() :</b> ${s}<br>
2663
+ <b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
2664
+ <b>format() :</b> ${sql.format(s, sd)}`);
2665
+ break;
2666
+ }
2667
+ case 'by': {
2668
+ let s = sql.select('*', 'test').by('id').getSql();
2669
+ let sd = sql.getData();
2670
+ echo.push(`<pre>sql.select('*', 'test').by('id');</pre>
2671
+ <b>getSql() :</b> ${s}<br>
2672
+ <b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
2673
+ <b>format() :</b> ${sql.format(s, sd)}<hr>`);
2674
+
2675
+ s = sql.select('*', 'test').by(['index', 'id']).getSql();
2676
+ sd = sql.getData();
2677
+ echo.push(`<pre>sql.select('*', 'test').by(['index', 'id']);</pre>
2678
+ <b>getSql() :</b> ${s}<br>
2679
+ <b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
2680
+ <b>format() :</b> ${sql.format(s, sd)}<hr>`);
2681
+
2682
+ s = sql.select('*', 'test').by(['index', ['id', 'ASC']], 'DESC').getSql();
2683
+ sd = sql.getData();
2684
+ echo.push(`<pre>sql.select('*', 'test').by(['index', ['id', 'ASC']], 'DESC');</pre>
2685
+ <b>getSql() :</b> ${s}<br>
2686
+ <b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
2687
+ <b>format() :</b> ${sql.format(s, sd)}`);
2688
+ break;
2689
+ }
2690
+ case 'field': {
2691
+ echo.push(`<pre>sql.field('abc');</pre>` + sql.field('abc'));
2692
+ echo.push(`<pre>sql.field('abc', 'a_');</pre>` + sql.field('abc', 'a_'));
2693
+ echo.push(`<pre>sql.field('x.abc');</pre>` + sql.field('x.abc'));
2694
+ echo.push(`<pre>sql.field('def f');</pre>` + sql.field('def f'));
2695
+ echo.push(`<pre>sql.field('def \`f\`', 'a_');</pre>` + sql.field('def `f`', 'a_'));
2696
+ echo.push(`<pre>sql.field('x.def f');</pre>` + sql.field('x.def f'));
2697
+ echo.push(`<pre>sql.field('x.def as f');</pre>` + sql.field('x.def as f'));
2698
+ echo.push(`<pre>sql.field('SUM(num) all');</pre>` + sql.field('SUM(num) all'));
2699
+ echo.push(`<pre>sql.field('SUM(x.num) all');</pre>` + sql.field('SUM(x.num) all'));
2700
+ echo.push(`<pre>sql.field('SUM(x.\`num\`) all');</pre>` + sql.field('SUM(x.`num`) all'));
2701
+ echo.push(`<pre>sql.field('FROM_UNIXTIME(time, \\'%Y-%m-%d\\') time');</pre>` + sql.field('FROM_UNIXTIME(time, \'%Y-%m-%d\') time'));
2702
+ echo.push(`<pre>sql.field('(6371 * ACOS(COS(RADIANS(31.239845)) * COS(RADIANS(lat)) * COS(RADIANS(\`lng\`) - RADIANS(121.499662)) + SIN(RADIANS(31.239845)) * SIN(RADIANS(\`lat\`))))');</pre>` + sql.field('(6371 * ACOS(COS(RADIANS(31.239845)) * COS(RADIANS(lat)) * COS(RADIANS(`lng`) - RADIANS(121.499662)) + SIN(RADIANS(31.239845)) * SIN(RADIANS(`lat`))))'));
2703
+ echo.push(`<pre>sql.field('MATCH(name_sc, name_tc) AGAINST("ok") tmp'));</pre>` + sql.field('MATCH(name_sc, name_tc) AGAINST("ok") tmp'));
2704
+ echo.push(`<pre>sql.field('a\\'bc');</pre>` + sql.field('a\'bc'));
2705
+ echo.push(`<pre>sql.field('\`a\`WHERE\`q\` = SUM(0) AND \`b\` = "abc" LEFT JOIN \`abc\`');</pre>` + sql.field('`a`WHERE`q` = SUM(0) AND `b` = "abc" LEFT JOIN `abc`'));
2706
+ echo.push(`<pre>sql.field('TEST(UTC_TIMESTAMP)');</pre>` + sql.field('TEST(UTC_TIMESTAMP)'));
2707
+ echo.push(`<pre>sql.field('a + b + 10 + c');</pre>` + sql.field('a + b + 10 + c'));
2708
+ echo.push(`<pre>sql.field('*');</pre>` + sql.field('*'));
2709
+ break;
2710
+ }
2711
+ }
2712
+ return echo.join('') + '<br><br>' + this._getEnd();
2713
+ }
2714
+
2715
+ public consistentHash(): string {
2716
+ const echo: string[] = [];
2717
+
2718
+ echo.push(`<pre>lConsistent.hash('abc');</pre>` + lConsistent.hash('abc').toString());
2719
+ echo.push(`<pre>lConsistent.hash('thisisnone');</pre>` + lConsistent.hash('thisisnone').toString());
2720
+ echo.push(`<pre>lConsistent.hash('haha');</pre>` + lConsistent.hash('haha').toString());
2721
+
2722
+ return echo.join('') + '<br><br>' + this._getEnd();
2723
+ }
2724
+
2725
+ public consistentDistributed(): string {
2726
+ const echo: string[] = [];
2727
+
2728
+ const servers = ['srv-sh.test.simu', 'srv-cd.test.simu', 'srv-tk.test.simu'];
2729
+ const files = [8, 12, 18, 32, 89, 187, 678, 1098, 3012, 8901, 38141, 76291, 99981];
2730
+ const map: Record<string, string | null> = {};
2731
+ const cons = lConsistent.get();
2732
+ cons.add(servers);
2733
+ for (const file of files) {
2734
+ map[file] = cons.find(file);
2735
+ }
2736
+ echo.push(`<pre>const servers = ['srv-sh.test.simu', 'srv-cd.test.simu', 'srv-tk.test.simu'];
2737
+ const files = [8, 12, 18, 32, 89, 187, 678, 1098, 3012, 8901, 38141, 76291, 99981];
2738
+ const map: Record<string, string | null> = {};
2739
+ const cons = lConsistent.get();
2740
+ cons.add(servers);
2741
+ for (const file of files) {
2742
+ map[file] = cons.find(file);
2743
+ }</pre>`);
2744
+ echo.push('<table style="width: 100%;">');
2745
+ for (const k in map) {
2746
+ const v = map[k];
2747
+ echo.push('<tr><th>' + lText.htmlescape(k) + '</th><td>' + lText.htmlescape(v ?? 'null') + ' (' + lConsistent.hash(k).toString() + ')</td></tr>');
2748
+ }
2749
+ echo.push('</table>');
2750
+
2751
+ cons.add('srv-sg.test.simu');
2752
+ const file = files[lCore.rand(0, files.length - 1)];
2753
+ // const file = files[3];
2754
+ const oldSrv = map[file];
2755
+ const newSrv = cons.find(file);
2756
+ echo.push(`<pre>cons.add('srv-sg.test.simu');
2757
+ const file = files[lText.rand(0, files.length - 1)];
2758
+ const oldSrv = map[file];
2759
+ const newSrv = cons.find(file);</pre>`);
2760
+ echo.push(`<table style="width: 100%;">
2761
+ <tr><th>File</th><td>${file}</td></tr>
2762
+ <tr><th>Old</th><td>${oldSrv ?? 'null'}</td></tr>
2763
+ <tr><th>New</th><td>${newSrv ?? 'null'}</td></tr>
2764
+ <tr><th>State</th><td>${((oldSrv === newSrv) ? '<b>Hit</b>' : 'Miss')}</td></tr>
2765
+ </table>`);
2766
+
2767
+ return echo.join('') + '<br>' + this._getEnd();
2768
+ }
2769
+
2770
+ public consistentMigration(): string {
2771
+ const echo: string[] = [];
2772
+
2773
+ // --- 生成初始数据,5000 条数据分 5 长表 ---
2774
+ const tables = ['table-0', 'table-1', 'table-2', 'table-3', 'table-4'];
2775
+ const rows: number[] = [];
2776
+ for (let i = 1; i <= 5000; ++i) {
2777
+ rows.push(i);
2778
+ }
2779
+ const cons = lConsistent.get();
2780
+ cons.add(tables);
2781
+
2782
+ echo.push('Row length: ' + rows.length.toString() + '<br>Old tables:');
2783
+ for (const table of tables) {
2784
+ echo.push(' ' + table);
2785
+ }
2786
+
2787
+ echo.push(`<pre>const newTables = ['table-5', 'table-6', 'table-7', 'table-8', 'table-9'];
2788
+ const rtn = cons.migration(rows, newTables);</pre>`);
2789
+
2790
+ // --- 即将增长到 10000 条数据,然后先模拟 5 表拆分为 10 表,再查看要迁移哪些数据,迁移量有多少 ---
2791
+ const newTables = ['table-5', 'table-6', 'table-7', 'table-8', 'table-9'];
2792
+ const rtn = cons.migration(rows, newTables);
2793
+
2794
+ const count = Object.keys(rtn).length;
2795
+ echo.push('Migration length: ' + count.toString() + '<br>Added new tables: ');
2796
+ for (const table of newTables) {
2797
+ echo.push(' ' + table);
2798
+ }
2799
+ echo.push('<br><br>');
2800
+
2801
+ let i = 0;
2802
+ echo.push('<table style="width: 100%;">');
2803
+ for (const key in rtn) {
2804
+ const item = rtn[key];
2805
+ echo.push('<tr><th>' + key + '</th><td>' + item.old + '</td><td>' + item.new + '</td></tr>');
2806
+ if (i === 199) {
2807
+ break;
2808
+ }
2809
+ ++i;
2810
+ }
2811
+ echo.push('</table>');
2812
+
2813
+ return echo.join('') + '... More ' + (count - 200).toString() + ' ...<br><br>' + this._getEnd();
2814
+ }
2815
+
2816
+ public consistentFast(): string {
2817
+ const echo: string[] = [];
2818
+
2819
+ let rtn = lConsistent.fast('a', lConsistent.getRange(0, 30));
2820
+ echo.push(`<pre>Consistent.fast('a', lConsistent.getRange(0, 30))</pre>`);
2821
+ echo.push(JSON.stringify(rtn));
2822
+
2823
+ rtn = lConsistent.fast('b', lConsistent.getRange(0, 30));
2824
+ echo.push(`<pre>Consistent.fast('b', lConsistent.getRange(0, 30))</pre>`);
2825
+ echo.push(JSON.stringify(rtn));
2826
+
2827
+ return echo.join('') + '<br><br>' + this._getEnd();
2828
+ }
2829
+
2830
+ public text(): string {
2831
+ const echo = `<pre>json_encode(lText.parseUrl('HtTp://uSer:pAss@sUBDom.TopdOm23.CoM:29819/Adm@xw2Ksiz/dszas?Mdi=KdiMs1&a=JDd#hehHe'))</pre>
2832
+ ${lText.htmlescape(JSON.stringify(lText.parseUrl('HtTp://uSer:pAss@sUBDom.TopdOm23.CoM:29819/Adm@xw2Ksiz/dszas?Mdi=KdiMs1&a=JDd#hehHe')))}
2833
+ <pre>json_encode(lText.parseUrl('HtTp://uSer@sUBDom.TopdOm23.CoM/Admx%20w2Ksiz/dszas'))</pre>
2834
+ ${lText.htmlescape(JSON.stringify(lText.parseUrl('HtTp://uSer@sUBDom.TopdOm23.CoM/Admx%20w2Ksiz/dszas')))}
2835
+ <pre>json_encode(lText.parseUrl('C:\\Windows\\Mi@sc'))</pre>
2836
+ ${lText.htmlescape(JSON.stringify(lText.parseUrl('C:\\Windows\\Mi@sc')))}
2837
+ <pre>json_encode(lText.parseUrl('../../abc?q=e'))</pre>
2838
+ ${lText.htmlescape(JSON.stringify(lText.parseUrl('../../abc?q=e')))}
2839
+ <pre>lText.urlResolve('/', 'path?id=1');</pre>
2840
+ ${lText.htmlescape(lText.urlResolve('/', 'path?id=1'))}
2841
+ <pre>lText.urlResolve('https://www.url.com/view/path', 'find');</pre>
2842
+ ${lText.htmlescape(lText.urlResolve('https://www.url.com/view/path', 'find'))}
2843
+ <pre>lText.urlResolve('https://www.url.com/view/path', '/');</pre>
2844
+ ${lText.htmlescape(lText.urlResolve('https://www.url.com/view/path', '/'))}
2845
+ <pre>lText.urlResolve('https://www.url.com/view/path/oh', '../ok/./index.js');</pre>
2846
+ ${lText.htmlescape(lText.urlResolve('https://www.url.com/view/path/oh', '../ok/./index.js'))}
2847
+ <pre>lText.urlResolve('https://www.url.com/view/path/oh', '../hah/../dodo/../112/666/777/../en');</pre>
2848
+ ${lText.htmlescape(lText.urlResolve('https://www.url.com/view/path/oh', '../hah/../dodo/../112/666/777/../en'))}
2849
+ <pre>lText.urlResolve('/hehe/ooo/', '../../../../../index.html');</pre>
2850
+ ${lText.htmlescape(lText.urlResolve('/hehe/ooo/', '../../../../../index.html'))}
2851
+ <pre>lText.urlResolve('https://www.url.com/view/path', '/xxx/yyy');</pre>
2852
+ ${lText.htmlescape(lText.urlResolve('https://www.url.com/view/path', '/xxx/yyy'))}
2853
+ <pre>lText.urlResolve('/', '//www.url.com/path');</pre>
2854
+ ${lText.htmlescape(lText.urlResolve('/', '//www.url.com/path'))}
2855
+ <pre>lText.urlResolve('http://www.url.com/path', 'hTtps://www.url.com/path');</pre>
2856
+ ${lText.htmlescape(lText.urlResolve('http://www.url.com/path', 'hTtps://www.url.com/path'))}
2857
+ <pre>lText.urlResolve('hTtp://www.url.com/path?ok=b', '?do=some');</pre>
2858
+ ${lText.htmlescape(lText.urlResolve('hTtp://www.url.com/path?ok=b', '?do=some'))}
2859
+ <pre>lText.urlResolve('/', 'C:\\Windows\\Boot');</pre>
2860
+ ${lText.htmlescape(lText.urlResolve('/', 'C:\\Windows\\Boot'))}
2861
+ <pre>lText.urlResolve('C:\\Windows\\Misc', '/');</pre>
2862
+ ${lText.htmlescape(lText.urlResolve('C:\\Windows\\Misc', '/'))}
2863
+ <pre>lText.urlResolve('C:\\Windows\\Misc', '/xxx/yyy');</pre>
2864
+ ${lText.htmlescape(lText.urlResolve('C:\\Windows\\Misc', '/xxx/yyy'))}
2865
+ <pre>lText.urlResolve('/abc/def/', '');</pre>
2866
+ ${lText.htmlescape(lText.urlResolve('/abc/def/', ''))}
2867
+ <pre>lText.isEMail('test@gmail.com');</pre>
2868
+ ${JSON.stringify(lText.isEMail('test@gmail.com'))}
2869
+ <pre>lText.isEMail('test@x');</pre>
2870
+ ${JSON.stringify(lText.isEMail('test@x'))}
2871
+ <pre>lText.isIPv4('192.168.0.1');</pre>
2872
+ ${JSON.stringify(lText.isIPv4('192.168.0.1'))}
2873
+ <pre>lText.isIPv4('192.168.0');</pre>
2874
+ ${JSON.stringify(lText.isIPv4('192.168.0'))}
2875
+ <pre>lText.isIPv6(':');</pre>
2876
+ ${JSON.stringify(lText.isIPv6(':'))}
2877
+ <pre>lText.isIPv6('::');</pre>
2878
+ ${JSON.stringify(lText.isIPv6('::'))}
2879
+ <pre>lText.isIPv6('::1');</pre>
2880
+ ${JSON.stringify(lText.isIPv6('::1'))}
2881
+ <pre>lText.isIPv6('::FFFF:C0A8:0201');</pre>
2882
+ ${JSON.stringify(lText.isIPv6('::FFFF:C0A8:0201'))}
2883
+ <pre>lText.isIPv6('2031:0000:1F1F:0000:0000:0100:11A0:ADDF');</pre>
2884
+ ${JSON.stringify(lText.isIPv6('2031:0000:1F1F:0000:0000:0100:11A0:ADDF'))}
2885
+ <pre>lText.isIPv6('2031:0000:1F1F:0000:0000:0100:11A0:ADDF:AZ');</pre>
2886
+ ${JSON.stringify(lText.isIPv6('2031:0000:1F1F:0000:0000:0100:11A0:ADDF:AZ'))}
2887
+ <pre>lText.isIPv6('::FFFF:192.168.0.1');</pre>
2888
+ ${JSON.stringify(lText.isIPv6('::FFFF:192.168.0.1'))}
2889
+ <pre>lText.isDomain('::FFFF:192.168.0.1');</pre>
2890
+ ${JSON.stringify(lText.isDomain('::FFFF:192.168.0.1'))}
2891
+ <pre>lText.isDomain('www.xxx.com.cn');</pre>
2892
+ ${JSON.stringify(lText.isDomain('www.xxx.com.cn'))}
2893
+ <pre>lText.isDomain('com');</pre>
2894
+ ${JSON.stringify(lText.isDomain('com'))}
2895
+ <pre>lText.parseDomain('www.xxx.com.cn');</pre>
2896
+ ${JSON.stringify(lText.parseDomain('www.xxx.com.cn'))}
2897
+ <pre>lText.parseDomain('www.xxx.us');</pre>
2898
+ ${JSON.stringify(lText.parseDomain('www.xxx.us'))}
2899
+ <pre>lText.parseDomain('xxx.co.jp');</pre>
2900
+ ${JSON.stringify(lText.parseDomain('xxx.co.jp'))}
2901
+ <pre>lText.parseDomain('js.cn');</pre>
2902
+ ${JSON.stringify(lText.parseDomain('js.cn'))}
2903
+ <pre>lText.parseDomain('xxx.cn');</pre>
2904
+ ${JSON.stringify(lText.parseDomain('xxx.cn'))}
2905
+ <pre>lText.parseJson('{"num":90071992547409993149,"num2":3242354,"num3":"16565","str":"abc","bool":false}');</pre>
2906
+ ${lText.stringifyJson(lText.parseJson('{"num":90071992547409993149,"num2":3242354,"num3":"16565","str":"abc","bool":false}'))}
2907
+ <pre>lText.isIdCardCN('110101200007284901')</pre>
2908
+ ${JSON.stringify(lText.isIdCardCN('110101200007284901'))}`;
2909
+ return echo + '<br><br>' + this._getEnd();
2910
+ }
2911
+
2912
+ public time(): string {
2913
+ const echo = `<pre>lTime.format(this, 'Y-m-d H:i:s');</pre>
2914
+ ${lTime.format(this, 'Y-m-d H:i:s')}
2915
+ <pre>lTime.format(0, 'Y-m-d H:i:s');</pre>
2916
+ ${lTime.format(0, 'Y-m-d H:i:s')}
2917
+ <pre>lTime.format(null, 'Y-m-d H:i:s');</pre>
2918
+ ${lTime.format(null, 'Y-m-d H:i:s')}
2919
+ <pre>lTime.format(9, 'Y-m-d H:i:s');</pre>
2920
+ ${lTime.format(9, 'Y-m-d H:i:s')}
2921
+ <pre>lTime.format(9.5, 'Y-m-d H:i:s');</pre>
2922
+ ${lTime.format(9.5, 'Y-m-d H:i:s')}
2923
+ <pre>lTime.format(null, 'd|D|j|l|N|w|Y|y|F|M|m|H|h|i|s|T');</pre>
2924
+ ${lTime.format(null, 'd|D|j|l|N|w|Y|y|F|M|m|H|h|i|s|T')}`;
2925
+ return echo + '<br><br>' + this._getEnd();
2926
+ }
2927
+
2928
+ public wsServer(): string {
2929
+ const echo = '<a href="' + this._config.const.urlBase + 'test/ws-server">Default</a> | ' +
2930
+ '<a href="' + this._config.const.urlBase + 'test/ws-server?ac=rproxy">rproxy</a> | ' +
2931
+ '<a href="' + this._config.const.urlBase + 'test">Return</a><br><br>' +
2932
+ `Nick: <input id="nick"> <input id="btn" type="button" value="Enter" onclick="enter()"> <input id="stop" type="button" value="Stop" onclick="stop()" disabled>
2933
+ <div id="list" style="border: solid 1px #000; line-height: 1.5; height: 300px; overflow-y: scroll; margin-top: 10px; padding: 10px;"></div>
2934
+ <div style="margin-top: 10px; display: flex;">
2935
+ <input id="text" style="flex: 1;">
2936
+ <input id="send" type="button" value="Send" onclick="send()" disabled style="margin-left: 10px;">
2937
+ </div>
2938
+ <script>
2939
+ var ws = null;
2940
+ var nickEl = document.getElementById('nick');
2941
+ var listEl = document.getElementById('list');
2942
+ var btnEl = document.getElementById('btn');
2943
+ var stopEl = document.getElementById('stop');
2944
+
2945
+ var textEl = document.getElementById('text');
2946
+ var sendEl = document.getElementById('send');
2947
+ function enter() {
2948
+ var nick = nickEl.value.trim();
2949
+ if (nick === '') {
2950
+ alert('Must input nick.');
2951
+ return;
2952
+ }
2953
+ nickEl.disabled = true;
2954
+ btnEl.disabled = true;
2955
+ listEl.insertAdjacentHTML('afterbegin', '<div>Connecting...</div>');
2956
+ ws = new WebSocket('ws${this._config.const.https ? 's' : ''}://${this._config.const.host}/${this._get['ac'] === 'rproxy' ? 'rproxy' : 'test'}');
2957
+ ws.onopen = function() {
2958
+ listEl.insertAdjacentHTML('afterbegin', '<div>Event: onOpen.</div>');
2959
+ ws.send('Hello: ' + nick);
2960
+ listEl.insertAdjacentHTML('afterbegin', '<div>Client: send "Hello: ' + nick + '".</div>');
2961
+ stopEl.disabled = false;
2962
+ sendEl.disabled = false;
2963
+ };
2964
+ ws.onmessage = function(ev) {
2965
+ listEl.insertAdjacentHTML('afterbegin', '<div>Server: ' + ev.data + '.</div>');
2966
+ };
2967
+ ws.onclose = function() {
2968
+ listEl.insertAdjacentHTML('afterbegin', '<div>Event: onClose.</div>');
2969
+ nickEl.disabled = false;
2970
+ btnEl.disabled = false;
2971
+ stopEl.disabled = true;
2972
+ sendEl.disabled = true;
2973
+ };
2974
+ ws.onerror = function(ev) {
2975
+ listEl.insertAdjacentHTML('afterbegin', '<div>Event: onError.</div>');
2976
+ nickEl.disabled = false;
2977
+ btnEl.disabled = false;
2978
+ stopEl.disabled = true;
2979
+ sendEl.disabled = true;
2980
+ };
2981
+ }
2982
+ function stop() {
2983
+ ws.close();
2984
+ ws = null;
2985
+ }
2986
+ function send() {
2987
+ ws.send(textEl.value);
2988
+ textEl.value = '';
2989
+ }
2990
+ </script>`;
2991
+ return echo + '<br>' + this._getEnd();
2992
+ }
2993
+
2994
+ public async wsClient(): Promise<string> {
2995
+ const ws = await lWs.connect('ws' + (this._config.const.https ? 's' : '') + '://' + this._config.const.host + '/test', {
2996
+ 'mproxy': this._get['ac'] === 'mproxy' ? {
2997
+ 'url': `ws${this._config.const.https ? 's' : ''}://${this._config.const.host}/mproxy`,
2998
+ 'auth': '123456'
2999
+ } : undefined
3000
+ });
3001
+ if (!ws) {
3002
+ return '<div>Connect "ws' + (this._config.const.https ? 's' : '') + '://' + this._config.const.host + '/test" failed.</div><br>' + this._getEnd();
3003
+ }
3004
+ const echo: string[] = ['<div>Connected "ws' + (this._config.const.https ? 's' : '') + '://' + this._config.const.host + '/test".</div>'];
3005
+ // --- 绑定事件 ---
3006
+ await new Promise<void>((resolve) => {
3007
+ (async () => {
3008
+ ws.on('message', (frame) => {
3009
+ echo.push('<div>Server: ' + frame.data.toString() + '.</div>');
3010
+ });
3011
+ ws.on('close', () => {
3012
+ resolve();
3013
+ });
3014
+ ws.writeText('Hello: clientws');
3015
+ echo.push('<div>Client: send "Hello: clientws".</div>');
3016
+ await lCore.sleep(1000);
3017
+ ws.writeText('aaa');
3018
+ await lCore.sleep(1000);
3019
+ ws.writeText('abc');
3020
+ await lCore.sleep(1000);
3021
+ ws.writeText('ok');
3022
+ await lCore.sleep(1000);
3023
+ ws.end();
3024
+ })().catch(() => {
3025
+ //
3026
+ });
3027
+ });
3028
+
3029
+ return echo.join('') + '<br>' + this._getEnd();
3030
+ }
3031
+
3032
+ public async ssh(): Promise<string | types.Json[]> {
3033
+ const retur: types.Json[] = [];
3034
+ if (!(this._checkInput(this._get, {
3035
+ 'type': ['require', ['shell', 'sftp'], [0, 'Type not found.']]
3036
+ }, retur))) {
3037
+ return retur;
3038
+ }
3039
+
3040
+ const host = '1.1.1.1';
3041
+ const port = 22;
3042
+ const user = 'root';
3043
+ const pwd = 'xxx';
3044
+
3045
+ // --- 连接 ssh 服务器 ---
3046
+ let ms = Date.now();
3047
+ const ssh = await lSsh.get({
3048
+ 'host': host,
3049
+ 'port': port,
3050
+ 'username': user,
3051
+ 'password': pwd
3052
+ });
3053
+ const echo: string[] = [
3054
+ `<pre>const ssh = await lSsh.get({
3055
+ 'host': '${host}',
3056
+ 'port': ${port},
3057
+ 'username': '${user}',
3058
+ 'password': '${pwd}'
3059
+ });</pre>`
3060
+ ];
3061
+ if (!ssh) {
3062
+ echo.push('Connection failed.');
3063
+ return echo.join('') + '<br><br>' + this._getEnd();
3064
+ }
3065
+ echo.push(`Connection successful, ${Date.now() - ms}ms.`);
3066
+
3067
+ // --- 执行一个命令 ---
3068
+ echo.push(`<pre>const rtn = await ssh.exec('ls');</pre>`);
3069
+ const rtn = await ssh.exec('ls');
3070
+ if (!rtn) {
3071
+ echo.push('Execution failed.');
3072
+ return echo.join('') + '<br><br>' + this._getEnd();
3073
+ }
3074
+ echo.push(lText.htmlescape(rtn.toString()));
3075
+
3076
+ if (this._get['type'] === 'shell') {
3077
+ // --- 获取 shell ---
3078
+ ms = Date.now();
3079
+ const shell = await ssh.getShell();
3080
+ echo.push(`<pre>const shell = await ssh.getShell();</pre>`);
3081
+ if (!shell) {
3082
+ echo.push(`Get failed.`);
3083
+ return echo.join('') + '<br><br>' + this._getEnd();
3084
+ }
3085
+ echo.push(`Get successful, ${Date.now() - ms}ms:<pre>${lText.htmlescape((await shell.getContent()).toString())}</pre>`);
3086
+
3087
+ // --- 执行一些命令 ---
3088
+ ms = Date.now();
3089
+ await shell.sendLine('cd ../../');
3090
+ echo.push(`await shell.sendLine('cd ../../'), ${Date.now() - ms}ms:<pre>${lText.htmlescape((await shell.getContent()).toString())}</pre>`);
3091
+
3092
+ await shell.sendLine('ls');
3093
+ ms = Date.now();
3094
+ echo.push(`await shell.sendLine('ls'), ${Date.now() - ms}ms:<pre>${lText.htmlescape((await shell.getContent()).toString())}</pre>`);
3095
+
3096
+ await shell.close();
3097
+ }
3098
+ else {
3099
+ // --- 获取 sftp ---
3100
+ ms = Date.now();
3101
+ const sftp = await ssh.getSftp();
3102
+ echo.push(`<pre>const sftp = await ssh.getSftp();</pre>`);
3103
+ if (!sftp) {
3104
+ echo.push(`Get failed.`);
3105
+ return echo.join('') + '<br><br>' + this._getEnd();
3106
+ }
3107
+ echo.push(`Get successful, ${Date.now() - ms}ms, ${sftp.pwd()}:`);
3108
+ const list = await sftp.readDir('./');
3109
+ echo.push(`<table width="100%"><tr><th>Name</th><th>Size</th><th>Uid</th><th>Gid</th><th>PMSN</th><th>Mode</th><th>Atime</th><th>Mtime</th></tr>`);
3110
+ for (const item of list) {
3111
+ echo.push(`<tr><td>${item.filename}</td><td>${lText.sizeFormat(item.attrs.size)}</td><td>${item.attrs.uid}</td><td>${item.attrs.gid}</td><td>${item.attrs.mode}</td><td>${item.attrs.mode.toString(8).slice(-4)}</td><td>${lTime.format(this, 'Y-m-d H:i:s', new Date(item.attrs.atime * 1000))}</td><td>${lTime.format(this, 'Y-m-d H:i:s', new Date(item.attrs.mtime * 1000))}</td></tr>`);
3112
+ }
3113
+ echo.push(`</table><br>`);
3114
+ }
3115
+
3116
+ ssh.disconnect();
3117
+
3118
+ return '<a href="' + this._config.const.urlBase + 'test/ssh?type=shell">shell</a> | ' +
3119
+ '<a href="' + this._config.const.urlBase + 'test/ssh?type=sftp">sftp</a> | ' +
3120
+ '<a href="' + this._config.const.urlBase + 'test">Return</a>' + echo.join('') + this._getEnd();
3121
+ }
3122
+
3123
+ public async s3(): Promise<string> {
3124
+ const s3 = lS3.get(this, {
3125
+ 'service': lS3.ESERVICE.AMAZON,
3126
+ 'region': 'ap-southeast-1',
3127
+ 'bucket': 'xxx'
3128
+ });
3129
+ const echo = [`<pre>const s3 = lS3.get(this, {
3130
+ 'service': lS3.SERVICE.AMAZON,
3131
+ 'region': 'ap-southeast-1',
3132
+ 'bucket': 'xxx'
3133
+ });</pre>`];
3134
+ const putr = await s3.putObject('a/b.txt', 'x');
3135
+ echo.push(`<pre>await s3.putObject('a/b.txt', 'x');</pre>` + (putr ? JSON.stringify(putr) : 'false'));
3136
+ const r = await s3.headObject('a.txt');
3137
+ echo.push(`<pre>await s3.headObject('a.txt');</pre>` + (r ? JSON.stringify(r) : 'false'));
3138
+ const r2 = await s3.deleteObjects(['a.txt', 'a/b.txt']);
3139
+ echo.push(`<pre>s3.deleteObjects(['a.txt', 'a/b.txt']);</pre>` + (r2 ? 'true' : 'false'));
3140
+ return echo.join('') + '<br><br>' + this._getEnd();
3141
+ }
3142
+
3143
+ public async zip(): Promise<string> {
3144
+ const path = this._config.const.dataPath + 'test.zip';
3145
+ const echo: string[] = ['Path: ' + path + '<br><br>'];
3146
+ const buf = await lFs.getContent(path);
3147
+ if (!buf) {
3148
+ return 'Failed<br><br>' + this._getEnd();
3149
+ }
3150
+ const z = await lZip.get(buf);
3151
+ if (!z) {
3152
+ return 'Failed<br><br>' + this._getEnd();
3153
+ }
3154
+ const ls = await z.getList();
3155
+ echo.push('<table style="width: 100%;"><tr>');
3156
+ if (Object.keys(ls).length) {
3157
+ for (const path in ls) {
3158
+ echo.push('<tr>');
3159
+ echo.push('<td>' + lText.htmlescape(path) + '</td>');
3160
+ echo.push('<td>' + lText.sizeFormat(z.stats(path)?.uncompressedSize ?? 0) + '</td>');
3161
+ echo.push('<td>' + Object.prototype.toString.call(ls[path]) + '</td>');
3162
+ echo.push('</tr>');
3163
+ }
3164
+ }
3165
+ else {
3166
+ echo.push('<th>Empty</th></tr>');
3167
+ }
3168
+ echo.push('</table>');
3169
+ return echo.join('') + '<br>' + this._getEnd();
3170
+ }
3171
+
3172
+ public buffer(): string {
3173
+ // --- 写 ---
3174
+ const writer = lBuffer.getWriter(8);
3175
+ writer.writeUInt8(8);
3176
+ writer.writeUInt16BE(2024);
3177
+ writer.writeBCDString('1213141516');
3178
+ const b = writer.get();
3179
+ const echo: string[] = [`<pre>const buf = lBuffer.getWriter(8);
3180
+ writer.writeUInt8(8);
3181
+ writer.writeUInt16BE(2024);
3182
+ writer.writeBCDString('1213141516');
3183
+ const b = writer.get();</pre>${b.toString('hex').replace(/(.{2})/g, '$1 ')}`];
3184
+ // --- 读 ---
3185
+ const reader = lBuffer.getReader(b);
3186
+ const rtn: any[] = [];
3187
+ rtn.push(reader.readUInt8());
3188
+ rtn.push(reader.readUInt16BE());
3189
+ rtn.push(reader.readBCDString());
3190
+ echo.push(`<pre>const reader = lBuffer.getReader(b);
3191
+ const rtn: any[] = [];
3192
+ rtn.push(reader.readUInt8());
3193
+ rtn.push(reader.readUInt16BE());
3194
+ rtn.push(reader.readBCDString());</pre>${JSON.stringify(rtn)}`);
3195
+ return echo.join('') + '<br><br>' + this._getEnd();
3196
+ }
3197
+
3198
+ public async lan(): Promise<string> {
3199
+ const echo: string[] = [];
3200
+
3201
+ const r = await lLan.card();
3202
+ echo.push(`<pre>lLan.card();</pre>` + JSON.stringify(r));
3203
+
3204
+ const r2 = await lLan.scan();
3205
+ echo.push(`<pre>await lLan.scan();</pre>` + JSON.stringify(r2));
3206
+
3207
+ return echo.join('') + '<br><br>' + this._getEnd();
3208
+ }
3209
+
3210
+ /**
3211
+ * --- END ---
3212
+ */
3213
+ private _getEnd(): string {
3214
+ const rt = this._getRunTime();
3215
+ return 'Processed in ' + rt.toString() + ' second(s), ' + (Math.round(rt * 10000000) / 10000).toString() + 'ms, ' + (Math.round(this._getMemoryUsage() / 1024 * 100) / 100).toString() + ' K.<style>*{font-family:Consolas,"Courier New",Courier,FreeMono,monospace;line-height: 1.5;font-size:12px;}pre{padding:10px;background-color:rgba(0,0,0,.07);white-space:pre-wrap;word-break:break-all;}hr{margin:20px 0;border-color:#000;border-style:dashed;border-width:1px 0 0 0;}td,th{padding:5px;border:solid 1px #000;}</style><meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no">';
3216
+ }
3217
+
3218
+ }