@form8ion/javascript 6.0.9 → 6.1.0-alpha.3

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