@leverege/build-tools 1.8.4

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 (58) hide show
  1. package/.publishrc +15 -0
  2. package/CHANGELOG.md +30 -0
  3. package/LICENSE.md +3 -0
  4. package/README.md +32 -0
  5. package/lib/server/auditate/help.js +119 -0
  6. package/lib/server/auditate/index.js +23 -0
  7. package/lib/server/auditate/report.js +61 -0
  8. package/lib/server/circleate +549 -0
  9. package/lib/server/decrypt-secrets +91 -0
  10. package/lib/server/dnsify/CloudflareAPI.js +103 -0
  11. package/lib/server/dnsify/accounts.json.enc +0 -0
  12. package/lib/server/dnsify/index.js +92 -0
  13. package/lib/server/dockreate +338 -0
  14. package/lib/server/encrypt-secrets +31 -0
  15. package/lib/server/getfbcfg +23 -0
  16. package/lib/server/getjson +48 -0
  17. package/lib/server/helmdn +103 -0
  18. package/lib/server/helmify +289 -0
  19. package/lib/server/helmup +87 -0
  20. package/lib/server/overwhelm +303 -0
  21. package/lib/server/packleate/Packleator.js +269 -0
  22. package/lib/server/packleate/index.js +98 -0
  23. package/lib/server/packleate/logo-ansi.js +17 -0
  24. package/lib/server/pkgck +136 -0
  25. package/lib/server/pkglint/index.js +19 -0
  26. package/lib/server/test.json +4 -0
  27. package/lib/web/auditate/help.js +158 -0
  28. package/lib/web/auditate/index.js +27 -0
  29. package/lib/web/auditate/report.js +91 -0
  30. package/lib/web/dnsify/CloudflareAPI.js +250 -0
  31. package/lib/web/dnsify/index.js +147 -0
  32. package/lib/web/packleate/Packleator.js +645 -0
  33. package/lib/web/packleate/index.js +157 -0
  34. package/lib/web/packleate/logo-ansi.js +3 -0
  35. package/lib/web/pkglint/index.js +19 -0
  36. package/package.json +74 -0
  37. package/src/auditate/help.js +83 -0
  38. package/src/auditate/index.js +25 -0
  39. package/src/auditate/report.js +54 -0
  40. package/src/circleate +549 -0
  41. package/src/decrypt-secrets +91 -0
  42. package/src/dnsify/CloudflareAPI.js +99 -0
  43. package/src/dnsify/accounts.json.enc +0 -0
  44. package/src/dnsify/index.js +82 -0
  45. package/src/dockreate +338 -0
  46. package/src/encrypt-secrets +31 -0
  47. package/src/getfbcfg +23 -0
  48. package/src/getjson +48 -0
  49. package/src/helmdn +103 -0
  50. package/src/helmify +289 -0
  51. package/src/helmup +87 -0
  52. package/src/overwhelm +303 -0
  53. package/src/packleate/Packleator.js +271 -0
  54. package/src/packleate/index.js +86 -0
  55. package/src/packleate/logo-ansi.js +16 -0
  56. package/src/pkgck +136 -0
  57. package/src/pkglint/index.js +21 -0
  58. package/src/test.json +4 -0
