@weotro/dx 0.1.21 → 0.2.0

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.
Files changed (71) hide show
  1. package/README.md +76 -768
  2. package/bin/dx.js +100 -182
  3. package/example/.env.development +1 -0
  4. package/example/README.md +24 -0
  5. package/example/dx/scripts/build +2 -0
  6. package/example/dx/scripts/db +2 -0
  7. package/example/dx/scripts/deploy +2 -0
  8. package/example/dx/scripts/setup +2 -0
  9. package/example/dx/scripts/start +12 -0
  10. package/example/dx/scripts/test +2 -0
  11. package/lib/env.js +40 -257
  12. package/lib/logger.js +5 -238
  13. package/lib/setup.js +72 -0
  14. package/package.json +27 -13
  15. package/skills/ask_3th/SKILL.md +2 -0
  16. package/skills/delegate_3th/SKILL.md +4 -2
  17. package/skills/delegate_3th/scripts/delegate_3th.py +37 -41
  18. package/skills/delegate_3th/scripts/test_delegate_3th.py +43 -17
  19. package/bin/dx-with-version-env.js +0 -8
  20. package/lib/artifact-deploy/artifact-builder.js +0 -144
  21. package/lib/artifact-deploy/config.js +0 -180
  22. package/lib/artifact-deploy/remote-script.js +0 -301
  23. package/lib/artifact-deploy/remote-transport.js +0 -86
  24. package/lib/artifact-deploy.js +0 -70
  25. package/lib/backend-artifact-deploy/artifact-builder.js +0 -267
  26. package/lib/backend-artifact-deploy/config.js +0 -218
  27. package/lib/backend-artifact-deploy/path-utils.js +0 -18
  28. package/lib/backend-artifact-deploy/remote-phases.js +0 -14
  29. package/lib/backend-artifact-deploy/remote-result.js +0 -44
  30. package/lib/backend-artifact-deploy/remote-script.js +0 -507
  31. package/lib/backend-artifact-deploy/remote-transport.js +0 -123
  32. package/lib/backend-artifact-deploy/rollback.js +0 -5
  33. package/lib/backend-artifact-deploy/runtime-package.js +0 -46
  34. package/lib/backend-artifact-deploy.js +0 -91
  35. package/lib/backend-package.js +0 -674
  36. package/lib/cli/args.js +0 -38
  37. package/lib/cli/command-result.js +0 -1
  38. package/lib/cli/commands/contracts.js +0 -60
  39. package/lib/cli/commands/core.js +0 -533
  40. package/lib/cli/commands/db.js +0 -231
  41. package/lib/cli/commands/deploy.js +0 -175
  42. package/lib/cli/commands/env.js +0 -120
  43. package/lib/cli/commands/export.js +0 -39
  44. package/lib/cli/commands/package.js +0 -22
  45. package/lib/cli/commands/release.js +0 -55
  46. package/lib/cli/commands/stack.js +0 -427
  47. package/lib/cli/commands/start.js +0 -58
  48. package/lib/cli/commands/worktree.js +0 -145
  49. package/lib/cli/dx-cli.js +0 -1098
  50. package/lib/cli/flags.js +0 -123
  51. package/lib/cli/help-model.js +0 -234
  52. package/lib/cli/help-renderer.js +0 -137
  53. package/lib/cli/help-schema.js +0 -552
  54. package/lib/cli/help.js +0 -141
  55. package/lib/cli/index.js +0 -4
  56. package/lib/cli/nx-command.js +0 -13
  57. package/lib/confirm.js +0 -213
  58. package/lib/env-policy.js +0 -134
  59. package/lib/env-profile.js +0 -531
  60. package/lib/exec.js +0 -698
  61. package/lib/nx-ignore.js +0 -45
  62. package/lib/run-with-version-env.js +0 -163
  63. package/lib/sdk-build.js +0 -424
  64. package/lib/start-dev.js +0 -401
  65. package/lib/telegram-webhook.js +0 -431
  66. package/lib/validate-env.js +0 -317
  67. package/lib/vercel-deploy.js +0 -549
  68. package/lib/worktree.js +0 -1052
  69. package/skills/delegate_3th/scripts/__pycache__/delegate_3th.cpython-314.pyc +0 -0
  70. package/skills/delegate_3th/scripts/__pycache__/delegate_cc.cpython-314.pyc +0 -0
  71. package/skills/delegate_3th/scripts/__pycache__/test_delegate_cc.cpython-314.pyc +0 -0
