@widget-js/cli 1.2.11 → 24.1.1-beta.10
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/.idea/codeStyles/Project.xml +60 -0
- package/.idea/codeStyles/codeStyleConfig.xml +5 -0
- package/.idea/misc.xml +5 -7
- package/jest.config.js +3 -3
- package/lib/{chunk-RAXJBANW.js → chunk-I4ZBPB2S.js} +6 -6
- package/lib/{chunk-IJH6LXRT.js → chunk-RDJH7Z4C.js} +5 -5
- package/lib/{chunk-3GPAHQ6O.js → chunk-XPJ33Y5L.js} +2 -2
- package/lib/{createWidget-UFW26NP6.js → createWidget-4LQ6PVEM.js} +16 -16
- package/lib/{dependencies-MRJDJJ6Q.js → dependencies-AVNHKRF3.js} +18 -18
- package/lib/index.js +13 -8
- package/lib/{init-MQONV3N3.js → init-HCEGKTNF.js} +15 -15
- package/lib/publish-C52GHJWG.js +50 -0
- package/lib/{release-XUYU5WNC.js → release-5GS34BAJ.js} +52 -48
- package/package.json +29 -18
- package/src/build/build.ts +8 -8
- package/src/createWidget.ts +232 -226
- package/src/dependencies/index.ts +6 -5
- package/src/dependencies/localDependencies.ts +17 -18
- package/src/dependencies/remoteDependencies.ts +22 -25
- package/src/index.ts +47 -38
- package/src/init/init.ts +121 -119
- package/src/promts/promptChecker.ts +10 -8
- package/src/publish/index.ts +60 -0
- package/src/release/ftp.ts +31 -27
- package/src/release/oss.ts +41 -38
- package/src/release/release.ts +17 -24
- package/src/release/update-zip.ts +18 -14
- package/src/utils/EJSUtils.ts +18 -17
- package/src/utils/PrettierUtils.ts +12 -11
- package/src/utils/WidgetPackageUtils.ts +13 -13
- package/src/utils.ts +31 -27
- package/template/WidgetConfig.ejs +7 -6
- package/template/WidgetDefine.ejs +6 -18
- package/template/widget-router.ts +4 -3
- package/test/index.test.ts +7 -7
- package/tsconfig.json +25 -25
- package/tsup.config.ts +4 -4
- package/vite.config.ts +15 -15
- package/.editorconfig +0 -16
- package/.idea/inspectionProfiles/Project_Default.xml +0 -6
- package/.idea/jpa-buddy.xml +0 -6
- package/.idea/prettier.xml +0 -6
- package/release-xyy.json +0 -7
package/src/index.ts
CHANGED
|
@@ -1,56 +1,65 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
1
|
+
import fs from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import * as process from 'node:process'
|
|
4
|
+
import { Option, program } from 'commander'
|
|
5
5
|
|
|
6
|
-
import figlet from
|
|
7
|
-
import gradient from
|
|
8
|
-
import {dirname} from
|
|
6
|
+
import figlet from 'figlet'
|
|
7
|
+
import gradient from 'gradient-string'
|
|
8
|
+
import { dirname } from 'dirname-filename-esm'
|
|
9
9
|
|
|
10
10
|
//
|
|
11
|
-
const packageJsonPath = path.join(dirname(import.meta),
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
console.log(gradient.pastel.multiline(figlet.textSync(
|
|
15
|
-
program.version(`@widget-js/cli ${cliPackage.version}`).usage(
|
|
11
|
+
const packageJsonPath = path.join(dirname(import.meta), '../package.json')
|
|
12
|
+
const cliPackage = JSON.parse(fs.readFileSync(packageJsonPath).toString())
|
|
13
|
+
// eslint-disable-next-line no-console
|
|
14
|
+
console.log(gradient.pastel.multiline(figlet.textSync('widget-cli', { horizontalLayout: 'full' })))
|
|
15
|
+
program.version(`@widget-js/cli ${cliPackage.version}`).usage('<command> [options]')
|
|
16
16
|
program
|
|
17
|
-
.command(
|
|
18
|
-
.description(
|
|
17
|
+
.command('create')
|
|
18
|
+
.description('Create new widget')
|
|
19
19
|
.action(async () => {
|
|
20
|
-
const createWidget = await import(
|
|
21
|
-
await createWidget.default()
|
|
22
|
-
})
|
|
20
|
+
const createWidget = await import('./createWidget')
|
|
21
|
+
await createWidget.default()
|
|
22
|
+
})
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
const dependenciesOption = new Option('-t, --type <type>').choices(['remote', 'local'])
|
|
25
25
|
|
|
26
26
|
program
|
|
27
|
-
.command(
|
|
28
|
-
.description(
|
|
27
|
+
.command('dependencies')
|
|
28
|
+
.description('Set @widget-js dependencies to local(workspace:*) or remote(^1.0.0 etc)')
|
|
29
29
|
.addOption(dependenciesOption)
|
|
30
30
|
.action(async (options) => {
|
|
31
|
-
|
|
32
|
-
await dependencies.default(options)
|
|
33
|
-
})
|
|
31
|
+
const dependencies = await import('./dependencies/index')
|
|
32
|
+
await dependencies.default(options)
|
|
33
|
+
})
|
|
34
34
|
|
|
35
35
|
program
|
|
36
|
-
.command(
|
|
37
|
-
.description(
|
|
36
|
+
.command('init')
|
|
37
|
+
.description('Initialize widget-js project')
|
|
38
38
|
.action(async () => {
|
|
39
|
-
const init = await import(
|
|
40
|
-
await init.init()
|
|
41
|
-
})
|
|
39
|
+
const init = await import('./init/init')
|
|
40
|
+
await init.init()
|
|
41
|
+
})
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
let fileOption = new Option("-f, --file <file>");
|
|
43
|
+
const keyOption = new Option('-k, --key <key>')
|
|
45
44
|
program
|
|
46
|
-
.command(
|
|
47
|
-
.description(
|
|
45
|
+
.command('publish')
|
|
46
|
+
.description('Publish widget package with developer key')
|
|
47
|
+
.addOption(keyOption)
|
|
48
|
+
.action(async (options) => {
|
|
49
|
+
const publishImport = await import('./publish/index')
|
|
50
|
+
await publishImport.publish(options)
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
const typeOption = new Option('-t, --type <type>').choices(['ftp', 'oss'])
|
|
54
|
+
const fileOption = new Option('-f, --file <file>')
|
|
55
|
+
program
|
|
56
|
+
.command('release')
|
|
57
|
+
.description('通过FTP/OSS发布文件,仅内部使用')
|
|
48
58
|
.addOption(typeOption)
|
|
49
59
|
.addOption(fileOption)
|
|
50
|
-
.action(async (options
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
});
|
|
60
|
+
.action(async (options) => {
|
|
61
|
+
const release = await import('./release/release')
|
|
62
|
+
await release.default(options)
|
|
63
|
+
})
|
|
55
64
|
|
|
56
|
-
program.parse(process.argv)
|
|
65
|
+
program.parse(process.argv)
|
package/src/init/init.ts
CHANGED
|
@@ -1,119 +1,121 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import consola from 'consola'
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import {
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
await
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
await addDependency('@widget-js/
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
viteConfig =
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
vueRouterContent =
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
1
|
+
import path from 'node:path'
|
|
2
|
+
import process from 'node:process'
|
|
3
|
+
import fs from 'node:fs'
|
|
4
|
+
import { fileURLToPath } from 'node:url'
|
|
5
|
+
import consola from 'consola'
|
|
6
|
+
import chalk from 'chalk'
|
|
7
|
+
import ora from 'ora'
|
|
8
|
+
import { scanWidgetPackage } from '@widget-js/utils'
|
|
9
|
+
import { Utils } from '../utils'
|
|
10
|
+
import promptChecker from '../promts/promptChecker'
|
|
11
|
+
import { EJSUtils } from '../utils/EJSUtils'
|
|
12
|
+
import { PrettierUtils } from '../utils/PrettierUtils'
|
|
13
|
+
import { WidgetPackageUtils } from '../utils/WidgetPackageUtils'
|
|
14
|
+
|
|
15
|
+
const __filename = fileURLToPath(import.meta.url)
|
|
16
|
+
const __dirname = path.dirname(__filename)
|
|
17
|
+
const spinner = ora('Loading')
|
|
18
|
+
|
|
19
|
+
export async function init() {
|
|
20
|
+
await addDependencies()
|
|
21
|
+
await addWidgetTs()
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async function addWidgetTs() {
|
|
25
|
+
const name = await promptChecker(
|
|
26
|
+
{
|
|
27
|
+
type: 'input',
|
|
28
|
+
name: 'name',
|
|
29
|
+
message: chalk.blue('组件包 包名 (示例 cn.widget.countdown):'),
|
|
30
|
+
},
|
|
31
|
+
(answer) => {
|
|
32
|
+
const name = answer.name
|
|
33
|
+
if (name == null || name === '') {
|
|
34
|
+
consola.log(chalk.red(`包名不能为空`))
|
|
35
|
+
return false
|
|
36
|
+
}
|
|
37
|
+
return true
|
|
38
|
+
},
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
const widgetPackageTs = path.join(process.cwd(), 'widget.package.ts')
|
|
42
|
+
if (fs.existsSync(widgetPackageTs)) {
|
|
43
|
+
spinner.info('widget.package.ts已存在,跳过')
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
spinner.info('创建 widget.package.ts')
|
|
47
|
+
await EJSUtils.renderToFile('WidgetPackage.ejs', widgetPackageTs, 'typescript', { name })
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
await addVitePlugin()
|
|
51
|
+
await createRouter()
|
|
52
|
+
|
|
53
|
+
spinner.succeed('初始化完成,请运行 npm install')
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* 增加widget-js依赖
|
|
58
|
+
*/
|
|
59
|
+
async function addDependencies() {
|
|
60
|
+
const packageJson = Utils.getPackageJson()
|
|
61
|
+
let dependencies = packageJson.dependencies
|
|
62
|
+
const devDependencies = packageJson.devDependencies
|
|
63
|
+
if (!dependencies) {
|
|
64
|
+
dependencies = {}
|
|
65
|
+
}
|
|
66
|
+
if (!devDependencies) {
|
|
67
|
+
packageJson.devDependencies = {}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
await addDependency('@widget-js/core', dependencies)
|
|
71
|
+
await addDependency('@widget-js/vue3', dependencies)
|
|
72
|
+
await addDependency('@widget-js/vite-plugin-widget', devDependencies)
|
|
73
|
+
|
|
74
|
+
packageJson.dependencies = dependencies
|
|
75
|
+
packageJson.devDependencies = devDependencies
|
|
76
|
+
|
|
77
|
+
fs.writeFileSync(Utils.getPackagePath(), JSON.stringify(packageJson, null, 2))
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async function addVitePlugin() {
|
|
81
|
+
spinner.info('添加 vite-plugin-widget 到 vite plugin')
|
|
82
|
+
const viteConfigPath = path.join(process.cwd(), 'vite.config.ts')
|
|
83
|
+
if (!fs.existsSync(viteConfigPath)) {
|
|
84
|
+
spinner.warn('vite.config.ts not exists')
|
|
85
|
+
return
|
|
86
|
+
}
|
|
87
|
+
let viteConfig = fs.readFileSync(viteConfigPath).toString()
|
|
88
|
+
viteConfig = `import widget from '@widget-js/vite-plugin-widget'\n${viteConfig}`
|
|
89
|
+
viteConfig = viteConfig.replace('vue()', `vue(),widget()`)
|
|
90
|
+
fs.writeFileSync(viteConfigPath, await PrettierUtils.format(viteConfig, 'typescript'))
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async function createRouter() {
|
|
94
|
+
const widgetPackage = await scanWidgetPackage()
|
|
95
|
+
if (widgetPackage) {
|
|
96
|
+
spinner.info('创建 widget-router.ts')
|
|
97
|
+
const rootDir = WidgetPackageUtils.getRootDir(widgetPackage)
|
|
98
|
+
const widgetRouterPath = path.join(rootDir, 'widget-router.ts')
|
|
99
|
+
const routerContent = fs.readFileSync(path.join(__dirname, '../template/widget-router.ts'), 'utf8')
|
|
100
|
+
fs.writeFileSync(widgetRouterPath, routerContent)
|
|
101
|
+
|
|
102
|
+
const vueRouterPath = path.join(process.cwd(), './src/router/index.ts')
|
|
103
|
+
spinner.info('修改VueRouter配置')
|
|
104
|
+
if (fs.existsSync(vueRouterPath)) {
|
|
105
|
+
let vueRouterContent = fs.readFileSync(vueRouterPath, 'utf8')
|
|
106
|
+
const importStr = `import WidgetRouter from "../widgets/widget-router";`
|
|
107
|
+
vueRouterContent = `${importStr}\n${vueRouterContent}`
|
|
108
|
+
vueRouterContent = vueRouterContent.replace('routes: [', `routes: [\n...WidgetRouter,`)
|
|
109
|
+
fs.writeFileSync(vueRouterPath, await PrettierUtils.format(vueRouterContent, 'typescript'))
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
async function addDependency(packageName: string, dependencies: any) {
|
|
115
|
+
spinner.info(`Adding dependencies ${packageName}`)
|
|
116
|
+
if (dependencies[packageName]) {
|
|
117
|
+
return
|
|
118
|
+
}
|
|
119
|
+
const remoteVersion = await Utils.getRemoteVersion(packageName)
|
|
120
|
+
dependencies[packageName] = `^${remoteVersion}`
|
|
121
|
+
}
|
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
import
|
|
1
|
+
import type { Answers, Question } from 'inquirer'
|
|
2
|
+
import inquirer from 'inquirer'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
const answer:Answers = await inquirer.prompt([prompt])
|
|
4
|
+
async function promptChecker<T extends Question>(prompt: T, checker?: (answer: any) => boolean): Promise<any> {
|
|
5
|
+
const answer: Answers = await inquirer.prompt([prompt])
|
|
5
6
|
if (checker) {
|
|
6
7
|
if (checker(answer)) {
|
|
7
|
-
return answer[prompt.name!]
|
|
8
|
-
}
|
|
9
|
-
|
|
8
|
+
return answer[prompt.name!]
|
|
9
|
+
}
|
|
10
|
+
else {
|
|
11
|
+
return promptChecker(prompt, checker)
|
|
10
12
|
}
|
|
11
13
|
}
|
|
12
|
-
return answer[prompt.name!]
|
|
14
|
+
return answer[prompt.name!]
|
|
13
15
|
}
|
|
14
16
|
|
|
15
|
-
export default promptChecker
|
|
17
|
+
export default promptChecker
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import fs from 'node:fs'
|
|
2
|
+
import fastGlob from 'fast-glob'
|
|
3
|
+
import axios from 'axios'
|
|
4
|
+
import consola from 'consola'
|
|
5
|
+
import ora from 'ora'
|
|
6
|
+
/**
|
|
7
|
+
* 用fast-glob扫描运行目录下第一个 widget.json 文件
|
|
8
|
+
* 然后用axios发送post请求到 https://widgetjs.cn/api/widget/package,把key加到请求头中,把 widget.json 文件内容作为请求体
|
|
9
|
+
*/
|
|
10
|
+
export async function publish(options: { key: string }): Promise<void> {
|
|
11
|
+
if (!options.key) {
|
|
12
|
+
consola.error('Please provide a developer key with -k or --key option.')
|
|
13
|
+
return
|
|
14
|
+
}
|
|
15
|
+
const spinner = ora('Search widget.json').start()
|
|
16
|
+
try {
|
|
17
|
+
// Scan the current directory for the first widget.json file, ignore node_modules
|
|
18
|
+
const files = await fastGlob('**/widget.json', { onlyFiles: true, ignore: ['node_modules/**'], absolute: true })
|
|
19
|
+
if (files.length === 0) {
|
|
20
|
+
spinner.fail('No widget.json file found.')
|
|
21
|
+
return
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
spinner.succeed(`Widget.json found: ${files[0]}`)
|
|
25
|
+
|
|
26
|
+
const widgetPath = files[0]
|
|
27
|
+
const widgetContent = fs.readFileSync(widgetPath, 'utf-8')
|
|
28
|
+
|
|
29
|
+
const json = JSON.parse(widgetContent)
|
|
30
|
+
consola.info(`Package name:${json.name}`)
|
|
31
|
+
const widgets = json.widgets
|
|
32
|
+
consola.info(`Widget size:${widgets?.length ?? 0}`)
|
|
33
|
+
|
|
34
|
+
spinner.start('Publishing widget package...')
|
|
35
|
+
// Send a POST request to the specified URL with the widget content
|
|
36
|
+
const response = await axios.post('https://widgetjs.cn/api/v1/widget/package', json, {
|
|
37
|
+
headers: {
|
|
38
|
+
'Content-Type': 'application/json',
|
|
39
|
+
'Key': options.key,
|
|
40
|
+
},
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
if (response.data) {
|
|
44
|
+
if (response.data.code == 200) {
|
|
45
|
+
spinner.succeed('Widget published successfully.')
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
spinner.fail('Failed to publish widget.')
|
|
49
|
+
consola.error(response.data.msg)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
spinner.fail('Empty Response')
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
spinner.fail('Failed to publish widget.')
|
|
58
|
+
consola.error(error)
|
|
59
|
+
}
|
|
60
|
+
}
|
package/src/release/ftp.ts
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import path from 'path'
|
|
2
|
-
import fs from 'fs'
|
|
1
|
+
import path from 'node:path'
|
|
2
|
+
import fs from 'node:fs'
|
|
3
|
+
import os from 'node:os'
|
|
4
|
+
import * as process from 'node:process'
|
|
3
5
|
import SSHConfig from '@widget-js/ssh-config'
|
|
4
|
-
import os from 'os'
|
|
5
6
|
import Client from 'ssh2-sftp-client'
|
|
6
7
|
import consola from 'consola'
|
|
7
8
|
import inquirer from 'inquirer'
|
|
8
9
|
import ora from 'ora'
|
|
9
|
-
import
|
|
10
|
-
import {Utils} from '../utils'
|
|
11
|
-
import {minimatch} from 'minimatch'
|
|
10
|
+
import { minimatch } from 'minimatch'
|
|
11
|
+
import { Utils } from '../utils'
|
|
12
12
|
|
|
13
13
|
interface PasswordAnswer {
|
|
14
14
|
password: string
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
async function checkParentDir(ftpClient: Client, file: string, onMkdir: (dir: string) => void) {
|
|
18
|
-
|
|
18
|
+
const dir = path.dirname(file)
|
|
19
19
|
const dirExists = await ftpClient.exists(dir)
|
|
20
20
|
if (!dirExists) {
|
|
21
21
|
onMkdir(dir)
|
|
@@ -26,38 +26,39 @@ async function checkParentDir(ftpClient: Client, file: string, onMkdir: (dir: st
|
|
|
26
26
|
async function runSSH(sshConfig: Record<string, string | string[]>, releaseConfig: ReleaseConfig) {
|
|
27
27
|
consola.info('run ssh:', sshConfig)
|
|
28
28
|
const answer = await inquirer.prompt<PasswordAnswer>([
|
|
29
|
-
{type: 'password', name: 'password', mask: '*', message: 'Enter key pair password'},
|
|
29
|
+
{ type: 'password', name: 'password', mask: '*', message: 'Enter key pair password' },
|
|
30
30
|
])
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
const port = sshConfig
|
|
32
|
+
const ftpClient = new Client()
|
|
33
|
+
const port = sshConfig.Port
|
|
34
34
|
const key = fs.readFileSync(path.resolve(os.homedir(), '.ssh/id_rsa'))
|
|
35
35
|
const spinner = ora('Connecting')
|
|
36
36
|
try {
|
|
37
37
|
spinner.start()
|
|
38
38
|
await ftpClient.connect({
|
|
39
|
-
host: sshConfig
|
|
40
|
-
port: port ? parseInt(port as string) : 22,
|
|
41
|
-
username: sshConfig
|
|
39
|
+
host: sshConfig.HostName as string,
|
|
40
|
+
port: port ? Number.parseInt(port as string) : 22,
|
|
41
|
+
username: sshConfig.User as string,
|
|
42
42
|
passphrase: answer.password,
|
|
43
43
|
privateKey: key,
|
|
44
44
|
})
|
|
45
45
|
releaseConfig.fileMap.sort((it1, it2) => (it1.order ?? 0) - (it2.order ?? 0))
|
|
46
46
|
// upload files
|
|
47
|
-
for (
|
|
47
|
+
for (const item of releaseConfig.fileMap) {
|
|
48
48
|
if (typeof item.src == 'string') {
|
|
49
49
|
if (item.remoteCopy) {
|
|
50
|
-
await checkParentDir(ftpClient, item.dest, dir => {
|
|
50
|
+
await checkParentDir(ftpClient, item.dest, (dir) => {
|
|
51
51
|
spinner.warn(`Create Dir: ${dir}`)
|
|
52
52
|
})
|
|
53
|
-
|
|
53
|
+
const destExists = await ftpClient.exists(item.dest)
|
|
54
54
|
if (destExists) {
|
|
55
55
|
spinner.warn(`Delete exists file:${item.dest}`)
|
|
56
56
|
await ftpClient.delete(item.dest)
|
|
57
57
|
}
|
|
58
58
|
spinner.info(`Copying File: ${item.src} -> ${item.dest}`)
|
|
59
59
|
await ftpClient.rcopy(item.src, item.dest)
|
|
60
|
-
}
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
61
62
|
const localFile = path.resolve(process.cwd(), item.src as string)
|
|
62
63
|
if (!item.remoteCopy && !fs.existsSync(localFile)) {
|
|
63
64
|
spinner.warn(`Skip not exists file:${localFile}`)
|
|
@@ -66,19 +67,20 @@ async function runSSH(sshConfig: Record<string, string | string[]>, releaseConfi
|
|
|
66
67
|
if (fs.lstatSync(localFile).isDirectory()) {
|
|
67
68
|
spinner.info(`Uploading Dir: ${localFile} -> ${item.dest}`)
|
|
68
69
|
await ftpClient.uploadDir(localFile, item.dest, {
|
|
69
|
-
filter: (filePath: string, isDirectory: boolean):boolean => {
|
|
70
|
+
filter: (filePath: string, isDirectory: boolean): boolean => {
|
|
70
71
|
if (item.ignorePattern && !isDirectory) {
|
|
71
|
-
|
|
72
|
+
const fileName = path.basename(filePath)
|
|
72
73
|
if (minimatch(fileName, item.ignorePattern)) {
|
|
73
74
|
spinner.warn(`Skip file:${filePath}`)
|
|
74
75
|
return false
|
|
75
76
|
}
|
|
76
77
|
}
|
|
77
|
-
return true
|
|
78
|
+
return true
|
|
78
79
|
},
|
|
79
80
|
})
|
|
80
|
-
}
|
|
81
|
-
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
await checkParentDir(ftpClient, item.dest, (dir) => {
|
|
82
84
|
spinner.succeed(`Create Dir: ${dir}`)
|
|
83
85
|
})
|
|
84
86
|
|
|
@@ -86,13 +88,15 @@ async function runSSH(sshConfig: Record<string, string | string[]>, releaseConfi
|
|
|
86
88
|
await ftpClient.put(localFile, item.dest)
|
|
87
89
|
}
|
|
88
90
|
}
|
|
89
|
-
}
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
90
93
|
await ftpClient.put(Buffer.from(JSON.stringify(item.src), 'utf-8'), item.dest)
|
|
91
94
|
}
|
|
92
95
|
}
|
|
93
96
|
spinner.succeed('Files uploaded!')
|
|
94
97
|
await ftpClient.end()
|
|
95
|
-
}
|
|
98
|
+
}
|
|
99
|
+
catch (e) {
|
|
96
100
|
spinner.fail(`Connection error:${e}`)
|
|
97
101
|
await ftpClient.end()
|
|
98
102
|
}
|
|
@@ -104,13 +108,13 @@ export async function ftpUpload(releaseFile: string = 'release.json') {
|
|
|
104
108
|
const packageVersion = Utils.getPackageVersion()
|
|
105
109
|
consola.info('Package Version:', packageVersion)
|
|
106
110
|
|
|
107
|
-
|
|
111
|
+
const releaseJson = fs.readFileSync(releaseJsonFilePath).toString().replaceAll('${version}', packageVersion)
|
|
108
112
|
const releaseConfig = JSON.parse(releaseJson) as ReleaseConfig
|
|
109
113
|
const sshConfigFile = path.resolve(os.homedir(), '.ssh/config')
|
|
110
114
|
consola.info('SSH Config File Path:', sshConfigFile)
|
|
111
115
|
const sshConfigs = SSHConfig.parse(fs.readFileSync(sshConfigFile).toString())
|
|
112
|
-
for (
|
|
113
|
-
|
|
116
|
+
for (const host of releaseConfig.ftpConfig.host) {
|
|
117
|
+
const sshConfig = sshConfigs.compute(host)
|
|
114
118
|
if (!sshConfig) {
|
|
115
119
|
consola.error(`SSH config ${releaseConfig.ftpConfig.host} not found`)
|
|
116
120
|
return
|