@ranger1/dx 0.1.0 → 0.1.1
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 +10 -9
- package/bin/dx.js +45 -9
- package/lib/cli/dx-cli.js +8 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,25 +4,24 @@
|
|
|
4
4
|
|
|
5
5
|
## 安装
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
全局安装(推荐):
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
pnpm add -
|
|
10
|
+
pnpm add -g @ranger1/dx
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
安装后即可在任意目录使用:
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
pnpm exec dx build sdk --dev
|
|
16
|
+
dx --help
|
|
17
|
+
dx status
|
|
19
18
|
```
|
|
20
19
|
|
|
21
|
-
|
|
20
|
+
项目内安装(可选,如果你更希望锁定版本):
|
|
22
21
|
|
|
23
22
|
```bash
|
|
24
|
-
pnpm add -
|
|
25
|
-
dx --help
|
|
23
|
+
pnpm add -D @ranger1/dx
|
|
24
|
+
pnpm exec dx --help
|
|
26
25
|
```
|
|
27
26
|
|
|
28
27
|
## 项目配置(必须)
|
|
@@ -46,6 +45,8 @@ dx/
|
|
|
46
45
|
- 环境变量:`DX_CONFIG_DIR=/abs/path/to/config`
|
|
47
46
|
- 参数:`dx --config-dir /abs/path/to/config ...`
|
|
48
47
|
|
|
48
|
+
全局安装场景下,如果你不在项目目录内执行,也可以通过 `DX_CONFIG_DIR` / `--config-dir` 显式指定配置目录(目录下需要存在 `commands.json`)。
|
|
49
|
+
|
|
49
50
|
## 命令
|
|
50
51
|
|
|
51
52
|
dx 的命令由 `dx/config/commands.json` 驱动,并且内置了一些 internal runner(避免项目侧依赖任何 `scripts/lib/*.js`):
|
package/bin/dx.js
CHANGED
|
@@ -43,24 +43,60 @@ function findProjectRootFrom(startDir) {
|
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
function findRepoRootFrom(startDir) {
|
|
47
|
+
let current = resolve(startDir)
|
|
48
|
+
while (true) {
|
|
49
|
+
// ai-monorepo style marker
|
|
50
|
+
if (existsSync(join(current, 'pnpm-workspace.yaml'))) return current
|
|
51
|
+
// fallback marker
|
|
52
|
+
if (existsSync(join(current, 'package.json'))) return current
|
|
53
|
+
|
|
54
|
+
const parent = dirname(current)
|
|
55
|
+
if (parent === current) return null
|
|
56
|
+
current = parent
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function inferProjectRootFromConfigDir(configDir, startDir) {
|
|
61
|
+
const normalized = String(configDir).replace(/\\/g, '/')
|
|
62
|
+
if (normalized.endsWith('/dx/config')) return resolve(configDir, '..', '..')
|
|
63
|
+
if (normalized.endsWith('/scripts/config')) return resolve(configDir, '..', '..')
|
|
64
|
+
|
|
65
|
+
return findRepoRootFrom(configDir) || findRepoRootFrom(startDir) || resolve(startDir)
|
|
66
|
+
}
|
|
67
|
+
|
|
46
68
|
async function main() {
|
|
47
69
|
const rawArgs = process.argv.slice(2)
|
|
48
70
|
const overrideConfigDir = parseConfigDir(rawArgs)
|
|
49
71
|
const filteredArgs = stripConfigDirArgs(rawArgs)
|
|
50
72
|
|
|
51
73
|
const startDir = process.cwd()
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
74
|
+
let projectRoot
|
|
75
|
+
let configDir
|
|
76
|
+
|
|
77
|
+
if (overrideConfigDir) {
|
|
78
|
+
// When dx is installed globally, users may prefer providing DX_CONFIG_DIR/--config-dir.
|
|
79
|
+
// In that case, do not require dx/config marker discovery.
|
|
80
|
+
configDir = resolve(startDir, overrideConfigDir)
|
|
81
|
+
if (!existsSync(join(configDir, 'commands.json'))) {
|
|
82
|
+
console.error(`dx: 配置目录无效: ${configDir}`)
|
|
83
|
+
console.error('dx: 期望存在 commands.json')
|
|
84
|
+
process.exit(1)
|
|
85
|
+
}
|
|
86
|
+
projectRoot = inferProjectRootFromConfigDir(configDir, startDir)
|
|
87
|
+
} else {
|
|
88
|
+
projectRoot = findProjectRootFrom(startDir)
|
|
89
|
+
if (!projectRoot) {
|
|
90
|
+
console.error('dx: 未找到项目配置目录: dx/config/commands.json')
|
|
91
|
+
console.error('dx: 请在项目目录内执行 dx,或先创建 dx/config 并放置 commands.json')
|
|
92
|
+
console.error('dx: 也可通过 DX_CONFIG_DIR 或 --config-dir 指定配置目录')
|
|
93
|
+
process.exit(1)
|
|
94
|
+
}
|
|
95
|
+
configDir = join(projectRoot, 'dx', 'config')
|
|
58
96
|
}
|
|
59
97
|
|
|
60
98
|
process.env.DX_PROJECT_ROOT = projectRoot
|
|
61
|
-
|
|
62
|
-
const defaultConfigDir = join(projectRoot, 'dx', 'config')
|
|
63
|
-
process.env.DX_CONFIG_DIR = overrideConfigDir ? resolve(projectRoot, overrideConfigDir) : defaultConfigDir
|
|
99
|
+
process.env.DX_CONFIG_DIR = configDir
|
|
64
100
|
|
|
65
101
|
process.chdir(projectRoot)
|
|
66
102
|
|
package/lib/cli/dx-cli.js
CHANGED
|
@@ -610,17 +610,19 @@ class DxCli {
|
|
|
610
610
|
// 校验是否在仓库根目录执行
|
|
611
611
|
ensureRepoRoot() {
|
|
612
612
|
const cwd = process.cwd()
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
'package.json',
|
|
616
|
-
'apps',
|
|
617
|
-
'dx/config/commands.json',
|
|
618
|
-
]
|
|
613
|
+
|
|
614
|
+
const markers = ['pnpm-workspace.yaml', 'package.json', 'apps']
|
|
619
615
|
const missing = markers.filter(p => !existsSync(join(cwd, p)))
|
|
620
616
|
if (missing.length) {
|
|
621
617
|
logger.error(`请从仓库根目录运行此命令。缺少标识文件/目录: ${missing.join(', ')}`)
|
|
622
618
|
process.exit(1)
|
|
623
619
|
}
|
|
620
|
+
|
|
621
|
+
const commandsPath = join(this.configDir, 'commands.json')
|
|
622
|
+
if (!existsSync(commandsPath)) {
|
|
623
|
+
logger.error(`未找到命令配置文件: ${commandsPath}`)
|
|
624
|
+
process.exit(1)
|
|
625
|
+
}
|
|
624
626
|
}
|
|
625
627
|
|
|
626
628
|
async getWorktreeManager() {
|