package/lib/cli/flags.js DELETED
@@ -1,123 +0,0 @@
1
- export const FLAG_DEFINITIONS = {
2
- _global: [
3
- { flag: '--dev' },
4
- { flag: '--prod' },
5
- { flag: '--staging' },
6
- { flag: '--test' },
7
- { flag: '--e2e' },
8
- { flag: '--no-env-check' },
9
- { flag: '-Y' },
10
- { flag: '--yes' },
11
- { flag: '-v' },
12
- { flag: '--verbose' },
13
- { flag: '-h' },
14
- { flag: '--help' },
15
- { flag: '-V' },
16
- { flag: '--version' },
17
- { flag: '--parallel' },
18
- { flag: '-P' },
19
- ],
20
- db: [
21
- { flag: '--name', expectsValue: true },
22
- { flag: '-n', expectsValue: true },
23
- ],
24
- test: [
25
- { flag: '-t', expectsValue: true },
26
- { flag: '--name', expectsValue: true },
27
- { flag: '--test-name-pattern', expectsValue: true },
28
- ],
29
- package: [
30
- { flag: '--skip-build' },
31
- { flag: '--keep-workdir' },
32
- ],
33
- worktree: [
34
- { flag: '--base', expectsValue: true },
35
- { flag: '-b', expectsValue: true },
36
- { flag: '--all' },
37
- ],
38
- lint: [
39
- { flag: '--fix' },
40
- ],
41
- deploy: [
42
- { flag: '--BR' },
43
- { flag: '--build-only' },
44
- { flag: '--artifact', expectsValue: true },
45
- { flag: '--skip-migration' },
46
- { flag: '--webhook-path', expectsValue: true },
47
- { flag: '--webhook-dry-run' },
48
- { flag: '--strict-webhook' },
49
- { flag: '--no-strict-webhook' },
50
- ],
51
- }
52
-
53
- export function parseFlags(args = []) {
54
- const flags = {}
55
-
56
- for (let index = 0; index < args.length; index += 1) {
57
- const flag = args[index]
58
- if (flag === '--') break
59
- if (!flag.startsWith('-')) continue
60
- switch (flag) {
61
- case '--dev':
62
- flags.dev = true
63
- break
64
- case '--prod':
65
- flags.prod = true
66
- break
67
- case '--staging':
68
- flags.staging = true
69
- break
70
- case '--test':
71
- flags.test = true
72
- break
73
- case '--e2e':
74
- flags.e2e = true
75
- break
76
- case '-Y':
77
- case '--yes':
78
- flags.Y = true
79
- break
80
- case '-v':
81
- case '--verbose':
82
- flags.verbose = true
83
- break
84
- case '-h':
85
- case '--help':
86
- flags.help = true
87
- break
88
- case '-V':
89
- case '--version':
90
- flags.version = true
91
- break
92
- case '--no-env-check':
93
- flags.noEnvCheck = true
94
- break
95
- case '--fix':
96
- flags.fix = true
97
- break
98
- case '--parallel':
99
- case '-P':
100
- flags.parallel = true
101
- break
102
- case '--all':
103
- flags.all = true
104
- break
105
- case '--BR':
106
- flags.BR = true
107
- break
108
- case '--build-only':
109
- flags.buildOnly = true
110
- break
111
- case '--artifact':
112
- flags.artifact = args[index + 1]
113
- break
114
- case '--skip-migration':
115
- flags.skipMigration = true
116
- break
117
- default:
118
- break
119
- }
120
- }
121
-
122
- return flags
123
- }
@@ -1,234 +0,0 @@
1
- const ENVIRONMENT_KEYS = new Set(['development', 'production', 'staging', 'test', 'e2e'])
2
- const COMMAND_LIST_HIDDEN = new Set(['help'])
3
- const META_KEYS = new Set(['help', 'description', 'args', 'interactive', 'dangerous'])
4
- const INTERNAL_CONFIG_KEYS = new Set([
5
- 'services',
6
- 'urls',
7
- 'preflight',
8
- 'ecosystemConfig',
9
- 'pm2Bin',
10
- 'backendDeploy',
11
- 'artifactDeploy',
12
- 'telegramWebhook',
13
- ])
14
- const BUILTIN_SUMMARIES = {
15
- env: '安全校验并临时装配本地品牌环境配置',
16
- }
17
-
18
- export function buildHelpRuntimeContext(cli = {}) {
19
- return {
20
- registeredCommands: getRegisteredCommands(cli),
21
- knownFlags: getKnownFlags(cli),
22
- }
23
- }
24
-
25
- export function getRegisteredCommands(cli = {}) {
26
- const handlers = cli?.commandHandlers
27
- if (!handlers || typeof handlers !== 'object') return []
28
-
29
- return Object.keys(handlers).filter(name => !COMMAND_LIST_HIDDEN.has(name))
30
- }
31
-
32
- export function getKnownFlags(cli = {}) {
33
- const definitions = cli?.flagDefinitions
34
- const knownFlags = new Map()
35
-
36
- if (!definitions || typeof definitions !== 'object') return knownFlags
37
-
38
- for (const entries of Object.values(definitions)) {
39
- if (!Array.isArray(entries)) continue
40
- for (const entry of entries) {
41
- if (!entry?.flag) continue
42
- knownFlags.set(entry.flag, {
43
- expectsValue: Boolean(entry.expectsValue),
44
- })
45
- }
46
- }
47
-
48
- return knownFlags
49
- }
50
-
51
- export function classifyCommandNode(node = {}) {
52
- if (node?.help?.nodeType) return node.help.nodeType
53
- if (looksLikeInternalConfigBag(node)) return 'internal-config-bag'
54
- if (node?.command || node?.internal) return 'target-leaf'
55
- if (node?.concurrent || node?.sequential) return 'orchestration-node'
56
- if (looksLikeEnvContainer(node)) return 'env-container'
57
- if (looksLikeCategoryNode(node)) return 'category-node'
58
- return 'unknown-node'
59
- }
60
-
61
- export function isVisibleHelpNode(name, node, nodeType = classifyCommandNode(node)) {
62
- void name
63
-
64
- if (node?.help?.expose === false) return false
65
- if (nodeType === 'internal-config-bag') return false
66
- if (nodeType === 'category-node') return false
67
- if (nodeType === 'orchestration-node') return node?.help?.expose === true
68
- return true
69
- }
70
-
71
- export function getGlobalHelpModel(commands = {}, context = {}) {
72
- const registeredCommands = Array.isArray(context?.registeredCommands)
73
- ? context.registeredCommands
74
- : []
75
-
76
- return {
77
- summary: commands?.help?.summary ?? '',
78
- commands: registeredCommands.map(name => getCommandHelpModel(commands, name, context)),
79
- globalOptions: normalizeArray(commands?.help?.globalOptions),
80
- examples: normalizeArray(commands?.help?.examples),
81
- }
82
- }
83
-
84
- export function getCommandHelpModel(commands = {}, commandName, context = {}) {
85
- const commandConfig = commands?.[commandName] ?? {}
86
- const commandHelp = getCommandHelpConfig(commands, commandName)
87
- const notes = [...normalizeArray(commandHelp?.notes)]
88
- if (hasPassthroughCommand(commandConfig)) {
89
- notes.push(`自定义 command 叶节点设置 allowPassthrough: true 后可透传参数:dx ${commandName} <命令路径> [环境标志] -- <子命令参数>;未开启或组合/internal 命令收到额外参数会报错。`)
90
- }
91
-
92
- return {
93
- name: commandName,
94
- summary: resolveSummary(commandConfig, commandHelp) || BUILTIN_SUMMARIES[commandName] || '',
95
- usage: resolveUsage(commandName, commandHelp, commandConfig),
96
- args: normalizeArray(commandHelp?.args),
97
- notes,
98
- examples: normalizeArray(commandHelp?.examples),
99
- options: normalizeArray(commandHelp?.options),
100
- targets: resolveVisibleTargets(commands, commandName, commandConfig, context),
101
- }
102
- }
103
-
104
- function hasPassthroughCommand(node) {
105
- if (!isPlainObject(node)) return false
106
- if (node.command || node.internal || node.concurrent || node.sequential) {
107
- return Boolean(node.command && node.allowPassthrough === true && !node.internal && !node.concurrent && !node.sequential)
108
- }
109
- return Object.entries(node).some(([key, value]) => key !== 'help' && hasPassthroughCommand(value))
110
- }
111
-
112
- export function resolveSummary(node = {}, help = null) {
113
- return help?.summary || node?.help?.summary || node?.description || ''
114
- }
115
-
116
- function resolveUsage(commandName, commandHelp = {}, commandConfig = {}) {
117
- return commandHelp?.usage || generateUsage(commandName, commandConfig)
118
- }
119
-
120
- function generateUsage(commandName, commandConfig = {}) {
121
- switch (commandName) {
122
- case 'start':
123
- return 'dx start <service> [环境标志]'
124
- case 'build':
125
- case 'package':
126
- return `dx ${commandName} <target> [环境标志]`
127
- case 'db':
128
- return 'dx db <action> [name] [环境标志]'
129
- case 'test':
130
- return 'dx test [type] <target> [path]'
131
- case 'deploy':
132
- case 'clean':
133
- case 'cache':
134
- return `dx ${commandName} <target>`
135
- case 'help':
136
- return 'dx help [command]'
137
- case 'worktree':
138
- return 'dx worktree [action] [args...]'
139
- case 'env':
140
- return 'dx env status | validate <profile> [环境标志] | exec <profile> [环境标志] -- <command>'
141
- case 'lint':
142
- case 'status':
143
- return `dx ${commandName}`
144
- default:
145
- return hasVisibleTargets(commandConfig) ? `dx ${commandName} <target>` : `dx ${commandName}`
146
- }
147
- }
148
-
149
- function hasVisibleTargets(commandConfig) {
150
- if (!isPlainObject(commandConfig)) return false
151
-
152
- return Object.entries(commandConfig).some(([name, node]) => {
153
- if (name === 'help') return false
154
- return isVisibleHelpNode(name, node)
155
- })
156
- }
157
-
158
- function resolveVisibleTargets(commands, commandName, commandConfig, context) {
159
- void context
160
-
161
- if (!isPlainObject(commandConfig)) return []
162
-
163
- return Object.entries(commandConfig)
164
- .filter(([name]) => name !== 'help')
165
- .map(([name, node]) => {
166
- const nodeType = classifyCommandNode(node)
167
- if (!isVisibleHelpNode(name, node, nodeType)) return null
168
-
169
- const targetHelp = getTargetHelpConfig(commands, commandName, name)
170
-
171
- return {
172
- name,
173
- nodeType,
174
- summary: resolveSummary(node, targetHelp),
175
- notes: normalizeArray(targetHelp?.notes),
176
- options: normalizeArray(targetHelp?.options),
177
- examples: normalizeArray(targetHelp?.examples),
178
- }
179
- })
180
- .filter(Boolean)
181
- }
182
-
183
- function getCommandHelpConfig(commands, commandName) {
184
- const config = commands?.help?.commands?.[commandName]
185
- return isPlainObject(config) ? config : {}
186
- }
187
-
188
- function getTargetHelpConfig(commands, commandName, targetName) {
189
- const config = commands?.help?.targets?.[commandName]?.[targetName]
190
- return isPlainObject(config) ? config : {}
191
- }
192
-
193
- function looksLikeInternalConfigBag(node) {
194
- if (!isPlainObject(node)) return false
195
- if (node.command || node.internal || node.concurrent || node.sequential) return false
196
- if (looksLikeEnvContainer(node)) return false
197
-
198
- const visibleKeys = getVisibleKeys(node)
199
- if (visibleKeys.length === 0) return false
200
-
201
- return visibleKeys.some(key => INTERNAL_CONFIG_KEYS.has(key))
202
- }
203
-
204
- function looksLikeEnvContainer(node) {
205
- if (!isPlainObject(node)) return false
206
- const visibleKeys = getVisibleKeys(node)
207
- if (visibleKeys.length === 0) return false
208
-
209
- const envKeys = visibleKeys.filter(key => ENVIRONMENT_KEYS.has(key))
210
- return envKeys.length > 0 && envKeys.length === visibleKeys.length
211
- }
212
-
213
- function looksLikeCategoryNode(node) {
214
- if (!isPlainObject(node)) return false
215
- if (node.command || node.internal || node.concurrent || node.sequential) return false
216
- if (looksLikeEnvContainer(node) || looksLikeInternalConfigBag(node)) return false
217
-
218
- const visibleKeys = getVisibleKeys(node)
219
- if (visibleKeys.length === 0) return false
220
-
221
- return visibleKeys.every(key => isPlainObject(node[key]))
222
- }
223
-
224
- function getVisibleKeys(node) {
225
- return Object.keys(node).filter(key => !META_KEYS.has(key))
226
- }
227
-
228
- function normalizeArray(value) {
229
- return Array.isArray(value) ? value : []
230
- }
231
-
232
- function isPlainObject(value) {
233
- return Boolean(value) && typeof value === 'object' && !Array.isArray(value)
234
- }
@@ -1,137 +0,0 @@
1
- function normalizeArray(value) {
2
- return Array.isArray(value) ? value : []
3
- }
4
-
5
- function pushSection(lines, title, entries = []) {
6
- const normalizedEntries = entries.filter(Boolean)
7
- if (normalizedEntries.length === 0) return
8
-
9
- lines.push('', title, ...normalizedEntries)
10
- }
11
-
12
- function formatExample(example = {}, indent = ' ') {
13
- const command = typeof example.command === 'string' ? example.command : ''
14
- const description = typeof example.description === 'string' ? example.description : ''
15
-
16
- if (!command) return ''
17
- if (!description) return `${indent}${command}`
18
- return `${indent}${command} # ${description}`
19
- }
20
-
21
- function formatOption(option = {}, indent = ' ') {
22
- const flags = normalizeArray(option.flags).filter(Boolean).join(', ')
23
- const description = typeof option.description === 'string' ? option.description : ''
24
-
25
- if (!flags && !description) return ''
26
- if (!description) return `${indent}${flags}`
27
- return `${indent}${flags} ${description}`
28
- }
29
-
30
- function getVisibleTargets(targets = []) {
31
- return normalizeArray(targets).filter(target => target?.nodeType !== 'orchestration-node')
32
- }
33
-
34
- function formatTarget(target = {}, width = 0) {
35
- const name = typeof target.name === 'string' ? target.name : ''
36
- const summary = typeof target.summary === 'string' ? target.summary : ''
37
- const lines = []
38
-
39
- if (!name) return lines
40
-
41
- lines.push(summary ? ` ${name.padEnd(width)} ${summary}` : ` ${name}`)
42
-
43
- normalizeArray(target.notes).forEach(note => {
44
- if (!note) return
45
- lines.push(` 提示: ${note}`)
46
- })
47
-
48
- normalizeArray(target.options).forEach(option => {
49
- const rendered = formatOption(option, ' 选项: ')
50
- if (rendered) lines.push(rendered)
51
- })
52
-
53
- normalizeArray(target.examples).forEach(example => {
54
- const rendered = formatExample(example, ' 示例: ')
55
- if (rendered) lines.push(rendered)
56
- })
57
-
58
- return lines
59
- }
60
-
61
- export function renderGlobalHelp(model = {}) {
62
- const lines = []
63
- const invocation = model.invocation || 'dx'
64
- const title = [model.title, model.summary].filter(Boolean).join(' - ') || model.title || model.summary
65
- const commands = normalizeArray(model.commands)
66
- const commandWidth = Math.max(0, ...commands.map(command => String(command?.name || '').length))
67
-
68
- if (title) {
69
- lines.push('', title)
70
- }
71
-
72
- pushSection(lines, '用法:', [` ${invocation} <命令> [选项] [参数...]`])
73
- pushSection(
74
- lines,
75
- '命令:',
76
- commands.map(command => {
77
- const name = String(command?.name || '')
78
- const summary = String(command?.summary || '')
79
- if (!name) return ''
80
- return summary ? ` ${name.padEnd(commandWidth)} ${summary}` : ` ${name}`
81
- }),
82
- )
83
- pushSection(lines, '选项:', normalizeArray(model.globalOptions).map(option => formatOption(option)))
84
- pushSection(lines, '示例:', normalizeArray(model.examples).map(example => formatExample(example)))
85
-
86
- lines.push('', `运行 ${invocation} help <命令> 查看子命令的详细用法和示例`)
87
-
88
- return lines.join('\n')
89
- }
90
-
91
- export function renderCommandHelp(model = {}) {
92
- const name = typeof model.name === 'string' ? model.name : ''
93
- const usage = typeof model.usage === 'string' ? model.usage : ''
94
- const args = normalizeArray(model.args)
95
- const notes = normalizeArray(model.notes)
96
- const options = normalizeArray(model.options)
97
- const examples = normalizeArray(model.examples)
98
- const targets = getVisibleTargets(model.targets)
99
- const targetWidth = Math.max(0, ...targets.map(target => String(target?.name || '').length))
100
- const lines = []
101
-
102
- if (name) {
103
- lines.push('', `${name} 命令用法:`)
104
- }
105
-
106
- if (usage) {
107
- lines.push(` ${usage}`)
108
- }
109
-
110
- if (model.summary) {
111
- pushSection(lines, '摘要:', [` ${model.summary}`])
112
- }
113
-
114
- pushSection(
115
- lines,
116
- '参数说明:',
117
- args.map(arg => {
118
- const argName = typeof arg.name === 'string' ? arg.name : ''
119
- const description = typeof arg.description === 'string' ? arg.description : ''
120
-
121
- if (!argName && !description) return ''
122
- if (!description) return ` ${argName}`
123
- return ` ${argName}: ${description}`
124
- }),
125
- )
126
-
127
- pushSection(
128
- lines,
129
- '可用 target:',
130
- targets.flatMap(target => formatTarget(target, targetWidth)),
131
- )
132
- pushSection(lines, '选项:', options.map(option => formatOption(option)))
133
- pushSection(lines, '提示:', notes.map(note => (note ? ` ${note}` : '')))
134
- pushSection(lines, '示例:', examples.map(example => formatExample(example)))
135
-
136
- return lines.join('\n')
137
- }