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