• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

overlookmotel / livepack / 7046923391

30 Nov 2023 01:07PM UTC coverage: 90.231% (-0.003%) from 90.234%
7046923391

push

github

overlookmotel
TODO

4630 of 4985 branches covered (0.0%)

Branch coverage included in aggregate %.

12476 of 13973 relevant lines covered (89.29%)

12986.22 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/lib/cli.js
1
#!/usr/bin/env node
×
2

×
3
/* eslint-disable import/order, import/newline-after-import */
×
4

×
5
'use strict';
×
6

×
7
// Use internal module cache
×
8
const {useInternalModuleCache, useGlobalModuleCache} = require('./shared/moduleCache.js');
×
9
useInternalModuleCache();
×
10

×
11
// Modules
×
12
const {resolve: pathResolve, join: pathJoin, dirname, parse: pathParse} = require('path'),
×
13
        {readFileSync} = require('fs'),
×
14
        yargs = require('yargs'),
×
15
        findUp = require('find-up'),
×
16
        stripJsonComments = require('strip-json-comments'),
×
17
        {isObject, isArray, isString, isBoolean} = require('is-it-type'),
×
18
        assert = require('simple-invariant');
×
19

×
20
// CLI
×
21

×
22
// Throw unhandled rejections
×
23
process.on('unhandledRejection', (err) => {
×
24
        throw err;
×
25
});
×
26

×
27
// Load config file
×
28
const configPath = findUp.sync(['.livepackrc', 'livepack.config.json', 'livepack.config.js']);
×
29
let config;
×
30
if (configPath) {
×
31
        if (/\.js$/.test(configPath)) {
×
32
                config = require(configPath); // eslint-disable-line global-require, import/no-dynamic-require
×
33
        } else {
×
34
                config = JSON.parse(stripJsonComments(readFileSync(configPath, 'utf8')));
×
35
        }
×
36
} else {
×
37
        config = {};
×
38
}
×
39

×
40
// Parse args
×
41
const {argv} = yargs
×
42
        .config(config)
×
43
        .command(
×
44
                '$0',
×
45
                'livepack <input path(s)..> -o <output dir path> [options]',
×
46
                () => {},
×
47
                (_argv) => {
×
48
                        const {input} = _argv;
×
49
                        if (input === undefined) {
×
50
                                const inputs = _argv._;
×
51
                                assert(inputs.length > 0, 'Must specify input file');
×
52
                                _argv.input = inputs;
×
53
                        }
×
54
                }
×
55
        )
×
56
        .alias('help', 'h')
×
57
        .alias('version', 'v')
×
58
        .option('input', {
×
59
                // Only used in config file
×
60
                alias: 'inputs',
×
61
                description: 'Input file path',
×
62
                type: 'string',
×
63
                hidden: true
×
64
        })
×
65
        .option('output', {
×
66
                alias: 'o',
×
67
                description: 'Output directory path',
×
68
                demandOption: true,
×
69
                type: 'string'
×
70
        })
×
71
        .option('format', {
×
72
                alias: 'f',
×
73
                description: 'Output format',
×
74
                type: 'string',
×
75
                choices: ['esm', 'cjs'],
×
76
                default: 'esm'
×
77
        })
×
78
        .option('ext', {
×
79
                description: 'JS file extension',
×
80
                type: 'string',
×
81
                default: 'js'
×
82
        })
×
83
        .option('map-ext', {
×
84
                description: 'Source map file extension',
×
85
                type: 'string',
×
86
                default: 'map'
×
87
        })
×
88
        .option('minify', {
×
89
                alias: 'm',
×
90
                description: 'Minify output',
×
91
                type: 'boolean',
×
92
                default: false
×
93
        })
×
94
        .option('inline', {
×
95
                type: 'boolean',
×
96
                description: 'Inline code where possible',
×
97
                default: true
×
98
        })
×
99
        .option('mangle', {
×
100
                type: 'boolean',
×
101
                description: 'Mangle var names'
×
102
        })
×
103
        .option('comments', {
×
104
                type: 'boolean',
×
105
                description: 'Keep comments in output'
×
106
        })
×
107
        .option('entry-chunk-name', {
×
108
                type: 'string',
×
109
                description: 'Template for entry point chunk names'
×
110
        })
×
111
        .option('split-chunk-name', {
×
112
                type: 'string',
×
113
                description: 'Template for split chunk names'
×
114
        })
×
115
        .option('common-chunk-name', {
×
116
                type: 'string',
×
117
                description: 'Template for common chunk names'
×
118
        })
×
119
        .option('source-maps', {
×
120
                alias: 's',
×
121
                description: 'Create source maps',
×
122
                defaultDescription: 'false',
×
123
                type: 'string',
×
124
                coerce(val) {
×
125
                        if (val === 'inline' || isBoolean(val) || val === undefined) return val;
×
126
                        if (val === '') return true;
×
127
                        throw new Error("--source-maps option should have no value or 'inline'");
×
128
                }
×
129
        })
×
130
        .option('exec', {
×
131
                description: 'Output executable script',
×
132
                type: 'boolean',
×
133
                default: true
×
134
        })
×
135
        .option('esm', {
×
136
                description: 'ES modules source',
×
137
                type: 'boolean',
×
138
                default: false
×
139
        })
