@ranger1/dx 0.1.0 → 0.1.2

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 CHANGED
@@ -1,28 +1,27 @@
1
1
  # dx
2
2
 
3
- 一个可安装的 Node.js CLI,用于管理 ai-monorepo 类项目的构建/启动/数据库/部署等流程。
3
+ 一个可安装的 Node.js CLI,用于管理符合约定的 pnpm + nx monorepo 项目的构建/启动/数据库/部署等流程。
4
4
 
5
5
  ## 安装
6
6
 
7
- 项目内安装(推荐):
7
+ 全局安装(推荐):
8
8
 
9
9
  ```bash
10
- pnpm add -D dx
10
+ pnpm add -g @ranger1/dx
11
11
  ```
12
12
 
13
- 使用:
13
+ 安装后即可在任意目录使用:
14
14
 
15
15
  ```bash
16
- pnpm exec dx --help
17
- pnpm exec dx status
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 -g dx
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`):
@@ -75,7 +76,7 @@ dx test e2e backend
75
76
 
76
77
  ```json
77
78
  {
78
- "command": "../../node_modules/.bin/dx-with-version-env --app front -- next build"
79
+ "command": "dx-with-version-env --app front -- next build"
79
80
  }
80
81
  ```
81
82
 
@@ -83,10 +84,11 @@ dx test e2e backend
83
84
 
84
85
  ## 约束与假设
85
86
 
86
- 当前版本面向 ai-monorepo 类结构,默认假设:
87
+ 当前版本面向 pnpm + nx 的 monorepo,默认假设:
87
88
 
88
89
  - 使用 pnpm + nx
89
- - 项目布局包含 `apps/backend`、`apps/front`、`apps/admin-front`、`apps/sdk`
90
+ - 项目布局包含 `apps/backend`、`apps/front`、`apps/admin-front`、`apps/sdk`(如果你的命令配置不依赖这些目录,可自行调整)
91
+ - 版本注入脚本 `dx-with-version-env` 默认支持 app: `backend` / `front` / `admin`
90
92
 
91
93
  ## 发布到 npm(准备工作)
92
94
 
@@ -100,4 +102,3 @@ dx test e2e backend
100
102
  npm publish --access public --registry=https://registry.npmjs.org
101
103
  ```
102
104
 
103
- 提示:当前仓库包含一个 `.npmrc`,用于确保 publish 走 npm 官方 registry(避免镜像源导致发布失败)。
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
- const projectRoot = findProjectRootFrom(startDir)
53
- if (!projectRoot) {
54
- console.error('dx: 未找到项目配置目录: dx/config/commands.json')
55
- console.error('dx: 请在项目目录内执行 dx,或先创建 dx/config 并放置 commands.json')
56
- console.error('dx: 也可通过 DX_CONFIG_DIR --config-dir 指定配置目录')
57
- process.exit(1)
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
@@ -8,6 +8,7 @@ import { validateEnvironment } from '../validate-env.js'
8
8
  import { FLAG_DEFINITIONS, parseFlags } from './flags.js'
9
9
  import { getCleanArgs } from './args.js'
10
10
  import { showHelp, showCommandHelp } from './help.js'
11
+ import { getPackageVersion } from '../version.js'
11
12
  import {
12
13
  handleHelp,
13
14
  handleDev,
@@ -261,6 +262,11 @@ class DxCli {
261
262
  // 主执行方法
262
263
  async run() {
263
264
  try {
265
+ if (this.flags.version) {
266
+ console.log(getPackageVersion())
267
+ return
268
+ }
269
+
264
270
  // 显示帮助
265
271
  if (this.flags.help || !this.command) {
266
272
  if (this.flags.help && this.command && this.command !== 'help') {
@@ -610,17 +616,19 @@ class DxCli {
610
616
  // 校验是否在仓库根目录执行
611
617
  ensureRepoRoot() {
612
618
  const cwd = process.cwd()
613
- const markers = [
614
- 'pnpm-workspace.yaml',
615
- 'package.json',
616
- 'apps',
617
- 'dx/config/commands.json',
618
- ]
619
+
620
+ const markers = ['pnpm-workspace.yaml', 'package.json', 'apps']
619
621
  const missing = markers.filter(p => !existsSync(join(cwd, p)))
620
622
  if (missing.length) {
621
623
  logger.error(`请从仓库根目录运行此命令。缺少标识文件/目录: ${missing.join(', ')}`)
622
624
  process.exit(1)
623
625
  }
626
+
627
+ const commandsPath = join(this.configDir, 'commands.json')
628
+ if (!existsSync(commandsPath)) {
629
+ logger.error(`未找到命令配置文件: ${commandsPath}`)
630
+ process.exit(1)
631
+ }
624
632
  }
625
633
 
626
634
  async getWorktreeManager() {
package/lib/cli/flags.js CHANGED
@@ -15,6 +15,8 @@ export const FLAG_DEFINITIONS = {
15
15
  { flag: '--verbose' },
16
16
  { flag: '-h' },
17
17
  { flag: '--help' },
18
+ { flag: '-V' },
19
+ { flag: '--version' },
18
20
  { flag: '--parallel' },
19
21
  { flag: '-P' },
20
22
  ],
@@ -74,6 +76,10 @@ export function parseFlags(args = []) {
74
76
  case '--help':
75
77
  flags.help = true
76
78
  break
79
+ case '-V':
80
+ case '--version':
81
+ flags.version = true
82
+ break
77
83
  case '--no-env-check':
78
84
  flags.noEnvCheck = true
79
85
  break
package/lib/cli/help.js CHANGED
@@ -1,6 +1,9 @@
1
+ import { getPackageVersion } from '../version.js'
2
+
1
3
  export function showHelp() {
4
+ const version = getPackageVersion()
2
5
  console.log(`
3
- DX CLI - 统一开发环境管理工具
6
+ DX CLI v${version} - 统一开发环境管理工具
4
7
 
5
8
  用法:
6
9
  dx <命令> [选项] [参数...]
@@ -67,8 +70,9 @@ DX CLI - 统一开发环境管理工具
67
70
  --test 使用测试环境
68
71
  --e2e 使用E2E测试环境
69
72
  -Y, --yes 跳过所有确认提示
70
- -v, --verbose 详细输出
71
- -h, --help 显示此帮助信息
73
+ -v, --verbose 详细输出
74
+ -h, --help 显示此帮助信息
75
+ -V, --version 显示版本号
72
76
 
73
77
  示例:
74
78
  dx start stack # PM2 交互式服务栈(推荐)- 同时管理三个服务
package/lib/version.js ADDED
@@ -0,0 +1,14 @@
1
+ import { readFileSync } from 'node:fs'
2
+ import { join, dirname } from 'node:path'
3
+ import { fileURLToPath } from 'node:url'
4
+
5
+ export function getPackageVersion() {
6
+ try {
7
+ const here = dirname(fileURLToPath(import.meta.url))
8
+ const pkgPath = join(here, '..', 'package.json')
9
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'))
10
+ return typeof pkg.version === 'string' ? pkg.version : '0.0.0'
11
+ } catch {
12
+ return '0.0.0'
13
+ }
14
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ranger1/dx",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "repository": {