@startupjs/cli 0.56.0-alpha.0 → 0.56.0-alpha.13

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.
package/index.js CHANGED
@@ -1,673 +1,36 @@
1
- const commander = require('commander')
2
- const execa = require('execa')
3
- const path = require('path')
4
- const fs = require('fs')
5
- const template = require('lodash/template')
6
- const CLI_VERSION = require('./package.json').version
1
+ import { Command } from 'commander'
2
+ import url from 'url'
3
+ import { dirname, join } from 'path'
4
+ import { readFileSync } from 'fs'
5
+ import * as commands from './commands/index.js'
7
6
 
8
- const IS_PRERELEASE = /(?:alpha|canary)/.test(CLI_VERSION)
9
- const STARTUPJS_VERSION = IS_PRERELEASE ? `^${CLI_VERSION.replace(/\.\d+$/, '.0')}` : 'latest'
7
+ const __filename = url.fileURLToPath(import.meta.url)
8
+ const packageJson = JSON.parse(readFileSync(join(dirname(__filename), 'package.json')))
10
9
 
11
- let PATCHES_DIR
12
- try {
13
- PATCHES_DIR = path.join(
14
- path.dirname(require.resolve('@startupjs/patches')),
15
- 'patches'
16
- )
17
- // patch-package requires the path to be relative
18
- PATCHES_DIR = path.relative(process.cwd(), PATCHES_DIR)
19
- } catch (err) {
20
- console.error(err)
21
- console.error('ERROR!!! Patches packages not found. Falling back to local patches folder')
22
- PATCHES_DIR = './patches'
23
- }
24
-
25
- let PM_SCRIPTS_PATH
26
- try {
27
- PM_SCRIPTS_PATH = path.join(
28
- path.dirname(require.resolve('@startupjs/pm')),
29
- 'scripts.sh'
30
- )
31
- } catch (err) {
32
- console.error(err)
33
- console.error('ERROR!!! @startupjs/pm package wasn\'t found.')
34
- }
35
-
36
- let PATCHES_GESTURE_HANDLER_DIR
37
- try {
38
- PATCHES_GESTURE_HANDLER_DIR = path.join(
39
- path.dirname(require.resolve('@startupjs/patches')),
40
- 'patches_gestureHandler'
41
- )
42
- // patch-package requires the path to be relative
43
- PATCHES_GESTURE_HANDLER_DIR = path.relative(process.cwd(), PATCHES_GESTURE_HANDLER_DIR)
44
- } catch (err) {
45
- console.error(err)
46
- console.error('ERROR!!! Gesture handler patches not found.')
47
- }
48
-
49
- const LINK = !!process.env.LINK
50
- const LOCAL_DIR = process.env.LOCAL_DIR || '.'
51
-
52
- const DEPENDENCIES = [
53
- // Install alpha version of startupjs when running the alpha of cli
54
- `startupjs@${STARTUPJS_VERSION}`,
55
- 'react-native-svg@^14.0.0',
56
- 'nconf@^0.10.0',
57
- 'react',
58
- 'react-dom',
59
- 'axios@^0.26.0' // For making AJAX requests
60
- ]
61
-
62
- const DEV_DEPENDENCIES = [
63
- '@babel/eslint-parser',
64
- 'eslint@latest',
65
- 'eslint-config-standard',
66
- 'eslint-config-standard-react',
67
- 'eslint-plugin-import',
68
- 'eslint-plugin-import-helpers',
69
- 'eslint-plugin-n',
70
- 'eslint-plugin-promise',
71
- 'eslint-plugin-react',
72
- 'eslint-plugin-react-pug',
73
- 'eslint-plugin-react-hooks',
74
- 'eslint-plugin-standard',
75
- 'husky@^4.3.0',
76
- 'lint-staged'
77
- ]
78
-
79
- const REMOVE_DEPENDENCIES = [
80
- '@babel/core',
81
- '@babel/runtime',
82
- '@react-native/eslint-config',
83
- 'metro-react-native-babel-preset'
84
- ]
85
-
86
- const REMOVE_FILES = [
87
- '.prettierrc.js',
88
- '.eslintrc.js',
89
- '.flowconfig',
90
- 'App.js',
91
- 'babel.config.js',
92
- 'metro.config.js'
93
- ]
94
-
95
- const SCRIPTS_ORIG = {}
96
-
97
- // Development
98
-
99
- SCRIPTS_ORIG.start = ({ inspect } = {}) => oneLine(`
100
- npx concurrently
101
- "${SCRIPTS_ORIG.web}"
102
- "${SCRIPTS_ORIG.server({ inspect })}"
103
- `)
104
-
105
- // Web
106
-
107
- SCRIPTS_ORIG.web = oneLine(`
108
- npx cross-env WEBPACK_DEV=1
109
- npx webpack-dev-server --config webpack.web.config.cjs
110
- `)
111
-
112
- // Server
113
-
114
- SCRIPTS_ORIG.server = ({ inspect } = {}) => oneLine(`
115
- node
116
- ${inspect ? '--inspect' : ''}
117
- --watch
118
- --experimental-detect-module
119
- server.js
120
- `)
121
-
122
- // Production
123
-
124
- SCRIPTS_ORIG.build = ({ async } = {}) => oneLine(`
125
- npx rimraf ./build &&
126
- ${async ? 'npx cross-env ASYNC=1' : ''}
127
- npx webpack --config webpack.web.config.cjs
128
- `)
129
-
130
- SCRIPTS_ORIG.startProduction = oneLine(`
131
- npx cross-env NODE_ENV=production
132
- node --experimental-detect-module server.js
133
- `)
134
-
135
- // Etc
136
-
137
- SCRIPTS_ORIG.patchPackage = () => oneLine(`
138
- npx patch-package --patch-dir ${PATCHES_DIR} && ${SCRIPTS_ORIG.patchGestureHandler()}
139
- `)
140
-
141
- SCRIPTS_ORIG.patchGestureHandler = () => PATCHES_GESTURE_HANDLER_DIR
142
- ? oneLine(`
143
- (cat package.json | grep -q react-native-gesture-handler && npx patch-package --patch-dir ${PATCHES_GESTURE_HANDLER_DIR} || true)
144
- `)
145
- : 'true'
146
-
147
- SCRIPTS_ORIG.postinstall = () => oneLine(`
148
- ${SCRIPTS_ORIG.patchPackage()}
149
- `)
150
-
151
- SCRIPTS_ORIG.testE2E = ({ inspect } = {}) => {
152
- return oneLine(`
153
- startupjs build --async && npx concurrently "startupjs start-production" "sleep 15s && npx playwright test $@" --kill-others --success first
154
- `)
155
- }
156
-
157
- SCRIPTS_ORIG.codegenTestE2E = ({ inspect } = {}) => {
158
- return oneLine(`
159
- startupjs build --async && npx concurrently "startupjs start-production" "npx playwright codegen $@"
160
- `)
161
- }
162
-
163
- const SCRIPTS = {
164
- start: 'startupjs start',
165
- metro: 'react-native start --reset-cache',
166
- web: 'startupjs web',
167
- server: 'startupjs server',
168
- postinstall: 'startupjs postinstall',
169
- adb: 'adb reverse tcp:8081 tcp:8081 && adb reverse tcp:3000 tcp:3000 && adb reverse tcp:3010 tcp:3010',
170
- 'log-android-color': 'react-native log-android | ccze -m ansi -C -o nolookups',
171
- 'log-android': 'hash ccze 2>/dev/null && npm run log-android-color || (echo "WARNING! Falling back to plain logging. For colored logs install ccze - brew install ccze" && react-native log-android)',
172
- android: 'react-native run-android && (npm run adb || true) && npm run log-android',
173
- 'android-release': 'react-native run-android --variant Release',
174
- ios: 'react-native run-ios',
175
- 'ios-release': 'react-native run-ios --configuration Release',
176
- build: 'startupjs build --async',
177
- 'start-production': 'startupjs start-production',
178
- 'test-e2e': 'startupjs test-e2e',
179
- 'codegen-test-e2e': 'startupjs codegen-test-e2e'
180
- }
181
-
182
- const DEFAULT_TEMPLATE = 'ui'
183
- const DEFAULT_YARN_VERSION = '4'
184
- const TEMPLATES = {
185
- simple: {
186
- subTemplates: ['simple']
187
- },
188
- routing: {
189
- subTemplates: ['simple', 'routing'],
190
- packages: [
191
- // === START APP PEER DEPS ===
192
- 'react-native-restart@^0.0.22'
193
- // === END APP PEER DEPS ===
194
- ]
195
- },
196
- ui: {
197
- subTemplates: ['simple', 'routing', 'ui'],
198
- packages: [
199
- // === START APP PEER DEPS ===
200
- 'react-native-restart@^0.0.22',
201
- // === END APP PEER DEPS ===
202
-
203
- // === START UI PEER PEDS ===
204
- `@startupjs/ui@${STARTUPJS_VERSION}`,
205
- '@react-native-picker/picker@^1.16.1',
206
- 'react-native-gesture-handler@^2.14.0',
207
- 'react-native-pager-view@^6.2.0'
208
- // === END UI PEER DEPS ===
209
- ]
210
- }
211
- }
212
-
213
- let templatesPath
214
-
215
- // ----- init
216
-
217
- commander
218
- .command('init <projectName>')
219
- .description('bootstrap a new startupjs application')
220
- .option('--react-native <semver>', 'Use a particular semver of React Native as a template', 'latest')
221
- .option('-t, --template <name>', 'Which startupjs template to use to bootstrap the project', DEFAULT_TEMPLATE)
222
- .option('-y, --yarn <semver>', 'Use a particular semver of yarn', DEFAULT_YARN_VERSION)
223
- .action(async (projectName, { reactNative, template, yarn }) => {
224
- console.log('> run npx', projectName, { reactNative, template, yarn })
225
-
226
- // setup corepack
227
- try {
228
- await execa.command(
229
- `${path.join(__dirname, 'corepack.sh')} ${yarn}`,
230
- { shell: true, stdio: 'inherit' }
231
- )
232
- } catch (e) {
233
- throw Error('Setup corepack: ', e)
234
- }
235
-
236
- const projectPath = path.join(process.cwd(), LOCAL_DIR, projectName)
237
-
238
- // check if template exists
239
- if (!TEMPLATES[template]) {
240
- throw Error(`Template '${template}' doesn't exist. Templates available: ${Object.keys(TEMPLATES).join(', ')}`)
241
- }
242
-
243
- if (LOCAL_DIR !== '.') {
244
- await execa(
245
- 'mkdir',
246
- ['-p', LOCAL_DIR],
247
- { stdio: 'inherit' }
248
- )
249
- }
250
-
251
- // init react-native application
252
- await execa('npx', [
253
- '--yes',
254
- `react-native${'@' + reactNative}`,
255
- 'init',
256
- '--skip-install',
257
- projectName
258
- ].concat(['--version', reactNative]), {
259
- cwd: path.join(process.cwd(), LOCAL_DIR),
260
- stdio: 'inherit'
261
- })
262
-
263
- // specify yarn version
264
- await execa('rm', ['-rf', 'node_modules'], {
265
- cwd: projectPath,
266
- stdio: 'inherit'
267
- })
268
- await execa('rm', ['-f', 'yarn.lock'], {
269
- cwd: projectPath,
270
- stdio: 'inherit'
271
- })
272
- await execa('corepack', ['use', `yarn@${yarn}`], {
273
- cwd: projectPath,
274
- stdio: 'inherit'
275
- })
276
-
277
- // remove extra files which are covered by startupjs core
278
- if (REMOVE_FILES.length) {
279
- await execa('rm', ['-f'].concat(REMOVE_FILES), {
280
- cwd: projectPath,
281
- stdio: 'inherit'
282
- })
283
- }
284
-
285
- await execa('yarn', ['config', 'set', 'nodeLinker', 'node-modules'], {
286
- cwd: projectPath,
287
- stdio: 'inherit'
288
- })
289
-
290
- // remove extra dependencies which are covered by startupjs core
291
- if (REMOVE_DEPENDENCIES.length) {
292
- await execa('yarn', ['remove'].concat(REMOVE_DEPENDENCIES), {
293
- cwd: projectPath,
294
- stdio: 'inherit'
295
- })
296
- }
297
-
298
- // copy additional startupjs template files over react-native ones
299
- console.log(`> Copy template '${template}'`)
300
- for (const subTemplate of TEMPLATES[template].subTemplates) {
301
- const subTemplatePath = path.join(templatesPath, subTemplate)
302
- await recursivelyCopyFiles(subTemplatePath, projectPath)
303
- }
304
-
305
- // install startupjs dependencies
306
- await execa('yarn', ['add'].concat(DEPENDENCIES).concat(TEMPLATES[template].packages || []), {
307
- cwd: projectPath,
308
- stdio: 'inherit'
309
- })
310
-
311
- if (LINK) {
312
- // TODO: Link startupjs packages. ref:
313
- // https://stackoverflow.com/questions/48681642/yarn-workspaces-and-yarn-link
314
- console.log('> TODO: Link startupjs packages for local install')
315
- }
316
-
317
- if (DEV_DEPENDENCIES.length) {
318
- // install startupjs devDependencies
319
- await execa('yarn', ['add', '-D'].concat(DEV_DEPENDENCIES), {
320
- cwd: projectPath,
321
- stdio: 'inherit'
322
- })
323
- }
324
-
325
- console.log('> Update config.json')
326
- updateConfigJson(projectPath, { projectName })
327
-
328
- console.log('> Patch package.json')
329
- patchPackageJson(projectPath)
330
-
331
- console.log('> Add additional things to .gitignore')
332
- appendGitignore(projectPath)
333
-
334
- console.log('> Apply module patches from /patches/ folder')
335
- await execa('yarn', ['postinstall'], {
336
- cwd: projectPath,
337
- stdio: 'inherit'
338
- })
339
-
340
- if (process.platform === 'darwin') {
341
- await execa('pod', ['install'], {
342
- cwd: path.join(projectPath, 'ios'),
343
- stdio: 'inherit'
344
- })
345
- }
346
-
347
- if (template === 'ui') {
348
- await execa('startupjs', ['link'], {
349
- cwd: projectPath,
350
- stdio: 'inherit'
351
- })
352
- }
353
-
354
- console.log(getSuccessInstructions(projectName))
355
- })
356
-
357
- // ----- init
358
-
359
- commander
360
- .command('start')
361
- .description('Run "startupjs web" and "startupjs server" at the same time.')
362
- .option('-i, --inspect', 'Use node --inspect')
363
- .action(async (options) => {
364
- await execa.command(
365
- SCRIPTS_ORIG.start(options),
366
- { stdio: 'inherit', shell: true }
367
- )
368
- })
369
-
370
- commander
371
- .command('test-e2e')
372
- .description('Run e2e tests')
373
- .action(async (options) => {
374
- await execa.command(
375
- SCRIPTS_ORIG.testE2E(options),
376
- { stdio: 'inherit', shell: true }
377
- )
378
- })
379
-
380
- commander
381
- .command('codegen-test-e2e')
382
- .description('Run codegen for e2e tests')
383
- .action(async (options) => {
384
- await execa.command(
385
- SCRIPTS_ORIG.codegenTestE2E(options),
386
- { stdio: 'inherit', shell: true }
387
- )
388
- })
389
-
390
- commander
391
- .command('web')
392
- .description('Compile (with webpack) and run web')
393
- .action(async (options) => {
394
- await execa.command(
395
- SCRIPTS_ORIG.web,
396
- { stdio: 'inherit', shell: true }
397
- )
398
- })
399
-
400
- commander
401
- .command('server')
402
- .description('Compile (with webpack) and run server')
403
- .option('-i, --inspect', 'Use node --inspect')
404
- .action(async (options) => {
405
- await execa.command(
406
- SCRIPTS_ORIG.server(options),
407
- { stdio: 'inherit', shell: true }
408
- )
409
- })
410
-
411
- commander
412
- .command('build')
413
- .description('Build web bundles')
414
- .option('-a, --async', 'Build with splitting code into async chunks loaded dynamically')
415
- .action(async (options) => {
416
- await execa.command(
417
- SCRIPTS_ORIG.build(options),
418
- { stdio: 'inherit', shell: true }
419
- )
420
- })
421
-
422
- commander
423
- .command('start-production')
424
- .description('Start production')
425
- .action(async (options) => {
426
- await execa.command(
427
- SCRIPTS_ORIG.startProduction,
428
- { stdio: 'inherit', shell: true }
429
- )
430
- })
431
-
432
- commander
433
- .command('patch-package')
434
- .description('Apply required patches to libraries used by startupjs')
435
- .action(async (options) => {
436
- await execa.command(
437
- SCRIPTS_ORIG.patchPackage(options),
438
- { stdio: 'inherit', shell: true }
439
- )
440
- })
441
-
442
- commander
443
- .command('link')
444
- .description('Links files')
445
- .action(async () => {
446
- // this is important because ./link contains files that are initialized on require. Thus, 'glob' in ./linc/path does not work correctly when required in a header
447
- const link = require('./link')
448
- link()
449
- })
450
-
451
- commander
452
- .command('android-link')
453
- .description('Links android files')
454
- .action(async () => {
455
- console.warn('"startupjs android-link" is deprecated. Use "startupjs link" instead.')
456
- // this is important because ./link contains files that are initialized on require. Thus, 'glob' in ./linc/path does not work correctly when required in a header
457
- const link = require('./link')
458
- link()
459
- })
460
-
461
- commander
462
- .command('postinstall')
463
- .description('Run startupjs postinstall scripts')
464
- .action(async (options) => {
465
- await execa.command(
466
- SCRIPTS_ORIG.postinstall(options),
467
- { stdio: 'inherit', shell: true }
468
- )
469
- })
10
+ const program = new Command()
11
+ .usage('<command> [options]')
12
+ .version(packageJson.version, '-v, --version', 'output the version of startupjs cli utility in this project')
470
13
 
