@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,303 @@
1
+ #!/usr/bin/env node
2
+
3
+ const chalk = require( 'chalk' )
4
+ const cliArgs = require( 'command-line-args' )
5
+ const cliHelp = require( 'command-line-usage' )
6
+ const exec = require( 'child_process' ).execSync
7
+ const fs = require( 'fs' )
8
+ const glob = require( 'glob' )
9
+ const parse = require( 'parse-gitignore' )
10
+ const ask = require( 'readline-sync' )
11
+ const YAML = require( 'js-yaml' )
12
+
13
+ const optionsDefinitions = [
14
+ { name : 'section', alias : 's', type : String, default : 'default' },
15
+ { name : 'key', alias : 'k', type : String },
16
+ { name : 'export', alias : 'e', type : Boolean, default : false },
17
+ { name : 'continue', alias : 'c', type : Boolean, default : false },
18
+ { name : 'verbose', alias : 'v', type : Boolean, default : false },
19
+ ]
20
+ const args = cliArgs( optionsDefinitions )
21
+
22
+ // The kubernetes context is equal to the git branch name.
23
+ const context = require( 'git-branch' ).sync()
24
+
25
+ if ( context == 'master' ) {
26
+ console.log( '***ERROR: master context is forbidden; change to a different branch\n\n' )
27
+ process.exit( 1 )
28
+ }
29
+
30
+ // Load the default values and then overlay with the project specific yaml
31
+ // values. This supports the notion of this type of approach in the
32
+ // overwhelm yaml settings:
33
+ // default:
34
+ // GCE_MACHINE : "n1-standard-2"
35
+ //
36
+ // my-project:
37
+ // GCE_MACHINE : "n1-highcpu-8"
38
+ //
39
+ // where the my-project specific setting may override the default if it
40
+ // needs a beefier deployment. Any setting can be defaulted in this
41
+ // fashion, but it is advised not to set a default region with this
42
+ // approach in order to keep us cognizant of exactly where a cluster is
43
+ // being formed.
44
+ //
45
+ const yaml = YAML.safeLoad( fs.readFileSync( 'overwhelm.yaml', 'utf-8' ) )
46
+ const over = yaml.default
47
+ const cfgs = yaml[context]
48
+
49
+ if ( !cfgs ) {
50
+ console.log( `***ERROR: Unknown context => [${context}]\n` )
51
+ console.log( ' Known k8s contexts are:' )
52
+ Object.keys( yaml ).forEach( ( key ) => {
53
+ if ( key !== 'default' ) { console.log( ` ${key}` ) }
54
+ } )
55
+ console.log( `Add a section into overwhelm.yaml for ${context}\n\n` )
56
+ process.exit( 1 )
57
+ }
58
+
59
+ Object.keys( cfgs ).forEach( ( key ) => { over[key] = cfgs[key] || over[key] } )
60
+
61
+ // Expand any variables that reference other variable settings. A perfect
62
+ // example of where this is useful is in the setting of a PROJECT_NAME and
63
+ // a PROJECT_ID. Most of the time these values are identical, which is why
64
+ // this setting exists in the default section:
65
+ // default:
66
+ // PROJECT_ID : ${PROJECT_NAME}
67
+ //
68
+ // However, in the case of projects like Siren Marine, this is the more
69
+ // likely setup due to legacy naming schemes:
70
+ // sire-marine:
71
+ // PROJECT_NAME : siren-marine
72
+ // PROJECT_ID : prod-rt-data
73
+ //
74
+ const varErrors = []
75
+ Object.keys( over ).forEach( ( key ) => {
76
+ if ( !over[key] ) return // no value to work with - skip it
77
+
78
+ // Look for something in the form of "thing-${VAR1}-${VAR2}-${VARn}-stuff"
79
+ const matches = over[key].match( /\$\{\w+\}/g )
80
+ if ( !matches ) return
81
+
82
+ matches.forEach( ( replaceThis ) => {
83
+ // The matched variable names will be in the form of ${VARNAME} so drop
84
+ // the ${} characters before using the VARNAME to map into the
85
+ // overwhelm map containing the desired replacement value.
86
+ const withThat = over[replaceThis.replace( /\W+/g, '' )]
87
+ if ( !withThat ) {
88
+ varErrors.push( `${key} : ${over[key]}` )
89
+ return
90
+ }
91
+ // Store the replaced string back in the overwhelm value map.
92
+ over[key] = over[key].replace( replaceThis, withThat )
93
+ } )
94
+ } )
95
+
96
+ if ( varErrors.length > 0 ) {
97
+ console.log( '***ERROR: unkown variable reference(s) in overwhelm.yaml:\n' )
98
+ varErrors.forEach( ( error ) => {
99
+ console.log( ` ${error}` )
100
+ } )
101
+ console.log('' )
102
+ process.exit( 1 )
103
+ }
104
+
105
+ // Grab a list of the existing yaml templates.
106
+ const yams = glob.sync( 'values-*.yaml' )
107
+
108
+ // A function to apply the replacements to all of the matching yaml which
109
+ // will error out if it runs into an unknown OVH<tag>.
110
+ const doReplacements = ( yamls, replacements ) => {
111
+ let replYaml = yamls
112
+
113
+ Object.keys( replacements ).forEach( ( repl ) => {
114
+ const replaceThis = new RegExp( `OVH:<${repl}>`, 'g' )
115
+ const withThat = `${replacements[repl]}`
116
+ replYaml = replYaml.replace( replaceThis, withThat )
117
+ } )
118
+
119
+ // Verify all replaceables have been handled, or error out.
120
+ const missed = replYaml.match( /OVH:<(.*)>/g )
121
+
122
+ if ( missed ) {
123
+ console.log( '\n***ERROR: missing replacements in overwhelm.yaml for these tags:\n' )
124
+ missed.forEach( ( miss ) => {
125
+ console.log( ` TAG: ${miss.match( /OVH:<(.*)>/)[1]}` )
126
+ } )
127
+ console.log('' )
128
+ process.exit( 1 )
129
+ }
130
+
131
+ return replYaml
132
+ }
133
+
134
+ // Collect all of the yaml from the yams, and always expect the default and
135
+ // platform yamls to be in that list.
136
+ const buildYaml = ( yamls, replacements ) => {
137
+ // We always start with default but values-platform is no longer needed.
138
+ const always = [ 'values-default.yaml' ]
139
+ const values = [ ...always, ...yamls ]
140
+ const loaded = []
141
+ let allYamls = ''
142
+
143
+ values.forEach( ( yaml ) => {
144
+ if ( !fs.existsSync( yaml ) ) {
145
+ console.log( `\n***ERROR: yaml file missing => ${yaml}\n` )
146
+ process.exit( 1 )
147
+ }
148
+
149
+ if ( !loaded.includes( yaml ) ) {
150
+ allYamls += `\n# AHOY => ${yaml}\n\n`
151
+ allYamls += fs.readFileSync( yaml, { encoding : 'utf-8' } )
152
+ loaded.push( yaml )
153
+ }
154
+ } )
155
+
156
+ // Now apply all of the replacements from the overwhelm file.
157
+ return doReplacements( allYamls, replacements )
158
+ }
159
+
160
+ // Call buildYaml to replace the OVH strings in the yaml files.
161
+ const values = buildYaml( yams, over )
162
+
163
+ // Check to see if someone is requesting a value from the yaml.
164
+ if ( args.key ) {
165
+ const section = args.section || 'default'
166
+ const keys = yaml[section]
167
+ if ( args.verbose ) {
168
+ console.log( 'replacements' )
169
+ console.log( keys )
170
+ }
171
+ if ( args.export ) {
172
+ console.log( `export ${args.key}=${keys[args.key]}` )
173
+ }
174
+ else {
175
+ console.log( keys[args.key] )
176
+ }
177
+ if ( ! args.continue ) process.exit()
178
+ }
179
+
180
+ // Find all of the potential target dirs. Utilize .gitignore to ignore files
181
+ const opt = {
182
+ ignore : parse( fs.readFileSync( '.gitignore' ) )
183
+ }
184
+
185
+ const ahoy = glob.sync( '*/', opt )
186
+
187
+ // Keel supports a "never" policy which will cause it to skip over a release
188
+ // if it is properly set. Adding a .nokeel file to a release directoy will
189
+ // cause the creation of the file if it does not already exist.
190
+ const generateKeelNeverPolicy = ( fileName ) => {
191
+ if ( fs.existsSync( fileName ) ) return
192
+ const neverPolicy = `
193
+ keel:
194
+ # keel policy (all/major/minor/patch/force)
195
+ policy: "never"
196
+ # approvals
197
+ # approvals: 1
198
+ # approvalDeadline: 24
199
+ # # images to track and update
200
+ # images:
201
+ # - repository: never.IMAGE # [1]
202
+ # tag: never.VERSION # [2]
203
+ `
204
+ fs.writeFileSync( fileName, neverPolicy )
205
+ }
206
+
207
+ // Generate the values.yaml files in directories not marked with .nohelm.
208
+ ahoy.forEach( ( dir ) => {
209
+ if ( !fs.existsSync( `${dir}/.nohelm` ) ) {
210
+ console.log( `Generating values in ${dir}` )
211
+
212
+ let valuesOut = [] // An accumulator for all of the output values.
213
+
214
+ // Add support for localized values for things like keel (or whatever)
215
+ const valuesLocal = `${dir}values-local.yaml`
216
+
217
+ if ( fs.existsSync( `${dir}.nokeel` ) ) {
218
+ generateKeelNeverPolicy( valuesLocal )
219
+ }
220
+
221
+ if ( fs.existsSync( valuesLocal ) ) {
222
+ console.log( ` Local values in ${valuesLocal}` )
223
+ valuesOut += `\n# AHOY => values-local.yaml\n\n`
224
+ valuesOut += fs.readFileSync( valuesLocal, { encoding : 'utf-8' } )
225
+ }
226
+ valuesOut += `\n${values}`
227
+ valuesOut = doReplacements( valuesOut, over )
228
+
229
+ fs.writeFileSync( `${dir}/values.yaml`, valuesOut )
230
+ }
231
+ } )
232
+
233
+ // Set the GCP context for safety!
234
+ const clusterName = over['CLUSTER_NAME']
235
+ const projectName = over['PROJECT_NAME']
236
+ const zone = over['GCE_REGION'] + ( over['GCE_ZONE'] ? `-${over['GCE_ZONE']}` : '' )
237
+
238
+ if ( !clusterName ) {
239
+ console.log( chalk.yellow(
240
+ `
241
+
242
+ The overwhelm.yaml file in this branch is missing a CLUSTER_NAME setting,
243
+ which was added to support cluster names that do not match the project
244
+ name. Since the mismatch is rare, you can probably get by with simply
245
+ adding this line following PROJECT_NAME in the default section of
246
+ overwhelm.yaml:
247
+
248
+ ${chalk.bold.green( `CLUSTER_NAME : "\${PROJECT_NAME}"` )}
249
+
250
+ However, if the CLUSTER_NAME is not the same as the PROJECT_NAME then go
251
+ ahead and add the CLUSTER_NAME setting to the ${chalk.bold.green(projectName)} section of the
252
+ overwhelm.yaml file.
253
+
254
+ ` ) )
255
+ process.exit( 1 )
256
+ }
257
+
258
+ let kubeout = '_no_current_context_'
259
+ try {
260
+ // if current is not set exec will throw
261
+ kubeout = exec( 'kubectl config current-context' )
262
+ } catch (err) { }
263
+
264
+ const currentCtx = kubeout.toString().trim()
265
+ const desiredCtx = `gke_${projectName}_${zone}_${clusterName}`
266
+ const matchedCtx = ( currentCtx === desiredCtx )
267
+ const cmd = `gcloud container clusters get-credentials ${clusterName} --zone ${zone} --project ${projectName}`
268
+
269
+ if ( matchedCtx ) {
270
+ console.log( `
271
+
272
+ Your current context matches. Do you want to update credentials anyway?
273
+
274
+ ` )
275
+ }
276
+ else {
277
+ console.log( `
278
+
279
+ You are about to change your GCP context to:
280
+ CLUSTER_NAME => ${chalk.bold.green(clusterName)}
281
+ PROJECT_NAME => ${chalk.bold.green(projectName)}
282
+ GCE_REGION => ${chalk.bold.green(zone)}
283
+
284
+ ` )
285
+ }
286
+ const ans = ask.question( `Enter "${chalk.bold.green( 'yes' )}" if you wish to proceed => ` )
287
+ if ( ans !== 'yes' ) {
288
+ if ( matchedCtx ) {
289
+ console.log( chalk.bold.yellow( `\n\nSkipping a refetch of your GCP context and credentials\n\n` ) )
290
+ process.exit( 0 )
291
+ }
292
+
293
+ console.log( chalk.bold.red( `\n\nYour GCP context and credentials do NOT match - this could be bad!\n\n` ) )
294
+ process.exit( 1 )
295
+ }
296
+
297
+ console.log( `\n\nExecuting: ${cmd}\n\n` )
298
+ exec( `${cmd}`, ( error, out ) => {
299
+ if ( error ) {
300
+ console.log( `\n\n***ERROR ${error}\n\n` )
301
+ process.exit( 1 )
302
+ }
303
+ } )
@@ -0,0 +1,269 @@
1
+ "use strict";
2
+
3
+ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
4
+
5
+ const exec = require('child_process').exec;
6
+
7
+ const fs = require('fs-extra');
8
+
9
+ const path = require('path');
10
+
11
+ const async = require('async');
12
+
13
+ const copy = require('recursive-copy');
14
+
15
+ const ora = require('ora');
16
+
17
+ const tar = require('tar');
18
+
19
+ const semver = require('semver');
20
+
21
+ class Packleator {
22
+ constructor(options) {
23
+ const {
24
+ args
25
+ } = options;
26
+ this.privatePackages = new Set();
27
+ this.args = args ? { ...args,
28
+ output: args.output.substr(-1) === '/' ? args.output.substr(0, args.output.length) : args.output
29
+ } : {}; // args || {}
30
+
31
+ this.spinner = ora({
32
+ text: 'Installing NPM dependencies...',
33
+ spinner: 'monkey'
34
+ });
35
+ this.stderr = '';
36
+ this.tarredVersions = {};
37
+ this.outputPackageJson = {};
38
+ this.outputPackageLockJson = {};
39
+ }
40
+
41
+ async run() {
42
+ try {
43
+ this.spinner.start();
44
+ await this.npmInstall();
45
+ this.spinner.text = 'Copying files...';
46
+ await this.copyFiles();
47
+ process.chdir(this.args.output);
48
+ this.outputPackageJson = await this.getPackageJson();
49
+ this.outputPackageLockJson = await this.getPackageJson(undefined, true);
50
+ this.spinner.text = 'Parsing private dependencies...';
51
+ const deps = await this.getPrivateDeps();
52
+ this.spinner.text = 'Packaging modules...';
53
+ async.eachOfSeries(deps, async (item, key) => {
54
+ const packageJson = await this.getPackageJson(item);
55
+ const {
56
+ name,
57
+ version
58
+ } = packageJson;
59
+ await this.pack(name, version, item);
60
+ }, async err => {
61
+ await this.rebuildPackageJson();
62
+ await this.rebuildPackageLockJson();
63
+ await fs.writeFile('package.json', JSON.stringify(this.outputPackageJson, null, 2));
64
+ await fs.writeFile('package-lock.json', JSON.stringify(this.outputPackageLockJson, null, 2));
65
+ await fs.remove('node_modules');
66
+ const {
67
+ name,
68
+ version
69
+ } = this.outputPackageJson;
70
+ const fileName = `${name.replace('@', '').replace('/', '-')}-${version}.tgz`;
71
+ process.chdir('..');
72
+ this.spinner.text = 'Packaging results...';
73
+ await tar.c({
74
+ file: fileName,
75
+ strict: true,
76
+ prefix: 'package/',
77
+ C: this.args.output
78
+ }, ['.']);
79
+ this.spinner.text = 'Cleaning up...';
80
+ await this.cleanup();
81
+ this.spinner.stop();
82
+ });
83
+ } catch (ex) {
84
+ this.spinner.stop();
85
+ throw ex;
86
+ }
87
+ }
88
+
89
+ async rebuildPackageJson() {
90
+ const packageJson = this.outputPackageJson;
91
+ const tarredPackages = Object.keys(this.tarredVersions);
92
+ const {
93
+ dependencies = {},
94
+ devDependencies = {}
95
+ } = packageJson;
96
+ tarredPackages.forEach(tarredPackage => {
97
+ if (dependencies[tarredPackage]) {
98
+ const version = semver.maxSatisfying(this.tarredVersions[tarredPackage], dependencies[tarredPackage]);
99
+
100
+ if (version != null) {
101
+ packageJson.dependencies[tarredPackage] = `file:${Packleator.PRIVATE_PACKAGES_DIRECTORY}${path.sep}${tarredPackage.replace('@', '').replace('/', '-')}-${version}.tgz`;
102
+ }
103
+ }
104
+
105
+ if (devDependencies[tarredPackage]) {
106
+ const version = semver.maxSatisfying(this.tarredVersions[tarredPackage], devDependencies[tarredPackage]);
107
+
108
+ if (version != null) {
109
+ packageJson.devDependencies[tarredPackage] = `file:${Packleator.PRIVATE_PACKAGES_DIRECTORY}${path.sep}${tarredPackage.replace('@', '').replace('/', '-')}-${version}.tgz`;
110
+ }
111
+ }
112
+ });
113
+ }
114
+
115
+ async rebuildPackageLockJson() {
116
+ const packageLockJson = this.outputPackageLockJson;
117
+ const tarredPackages = Object.keys(this.tarredVersions);
118
+
119
+ const recurseDeps = deps => {
120
+ Object.keys(deps).forEach(key => {
121
+ const dep = deps[key];
122
+ tarredPackages.forEach(tarredPackage => {
123
+ if (key === tarredPackage) {
124
+ dep.version = `file:${Packleator.PRIVATE_PACKAGES_DIRECTORY}${path.sep}${key.replace('@', '').replace('/', '-')}-${dep.version}.tgz`;
125
+ delete dep.resolved;
126
+ delete dep.integrity;
127
+ }
128
+
129
+ if (dep.requires && dep.requires[tarredPackage]) {
130
+ delete dep.requires[tarredPackage];
131
+ }
132
+ });
133
+
134
+ if (dep.dependencies) {
135
+ recurseDeps(dep.dependencies);
136
+ }
137
+ });
138
+ };
139
+
140
+ recurseDeps(packageLockJson.dependencies);
141
+ }
142
+
143
+ async copyFiles() {
144
+ const startsWith = new RegExp(`^(dist|lib|image|package|${this.args.output})`);
145
+ const endsWith = /\.tgz$/;
146
+ await fs.remove(this.args.output);
147
+ await fs.mkdirp(this.args.output);
148
+ await copy('.', this.args.output, {
149
+ overwrite: true,
150
+ dot: true,
151
+ filter: item => {
152
+ if (item === 'package.json' || item === 'package-lock.json') {
153
+ return true;
154
+ }
155
+
156
+ if (startsWith.test(item) || endsWith.test(item)) {
157
+ return false;
158
+ }
159
+
160
+ if (item.startsWith('.') && item.indexOf('.babelrc') === -1) {
161
+ return false;
162
+ }
163
+
164
+ if (this.args.ignore.length > 0) {
165
+ return this.args.ignore.indexOf(item) === -1;
166
+ }
167
+
168
+ return true;
169
+ }
170
+ });
171
+ }
172
+
173
+ async pack(name, version, dir) {
174
+ const fileName = `${name.replace('@', '').replace('/', '-')}-${version}.tgz`;
175
+ await tar.c({
176
+ file: fileName,
177
+ C: dir,
178
+ strict: true,
179
+ prefix: 'package/'
180
+ }, ['.']);
181
+ await fs.move(path.join(process.cwd(), fileName), path.join(process.cwd(), Packleator.PRIVATE_PACKAGES_DIRECTORY, fileName), {
182
+ overwrite: true
183
+ });
184
+
185
+ if (this.tarredVersions[name]) {
186
+ this.tarredVersions[name].push(version);
187
+ } else {
188
+ this.tarredVersions[name] = [version];
189
+ }
190
+
191
+ return fileName;
192
+ }
193
+
194
+ async cleanup() {
195
+ await copy(this.args.output, process.cwd(), {
196
+ overwrite: true,
197
+ filter: '*.tgz'
198
+ });
199
+ await fs.remove(this.args.output);
200
+ }
201
+
202
+ async npmInstall(dir = process.cwd()) {
203
+ const currentDir = process.cwd();
204
+ return new Promise((resolve, reject) => {
205
+ if (currentDir !== dir) {
206
+ process.chdir(dir);
207
+ }
208
+
209
+ const npmInstall = exec('npm install');
210
+ npmInstall.stderr.on('data', data => {
211
+ this.stderr += data.toString();
212
+ });
213
+ npmInstall.on('exit', code => {
214
+ if (currentDir !== dir) {
215
+ process.chdir(currentDir);
216
+ }
217
+
218
+ resolve();
219
+ });
220
+ npmInstall.on('error', err => {
221
+ if (currentDir !== dir) {
222
+ process.chdir(currentDir);
223
+ }
224
+
225
+ reject(err);
226
+ });
227
+ });
228
+ }
229
+
230
+ async getPrivateDeps(depth) {
231
+ return new Promise((resolve, reject) => {
232
+ const depthArg = depth != null ? ` --depth ${depth}` : '';
233
+ exec(`npm ls --parseable --silent${depthArg}`, (err, stdout, stderr) => {
234
+ if (err && !stdout) {
235
+ reject(err);
236
+ return;
237
+ }
238
+
239
+ const dependencies = stdout.split('\n');
240
+
241
+ if (dependencies) {
242
+ resolve(dependencies.filter(item => {
243
+ const parts = item.split(path.sep);
244
+ return this.args.namespaces.indexOf(parts[parts.length - 2]) !== -1;
245
+ }));
246
+ } else {
247
+ reject(new Error('Unable to resolve package.json dependencies'));
248
+ }
249
+ });
250
+ });
251
+ }
252
+
253
+ async getPackageJson(dir = process.cwd(), lock = false) {
254
+ const lockModifier = lock ? '-lock' : '';
255
+
256
+ try {
257
+ const file = await fs.readFile(path.join(dir, `package${lockModifier}.json`), 'utf-8');
258
+ const json = JSON.parse(file);
259
+ return json;
260
+ } catch (ex) {
261
+ throw new Error('Error getting package.json. Make sure the current directory contains a valid package.json file');
262
+ }
263
+ }
264
+
265
+ }
266
+
267
+ _defineProperty(Packleator, "PRIVATE_PACKAGES_DIRECTORY", 'private_packages');
268
+
269
+ module.exports = Packleator;
@@ -0,0 +1,98 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ const commandLineArgs = require('command-line-args');
5
+
6
+ const commandLineUsage = require('command-line-usage');
7
+
8
+ const path = require('path');
9
+
10
+ const Packleator = require('./Packleator');
11
+
12
+ const ansiLogo = require('./logo-ansi');
13
+
14
+ const defaultConfig = {
15
+ namespaces: ['@leverege'],
16
+ output: 'lev_dest'
17
+ };
18
+ const sections = [{
19
+ content: ansiLogo,
20
+ raw: true
21
+ }, {
22
+ content: 'Bundles private/proprietary npm packages and source code into a tarball for distribution'
23
+ }, {
24
+ header: 'Options',
25
+ optionList: [{
26
+ name: 'output',
27
+ alias: 'o',
28
+ description: 'The destination folder (optional)',
29
+ defaultValue: 'lev_dest'
30
+ }, {
31
+ name: 'ignore',
32
+ alias: 'i',
33
+ description: 'List of files or folders to ignore. Uses glob pattern matching (optional)',
34
+ multiple: true
35
+ }, {
36
+ name: 'namespaces',
37
+ alias: 'n',
38
+ description: 'List of npm namespaces to be considered private/proprietary (optional)',
39
+ multiple: true
40
+ }, {
41
+ name: 'verbose',
42
+ alias: 'v',
43
+ description: 'Log a little bit louder now'
44
+ }, {
45
+ name: 'help',
46
+ description: 'Print this usage guide.'
47
+ }]
48
+ }];
49
+ const usage = commandLineUsage(sections);
50
+ const optionDefinitions = [{
51
+ name: 'output',
52
+ alias: 'o',
53
+ type: String,
54
+ defaultValue: defaultConfig.output
55
+ }, {
56
+ name: 'ignore',
57
+ alias: 'i',
58
+ type: String,
59
+ multiple: true,
60
+ defaultValue: []
61
+ }, {
62
+ name: 'namespaces',
63
+ alias: 'n',
64
+ type: String,
65
+ defaultValue: defaultConfig.namespaces
66
+ }, {
67
+ name: 'verbose',
68
+ alias: 'v',
69
+ type: Boolean,
70
+ defaultValue: false
71
+ }, {
72
+ name: 'help',
73
+ type: Boolean
74
+ }];
75
+ const args = commandLineArgs(optionDefinitions);
76
+
77
+ async function main() {
78
+ if (args.help) {
79
+ console.log(usage);
80
+ } else {
81
+ const packleator = new Packleator({ ...defaultConfig,
82
+ args
83
+ });
84
+
85
+ if (args.verbose) {
86
+ console.log(packleator.args);
87
+ }
88
+
89
+ try {
90
+ await packleator.getPackageJson();
91
+ await packleator.run();
92
+ } catch (ex) {
93
+ console.error(ex.message);
94
+ }
95
+ }
96
+ }
97
+
98
+ main();
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+
3
+ module.exports = ` . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 
4
+  . . S% . . . . . . . . . . . . . . . . . . 
5
+  . .:% : . . . .. . . . . . ...... . ... .. . . . .. .. . ..... . .... . .. . ..... . ... . ..... . .. . . ..... . . . . 
6
+  . :88:.. . . .8: . .8. . .. @8X@@@@@@8% @88X . . tX8% 888@@@@@@@@t. t8@@@@@%;% . . @8@@@@@@@8%. .. ;t%88t@. .:X8@@@@@@@88 . . .
7
+  . .. 8888:. . .X8S . . S%  . . :S@;ttttt%. St%8.. . @S;@ XX8S:tttttt@ 8SS;tttS88 X.. ;SX;ttttt% . ..t @8tttX88 t. t@@S:t%%ttSt . . 
8
+  . . @8888;. :t @8;. . @@  . .8SS:;:;:: . 8SS. . . ;8@@. X88@.;:;:;. . X@:;::;.;X8t%. .8SX:;:;:: .% 8::t;:: S S . tSXt.;;:;:. . 
9
+  .  888; .t8 .X:. . XS@ . . :XSt . . . S8SS . :.%X : @@88 . . . @S . . 8888 :XS; . .. @@@8.. .... t%S:.. . . . . 
10
+  . . . ..888StS 8: ... . . @@  .. :X@   t ..%;t@.. ;@.S . X88;.  .8 : X@.: ...t8X.t. :@@ S ..S8.. . %X; tX8;. .  . . . 
11
+  . . t8888X %8t . .. @SX . . :XX ;;;;:t: ..8S@:.X888 .. X88S::;;;.% . @X@%S;%X8X@X . :@t;;;;;:;;. %@ .. ..  %t. t%X8;:;;; 8.. . 
12
+  . . . .:88Xtt88 . . @X  ..... :XSS..:..:.. . @X;: SS . . X88@ ::.:.. . @XX@X@@S@t ... .@@S ::..:.. ;88t ..... SX: tSX; ::.:... . 
13
+  . . :8888% . . @X S8@@8@: :XS8X@X@X@X: . %;8 @%X . . @88:S@X@X@@;. @X . ..8X8; .. :XS8S@X@X@@: t88 t8%S8:;t: t%XSX@@X@X@% . . 
14
+  . . . . . :X8@.: . . 88X8@888SS .8@@8888@888.. ..8S@X8 . . @8@@88888@8; S8 . . .@.8St. .8@888888888...% S%888Xt@t; .;%8888888@@8 . . .
15
+  . 8 :.. .;;:::;::. :;;::::;:;:. .:;. .;:;::;::::. .;: . .:;: :;:::::::::: . ..:t;:: . :%;;:::::::. . 
16
+  . . . . . X% . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . .. . . . 
17
+  . .. . . . . . . . . . . . . . . . . . . . . . . . .`;