@@ -0,0 +1,99 @@
1
+ const ora = require( 'ora' )
2
+ const fs = require( 'fs' )
3
+ const path = require( 'path' )
4
+ const { promisify } = require( 'util' )
5
+
6
+ class CloudflareAPI {
7
+ constructor( options ) {
8
+ const { args } = options
9
+ const { url, proxy, ipaddress, account } = args
10
+
11
+ this.url = url
12
+ this.proxy = proxy
13
+ this.ipaddress = ipaddress
14
+ this.spinner = ora( { text : 'Creating DNS record...', spinner : 'monkey' } )
15
+ this.account = account
16
+ }
17
+
18
+ async decrypt(
19
+ projectId = 'leverege-docker-images',
20
+ keyRingId = 'build-tools',
21
+ cryptoKeyId = 'circle-ci',
22
+ ciphertextFileName = './accounts.json.enc',
23
+ plaintextFileName = './accounts.json'
24
+ ) {
25
+
26
+ // Import the library and create a client
27
+ const kms = require( '@google-cloud/kms' )
28
+ const client = new kms.KeyManagementServiceClient()
29
+
30
+ // The location of the crypto key's key ring, e.g. "global"
31
+ const locationId = 'us-east4'
32
+
33
+ // Reads the file to be decrypted
34
+ const readFile = promisify( fs.readFile );
35
+ const contentsBuffer = await readFile( path.resolve( __dirname, ciphertextFileName ) )
36
+ const name = client.cryptoKeyPath(
37
+ projectId,
38
+ locationId,
39
+ keyRingId,
40
+ cryptoKeyId
41
+ );
42
+ const ciphertext = contentsBuffer.toString( 'base64' )
43
+
44
+ // Decrypts the file using the specified crypto key
45
+ const [ result ] = await client.decrypt( { name, ciphertext } )
46
+
47
+ // Writes the decrypted file to disk
48
+ const writeFile = promisify( fs.writeFile )
49
+ await writeFile( path.resolve( __dirname, plaintextFileName ), Buffer.from( result.plaintext, 'base64' ) )
50
+ }
51
+
52
+ setAccountValues() {
53
+ const accountJson = require( path.resolve( __dirname, './accounts.json' ) )
54
+ const accountInfo = accountJson[this.account]
55
+ const { email, key, zone } = accountInfo
56
+
57
+ this.cf = require( 'cloudflare' )( {
58
+ email,
59
+ key
60
+ } )
61
+ this.zone = zone
62
+ }
63
+
64
+ async deleteSecrets() {
65
+ const deleteFile = promisify( fs.unlink )
66
+ await deleteFile( path.resolve( __dirname, './accounts.json' ) )
67
+ }
68
+
69
+ async createDNSRecord() {
70
+ try {
71
+ this.spinner.start()
72
+
73
+ this.spinner.text = 'Decrypting Cloudflare secrets...'
74
+ await this.decrypt()
75
+
76
+ this.spinner.text = 'Initializing Cloudflare API...'
77
+ this.setAccountValues()
78
+
79
+ this.spinner.text = 'Adding A name record...'
80
+ await this.cf.dnsRecords.add( this.zone,
81
+ { type : 'A',
82
+ name : this.url,
83
+ content : this.ipaddress,
84
+ proxied : this.proxy
85
+ } )
86
+
87
+ this.spinner.text = 'Removing secrets...'
88
+ await this.deleteSecrets()
89
+
90
+ this.spinner.stop()
91
+ } catch ( ex ) {
92
+ this.spinner.stop()
93
+ console.log( ex )
94
+ throw ex
95
+ }
96
+ }
97
+ }
98
+
99
+ module.exports = CloudflareAPI
Binary file
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env node
2
+ const commandLineArgs = require( 'command-line-args' )
3
+ const commandLineUsage = require( 'command-line-usage' )
4
+ const Cloudflare = require( './CloudflareAPI' )
5
+
6
+ const defaultConfig = {
7
+ account : 'leverege',
8
+ proxy : true
9
+ }
10
+
11
+ const sections = [
12
+ {
13
+ content : 'Wraps Cloudflare to modify DNS configs for new UI/Servers'
14
+ },
15
+ {
16
+ header : 'Options',
17
+ optionList : [
18
+ {
19
+ name : 'account',
20
+ alias : 'a',
21
+ description : 'Cloudflare account to use'
22
+ },
23
+ {
24
+ name : 'ipaddress',
25
+ alias : 'i',
26
+ description : 'IP address to point DNS account to (e.g. 35.178.29.10)'
27
+ },
28
+ {
29
+ name : 'url',
30
+ alias : 'u',
31
+ description : 'URL name (e.g. myserver)'
32
+ },
33
+ {
34
+ name : 'proxy',
35
+ alias : 'p',
36
+ description : 'Turn on Cloudflare proxy (optional)'
37
+ },
38
+ {
39
+ name : 'help',
40
+ description : 'Print this usage guide.'
41
+ }
42
+ ]
43
+ }
44
+ ]
45
+
46
+ const usage = commandLineUsage( sections )
47
+
48
+ const optionDefinitions = [
49
+ { name : 'account', alias : 'a', type : String, defaultValue : defaultConfig.account },
50
+ { name : 'ipaddress', alias : 'i', type : String },
51
+ { name : 'url', alias : 'u', type : String },
52
+ { name : 'proxy', alias : 'p', type : Boolean, defaultValue : defaultConfig.proxy },
53
+ { name : 'help', alias : 'h', type : Boolean }
54
+ ]
55
+
56
+ const args = commandLineArgs( optionDefinitions )
57
+
58
+ async function main() {
59
+ if ( args.help ) {
60
+ console.log( usage )
61
+ }
62
+
63
+ if ( !args.url || !args.ipaddress ) {
64
+ console.log( '\n*******************************************' )
65
+ console.log( '** **' )
66
+ console.log( '** Need to specify URL and/or IP address **' )
67
+ console.log( '** **' )
68
+ console.log( '*******************************************' )
69
+ console.log( usage )
70
+ } else {
71
+ const CF = new Cloudflare( { ...defaultConfig, args } )
72
+ try {
73
+ await CF.createDNSRecord()
74
+ console.log( 'Successfully created a new DNS record' )
75
+ console.log( 'It may take a few minutes for DNS to propagate' )
76
+ } catch ( ex ) {
77
+ console.error( ex.message )
78
+ }
79
+ }
80
+ }
81
+
82
+ main()
package/src/dockreate ADDED
@@ -0,0 +1,338 @@
1
+ #!/bin/bash
2
+ if [ -z "$1" ]; then
3
+ echo " Usage: create <version number>"
4
+ exit 1
5
+ fi
6
+
7
+ # cleanup trapper for gracefully killing, which doesn't do much right now
8
+ cleanup() {
9
+ printf "\nCleaning up and exiting...\n\n"
10
+ rm -rf ./workspace $SSHDIR .npmrc
11
+ exit 0
12
+ }
13
+ trap cleanup INT
14
+
15
+ # Usage: colorize <color> <string>
16
+ # where: color = [red|green|yellow]
17
+ # string = the thing to apply the color to
18
+ colorize() {
19
+ local C_green='\e[92m'
20
+ local C_yellow='\e[93m'
21
+ local C_red='\e[91m'
22
+ local C_off='\e[0m'
23
+
24
+ case "$1" in
25
+ 'red' ) clr="$C_red" ;;
26
+ 'green' ) clr="$C_green" ;;
27
+ 'yellow') clr="$C_yellow" ;;
28
+ *) clr=$C_off;;
29
+ esac
30
+
31
+ printf "$clr$2$C_off"
32
+ }
33
+
34
+ strip_undefined() {
35
+ local result="$1"
36
+ [ "$1" == "undefined" ] && result=""
37
+ printf "$result"
38
+ }
39
+
40
+ # Useful links with information regarding k8s/docker/nodejs and PID 1
41
+ # No PID 1 for NodeJS => https://bit.ly/2Txi9Jq
42
+ # What tini is all about => https://bit.ly/2HsSxqP
43
+ # Graceful kills with k8s => https://bit.ly/2NONEJG
44
+ #
45
+ # Params: $1 = version from dockerize invocation
46
+ # $2 = node image to dockerize, default: carbon-alpine (node 8)
47
+ # $3 = additional packages to install (htop redis-cli etc)
48
+ create_Dockerfile() {
49
+ local regvers="${1}"
50
+ local nodeimg="${2:-carbon-alpine}"
51
+ local apkadds="${3}"
52
+ echo "Creating the Dockerfile for node ${nodeimg}"
53
+ cat<<EODOCKER > Dockerfile
54
+ # Version ${regvers} @ `date`
55
+ #
56
+ # The FROM directive sets the Base Image for subsequent instructions
57
+ FROM node:${nodeimg} as intermediate
58
+
59
+ RUN mkdir -p /usr/src/app
60
+ WORKDIR /usr/src/app
61
+
62
+ # Install app dependencies
63
+ COPY ./workspace/ /usr/src/app/
64
+
65
+ # --------------------------------------------------------------
66
+ # copy the ssh keys into place, npm install, and remove them
67
+ # --------------------------------------------------------------
68
+
69
+ # Install packages to install private repos with ssh keys
70
+ COPY ./.npmrc /usr/src/app/.npmrc
71
+ RUN apk --no-cache add curl git openssh-client && \
72
+ apk --update add --no-cache --virtual build-dep g++ gcc libgcc \\
73
+ libstdc++ linux-headers make python && \
74
+ npm install --production --silent && \
75
+ rm -f /usr/src/app/.npmrc /root/.ssh/*
76
+
77
+ # --------------------------------------------------------------
78
+ # On to the real build now, the thing before was just an intermediate container
79
+ # --------------------------------------------------------------
80
+
81
+ FROM node:${nodeimg}
82
+
83
+ # Install tint for PID 1 and replace shell with bash so we can source files
84
+ RUN apk update && \
85
+ apk add --no-cache tini bash vim ${apkadds} && \
86
+ rm /bin/sh && ln -s /bin/bash /bin/sh && \
87
+ mkdir -p /usr/src/app /tmp/levlog
88
+ ENTRYPOINT [ "/sbin/tini", "--" ]
89
+ WORKDIR /usr/src/app
90
+
91
+ COPY --from=intermediate /usr/src/app /usr/src/app
92
+
93
+ USER node
94
+ COPY ./bashrc /home/node/.bashrc
95
+ CMD [ "/bin/bash", "-c", "node index.js" ]
96
+ EODOCKER
97
+ } # end of create_Dockerfile
98
+
99
+ # Params: $1 = version from dockerize invocation
100
+ create_bashrc() {
101
+ cat<<EOBASHRC > bashrc
102
+ #!/bin/bash
103
+ #
104
+ # Version $1 @ `date`
105
+
106
+ alias golog='cd /var/log/levlog;ls -l'
107
+ alias h=history
108
+
109
+ alias ls='ls -CF --color=auto'
110
+ alias ll='ls -lh'
111
+ alias lla='ls -lha'
112
+ alias ltr='ls -CF --color=auto -lthr'
113
+ alias genv='env | grep -i'
114
+ alias glep='grep -l -s'
115
+ alias golog='cd /var/log/levlog'
116
+ alias m=less
117
+ alias menv='env | sort | less'
118
+
119
+ alias whatsmyip='wget -qO- ifconfig.co'
120
+
121
+ alias rcli='redis-cli -h \${DATABASES_REDIS_SERVICE_HOST}'
122
+
123
+ alias buny='/usr/src/app/node_modules/bunyan/bin/bunyan'
124
+ alias bunlog='golog;cat *-1.log | buny | m'
125
+ alias dbg='wget -q -O- localhost:5111/logLevel/debug'
126
+ alias inf='wget -q -O- localhost:5111/logLevel/info'
127
+
128
+ loglev()
129
+ {
130
+ local wget='wget -q -O- localhost:5111'
131
+ local logl=''
132
+
133
+ if [ "\$1" != "" ];
134
+ then
135
+ logl="logLevel/\$1"
136
+ fi
137
+
138
+ printf "Running=> \$wget/\$logl\n"
139
+ printf "\n\`\$wget/\$logl\`\n\n"
140
+ }
141
+ EOBASHRC
142
+ } # end of create_bashrc
143
+
144
+ NPMRC="$HOME/.npmrc.ro"
145
+ if [ ! -f "$NPMRC" ];
146
+ then
147
+ cat<<ROTOKEN
148
+
149
+ $(colorize 'red' '***ERROR: expecting to see a readonly npmjs token')
150
+
151
+ For security purposes, we deploy images with read-only npmjs tokens.
152
+ These may be acquired from another developer, or can be created with the
153
+ npmjs leverege account.
154
+
155
+ Obtain the token and drop it here => $(colorize 'green' "$NPMRC")
156
+
157
+
158
+ ROTOKEN
159
+ exit 1
160
+ fi
161
+
162
+ # Look for leverege specifics, but only require the project name.
163
+ project=$(strip_undefined "`node -p \"require('../package.json').leverege.project\"`")
164
+ if [ "$project" == "" ];
165
+ then
166
+ cat<<NOPROJ
167
+
168
+ $(colorize 'red' '***ERROR: package.json missing a leverege project statement')
169
+
170
+ The package.json file must contain a project setting in the leverege
171
+ namespace stating which GCP project the docker images are written to. It
172
+ should look something like:
173
+
174
+ "leverege": {
175
+ "project": "leverege-docker-images"
176
+ },
177
+
178
+ NOPROJ
179
+ exit 1
180
+ fi
181
+
182
+ nodeimg=$(strip_undefined "`node -p \"require('../package.json').leverege.nodeimg\"`")
183
+ nodeimg="${nodeimg:-carbon-alpine}"
184
+ apkadds=$(strip_undefined "`node -p \"require('../package.json').leverege.apkadds\"`")
185
+
186
+ container="`node -p \"require('../package.json').leverege.container\"`"
187
+ if [ "$container" == "undefined" ];
188
+ then
189
+ container=$(basename `git config --get remote.origin.url` .git)
190
+ fi
191
+ gcimage=gcr.io/$project/$container
192
+
193
+ version=$1
194
+ previous=`cat .previous`
195
+ pckgver="v`node -p \"require('../package.json').version\"`"
196
+ pckgdts="`date +\"%Y%m%d-%H%M\"`"
197
+ tagging=`echo $version | egrep -e "^v\d+\.\d+\.\d+$"`
198
+
199
+ if [ $tagging ];
200
+ then
201
+ if [[ `git status --porcelain` ]]; then
202
+ cat<<DIRTAG
203
+
204
+ $(colorize 'red' '***ERROR: attempting to tag a non-beta dirty git repository')
205
+
206
+ You are attempting to create a tagged release image for pushing to the
207
+ container registry, but there are locally modified files. This is not
208
+ allowed since the applied tag will not be relevant to the image version
209
+ due to the pending commits.
210
+
211
+ Available options for proceeding:
212
+
213
+ $(colorize 'green' '1) cleanly commit all local mods assuming relevance')
214
+ $(colorize 'yellow' '2) eliminate unwanted local modifications')
215
+ $(colorize 'red' '3) stash anything that is irrelevant to this release')
216
+
217
+
218
+ DIRTAG
219
+ exit 1
220
+ fi
221
+
222
+ # since we're tagging, the current branch must have an upstream
223
+ branch=`git rev-parse --abbrev-ref HEAD`
224
+ git rev-parse --abbrec-ref ${branch}@{u} &> /dev/null
225
+
226
+ if [ $? -ne 0 ];
227
+ then
228
+ cat<<NOUPSTR
229
+
230
+ $(colorize 'red' '***ERROR: the current branch must have an upstream')
231
+
232
+ You are attempting to create a tagged release image for pushing to the
233
+ container registry, but the current branch does not have an upstream to
234
+ push to. This is not allowed since the applied tag will be stranded here
235
+ in your local repository, which is what we are attempting to avoid.
236
+
237
+ Available options for proceeding:
238
+
239
+ $(colorize 'green' '1) set an upstream for this branch via:')
240
+ $(colorize 'green' " git push --set-upstream origin ${branch}")
241
+
242
+ $(colorize 'yellow' '2) rebase, squash and merge onto a branch with an upstream')
243
+
244
+ NOUPSTR
245
+ exit 1
246
+ fi
247
+
248
+ tagstat=$(colorize 'yellow' 'will be tagged')
249
+ else
250
+ tagstat=$(colorize 'red' 'BETA RELEASE WILL NOT BE TAGGED')
251
+ fi
252
+
253
+ cat<<IMGINFO
254
+
255
+ Project: $(colorize 'green' "$project")
256
+ Container: $(colorize 'green' "$container")
257
+ NodeImage: $(colorize 'green' "$nodeimg")
258
+ AddedPkgs: $(colorize 'green' "$apkadds")
259
+ Version: $(colorize 'green' "$version") $tagstat
260
+ Previous: $(colorize 'yellow' "$previous")
261
+ DateStamp: $(colorize 'green' "$pckgdts")
262
+ GCImage: $(colorize 'green' "$gcimage:$version")
263
+
264
+ IMGINFO
265
+
266
+ if [ "$pckgver" != "$version" ];
267
+ then
268
+ cat<<EOPKG
269
+ $(colorize 'yellow' '***WARNING: specified version does not match package.json version' )
270
+ package.json => $(colorize 'green' "$pckgver")
271
+ specified => $(colorize 'red' "$version")
272
+
273
+ EOPKG
274
+ if [ $tagging ];
275
+ then
276
+ cat<<EONOPE
277
+
278
+ $(colorize 'red' '... and you are attempting to release so NOPE!' )
279
+
280
+ EONOPE
281
+ exit 1
282
+ fi
283
+ fi
284
+
285
+ create_Dockerfile "$version" "$nodeimg" "$apkadds"
286
+ create_bashrc "$version" "$nodeimg"
287
+
288
+ [ -d ./workspace ] && rm -rf ./workspace
289
+ mkdir -p ./workspace
290
+ cp -rfp ../package*json ../dist/* ./workspace
291
+
292
+ # grab the read only npmrc token for the image
293
+ cp -f $NPMRC .npmrc
294
+
295
+ [ "$CIRCLECI" == "true" ] && exit 0
296
+
297
+ printf "Hit return to continue or ^C to exit\n\n"; read ANS
298
+
299
+ echo $version > .previous
300
+
301
+ echo "Changing Google Project to $project"
302
+ gcloud config set project $project
303
+
304
+ echo "Creating Docker Image for $gcimage:$version"
305
+ echo " Building the workspace"
306
+
307
+ # submit the build request to gcloud
308
+ gcloud builds submit --tag $gcimage:$version .
309
+
310
+ if [ $? -ne 0 ];
311
+ then
312
+ bldErr=$?
313
+ cat<<BUILDERR
314
+
315
+ $(colorize 'red' '***ERROR: build failed! Aborting without tagging.')
316
+
317
+ The gcloud build process seems to have run into a problem. Please fix the
318
+ issue and rerun the dockerize process. This build will not be tagged, nor
319
+ will it be pushed.
320
+
321
+ BUILDERR
322
+ exit $bldErr
323
+ fi
324
+
325
+ # Tag the container with the node detailsand the culprit.
326
+ gcloud beta container images add-tag --quiet $gcimage:$version $gcimage:$pckgdts-$nodeimg-$USER
327
+
328
+ if [ $tagging ];
329
+ then
330
+ printf "\n$(colorize 'green' "Tagging and Pushing $version")\n"
331
+ git tag -af $1 -m "Docker version $1"
332
+ git push --follow-tags
333
+ gcloud beta container images add-tag --quiet $gcimage:$version $gcimage:latest
334
+ else
335
+ printf "\n$(colorize 'yellow' '*** Skipped git tagging - beta release')\n\n"
336
+ fi
337
+
338
+ cleanup
@@ -0,0 +1,31 @@
1
+ #!/bin/bash
2
+ display_usage() {
3
+ echo "This script encrypts files using Google KMS."
4
+ echo -e "\nInputs: .env and secrets directory (if it exists) \n"
5
+ }
6
+
7
+ if [ "$1" == "-h" ]; then
8
+ display_usage
9
+ exit 1
10
+ fi
11
+
12
+ if [ -d "secrets" ]; then
13
+ # tar up secrets directory
14
+ tar -zcvf secrets.tar.gz secrets
15
+ # encrypt secrets file
16
+ gcloud kms encrypt \
17
+ --project leverege-docker-images \
18
+ --key circle-ci \
19
+ --keyring build-tools \
20
+ --location us-east4 \
21
+ --plaintext-file secrets.tar.gz \
22
+ --ciphertext-file secrets.tar.gz.enc
23
+ fi
24
+
25
+ # encrypt .env file
26
+ gcloud kms encrypt --project leverege-docker-images \
27
+ --key circle-ci \
28
+ --keyring build-tools \
29
+ --location us-east4 \
30
+ --plaintext-file .env \
31
+ --ciphertext-file .env.enc
package/src/getfbcfg ADDED
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * This script parses a firebase config into something useful.
5
+ */
6
+ let stdbuf = []
7
+
8
+ process.stdin
9
+ .on( 'data', ( d ) => { stdbuf.push( d ) } )
10
+ .on( 'end', () => {
11
+ const rawCfg = stdbuf.join( '' ).replace( /[":\n\r]/g, '' )
12
+ const keyVals = rawCfg.match(/\{(.*)\}/)[1].split(',')
13
+
14
+ const lastLine = keyVals.length - 1
15
+ console.log( "{" )
16
+ for( let i = 0; i <= lastLine; i++ ) {
17
+ const kv = keyVals[i].trim().split( ' ' )
18
+ console.log( ` "${kv[0]}": "${kv[1]}"${(i < lastLine ? ',' : '')}` )
19
+ }
20
+ console.log( "}" )
21
+
22
+ } )
23
+ .setEncoding( 'utf8' )
package/src/getjson ADDED
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * This script will allow the user to grab a value from a JSON file and
5
+ * optionally apply a regular expression to it. Given this test.json file:
6
+ *
7
+ * {
8
+ * "name": "@leverege/packagename",
9
+ * "main": "lib/index.js"
10
+ * }
11
+ *
12
+ * and invoking as:
13
+ * ./getjson --file ./test.json --key name --regex "^@\w{3}"
14
+ *
15
+ * will yield an output of: @lev
16
+ */
17
+
18
+ /**
19
+ * Get a command line switch parser.
20
+ */
21
+ const fs = require( 'fs' )
22
+ const opts = require( 'commander' )
23
+
24
+ opts
25
+ .version( '0.0.1' )
26
+ .option( '-f, --file <file name>', 'file to parse JSON from' )
27
+ .option( '-k, --key <key>', 'JSON key whose value to grab' )
28
+ .option( '-r, --regex <reg>', 'regular expression to apply to the value' )
29
+ .parse( process.argv )
30
+
31
+ if( !opts.key ) { return }
32
+
33
+ if( !opts.file ) {
34
+ console.error( `\n***ERROR: Missing a --file param\n` )
35
+ opts.outputHelp()
36
+ process.exit( 1 )
37
+ }
38
+
39
+ try {
40
+ const json = JSON.parse( fs.readFileSync( opts.file, 'utf8' ))
41
+ const value = json[opts.key]
42
+ const match = new RegExp( opts.regex || ".*" ).exec( value )
43
+
44
+ console.log( match ? match[match.length-1] : '' )
45
+ }
46
+ catch( e ) {
47
+ console.log( e )
48
+ }