@maiyunnet/kebab 2.0.9 → 2.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.ts +3 -1
- package/index.js +3 -1
- package/lib/turnstile.d.ts +15 -0
- package/lib/turnstile.js +108 -0
- package/package.json +1 -1
- package/sys/cmd.js +10 -0
- package/sys/ctr.js +1 -1
- package/sys/mod.d.ts +2 -0
- package/sys/mod.js +27 -16
- package/www/example/ctr/test.js +3 -0
- package/www/example/mod/test.d.ts +2 -0
- package/www/example/mod/test.js +14 -11
package/index.d.ts
CHANGED
|
@@ -3,10 +3,12 @@
|
|
|
3
3
|
* Date: 2019-3-30 12:46:41
|
|
4
4
|
* Last: 2020-3-8 21:04:24, 2022-07-22 14:20:34, 2023-5-24 01:34:57, 2025-6-13 14:49:27
|
|
5
5
|
* --- 本文件用来定义每个目录实体地址的常量 ---
|
|
6
|
+
* ------------------------
|
|
6
7
|
* --- npx tsc-alias -w ---
|
|
8
|
+
* ------------------------
|
|
7
9
|
*/
|
|
8
10
|
/** --- 当前系统版本号 --- */
|
|
9
|
-
export declare const VER = "2.0.
|
|
11
|
+
export declare const VER = "2.0.11";
|
|
10
12
|
/** --- 框架根目录,以 / 结尾 --- */
|
|
11
13
|
export declare const ROOT_PATH: string;
|
|
12
14
|
export declare const LIB_PATH: string;
|
package/index.js
CHANGED
|
@@ -4,12 +4,14 @@
|
|
|
4
4
|
* Date: 2019-3-30 12:46:41
|
|
5
5
|
* Last: 2020-3-8 21:04:24, 2022-07-22 14:20:34, 2023-5-24 01:34:57, 2025-6-13 14:49:27
|
|
6
6
|
* --- 本文件用来定义每个目录实体地址的常量 ---
|
|
7
|
+
* ------------------------
|
|
7
8
|
* --- npx tsc-alias -w ---
|
|
9
|
+
* ------------------------
|
|
8
10
|
*/
|
|
9
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
12
|
exports.MOD_CWD = exports.FTMP_CWD = exports.IND_CWD = exports.WWW_CWD = exports.LOG_CWD = exports.LIB_CWD = exports.VHOST_CWD = exports.CERT_CWD = exports.CONF_CWD = exports.ROOT_CWD = exports.SYS_PATH = exports.LIB_PATH = exports.ROOT_PATH = exports.VER = void 0;
|
|
11
13
|
/** --- 当前系统版本号 --- */
|
|
12
|
-
exports.VER = '2.0.
|
|
14
|
+
exports.VER = '2.0.11';
|
|
13
15
|
// --- 服务端用的路径 ---
|
|
14
16
|
/** --- /xxx/xxx --- */
|
|
15
17
|
const dirname = __dirname.replace(/\\/g, '/');
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import * as sCtr from '../sys/ctr';
|
|
2
|
+
/**
|
|
3
|
+
* 0. CloudFlare:https://developers.cloudflare.com/turnstile/get-started/server-side-validation/
|
|
4
|
+
* 1. 腾讯云:https://cloud.tencent.com/document/product/1110/36926
|
|
5
|
+
*/
|
|
6
|
+
/** --- 厂家 --- */
|
|
7
|
+
export declare enum EFACTORY {
|
|
8
|
+
'CLOUDFLARE' = 0,
|
|
9
|
+
'TENCENT' = 1
|
|
10
|
+
}
|
|
11
|
+
export declare function verify(ctr: sCtr.Ctr, opt: {
|
|
12
|
+
'factory': EFACTORY;
|
|
13
|
+
'token': string;
|
|
14
|
+
'ip': string;
|
|
15
|
+
}): Promise<boolean>;
|
package/lib/turnstile.js
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.EFACTORY = void 0;
|
|
37
|
+
exports.verify = verify;
|
|
38
|
+
/**
|
|
39
|
+
* Project: Kebab, User: JianSuoQiYue
|
|
40
|
+
* Date: 2025-6-11
|
|
41
|
+
* Last: 2025-6-11 21:50:31
|
|
42
|
+
*/
|
|
43
|
+
const tc = __importStar(require("tencentcloud-sdk-nodejs"));
|
|
44
|
+
// --- 库和定义 ---
|
|
45
|
+
const lNet = __importStar(require("../lib/net"));
|
|
46
|
+
const lText = __importStar(require("../lib/text"));
|
|
47
|
+
/**
|
|
48
|
+
* 0. CloudFlare:https://developers.cloudflare.com/turnstile/get-started/server-side-validation/
|
|
49
|
+
* 1. 腾讯云:https://cloud.tencent.com/document/product/1110/36926
|
|
50
|
+
*/
|
|
51
|
+
/** --- 厂家 --- */
|
|
52
|
+
var EFACTORY;
|
|
53
|
+
(function (EFACTORY) {
|
|
54
|
+
EFACTORY[EFACTORY["CLOUDFLARE"] = 0] = "CLOUDFLARE";
|
|
55
|
+
EFACTORY[EFACTORY["TENCENT"] = 1] = "TENCENT";
|
|
56
|
+
})(EFACTORY || (exports.EFACTORY = EFACTORY = {}));
|
|
57
|
+
async function verify(ctr, opt) {
|
|
58
|
+
const config = ctr.getPrototype('_config');
|
|
59
|
+
switch (opt.factory) {
|
|
60
|
+
case EFACTORY.CLOUDFLARE: {
|
|
61
|
+
// --- CloudFlare 验证 ---
|
|
62
|
+
const res = await lNet.postJson('https://challenges.cloudflare.com/turnstile/v0/siteverify', {
|
|
63
|
+
'secret': config.turnstile['CF'].skey,
|
|
64
|
+
'response': opt.token,
|
|
65
|
+
'remoteip': opt.ip,
|
|
66
|
+
});
|
|
67
|
+
const content = await res.getContent();
|
|
68
|
+
if (!content) {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
const str = content.toString();
|
|
72
|
+
const json = lText.parseJson(str);
|
|
73
|
+
if (!json) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
return json.success;
|
|
77
|
+
}
|
|
78
|
+
case EFACTORY.TENCENT: {
|
|
79
|
+
// --- 腾讯云验证 ---
|
|
80
|
+
const client = new tc.captcha.v20190722.Client({
|
|
81
|
+
'credential': {
|
|
82
|
+
'secretId': config.turnstile['TENCENT'].sid,
|
|
83
|
+
'secretKey': config.turnstile['TENCENT'].skey,
|
|
84
|
+
},
|
|
85
|
+
'profile': {
|
|
86
|
+
'signMethod': 'HmacSHA256', // 签名方法
|
|
87
|
+
'httpProfile': {
|
|
88
|
+
'reqMethod': 'POST', // 请求方法
|
|
89
|
+
'reqTimeout': 30, // 请求超时时间,默认60s
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
const io = opt.token.indexOf('|');
|
|
94
|
+
if (io === -1) {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
const res = await client.DescribeCaptchaResult({
|
|
98
|
+
'CaptchaType': 9,
|
|
99
|
+
'Ticket': opt.token.slice(0, io),
|
|
100
|
+
'UserIp': opt.ip,
|
|
101
|
+
'Randstr': opt.token.slice(io + 1),
|
|
102
|
+
'CaptchaAppId': parseInt(config.turnstile['TENCENT'].aid), // --- 防止后期又不是 number 了还要改config,这样只需要更新代码无损升级 ---
|
|
103
|
+
'AppSecretKey': config.turnstile['TENCENT'].akey,
|
|
104
|
+
});
|
|
105
|
+
return res.CaptchaCode === 1;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
package/package.json
CHANGED
package/sys/cmd.js
CHANGED
|
@@ -169,6 +169,16 @@ async function run() {
|
|
|
169
169
|
config.s3['TENCENT'].skey = '';
|
|
170
170
|
config.s3['TENCENT'].region = '';
|
|
171
171
|
config.s3['TENCENT'].bucket = '';
|
|
172
|
+
// --- config - turnstile ---
|
|
173
|
+
config.turnstile ??= {};
|
|
174
|
+
config.turnstile['CF'] ??= {};
|
|
175
|
+
config.turnstile['CF'].sid ??= '';
|
|
176
|
+
config.turnstile['CF'].skey ??= '';
|
|
177
|
+
config.turnstile['TENCENT'] ??= {};
|
|
178
|
+
config.turnstile['TENCENT'].sid ??= '';
|
|
179
|
+
config.turnstile['TENCENT'].skey ??= '';
|
|
180
|
+
config.turnstile['TENCENT'].aid ??= '';
|
|
181
|
+
config.turnstile['TENCENT'].akey ??= '';
|
|
172
182
|
// --- 保存 config.json ---
|
|
173
183
|
if (!await lFs.putContent(kebab.CONF_CWD + 'config.json', lText.stringifyJson(config, 4))) {
|
|
174
184
|
lCore.display('KEBAB', 'CREATE', 'FILE', kebab.CONF_CWD + 'config.json', '[FAILED]');
|
package/sys/ctr.js
CHANGED
|
@@ -690,7 +690,7 @@ class Ctr {
|
|
|
690
690
|
this._res.setHeader('access-control-allow-headers', '*');
|
|
691
691
|
this._res.setHeader('access-control-allow-methods', '*');
|
|
692
692
|
if (this._req.method === 'OPTIONS') {
|
|
693
|
-
this._res.setHeader('access-control-max-age', '
|
|
693
|
+
this._res.setHeader('access-control-max-age', '3600');
|
|
694
694
|
return false;
|
|
695
695
|
}
|
|
696
696
|
return true;
|
package/sys/mod.d.ts
CHANGED
|
@@ -33,6 +33,8 @@ export default class Mod {
|
|
|
33
33
|
protected static _$primary: string;
|
|
34
34
|
/** --- 设置后将由 _keyGenerator 函数生成唯一字段 --- */
|
|
35
35
|
protected static _$key: string;
|
|
36
|
+
/** --- 若使用 _$key 并且有多个 unique 索引,这里指定 _$key 的索引名 --- */
|
|
37
|
+
protected static _$index: string;
|
|
36
38
|
/** ---- 可开启软删软更新软新增 --- */
|
|
37
39
|
protected static _$soft: boolean;
|
|
38
40
|
/** --- 要 update 的内容 --- */
|
package/sys/mod.js
CHANGED
|
@@ -353,8 +353,8 @@ class Mod {
|
|
|
353
353
|
if (typeof opt.index === 'string') {
|
|
354
354
|
opt.index = [opt.index];
|
|
355
355
|
}
|
|
356
|
-
else
|
|
357
|
-
opt.index
|
|
356
|
+
else {
|
|
357
|
+
opt.index ??= [''];
|
|
358
358
|
}
|
|
359
359
|
if (this._$soft && !opt.raw) {
|
|
360
360
|
if (typeof where === 'string') {
|
|
@@ -657,9 +657,7 @@ class Mod {
|
|
|
657
657
|
for (const k in this._updates) {
|
|
658
658
|
updates[k] = this._data[k];
|
|
659
659
|
}
|
|
660
|
-
|
|
661
|
-
table = cstr._$table + (this._index ? ('_' + this._index[0]) : '');
|
|
662
|
-
}
|
|
660
|
+
table ??= cstr._$table + (this._index ? ('_' + this._index[0]) : '');
|
|
663
661
|
let r = null;
|
|
664
662
|
if ((cstr._$key !== '') && (updates[cstr._$key] === undefined)) {
|
|
665
663
|
let count = 0;
|
|
@@ -682,18 +680,29 @@ class Mod {
|
|
|
682
680
|
if (!r.error) {
|
|
683
681
|
break;
|
|
684
682
|
}
|
|
685
|
-
if (r.error.errno
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
683
|
+
if (r.error.errno === 1062) {
|
|
684
|
+
// --- 与唯一键冲突 ---
|
|
685
|
+
if (!cstr._$index) {
|
|
686
|
+
// --- 没设置 index,那就当做是本次生成的 key 重复了 ---
|
|
687
|
+
continue;
|
|
688
|
+
}
|
|
689
|
+
const match = /for key '([\w.]+)'/.exec(r.error.message);
|
|
690
|
+
if (match?.[1].includes(cstr._$index)) {
|
|
691
|
+
// --- 确实重复了 ---
|
|
692
|
+
continue;
|
|
693
|
+
}
|
|
696
694
|
}
|
|
695
|
+
// --- 未处理的错误 ---
|
|
696
|
+
await lCore.log(this._ctr ?? {
|
|
697
|
+
'path': '',
|
|
698
|
+
'urlFull': '',
|
|
699
|
+
'hostname': '',
|
|
700
|
+
'req': null,
|
|
701
|
+
'get': {},
|
|
702
|
+
'cookie': {},
|
|
703
|
+
'headers': {}
|
|
704
|
+
}, '[create0, mod] [' + table + '] ' + lText.stringifyJson(r.error?.message ?? '').slice(1, -1).replace(/"/g, '""'), '-error');
|
|
705
|
+
return false;
|
|
697
706
|
}
|
|
698
707
|
}
|
|
699
708
|
else {
|
|
@@ -1603,6 +1612,8 @@ Mod._$table = '';
|
|
|
1603
1612
|
Mod._$primary = 'id';
|
|
1604
1613
|
/** --- 设置后将由 _keyGenerator 函数生成唯一字段 --- */
|
|
1605
1614
|
Mod._$key = '';
|
|
1615
|
+
/** --- 若使用 _$key 并且有多个 unique 索引,这里指定 _$key 的索引名 --- */
|
|
1616
|
+
Mod._$index = '';
|
|
1606
1617
|
/** ---- 可开启软删软更新软新增 --- */
|
|
1607
1618
|
Mod._$soft = false;
|
|
1608
1619
|
exports.default = Mod;
|
package/www/example/ctr/test.js
CHANGED
|
@@ -548,6 +548,7 @@ Result:<pre id="result">Nothing.</pre>` + this._getEnd();
|
|
|
548
548
|
'ctr': this
|
|
549
549
|
});
|
|
550
550
|
test.set({
|
|
551
|
+
'name': 'nam' + lCore.rand(0, 3).toString(),
|
|
551
552
|
'point': { 'x': lCore.rand(0, 99), 'y': lCore.rand(0, 99) },
|
|
552
553
|
'polygon': [
|
|
553
554
|
[
|
|
@@ -566,6 +567,7 @@ const test = mTest.getCreate<mTest>(db, {
|
|
|
566
567
|
'ctr': this
|
|
567
568
|
});
|
|
568
569
|
test.set({
|
|
570
|
+
'name': 'nam' + lCore.rand(0, 4).toString(),
|
|
569
571
|
'point': { 'x': lCore.rand(0, 99), 'y': lCore.rand(0, 99) },
|
|
570
572
|
'polygon': [
|
|
571
573
|
[
|
|
@@ -744,6 +746,7 @@ CREATE TABLE \`m_test_data_0\` (
|
|
|
744
746
|
'ctr': this
|
|
745
747
|
});
|
|
746
748
|
test.set({
|
|
749
|
+
'name': lCore.random(4),
|
|
747
750
|
'token': lCore.random(lCore.rand(8, 32)),
|
|
748
751
|
'point': {
|
|
749
752
|
'x': 10,
|
package/www/example/mod/test.js
CHANGED
|
@@ -39,25 +39,28 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
39
39
|
const lCore = __importStar(require("../../../lib/core"));
|
|
40
40
|
const mod_1 = __importDefault(require("../../../sys/mod"));
|
|
41
41
|
/*
|
|
42
|
-
CREATE TABLE `m_test`
|
|
43
|
-
`id`
|
|
44
|
-
`
|
|
45
|
-
`
|
|
46
|
-
`
|
|
47
|
-
`
|
|
48
|
-
`
|
|
42
|
+
CREATE TABLE `m_test` (
|
|
43
|
+
`id` int NOT NULL AUTO_INCREMENT,
|
|
44
|
+
`name` char(4) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
|
|
45
|
+
`token` varchar(32) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
|
|
46
|
+
`point` point NOT NULL,
|
|
47
|
+
`polygon` polygon NULL,
|
|
48
|
+
`json` json NULL,
|
|
49
|
+
`time_add` bigint NOT NULL,
|
|
49
50
|
PRIMARY KEY (`id`) USING BTREE,
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
)
|
|
51
|
+
INDEX `time_add`(`time_add` ASC) USING BTREE,
|
|
52
|
+
UNIQUE INDEX `utoken`(`token` ASC) USING BTREE,
|
|
53
|
+
UNIQUE INDEX `uname`(`name` ASC) USING BTREE
|
|
54
|
+
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
|
|
53
55
|
*/
|
|
54
56
|
class default_1 extends mod_1.default {
|
|
55
57
|
/* eslint-enable */
|
|
56
58
|
_keyGenerator() {
|
|
57
|
-
return 'test_' + lCore.rand(0,
|
|
59
|
+
return 'test_' + lCore.rand(0, 3).toString();
|
|
58
60
|
}
|
|
59
61
|
}
|
|
60
62
|
default_1._$table = 'test';
|
|
61
63
|
default_1._$primary = 'id';
|
|
62
64
|
default_1._$key = 'token';
|
|
65
|
+
default_1._$index = 'utoken';
|
|
63
66
|
exports.default = default_1;
|