×
140
        .option('jsx', {
×
141
                description: 'JSX source',
×
142
                type: 'boolean',
×
143
                default: false
×
144
        })
×
145
        .option('stats', {
×
146
                description: 'Output stats file',
×
147
                defaultDescription: 'false',
×
148
                type: 'string',
×
149
                coerce(val) {
×
150
                        if (val === '') return true;
×
151
                        if (isString(val) || isBoolean(val) || val === undefined) return val;
×
152
                        throw new Error('--stats option should have no value or string for name of stats file');
×
153
                }
×
154
        })
×
155
        .option('babel-cache', {
×
156
                description: 'Enable Babel cache',
×
157
                type: 'boolean',
×
158
                default: true
×
159
        })
×
160
        .option('debug', {
×
161
                description: 'Output debug info',
×
162
                type: 'boolean',
×
163
                default: false,
×
164
                hidden: true
×
165
        });
×
166

×
167
// The following is all after yargs option parsing, rather than at top of file,
×
168
// to avoid slow response for `livepack --help` or a command with missing/invalid options.
×
169

×
170
// Catalog globals etc
×
171
require('./init/index.js');
×
172

×
173
// Import dependencies required for serialize
×
174
const {writeFile, mkdir} = require('fs/promises'),
×
175
        {serializeEntries} = require('./serialize/index.js'),
×
176
        {DEFAULT_OUTPUT_FILENAME} = require('./shared/constants.js');
×
177

×
178
// Switch back to global module cache
×
179
useGlobalModuleCache();
×
180

×
181
// Register Babel transform to track scopes
×
182
const register = require('./register/index.js');
×
183

×
184
register({
×
185
        esm: argv.esm,
×
186
        jsx: argv.jsx,
×
187
        cache: argv.babelCache
×
188
});
×
189

×
190
// Serialize
×
191
(async () => {
×
192
        // Determine output path
×
193
        const outPath = pathResolve(argv.output);
×
194

×
195
        // Conform inputs array to object
×
196
        let inputs = argv.input;
×
197
        if (isString(inputs)) {
×
198
                inputs = {[DEFAULT_OUTPUT_FILENAME]: inputs};
×
199
        } else if (isArray(inputs)) {
×
200
                const inputsObj = {};
×
201
                for (const path of inputs) {
×
202
                        assert(isString(path), '`input` paths must be strings');
×
203
                        const {name} = pathParse(path);
×
204
                        assert(!inputsObj[name], `Multiple input files with same name '${name}'`);
×
205
                        inputsObj[name] = path;
×
206
                }
×
207
                inputs = inputsObj;
×
208
        } else {
×
209
                assert(isObject(inputs), '`input` must be a string, object or array');
×
210
                for (const [name, path] of Object.entries(inputs)) {
×
211
                        assert(isString(name), '`input` keys must be strings');
×
212
                        assert(isString(path), '`input` paths must be strings');
×
213
                }
×
214
        }
×
215

×
216
        // Load sources
×
217
        const entries = {};
×
218
        await Promise.all(
×
219
                Object.entries(inputs).map(async ([name, pathOriginal]) => {
×
220
                        const path = pathResolve(pathOriginal);
×
221

×
222
                        let entry;
×
223
                        try {
×
224
                                entry = require(path); // eslint-disable-line global-require, import/no-dynamic-require
×
225
                        } catch (err) {
×
226
                                if (
×
227
                                        err && err.code === 'MODULE_NOT_FOUND'
×
228
                                        && err.message.split('\n')[0] === `Cannot find module '${path}'`
×
229
                                        && err.requireStack
×
230
                                        && err.requireStack.length === 1
×
231
                                        && err.requireStack[0] === __filename
×
232
                                ) {
×
233
                                        throw new Error(`Cannot load input file '${pathOriginal}'`);
×
234
                                }
×
235
                                throw err;
×
236
                        }
×
237

×
238
                        if (entry && entry.__esModule) entry = entry.default;
×
239

×
240
                        // Await Promise value
×
241
                        entry = await entry;
×
242

×
243
                        entries[name] = entry;
×
244
                })
×
245
        );
×
246

×
247
        // Serialize
×
248
        const files = serializeEntries(entries, {
×
249
                format: argv.format,
×
250
                ext: argv.ext,
×
251
                mapExt: argv.mapExt,
×
252
                exec: argv.exec,
×
253
                minify: argv.minify,
×
254
                inline: argv.inline,
×
255
                mangle: argv.mangle,
×
256
                comments: argv.comments,
×
257
                entryChunkName: argv.entryChunkName,
×
258
                splitChunkName: argv.splitChunkName,
×
259
                commonChunkName: argv.commonChunkName,
×
260
                sourceMaps: argv.sourceMaps || false,
×
261
                stats: argv.stats,
×
262
                outputDir: argv.sourceMaps ? outPath : undefined,
×
263
                debug: argv.debug
×
264
        });
×
265

×
266
        // Output files
×
267
        for (const {filename, content} of files) {
×
268
                const path = pathJoin(outPath, filename);
×
269
                await mkdir(dirname(path), {recursive: true});
×
270
                await writeFile(path, content);
×
271
        }
×
272
})();
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc