@liujitcn/kratos-admin-cli 0.0.86 → 0.0.87
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/package.json +2 -2
- package/templates/business-workspace/.gitattributes +2 -0
- package/templates/business-workspace/.nvmrc +1 -0
- package/templates/business-workspace/.stylelintignore +4 -0
- package/templates/business-workspace/README.en-US.md +4 -0
- package/templates/business-workspace/README.md +4 -0
- package/templates/business-workspace/package.json +18 -9
- package/templates/business-workspace/patches/braces@3.0.3.patch +135 -0
- package/templates/business-workspace/scripts/dependency-security.test.mjs +50 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@liujitcn/kratos-admin-cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.87",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Create pnpm workspace projects for kratos-admin business modules",
|
|
6
6
|
"license": "MIT",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"kratos-admin": "./dist/index.js"
|
|
14
14
|
},
|
|
15
15
|
"engines": {
|
|
16
|
-
"node": "^
|
|
16
|
+
"node": "^24.0.0"
|
|
17
17
|
},
|
|
18
18
|
"files": [
|
|
19
19
|
"dist/index.d.ts",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
24
|
|
@@ -38,6 +38,10 @@ Each directory containing a `package.json` has its own README with details about
|
|
|
38
38
|
|
|
39
39
|
## Development
|
|
40
40
|
|
|
41
|
+
Use Node.js 24 and pnpm 10.33.4. Run `nvm install && nvm use` first. After dependency upgrades, regenerate the lockfile with `pnpm install --no-frozen-lockfile` and verify it with `pnpm install --frozen-lockfile`.
|
|
42
|
+
|
|
43
|
+
`patches/braces@3.0.3.patch` bounds parser and AST traversal depth for CVE-2026-93687, which has no upstream fixed release. The audit exception applies only to this patch. Run `pnpm test:dependency-security` before `pnpm audit --audit-level high`; remove the patch, this exception and its regression tests together when an upstream fix becomes available.
|
|
44
|
+
|
|
41
45
|
```bash
|
|
42
46
|
pnpm install
|
|
43
47
|
pnpm dev
|
|
@@ -39,6 +39,10 @@ __MODULE_TABLE_ROWS__
|
|
|
39
39
|
|
|
40
40
|
## 开发
|
|
41
41
|
|
|
42
|
+
使用 Node.js 24 和 pnpm 10.33.4,先执行 `nvm install && nvm use`。依赖升级后通过 `pnpm install --no-frozen-lockfile` 生成锁文件,再用 `pnpm install --frozen-lockfile` 验证。
|
|
43
|
+
|
|
44
|
+
`patches/braces@3.0.3.patch` 限制括号解析与 AST 遍历深度,处理尚无上游修复版本的 `CVE-2026-93687`;审计豁免仅针对此补丁。执行 `pnpm test:dependency-security` 验证实际安装的依赖后再运行 `pnpm audit --audit-level high`,上游发布修复版本后同时删除补丁、该豁免和对应测试。
|
|
45
|
+
|
|
42
46
|
```bash
|
|
43
47
|
pnpm install
|
|
44
48
|
pnpm dev
|
|
@@ -12,20 +12,21 @@
|
|
|
12
12
|
"lint:oxlint": "oxlint --fix --vue-plugin --config ./internal/lint-config/oxlint.json --ignore-path .oxlintignore ./apps ./packages ./internal ./scripts",
|
|
13
13
|
"lint:lint-staged": "lint-staged",
|
|
14
14
|
"lint:prettier": "prettier --write \"{apps,packages,internal,scripts}/**/*.{js,mjs,ts,json,tsx,css,less,scss,vue,html,md,yaml}\"",
|
|
15
|
-
"lint:stylelint": "stylelint --cache --fix \"{apps,packages}/**/*.{vue,less,postcss,css,scss}\" --cache-location node_modules/.cache/stylelint/",
|
|
15
|
+
"lint:stylelint": "stylelint --config .stylelintrc.cjs --cache --fix \"{apps,packages}/**/*.{vue,less,postcss,css,scss}\" --cache-location node_modules/.cache/stylelint/",
|
|
16
16
|
"generate:auto-import-types": "node scripts/generate-auto-import-types.mjs",
|
|
17
17
|
"i18n:sync": "node scripts/sync-locales.mjs --write",
|
|
18
|
-
"i18n:check": "node scripts/sync-locales.mjs"
|
|
18
|
+
"i18n:check": "node scripts/sync-locales.mjs",
|
|
19
|
+
"test:dependency-security": "node --test scripts/dependency-security.test.mjs"
|
|
19
20
|
},
|
|
20
21
|
"devDependencies": {
|
|
21
|
-
"@types/node": "
|
|
22
|
+
"@types/node": "26.5.1",
|
|
22
23
|
"sass": "^1.100.0",
|
|
23
24
|
"turbo": "^2.5.6",
|
|
24
25
|
"typescript": "6.0.3",
|
|
25
26
|
"vite": "^8.0.14",
|
|
26
27
|
"vue-tsc": "^3.3.2",
|
|
27
|
-
"@commitlint/cli": "
|
|
28
|
-
"@commitlint/config-conventional": "
|
|
28
|
+
"@commitlint/cli": "21.2.2",
|
|
29
|
+
"@commitlint/config-conventional": "21.2.2",
|
|
29
30
|
"@types/md5": "^2.3.5",
|
|
30
31
|
"@types/nprogress": "^0.2.3",
|
|
31
32
|
"@types/qs": "^6.9.15",
|
|
@@ -39,7 +40,7 @@
|
|
|
39
40
|
"postcss-html": "^1.8.1",
|
|
40
41
|
"prettier": "^3.3.2",
|
|
41
42
|
"standard-version": "^9.5.0",
|
|
42
|
-
"stylelint": "^17.
|
|
43
|
+
"stylelint": "^17.15.0",
|
|
43
44
|
"stylelint-config-html": "^1.1.0",
|
|
44
45
|
"stylelint-config-recess-order": "^7.7.0",
|
|
45
46
|
"stylelint-config-recommended-scss": "^17.0.1",
|
|
@@ -50,7 +51,7 @@
|
|
|
50
51
|
"ts-proto": "^2.11.8"
|
|
51
52
|
},
|
|
52
53
|
"engines": {
|
|
53
|
-
"node": "^
|
|
54
|
+
"node": "^24.0.0"
|
|
54
55
|
},
|
|
55
56
|
"packageManager": "pnpm@10.33.4",
|
|
56
57
|
"pnpm": {
|
|
@@ -61,7 +62,11 @@
|
|
|
61
62
|
"svg-baker>micromatch": "4.0.8",
|
|
62
63
|
"svg-baker>postcss": "8.5.26",
|
|
63
64
|
"vue": "3.5.42",
|
|
64
|
-
"vue-router": "5.3.1"
|
|
65
|
+
"vue-router": "5.3.1",
|
|
66
|
+
"brace-expansion@<2.0.0": "1.1.20",
|
|
67
|
+
"brace-expansion@>=2.0.0 <3.0.0": "2.1.6",
|
|
68
|
+
"handlebars@<4.7.10": "4.7.10",
|
|
69
|
+
"source-map-js@<1.2.2": "1.2.2"
|
|
65
70
|
},
|
|
66
71
|
"onlyBuiltDependencies": [
|
|
67
72
|
"@parcel/watcher",
|
|
@@ -76,8 +81,12 @@
|
|
|
76
81
|
"auditConfig": {
|
|
77
82
|
"ignoreCves": [
|
|
78
83
|
"CVE-2025-71330",
|
|
79
|
-
"CVE-2025-71329"
|
|
84
|
+
"CVE-2025-71329",
|
|
85
|
+
"CVE-2026-93687"
|
|
80
86
|
]
|
|
87
|
+
},
|
|
88
|
+
"patchedDependencies": {
|
|
89
|
+
"braces@3.0.3": "patches/braces@3.0.3.patch"
|
|
81
90
|
}
|
|
82
91
|
}
|
|
83
92
|
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
diff --git a/lib/compile.js b/lib/compile.js
|
|
2
|
+
index dce69beb90ece5c3b0ca234a949418f9f34eedbc..2f9fd0e732e0e1f90f71ce3f7681505002ad3290 100644
|
|
3
|
+
--- a/lib/compile.js
|
|
4
|
+
+++ b/lib/compile.js
|
|
5
|
+
@@ -2,9 +2,14 @@
|
|
6
|
+
|
|
7
|
+
const fill = require('fill-range');
|
|
8
|
+
const utils = require('./utils');
|
|
9
|
+
+const { MAX_DEPTH } = require('./constants');
|
|
10
|
+
|
|
11
|
+
const compile = (ast, options = {}) => {
|
|
12
|
+
- const walk = (node, parent = {}) => {
|
|
13
|
+
+ const walk = (node, parent = {}, depth = 0) => {
|
|
14
|
+
+ // 调用方也能直接传入 AST,因此遍历入口独立限制深度。
|
|
15
|
+
+ if (node.nodes && depth > MAX_DEPTH) {
|
|
16
|
+
+ throw new SyntaxError('Pattern nesting exceeds maximum depth');
|
|
17
|
+
+ }
|
|
18
|
+
const invalidBlock = utils.isInvalidBrace(parent);
|
|
19
|
+
const invalidNode = node.invalid === true && options.escapeInvalid === true;
|
|
20
|
+
const invalid = invalidBlock === true || invalidNode === true;
|
|
21
|
+
@@ -47,7 +52,7 @@ const compile = (ast, options = {}) => {
|
|
22
|
+
|
|
23
|
+
if (node.nodes) {
|
|
24
|
+
for (const child of node.nodes) {
|
|
25
|
+
- output += walk(child, node);
|
|
26
|
+
+ output += walk(child, node, depth + 1);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
diff --git a/lib/constants.js b/lib/constants.js
|
|
31
|
+
index 2bb3b8840382c56700869b3a9e1f958fcce01efd..3289d5650833bbbe39882f833bce71612d661c12 100644
|
|
32
|
+
--- a/lib/constants.js
|
|
33
|
+
+++ b/lib/constants.js
|
|
34
|
+
@@ -2,6 +2,7 @@
|
|
35
|
+
|
|
36
|
+
module.exports = {
|
|
37
|
+
MAX_LENGTH: 10000,
|
|
38
|
+
+ MAX_DEPTH: 128,
|
|
39
|
+
|
|
40
|
+
// Digits
|
|
41
|
+
CHAR_0: '0', /* 0 */
|
|
42
|
+
diff --git a/lib/expand.js b/lib/expand.js
|
|
43
|
+
index 35b2c41d6afdb8f0197959e26079f266e48370d3..2c4a5ee11e882a172c2654b985b1447b53b1d204 100644
|
|
44
|
+
--- a/lib/expand.js
|
|
45
|
+
+++ b/lib/expand.js
|
|
46
|
+
@@ -3,6 +3,7 @@
|
|
47
|
+
const fill = require('fill-range');
|
|
48
|
+
const stringify = require('./stringify');
|
|
49
|
+
const utils = require('./utils');
|
|
50
|
+
+const { MAX_DEPTH } = require('./constants');
|
|
51
|
+
|
|
52
|
+
const append = (queue = '', stash = '', enclose = false) => {
|
|
53
|
+
const result = [];
|
|
54
|
+
@@ -33,7 +34,10 @@ const append = (queue = '', stash = '', enclose = false) => {
|
|
55
|
+
const expand = (ast, options = {}) => {
|
|
56
|
+
const rangeLimit = options.rangeLimit === undefined ? 1000 : options.rangeLimit;
|
|
57
|
+
|
|
58
|
+
- const walk = (node, parent = {}) => {
|
|
59
|
+
+ const walk = (node, parent = {}, depth = 0) => {
|
|
60
|
+
+ if (node.nodes && depth > MAX_DEPTH) {
|
|
61
|
+
+ throw new SyntaxError('Pattern nesting exceeds maximum depth');
|
|
62
|
+
+ }
|
|
63
|
+
node.queue = [];
|
|
64
|
+
|
|
65
|
+
let p = parent;
|
|
66
|
+
@@ -100,7 +104,7 @@ const expand = (ast, options = {}) => {
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (child.nodes) {
|
|
70
|
+
- walk(child, node);
|
|
71
|
+
+ walk(child, node, depth + 1);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
diff --git a/lib/parse.js b/lib/parse.js
|
|
76
|
+
index 3a6988e629f52aee6609dc5ec290a5e9ff47cecb..ec76ce445e89d8cf78b23596296f19f1832a8057 100644
|
|
77
|
+
--- a/lib/parse.js
|
|
78
|
+
+++ b/lib/parse.js
|
|
79
|
+
@@ -8,6 +8,7 @@ const stringify = require('./stringify');
|
|
80
|
+
|
|
81
|
+
const {
|
|
82
|
+
MAX_LENGTH,
|
|
83
|
+
+ MAX_DEPTH,
|
|
84
|
+
CHAR_BACKSLASH, /* \ */
|
|
85
|
+
CHAR_BACKTICK, /* ` */
|
|
86
|
+
CHAR_COMMA, /* , */
|
|
87
|
+
@@ -143,6 +144,10 @@ const parse = (input, options = {}) => {
|
|
88
|
+
*/
|
|
89
|
+
|
|
90
|
+
if (value === CHAR_LEFT_PARENTHESES) {
|
|
91
|
+
+ // 限制 AST 深度,避免后续递归遍历耗尽调用栈。
|
|
92
|
+
+ if (stack.length > MAX_DEPTH) {
|
|
93
|
+
+ throw new SyntaxError('Pattern nesting exceeds maximum depth');
|
|
94
|
+
+ }
|
|
95
|
+
block = push({ type: 'paren', nodes: [] });
|
|
96
|
+
stack.push(block);
|
|
97
|
+
push({ type: 'text', value });
|
|
98
|
+
@@ -195,6 +200,9 @@ const parse = (input, options = {}) => {
|
|
99
|
+
*/
|
|
100
|
+
|
|
101
|
+
if (value === CHAR_LEFT_CURLY_BRACE) {
|
|
102
|
+
+ if (stack.length > MAX_DEPTH) {
|
|
103
|
+
+ throw new SyntaxError('Pattern nesting exceeds maximum depth');
|
|
104
|
+
+ }
|
|
105
|
+
depth++;
|
|
106
|
+
|
|
107
|
+
const dollar = prev.value && prev.value.slice(-1) === '$' || block.dollar === true;
|
|
108
|
+
diff --git a/lib/stringify.js b/lib/stringify.js
|
|
109
|
+
index 8bcf872c31894f81a8c64d9202fd607e4fd7ea2b..a88fa77189d01ec08a8084ab6275be7a33d5efbd 100644
|
|
110
|
+
--- a/lib/stringify.js
|
|
111
|
+
+++ b/lib/stringify.js
|
|
112
|
+
@@ -1,9 +1,13 @@
|
|
113
|
+
'use strict';
|
|
114
|
+
|
|
115
|
+
const utils = require('./utils');
|
|
116
|
+
+const { MAX_DEPTH } = require('./constants');
|
|
117
|
+
|
|
118
|
+
module.exports = (ast, options = {}) => {
|
|
119
|
+
- const stringify = (node, parent = {}) => {
|
|
120
|
+
+ const stringify = (node, parent = {}, depth = 0) => {
|
|
121
|
+
+ if (node.nodes && depth > MAX_DEPTH) {
|
|
122
|
+
+ throw new SyntaxError('Pattern nesting exceeds maximum depth');
|
|
123
|
+
+ }
|
|
124
|
+
const invalidBlock = options.escapeInvalid && utils.isInvalidBrace(parent);
|
|
125
|
+
const invalidNode = node.invalid === true && options.escapeInvalid === true;
|
|
126
|
+
let output = '';
|
|
127
|
+
@@ -21,7 +25,7 @@ module.exports = (ast, options = {}) => {
|
|
128
|
+
|
|
129
|
+
if (node.nodes) {
|
|
130
|
+
for (const child of node.nodes) {
|
|
131
|
+
- output += stringify(child);
|
|
132
|
+
+ output += stringify(child, {}, depth + 1);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return output;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import test from "node:test";
|
|
4
|
+
|
|
5
|
+
const require = createRequire(import.meta.url);
|
|
6
|
+
|
|
7
|
+
for (const consumer of ["stylelint", "lint-staged"]) {
|
|
8
|
+
const consumerRequire = createRequire(require.resolve(consumer));
|
|
9
|
+
const micromatchRequire = createRequire(consumerRequire.resolve("micromatch"));
|
|
10
|
+
const braces = micromatchRequire("braces");
|
|
11
|
+
|
|
12
|
+
test(`${consumer} 保留常规嵌套 glob 的编译与展开结果`, () => {
|
|
13
|
+
const pattern = "src/{core,modules}/{a,b}.vue";
|
|
14
|
+
assert.equal(braces.compile(pattern), "src/(core|modules)/(a|b).vue");
|
|
15
|
+
assert.deepEqual(braces.expand(pattern), ["src/core/a.vue", "src/core/b.vue", "src/modules/a.vue", "src/modules/b.vue"]);
|
|
16
|
+
assert.equal(braces.stringify(pattern), pattern);
|
|
17
|
+
assert.deepEqual(braces.expand("{1..3}"), ["1", "2", "3"]);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
for (const [name, pattern] of [
|
|
21
|
+
["花括号", "{".repeat(4000) + "a,b" + "}".repeat(4000)],
|
|
22
|
+
["圆括号", "(".repeat(4000) + "a" + ")".repeat(4000)],
|
|
23
|
+
["未闭合括号", "{".repeat(4000) + "a"]
|
|
24
|
+
]) {
|
|
25
|
+
test(`${consumer} 在递归前拒绝过深${name}`, () => {
|
|
26
|
+
for (const method of ["parse", "compile", "expand", "stringify"]) {
|
|
27
|
+
assert.throws(() => braces[method](pattern), { name: "SyntaxError", message: "Pattern nesting exceeds maximum depth" });
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
test(`${consumer} 直接接收 AST 时仍限制遍历深度`, () => {
|
|
33
|
+
for (const method of ["compile", "expand", "stringify"]) {
|
|
34
|
+
let node = { type: "text", value: "a" };
|
|
35
|
+
for (let depth = 0; depth < 2000; depth++) {
|
|
36
|
+
const parent = { type: "paren", nodes: [node] };
|
|
37
|
+
node.parent = parent;
|
|
38
|
+
node = parent;
|
|
39
|
+
}
|
|
40
|
+
const ast = { type: "root", nodes: [node] };
|
|
41
|
+
node.parent = ast;
|
|
42
|
+
assert.throws(() => braces[method](ast), { name: "SyntaxError", message: "Pattern nesting exceeds maximum depth" });
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test(`${consumer} 不把转义字符或引号中的括号计入深度`, () => {
|
|
47
|
+
assert.doesNotThrow(() => braces.compile("\\{".repeat(1000)));
|
|
48
|
+
assert.doesNotThrow(() => braces.compile('"' + "{".repeat(1000) + '"'));
|
|
49
|
+
});
|
|
50
|
+
}
|