-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathupdate.command.ts
executable file
·157 lines (136 loc) · 5.02 KB
/
update.command.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/* eslint-disable no-useless-escape */
import { Command, CommandRunner, Option } from 'nest-commander'
import { existsSync } from 'node:fs'
import { env } from 'node:process'
import ora from 'ora'
import { execPromise } from '@common/utils'
import { CheckUpdateService } from '@services/check-update.service'
import { InjectLogger, LoggerService } from '@services/logger'
import {
DOWNLOAD_FILE_PATH,
DOWNLOAD_SCRIPT_CUSTOM,
DOWNLOAD_SCRIPT_LATEST,
INIT_SCRIPT,
MIGRATE_SCRIPT,
UNZIP_SCRIPT,
} from './config/update-script.config'
import type { IUpdateCommandOptions } from './models/update-command.options'
@Command({
name: 'update',
description: 'Update the CLI to the latest version',
options: { isDefault: false },
})
export class UpdateCommand extends CommandRunner {
constructor(
@InjectLogger(UpdateCommand.name) private readonly logger: LoggerService,
private readonly checkUpdateService: CheckUpdateService,
) {
super()
}
async run(inputs: string[], options: IUpdateCommandOptions): Promise<void> {
const { target: version, mute } = options
if (mute) {
await this.checkUpdateService.checkForUpdates()
return
}
const spinner = ora({
text: 'Starting update...',
hideCursor: false,
discardStdin: false,
})
spinner.start()
try {
let downloadScript: string
switch (version) {
case 'latest': {
downloadScript = DOWNLOAD_SCRIPT_LATEST
break
}
default: {
downloadScript = DOWNLOAD_SCRIPT_CUSTOM(version)
break
}
}
if (version !== 'latest') {
const isVerified: boolean = await this.verifyCustomVersion(version)
if (!isVerified) {
spinner.fail('Failed to update')
this.logger.warn('No version found!')
return
}
}
const downloadMsg = 'Downloading new Version...'
this.logger.debug(downloadMsg)
spinner.text = downloadMsg
await execPromise(downloadScript)
const unzipMsg = 'Unzipping new Version...'
this.logger.debug(unzipMsg)
spinner.text = unzipMsg
const { stdout: fileName } = await execPromise(UNZIP_SCRIPT)
const downloadPath = DOWNLOAD_FILE_PATH(fileName)
const isExists: boolean = existsSync(downloadPath)
if (!isExists) {
this.logger.error(`Error while trying to migrate to the new version.\nTry again later.`)
spinner.fail('Failed to update')
return
}
const migrateMsg = 'Migrating to new Version...'
spinner.text = migrateMsg
this.logger.debug(migrateMsg)
await execPromise(MIGRATE_SCRIPT(fileName))
const applyMsg = 'Apply changes...'
spinner.text = applyMsg
this.logger.debug(applyMsg)
this.logger.log('\nMight need to enter your password to apply changes.')
await execPromise(INIT_SCRIPT, { shell: env.SHELL })
const successMsg = 'Updated successfully!'
this.logger.debug(successMsg)
spinner.succeed(successMsg)
} catch (error) {
this.logger.error(`Error UpdateCommand, Error: ${error.stack}`)
spinner.fail('Failed to update')
}
}
private async verifyCustomVersion(version: string): Promise<boolean> {
try {
const releases = await this.checkUpdateService.getGithubReleases()
const targetVersion = releases.find((release) => {
const { name } = release
const isTargetVersion: boolean = name === version
return isTargetVersion
})
if (!targetVersion) {
this.logger.warn(`No version found!`)
return false
}
return true
} catch (error) {
this.logger.error(`Error verifyCustomVersion, error: ${error.stack}`)
return false
}
}
@Option({
flags: '-t, --target <target>',
defaultValue: 'latest',
description: 'Select update version',
})
private getVersion(version: string): string {
if (version === 'latest') {
return 'latest'
}
const parsedVersion = version.match(/v?(\d+\.\d+\.\d+)(\-beta\.\d+)?/)
const [, target, suffixBeta] = parsedVersion ?? []
if (!target) {
throw new Error(`Invalid version: ${version}`)
}
return `v${target}${suffixBeta ?? ''}`
}
@Option({
flags: '-m, --mute',
defaultValue: false,
description: 'Daemon check for update notification. When specified is true.',
})
private checkForUpdateMute(mute: string): boolean {
return true
}
}