@maiyunnet/kebab 5.3.0 → 6.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.
- package/README.md +1 -1
- package/index.d.ts +2 -3
- package/index.js +6 -2
- package/lib/ai.d.ts +4 -3
- package/lib/ai.js +19 -11
- package/lib/buffer.d.ts +8 -4
- package/lib/buffer.js +16 -4
- package/lib/core.d.ts +24 -10
- package/lib/core.js +19 -12
- package/lib/crypto.d.ts +11 -2
- package/lib/crypto.js +6 -8
- package/lib/db/conn.js +1 -1
- package/lib/db/pool.js +1 -1
- package/lib/db.d.ts +5 -3
- package/lib/db.js +5 -3
- package/lib/dns.d.ts +17 -17
- package/lib/dns.js +44 -42
- package/lib/fs.d.ts +2 -2
- package/lib/fs.js +2 -2
- package/lib/kv.d.ts +22 -7
- package/lib/kv.js +28 -7
- package/lib/net/request.d.ts +1 -1
- package/lib/net.d.ts +6 -6
- package/lib/net.js +3 -3
- package/lib/scan.d.ts +3 -3
- package/lib/scan.js +3 -3
- package/lib/sql.d.ts +16 -5
- package/lib/sql.js +176 -257
- package/lib/ssh.d.ts +1 -2
- package/lib/text.d.ts +4 -4
- package/lib/text.js +2 -2
- package/lib/vector.d.ts +1 -1
- package/lib/vector.js +10 -4
- package/lib/ws.d.ts +0 -1
- package/lib/ws.js +0 -1
- package/lib/zip.d.ts +0 -1
- package/lib/zip.js +0 -1
- package/lib/zlib.d.ts +1 -2
- package/lib/zlib.js +1 -2
- package/package.json +6 -1
- package/sys/cmd.js +0 -7
- package/sys/ctr.d.ts +0 -2
- package/sys/ctr.js +0 -2
- package/sys/mod.d.ts +23 -9
- package/sys/mod.js +114 -12
- package/sys/route.js +0 -1
- package/www/example/ctr/test.d.ts +2 -2
- package/www/example/ctr/test.js +170 -93
- package/lib/jwt.d.ts +0 -73
- package/lib/jwt.js +0 -226
package/www/example/ctr/test.js
CHANGED
|
@@ -14,7 +14,6 @@ import * as lScan from '#kebab/lib/scan.js';
|
|
|
14
14
|
import * as lSql from '#kebab/lib/sql.js';
|
|
15
15
|
import * as lConsistent from '#kebab/lib/consistent.js';
|
|
16
16
|
import * as lSsh from '#kebab/lib/ssh.js';
|
|
17
|
-
import * as lJwt from '#kebab/lib/jwt.js';
|
|
18
17
|
import * as lWs from '#kebab/lib/ws.js';
|
|
19
18
|
import * as lS3 from '#kebab/lib/s3.js';
|
|
20
19
|
import * as lZip from '#kebab/lib/zip.js';
|
|
@@ -86,6 +85,8 @@ export default class extends sCtr.Ctr {
|
|
|
86
85
|
'<br>STATIC_PATH: ' + this._config.set.staticPath,
|
|
87
86
|
'<br>STATIC_PATH_FULL: ' + this._config.set.staticPathFull,
|
|
88
87
|
'<br>_internalUrl: ' + this._internalUrl,
|
|
88
|
+
'<br><br>ROOT_PATH: ' + this._config.const.rootPath,
|
|
89
|
+
'<br>ROOT_CWD: ' + kebab.ROOT_CWD,
|
|
89
90
|
'<br><br>headers: ' + lText.htmlescape(JSON.stringify(this._headers)),
|
|
90
91
|
'<br><br><b style="color: red;">Tips: The file can be deleted.</b>',
|
|
91
92
|
'<br><br><b>Route (route.json):</b>',
|
|
@@ -124,6 +125,8 @@ export default class extends sCtr.Ctr {
|
|
|
124
125
|
`<br><a href="${this._config.const.urlBase}test/mod-test">Click to see an example of a Test model</a> <a href="${this._config.const.urlBase}test/mod-test?s=pgsql">pgsql</a>`,
|
|
125
126
|
`<br><a href="${this._config.const.urlBase}test/mod-split">View "test/mod-split"</a>`,
|
|
126
127
|
`<br><a href="${this._config.const.urlBase}test/mod-insert">View "test/mod-insert"</a>`,
|
|
128
|
+
`<br><a href="${this._config.const.urlBase}test/mod-upsert">View "test/mod-upsert"</a>`,
|
|
129
|
+
`<br><a href="${this._config.const.urlBase}test/mod-update-list">View "test/mod-update-list"</a>`,
|
|
127
130
|
'<br><br><b>Library test:</b>',
|
|
128
131
|
`<br><br><b>Ai:</b>`,
|
|
129
132
|
`<br><br><a href="${this._config.const.urlBase}test/ai">View "test/ai"</a>`,
|
|
@@ -182,15 +185,12 @@ export default class extends sCtr.Ctr {
|
|
|
182
185
|
`<br><br><a href="${this._config.const.urlBase}test/sql?type=insert">View "test/sql?type=insert"</a> <a href="${this._config.const.urlBase}test/sql?type=insert&s=pgsql">pgsql</a>`,
|
|
183
186
|
`<br><a href="${this._config.const.urlBase}test/sql?type=select">View "test/sql?type=select"</a> <a href="${this._config.const.urlBase}test/sql?type=select&s=pgsql">pgsql</a>`,
|
|
184
187
|
`<br><a href="${this._config.const.urlBase}test/sql?type=update">View "test/sql?type=update"</a> <a href="${this._config.const.urlBase}test/sql?type=update&s=pgsql">pgsql</a>`,
|
|
188
|
+
`<br><a href="${this._config.const.urlBase}test/sql?type=upsert">View "test/sql?type=upsert"</a> <a href="${this._config.const.urlBase}test/sql?type=upsert&s=pgsql">pgsql</a>`,
|
|
185
189
|
`<br><a href="${this._config.const.urlBase}test/sql?type=delete">View "test/sql?type=delete"</a> <a href="${this._config.const.urlBase}test/sql?type=delete&s=pgsql">pgsql</a>`,
|
|
186
190
|
`<br><a href="${this._config.const.urlBase}test/sql?type=where">View "test/sql?type=where"</a> <a href="${this._config.const.urlBase}test/sql?type=where&s=pgsql">pgsql</a>`,
|
|
187
191
|
`<br><a href="${this._config.const.urlBase}test/sql?type=having">View "test/sql?type=having"</a> <a href="${this._config.const.urlBase}test/sql?type=having&s=pgsql">pgsql</a>`,
|
|
188
192
|
`<br><a href="${this._config.const.urlBase}test/sql?type=by">View "test/sql?type=by"</a> <a href="${this._config.const.urlBase}test/sql?type=by&s=pgsql">pgsql</a>`,
|
|
189
193
|
`<br><a href="${this._config.const.urlBase}test/sql?type=field">View "test/sql?type=field"</a> <a href="${this._config.const.urlBase}test/sql?type=field&s=pgsql">pgsql</a>`,
|
|
190
|
-
'<br><br><b>Jwt:</b>',
|
|
191
|
-
`<br><br><a href="${this._config.const.urlBase}test/jwt">View "test/jwt"</a>`,
|
|
192
|
-
`<br><a href="${this._config.const.urlBase}test/jwt?type=kv">View "test/jwt?type=kv"</a>`,
|
|
193
|
-
`<br><a href="${this._config.const.urlBase}test/jwt?type=auth">View "test/jwt?type=auth" Header Authorization</a>`,
|
|
194
194
|
'<br><br><b>Consistent:</b>',
|
|
195
195
|
`<br><br><a href="${this._config.const.urlBase}test/consistent-hash">View "test/consistent-hash"</a>`,
|
|
196
196
|
`<br><a href="${this._config.const.urlBase}test/consistent-distributed">View "test/consistent-distributed"</a>`,
|
|
@@ -281,7 +281,7 @@ Result:<pre id="result">Nothing.</pre>${this._getEnd()}`;
|
|
|
281
281
|
'num2': ['> 0', '<= 100', [0, 'The num2 param must > 0.']],
|
|
282
282
|
'reg': ['/^[A-CX-Z5-7]+$/', [0, 'The reg param is incorrect.']],
|
|
283
283
|
'arr': [['a', 'x', 'hehe'], [0, 'The arr param is incorrect.']],
|
|
284
|
-
'type': [{ 'type': { 'a': 1, 'b': '' } }, [0, 'The
|
|
284
|
+
'type': [{ 'type': { 'a': 1, 'b': '' } }, [0, 'The type param is incorrect']],
|
|
285
285
|
'json': [{ 'type': { 'a': '1', 'b': [ { 'c': 1 } ] } }, [0, 'The type param is incorrect']],
|
|
286
286
|
'json2': [{ 'type': { 'a': '1', 'b': 0, 'c?': { 'd': '1' } } }, [0, 'The json2 param is incorrect']],
|
|
287
287
|
}</pre>`];
|
|
@@ -841,6 +841,127 @@ CREATE TABLE \`m_test_data_0\` (
|
|
|
841
841
|
echo.push('<br><br>Result: ' + JSON.stringify(res));
|
|
842
842
|
return echo.join('') + '<br><br>' + this._getEnd();
|
|
843
843
|
}
|
|
844
|
+
async modUpsert() {
|
|
845
|
+
const echo = ['<b style="color: red;">In a production environment, please delete "mod/test.ts" and "mod/testdata.ts" files.</b>'];
|
|
846
|
+
const db = this._get['s'] === 'pgsql' ? lDb.get(this, {
|
|
847
|
+
'service': lDb.ESERVICE.PGSQL,
|
|
848
|
+
}) : lDb.get(this);
|
|
849
|
+
// --- 1. 第一次 Upsert (插入新记录) ---
|
|
850
|
+
echo.push('<b>Test 1: Insert new record (default conflict field)</b><br>');
|
|
851
|
+
const test1 = mTest.getCreate(db, {
|
|
852
|
+
'ctr': this,
|
|
853
|
+
'pre': this._get['s'] === 'pgsql' ? 'm' : undefined,
|
|
854
|
+
});
|
|
855
|
+
test1.set({
|
|
856
|
+
'name': lCore.random(4),
|
|
857
|
+
'point': { 'x': 10, 'y': 10 },
|
|
858
|
+
'time_add': lTime.stamp(),
|
|
859
|
+
});
|
|
860
|
+
const res1 = await test1.upsert('name');
|
|
861
|
+
echo.push(`<pre>const test1 = mTest.getCreate(db);
|
|
862
|
+
test1.set({
|
|
863
|
+
'name': '${test1.name}',
|
|
864
|
+
'point': { 'x': 10, 'y': 10 },
|
|
865
|
+
'time_add': ${test1.time_add},
|
|
866
|
+
});
|
|
867
|
+
const res1 = await test1.upsert('name');
|
|
868
|
+
</pre>Result: ${res1}<br><br>`);
|
|
869
|
+
let stmt = await db.query(this._get['s'] === 'pgsql' ?
|
|
870
|
+
`SELECT * FROM "m"."test" WHERE "token" LIKE \'test_%\' ORDER BY "id" ASC;` :
|
|
871
|
+
'SELECT * FROM `m_test` WHERE `token` LIKE \'test_%\' ORDER BY `id` ASC;');
|
|
872
|
+
this._dbTable(stmt, echo);
|
|
873
|
+
// --- 2. 第二次 Upsert (更新已有记录) ---
|
|
874
|
+
echo.push('<br><b>Test 2: Update existing record (same name)</b><br>');
|
|
875
|
+
const test2 = mTest.getCreate(db, {
|
|
876
|
+
'ctr': this,
|
|
877
|
+
'pre': this._get['s'] === 'pgsql' ? 'm' : undefined,
|
|
878
|
+
});
|
|
879
|
+
test2.set({
|
|
880
|
+
'name': test1.name, // --- 相同的 name ---
|
|
881
|
+
'point': { 'x': 20, 'y': 20 },
|
|
882
|
+
'time_add': lTime.stamp(),
|
|
883
|
+
});
|
|
884
|
+
const res2 = await test2.upsert('name');
|
|
885
|
+
echo.push(`<pre>const test2 = mTest.getCreate(db);
|
|
886
|
+
test2.set({
|
|
887
|
+
'name': '${test1.name}',
|
|
888
|
+
'point': { 'x': 20, 'y': 20 },
|
|
889
|
+
'time_add': ${test2.time_add},
|
|
890
|
+
});
|
|
891
|
+
const res2 = await test2.upsert('name');</pre>Result: ${res2}<br><br>`);
|
|
892
|
+
stmt = await db.query(this._get['s'] === 'pgsql' ?
|
|
893
|
+
`SELECT * FROM "m"."test" WHERE "token" LIKE \'test_%\' ORDER BY "id" ASC;` :
|
|
894
|
+
'SELECT * FROM `m_test` WHERE `token` LIKE \'test_%\' ORDER BY `id` ASC;');
|
|
895
|
+
this._dbTable(stmt, echo);
|
|
896
|
+
// --- 清理测试数据 ---
|
|
897
|
+
await mTest.removeByWhere(db, [
|
|
898
|
+
['token', 'LIKE', 'test_%']
|
|
899
|
+
], {
|
|
900
|
+
'ctr': this,
|
|
901
|
+
'pre': this._get['s'] === 'pgsql' ? 'm' : undefined,
|
|
902
|
+
});
|
|
903
|
+
return echo.join('') + '<br>' + this._getEnd();
|
|
904
|
+
}
|
|
905
|
+
async modUpdateList() {
|
|
906
|
+
const echo = ['<b style="color: red;">In a production environment, please delete "mod/test.ts" and "mod/testdata.ts" files.</b>'];
|
|
907
|
+
const db = this._get['s'] === 'pgsql' ? lDb.get(this, {
|
|
908
|
+
'service': lDb.ESERVICE.PGSQL,
|
|
909
|
+
}) : lDb.get(this);
|
|
910
|
+
// --- 准备数据 ---
|
|
911
|
+
const time = lTime.stamp();
|
|
912
|
+
const data = [];
|
|
913
|
+
for (let i = 0; i < 5; ++i) {
|
|
914
|
+
data.push({
|
|
915
|
+
'name': 'ul_' + i,
|
|
916
|
+
'token': 'ul_token_' + i,
|
|
917
|
+
'point': { 'x': i, 'y': i },
|
|
918
|
+
'time_add': time,
|
|
919
|
+
});
|
|
920
|
+
}
|
|
921
|
+
// --- 插入数据 ---
|
|
922
|
+
await mTest.insert(db, ['name', 'token', 'point', 'time_add'], data.map(item => [item.name, item.token, item.point, item.time_add]), {
|
|
923
|
+
'ctr': this,
|
|
924
|
+
'pre': this._get['s'] === 'pgsql' ? 'm' : undefined,
|
|
925
|
+
});
|
|
926
|
+
echo.push('<br><br>Inserted 5 rows.<br><br>');
|
|
927
|
+
// --- 查询插入的数据 ---
|
|
928
|
+
let stmt = await db.query(this._get['s'] === 'pgsql' ?
|
|
929
|
+
`SELECT * FROM "m"."test" WHERE "token" LIKE 'ul_token_%' ORDER BY "id" ASC;` :
|
|
930
|
+
`SELECT * FROM \`m_test\` WHERE \`token\` LIKE 'ul_token_%' ORDER BY \`id\` ASC;`);
|
|
931
|
+
this._dbTable(stmt, echo);
|
|
932
|
+
// --- 构造批量更新数据 ---
|
|
933
|
+
// --- 更新 name 和 point ---
|
|
934
|
+
const updateData = [];
|
|
935
|
+
if (stmt.rows) {
|
|
936
|
+
for (let i = 0; i < stmt.rows.length; ++i) {
|
|
937
|
+
const row = stmt.rows[i];
|
|
938
|
+
updateData.push({
|
|
939
|
+
'id': row.id,
|
|
940
|
+
'name': 'up_' + i,
|
|
941
|
+
'point': { 'x': i + 10, 'y': i + 10 }
|
|
942
|
+
});
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
// --- 执行批量更新 ---
|
|
946
|
+
const res = await mTest.updateList(db, updateData, 'id', {
|
|
947
|
+
'ctr': this,
|
|
948
|
+
'pre': this._get['s'] === 'pgsql' ? 'm' : undefined,
|
|
949
|
+
});
|
|
950
|
+
echo.push(`<br><b>updateList result:</b> ${lText.stringifyJson(res)}<br><br>`);
|
|
951
|
+
// --- 查询更新后的数据 ---
|
|
952
|
+
stmt = await db.query(this._get['s'] === 'pgsql' ?
|
|
953
|
+
`SELECT * FROM "m"."test" WHERE "token" LIKE 'ul_token_%' ORDER BY "id" ASC;` :
|
|
954
|
+
`SELECT * FROM \`m_test\` WHERE \`token\` LIKE 'ul_token_%' ORDER BY \`id\` ASC;`);
|
|
955
|
+
this._dbTable(stmt, echo);
|
|
956
|
+
// --- 清理数据 ---
|
|
957
|
+
await mTest.removeByWhere(db, [
|
|
958
|
+
['token', 'LIKE', 'ul_token_%']
|
|
959
|
+
], {
|
|
960
|
+
'ctr': this,
|
|
961
|
+
'pre': this._get['s'] === 'pgsql' ? 'm' : undefined,
|
|
962
|
+
});
|
|
963
|
+
return echo.join('') + '<br>' + this._getEnd();
|
|
964
|
+
}
|
|
844
965
|
captchaFastbuild() {
|
|
845
966
|
return lCaptcha.get(400, 100).getBuffer();
|
|
846
967
|
}
|
|
@@ -1089,7 +1210,7 @@ for (let i = 0; i < 30000; ++i) {
|
|
|
1089
1210
|
const echo = [];
|
|
1090
1211
|
echo.push('<table style="width: 100%;">');
|
|
1091
1212
|
if (list) {
|
|
1092
|
-
echo.push('<tr><th>TIME</th><th>UNIX</th><th>URL</th><th>COOKIE</th><th>SESSION</th><th>
|
|
1213
|
+
echo.push('<tr><th>TIME</th><th>UNIX</th><th>URL</th><th>COOKIE</th><th>SESSION</th><th>USER_AGENT</th><th>REALIP</th><th>CLIENTIP</th><th>OS</th><th>PROCESS</th><th>MESSAGE</th></tr>');
|
|
1093
1214
|
for (const row of list) {
|
|
1094
1215
|
echo.push('<tr>');
|
|
1095
1216
|
for (const item of row) {
|
|
@@ -1766,7 +1887,7 @@ lCore.setCookie(this, 'test10', 'httponly', {
|
|
|
1766
1887
|
});</pre>
|
|
1767
1888
|
headers: <pre>${JSON.stringify(res.headers, null, 4)}</pre>
|
|
1768
1889
|
content: <pre>${(await res.getContent())?.toString() ?? 'null'}</pre>
|
|
1769
|
-
error: ${JSON.stringify(res.error)}
|
|
1890
|
+
error: ${JSON.stringify(res.error)}`);
|
|
1770
1891
|
return echo.join('') + this._getEnd();
|
|
1771
1892
|
}
|
|
1772
1893
|
async netFollow() {
|
|
@@ -2192,65 +2313,6 @@ Result:<pre id="result">Nothing.</pre>`);
|
|
|
2192
2313
|
}
|
|
2193
2314
|
}
|
|
2194
2315
|
}
|
|
2195
|
-
async jwt() {
|
|
2196
|
-
const retur = [];
|
|
2197
|
-
if (!(this._checkInput(this._get, {
|
|
2198
|
-
'type': [['', 'kv', 'auth'], [0, 'Bad request.']]
|
|
2199
|
-
}, retur))) {
|
|
2200
|
-
return retur;
|
|
2201
|
-
}
|
|
2202
|
-
const echo = ['<pre>'];
|
|
2203
|
-
let link = undefined;
|
|
2204
|
-
if (this._get['type'] === 'kv') {
|
|
2205
|
-
link = lKv.get(this);
|
|
2206
|
-
echo.push('link = lKv.get(this);\n');
|
|
2207
|
-
}
|
|
2208
|
-
const origin = lJwt.getOrigin(this);
|
|
2209
|
-
echo.push(`const origin = lJwt.getOrigin(this);
|
|
2210
|
-
JSON.stringify(origin);</pre>`);
|
|
2211
|
-
echo.push(JSON.stringify(origin));
|
|
2212
|
-
// --- 创建 jwt 对象 ---
|
|
2213
|
-
const jwt = await lJwt.get(this, {}, link);
|
|
2214
|
-
echo.push(`<pre>const jwt = lJwt.get(this, {}, ${link ? 'link' : 'undefined'});
|
|
2215
|
-
JSON.stringify(this._jwt);</pre>`);
|
|
2216
|
-
echo.push(JSON.stringify(this._jwt));
|
|
2217
|
-
this._jwt['test'] = 'a';
|
|
2218
|
-
const value = jwt.renew();
|
|
2219
|
-
echo.push(`<pre>this._jwt['test'] = 'a';
|
|
2220
|
-
const value = jwt.renew();
|
|
2221
|
-
JSON.stringify(this._jwt);</pre>`);
|
|
2222
|
-
echo.push(JSON.stringify(this._jwt));
|
|
2223
|
-
echo.push(`<pre>JSON.stringify(value);</pre>`);
|
|
2224
|
-
echo.push(JSON.stringify(value));
|
|
2225
|
-
const token = this._jwt['token'];
|
|
2226
|
-
const rtn = await jwt.destory();
|
|
2227
|
-
echo.push(`<pre>const token = this._jwt['token'];
|
|
2228
|
-
const rtn = await jwt.destory();
|
|
2229
|
-
JSON.stringify(rtn);</pre>`);
|
|
2230
|
-
echo.push(JSON.stringify(rtn));
|
|
2231
|
-
echo.push('<pre>JSON.stringify(this._jwt);</pre>');
|
|
2232
|
-
echo.push(JSON.stringify(this._jwt));
|
|
2233
|
-
const rtn2 = await lJwt.decode(this, origin, link);
|
|
2234
|
-
echo.push(`<pre>const rtn2 = await lJwt.decode(this, origin, ${link ? 'link' : 'undefined'});
|
|
2235
|
-
JSON.stringify(rtn2);</pre>`);
|
|
2236
|
-
echo.push(JSON.stringify(rtn2));
|
|
2237
|
-
if (this._get['type'] === 'auth') {
|
|
2238
|
-
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>
|
|
2239
|
-
Token: <span id="token">${token}</span><br>
|
|
2240
|
-
Post Authorization header: <span id="_auth">Bearer ${origin}</span><br><br>
|
|
2241
|
-
Result:<pre id="result">Nothing.</pre>`);
|
|
2242
|
-
}
|
|
2243
|
-
else {
|
|
2244
|
-
echo.push('<br><br>');
|
|
2245
|
-
}
|
|
2246
|
-
return echo.join('') + this._getEnd();
|
|
2247
|
-
}
|
|
2248
|
-
async jwt1() {
|
|
2249
|
-
await lJwt.get(this, {
|
|
2250
|
-
'auth': true
|
|
2251
|
-
});
|
|
2252
|
-
return [1, { 'txt': JSON.stringify(this._jwt) }];
|
|
2253
|
-
}
|
|
2254
2316
|
sql() {
|
|
2255
2317
|
const echo = [];
|
|
2256
2318
|
let sql = this._get['s'] === 'pgsql' ? lSql.get('test', {
|
|
@@ -2292,18 +2354,10 @@ Result:<pre id="result">Nothing.</pre>`);
|
|
|
2292
2354
|
s = sql.insert('geo').values(['name', 'point', 'point2', 'polygon', 'json'], [
|
|
2293
2355
|
[
|
|
2294
2356
|
'POINT A', ['ST_POINTFROMTEXT(?)', ['POINT(122.147775 30.625015)']], { 'x': 1, 'y': 1 }, [
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
{ 'x': 1, 'y': 1 }
|
|
2300
|
-
],
|
|
2301
|
-
[
|
|
2302
|
-
{ 'x': 6, 'y': 1 },
|
|
2303
|
-
{ 'x': 7, 'y': 2 },
|
|
2304
|
-
{ 'x': 8, 'y': 3 },
|
|
2305
|
-
{ 'x': 6, 'y': 1 }
|
|
2306
|
-
]
|
|
2357
|
+
{ 'x': 1, 'y': 1 },
|
|
2358
|
+
{ 'x': 2, 'y': 2 },
|
|
2359
|
+
{ 'x': 3, 'y': 3 },
|
|
2360
|
+
{ 'x': 1, 'y': 1 }
|
|
2307
2361
|
],
|
|
2308
2362
|
{ 'x': { 'y': 'ghi' } }
|
|
2309
2363
|
],
|
|
@@ -2315,18 +2369,10 @@ Result:<pre id="result">Nothing.</pre>`);
|
|
|
2315
2369
|
echo.push(`<pre>sql.insert('geo').values(['name', 'point', 'point2', 'polygon', 'json'], [
|
|
2316
2370
|
[
|
|
2317
2371
|
'POINT A', ['ST_POINTFROMTEXT(?)', ['POINT(122.147775 30.625015)']], { 'x': 1, 'y': 1 }, [
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
{ 'x': 1, 'y': 1 }
|
|
2323
|
-
],
|
|
2324
|
-
[
|
|
2325
|
-
{ 'x': 6, 'y': 1 },
|
|
2326
|
-
{ 'x': 7, 'y': 2 },
|
|
2327
|
-
{ 'x': 8, 'y': 3 },
|
|
2328
|
-
{ 'x': 6, 'y': 1 }
|
|
2329
|
-
]
|
|
2372
|
+
{ 'x': 1, 'y': 1 },
|
|
2373
|
+
{ 'x': 2, 'y': 2 },
|
|
2374
|
+
{ 'x': 3, 'y': 3 },
|
|
2375
|
+
{ 'x': 1, 'y': 1 }
|
|
2330
2376
|
],
|
|
2331
2377
|
{ 'x': { 'y': 'ghi' } }
|
|
2332
2378
|
],
|
|
@@ -2438,6 +2484,37 @@ Result:<pre id="result">Nothing.</pre>`);
|
|
|
2438
2484
|
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>
|
|
2439
2485
|
<b>getSql() :</b> ${s}<br>
|
|
2440
2486
|
<b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
|
|
2487
|
+
<b>format() :</b> ${sql.format(s, sd)}`);
|
|
2488
|
+
break;
|
|
2489
|
+
}
|
|
2490
|
+
case 'upsert': {
|
|
2491
|
+
// --- 对象形式 ---
|
|
2492
|
+
let s = sql.insert('user').values({ 'id': 1, 'name': 'Bob', 'age': 25 }).upsert({ 'name': 'Updated Bob', 'age': 26 }).getSql();
|
|
2493
|
+
let sd = sql.getData();
|
|
2494
|
+
echo.push(`<pre>sql.insert('user').values({ 'id': 1, 'name': 'Bob', 'age': 25 }).upsert({ 'name': 'Updated Bob', 'age': 26 });</pre>
|
|
2495
|
+
<b>getSql() :</b> ${s}<br>
|
|
2496
|
+
<b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
|
|
2497
|
+
<b>format() :</b> ${sql.format(s, sd)}<hr>`);
|
|
2498
|
+
// --- 数组形式 ---
|
|
2499
|
+
s = sql.insert('user').values(['id', 'name', 'age'], [1, 'Alice', 30]).upsert({ 'name': 'Updated Alice', 'age': 31 }).getSql();
|
|
2500
|
+
sd = sql.getData();
|
|
2501
|
+
echo.push(`<pre>sql.insert('user').values(['id', 'name', 'age'], [1, 'Alice', 30]).upsert({ 'name': 'Updated Alice', 'age': 31 });</pre>
|
|
2502
|
+
<b>getSql() :</b> ${s}<br>
|
|
2503
|
+
<b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
|
|
2504
|
+
<b>format() :</b> ${sql.format(s, sd)}<hr>`);
|
|
2505
|
+
// --- 列引用 ---
|
|
2506
|
+
s = sql.insert('user').values({ 'id': 1, 'name': 'Charlie', 'age': 35 }).upsert([{ 'name': 'abc' }, ['age', '+', lSql.column('age')]]).getSql();
|
|
2507
|
+
sd = sql.getData();
|
|
2508
|
+
echo.push(`<pre>sql.insert('user').values({ 'id': 1, 'name': 'Charlie', 'age': 35 }).upsert([ { 'name': 'abc' }, ['age', '+', lSql.column('age')] ]);</pre>
|
|
2509
|
+
<b>getSql() :</b> ${s}<br>
|
|
2510
|
+
<b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
|
|
2511
|
+
<b>format() :</b> ${sql.format(s, sd)}<hr>`);
|
|
2512
|
+
// --- 多字段 ---
|
|
2513
|
+
s = sql.insert('user').values({ 'id': 1, 'name': 'Dave', 'age': 40, 'city': 'Beijing' }).upsert({ 'name': 'Updated Dave', 'age': 41, 'city': 'Shanghai' }).getSql();
|
|
2514
|
+
sd = sql.getData();
|
|
2515
|
+
echo.push(`<pre>sql.insert('user').values({ 'id': 1, 'name': 'Dave', 'age': 40, 'city': 'Beijing' }).upsert({ 'name': 'Updated Dave', 'age': 41, 'city': 'Shanghai' });</pre>
|
|
2516
|
+
<b>getSql() :</b> ${s}<br>
|
|
2517
|
+
<b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
|
|
2441
2518
|
<b>format() :</b> ${sql.format(s, sd)}`);
|
|
2442
2519
|
break;
|
|
2443
2520
|
}
|
|
@@ -2602,7 +2679,7 @@ Result:<pre id="result">Nothing.</pre>`);
|
|
|
2602
2679
|
echo.push(`<pre>sql.field('SUM(num) all');</pre>` + sql.field('SUM(num) all'));
|
|
2603
2680
|
echo.push(`<pre>sql.field('SUM(x.num) all');</pre>` + sql.field('SUM(x.num) all'));
|
|
2604
2681
|
echo.push(`<pre>sql.field('SUM(x.\`num\`) all');</pre>` + sql.field('SUM(x.`num`) all'));
|
|
2605
|
-
echo.push(`<pre>sql.field('FROM_UNIXTIME(time, \\'%Y-%m-%d\\') time');</pre>` + sql.field(
|
|
2682
|
+
echo.push(`<pre>sql.field('FROM_UNIXTIME(time, \\'%Y-%m-%d\\') time');</pre>` + sql.field(`FROM_UNIXTIME(time, '%Y-%m-%d') time`));
|
|
2606
2683
|
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`))))'));
|
|
2607
2684
|
echo.push(`<pre>sql.field('MATCH(name_sc, name_tc) AGAINST("ok") tmp'));</pre>` + sql.field('MATCH(name_sc, name_tc) AGAINST("ok") tmp'));
|
|
2608
2685
|
echo.push(`<pre>sql.field('a\\'bc');</pre>` + sql.field('a\'bc'));
|
|
@@ -3094,7 +3171,7 @@ rtn.push(reader.readBCDString());</pre>${JSON.stringify(rtn)}`);
|
|
|
3094
3171
|
// --- 注意,这个只是演示,你实际需要在 ind 目录中创建计划任务 ---
|
|
3095
3172
|
// --- 并用 --ind 单线程模式运行 ---
|
|
3096
3173
|
const echo = [];
|
|
3097
|
-
|
|
3174
|
+
const rtn = await lCron.regular({
|
|
3098
3175
|
'name': 'test',
|
|
3099
3176
|
'rule': '40 * * * *',
|
|
3100
3177
|
'callback': (date, immediate) => {
|
package/lib/jwt.d.ts
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Project: Kebab, User: JianSuoQiYue
|
|
3
|
-
* Date: 2023-1-31 20:34:47
|
|
4
|
-
* Last: 2023-1-31 20:34:47, 2023-12-8 13:55:09, 2025-11-6 16:22:06
|
|
5
|
-
*/
|
|
6
|
-
import * as kebab from '#kebab/index.js';
|
|
7
|
-
import * as lKv from '#kebab/lib/kv.js';
|
|
8
|
-
import * as sCtr from '#kebab/sys/ctr.js';
|
|
9
|
-
export interface IOptions {
|
|
10
|
-
'name'?: string;
|
|
11
|
-
'ttl'?: number;
|
|
12
|
-
'ssl'?: boolean;
|
|
13
|
-
'secret'?: string;
|
|
14
|
-
'auth'?: boolean;
|
|
15
|
-
}
|
|
16
|
-
export declare class Jwt {
|
|
17
|
-
/** --- Kv --- */
|
|
18
|
-
private _link?;
|
|
19
|
-
/** --- 在前端或 Kv 中储存的名前缀 --- */
|
|
20
|
-
private _name;
|
|
21
|
-
/** --- 有效期 --- */
|
|
22
|
-
private _ttl;
|
|
23
|
-
/** --- cookie 模式时是否仅支持 SSL --- */
|
|
24
|
-
private _ssl;
|
|
25
|
-
/** --- 验证密钥 --- */
|
|
26
|
-
private _secret;
|
|
27
|
-
/** --- 是否从头部读取 --- */
|
|
28
|
-
private _auth;
|
|
29
|
-
/** --- ctr 对象 --- */
|
|
30
|
-
private _ctr;
|
|
31
|
-
/**
|
|
32
|
-
* --- 初始化函数,相当于 construct ---
|
|
33
|
-
* @param ctr 模型实例
|
|
34
|
-
* @param link Kv 或 Db 实例
|
|
35
|
-
* @param auth 设为 true 则优先从头 Authorization 或 post _auth 值读取 token
|
|
36
|
-
* @param opt 选项
|
|
37
|
-
*/
|
|
38
|
-
init(ctr: sCtr.Ctr, opt?: IOptions, link?: lKv.Kv): Promise<boolean>;
|
|
39
|
-
/**
|
|
40
|
-
* --- 将 _jwt 数据封装并返回(创建新的或者续期老的 token),默认会同时设置一个 cookie(data 值会自动设置 token、exp) ---
|
|
41
|
-
*/
|
|
42
|
-
renew(): string;
|
|
43
|
-
/**
|
|
44
|
-
* --- 清除 cookie,仅仅清除 cookie,jwt 并不会失效 ---
|
|
45
|
-
*/
|
|
46
|
-
clearCookie(): void;
|
|
47
|
-
/**
|
|
48
|
-
* --- 销毁 jwt,其实就是将 token block 信息写入 redis,如果没有 redis 则不能销毁,返回数组代表销毁成功的 token 和原 exp,否则失败返回 false ---
|
|
49
|
-
*/
|
|
50
|
-
destory(): Promise<{
|
|
51
|
-
token: string;
|
|
52
|
-
exp: number;
|
|
53
|
-
} | boolean>;
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* --- 获取 jwt 原始字符串,不保证有效 ---
|
|
57
|
-
*/
|
|
58
|
-
export declare function getOrigin(ctr: sCtr.Ctr, name?: string, auth?: boolean): string;
|
|
59
|
-
/**
|
|
60
|
-
* --- decode ---
|
|
61
|
-
* 不传入 link 的话,将不做 block 有效校验,只做本身的 exp 有效校验
|
|
62
|
-
*/
|
|
63
|
-
export declare function decode(ctr: sCtr.Ctr, val: string, link?: lKv.Kv, name?: string, secret?: string): Promise<Record<string, kebab.DbValue> | false>;
|
|
64
|
-
/**
|
|
65
|
-
* --- 仅往 redis 写禁止相关 token 的数据,一般用于异步通知时在异处的服务器来调用的 ---
|
|
66
|
-
*/
|
|
67
|
-
export declare function block(ctr: sCtr.Ctr, token: string, exp: number, link: lKv.Kv, name?: string): Promise<boolean>;
|
|
68
|
-
/**
|
|
69
|
-
* @param ctr 模型实例
|
|
70
|
-
* @param opt name, ttl, ssl, secret, auth: false, true 则优先从头 Authorization 或 post _auth 值读取 token
|
|
71
|
-
* @param link 实例
|
|
72
|
-
*/
|
|
73
|
-
export declare function get(ctr: sCtr.Ctr, opt?: IOptions, link?: lKv.Kv): Promise<Jwt>;
|
package/lib/jwt.js
DELETED
|
@@ -1,226 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Project: Kebab, User: JianSuoQiYue
|
|
3
|
-
* Date: 2023-1-31 20:34:47
|
|
4
|
-
* Last: 2023-1-31 20:34:47, 2023-12-8 13:55:09, 2025-11-6 16:22:06
|
|
5
|
-
*/
|
|
6
|
-
import * as lCore from '#kebab/lib/core.js';
|
|
7
|
-
import * as lTime from '#kebab/lib/time.js';
|
|
8
|
-
import * as lText from '#kebab/lib/text.js';
|
|
9
|
-
import * as lCrypto from '#kebab/lib/crypto.js';
|
|
10
|
-
export class Jwt {
|
|
11
|
-
/**
|
|
12
|
-
* --- 初始化函数,相当于 construct ---
|
|
13
|
-
* @param ctr 模型实例
|
|
14
|
-
* @param link Kv 或 Db 实例
|
|
15
|
-
* @param auth 设为 true 则优先从头 Authorization 或 post _auth 值读取 token
|
|
16
|
-
* @param opt 选项
|
|
17
|
-
*/
|
|
18
|
-
async init(ctr, opt = {}, link) {
|
|
19
|
-
const config = ctr.getPrototype('_config');
|
|
20
|
-
this._ctr = ctr;
|
|
21
|
-
this._link = link;
|
|
22
|
-
this._name = opt.name ?? config.jwt.name;
|
|
23
|
-
this._ttl = opt.ttl ?? config.jwt.ttl;
|
|
24
|
-
this._ssl = opt.ssl ?? config.jwt.ssl;
|
|
25
|
-
this._secret = opt.secret ?? config.jwt.secret;
|
|
26
|
-
this._auth = opt.auth ?? config.jwt.auth;
|
|
27
|
-
let jwt = '';
|
|
28
|
-
if (this._auth) {
|
|
29
|
-
const a = this._ctr.getAuthorization();
|
|
30
|
-
if (typeof a !== 'string') {
|
|
31
|
-
return false;
|
|
32
|
-
}
|
|
33
|
-
jwt = a;
|
|
34
|
-
}
|
|
35
|
-
if (!jwt) {
|
|
36
|
-
const cookie = this._ctr.getPrototype('_cookie');
|
|
37
|
-
if (!cookie[this._name]) {
|
|
38
|
-
return false;
|
|
39
|
-
}
|
|
40
|
-
jwt = cookie[this._name];
|
|
41
|
-
}
|
|
42
|
-
const data = await decode(this._ctr, jwt, this._link, this._name, this._secret);
|
|
43
|
-
if (!data) {
|
|
44
|
-
// --- 清除 cookie ---
|
|
45
|
-
const cookie = this._ctr.getPrototype('_cookie');
|
|
46
|
-
if (cookie[this._name]) {
|
|
47
|
-
delete cookie[this._name];
|
|
48
|
-
}
|
|
49
|
-
return false;
|
|
50
|
-
}
|
|
51
|
-
this._ctr.setPrototype('_jwt', data);
|
|
52
|
-
return true;
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* --- 将 _jwt 数据封装并返回(创建新的或者续期老的 token),默认会同时设置一个 cookie(data 值会自动设置 token、exp) ---
|
|
56
|
-
*/
|
|
57
|
-
renew() {
|
|
58
|
-
const time = lTime.stamp();
|
|
59
|
-
const data = this._ctr.getPrototype('_jwt');
|
|
60
|
-
const token = lText.isFalsy(data['token']) ? lCore.random(16, lCore.RANDOM_LUN) : data['token'];
|
|
61
|
-
data['exp'] = time + this._ttl;
|
|
62
|
-
data['token'] = token;
|
|
63
|
-
// --- 拼装 ---
|
|
64
|
-
const header = lCrypto.base64Encode(lText.stringifyJson({
|
|
65
|
-
'alg': 'HS256',
|
|
66
|
-
'typ': 'JWT'
|
|
67
|
-
}));
|
|
68
|
-
const payload = lCrypto.base64Encode(lText.stringifyJson(data));
|
|
69
|
-
const signature = lCrypto.hashHmac('sha256', header + '.' + payload, this._secret, 'base64');
|
|
70
|
-
const jwt = header + '.' + payload + '.' + signature;
|
|
71
|
-
if (!this._auth) {
|
|
72
|
-
lCore.setCookie(this._ctr, this._name, jwt, {
|
|
73
|
-
'ttl': this._ttl,
|
|
74
|
-
'ssl': this._ssl
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
return jwt;
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* --- 清除 cookie,仅仅清除 cookie,jwt 并不会失效 ---
|
|
81
|
-
*/
|
|
82
|
-
clearCookie() {
|
|
83
|
-
if (this._auth) {
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
lCore.setCookie(this._ctr, this._name, '', {
|
|
87
|
-
'ttl': 0,
|
|
88
|
-
'ssl': this._ssl
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* --- 销毁 jwt,其实就是将 token block 信息写入 redis,如果没有 redis 则不能销毁,返回数组代表销毁成功的 token 和原 exp,否则失败返回 false ---
|
|
93
|
-
*/
|
|
94
|
-
async destory() {
|
|
95
|
-
if (!this._link) {
|
|
96
|
-
return false;
|
|
97
|
-
}
|
|
98
|
-
const jwt = this._ctr.getPrototype('_jwt');
|
|
99
|
-
if (!jwt.token) {
|
|
100
|
-
return false;
|
|
101
|
-
}
|
|
102
|
-
const time = lTime.stamp();
|
|
103
|
-
const token = jwt.token;
|
|
104
|
-
const exp = jwt.exp;
|
|
105
|
-
const ttl = exp - time;
|
|
106
|
-
if (ttl <= 0) {
|
|
107
|
-
lCore.emptyObject(jwt);
|
|
108
|
-
return {
|
|
109
|
-
token,
|
|
110
|
-
exp
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
lCore.emptyObject(jwt);
|
|
114
|
-
await this._link.set(`${this._name}_block_${token}`, '1', ttl + 1);
|
|
115
|
-
return {
|
|
116
|
-
token,
|
|
117
|
-
exp
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* --- 获取 jwt 原始字符串,不保证有效 ---
|
|
123
|
-
*/
|
|
124
|
-
export function getOrigin(ctr, name = '', auth = false) {
|
|
125
|
-
if (!name) {
|
|
126
|
-
name = ctr.getPrototype('_config').jwt.name;
|
|
127
|
-
}
|
|
128
|
-
let jwt = '';
|
|
129
|
-
if (auth) {
|
|
130
|
-
const a = ctr.getAuthorization();
|
|
131
|
-
if (typeof a !== 'string') {
|
|
132
|
-
return jwt;
|
|
133
|
-
}
|
|
134
|
-
jwt = a;
|
|
135
|
-
}
|
|
136
|
-
if (!jwt) {
|
|
137
|
-
const cookie = ctr.getPrototype('_cookie');
|
|
138
|
-
if (!cookie[name]) {
|
|
139
|
-
return jwt;
|
|
140
|
-
}
|
|
141
|
-
jwt = cookie[name];
|
|
142
|
-
}
|
|
143
|
-
return jwt;
|
|
144
|
-
}
|
|
145
|
-
/**
|
|
146
|
-
* --- decode ---
|
|
147
|
-
* 不传入 link 的话,将不做 block 有效校验,只做本身的 exp 有效校验
|
|
148
|
-
*/
|
|
149
|
-
export async function decode(ctr, val, link, name = '', secret = '') {
|
|
150
|
-
if (!val) {
|
|
151
|
-
return false;
|
|
152
|
-
}
|
|
153
|
-
const config = ctr.getPrototype('_config');
|
|
154
|
-
if (!secret) {
|
|
155
|
-
secret = config.jwt.secret;
|
|
156
|
-
}
|
|
157
|
-
if (!name) {
|
|
158
|
-
name = config.jwt.name;
|
|
159
|
-
}
|
|
160
|
-
const jwtArray = val.split('.');
|
|
161
|
-
if (!jwtArray[2]) {
|
|
162
|
-
return false;
|
|
163
|
-
}
|
|
164
|
-
// jwtArray[1]: payload, jwtArray[2]: signature
|
|
165
|
-
// --- 判断是否合法 ---
|
|
166
|
-
const nsignature = lCrypto.hashHmac('sha256', jwtArray[0] + '.' + jwtArray[1], secret, 'base64');
|
|
167
|
-
if (nsignature !== jwtArray[2]) {
|
|
168
|
-
return false;
|
|
169
|
-
}
|
|
170
|
-
try {
|
|
171
|
-
const payload = lCrypto.base64Decode(jwtArray[1]);
|
|
172
|
-
if (!payload) {
|
|
173
|
-
return false;
|
|
174
|
-
}
|
|
175
|
-
const data = lText.parseJson(payload);
|
|
176
|
-
if (!data) {
|
|
177
|
-
return false;
|
|
178
|
-
}
|
|
179
|
-
// --- 检测 token ---
|
|
180
|
-
if (!data['token']) {
|
|
181
|
-
return false;
|
|
182
|
-
}
|
|
183
|
-
// --- 检测 exp ---
|
|
184
|
-
if (!data['exp']) {
|
|
185
|
-
return false;
|
|
186
|
-
}
|
|
187
|
-
const time = lTime.stamp();
|
|
188
|
-
if (data['exp'] < time) {
|
|
189
|
-
// --- 过期 ---
|
|
190
|
-
return false;
|
|
191
|
-
}
|
|
192
|
-
// --- 检测 token 是否有效 ---
|
|
193
|
-
if (!link || !await link.get(name + '_block_' + data['token'])) {
|
|
194
|
-
return data;
|
|
195
|
-
}
|
|
196
|
-
return false;
|
|
197
|
-
}
|
|
198
|
-
catch {
|
|
199
|
-
return false;
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
/**
|
|
203
|
-
* --- 仅往 redis 写禁止相关 token 的数据,一般用于异步通知时在异处的服务器来调用的 ---
|
|
204
|
-
*/
|
|
205
|
-
export async function block(ctr, token, exp, link, name = '') {
|
|
206
|
-
const time = lTime.stamp();
|
|
207
|
-
if (!name) {
|
|
208
|
-
name = ctr.getPrototype('_config').jwt.name;
|
|
209
|
-
}
|
|
210
|
-
const ttl = exp - time;
|
|
211
|
-
if (ttl <= 0) {
|
|
212
|
-
return true;
|
|
213
|
-
}
|
|
214
|
-
await link.set(name + '_block_' + token, '1', ttl + 1);
|
|
215
|
-
return true;
|
|
216
|
-
}
|
|
217
|
-
/**
|
|
218
|
-
* @param ctr 模型实例
|
|
219
|
-
* @param opt name, ttl, ssl, secret, auth: false, true 则优先从头 Authorization 或 post _auth 值读取 token
|
|
220
|
-
* @param link 实例
|
|
221
|
-
*/
|
|
222
|
-
export async function get(ctr, opt = {}, link) {
|
|
223
|
-
const jwt = new Jwt();
|
|
224
|
-
await jwt.init(ctr, opt, link);
|
|
225
|
-
return jwt;
|
|
226
|
-
}
|