@mikeyt23/node-cli-utils 1.0.0 → 1.2.1

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 (4) hide show
  1. package/LICENSE +6 -6
  2. package/README.md +102 -102
  3. package/index.js +245 -166
  4. package/package.json +22 -20
package/LICENSE CHANGED
@@ -1,7 +1,7 @@
1
- Copyright 2021 Michael Thompson
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
-
5
- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
-
1
+ Copyright 2021 Michael Thompson
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
7
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md CHANGED
@@ -1,102 +1,102 @@
1
- # @mikeyt23/node-cli-utils
2
-
3
- Simple node cli utils to:
4
-
5
- - Wait for a node spawned process
6
- - Copy env template file to env file
7
- - Sync new env values from template to "real" env files
8
- - Manage all env values in root files that then get copied to other locations
9
-
10
- # Env Utility Function Notes
11
-
12
- A project can have multiple locations that requires the same env values. For example, you might have a database that needs to be used by a docker project, your main app and also a db migration project. Rather than having to remember where each of the .env files is, we want to use the root directory and overwrite subdirectory env files with the ones in the root. We also want to add new `.env.template` values to the root `.env` files and propagate them to subdirectories - all without having to know about anything about any of the .env files except the ones in the root of the project.
13
-
14
- # Examples
15
-
16
- An example syncEnvFiles gulp task function:
17
-
18
- ```JavaScript
19
- const projectDir = 'src/YourProjectDir/'
20
- const serverAppDir = `src/${projectDir}`
21
- const clientAppDir = `src/${projectDir}client-app/`
22
- const dockerDir = 'docker/'
23
-
24
- async function syncEnvFiles() {
25
- const rootServerEnv = './.env.server'
26
- const rootClientEnv = './.env.client'
27
-
28
- // Copy new values from root .env.[category].template to .env.[category]
29
- await copyNewEnvValues('./.env.server.template', rootServerEnv)
30
- await copyNewEnvValues('./.env.client.template', rootClientEnv)
31
-
32
- // Copy root .env.[category] to subdirectory .env files (overwrites target env file)
33
- // Server env to server app and docker directories
34
- await overwriteEnvFile(rootServerEnv, path.join(serverAppDir, '.env'))
35
- await overwriteEnvFile(rootServerEnv, path.join(dockerDir, '.env'))
36
- // Client env to client app directory
37
- await overwriteEnvFile(rootClientEnv, path.join(clientAppDir, '.env'))
38
- }
39
-
40
- exports.syncEnvFiles = syncEnvFiles
41
- ```
42
-
43
- > **WARNING**: Be sure to .gitignore `.env`, `.env.server` and `.env.client` files in the root **AND** the location they're being copied to. Only the template files with placeholder values should go in source control. For example, your .gitignore could have `**/.env*` and then `!.env.server.template` and `!.env.client.template`, etc.
44
-
45
- Example gulp task calling docker-compose:
46
-
47
- ```JavaScript
48
- const spawnOptions = {...defaultSpawnOptions}
49
-
50
- const dockerDirPath = 'docker/'
51
- const dockerDepsProjectName = 'your_project'
52
- const dockerDepsComposeName = 'docker-compose.deps.yml'
53
-
54
- const dockerSpawnOptions = {...spawnOptions, cwd: path.resolve(__dirname, dockerDirPath)}
55
-
56
- async function dockerDepsUpDetached() {
57
- return waitForProcess(spawn('docker-compose', ['--project-name', dockerDepsProjectName, '-f', dockerDepsComposeName, 'up', '-d'], dockerSpawnOptions))
58
- }
59
-
60
- exports.dockerDepsUpDetached = series(syncEnvFiles, dockerDepsUpDetached)
61
- ```
62
-
63
- Example gulp task using util method `throwIfDockerNotRunning`:
64
-
65
-
66
- ```JavaScript
67
- async function dockerDepsUp() {
68
- await throwIfDockerNotRunning()
69
- return waitForProcess(spawn('docker-compose', ['--project-name', dockerDepsProjectName, '-f', dockerDepsComposeName, 'up'], dockerSpawnOptions))
70
- }
71
-
72
- exports.dockerDepsUp = series(syncEnvFiles, dockerDepsUp)
73
- ```
74
-
75
- Example gulp task using util method `dockerContainerIsRunning`:
76
-
77
- ```JavaScript
78
- async function throwIfDockerDepsNotUp() {
79
- const postgresIsRunning = await dockerContainerIsRunning(`${dockerDepsProjectName}_postgresql`)
80
- if (!postgresIsRunning) {
81
- throw 'Docker dependencies are not running'
82
- }
83
- }
84
-
85
- async function runDbMigrator() {
86
- return waitForProcess(spawn('dotnet', [`publish/${DotnetNamespace}.DbMigrator.dll`], migratorSpawnOptions))
87
- }
88
-
89
- exports.dbMigrate = series(throwIfDockerDepsNotUp, parallel(syncEnvFiles, deleteMigratorPublishDir), publishMigrator, runDbMigrator)
90
- ```
91
-
92
- Example gulp task using util method `bashIntoRunningDockerContainer` and `argv` to pass in param `--imageName`:
93
-
94
- ```JavaScript
95
- async function dockerBashRunningContainer() {
96
- await throwIfDockerNotRunning()
97
- await bashIntoRunningDockerContainer(`${dockerDepsProjectName}_${argv['imageName']}`)
98
- }
99
-
100
- exports.dockerBash = dockerBashRunningContainer
101
- ```
102
-
1
+ # @mikeyt23/node-cli-utils
2
+
3
+ Simple node cli utils to:
4
+
5
+ - Wait for a node spawned process
6
+ - Copy env template file to env file
7
+ - Sync new env values from template to "real" env files
8
+ - Manage all env values in root files that then get copied to other locations
9
+
10
+ # Env Utility Function Notes
11
+
12
+ A project can have multiple locations that requires the same env values. For example, you might have a database that needs to be used by a docker project, your main app and also a db migration project. Rather than having to remember where each of the .env files is, we want to use the root directory and overwrite subdirectory env files with the ones in the root. We also want to add new `.env.template` values to the root `.env` files and propagate them to subdirectories - all without having to know about anything about any of the .env files except the ones in the root of the project.
13
+
14
+ # Examples
15
+
16
+ An example syncEnvFiles gulp task function:
17
+
18
+ ```JavaScript
19
+ const projectDir = 'src/YourProjectDir/'
20
+ const serverAppDir = `src/${projectDir}`
21
+ const clientAppDir = `src/${projectDir}client-app/`
22
+ const dockerDir = 'docker/'
23
+
24
+ async function syncEnvFiles() {
25
+ const rootServerEnv = './.env.server'
26
+ const rootClientEnv = './.env.client'
27
+
28
+ // Copy new values from root .env.[category].template to .env.[category]
29
+ await copyNewEnvValues('./.env.server.template', rootServerEnv)
30
+ await copyNewEnvValues('./.env.client.template', rootClientEnv)
31
+
32
+ // Copy root .env.[category] to subdirectory .env files (overwrites target env file)
33
+ // Server env to server app and docker directories
34
+ await overwriteEnvFile(rootServerEnv, path.join(serverAppDir, '.env'))
35
+ await overwriteEnvFile(rootServerEnv, path.join(dockerDir, '.env'))
36
+ // Client env to client app directory
37
+ await overwriteEnvFile(rootClientEnv, path.join(clientAppDir, '.env'))
38
+ }
39
+
40
+ exports.syncEnvFiles = syncEnvFiles
41
+ ```
42
+
43
+ > **WARNING**: Be sure to .gitignore `.env`, `.env.server` and `.env.client` files in the root **AND** the location they're being copied to. Only the template files with placeholder values should go in source control. For example, your .gitignore could have `**/.env*` and then `!.env.server.template` and `!.env.client.template`, etc.
44
+
45
+ Example gulp task calling docker-compose:
46
+
47
+ ```JavaScript
48
+ const spawnOptions = {...defaultSpawnOptions}
49
+
50
+ const dockerDirPath = 'docker/'
51
+ const dockerDepsProjectName = 'your_project'
52
+ const dockerDepsComposeName = 'docker-compose.deps.yml'
53
+
54
+ const dockerSpawnOptions = {...spawnOptions, cwd: path.resolve(__dirname, dockerDirPath)}
55
+
56
+ async function dockerDepsUpDetached() {
57
+ return waitForProcess(spawn('docker-compose', ['--project-name', dockerDepsProjectName, '-f', dockerDepsComposeName, 'up', '-d'], dockerSpawnOptions))
58
+ }
59
+
60
+ exports.dockerDepsUpDetached = series(syncEnvFiles, dockerDepsUpDetached)
61
+ ```
62
+
63
+ Example gulp task using util method `throwIfDockerNotRunning`:
64
+
65
+
66
+ ```JavaScript
67
+ async function dockerDepsUp() {
68
+ await throwIfDockerNotRunning()
69
+ return waitForProcess(spawn('docker-compose', ['--project-name', dockerDepsProjectName, '-f', dockerDepsComposeName, 'up'], dockerSpawnOptions))
70
+ }
71
+
72
+ exports.dockerDepsUp = series(syncEnvFiles, dockerDepsUp)
73
+ ```
74
+
75
+ Example gulp task using util method `dockerContainerIsRunning`:
76
+
77
+ ```JavaScript
78
+ async function throwIfDockerDepsNotUp() {
79
+ const postgresIsRunning = await dockerContainerIsRunning(`${dockerDepsProjectName}_postgresql`)
80
+ if (!postgresIsRunning) {
81
+ throw 'Docker dependencies are not running'
82
+ }
83
+ }
84
+
85
+ async function runDbMigrator() {
86
+ return waitForProcess(spawn('dotnet', [`publish/${DotnetNamespace}.DbMigrator.dll`], migratorSpawnOptions))
87
+ }
88
+
89
+ exports.dbMigrate = series(throwIfDockerDepsNotUp, parallel(syncEnvFiles, deleteMigratorPublishDir), publishMigrator, runDbMigrator)
90
+ ```
91
+
92
+ Example gulp task using util method `bashIntoRunningDockerContainer` and `argv` to pass in param `--imageName`:
93
+
94
+ ```JavaScript
95
+ async function dockerBashRunningContainer() {
96
+ await throwIfDockerNotRunning()
97
+ await bashIntoRunningDockerContainer(`${dockerDepsProjectName}_${argv['imageName']}`)
98
+ }
99
+
100
+ exports.dockerBash = dockerBashRunningContainer
101
+ ```
102
+
package/index.js CHANGED
@@ -1,166 +1,245 @@
1
- const fs = require('fs')
2
- const fsp = require('fs').promises
3
- const which = require('which')
4
- const {spawn, spawnSync} = require('child_process')
5
-
6
- const defaultSpawnOptions = {
7
- shell: true,
8
- stdio: ['ignore', 'inherit', 'inherit']
9
- }
10
- const spawnOptionsWithInput = {...defaultSpawnOptions, stdio: 'inherit'}
11
-
12
- function waitForProcess(childProcess) {
13
- return new Promise((resolve, reject) => {
14
- childProcess.once('exit', (returnCode) => {
15
- if (returnCode === 0) {
16
- resolve(returnCode)
17
- } else {
18
- reject(returnCode)
19
- }
20
- })
21
- childProcess.once('error', (err) => {
22
- reject(err)
23
- })
24
- })
25
- }
26
-
27
- async function copyNewEnvValues(fromPath, toPath) {
28
- await copyEnv(fromPath, toPath, false)
29
- }
30
-
31
- async function overwriteEnvFile(fromPath, toPath) {
32
- await copyEnv(fromPath, toPath)
33
- }
34
-
35
-
36
- async function throwIfDockerNotRunning() {
37
- if (!which.sync('docker')) {
38
- throw Error('docker command not found')
39
- }
40
-
41
- let childProcess = spawnSync('docker', ['info'], {encoding: 'utf8'})
42
- if (childProcess.error) {
43
- throw childProcess.error
44
- }
45
- if (!childProcess.stdout || childProcess.stdout.includes('ERROR: error during connect')) {
46
- throw Error('docker is not running')
47
- }
48
- }
49
-
50
- async function bashIntoRunningDockerContainer(containerNamePartial, entryPoint = 'bash') {
51
- await throwIfDockerNotRunning()
52
-
53
- let childProcess = spawnSync('docker', ['container', 'ls'], {encoding: 'utf8'})
54
- if (childProcess.error) {
55
- throw childProcess.error
56
- }
57
-
58
- let matchingLines = childProcess.stdout.split('\n').filter(line => line.includes(containerNamePartial))
59
-
60
- if (!matchingLines || matchingLines.length === 0) {
61
- throw Error('container is not running')
62
- }
63
-
64
- if (matchingLines.length > 1) {
65
- throw Error('more than one container matches the provided containerNamePartial ' + containerNamePartial)
66
- }
67
-
68
- let stringArray = matchingLines[0].split(/(\s+)/)
69
-
70
- let containerName = stringArray[stringArray.length - 1]
71
-
72
- console.log('full container name: ' + containerName)
73
-
74
- const args = ['exec', '-it', containerName, entryPoint]
75
- return waitForProcess(spawn('docker', args, spawnOptionsWithInput))
76
- }
77
-
78
- async function dockerContainerIsRunning(containerNamePartial) {
79
- await throwIfDockerNotRunning()
80
-
81
- let childProcess = spawnSync('docker', ['container', 'ls'], {encoding: 'utf8'})
82
- if (childProcess.error) {
83
- throw childProcess.error
84
- }
85
-
86
- let matchingLines = childProcess.stdout.split('\n').filter(l => l.includes(containerNamePartial))
87
-
88
- return !!matchingLines && matchingLines.length > 0
89
- }
90
-
91
- async function copyEnv(fromPath, toPath, overrideAll = true) {
92
- await ensureFile(fromPath, toPath)
93
-
94
- let templateDict = getEnvDictionary(fromPath)
95
- let envDict = getEnvDictionary(toPath)
96
-
97
- // Determine what keys are missing from .env that are in template
98
- let templateKeys = Object.keys(templateDict)
99
- let envKeys = Object.keys(envDict)
100
- let missingKeys = templateKeys.filter(k => !envKeys.includes(k))
101
-
102
- if (missingKeys.length > 0) {
103
- console.log(`Adding missing keys in ${toPath}: `, missingKeys)
104
- }
105
-
106
- // Merge missing values with existing
107
- let newEnvDict = {}
108
- for (const [key, value] of Object.entries(overrideAll ? templateDict : envDict)) {
109
- newEnvDict[key] = value
110
- }
111
- for (const key of missingKeys) {
112
- newEnvDict[key] = templateDict[key]
113
- }
114
-
115
- // Sort
116
- let newDictEntries = Object.entries(newEnvDict)
117
- let newSortedEntries = newDictEntries.sort((a, b) => {
118
- if (a < b) {
119
- return -1
120
- }
121
- if (a > b) {
122
- return 1
123
- }
124
- return 0
125
- })
126
-
127
- // Write to .env file
128
- let newEnvFileContent = ''
129
- for (let kvp of newSortedEntries) {
130
- newEnvFileContent += `${kvp[0]}=${kvp[1]}\n`
131
- }
132
- await fsp.writeFile(toPath, newEnvFileContent)
133
- }
134
-
135
- function getEnvDictionary(filePath) {
136
- let dict = {}
137
- fs.readFileSync(filePath).toString().split('\n').forEach(function (line) {
138
- if (line && line.indexOf('=') !== -1) {
139
- line = line.replace('\r', '').trim()
140
- let parts = line.split('=')
141
- dict[parts[0].trim()] = parts[1].trim()
142
- }
143
- })
144
- return dict
145
- }
146
-
147
- async function ensureFile(fromPath, toPath) {
148
- if (!fs.existsSync(toPath)) {
149
- console.log('Creating new file ' + toPath)
150
- await fsp.copyFile(fromPath, toPath)
151
- }
152
- }
153
-
154
- exports.defaultSpawnOptions = {
155
- shell: true,
156
- cwd: __dirname,
157
- stdio: ['ignore', 'inherit', 'inherit']
158
- }
159
-
160
- exports.defaultSpawnOptions = defaultSpawnOptions
161
- exports.waitForProcess = waitForProcess
162
- exports.copyNewEnvValues = copyNewEnvValues
163
- exports.overwriteEnvFile = overwriteEnvFile
164
- exports.throwIfDockerNotRunning = throwIfDockerNotRunning
165
- exports.bashIntoRunningDockerContainer = bashIntoRunningDockerContainer
166
- exports.dockerContainerIsRunning = dockerContainerIsRunning
1
+ const fs = require('fs')
2
+ const fse = require('fs-extra')
3
+ const fsp = require('fs').promises
4
+ const which = require('which')
5
+ const { spawn, spawnSync } = require('child_process')
6
+ const path = require('path')
7
+ const tar = require('tar')
8
+
9
+ const defaultSpawnOptions = {
10
+ shell: true,
11
+ stdio: ['ignore', 'inherit', 'inherit']
12
+ }
13
+ const spawnOptionsWithInput = { ...defaultSpawnOptions, stdio: 'inherit' }
14
+
15
+ function waitForProcess(childProcess) {
16
+ return new Promise((resolve, reject) => {
17
+ childProcess.once('exit', (returnCode) => {
18
+ if (returnCode === 0) {
19
+ resolve(returnCode)
20
+ } else {
21
+ reject(returnCode)
22
+ }
23
+ })
24
+ childProcess.once('error', (err) => {
25
+ reject(err)
26
+ })
27
+ })
28
+ }
29
+
30
+ async function copyNewEnvValues(fromPath, toPath) {
31
+ await copyEnv(fromPath, toPath, false)
32
+ }
33
+
34
+ async function overwriteEnvFile(fromPath, toPath) {
35
+ await copyEnv(fromPath, toPath)
36
+ }
37
+
38
+
39
+ async function throwIfDockerNotRunning() {
40
+ if (!which.sync('docker')) {
41
+ throw Error('docker command not found')
42
+ }
43
+
44
+ let childProcess = spawnSync('docker', ['info'], { encoding: 'utf8' })
45
+ if (childProcess.error) {
46
+ throw childProcess.error
47
+ }
48
+ if (!childProcess.stdout || childProcess.stdout.includes('ERROR: error during connect')) {
49
+ throw Error('docker is not running')
50
+ }
51
+ }
52
+
53
+ async function bashIntoRunningDockerContainer(containerNamePartial, entryPoint = 'bash') {
54
+ await throwIfDockerNotRunning()
55
+
56
+ let childProcess = spawnSync('docker', ['container', 'ls'], { encoding: 'utf8' })
57
+ if (childProcess.error) {
58
+ throw childProcess.error
59
+ }
60
+
61
+ let matchingLines = childProcess.stdout.split('\n').filter(line => line.includes(containerNamePartial))
62
+
63
+ if (!matchingLines || matchingLines.length === 0) {
64
+ throw Error('container is not running')
65
+ }
66
+
67
+ if (matchingLines.length > 1) {
68
+ throw Error('more than one container matches the provided containerNamePartial ' + containerNamePartial)
69
+ }
70
+
71
+ let stringArray = matchingLines[0].split(/(\s+)/)
72
+
73
+ let containerName = stringArray[stringArray.length - 1]
74
+
75
+ console.log('full container name: ' + containerName)
76
+
77
+ const args = ['exec', '-it', containerName, entryPoint]
78
+ return waitForProcess(spawn('docker', args, spawnOptionsWithInput))
79
+ }
80
+
81
+ async function dockerContainerIsRunning(containerNamePartial) {
82
+ await throwIfDockerNotRunning()
83
+
84
+ let childProcess = spawnSync('docker', ['container', 'ls'], { encoding: 'utf8' })
85
+ if (childProcess.error) {
86
+ throw childProcess.error
87
+ }
88
+
89
+ let matchingLines = childProcess.stdout.split('\n').filter(l => l.includes(containerNamePartial))
90
+
91
+ return !!matchingLines && matchingLines.length > 0
92
+ }
93
+
94
+ async function copyEnv(fromPath, toPath, overrideAll = true) {
95
+ await ensureFile(fromPath, toPath)
96
+
97
+ let templateDict = getEnvDictionary(fromPath)
98
+ let envDict = getEnvDictionary(toPath)
99
+
100
+ // Determine what keys are missing from .env that are in template
101
+ let templateKeys = Object.keys(templateDict)
102
+ let envKeys = Object.keys(envDict)
103
+ let missingKeys = templateKeys.filter(k => !envKeys.includes(k))
104
+
105
+ if (missingKeys.length > 0) {
106
+ console.log(`Adding missing keys in ${toPath}: `, missingKeys)
107
+ }
108
+
109
+ // Merge missing values with existing
110
+ let newEnvDict = {}
111
+ for (const [key, value] of Object.entries(overrideAll ? templateDict : envDict)) {
112
+ newEnvDict[key] = value
113
+ }
114
+ for (const key of missingKeys) {
115
+ newEnvDict[key] = templateDict[key]
116
+ }
117
+
118
+ // Sort
119
+ let newDictEntries = Object.entries(newEnvDict)
120
+ let newSortedEntries = newDictEntries.sort((a, b) => {
121
+ if (a < b) {
122
+ return -1
123
+ }
124
+ if (a > b) {
125
+ return 1
126
+ }
127
+ return 0
128
+ })
129
+
130
+ // Write to .env file
131
+ let newEnvFileContent = ''
132
+ for (let kvp of newSortedEntries) {
133
+ newEnvFileContent += `${kvp[0]}=${kvp[1]}\n`
134
+ }
135
+ await fsp.writeFile(toPath, newEnvFileContent)
136
+ }
137
+
138
+ function getEnvDictionary(filePath) {
139
+ let dict = {}
140
+ fs.readFileSync(filePath).toString().split('\n').forEach(function (line) {
141
+ if (line && line.indexOf('=') !== -1) {
142
+ line = line.replace('\r', '').trim()
143
+ let parts = line.split('=')
144
+ dict[parts[0].trim()] = parts[1].trim()
145
+ }
146
+ })
147
+ return dict
148
+ }
149
+
150
+ async function ensureFile(fromPath, toPath) {
151
+ if (!fs.existsSync(toPath)) {
152
+ console.log('Creating new file ' + toPath)
153
+ await fsp.copyFile(fromPath, toPath)
154
+ }
155
+ }
156
+
157
+ exports.defaultSpawnOptions = {
158
+ shell: true,
159
+ cwd: __dirname,
160
+ stdio: ['ignore', 'inherit', 'inherit']
161
+ }
162
+
163
+ async function createTarball(directoryToTarball, outputDirectory, tarballName) {
164
+ if (!directoryToTarball || directoryToTarball.length === 0) {
165
+ throw new Error('directoryToTarball is required')
166
+ }
167
+ if (!outputDirectory || outputDirectory.length === 0) {
168
+ throw new Error('outputDirectory is required')
169
+ }
170
+ if (!tarballName || tarballName.length === 0) {
171
+ throw new Error('tarballName is required')
172
+ }
173
+
174
+ const tarballPath = path.join(outputDirectory, tarballName)
175
+
176
+ console.log('directory to create tarball from: ' + directoryToTarball)
177
+ console.log('output will be: ' + tarballPath)
178
+
179
+ if (!fs.existsSync(directoryToTarball)) {
180
+ throw new Error('error: dirToTarball directory does not exist')
181
+ }
182
+
183
+ if (!fs.existsSync(outputDirectory)) {
184
+ fs.mkdirSync(outputDirectory)
185
+ } else {
186
+ if (fs.existsSync(tarballPath)) {
187
+ fs.unlinkSync(tarballPath)
188
+ }
189
+ }
190
+
191
+ await tar.c({ gzip: true, file: tarballPath }, [directoryToTarball])
192
+ }
193
+
194
+ async function dockerCompose(command, projectName, dockerRelativeDirectory, detached = false) {
195
+ if (!projectName || projectName.length === 0) {
196
+ throw new Error('projectName is required')
197
+ }
198
+
199
+ const dockerRelativeDir = dockerRelativeDirectory || 'docker'
200
+ const dockerWorkingDir = path.join(process.cwd(), dockerRelativeDir)
201
+
202
+ if (!fs.existsSync(dockerWorkingDir)) {
203
+ throw new Error('Docker directory does not exist: ' + dockerWorkingDir)
204
+ }
205
+
206
+ await throwIfDockerNotRunning()
207
+
208
+ const dockerSpawnOptions = { ...defaultSpawnOptions, cwd: dockerWorkingDir }
209
+
210
+ let args = ['--project-name', projectName, command]
211
+ if (detached) {
212
+ args.push('-d')
213
+ }
214
+
215
+ return waitForProcess(spawn('docker-compose', args, dockerSpawnOptions))
216
+ }
217
+
218
+ async function dockerDepsUp(projectName, dockerRelativeDirectory) {
219
+ return dockerCompose('up', projectName, dockerRelativeDirectory)
220
+ }
221
+
222
+ async function dockerDepsUpDetached(projectName, dockerRelativeDirectory) {
223
+ return dockerCompose('up', projectName, dockerRelativeDirectory, true)
224
+ }
225
+
226
+ async function dockerDepsDown(projectName, dockerRelativeDirectory) {
227
+ return dockerCompose('down', projectName, dockerRelativeDirectory)
228
+ }
229
+
230
+ async function dockerDepsStop(projectName, dockerRelativeDirectory) {
231
+ return dockerCompose('stop', projectName, dockerRelativeDirectory)
232
+ }
233
+
234
+ exports.defaultSpawnOptions = defaultSpawnOptions
235
+ exports.waitForProcess = waitForProcess
236
+ exports.copyNewEnvValues = copyNewEnvValues
237
+ exports.overwriteEnvFile = overwriteEnvFile
238
+ exports.throwIfDockerNotRunning = throwIfDockerNotRunning
239
+ exports.bashIntoRunningDockerContainer = bashIntoRunningDockerContainer
240
+ exports.dockerContainerIsRunning = dockerContainerIsRunning
241
+ exports.createTarball = createTarball
242
+ exports.dockerDepsUp = dockerDepsUp
243
+ exports.dockerDepsUpDetached = dockerDepsUpDetached
244
+ exports.dockerDepsDown = dockerDepsDown
245
+ exports.dockerDepsStop = dockerDepsStop
package/package.json CHANGED
@@ -1,20 +1,22 @@
1
- {
2
- "name": "@mikeyt23/node-cli-utils",
3
- "version": "1.0.0",
4
- "description": "Some node cli utility functions",
5
- "author": "Mike Thompson",
6
- "license": "MIT",
7
- "private": false,
8
- "files": [
9
- "index.js"
10
- ],
11
- "homepage": "https://github.com/mikey-t/node-cli-utils",
12
- "repository": {
13
- "type": "git",
14
- "url": "https://github.com/mikey-t/node-cli-utils.git"
15
- },
16
- "main": "index.js",
17
- "dependencies": {
18
- "which": "^2.0.2"
19
- }
20
- }
1
+ {
2
+ "name": "@mikeyt23/node-cli-utils",
3
+ "version": "1.2.1",
4
+ "description": "Some node cli utility functions",
5
+ "author": "Mike Thompson",
6
+ "license": "MIT",
7
+ "private": false,
8
+ "files": [
9
+ "index.js"
10
+ ],
11
+ "homepage": "https://github.com/mikey-t/node-cli-utils",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "https://github.com/mikey-t/node-cli-utils.git"
15
+ },
16
+ "main": "index.js",
17
+ "dependencies": {
18
+ "fs-extra": "^10.0.0",
19
+ "tar": "^6.1.11",
20
+ "which": "^2.0.2"
21
+ }
22
+ }