@widget-js/cli 1.1.0 → 1.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/.editorconfig +16 -0
- package/.idea/cli.iml +4 -7
- package/.idea/jpa-buddy.xml +6 -0
- package/.idea/misc.xml +9 -0
- package/.prettierrc +21 -21
- package/lib/{chunk-SIAOIY3B.js → chunk-NJPDF23X.js} +7 -0
- package/lib/{createWidget-KWBUF3TN.js → createWidget-LWD7JPGR.js} +1 -1
- package/lib/dependencies-J3BZI237.js +87 -0
- package/lib/index.cjs +119 -68
- package/lib/index.js +6 -6
- package/lib/{release-PBOWWLKA.js → release-U3O2EENP.js} +1 -2
- package/package.json +3 -2
- package/release.json +21 -21
- package/src/build/build.ts +35 -35
- package/src/dependencies/index.ts +12 -0
- package/src/dependencies/localDependencies.ts +30 -0
- package/src/{upgrade/upgrade.ts → dependencies/remoteDependencies.ts} +12 -15
- package/src/index.ts +56 -55
- package/src/release/ftp.ts +116 -116
- package/src/release/release.ts +74 -75
- package/src/utils.ts +11 -8
- package/template/WidgetConfig.ejs +4 -10
- package/.idea/codeStyles/Project.xml +0 -58
- package/.idea/codeStyles/codeStyleConfig.xml +0 -5
- package/.idea/jsLibraryMappings.xml +0 -6
- package/lib/upgrade-ETO2LGMX.js +0 -52
package/release.json
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
{
|
|
2
|
-
"fileMap": [
|
|
3
|
-
{
|
|
4
|
-
"src": "./dist/youlu-${version}-setup-win-ia32.exe",
|
|
5
|
-
"dest": "/www/wwwroot/download.tool-vip.com/youlu/youlu.exe",
|
|
6
|
-
"order": 0
|
|
7
|
-
},
|
|
8
|
-
{
|
|
9
|
-
"src": ".gitignore",
|
|
10
|
-
"dest": "/www/wwwroot/template/aa/.gitignore"
|
|
11
|
-
},
|
|
12
|
-
{
|
|
13
|
-
"src": "/www/wwwroot/template/aa/.gitignore",
|
|
14
|
-
"dest": "/www/wwwroot/template/bbb/.gitignorexxx",
|
|
15
|
-
"remoteCopy": true
|
|
16
|
-
}
|
|
17
|
-
],
|
|
18
|
-
"ftpConfig": {
|
|
19
|
-
"host": "youlu"
|
|
20
|
-
}
|
|
21
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"fileMap": [
|
|
3
|
+
{
|
|
4
|
+
"src": "./dist/youlu-${version}-setup-win-ia32.exe",
|
|
5
|
+
"dest": "/www/wwwroot/download.tool-vip.com/youlu/youlu.exe",
|
|
6
|
+
"order": 0
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"src": ".gitignore",
|
|
10
|
+
"dest": "/www/wwwroot/template/aa/.gitignore"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"src": "/www/wwwroot/template/aa/.gitignore",
|
|
14
|
+
"dest": "/www/wwwroot/template/bbb/.gitignorexxx",
|
|
15
|
+
"remoteCopy": true
|
|
16
|
+
}
|
|
17
|
+
],
|
|
18
|
+
"ftpConfig": {
|
|
19
|
+
"host": "youlu"
|
|
20
|
+
}
|
|
21
|
+
}
|
package/src/build/build.ts
CHANGED
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
import ora from 'ora'
|
|
2
|
-
import {exec} from 'child_process'
|
|
3
|
-
import consola from 'consola'
|
|
4
|
-
|
|
5
|
-
export function build() {
|
|
6
|
-
const preloadSpinner = ora('Preload').start()
|
|
7
|
-
const mainSpinner = ora('Main').start()
|
|
8
|
-
//@ts-ignore
|
|
9
|
-
const build = exec('npm run build:preload').on('close', () => {
|
|
10
|
-
consola.success('done')
|
|
11
|
-
})
|
|
12
|
-
//@ts-ignore
|
|
13
|
-
build.stdout.on('data', data => {
|
|
14
|
-
consola.log('data', data)
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
//@ts-ignore
|
|
18
|
-
exec('npm run build:main', (error, stdout, stderr) => {
|
|
19
|
-
if (error) {
|
|
20
|
-
consola.error('error: ' + error)
|
|
21
|
-
return
|
|
22
|
-
}
|
|
23
|
-
consola.log('stdout: ' + stdout)
|
|
24
|
-
consola.log('stderr: ' + typeof stderr)
|
|
25
|
-
})
|
|
26
|
-
.on('message', () => {
|
|
27
|
-
consola.log('on-message')
|
|
28
|
-
})
|
|
29
|
-
.on('data', () => {
|
|
30
|
-
consola.log('on-data')
|
|
31
|
-
})
|
|
32
|
-
.on('close', () => {
|
|
33
|
-
consola.log('done')
|
|
34
|
-
})
|
|
35
|
-
}
|
|
1
|
+
import ora from 'ora'
|
|
2
|
+
import {exec} from 'child_process'
|
|
3
|
+
import consola from 'consola'
|
|
4
|
+
|
|
5
|
+
export function build() {
|
|
6
|
+
const preloadSpinner = ora('Preload').start()
|
|
7
|
+
const mainSpinner = ora('Main').start()
|
|
8
|
+
//@ts-ignore
|
|
9
|
+
const build = exec('npm run build:preload').on('close', () => {
|
|
10
|
+
consola.success('done')
|
|
11
|
+
})
|
|
12
|
+
//@ts-ignore
|
|
13
|
+
build.stdout.on('data', data => {
|
|
14
|
+
consola.log('data', data)
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
//@ts-ignore
|
|
18
|
+
exec('npm run build:main', (error, stdout, stderr) => {
|
|
19
|
+
if (error) {
|
|
20
|
+
consola.error('error: ' + error)
|
|
21
|
+
return
|
|
22
|
+
}
|
|
23
|
+
consola.log('stdout: ' + stdout)
|
|
24
|
+
consola.log('stderr: ' + typeof stderr)
|
|
25
|
+
})
|
|
26
|
+
.on('message', () => {
|
|
27
|
+
consola.log('on-message')
|
|
28
|
+
})
|
|
29
|
+
.on('data', () => {
|
|
30
|
+
consola.log('on-data')
|
|
31
|
+
})
|
|
32
|
+
.on('close', () => {
|
|
33
|
+
consola.log('done')
|
|
34
|
+
})
|
|
35
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import {RemoteDependencies} from "./remoteDependencies";
|
|
2
|
+
import {LocalDependencies} from "./localDependencies";
|
|
3
|
+
|
|
4
|
+
export type DependenciesOptions = 'remote' | 'local';
|
|
5
|
+
export default async function (options: any) {
|
|
6
|
+
let type = options.type as DependenciesOptions;
|
|
7
|
+
if (type == 'remote') {
|
|
8
|
+
await RemoteDependencies.start()
|
|
9
|
+
} else {
|
|
10
|
+
await LocalDependencies.start()
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import ora from "ora";
|
|
2
|
+
import {getPackageJson, getPackagePath, widgetPackages} from "../utils";
|
|
3
|
+
import fs from "fs";
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
const spinner = ora("Connecting");
|
|
7
|
+
|
|
8
|
+
export namespace LocalDependencies {
|
|
9
|
+
export async function start() {
|
|
10
|
+
spinner.start();
|
|
11
|
+
let json = getPackageJson();
|
|
12
|
+
let packageNames = Object.keys(widgetPackages);
|
|
13
|
+
let dependencies = json["dependencies"];
|
|
14
|
+
let devDependencies = json["devDependencies"];
|
|
15
|
+
await setWorkspaceVersion(dependencies, packageNames);
|
|
16
|
+
await setWorkspaceVersion(devDependencies, packageNames);
|
|
17
|
+
fs.writeFileSync(getPackagePath(), JSON.stringify(json, null, 2));
|
|
18
|
+
spinner.succeed("Using local versions(workspace:*)!");
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async function setWorkspaceVersion(dependencies: { [key: string]: string }, packageNames: string[]) {
|
|
22
|
+
let localPackages = Object.keys(dependencies);
|
|
23
|
+
for (let localPackage of localPackages) {
|
|
24
|
+
if (packageNames.indexOf(localPackage) > -1) {
|
|
25
|
+
dependencies[localPackage] = `workspace:*`;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
}
|
|
@@ -1,43 +1,40 @@
|
|
|
1
1
|
import packageJson from "package-json";
|
|
2
2
|
import ora from "ora";
|
|
3
|
-
import {
|
|
3
|
+
import {getPackageJson, getPackagePath, widgetPackages} from "../utils";
|
|
4
4
|
import fs from "fs";
|
|
5
5
|
|
|
6
|
-
const packages: { [key: string]: string } = {
|
|
7
|
-
"@widget-js/core": "", "@widget-js/vue3": "", "@widget-js/cli": "", "@widget-js/vite-plugin-widget": ""
|
|
8
|
-
};
|
|
9
6
|
const spinner = ora("Connecting");
|
|
10
7
|
|
|
11
|
-
export
|
|
8
|
+
export namespace RemoteDependencies {
|
|
12
9
|
|
|
13
|
-
async start() {
|
|
10
|
+
export async function start() {
|
|
14
11
|
spinner.start();
|
|
15
12
|
let json = getPackageJson();
|
|
16
|
-
let packageNames = Object.keys(
|
|
13
|
+
let packageNames = Object.keys(widgetPackages);
|
|
17
14
|
let dependencies = json["dependencies"];
|
|
18
15
|
let devDependencies = json["devDependencies"];
|
|
19
|
-
await
|
|
20
|
-
await
|
|
16
|
+
await upgradePackage(dependencies, packageNames);
|
|
17
|
+
await upgradePackage(devDependencies, packageNames);
|
|
21
18
|
fs.writeFileSync(getPackagePath(), JSON.stringify(json, null, 2));
|
|
22
|
-
spinner.succeed("
|
|
19
|
+
spinner.succeed("Using remote versions!");
|
|
23
20
|
}
|
|
24
21
|
|
|
25
22
|
|
|
26
|
-
|
|
23
|
+
async function upgradePackage(dependencies: { [key: string]: string }, packageNames: string[]) {
|
|
27
24
|
let localPackages = Object.keys(dependencies);
|
|
28
25
|
for (let localPackage of localPackages) {
|
|
29
26
|
if (packageNames.indexOf(localPackage) > -1) {
|
|
30
|
-
let packageVersion =
|
|
27
|
+
let packageVersion = widgetPackages[localPackage];
|
|
31
28
|
if (!packageVersion) {
|
|
32
|
-
packageVersion = await
|
|
33
|
-
|
|
29
|
+
packageVersion = await getRemoteVersion(localPackage);
|
|
30
|
+
widgetPackages[localPackage] = packageVersion;
|
|
34
31
|
}
|
|
35
32
|
dependencies[localPackage] = `^${packageVersion}`;
|
|
36
33
|
}
|
|
37
34
|
}
|
|
38
35
|
}
|
|
39
36
|
|
|
40
|
-
async getRemoteVersion(packageName: string): Promise<string> {
|
|
37
|
+
async function getRemoteVersion(packageName: string): Promise<string> {
|
|
41
38
|
spinner.info(`Fetching package version:${packageName}`);
|
|
42
39
|
const metadata = await packageJson(packageName);
|
|
43
40
|
let version = metadata["version"];
|
package/src/index.ts
CHANGED
|
@@ -1,55 +1,56 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import fs from "fs";
|
|
3
|
-
import path from "path";
|
|
4
|
-
import * as process from "process";
|
|
5
|
-
|
|
6
|
-
import {
|
|
7
|
-
import figlet from "figlet";
|
|
8
|
-
import gradient from "gradient-string";
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
program
|
|
19
|
-
|
|
20
|
-
.
|
|
21
|
-
.
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
.
|
|
30
|
-
.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
await
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
.
|
|
39
|
-
.
|
|
40
|
-
|
|
41
|
-
await build
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
.
|
|
48
|
-
.
|
|
49
|
-
.
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
await release
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
1
|
+
import {Option, program} from "commander";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import * as process from "process";
|
|
5
|
+
|
|
6
|
+
import {fileURLToPath} from "url";
|
|
7
|
+
import figlet from "figlet";
|
|
8
|
+
import gradient from "gradient-string";
|
|
9
|
+
|
|
10
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
11
|
+
const __dirname = path.dirname(__filename);
|
|
12
|
+
//
|
|
13
|
+
const packageJsonPath = path.join(__dirname, "../package.json");
|
|
14
|
+
let cliPackage = JSON.parse(fs.readFileSync(packageJsonPath).toString());
|
|
15
|
+
|
|
16
|
+
console.log(gradient.pastel.multiline(figlet.textSync("widget-cli", {horizontalLayout: "full"})));
|
|
17
|
+
program.version(`@widget-js/cli ${cliPackage.version}`).usage("<command> [options]");
|
|
18
|
+
program
|
|
19
|
+
.command("create")
|
|
20
|
+
.description("创建新的组件")
|
|
21
|
+
.action(async () => {
|
|
22
|
+
const createWidget = await import("./createWidget");
|
|
23
|
+
await createWidget.default();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
let dependenciesOption = new Option("-t, --type <type>").choices(["remote", "local"]);
|
|
27
|
+
|
|
28
|
+
program
|
|
29
|
+
.command("dependencies")
|
|
30
|
+
.description("将@widget-js依赖版本设置成远程或者本地")
|
|
31
|
+
.addOption(dependenciesOption)
|
|
32
|
+
.action(async (options) => {
|
|
33
|
+
let dependencies = await import("./dependencies/index");
|
|
34
|
+
await dependencies.default(options);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
program
|
|
38
|
+
.command("build")
|
|
39
|
+
.description("执行编译任务")
|
|
40
|
+
.action(async () => {
|
|
41
|
+
const build = await import("./build/build");
|
|
42
|
+
await build.build();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
let typeOption = new Option("-t, --type <type>").choices(["ftp", "oss"]);
|
|
46
|
+
program
|
|
47
|
+
.command("release")
|
|
48
|
+
.description("通过FTP/OSS发布文件,仅内部使用")
|
|
49
|
+
.addOption(typeOption)
|
|
50
|
+
.action(async (options, command) => {
|
|
51
|
+
// @ts-ignore
|
|
52
|
+
let release = await import("./release/release");
|
|
53
|
+
await release.default(options);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
program.parse(process.argv);
|
package/src/release/ftp.ts
CHANGED
|
@@ -1,116 +1,116 @@
|
|
|
1
|
-
import path from "path";
|
|
2
|
-
import fs from "fs";
|
|
3
|
-
import SSHConfig from "@widget-js/ssh-config";
|
|
4
|
-
import os from "os";
|
|
5
|
-
import Client from "ssh2-sftp-client";
|
|
6
|
-
import consola from "consola";
|
|
7
|
-
import inquirer from "inquirer";
|
|
8
|
-
import ora from "ora";
|
|
9
|
-
import * as process from "process";
|
|
10
|
-
import { getPackageVersion } from "../utils";
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
interface PasswordAnswer {
|
|
14
|
-
password: string
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
async function checkParentDir(ftpClient: Client, file: string, onMkdir: (dir: string) => void) {
|
|
18
|
-
let dir = path.dirname(file)
|
|
19
|
-
const dirExists = await ftpClient.exists(dir)
|
|
20
|
-
if (!dirExists) {
|
|
21
|
-
onMkdir(dir)
|
|
22
|
-
await ftpClient.mkdir(dir, true)
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function ftpUpload() {
|
|
27
|
-
// 读取
|
|
28
|
-
const releaseJsonFilePath = path.join(process.cwd(), 'release.json')
|
|
29
|
-
const packageVersion = getPackageVersion()
|
|
30
|
-
consola.info('Package Version:', packageVersion)
|
|
31
|
-
|
|
32
|
-
let releaseJson = fs.readFileSync(releaseJsonFilePath).toString().replaceAll('${version}', packageVersion);
|
|
33
|
-
const releaseConfig = JSON.parse(releaseJson) as ReleaseConfig
|
|
34
|
-
const sshConfigFile = path.resolve(os.homedir(), '.ssh/config')
|
|
35
|
-
consola.info('SSH Config File Path:', sshConfigFile)
|
|
36
|
-
const sshConfigs = SSHConfig.parse(fs.readFileSync(sshConfigFile).toString())
|
|
37
|
-
let sshConfig = sshConfigs.compute(releaseConfig.ftpConfig.host)
|
|
38
|
-
if (!sshConfig) {
|
|
39
|
-
consola.error(`SSH config ${releaseConfig.ftpConfig.host} not found`)
|
|
40
|
-
return
|
|
41
|
-
}
|
|
42
|
-
consola.info(sshConfig)
|
|
43
|
-
inquirer
|
|
44
|
-
.prompt<PasswordAnswer>([{type: 'password', name: 'password', mask: '*', message: 'Enter key pair password'}])
|
|
45
|
-
.then(async (answer: PasswordAnswer) => {
|
|
46
|
-
let ftpClient = new Client()
|
|
47
|
-
const port = sshConfig['Port']
|
|
48
|
-
const key = fs.readFileSync(path.resolve(os.homedir(), '.ssh/id_rsa'))
|
|
49
|
-
const spinner = ora('Connecting')
|
|
50
|
-
try {
|
|
51
|
-
spinner.start()
|
|
52
|
-
await ftpClient.connect({
|
|
53
|
-
host: sshConfig['HostName'] as string,
|
|
54
|
-
port: port ? parseInt(port as string) : 22,
|
|
55
|
-
username: sshConfig['User'] as string,
|
|
56
|
-
passphrase: answer.password,
|
|
57
|
-
privateKey: key,
|
|
58
|
-
})
|
|
59
|
-
releaseConfig.fileMap.sort((it1, it2) => (it1.order ?? 0) - (it2.order ?? 0))
|
|
60
|
-
// upload files
|
|
61
|
-
for (let item of releaseConfig.fileMap) {
|
|
62
|
-
if (typeof item.src == 'string') {
|
|
63
|
-
if (item.remoteCopy) {
|
|
64
|
-
await checkParentDir(ftpClient, item.dest, dir => {
|
|
65
|
-
spinner.warn(`Create Dir: ${dir}`)
|
|
66
|
-
})
|
|
67
|
-
let destExists = await ftpClient.exists(item.dest)
|
|
68
|
-
if (destExists) {
|
|
69
|
-
spinner.warn(`Delete exists file:${item.dest}`)
|
|
70
|
-
await ftpClient.delete(item.dest)
|
|
71
|
-
}
|
|
72
|
-
spinner.info(`Copying File: ${item.src} -> ${item.dest}`)
|
|
73
|
-
await ftpClient.rcopy(item.src, item.dest)
|
|
74
|
-
} else {
|
|
75
|
-
const localFile = path.resolve(process.cwd(), item.src as string)
|
|
76
|
-
if (!item.remoteCopy && !fs.existsSync(localFile)) {
|
|
77
|
-
spinner.warn(`Skip not exists file:${localFile}`)
|
|
78
|
-
continue
|
|
79
|
-
}
|
|
80
|
-
if (fs.lstatSync(localFile).isDirectory()) {
|
|
81
|
-
spinner.info(`Uploading Dir: ${localFile} -> ${item.dest}`)
|
|
82
|
-
await ftpClient.uploadDir(localFile, item.dest)
|
|
83
|
-
} else {
|
|
84
|
-
await checkParentDir(ftpClient, item.dest, dir => {
|
|
85
|
-
spinner.warn(`Create Dir: ${dir}`)
|
|
86
|
-
})
|
|
87
|
-
spinner.info(`Uploading File: ${localFile} -> ${item.dest}`)
|
|
88
|
-
await ftpClient.put(localFile, item.dest)
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
} else {
|
|
92
|
-
await ftpClient.put(Buffer.from(JSON.stringify(item.src), 'utf-8'), item.dest)
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
spinner.succeed('Files uploaded!')
|
|
96
|
-
await ftpClient.end()
|
|
97
|
-
} catch (e) {
|
|
98
|
-
spinner.fail(`Connection error:${e}`)
|
|
99
|
-
await ftpClient.end()
|
|
100
|
-
}
|
|
101
|
-
})
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
export interface ReleaseConfig {
|
|
105
|
-
fileMap: {
|
|
106
|
-
src: string | object
|
|
107
|
-
dest: string
|
|
108
|
-
remoteCopy: boolean
|
|
109
|
-
order: number
|
|
110
|
-
}[]
|
|
111
|
-
ftpConfig: FTPConfig
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export interface FTPConfig {
|
|
115
|
-
host: string
|
|
116
|
-
}
|
|
1
|
+
import path from "path";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import SSHConfig from "@widget-js/ssh-config";
|
|
4
|
+
import os from "os";
|
|
5
|
+
import Client from "ssh2-sftp-client";
|
|
6
|
+
import consola from "consola";
|
|
7
|
+
import inquirer from "inquirer";
|
|
8
|
+
import ora from "ora";
|
|
9
|
+
import * as process from "process";
|
|
10
|
+
import { getPackageVersion } from "../utils";
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
interface PasswordAnswer {
|
|
14
|
+
password: string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async function checkParentDir(ftpClient: Client, file: string, onMkdir: (dir: string) => void) {
|
|
18
|
+
let dir = path.dirname(file)
|
|
19
|
+
const dirExists = await ftpClient.exists(dir)
|
|
20
|
+
if (!dirExists) {
|
|
21
|
+
onMkdir(dir)
|
|
22
|
+
await ftpClient.mkdir(dir, true)
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function ftpUpload() {
|
|
27
|
+
// 读取
|
|
28
|
+
const releaseJsonFilePath = path.join(process.cwd(), 'release.json')
|
|
29
|
+
const packageVersion = getPackageVersion()
|
|
30
|
+
consola.info('Package Version:', packageVersion)
|
|
31
|
+
|
|
32
|
+
let releaseJson = fs.readFileSync(releaseJsonFilePath).toString().replaceAll('${version}', packageVersion);
|
|
33
|
+
const releaseConfig = JSON.parse(releaseJson) as ReleaseConfig
|
|
34
|
+
const sshConfigFile = path.resolve(os.homedir(), '.ssh/config')
|
|
35
|
+
consola.info('SSH Config File Path:', sshConfigFile)
|
|
36
|
+
const sshConfigs = SSHConfig.parse(fs.readFileSync(sshConfigFile).toString())
|
|
37
|
+
let sshConfig = sshConfigs.compute(releaseConfig.ftpConfig.host)
|
|
38
|
+
if (!sshConfig) {
|
|
39
|
+
consola.error(`SSH config ${releaseConfig.ftpConfig.host} not found`)
|
|
40
|
+
return
|
|
41
|
+
}
|
|
42
|
+
consola.info(sshConfig)
|
|
43
|
+
inquirer
|
|
44
|
+
.prompt<PasswordAnswer>([{type: 'password', name: 'password', mask: '*', message: 'Enter key pair password'}])
|
|
45
|
+
.then(async (answer: PasswordAnswer) => {
|
|
46
|
+
let ftpClient = new Client()
|
|
47
|
+
const port = sshConfig['Port']
|
|
48
|
+
const key = fs.readFileSync(path.resolve(os.homedir(), '.ssh/id_rsa'))
|
|
49
|
+
const spinner = ora('Connecting')
|
|
50
|
+
try {
|
|
51
|
+
spinner.start()
|
|
52
|
+
await ftpClient.connect({
|
|
53
|
+
host: sshConfig['HostName'] as string,
|
|
54
|
+
port: port ? parseInt(port as string) : 22,
|
|
55
|
+
username: sshConfig['User'] as string,
|
|
56
|
+
passphrase: answer.password,
|
|
57
|
+
privateKey: key,
|
|
58
|
+
})
|
|
59
|
+
releaseConfig.fileMap.sort((it1, it2) => (it1.order ?? 0) - (it2.order ?? 0))
|
|
60
|
+
// upload files
|
|
61
|
+
for (let item of releaseConfig.fileMap) {
|
|
62
|
+
if (typeof item.src == 'string') {
|
|
63
|
+
if (item.remoteCopy) {
|
|
64
|
+
await checkParentDir(ftpClient, item.dest, dir => {
|
|
65
|
+
spinner.warn(`Create Dir: ${dir}`)
|
|
66
|
+
})
|
|
67
|
+
let destExists = await ftpClient.exists(item.dest)
|
|
68
|
+
if (destExists) {
|
|
69
|
+
spinner.warn(`Delete exists file:${item.dest}`)
|
|
70
|
+
await ftpClient.delete(item.dest)
|
|
71
|
+
}
|
|
72
|
+
spinner.info(`Copying File: ${item.src} -> ${item.dest}`)
|
|
73
|
+
await ftpClient.rcopy(item.src, item.dest)
|
|
74
|
+
} else {
|
|
75
|
+
const localFile = path.resolve(process.cwd(), item.src as string)
|
|
76
|
+
if (!item.remoteCopy && !fs.existsSync(localFile)) {
|
|
77
|
+
spinner.warn(`Skip not exists file:${localFile}`)
|
|
78
|
+
continue
|
|
79
|
+
}
|
|
80
|
+
if (fs.lstatSync(localFile).isDirectory()) {
|
|
81
|
+
spinner.info(`Uploading Dir: ${localFile} -> ${item.dest}`)
|
|
82
|
+
await ftpClient.uploadDir(localFile, item.dest)
|
|
83
|
+
} else {
|
|
84
|
+
await checkParentDir(ftpClient, item.dest, dir => {
|
|
85
|
+
spinner.warn(`Create Dir: ${dir}`)
|
|
86
|
+
})
|
|
87
|
+
spinner.info(`Uploading File: ${localFile} -> ${item.dest}`)
|
|
88
|
+
await ftpClient.put(localFile, item.dest)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
} else {
|
|
92
|
+
await ftpClient.put(Buffer.from(JSON.stringify(item.src), 'utf-8'), item.dest)
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
spinner.succeed('Files uploaded!')
|
|
96
|
+
await ftpClient.end()
|
|
97
|
+
} catch (e) {
|
|
98
|
+
spinner.fail(`Connection error:${e}`)
|
|
99
|
+
await ftpClient.end()
|
|
100
|
+
}
|
|
101
|
+
})
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export interface ReleaseConfig {
|
|
105
|
+
fileMap: {
|
|
106
|
+
src: string | object
|
|
107
|
+
dest: string
|
|
108
|
+
remoteCopy: boolean
|
|
109
|
+
order: number
|
|
110
|
+
}[]
|
|
111
|
+
ftpConfig: FTPConfig
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export interface FTPConfig {
|
|
115
|
+
host: string
|
|
116
|
+
}
|