471
- // ----- project management commands
14
+ async function run () {
15
+ for (const command of Object.values(commands)) {
16
+ const { name, description, options = [], action } = command
472
17
 
473
- commander
474
- .command('init-pm')
475
- .description('Create a new project on github from template')
476
- .action(async () => {
477
- await execa.command(`${PM_SCRIPTS_PATH} init-pm`, { shell: true, stdio: 'inherit' })
478
- addPmScriptsToPackageJson() // add `yarn pm` and `yarn task` to package.json/scripts
479
- })
480
-
481
- commander
482
- .command('task <issueNumber>')
483
- .description('Create a task branch (or just switch to it if it already exists)')
484
- .action(async (issueNumber) => {
485
- await execa.command(`${PM_SCRIPTS_PATH} task ${issueNumber}`, { shell: true, stdio: 'inherit' })
486
- })
487
-
488
- commander
489
- .command('pr [issueNumber]')
490
- .description('Make PR for this task (or re-request review if it already exists)')
491
- .action(async (issueNumber = '') => {
492
- await execa.command(`${PM_SCRIPTS_PATH} pr ${issueNumber}`, { shell: true, stdio: 'inherit' })
493
- })
494
-
495
- // ----- helpers
496
-
497
- async function recursivelyCopyFiles (sourcePath, targetPath) {
498
- const fileNames = fs.readdirSync(sourcePath)
499
-
500
- if (fileNames.length === 0) return
501
-
502
- for (const fileName of fileNames) {
503
- const filePath = path.join(sourcePath, fileName)
504
- if (fs.lstatSync(filePath).isDirectory()) {
505
- const subTargetPath = path.join(targetPath, fileName)
506
- await execa(
507
- 'mkdir',
508
- ['-p', subTargetPath],
509
- { stdio: 'inherit' }
510
- )
511
- await recursivelyCopyFiles(filePath, subTargetPath)
512
- } else {
513
- await execa(
514
- 'cp',
515
- [filePath, targetPath],
516
- { stdio: 'inherit' }
517
- )
18
+ if (program.commands.find(cmd => cmd.name() === name)) {
19
+ throw new Error(`Attempted to override an already registered command: ${name}`)
518
20
  }
519
- }
520
- }
521
21
 
522
- function patchPackageJson (projectPath) {
523
- const packageJSONPath = path.join(projectPath, 'package.json')
524
- const packageJSON = JSON.parse(fs.readFileSync(packageJSONPath).toString())
22
+ const cmd = program.command(name)
23
+ if (description) cmd.description(description)
525
24
 
526
- delete packageJSON.scripts.test
527
- delete packageJSON.devDependencies['babel-jest']
528
- delete packageJSON.devDependencies['react-test-renderer']
529
- delete packageJSON.devDependencies.jest
530
-
531
- packageJSON.scripts = {
532
- ...packageJSON.scripts,
533
- ...SCRIPTS
534
- }
535
-
536
- packageJSON['lint-staged'] = {
537
- '*.{js,jsx}': [
538
- 'eslint --fix',
539
- 'git add'
540
- ]
541
- }
542
-
543
- packageJSON.husky = {
544
- hooks: {
545
- 'pre-commit': 'lint-staged'
25
+ for (const option of options) {
26
+ const { name, description } = option
27
+ cmd.option(name, description)
546
28
  }
547
- }
548
29
 
549
- // FIXME: We can't use type=module now, because metro does not support ESM
550
- // and does not provide ability to pass .cjs config.
551
- // packageJSON.type = 'module'
552
- packageJSON.sideEffects = ['*.css', '*.styl']
553
-
554
- fs.writeFileSync(
555
- packageJSONPath,
556
- `${JSON.stringify(packageJSON, null, 2)}\n`
557
- )
558
- }
559
-
560
- function addPmScriptsToPackageJson () {
561
- const projectPath = process.cwd()
562
- const packageJSONPath = path.join(projectPath, 'package.json')
563
- const packageJSON = JSON.parse(fs.readFileSync(packageJSONPath).toString())
564
-
565
- packageJSON.scripts = {
566
- ...packageJSON.scripts,
567
- task: 'npx startupjs task',
568
- pr: 'npx startupjs pr'
569
- }
570
-
571
- fs.writeFileSync(
572
- packageJSONPath,
573
- `${JSON.stringify(packageJSON, null, 2)}\n`
574
- )
575
- }
576
-
577
- function appendGitignore (projectPath) {
578
- const gitignorePath = path.join(projectPath, '.gitignore')
579
- let gitignore = fs.readFileSync(gitignorePath).toString()
580
-
581
- gitignore += `
582
- # DB data
583
- /data/
584
- # Protection from accidentally commiting private npm keys to a public repo
585
- .npmrc
586
- # Mongo data when running in a docker dev container
587
- /.mongo
588
- # yarn
589
- .yarn/
590
- # sqlite
591
- sqlite.db
592
- `.replace(/\n\s+/g, '\n')
593
-
594
- fs.writeFileSync(gitignorePath, gitignore)
595
- }
596
-
597
- function updateConfigJson (projectPath, options) {
598
- const configJsonPath = path.join(projectPath, 'config.json')
599
- let configJson = fs.readFileSync(configJsonPath).toString()
600
-
601
- try {
602
- const templateFn = template(configJson)
603
- const sessionSecret = generateRandomString(32)
604
- configJson = templateFn({ ...options, sessionSecret })
605
- } catch (e) {
606
- console.log(
607
- '\x1b[31m' +
608
- 'config.json has not been updated, update it manually!' +
609
- '\x1b[0m'
610
- )
30
+ cmd.action(action)
611
31
  }
612
32
 
613
- fs.writeFileSync(
614
- configJsonPath,
615
- configJson
616
- )
617
- }
618
-
619
- function generateRandomString (length = 0) {
620
- let result = ''
621
- const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
622
- const charactersLength = characters.length
623
-
624
- for (let i = 0; i < length; i++) {
625
- result += characters.charAt(
626
- Math.floor(
627
- Math.random() * charactersLength
628
- )
629
- )
630
- }
631
- return result
33
+ program.parse(process.argv)
632
34
  }
633
35
 
634
- function getSuccessInstructions (projectName) {
635
- return `
636
- StartupJS installation successful!
637
-
638
- To use private packages, log in via yarn npm login.
639
-
640
- INSTRUCTIONS
641
-
642
- $ cd ${projectName}
643
-
644
- Run each command in a separate terminal tab:
645
-
646
- 1. Start server:
647
-
648
- $ yarn server
649
-
650
- 2. Start web:
651
-
652
- $ yarn web
653
-
654
- and go to http://localhost:3000
655
-
656
- 3. Start native:
657
-
658
- $ yarn metro
659
- $ yarn android
660
- $ yarn ios
661
- `
662
- }
663
-
664
- // Replace all new lines with spaces to properly handle cli-commands
665
- function oneLine (str) {
666
- return str.replace(/\s+/g, ' ')
667
- }
668
-
669
- exports.run = (options = {}) => {
670
- if (!options.templatesPath) throw Error('templatesPath not found!')
671
- templatesPath = options.templatesPath
672
- commander.parse(process.argv)
673
- }
36
+ export { run }