@typinghare/trick 2.0.0 → 2.1.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.
- package/LICENSE +22 -0
- package/README.md +175 -41
- package/dist/app.js +157 -65
- package/dist/color.d.ts +2 -0
- package/dist/color.js +7 -0
- package/dist/config.d.ts +45 -26
- package/dist/config.js +70 -29
- package/dist/console.d.ts +3 -0
- package/dist/console.js +9 -0
- package/dist/encrypt.d.ts +24 -32
- package/dist/encrypt.js +31 -38
- package/dist/error.d.ts +25 -6
- package/dist/error.js +36 -17
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/passphrase.d.ts +11 -3
- package/dist/passphrase.js +17 -11
- package/env.sh +1 -0
- package/package.json +12 -12
- package/src/app.ts +232 -155
- package/src/color.ts +9 -0
- package/src/config.ts +112 -69
- package/src/console.ts +11 -0
- package/src/encrypt.ts +104 -127
- package/src/error.ts +70 -57
- package/src/index.ts +3 -0
- package/src/passphrase.ts +21 -23
- package/test/resources/task_info.yml +4 -0
- package/test/resources/user_info.json +5 -0
- package/test/trick.config.json +16 -11
- package/test/resources/really.json +0 -4
- package/test/resources/task.yml +0 -3
package/src/config.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import fsExtra from 'fs-extra'
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
ReadConfigError,
|
|
4
|
+
TargetNotFoundError,
|
|
5
|
+
WriteConfigError,
|
|
6
|
+
RootDirectoryNotFoundError,
|
|
6
7
|
} from './error.js'
|
|
8
|
+
import { join, resolve } from 'path'
|
|
7
9
|
|
|
8
10
|
/**
|
|
9
11
|
* The name of the configuration file to look for in the root directory.
|
|
@@ -11,20 +13,26 @@ import {
|
|
|
11
13
|
export const CONFIG_FILE_NAME: string = 'trick.config.json'
|
|
12
14
|
|
|
13
15
|
/**
|
|
14
|
-
*
|
|
16
|
+
* A list of root markers.
|
|
17
|
+
*/
|
|
18
|
+
export const ROOT_MARKERS: string[] = ['.git', CONFIG_FILE_NAME]
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Represents Trick configuration type.
|
|
15
22
|
*
|
|
16
23
|
* @property targets Mapping from target names to target objects.
|
|
17
|
-
* @property
|
|
18
|
-
* @property
|
|
19
|
-
* @property
|
|
24
|
+
* @property trickRootDirectory The name of the Trick root directory under the project root.
|
|
25
|
+
* @property passphraseDirectory The path to the passphrase directory.
|
|
26
|
+
* @property defaultTargetNames A list of default target names. If no target name is specified
|
|
27
|
+
* when running Trick commands, these target names will be used.
|
|
20
28
|
* @property encryption Encryption configuration.
|
|
21
29
|
*/
|
|
22
30
|
export interface Config {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
31
|
+
targets: { [name: string]: Target }
|
|
32
|
+
trickRootDirectory: string
|
|
33
|
+
passphraseDirectory: string
|
|
34
|
+
defaultTargetNames: string[]
|
|
35
|
+
encryption: Encryption
|
|
28
36
|
}
|
|
29
37
|
|
|
30
38
|
/**
|
|
@@ -33,91 +41,129 @@ export interface Config {
|
|
|
33
41
|
* @property files A list of files to encrypt/decrypt.
|
|
34
42
|
*/
|
|
35
43
|
export interface Target {
|
|
36
|
-
|
|
44
|
+
files: string[]
|
|
37
45
|
}
|
|
38
46
|
|
|
39
47
|
/**
|
|
40
48
|
* Encryption configuration.
|
|
41
49
|
*
|
|
42
|
-
* @property
|
|
50
|
+
* @property iterationCount The number of iteration.
|
|
43
51
|
*/
|
|
44
52
|
export interface Encryption {
|
|
45
|
-
|
|
53
|
+
iterationCount: number
|
|
46
54
|
}
|
|
47
55
|
|
|
48
56
|
/**
|
|
49
57
|
* Default configuration.
|
|
50
58
|
*/
|
|
51
59
|
const DEFAULT_CONFIG: Config = {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
60
|
+
targets: {},
|
|
61
|
+
trickRootDirectory: '.trick',
|
|
62
|
+
passphraseDirectory: '~/.config/trick/passphrases',
|
|
63
|
+
defaultTargetNames: [],
|
|
64
|
+
encryption: {
|
|
65
|
+
iterationCount: 100_000,
|
|
66
|
+
},
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Recursively searches for the root directory of a project based on specified root markers.
|
|
71
|
+
*
|
|
72
|
+
* @param directory - The current directory to check. Defaults to the current working directory.
|
|
73
|
+
* @returns The path to the root directory.
|
|
74
|
+
* @throws {RootDirectoryNotFoundError} If the root directory cannot be found.
|
|
75
|
+
*/
|
|
76
|
+
export function getRootDirectory(directory: string | null = null): string {
|
|
77
|
+
if (!directory) {
|
|
78
|
+
return getRootDirectory(process.cwd())
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (directory === '/') {
|
|
82
|
+
throw new RootDirectoryNotFoundError()
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
for (const marker of ROOT_MARKERS) {
|
|
86
|
+
if (fsExtra.existsSync(join(directory, marker))) {
|
|
87
|
+
return directory
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return getRootDirectory(resolve(join(directory, '..')))
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Gets the full path to the configuration file based on the root directory.
|
|
96
|
+
*
|
|
97
|
+
* @return The full path to the configuration file.
|
|
98
|
+
* @throws {RootDirectoryNotFoundError} If the root directory cannot be found.
|
|
99
|
+
*/
|
|
100
|
+
export function getConfigFilePath(): string {
|
|
101
|
+
return resolve(getRootDirectory() + '/' + CONFIG_FILE_NAME)
|
|
59
102
|
}
|
|
60
103
|
|
|
61
104
|
/**
|
|
62
105
|
* Writes a configuration object to the configuration file.
|
|
63
106
|
*
|
|
64
107
|
* @param config The configuration to write.
|
|
65
|
-
* @
|
|
66
|
-
*
|
|
108
|
+
* @param createInRoot Whether to create the configuration file in the root directory if it
|
|
109
|
+
* doesn't exist. Defaults to false.
|
|
110
|
+
* @throws {WriteConfigError} If error occurs when writing to the configuration file.
|
|
67
111
|
*/
|
|
68
|
-
export
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
112
|
+
export function writeConfig(config: Config, createInRoot: boolean = true): void {
|
|
113
|
+
try {
|
|
114
|
+
if (createInRoot) {
|
|
115
|
+
const configFilePath = join(getRootDirectory(), CONFIG_FILE_NAME)
|
|
116
|
+
fsExtra.writeFileSync(configFilePath, JSON.stringify(config, null, 2))
|
|
117
|
+
} else {
|
|
118
|
+
// Always create in the current working directory
|
|
119
|
+
const configFilePath = join(process.cwd(), CONFIG_FILE_NAME)
|
|
120
|
+
fsExtra.writeFileSync(configFilePath, JSON.stringify(config, null, 2))
|
|
76
121
|
}
|
|
122
|
+
} catch (err) {
|
|
123
|
+
throw new WriteConfigError(err)
|
|
124
|
+
}
|
|
77
125
|
}
|
|
78
126
|
|
|
79
127
|
/**
|
|
80
128
|
* Retrieves the configuration object from the configuration file.
|
|
81
129
|
*
|
|
82
|
-
* @return The configuration object retrieved from the configuration object;
|
|
83
|
-
*
|
|
84
|
-
* @throws {ReadConfigError} If error occurs when reading the configuration
|
|
85
|
-
* file.
|
|
130
|
+
* @return The configuration object retrieved from the configuration object; null if the
|
|
131
|
+
* configuration file doesn't exist.
|
|
132
|
+
* @throws {ReadConfigError} If error occurs when reading the configuration file.
|
|
86
133
|
*/
|
|
87
|
-
export
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
134
|
+
export function readConfig(): Config | null {
|
|
135
|
+
const configFilePath = getConfigFilePath()
|
|
136
|
+
if (!fsExtra.existsSync(configFilePath)) {
|
|
137
|
+
return null
|
|
138
|
+
}
|
|
91
139
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
140
|
+
try {
|
|
141
|
+
return fsExtra.readJSONSync(configFilePath) as Config
|
|
142
|
+
} catch (err) {
|
|
143
|
+
throw new ReadConfigError(err)
|
|
144
|
+
}
|
|
97
145
|
}
|
|
98
146
|
|
|
99
147
|
/**
|
|
100
148
|
* Updates the configuration object.
|
|
101
149
|
*
|
|
102
|
-
* This function first retrieves the configuration object fromthe configuration
|
|
103
|
-
*
|
|
104
|
-
*
|
|
150
|
+
* This function first retrieves the configuration object fromthe configuration file. If the
|
|
151
|
+
* configuration file doesn't exist, the default configuration will be used instead.
|
|
152
|
+
*
|
|
153
|
+
* Then it calls the callback function by passing on the configuration object. If the callback
|
|
154
|
+
* function returns `true`, then the object will be written to the configuration file.
|
|
105
155
|
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
* the configuration file.
|
|
156
|
+
* @param callback The callback function taking the configuraition object retrieved from the
|
|
157
|
+
* configuration file.
|
|
109
158
|
*
|
|
110
|
-
* @param callback The callback function taking the configuraition object
|
|
111
|
-
* retrieved from the configuration file.
|
|
112
159
|
* @see DEFAULT_CONFIG
|
|
113
160
|
*/
|
|
114
|
-
export
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
}
|
|
161
|
+
export function updateConfig(
|
|
162
|
+
callback: (Config: Config) => boolean | void,
|
|
163
|
+
createInRoot: boolean = true
|
|
164
|
+
): void {
|
|
165
|
+
const config: Config = readConfig() || DEFAULT_CONFIG
|
|
166
|
+
Boolean(callback(config)) && writeConfig(config, createInRoot)
|
|
121
167
|
}
|
|
122
168
|
|
|
123
169
|
/**
|
|
@@ -128,14 +174,11 @@ export async function updateConfig(
|
|
|
128
174
|
* @return The target object associated with the given name.
|
|
129
175
|
* @throws {TargetNotFoundError} If the target object is not found.
|
|
130
176
|
*/
|
|
131
|
-
export function getTargetFromConfig(
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
if (!target) {
|
|
137
|
-
throw new TargetNotFoundError(targetName)
|
|
138
|
-
}
|
|
177
|
+
export function getTargetFromConfig(config: Config, targetName: string): Target {
|
|
178
|
+
const target = config.targets[targetName]
|
|
179
|
+
if (!target) {
|
|
180
|
+
throw new TargetNotFoundError(targetName)
|
|
181
|
+
}
|
|
139
182
|
|
|
140
|
-
|
|
183
|
+
return target
|
|
141
184
|
}
|
package/src/console.ts
ADDED
package/src/encrypt.ts
CHANGED
|
@@ -2,190 +2,167 @@ import { execa } from 'execa'
|
|
|
2
2
|
import * as path from 'node:path'
|
|
3
3
|
import fsExtra from 'fs-extra'
|
|
4
4
|
import { FailToDecryptFileError, FailToEncryptFileError } from './error.js'
|
|
5
|
+
import { success } from './console.js'
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Encrypts a file using OpenSSL with AES-256-CBC and PBKDF2 key derivation.
|
|
8
9
|
*
|
|
9
|
-
* This function checks whether the source file exists, constructs an OpenSSL
|
|
10
|
-
*
|
|
11
|
-
* encryption command.
|
|
10
|
+
* This function checks whether the source file exists, constructs an OpenSSL command, ensures the
|
|
11
|
+
* destination directory exists, and then executes the encryption command.
|
|
12
12
|
*
|
|
13
13
|
* @param srcFilePath The path to the source file that needs to be encrypted.
|
|
14
14
|
* @param destFilePath The path where the encrypted file will be saved.
|
|
15
15
|
* @param passphrase The passphrase used for encryption.
|
|
16
|
-
* @param
|
|
16
|
+
* @param iterationCount The number of iterations to use for PBKDF2.
|
|
17
17
|
* @returns Resolves when the file is successfully encrypted.
|
|
18
|
-
* @throws {FailToEncryptFileError} If the source file does not exist or if
|
|
19
|
-
*
|
|
20
|
-
* @throws {FailToDecryptFileError} If an unknown error occurs during
|
|
21
|
-
* encryption.
|
|
18
|
+
* @throws {FailToEncryptFileError} If the source file does not exist or if OpenSSL returns an error
|
|
19
|
+
* during encryption.
|
|
20
|
+
* @throws {FailToDecryptFileError} If an unknown error occurs during encryption.
|
|
22
21
|
*/
|
|
23
22
|
export async function encryptFile(
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
srcFilePath: string,
|
|
24
|
+
destFilePath: string,
|
|
25
|
+
passphrase: string,
|
|
26
|
+
iterationCount: number
|
|
28
27
|
): Promise<void> {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
if (!(await fsExtra.pathExists(srcFilePath))) {
|
|
29
|
+
throw new FailToEncryptFileError(srcFilePath)
|
|
30
|
+
}
|
|
32
31
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
32
|
+
const command: string = [
|
|
33
|
+
'openssl',
|
|
34
|
+
'enc',
|
|
35
|
+
'-aes-256-cbc',
|
|
36
|
+
'-salt',
|
|
37
|
+
'-pbkdf2',
|
|
38
|
+
'-iter',
|
|
39
|
+
Number(iterationCount),
|
|
40
|
+
'-in',
|
|
41
|
+
srcFilePath,
|
|
42
|
+
'-out',
|
|
43
|
+
destFilePath,
|
|
44
|
+
'-pass',
|
|
45
|
+
`'pass:${passphrase}'`,
|
|
46
|
+
].join(' ')
|
|
48
47
|
|
|
49
|
-
|
|
48
|
+
await fsExtra.ensureDir(path.dirname(destFilePath))
|
|
50
49
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
srcFilePath,
|
|
60
|
-
'Unknown error when encrypting the file.'
|
|
61
|
-
)
|
|
62
|
-
}
|
|
50
|
+
try {
|
|
51
|
+
await execa(`${command}`, { shell: true })
|
|
52
|
+
} catch (err) {
|
|
53
|
+
if (typeof err == 'object' && err && Object.hasOwn(err, 'stderr')) {
|
|
54
|
+
const error = err as { stderr: string }
|
|
55
|
+
throw new FailToEncryptFileError(srcFilePath, error.stderr)
|
|
56
|
+
} else {
|
|
57
|
+
throw new FailToDecryptFileError(srcFilePath, 'Unknown error when encrypting the file.')
|
|
63
58
|
}
|
|
59
|
+
}
|
|
64
60
|
}
|
|
65
61
|
|
|
66
62
|
/**
|
|
67
63
|
* Decrypts a file using OpenSSL with AES-256-CBC and PBKDF2 key derivation.
|
|
68
64
|
*
|
|
69
|
-
* This function checks whether the encrypted file exists, constructs an OpenSSL
|
|
70
|
-
*
|
|
71
|
-
* executes the decryption command.
|
|
65
|
+
* This function checks whether the encrypted file exists, constructs an OpenSSL decryption command,
|
|
66
|
+
* ensures the destination directory exists, and then executes the decryption command.
|
|
72
67
|
*
|
|
73
68
|
* @param srcFilePath The path where the decrypted file will be saved.
|
|
74
69
|
* @param destFilePath The path to the encrypted source file.
|
|
75
70
|
* @param passphrase The passphrase used for decryption.
|
|
76
|
-
* @param
|
|
71
|
+
* @param iterationCount The number of iterations used for PBKDF2.
|
|
77
72
|
* @returns Resolves when the file is successfully decrypted.
|
|
78
|
-
* @throws {FailToDecryptFileError} If the encrypted file does not exist or if
|
|
79
|
-
*
|
|
80
|
-
* @throws {FailToDecryptFileError} If an unknown error occurs during
|
|
81
|
-
* decryption.
|
|
73
|
+
* @throws {FailToDecryptFileError} If the encrypted file does not exist or if OpenSSL returns an
|
|
74
|
+
* error during decryption.
|
|
75
|
+
* @throws {FailToDecryptFileError} If an unknown error occurs during decryption.
|
|
82
76
|
*/
|
|
83
77
|
export async function decryptFile(
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
78
|
+
srcFilePath: string,
|
|
79
|
+
destFilePath: string,
|
|
80
|
+
passphrase: string,
|
|
81
|
+
iterationCount: number
|
|
88
82
|
): Promise<void> {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
83
|
+
if (!(await fsExtra.pathExists(destFilePath))) {
|
|
84
|
+
throw new FailToDecryptFileError(destFilePath)
|
|
85
|
+
}
|
|
92
86
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
87
|
+
const command: string = [
|
|
88
|
+
'openssl',
|
|
89
|
+
'enc',
|
|
90
|
+
'-d',
|
|
91
|
+
'-aes-256-cbc',
|
|
92
|
+
'-salt',
|
|
93
|
+
'-pbkdf2',
|
|
94
|
+
'-iter',
|
|
95
|
+
Number(iterationCount),
|
|
96
|
+
'-in',
|
|
97
|
+
destFilePath,
|
|
98
|
+
'-out',
|
|
99
|
+
srcFilePath,
|
|
100
|
+
'-pass',
|
|
101
|
+
`'pass:${passphrase}'`,
|
|
102
|
+
].join(' ')
|
|
109
103
|
|
|
110
|
-
|
|
104
|
+
await fsExtra.ensureDir(path.dirname(srcFilePath))
|
|
111
105
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
srcFilePath,
|
|
121
|
-
'Unknown error when decrypting the file.'
|
|
122
|
-
)
|
|
123
|
-
}
|
|
106
|
+
try {
|
|
107
|
+
await execa(`${command}`, { shell: true })
|
|
108
|
+
} catch (err) {
|
|
109
|
+
if (typeof err == 'object' && err && Object.hasOwn(err, 'stderr')) {
|
|
110
|
+
const error = err as { stderr: string }
|
|
111
|
+
throw new FailToDecryptFileError(srcFilePath, error.stderr)
|
|
112
|
+
} else {
|
|
113
|
+
throw new FailToDecryptFileError(srcFilePath, 'Unknown error when decrypting the file.')
|
|
124
114
|
}
|
|
115
|
+
}
|
|
125
116
|
}
|
|
126
117
|
|
|
127
118
|
/**
|
|
128
|
-
* Encrypts multiple files using OpenSSL with AES-256-CBC and PBKDF2 key
|
|
129
|
-
* derivation.
|
|
119
|
+
* Encrypts multiple files using OpenSSL with AES-256-CBC and PBKDF2 key derivation.
|
|
130
120
|
*
|
|
131
|
-
* For each source file path provided, this function constructs the destination
|
|
132
|
-
*
|
|
133
|
-
* operation.
|
|
121
|
+
* For each source file path provided, this function constructs the destination file path by
|
|
122
|
+
* appending `.enc`, then calls `encryptFile` and logs the operation.
|
|
134
123
|
*
|
|
135
124
|
* @param srcFilePaths An array of file paths to be encrypted.
|
|
136
125
|
* @param destDir The directory where the encrypted files will be saved.
|
|
137
126
|
* @param passphrase The passphrase used for encryption.
|
|
138
|
-
* @param
|
|
127
|
+
* @param iterationCount The number of iterations to use for PBKDF2.
|
|
139
128
|
* @returns Resolves when all files are successfully encrypted.
|
|
140
129
|
* @throws {FailToEncryptFileError} If any file fails to encrypt.
|
|
141
130
|
*/
|
|
142
131
|
export async function encryptFiles(
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
132
|
+
srcFilePaths: string[],
|
|
133
|
+
destDir: string,
|
|
134
|
+
passphrase: string,
|
|
135
|
+
iterationCount: number
|
|
147
136
|
): Promise<void> {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
passphrase,
|
|
154
|
-
iteration_count
|
|
155
|
-
)
|
|
156
|
-
console.log(`[ENCRYPTED] ${srcFilePath} -> ${destFilePath}`)
|
|
157
|
-
}
|
|
137
|
+
for (const srcFilePath of srcFilePaths) {
|
|
138
|
+
const destFilePath: string = path.join(destDir, srcFilePath + '.enc')
|
|
139
|
+
await encryptFile(srcFilePath, destFilePath, passphrase, iterationCount)
|
|
140
|
+
console.log(success(`Encrypted: ${srcFilePath} -> ${destFilePath}`))
|
|
141
|
+
}
|
|
158
142
|
}
|
|
159
143
|
|
|
160
144
|
/**
|
|
161
|
-
* Decrypts multiple files using OpenSSL with AES-256-CBC and PBKDF2 key
|
|
162
|
-
* derivation.
|
|
145
|
+
* Decrypts multiple files using OpenSSL with AES-256-CBC and PBKDF2 key derivation.
|
|
163
146
|
*
|
|
164
|
-
* For each source file path provided, this function assumes the corresponding
|
|
165
|
-
*
|
|
166
|
-
* operation.
|
|
147
|
+
* For each source file path provided, this function assumes the corresponding encrypted file has
|
|
148
|
+
* the `.enc` extension and calls `decryptFile`, logging the operation.
|
|
167
149
|
*
|
|
168
150
|
* @param srcFilePaths An array of original file paths that were encrypted.
|
|
169
151
|
* @param destDir The directory containing the encrypted files.
|
|
170
152
|
* @param passphrase The passphrase used for decryption.
|
|
171
|
-
* @param
|
|
153
|
+
* @param iterationCount The number of iterations used for PBKDF2.
|
|
172
154
|
* @returns Resolves when all files are successfully decrypted.
|
|
173
155
|
* @throws {FailToDecryptFileError} If any file fails to decrypt.
|
|
174
156
|
*/
|
|
175
157
|
export async function decryptFiles(
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
158
|
+
srcFilePaths: string[],
|
|
159
|
+
destDir: string,
|
|
160
|
+
passphrase: string,
|
|
161
|
+
iterationCount: number
|
|
180
162
|
): Promise<void> {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
passphrase,
|
|
187
|
-
iteration_count
|
|
188
|
-
)
|
|
189
|
-
console.log(`[DECRYPTED] ${destFilePath} -> ${srcFilePath}`)
|
|
190
|
-
}
|
|
163
|
+
for (const srcFilePath of srcFilePaths) {
|
|
164
|
+
const destFilePath: string = path.join(destDir, srcFilePath + '.enc')
|
|
165
|
+
await decryptFile(srcFilePath, destFilePath, passphrase, iterationCount)
|
|
166
|
+
console.log(success(`Decrypted: ${destFilePath} -> ${srcFilePath}`))
|
|
167
|
+
}
|
|
191
168
|
}
|