@form8ion/javascript 1.1.1 → 2.0.0

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/lib/index.es.js CHANGED
@@ -1,15 +1,97 @@
1
+ import { questionNames as questionNames$2, questions } from '@travi/language-scaffolder-prompts';
1
2
  import deepmerge from 'deepmerge';
2
- import { validateOptions, scaffoldChoice } from '@form8ion/javascript-core';
3
+ import { validateOptions, scaffoldChoice, dialects, projectTypes, packageManagers } from '@form8ion/javascript-core';
3
4
  import { scaffold as scaffold$1 } from '@form8ion/codecov';
4
5
  import { promises } from 'fs';
5
6
  import * as joi from '@hapi/joi';
6
7
  import { Separator } from 'inquirer';
7
- import { prompt } from '@form8ion/overridable-prompts';
8
+ import { prompt as prompt$1 } from '@form8ion/overridable-prompts';
9
+ import { warn, info } from '@travi/cli-messages';
10
+ import { lift } from '@form8ion/lift-javascript';
11
+ import { scaffold as scaffold$5 } from '@form8ion/commit-convention';
12
+ import hoek from '@hapi/hoek';
13
+ import execa from 'execa';
14
+ import { stringify } from 'ini';
15
+ import { EOL } from 'os';
16
+ import validatePackageName from 'validate-npm-package-name';
17
+ import { scaffold as scaffold$2 } from '@form8ion/rollup';
18
+ import mustache from 'mustache';
19
+ import camelcase from 'camelcase';
20
+ import makeDir from 'make-dir';
21
+ import touch from 'touch';
22
+ import { resolve } from 'path';
23
+ import { scaffold as scaffold$4 } from '@form8ion/husky';
24
+ import { scaffold as scaffold$3 } from '@form8ion/eslint';
8
25
 
