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