@kdcloudjs/cli 0.0.1 → 0.0.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
@@ -19,4 +19,45 @@ kd project create kwcdemo --type kwc
19
19
  #### 创建页面元数据
20
20
  ```
21
21
  kd project create kwcdemo --type page
22
+ ```
23
+
24
+ #### 环境配置
25
+ ```
26
+ 创建环境
27
+ kd env create dev --url https://dev.com
28
+
29
+ 设置目标环境
30
+ kd env set target-env dev
31
+
32
+ 当前环境信息
33
+ kd env info
34
+
35
+ 环境列表
36
+ kd env list
37
+
38
+ 删除环境
39
+ kd env delete dev
40
+
41
+ ```
42
+
43
+ #### 认证授权
44
+ ```
45
+ openapi认证
46
+ kd env auth openapi -e dev
47
+
48
+ ```
49
+
50
+ #### 上传
51
+ ```
52
+ kd project deploy
53
+ kd project deploy -e dev
54
+ kd project deploy -e dev -d app/kwc
55
+
56
+ ```
57
+
58
+ #### 调试
59
+ ```
60
+ kd debug
61
+ kd debug -e dev
62
+
22
63
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kdcloudjs/cli",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "Kingdee CLI",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"
@@ -0,0 +1,102 @@
1
+ const fs = require('fs')
2
+ const path = require('path')
3
+ const { findProjectRoot } = require('../project/deploy/projectRoot')
4
+ const { getEnvByName, loadDefaultEnv } = require('../env/config')
5
+ const { error, info } = require('../../utils/log')
6
+ const { safePrompts } = require('../../utils/prompts')
7
+ const { openBrowser, waitForPort, walk, getFormId } = require('./utils')
8
+ const { installDeps, runDebug } = require('./runner')
9
+
10
+ module.exports = async function debug(options = {}) {
11
+ const cwd = process.cwd()
12
+ const root = findProjectRoot(cwd)
13
+
14
+ if (!root) {
15
+ error('Current directory is not a KWC project')
16
+ return
17
+ }
18
+
19
+ // 1. Check and install dependencies
20
+ if (!fs.existsSync(path.join(root, 'node_modules'))) {
21
+ try {
22
+ await installDeps(root)
23
+ } catch (e) {
24
+ error(e.message)
25
+ return
26
+ }
27
+ }
28
+
29
+ // 2. Resolve Environment
30
+ let env
31
+ const envName = options.targetEnv
32
+ if (envName) {
33
+ env = getEnvByName(envName)
34
+ if (!env) {
35
+ error(`Environment "${envName}" not found`)
36
+ return
37
+ }
38
+ } else {
39
+ env = loadDefaultEnv()
40
+ if (!env || !env.name) {
41
+ error('No environment specified and no default environment found')
42
+ return
43
+ }
44
+ info(`Using default environment: ${env.name}`)
45
+ }
46
+
47
+ if (!env.url) {
48
+ error(`Environment "${env.name}" has no URL configured`)
49
+ return
50
+ }
51
+
52
+ // 3. Get Form IDs
53
+ const pagesDir = path.join(root, 'app/pages')
54
+ const pageFiles = walk(pagesDir)
55
+ const forms = []
56
+
57
+ for (const file of pageFiles) {
58
+ const id = getFormId(file)
59
+ if (id) {
60
+ forms.push({
61
+ title: id,
62
+ value: id
63
+ })
64
+ }
65
+ }
66
+
67
+ if (forms.length === 0) {
68
+ error('No pages found in app/pages')
69
+ return
70
+ }
71
+
72
+ // 4. Select Form
73
+ const response = await safePrompts({
74
+ type: 'select',
75
+ name: 'formId',
76
+ message: 'Select a form to debug',
77
+ choices: forms
78
+ })
79
+
80
+ if (!response.formId) return
81
+
82
+ // 5. Construct URL
83
+ const targetUrl = new URL(env.url)
84
+ targetUrl.searchParams.append('formId', response.formId)
85
+ targetUrl.searchParams.append('kdkwc_cdn', 'http://localhost:3333')
86
+ const finalUrl = targetUrl.toString()
87
+
88
+ // 6. Open Browser & Start Debug
89
+ // Start server first
90
+ const { promise: serverPromise, child } = runDebug(root)
91
+
92
+ try {
93
+ info('Waiting for debug server to be ready...')
94
+ await waitForPort(3333, child)
95
+ info(`Opening: ${finalUrl}`)
96
+ openBrowser(finalUrl)
97
+ } catch (e) {
98
+ error(`Server start failed: ${e.message}`)
99
+ }
100
+
101
+ await serverPromise
102
+ }
@@ -0,0 +1,38 @@
1
+ const { spawn } = require('child_process')
2
+ const { info } = require('../../utils/log')
3
+
4
+ function installDeps(root) {
5
+ return new Promise((resolve, reject) => {
6
+ info('Installing dependencies...')
7
+ const child = spawn('npm', ['install'], {
8
+ cwd: root,
9
+ stdio: 'inherit',
10
+ shell: true
11
+ })
12
+ child.on('close', (code) => {
13
+ if (code === 0) resolve()
14
+ else reject(new Error(`npm install failed with code ${code}`))
15
+ })
16
+ })
17
+ }
18
+
19
+ function runDebug(root) {
20
+ info('Starting debug server...')
21
+ let childProcess
22
+ const promise = new Promise((resolve, reject) => {
23
+ const child = spawn('npm', ['run', 'debug'], {
24
+ cwd: root,
25
+ stdio: 'inherit',
26
+ shell: true
27
+ })
28
+ childProcess = child
29
+ child.on('close', resolve)
30
+ child.on('error', reject)
31
+ })
32
+ return { promise, child: childProcess }
33
+ }
34
+
35
+ module.exports = {
36
+ installDeps,
37
+ runDebug
38
+ }
@@ -0,0 +1,84 @@
1
+ const fs = require('fs')
2
+ const path = require('path')
3
+ const net = require('net')
4
+ const { exec } = require('child_process')
5
+
6
+ function openBrowser(url) {
7
+ let cmd
8
+ if (process.platform === 'win32') {
9
+ cmd = `start "" "${url}"`
10
+ } else if (process.platform === 'darwin') {
11
+ cmd = `open "${url}"`
12
+ } else {
13
+ cmd = `xdg-open "${url}"`
14
+ }
15
+ exec(cmd)
16
+ }
17
+
18
+ function checkPort(port) {
19
+ return new Promise((resolve, reject) => {
20
+ const socket = new net.Socket()
21
+ socket.setTimeout(200)
22
+ socket.on('connect', () => {
23
+ socket.destroy()
24
+ resolve(true)
25
+ })
26
+ socket.on('timeout', () => {
27
+ socket.destroy()
28
+ reject(new Error('timeout'))
29
+ })
30
+ socket.on('error', (err) => {
31
+ socket.destroy()
32
+ reject(err)
33
+ })
34
+ socket.connect(port, '127.0.0.1')
35
+ })
36
+ }
37
+
38
+ async function waitForPort(port, child, retries = 60) {
39
+ for (let i = 0; i < retries; i++) {
40
+ if (child.exitCode !== null) {
41
+ throw new Error(`Server process exited with code ${child.exitCode}`)
42
+ }
43
+ try {
44
+ await checkPort(port)
45
+ return true
46
+ } catch (e) {
47
+ await new Promise(r => setTimeout(r, 1000))
48
+ }
49
+ }
50
+ throw new Error(`Timeout waiting for port ${port}`)
51
+ }
52
+
53
+ function walk(dir, files = []) {
54
+ if (!fs.existsSync(dir)) return files
55
+
56
+ const items = fs.readdirSync(dir)
57
+ for (const item of items) {
58
+ const fullPath = path.join(dir, item)
59
+ const stat = fs.statSync(fullPath)
60
+ if (stat.isDirectory()) {
61
+ walk(fullPath, files)
62
+ } else if (item.endsWith('.page-meta.kwp')) {
63
+ files.push(fullPath)
64
+ }
65
+ }
66
+ return files
67
+ }
68
+
69
+ function getFormId(filePath) {
70
+ try {
71
+ const content = fs.readFileSync(filePath, 'utf-8')
72
+ const match = content.match(/<name>(.*?)<\/name>/)
73
+ return match ? match[1] : null
74
+ } catch (e) {
75
+ return null
76
+ }
77
+ }
78
+
79
+ module.exports = {
80
+ openBrowser,
81
+ waitForPort,
82
+ walk,
83
+ getFormId
84
+ }
@@ -0,0 +1,9 @@
1
+ module.exports = function registerDebug(program) {
2
+ program
3
+ .command('debug')
4
+ .description('Debug project')
5
+ .option('-e, --target-env <env>', 'specified target environment')
6
+ .action((options) =>
7
+ require('../actions/debug')(options)
8
+ )
9
+ }
@@ -41,14 +41,6 @@ module.exports = function registerEnv(program) {
41
41
  require('./delete')(name)
42
42
  )
43
43
 
44
- env
45
- .command('remote [envName]')
46
- .description('Open remote environment page with local debug server')
47
- .requiredOption('-f, --form-id <id>', 'Form ID')
48
- .action((envName, options) =>
49
- require('./remote')(envName, options)
50
- )
51
-
52
44
  const auth = env
53
45
  .command('auth')
54
46
  .description('Authenticate environment')
@@ -56,7 +48,7 @@ module.exports = function registerEnv(program) {
56
48
  auth
57
49
  .command('web')
58
50
  .description('Authenticate via Web (username/password)')
59
- .option('--env <name>', 'target environment name')
51
+ .option('-e --target-env <name>', 'target environment name')
60
52
  .action((options) =>
61
53
  require('./auth')('web', options)
62
54
  )
@@ -64,7 +56,7 @@ module.exports = function registerEnv(program) {
64
56
  auth
65
57
  .command('openapi')
66
58
  .description('Authenticate via OpenAPI (client credentials)')
67
- .option('--env <name>', 'target environment name')
59
+ .option('-e --target-env <name>', 'target environment name')
68
60
  .action((options) =>
69
61
  require('./auth')('openapi', options)
70
62
  )
package/src/index.js CHANGED
@@ -20,5 +20,6 @@ program
20
20
 
21
21
  require('./commands/project')(program)
22
22
  require('./commands/env')(program)
23
+ require('./commands/debug')(program)
23
24
 
24
25
  program.parse(process.argv)
@@ -1,59 +0,0 @@
1
- const { exec } = require('child_process')
2
- const { getEnvByName, loadDefaultEnv } = require('./config')
3
- const { error, info } = require('../../utils/log')
4
-
5
- module.exports = async function remote(envName, options) {
6
- const { formId } = options
7
-
8
- if (!formId) {
9
- error('Error: --form-id (-f) is required')
10
- return
11
- }
12
-
13
- let env
14
- if (envName) {
15
- env = getEnvByName(envName)
16
- if (!env) {
17
- error(`Error: Environment "${envName}" not found`)
18
- return
19
- }
20
- } else {
21
- env = loadDefaultEnv()
22
- if (!env || !env.name) {
23
- error('Error: No environment specified and no default environment found')
24
- return
25
- }
26
- info(`Using default environment: ${env.name}`)
27
- }
28
-
29
- if (!env.url) {
30
- error(`Error: Environment "${env.name}" has no URL configured`)
31
- return
32
- }
33
-
34
- try {
35
- const targetUrl = new URL(env.url)
36
- targetUrl.searchParams.append('formId', formId)
37
- targetUrl.searchParams.append('kdkwc_cdn', 'http://localhost:3333')
38
-
39
- const finalUrl = targetUrl.toString()
40
- info(`Opening: ${finalUrl}`)
41
-
42
- let cmd
43
- if (process.platform === 'win32') {
44
- cmd = `start "" "${finalUrl}"`
45
- } else if (process.platform === 'darwin') {
46
- cmd = `open "${finalUrl}"`
47
- } else {
48
- cmd = `xdg-open "${finalUrl}"`
49
- }
50
-
51
- exec(cmd, (err) => {
52
- if (err) {
53
- error(`Failed to open browser: ${err.message}`)
54
- }
55
- })
56
- } catch (e) {
57
- error(`Invalid Environment URL: ${env.url}`)
58
- }
59
- }
@@ -1,2 +0,0 @@
1
- module.exports = (envName, options) =>
2
- require('../../actions/env/remote')(envName, options)