9
- function scaffold () {
10
- return undefined;
26
+ function ownKeys(object, enumerableOnly) {
27
+ var keys = Object.keys(object);
28
+
29
+ if (Object.getOwnPropertySymbols) {
30
+ var symbols = Object.getOwnPropertySymbols(object);
31
+
32
+ if (enumerableOnly) {
33
+ symbols = symbols.filter(function (sym) {
34
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
35
+ });
36
+ }
37
+
38
+ keys.push.apply(keys, symbols);
39
+ }
40
+
41
+ return keys;
42
+ }
43
+
44
+ function _objectSpread2(target) {
45
+ for (var i = 1; i < arguments.length; i++) {
46
+ var source = arguments[i] != null ? arguments[i] : {};
47
+
48
+ if (i % 2) {
49
+ ownKeys(Object(source), true).forEach(function (key) {
50
+ _defineProperty(target, key, source[key]);
51
+ });
52
+ } else if (Object.getOwnPropertyDescriptors) {
53
+ Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
54
+ } else {
55
+ ownKeys(Object(source)).forEach(function (key) {
56
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
57
+ });
58
+ }
59
+ }
60
+
61
+ return target;
62
+ }
63
+
64
+ function _defineProperty(obj, key, value) {
65
+ if (key in obj) {
66
+ Object.defineProperty(obj, key, {
67
+ value: value,
68
+ enumerable: true,
69
+ configurable: true,
70
+ writable: true
71
+ });
72
+ } else {
73
+ obj[key] = value;
74
+ }
75
+
76
+ return obj;
11
77
  }
12
78
 
79
+ const questionNames$1 = {
80
+ UNIT_TEST_FRAMEWORK: 'unitTestFramework',
81
+ NODE_VERSION_CATEGORY: 'nodeVersionCategory',
82
+ PACKAGE_MANAGER: 'packageManager',
83
+ PROJECT_TYPE: 'projectType',
84
+ PROJECT_TYPE_CHOICE: 'projectTypeChoice',
85
+ SHOULD_BE_SCOPED: 'shouldBeScoped',
86
+ SCOPE: 'scope',
87
+ AUTHOR_NAME: 'authorName',
88
+ AUTHOR_EMAIL: 'authorEmail',
89
+ AUTHOR_URL: 'authorUrl',
90
+ HOST: 'host',
91
+ CONFIGURE_LINTING: 'configureLint',
92
+ DIALECT: 'dialect'
93
+ };
94
+
13
95
  async function scaffoldC8 ({
14
96
  projectRoot
15
97
  }) {
@@ -38,7 +120,7 @@ async function scaffoldCoverage ({
38
120
  }) {
39
121
  return deepmerge(await scaffoldC8({
40
122
  projectRoot
41
- }), scaffold$1({
123
+ }), await scaffold$1({
42
124
  vcs,
43
125
  visibility
44
126
  }));
@@ -48,25 +130,21 @@ const unitTestFrameworksSchema = joi.object().required().pattern(/^/, joi.object
48
130
  scaffolder: joi.func().arity(1).required()
49
131
  }));
50
132
 
51
- const questionNames = {
52
- UNIT_TEST_FRAMEWORK: 'unitTestFramework'
53
- };
54
-
55
133
  async function chooseFramework ({
56
134
  frameworks,
57
135
  decisions
58
136
  }) {
59
137
  if (!Object.keys(frameworks).length) return 'Other';
60
- const answers = await prompt([{
61
- name: questionNames.UNIT_TEST_FRAMEWORK,
138
+ const answers = await prompt$1([{
139
+ name: questionNames$1.UNIT_TEST_FRAMEWORK,
62
140
  type: 'list',
63
141
  message: 'Which type of unit testing framework should be used?',
64
142
  choices: [...Object.keys(frameworks), new Separator(), 'Other']
65
143
  }], decisions);
66
- return answers[questionNames.UNIT_TEST_FRAMEWORK];
144
+ return answers[questionNames$1.UNIT_TEST_FRAMEWORK];
67
145
  }
68
146
 
69
- async function unit ({
147
+ async function scaffoldUnitTesting ({
70
148
  projectRoot,
71
149
  frameworks,
72
150
  decisions,
@@ -86,10 +164,1313 @@ async function unit ({
86
164
  })]);
87
165
  return deepmerge.all([{
88
166
  scripts: {
89
- 'test:unit': 'cross-env NODE_ENV=test nyc run-s test:unit:base'
167
+ 'test:unit': 'cross-env NODE_ENV=test c8 run-s test:unit:base'
90
168
  }
91
169
  }, framework, coverage]);
92
170
  }
93
171
 
94
- export { questionNames, scaffold, unit as scaffoldUnitTesting, unitTestFrameworksSchema };
172
+ function validate(options) {
173
+ const schema = joi.object().required().keys({
174
+ projectRoot: joi.string().required(),
175
+ projectName: joi.string().regex(/^@\w*\//, {
176
+ invert: true
177
+ }).required(),
178
+ visibility: joi.string().valid('Public', 'Private').required(),
179
+ license: joi.string().required(),
180
+ description: joi.string(),
181
+ pathWithinParent: joi.string()
182
+ }).keys({
183
+ vcs: joi.object({
184
+ host: joi.string().required(),
185
+ owner: joi.string().required(),
186
+ name: joi.string().required()
187
+ })
188
+ }).keys({
189
+ configs: joi.object({
190
+ eslint: joi.object({
191
+ scope: joi.string().regex(/^@[a-z0-9-]+$/i, 'scope').required()
192
+ }),
193
+ typescript: joi.object({
194
+ scope: joi.string().regex(/^@[a-z0-9-]+$/i, 'scope').required()
195
+ }),
196
+ commitlint: joi.object({
197
+ packageName: joi.string().required(),
198
+ name: joi.string().required()
199
+ }),
200
+ babelPreset: joi.object({
201
+ packageName: joi.string().required(),
202
+ name: joi.string().required()
203
+ }),
204
+ remark: joi.string()
205
+ }).default({})
206
+ }).keys({
207
+ overrides: joi.object({
208
+ npmAccount: joi.string(),
209
+ author: joi.object({
210
+ name: joi.string().required(),
211
+ email: joi.string().email(),
212
+ url: joi.string().uri()
213
+ })
214
+ }).default({})
215
+ }).keys({
216
+ ciServices: joi.object().pattern(/^/, joi.object({
217
+ scaffolder: joi.func().arity(1).required(),
218
+ public: joi.boolean(),
219
+ private: joi.boolean()
220
+ })).default({})
221
+ }).keys({
222
+ hosts: joi.object().pattern(/^/, joi.object({
223
+ scaffolder: joi.func().arity(1).required(),
224
+ projectTypes: joi.array().items(joi.string().valid('static', 'node')).default([])
225
+ })).default({})
226
+ }).keys({
227
+ applicationTypes: joi.object().pattern(/^/, joi.object({
228
+ scaffolder: joi.func().arity(1).required()
229
+ })).default({}),
230
+ packageTypes: joi.object().pattern(/^/, joi.object({
231
+ scaffolder: joi.func().arity(1).required()
232
+ })).default({}),
233
+ monorepoTypes: joi.object().pattern(/^/, joi.object({
234
+ scaffolder: joi.func().arity(1).required()
235
+ }))
236
+ }).keys({
237
+ decisions: joi.object()
238
+ }).keys({
239
+ unitTestFrameworks: unitTestFrameworksSchema
240
+ }).keys({
241
+ registries: joi.object().pattern(joi.string(), joi.string().uri())
242
+ });
243
+ const {
244
+ error,
245
+ value
246
+ } = schema.validate(options);
247
+ hoek.assert(!error, error);
248
+ return value;
249
+ }
250
+
251
+ const npmConf = require('npm-conf');
252
+
253
+ var npmConfFactory = npmConf;
254
+
255
+ function buildDialectChoices ({
256
+ babelPreset,
257
+ typescript
258
+ }) {
259
+ return [{
260
+ name: 'Common JS (no transpilation)',
261
+ value: dialects.COMMON_JS,
262
+ short: 'cjs'
263
+ }, ...(babelPreset ? [{
264
+ name: 'Modern JavaScript (transpiled)',
265
+ value: dialects.BABEL,
266
+ short: 'modern'
267
+ }] : []), {
268
+ name: 'ESM-only (no transpilation)',
269
+ value: dialects.ESM,
270
+ short: 'esm'
271
+ }, ...(typescript ? [{
272
+ name: 'TypeScript',
273
+ value: dialects.TYPESCRIPT,
274
+ short: 'ts'
275
+ }] : [])];
276
+ }
277
+
278
+ function projectIsPackage(answers) {
279
+ return projectTypes.PACKAGE === answers[questionNames$1.PROJECT_TYPE];
280
+ }
281
+
282
+ function projectIsCLI(answers) {
283
+ return projectTypes.CLI === answers[questionNames$1.PROJECT_TYPE];
284
+ }
285
+
286
+ function projectIsApplication(answers) {
287
+ return projectTypes.APPLICATION === answers[questionNames$1.PROJECT_TYPE];
288
+ }
289
+
290
+ function packageShouldBeScoped(visibility, answers) {
291
+ return 'Private' === visibility || answers[questionNames$1.SHOULD_BE_SCOPED];
292
+ }
293
+
294
+ function willBePublishedToNpm(answers) {
295
+ return projectIsPackage(answers) || projectIsCLI(answers);
296
+ }
297
+
298
+ function shouldBeScopedPromptShouldBePresented(answers) {
299
+ return willBePublishedToNpm(answers);
300
+ }
301
+ function scopePromptShouldBePresentedFactory(visibility) {
302
+ return answers => willBePublishedToNpm(answers) && packageShouldBeScoped(visibility, answers);
303
+ }
304
+ function lintingPromptShouldBePresented({
305
+ [questionNames$2.UNIT_TESTS]: unitTested,
306
+ [questionNames$2.INTEGRATION_TESTS]: integrationTested
307
+ }) {
308
+ return !unitTested && !integrationTested;
309
+ }
310
+
311
+ function scope(visibility) {
312
+ return input => {
313
+ if (!input && 'Private' === visibility) {
314
+ return 'Private packages must be scoped (https://docs.npmjs.com/private-modules/intro#setting-up-your-package)';
315
+ }
316
+
317
+ return true;
318
+ };
319
+ }
320
+
321
+ function authorQuestions({
322
+ name,
323
+ email,
324
+ url
325
+ }) {
326
+ return [{
327
+ name: questionNames$1.AUTHOR_NAME,
328
+ message: 'What is the author\'s name?',
329
+ default: name
330
+ }, {
331
+ name: questionNames$1.AUTHOR_EMAIL,
332
+ message: 'What is the author\'s email?',
333
+ default: email
334
+ }, {
335
+ name: questionNames$1.AUTHOR_URL,
336
+ message: 'What is the author\'s website url?',
337
+ default: url
338
+ }];
339
+ }
340
+
341
+ async function prompt({
342
+ npmAccount,
343
+ author
344
+ }, ciServices, hosts, visibility, vcs, decisions, configs, pathWithinParent) {
345
+ const npmConf = npmConfFactory();
346
+ let maybeLoggedInNpmUsername;
347
+
348
+ try {
349
+ maybeLoggedInNpmUsername = (await execa('npm', ['whoami'])).stdout;
350
+ } catch (failedExecutionResult) {
351
+ if (!decisions[questionNames$1.SCOPE]) {
352
+ warn('No logged in user found with `npm whoami`. Login with `npm login` ' + 'to use your npm account name as the package scope default.');
353
+ }
354
+ }
355
+
356
+ const {
357
+ [questionNames$2.UNIT_TESTS]: unitTested,
358
+ [questionNames$2.INTEGRATION_TESTS]: integrationTested,
359
+ [questionNames$1.PROJECT_TYPE]: projectType,
360
+ [questionNames$2.CI_SERVICE]: ci,
361
+ [questionNames$1.HOST]: chosenHost,
362
+ [questionNames$1.SCOPE]: scope$1,
363
+ [questionNames$1.NODE_VERSION_CATEGORY]: nodeVersionCategory,
364
+ [questionNames$1.AUTHOR_NAME]: authorName,
365
+ [questionNames$1.AUTHOR_EMAIL]: authorEmail,
366
+ [questionNames$1.AUTHOR_URL]: authorUrl,
367
+ [questionNames$1.CONFIGURE_LINTING]: configureLinting,
368
+ [questionNames$1.PACKAGE_MANAGER]: packageManager,
369
+ [questionNames$1.DIALECT]: dialect
370
+ } = await prompt$1([{
371
+ name: questionNames$1.DIALECT,
372
+ message: 'Which JavaScript dialect should this project follow?',
373
+ type: 'list',
374
+ choices: buildDialectChoices(configs),
375
+ default: 'babel'
376
+ }, ...(pathWithinParent ? [] : [{
377
+ name: questionNames$1.NODE_VERSION_CATEGORY,
378
+ message: 'What node.js version should be used?',
379
+ type: 'list',
380
+ choices: ['LTS', 'Latest'],
381
+ default: 'LTS'
382
+ }]), {
383
+ name: questionNames$1.PACKAGE_MANAGER,
384
+ message: 'Which package manager will be used with this project?',
385
+ type: 'list',
386
+ choices: Object.values(packageManagers),
387
+ default: packageManagers.NPM
388
+ }, {
389
+ name: questionNames$1.PROJECT_TYPE,
390
+ message: 'What type of JavaScript project is this?',
391
+ type: 'list',
392
+ choices: [...Object.values(projectTypes), new Separator(), 'Other'],
393
+ default: projectTypes.PACKAGE
394
+ }, ...('Private' === visibility ? [] : [{
395
+ name: questionNames$1.SHOULD_BE_SCOPED,
396
+ message: 'Should this package be scoped?',
397
+ type: 'confirm',
398
+ when: shouldBeScopedPromptShouldBePresented,
399
+ default: true
400
+ }]), {
401
+ name: questionNames$1.SCOPE,
402
+ message: 'What is the scope?',
403
+ when: scopePromptShouldBePresentedFactory(visibility),
404
+ validate: scope(visibility),
405
+ default: npmAccount || maybeLoggedInNpmUsername
406
+ }, ...authorQuestions(author || {
407
+ name: npmConf.get('init.author.name'),
408
+ email: npmConf.get('init.author.email'),
409
+ url: npmConf.get('init.author.url')
410
+ }), ...questions({
411
+ vcs,
412
+ ciServices,
413
+ visibility,
414
+ pathWithinParent
415
+ }), {
416
+ name: questionNames$1.CONFIGURE_LINTING,
417
+ message: 'Will there be source code that should be linted?',
418
+ type: 'confirm',
419
+ when: lintingPromptShouldBePresented
420
+ }, {
421
+ name: questionNames$1.HOST,
422
+ type: 'list',
423
+ message: 'Where will the application be hosted?',
424
+ when: projectIsApplication,
425
+ choices: [...Object.keys(hosts), new Separator(), 'Other']
426
+ }], decisions);
427
+ return {
428
+ tests: {
429
+ unit: unitTested,
430
+ integration: integrationTested
431
+ },
432
+ projectType,
433
+ ci,
434
+ chosenHost,
435
+ scope: scope$1,
436
+ nodeVersionCategory,
437
+ author: {
438
+ name: authorName,
439
+ email: authorEmail,
440
+ url: authorUrl
441
+ },
442
+ configureLinting: false !== configureLinting,
443
+ packageManager,
444
+ dialect
445
+ };
446
+ }
447
+
448
+ async function scaffoldBabel ({
449
+ projectRoot,
450
+ preset,
451
+ tests,
452
+ buildDirectory
453
+ }) {
454
+ if (!preset) {
455
+ throw new Error('No babel preset provided. Cannot configure babel transpilation');
456
+ }
457
+
458
+ await promises.writeFile(`${projectRoot}/.babelrc`, JSON.stringify(_objectSpread2({
459
+ presets: [preset.name],
460
+ ignore: [`./${buildDirectory}/`]
461
+ }, tests.unit && {
462
+ env: {
463
+ test: {
464
+ plugins: ['istanbul']
465
+ }
466
+ }
467
+ })));
468
+ return {
469
+ devDependencies: ['@babel/register', preset.packageName, ...(tests.unit ? ['babel-plugin-istanbul'] : [])],
470
+ eslint: {}
471
+ };
472
+ }
473
+
474
+ async function scaffoldTypescript ({
475
+ config,
476
+ projectType,
477
+ projectRoot,
478
+ testFilenamePattern
479
+ }) {
480
+ const eslintConfigs = ['typescript'];
481
+ const shareableTsConfigPackage = `${config.scope}/tsconfig`;
482
+ await promises.writeFile(`${projectRoot}/tsconfig.json`, JSON.stringify(_objectSpread2({
483
+ $schema: 'https://json.schemastore.org/tsconfig',
484
+ extends: shareableTsConfigPackage,
485
+ compilerOptions: _objectSpread2({
486
+ rootDir: 'src'
487
+ }, projectTypes.PACKAGE === projectType && {
488
+ outDir: 'lib',
489
+ declaration: true
490
+ }),
491
+ include: ['src/**/*.ts']
492
+ }, testFilenamePattern && {
493
+ exclude: [testFilenamePattern]
494
+ })));
495
+ return {
496
+ eslint: {
497
+ configs: eslintConfigs
498
+ },
499
+ eslintConfigs,
500
+ devDependencies: ['typescript', shareableTsConfigPackage],
501
+ packageProperties: {
502
+ types: 'lib/index.d.ts'
503
+ },
504
+ vcsIgnore: {
505
+ files: ['tsconfig.tsbuildinfo']
506
+ }
507
+ };
508
+ }
509
+
510
+ function scaffoldEsm () {
511
+ return {
512
+ packageProperties: {
513
+ engines: {
514
+ node: '>=12.20'
515
+ }
516
+ }
517
+ };
518
+ }
519
+
520
+ function scaffoldDialect ({
521
+ dialect,
522
+ projectType,
523
+ projectRoot,
524
+ configs,
525
+ tests,
526
+ buildDirectory,
527
+ testFilenamePattern
528
+ }) {
529
+ switch (dialect) {
530
+ case dialects.BABEL:
531
+ return scaffoldBabel({
532
+ preset: configs.babelPreset,
533
+ projectRoot,
534
+ tests,
535
+ buildDirectory
536
+ });
537
+
538
+ case dialects.TYPESCRIPT:
539
+ return scaffoldTypescript({
540
+ config: configs.typescript,
541
+ projectType,
542
+ projectRoot,
543
+ testFilenamePattern
544
+ });
545
+
546
+ case dialects.ESM:
547
+ return scaffoldEsm();
548
+
549
+ default:
550
+ return {
551
+ eslint: {}
552
+ };
553
+ }
554
+ }
555
+
556
+ function projectWillNotBeConsumed(projectType) {
557
+ return projectTypes.APPLICATION === projectType || projectTypes.CLI === projectType;
558
+ }
559
+
560
+ async function scaffoldNpmConfig ({
561
+ projectRoot,
562
+ projectType,
563
+ registries
564
+ }) {
565
+ await promises.writeFile(`${projectRoot}/.npmrc`, stringify(_objectSpread2(_objectSpread2({
566
+ 'update-notifier': false,
567
+ 'engine-strict': true
568
+ }, projectWillNotBeConsumed(projectType) && {
569
+ 'save-exact': true
570
+ }), registries && Object.fromEntries(Object.entries(registries).map(([scope, url]) => [`@${scope}:registry`, url])))));
571
+ return {
572
+ scripts: {
573
+ 'lint:peer': 'npm ls >/dev/null'
574
+ }
575
+ };
576
+ }
577
+
578
+ function buildDocumentationCommand (packageManager) {
579
+ if (packageManagers.NPM === packageManager) return 'npm run generate:md';
580
+ if (packageManagers.YARN === packageManager) return 'yarn generate:md';
581
+ throw new Error(`The ${packageManager} package manager is currently not supported. ` + `Only ${Object.values(packageManagers).join(' and ')} are currently supported.`);
582
+ }
583
+
584
+ function scaffoldDocumentation ({
585
+ projectTypeResults,
586
+ packageManager
587
+ }) {
588
+ return _objectSpread2(_objectSpread2({
589
+ toc: `Run \`${buildDocumentationCommand(packageManager)}\` to generate a table of contents`
590
+ }, projectTypeResults.documentation), {}, {
591
+ contributing: `### Dependencies
592
+
593
+ \`\`\`sh
594
+ $ nvm install
595
+ $ ${packageManager} install
596
+ \`\`\`
597
+
598
+ ### Verification
599
+
600
+ \`\`\`sh
601
+ $ ${packageManager} test
602
+ \`\`\``
603
+ });
604
+ }
605
+
606
+ async function determineLatestVersionOf(nodeVersionCategory) {
607
+ info('Determining version of node', {
608
+ level: 'secondary'
609
+ });
610
+ const {
611
+ stdout: nvmLsOutput
612
+ } = await execa(`. ~/.nvm/nvm.sh && nvm ls-remote${'LTS' === nodeVersionCategory ? ' --lts' : ''}`, {
613
+ shell: true
614
+ });
615
+ const lsLines = nvmLsOutput.split('\n');
616
+ const lsLine = lsLines[lsLines.length - 2];
617
+ return lsLine.match(/(v[0-9]+)\.[0-9]+\.[0-9]+/)[1];
618
+ }
619
+ function install(nodeVersionCategory) {
620
+ info(`Installing ${nodeVersionCategory} version of node using nvm`, {
621
+ level: 'secondary'
622
+ });
623
+ const subprocess = execa('. ~/.nvm/nvm.sh && nvm install', {
624
+ shell: true
625
+ });
626
+ subprocess.stdout.pipe(process.stdout);
627
+ return subprocess;
628
+ }
629
+
630
+ async function scaffoldNodeVersion ({
631
+ projectRoot,
632
+ nodeVersionCategory
633
+ }) {
634
+ if (!nodeVersionCategory) return undefined;
635
+ const lowerCaseCategory = nodeVersionCategory.toLowerCase();
636
+ info(`Configuring ${lowerCaseCategory} version of node`);
637
+ const version = await determineLatestVersionOf(nodeVersionCategory);
638
+ await promises.writeFile(`${projectRoot}/.nvmrc`, version);
639
+ await install(nodeVersionCategory);
640
+ return version;
641
+ }
642
+
643
+ function buildBadgesDetails (contributors) {
644
+ return deepmerge.all(contributors).badges;
645
+ }
646
+
647
+ function buildVcsIgnoreLists (vcsIgnoreLists = {}) {
648
+ return {
649
+ files: vcsIgnoreLists.files || [],
650
+ directories: ['/node_modules/', ...(vcsIgnoreLists.directories || [])]
651
+ };
652
+ }
653
+
654
+ function projectWillBeTested(scripts) {
655
+ return Object.keys(scripts).find(scriptName => scriptName.startsWith('test:'));
656
+ }
657
+
658
+ function projectShouldBeBuiltForVerification(scripts) {
659
+ return 'run-s build' === scripts['pregenerate:md'];
660
+ }
661
+
662
+ function defineScripts(scripts) {
663
+ return {
664
+ test: `npm-run-all --print-label${projectShouldBeBuiltForVerification(scripts) ? ' build' : ''} --parallel lint:*${projectWillBeTested(scripts) ? ' --parallel test:*' : ''}`
665
+ };
666
+ }
667
+
668
+ function defineVcsHostDetails(vcs, packageType, packageName, pathWithinParent) {
669
+ return vcs && 'github' === vcs.host && {
670
+ repository: pathWithinParent ? {
671
+ type: 'git',
672
+ url: `https://github.com/${vcs.owner}/${vcs.name}.git`,
673
+ directory: pathWithinParent
674
+ } : `${vcs.owner}/${vcs.name}`,
675
+ bugs: `https://github.com/${vcs.owner}/${vcs.name}/issues`,
676
+ homepage: projectTypes.PACKAGE === packageType ? `https://npm.im/${packageName}` : `https://github.com/${vcs.owner}/${vcs.name}#readme`
677
+ };
678
+ }
679
+
680
+ function buildPackageDetails ({
681
+ packageName,
682
+ projectType,
683
+ dialect,
684
+ license,
685
+ vcs,
686
+ author,
687
+ description,
688
+ scripts,
689
+ packageProperties,
690
+ pathWithinParent
691
+ }) {
692
+ return _objectSpread2(_objectSpread2(_objectSpread2({
693
+ name: packageName,
694
+ description,
695
+ license,
696
+ type: dialects.ESM === dialect ? 'module' : 'commonjs'
697
+ }, packageProperties), defineVcsHostDetails(vcs, projectType, packageName, pathWithinParent)), {}, {
698
+ author: `${author.name}${author.email ? ` <${author.email}>` : ''}${author.url ? ` (${author.url})` : ''}`,
699
+ scripts: defineScripts(scripts)
700
+ });
701
+ }
702
+
703
+ async function scaffoldPackage ({
704
+ projectRoot,
705
+ projectType,
706
+ dialect,
707
+ scripts,
708
+ packageName,
709
+ license,
710
+ vcs,
711
+ author,
712
+ description,
713
+ packageProperties,
714
+ pathWithinParent
715
+ }) {
716
+ info('Configuring package.json');
717
+ const packageData = await buildPackageDetails({
718
+ packageName,
719
+ projectType,
720
+ dialect,
721
+ license,
722
+ vcs,
723
+ author,
724
+ description,
725
+ scripts,
726
+ packageProperties,
727
+ pathWithinParent
728
+ });
729
+ await promises.writeFile(`${projectRoot}/package.json`, JSON.stringify(packageData));
730
+ return {
731
+ homepage: packageData.homepage
732
+ };
733
+ }
734
+
735
+ function buildPackageName (projectName, scope) {
736
+ const name = `${scope ? `@${scope}/` : ''}${projectName}`;
737
+ const {
738
+ validForNewPackages,
739
+ errors
740
+ } = validatePackageName(name);
741
+ if (validForNewPackages) return name;
742
+ if (1 === errors.length && errors.includes('name cannot start with a period')) return projectName.slice(1);
743
+ throw new Error(`The package name ${name} is invalid:${EOL}\t* ${errors.join(`${EOL}\t* `)}`);
744
+ }
745
+
746
+ async function chooseApplicationType ({
747
+ types,
748
+ projectType,
749
+ decisions
750
+ }) {
751
+ if (!Object.keys(types).length) return 'Other';
752
+ const answers = await prompt$1([{
753
+ name: questionNames$1.PROJECT_TYPE_CHOICE,
754
+ type: 'list',
755
+ message: `What type of ${projectType} is this?`,
756
+ choices: [...Object.keys(types), new Separator(), 'Other']
757
+ }], decisions);
758
+ return answers[questionNames$1.PROJECT_TYPE_CHOICE];
759
+ }
760
+
761
+ function getInstallationCommand(packageManager) {
762
+ if (packageManagers.NPM === packageManager) return 'npm install';
763
+ if (packageManagers.YARN === packageManager) return 'yarn add';
764
+ throw new Error(`The ${packageManager} package manager is currently not supported. ` + `Only ${Object.values(packageManagers).join(' and ')} are currently supported.`);
765
+ }
766
+
767
+ function scaffoldPackageDocumentation ({
768
+ scope,
769
+ packageName,
770
+ packageManager,
771
+ visibility
772
+ }) {
773
+ return {
774
+ usage: `### Installation
775
+ ${'Private' === visibility ? `
776
+ :warning: this is a private package, so you will need to use an npm token with
777
+ access to private packages under \`@${scope}\`
778
+ ` : ''}
779
+ \`\`\`sh
780
+ $ ${getInstallationCommand(packageManager)} ${packageName}
781
+ \`\`\`
782
+
783
+ ### Example
784
+
785
+ run \`${buildDocumentationCommand(packageManager)}\` to inject the usage example`
786
+ };
787
+ }
788
+
789
+ function defineBadges (packageName, visibility) {
790
+ return {
791
+ consumer: _objectSpread2({}, 'Public' === visibility && {
792
+ npm: {
793
+ img: `https://img.shields.io/npm/v/${packageName}.svg`,
794
+ text: 'npm',
795
+ link: `https://www.npmjs.com/package/${packageName}`
796
+ }
797
+ }),
798
+ status: {}
799
+ };
800
+ }
801
+
802
+ function determinePathToTemplateFile (fileName) {
803
+ return resolve(__dirname, '..', 'templates', fileName);
804
+ }
805
+
806
+ const defaultBuildDirectory$2 = 'lib';
807
+
808
+ async function createExample(projectRoot, projectName) {
809
+ return promises.writeFile(`${projectRoot}/example.js`, mustache.render(await promises.readFile(determinePathToTemplateFile('example.mustache'), 'utf8'), {
810
+ projectName: camelcase(projectName)
811
+ }));
812
+ }
813
+
814
+ async function buildDetailsForCommonJsProject({
815
+ projectRoot,
816
+ projectName
817
+ }) {
818
+ await Promise.all([touch(`${projectRoot}/index.js`), promises.writeFile(`${projectRoot}/example.js`, `const ${camelcase(projectName)} = require('.');\n`)]);
819
+ return {};
820
+ }
821
+
822
+ async function buildDetails ({
823
+ projectRoot,
824
+ projectName,
825
+ visibility,
826
+ packageName,
827
+ dialect
828
+ }) {
829
+ if (dialects.COMMON_JS === dialect) return buildDetailsForCommonJsProject({
830
+ projectRoot,
831
+ projectName
832
+ });
833
+ const pathToCreatedSrcDirectory = await makeDir(`${projectRoot}/src`);
834
+ const [rollupResults] = await Promise.all([scaffold$2({
835
+ projectRoot,
836
+ dialect,
837
+ projectType: projectTypes.PACKAGE
838
+ }), await createExample(projectRoot, projectName), touch(`${pathToCreatedSrcDirectory}/index.js`)]);
839
+ return deepmerge(rollupResults, {
840
+ devDependencies: ['rimraf'],
841
+ scripts: {
842
+ clean: `rimraf ./${defaultBuildDirectory$2}`,
843
+ prebuild: 'run-s clean',
844
+ build: 'npm-run-all --print-label --parallel build:*',
845
+ prepack: 'run-s build'
846
+ },
847
+ vcsIgnore: {
848
+ directories: [`/${defaultBuildDirectory$2}/`]
849
+ },
850
+ buildDirectory: defaultBuildDirectory$2,
851
+ badges: {
852
+ consumer: _objectSpread2({}, 'Public' === visibility && {
853
+ runkit: {
854
+ img: `https://badge.runkitcdn.com/${packageName}.svg`,
855
+ text: `Try ${packageName} on RunKit`,
856
+ link: `https://npm.runkit.com/${packageName}`
857
+ }
858
+ })
859
+ }
860
+ });
861
+ }
862
+
863
+ async function scaffoldPackageType ({
864
+ projectRoot,
865
+ projectName,
866
+ packageName,
867
+ packageManager,
868
+ visibility,
869
+ scope,
870
+ packageTypes,
871
+ tests,
872
+ decisions,
873
+ dialect
874
+ }) {
875
+ info('Scaffolding Package Details');
876
+ const detailsForBuild = await buildDetails({
877
+ projectRoot,
878
+ projectName,
879
+ visibility,
880
+ packageName,
881
+ dialect
882
+ });
883
+
884
+ const details = _objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({}, dialects.BABEL === dialect && _objectSpread2({
885
+ packageProperties: {
886
+ main: 'lib/index.cjs.js',
887
+ module: 'lib/index.es.js',
888
+ sideEffects: false,
889
+ files: ['lib/']
890
+ }
891
+ }, detailsForBuild)), dialects.ESM === dialect && _objectSpread2({
892
+ packageProperties: {
893
+ main: 'lib/index.es.js',
894
+ sideEffects: false,
895
+ files: ['lib/']
896
+ }
897
+ }, detailsForBuild)), dialects.TYPESCRIPT === dialect && _objectSpread2({
898
+ packageProperties: {
899
+ main: 'lib/index.cjs.js',
900
+ module: 'lib/index.es.js',
901
+ sideEffects: false,
902
+ files: ['lib/']
903
+ }
904
+ }, detailsForBuild)), dialects.COMMON_JS === dialect && _objectSpread2({
905
+ packageProperties: {
906
+ files: ['index.js']
907
+ }
908
+ }, detailsForBuild));
909
+
910
+ const chosenType = await chooseApplicationType({
911
+ types: packageTypes,
912
+ projectType: 'package',
913
+ decisions
914
+ });
915
+ const results = await scaffoldChoice(packageTypes, chosenType, {
916
+ projectRoot,
917
+ projectName,
918
+ packageName,
919
+ tests,
920
+ scope
921
+ });
922
+ return deepmerge.all([{
923
+ packageProperties: _objectSpread2({
924
+ files: ['example.js'],
925
+ publishConfig: {
926
+ access: 'Public' === visibility ? 'public' : 'restricted'
927
+ }
928
+ }, 'Public' === visibility && {
929
+ runkitExampleFilename: './example.js'
930
+ }),
931
+ documentation: scaffoldPackageDocumentation({
932
+ packageName,
933
+ visibility,
934
+ scope,
935
+ packageManager
936
+ }),
937
+ eslintConfigs: [],
938
+ nextSteps: [{
939
+ summary: 'Add the appropriate `save` flag to the installation instructions in the README'
940
+ }, {
941
+ summary: 'Publish pre-release versions to npm until package is stable enough to publish v1.0.0'
942
+ }],
943
+ scripts: {},
944
+ badges: defineBadges(packageName, visibility)
945
+ }, results, details]);
946
+ }
947
+
948
+ const defaultBuildDirectory$1 = 'lib';
949
+ async function scaffoldApplicationType ({
950
+ applicationTypes,
951
+ projectRoot,
952
+ projectName,
953
+ packageName,
954
+ packageManager,
955
+ tests,
956
+ decisions
957
+ }) {
958
+ info('Scaffolding Application Details');
959
+ const chosenType = await chooseApplicationType({
960
+ types: applicationTypes,
961
+ projectType: 'application',
962
+ decisions
963
+ });
964
+ const results = await scaffoldChoice(applicationTypes, chosenType, {
965
+ projectRoot,
966
+ projectName,
967
+ packageName,
968
+ packageManager,
969
+ tests
970
+ });
971
+ const buildDirectory = results.buildDirectory || defaultBuildDirectory$1;
972
+ return deepmerge({
973
+ scripts: {
974
+ clean: `rimraf ./${buildDirectory}`,
975
+ start: `node ./${buildDirectory}/index.js`,
976
+ prebuild: 'run-s clean'
977
+ },
978
+ dependencies: [],
979
+ devDependencies: ['rimraf'],
980
+ vcsIgnore: {
981
+ files: ['.env'],
982
+ directories: [`/${buildDirectory}/`]
983
+ },
984
+ buildDirectory,
985
+ packageProperties: {
986
+ private: true
987
+ },
988
+ eslintConfigs: [],
989
+ nextSteps: []
990
+ }, results);
991
+ }
992
+
993
+ async function scaffoldMonorepoType ({
994
+ monorepoTypes,
995
+ projectRoot,
996
+ packageManager,
997
+ decisions
998
+ }) {
999
+ info('Scaffolding Monorepo Details');
1000
+ const chosenType = await chooseApplicationType({
1001
+ types: monorepoTypes,
1002
+ projectType: projectTypes.MONOREPO,
1003
+ decisions
1004
+ });
1005
+ const results = await scaffoldChoice(monorepoTypes, chosenType, {
1006
+ projectRoot,
1007
+ packageManager
1008
+ });
1009
+ return deepmerge({
1010
+ eslintConfigs: [],
1011
+ packageProperties: {
1012
+ private: true
1013
+ },
1014
+ nextSteps: [{
1015
+ summary: 'Add packages to your new monorepo',
1016
+ description: 'Leverage [@form8ion/add-package-to-monorepo](https://npm.im/@form8ion/add-package-to-monorepo)' + ' to scaffold new packages into your new monorepo'
1017
+ }]
1018
+ }, results);
1019
+ }
1020
+
1021
+ const defaultBuildDirectory = 'bin';
1022
+ async function scaffoldCliType ({
1023
+ packageName,
1024
+ visibility,
1025
+ projectRoot,
1026
+ dialect
1027
+ }) {
1028
+ const rollupResults = await scaffold$2({
1029
+ projectRoot,
1030
+ dialect,
1031
+ projectType: projectTypes.CLI
1032
+ });
1033
+ return deepmerge(rollupResults, {
1034
+ scripts: {
1035
+ clean: `rimraf ./${defaultBuildDirectory}`,
1036
+ prebuild: 'run-s clean',
1037
+ build: 'npm-run-all --print-label --parallel build:*',
1038
+ prepack: 'run-s build'
1039
+ },
1040
+ dependencies: ['update-notifier'],
1041
+ devDependencies: ['rimraf'],
1042
+ vcsIgnore: {
1043
+ files: [],
1044
+ directories: [`/${defaultBuildDirectory}/`]
1045
+ },
1046
+ buildDirectory: defaultBuildDirectory,
1047
+ badges: defineBadges(packageName, visibility),
1048
+ packageProperties: {
1049
+ version: '0.0.0-semantically-released',
1050
+ bin: {},
1051
+ files: [`${defaultBuildDirectory}/`],
1052
+ publishConfig: {
1053
+ access: 'Public' === visibility ? 'public' : 'restricted'
1054
+ }
1055
+ },
1056
+ eslintConfigs: [],
1057
+ nextSteps: []
1058
+ });
1059
+ }
1060
+
1061
+ async function scaffoldProjectType ({
1062
+ projectType,
1063
+ projectRoot,
1064
+ projectName,
1065
+ packageName,
1066
+ packageManager,
1067
+ visibility,
1068
+ applicationTypes,
1069
+ packageTypes,
1070
+ monorepoTypes,
1071
+ scope,
1072
+ tests,
1073
+ vcs,
1074
+ decisions,
1075
+ dialect
1076
+ }) {
1077
+ switch (projectType) {
1078
+ case projectTypes.PACKAGE:
1079
+ return scaffoldPackageType({
1080
+ projectRoot,
1081
+ projectName,
1082
+ packageName,
1083
+ packageManager,
1084
+ visibility,
1085
+ scope,
1086
+ packageTypes,
1087
+ tests,
1088
+ vcs,
1089
+ decisions,
1090
+ dialect
1091
+ });
1092
+
1093
+ case projectTypes.APPLICATION:
1094
+ return scaffoldApplicationType({
1095
+ projectRoot,
1096
+ projectName,
1097
+ packageName,
1098
+ packageManager,
1099
+ applicationTypes,
1100
+ tests,
1101
+ decisions
1102
+ });
1103
+
1104
+ case projectTypes.CLI:
1105
+ return scaffoldCliType({
1106
+ packageName,
1107
+ visibility,
1108
+ projectRoot,
1109
+ dialect
1110
+ });
1111
+
1112
+ case projectTypes.MONOREPO:
1113
+ return scaffoldMonorepoType({
1114
+ monorepoTypes,
1115
+ projectRoot,
1116
+ packageManager,
1117
+ decisions
1118
+ });
1119
+
1120
+ case 'Other':
1121
+ return {
1122
+ eslintConfigs: []
1123
+ };
1124
+
1125
+ default:
1126
+ throw new Error(`The project-type of ${projectType} is invalid`);
1127
+ }
1128
+ }
1129
+
1130
+ async function scaffoldTesting ({
1131
+ projectRoot,
1132
+ visibility,
1133
+ tests: {
1134
+ unit,
1135
+ integration
1136
+ },
1137
+ vcs,
1138
+ unitTestFrameworks,
1139
+ decisions,
1140
+ dialect
1141
+ }) {
1142
+ const unitResults = unit ? await scaffoldUnitTesting({
1143
+ projectRoot,
1144
+ visibility,
1145
+ vcs,
1146
+ frameworks: unitTestFrameworks,
1147
+ decisions,
1148
+ dialect
1149
+ }) : {};
1150
+ return deepmerge({
1151
+ devDependencies: [...(unit || integration ? ['@travi/any'] : [])],
1152
+ eslint: [],
1153
+ eslintConfigs: []
1154
+ }, unitResults);
1155
+ }
1156
+
1157
+ async function scaffoldEslint ({
1158
+ config,
1159
+ projectRoot,
1160
+ buildDirectory,
1161
+ additionalConfiguration
1162
+ }) {
1163
+ const {
1164
+ scope
1165
+ } = config;
1166
+ const {
1167
+ ignore
1168
+ } = additionalConfiguration;
1169
+ const ignores = deepmerge(ignore, {
1170
+ directories: [`/${buildDirectory}/`]
1171
+ });
1172
+ return scaffold$3({
1173
+ scope,
1174
+ projectRoot,
1175
+ ignore: {
1176
+ directories: ignores.directories
1177
+ }
1178
+ });
1179
+ }
1180
+
1181
+ async function scaffoldRemark ({
1182
+ config,
1183
+ projectRoot,
1184
+ projectType,
1185
+ vcs,
1186
+ dialect
1187
+ }) {
1188
+ await promises.writeFile(`${projectRoot}/.remarkrc.json`, JSON.stringify({
1189
+ settings: {
1190
+ listItemIndent: 1,
1191
+ emphasis: '_',
1192
+ strong: '_',
1193
+ bullet: '*',
1194
+ incrementListMarker: false
1195
+ },
1196
+ plugins: [config, ['remark-toc', {
1197
+ tight: true
1198
+ }], ...(projectTypes.PACKAGE === projectType ? [['remark-usage', {
1199
+ heading: 'example'
1200
+ }]] : []), ...(!vcs ? [['validate-links', {
1201
+ repository: false
1202
+ }]] : [])]
1203
+ }));
1204
+ return deepmerge({
1205
+ devDependencies: [config, 'remark-cli', 'remark-toc'],
1206
+ scripts: {
1207
+ 'lint:md': 'remark . --frail',
1208
+ 'generate:md': 'remark . --output'
1209
+ }
1210
+ }, _objectSpread2({}, projectTypes.PACKAGE === projectType && _objectSpread2({
1211
+ devDependencies: ['remark-usage']
1212
+ }, dialects.COMMON_JS !== dialect && {
1213
+ scripts: {
1214
+ 'pregenerate:md': 'run-s build'
1215
+ }
1216
+ })));
1217
+ }
1218
+
1219
+ function scaffoldBanSensitiveFiles () {
1220
+ return {
1221
+ scripts: {
1222
+ 'lint:sensitive': 'ban'
1223
+ },
1224
+ devDependencies: ['ban-sensitive-files']
1225
+ };
1226
+ }
1227
+
1228
+ function determineLockfilePathFor(packageManager) {
1229
+ if (packageManagers.NPM === packageManager) return 'package-lock.json';
1230
+ if (packageManagers.YARN === packageManager) return 'yarn.lock';
1231
+ throw new Error(`The ${packageManager} package manager is currently not supported. ` + `Only ${Object.values(packageManagers).join(' and ')} are currently supported.`);
1232
+ }
1233
+
1234
+ async function scaffoldLockfileLint ({
1235
+ projectRoot,
1236
+ packageManager,
1237
+ registries
1238
+ }) {
1239
+ await promises.writeFile(`${projectRoot}/.lockfile-lintrc.json`, JSON.stringify({
1240
+ path: determineLockfilePathFor(packageManager),
1241
+ type: packageManager,
1242
+ 'validate-https': true,
1243
+ 'allowed-hosts': [packageManager, ...(registries ? Object.values(registries) : [])]
1244
+ }));
1245
+ return {
1246
+ devDependencies: ['lockfile-lint'],
1247
+ scripts: {
1248
+ 'lint:lockfile': 'lockfile-lint'
1249
+ }
1250
+ };
1251
+ }
1252
+
1253
+ async function scaffoldLinting ({
1254
+ projectRoot,
1255
+ projectType,
1256
+ packageManager,
1257
+ dialect,
1258
+ registries,
1259
+ configs,
1260
+ vcs,
1261
+ configureLinting,
1262
+ buildDirectory,
1263
+ eslint
1264
+ }) {
1265
+ return deepmerge.all(await Promise.all([scaffoldLockfileLint({
1266
+ projectRoot,
1267
+ packageManager,
1268
+ registries
1269
+ }), configs.eslint && configureLinting ? scaffoldEslint({
1270
+ projectRoot,
1271
+ config: configs.eslint,
1272
+ buildDirectory,
1273
+ additionalConfiguration: eslint
1274
+ }) : {}, scaffoldRemark({
1275
+ projectRoot,
1276
+ projectType,
1277
+ dialect,
1278
+ vcs,
1279
+ config: configs.remark || '@form8ion/remark-lint-preset'
1280
+ }), vcs ? scaffoldBanSensitiveFiles() : {}]));
1281
+ }
1282
+
1283
+ async function scaffoldVerification({
1284
+ projectRoot,
1285
+ projectType,
1286
+ dialect,
1287
+ visibility,
1288
+ packageManager,
1289
+ vcs,
1290
+ configs,
1291
+ registries,
1292
+ configureLinting,
1293
+ tests,
1294
+ unitTestFrameworks,
1295
+ decisions,
1296
+ buildDirectory,
1297
+ eslintConfigs
1298
+ }) {
1299
+ const [testingResults, huskyResults] = await Promise.all([scaffoldTesting({
1300
+ projectRoot,
1301
+ tests,
1302
+ visibility,
1303
+ vcs,
1304
+ unitTestFrameworks,
1305
+ decisions,
1306
+ dialect
1307
+ }), scaffold$4({
1308
+ projectRoot,
1309
+ packageManager
1310
+ })]);
1311
+ const lintingResults = await scaffoldLinting({
1312
+ projectRoot,
1313
+ projectType,
1314
+ packageManager,
1315
+ dialect,
1316
+ configs,
1317
+ registries,
1318
+ vcs,
1319
+ configureLinting,
1320
+ buildDirectory,
1321
+ eslint: deepmerge.all([testingResults.eslint, {
1322
+ configs: testingResults.eslintConfigs
1323
+ }, {
1324
+ configs: eslintConfigs
1325
+ }])
1326
+ });
1327
+ return deepmerge.all([testingResults, lintingResults, huskyResults]);
1328
+ }
1329
+
1330
+ async function scaffold(options) {
1331
+ info('Initializing JavaScript project');
1332
+ const {
1333
+ projectRoot,
1334
+ projectName,
1335
+ visibility,
1336
+ license,
1337
+ vcs,
1338
+ description,
1339
+ configs,
1340
+ overrides,
1341
+ ciServices,
1342
+ hosts,
1343
+ applicationTypes,
1344
+ packageTypes,
1345
+ monorepoTypes,
1346
+ decisions,
1347
+ unitTestFrameworks,
1348
+ pathWithinParent,
1349
+ registries
1350
+ } = validate(options);
1351
+ const {
1352
+ tests,
1353
+ projectType,
1354
+ ci,
1355
+ chosenHost,
1356
+ scope,
1357
+ nodeVersionCategory,
1358
+ author,
1359
+ configureLinting,
1360
+ packageManager,
1361
+ dialect
1362
+ } = await prompt(overrides, ciServices, hosts, visibility, vcs, decisions, configs, pathWithinParent);
1363
+ info('Writing project files', {
1364
+ level: 'secondary'
1365
+ });
1366
+ const packageName = buildPackageName(projectName, scope);
1367
+ const projectTypeResults = await scaffoldProjectType({
1368
+ projectType,
1369
+ projectRoot,
1370
+ projectName,
1371
+ packageName,
1372
+ packageManager,
1373
+ visibility,
1374
+ applicationTypes,
1375
+ packageTypes,
1376
+ monorepoTypes,
1377
+ scope,
1378
+ tests,
1379
+ vcs,
1380
+ decisions,
1381
+ dialect
1382
+ });
1383
+ const verificationResults = await scaffoldVerification({
1384
+ projectRoot,
1385
+ projectType,
1386
+ dialect,
1387
+ packageManager,
1388
+ visibility,
1389
+ vcs,
1390
+ configs,
1391
+ registries,
1392
+ configureLinting,
1393
+ tests,
1394
+ unitTestFrameworks,
1395
+ decisions,
1396
+ buildDirectory: projectTypeResults.buildDirectory,
1397
+ eslintConfigs: projectTypeResults.eslintConfigs
1398
+ });
1399
+ const [nodeVersion, npmResults, dialectResults] = await Promise.all([scaffoldNodeVersion({
1400
+ projectRoot,
1401
+ nodeVersionCategory
1402
+ }), scaffoldNpmConfig({
1403
+ projectType,
1404
+ projectRoot,
1405
+ registries
1406
+ }), scaffoldDialect({
1407
+ dialect,
1408
+ configs,
1409
+ projectRoot,
1410
+ projectType,
1411
+ tests,
1412
+ buildDirectory: projectTypeResults.buildDirectory,
1413
+ testFilenamePattern: verificationResults.testFilenamePattern
1414
+ })]);
1415
+ const mergedContributions = deepmerge.all([...(await Promise.all([scaffoldChoice(hosts, chosenHost, {
1416
+ buildDirectory: `./${projectTypeResults.buildDirectory}`,
1417
+ projectRoot,
1418
+ projectName,
1419
+ nodeVersion
1420
+ }), scaffoldChoice(ciServices, ci, {
1421
+ projectRoot,
1422
+ vcs,
1423
+ visibility,
1424
+ projectType,
1425
+ projectName,
1426
+ nodeVersion,
1427
+ tests
1428
+ }), scaffold$5({
1429
+ projectRoot,
1430
+ projectType,
1431
+ configs,
1432
+ pathWithinParent
1433
+ })])), projectTypeResults, verificationResults, npmResults, dialectResults]);
1434
+ const {
1435
+ homepage: projectHomepage
1436
+ } = await scaffoldPackage({
1437
+ projectRoot,
1438
+ projectType,
1439
+ dialect,
1440
+ packageName,
1441
+ license,
1442
+ vcs,
1443
+ author,
1444
+ description,
1445
+ packageProperties: mergedContributions.packageProperties,
1446
+ scripts: mergedContributions.scripts,
1447
+ pathWithinParent
1448
+ });
1449
+ const liftResults = await lift({
1450
+ results: deepmerge({
1451
+ devDependencies: ['npm-run-all'],
1452
+ packageManager
1453
+ }, mergedContributions),
1454
+ projectRoot,
1455
+ configs
1456
+ });
1457
+ return {
1458
+ badges: buildBadgesDetails([mergedContributions, liftResults]),
1459
+ documentation: scaffoldDocumentation({
1460
+ projectTypeResults,
1461
+ packageManager
1462
+ }),
1463
+ tags: projectTypeResults.tags,
1464
+ vcsIgnore: buildVcsIgnoreLists(mergedContributions.vcsIgnore),
1465
+ verificationCommand: `${buildDocumentationCommand(packageManager)} && ${packageManager} test`,
1466
+ projectDetails: _objectSpread2({}, projectHomepage && {
1467
+ homepage: projectHomepage
1468
+ }),
1469
+ nextSteps: mergedContributions.nextSteps
1470
+ };
1471
+ }
1472
+
1473
+ const questionNames = _objectSpread2(_objectSpread2({}, questionNames$2), questionNames$1);
1474
+
1475
+ export { questionNames, scaffold, scaffoldUnitTesting };
95
1476
  //# sourceMappingURL=index.es.js.map