1 | #!/usr/bin/env node
|
2 |
|
3 | import os from 'os'
|
4 | import path from 'path'
|
5 |
|
6 | import yargonaut from 'yargonaut'
|
7 | import yargs from 'yargs'
|
8 | import yaml from 'js-yaml'
|
9 |
|
10 | const VERSION = require('../package').version
|
11 |
|
12 | import DockerCompiler from './DockerCompiler'
|
13 | import { ApplicationError } from './errors'
|
14 | import CachingUrlFetcher from './CachingUrlFetcher'
|
15 | import nix from './cli-nix'
|
16 |
|
17 | const compiler = new DockerCompiler(new CachingUrlFetcher())
|
18 |
|
19 | yargonaut
|
20 | .style('blue')
|
21 | .helpStyle('green')
|
22 | .errorsStyle('red')
|
23 |
|
24 | yargs
|
25 | .scriptName('dockter')
|
26 |
|
27 |
|
28 | .alias('h', 'help')
|
29 | .usage('$0 <cmd> [args]')
|
30 |
|
31 |
|
32 | .alias('v', 'version')
|
33 | .version(VERSION)
|
34 | .describe('version', 'Show version')
|
35 |
|
36 |
|
37 | .option('nix', {
|
38 | describe: 'Use NixOS base image'
|
39 | })
|
40 |
|
41 |
|
42 | .demandCommand(1, 'Please provide a command.')
|
43 |
|
44 | .recommendCommands()
|
45 |
|
46 |
|
47 | .strict()
|
48 |
|
49 |
|
50 |
|
51 | .command('compile [folder]', 'Compile a project to a software environment', yargs => {
|
52 | folderArg(yargs)
|
53 | }, async (args: any) => {
|
54 | const folder = path.resolve(args.folder)
|
55 | let environ = await compiler.compile('file://' + folder, false).catch(error)
|
56 | if (args.nix) {
|
57 | nix.compile(environ, folder)
|
58 | }
|
59 | })
|
60 |
|
61 |
|
62 |
|
63 | .command('build [folder]', 'Build a Docker image for project', yargs => {
|
64 | folderArg(yargs)
|
65 | }, async (args: any) => {
|
66 | const folder = path.resolve(args.folder)
|
67 | if (args.nix) {
|
68 | await nix.build(folder)
|
69 | } else {
|
70 | await compiler.compile('file://' + folder, true).catch(error)
|
71 | }
|
72 | })
|
73 |
|
74 |
|
75 |
|
76 | .command('execute [folder] [command]', 'Execute a project', yargs => {
|
77 | folderArg(yargs),
|
78 | yargs.positional('command', {
|
79 | type: 'string',
|
80 | default: '',
|
81 | describe: 'The command to execute'
|
82 | })
|
83 | }, async (args: any) => {
|
84 | const folder = path.resolve(args.folder)
|
85 | if (args.nix) {
|
86 | await nix.execute(folder, args.command)
|
87 | } else {
|
88 | const node = await compiler.execute('file://' + folder, args.command).catch(error)
|
89 | output(node, args.format)
|
90 | }
|
91 | })
|
92 |
|
93 |
|
94 |
|
95 | .command('who [folder]', 'List the people your project depends upon', yargs => {
|
96 | folderArg(yargs)
|
97 | yargs.option('depth', {
|
98 | alias: 'd',
|
99 | type: 'integer',
|
100 | default: 100,
|
101 | describe: 'The maximum dependency recursion depth'
|
102 | })
|
103 | }, async (args: any) => {
|
104 | const folder = path.resolve(args.folder)
|
105 | const people = await compiler.who('file://' + folder, args.depth).catch(error)
|
106 | if (!people) {
|
107 | console.log('Nobody (?)')
|
108 | } else {
|
109 |
|
110 | let sorted = Object.entries(people).sort(([aName,aPkgs], [bName, bPkgs]) => {
|
111 | if (aPkgs.length > bPkgs.length) return -1
|
112 | if (aPkgs.length < bPkgs.length) return 1
|
113 | if (aName < bName) return -1
|
114 | if (aName > bName) return 1
|
115 | return 0
|
116 | })
|
117 |
|
118 | const output = sorted.map(([name, packages]) => {
|
119 | return `${name} (${packages.join(', ')})`
|
120 | }).join(', ')
|
121 | console.log(output)
|
122 | }
|
123 | })
|
124 |
|
125 | .parse()
|
126 |
|
127 |
|
128 |
|
129 |
|
130 |
|
131 |
|
132 | function folderArg (yargs: yargs.Argv) {
|
133 | yargs.positional('folder', {
|
134 | type: 'string',
|
135 | default: '.',
|
136 | describe: 'The path to the project folder'
|
137 | })
|
138 | }
|
139 |
|
140 |
|
141 |
|
142 |
|
143 |
|
144 |
|
145 |
|
146 | function output (object: any, format: string = 'json') {
|
147 | if (object) console.log(format === 'yaml' ? yaml.safeDump(object, { lineWidth: 120 }) : JSON.stringify(object, null, ' '))
|
148 | }
|
149 |
|
150 |
|
151 |
|
152 |
|
153 |
|
154 |
|
155 | function error (error: Error) {
|
156 | if (error instanceof ApplicationError) {
|
157 | console.error(error.message)
|
158 | } else {
|
159 | console.error('Woops, sorry something went wrong :(')
|
160 | console.error('Please help us fix this issue by posting this output to https://github.com/stencila/dockter/issues/new')
|
161 | console.error(` args: ${process.argv.slice(2).join(' ')}`)
|
162 | console.error(` version: ${VERSION}`)
|
163 | console.error(` platform: ${os.platform()}`)
|
164 | console.error(error)
|
165 | process.exit(1)
|
166 | }
|
167 | }
|