@form8ion/javascript 6.0.9 → 6.1.0-alpha.1

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,93 @@ 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
+ commitlint: joi.object({
375
+ packageName: joi.string().required(),
376
+ name: joi.string().required()
377
+ }),
378
+ babelPreset: joi.object({
379
+ packageName: joi.string().required(),
380
+ name: joi.string().required()
381
+ }),
382
+ remark: joi.string()
383
+ }).default({})
384
+ })
385
+ .keys({
386
+ overrides: joi.object({
387
+ npmAccount: joi.string(),
388
+ author: joi.object({
389
+ name: joi.string().required(),
390
+ email: joi.string().email(),
391
+ url: joi.string().uri()
392
+ })
393
+ }).default({})
394
+ })
395
+ .keys({
396
+ ciServices: joi.object().pattern(/^/, joi.object({
397
+ scaffolder: joi.func().arity(1).required(),
398
+ public: joi.boolean(),
399
+ private: joi.boolean()
400
+ })).default({})
401
+ })
402
+ .keys({
403
+ hosts: joi.object().pattern(/^/, joi.object({
404
+ scaffolder: joi.func().arity(1).required(),
405
+ projectTypes: joi.array().items(joi.string().valid('static', 'node')).default([])
406
+ })).default({})
407
+ })
408
+ .keys({
409
+ applicationTypes: joi.object().pattern(/^/, joi.object({
410
+ scaffolder: joi.func().arity(1).required()
411
+ })).default({}),
412
+ packageTypes: joi.object().pattern(/^/, joi.object({
413
+ scaffolder: joi.func().arity(1).required()
414
+ })).default({}),
415
+ monorepoTypes: joi.object().pattern(/^/, joi.object({
416
+ scaffolder: joi.func().arity(1).required()
417
+ }))
418
+ })
419
+ .keys({
420
+ unitTestFrameworks: unitTestFrameworksSchema,
421
+ packageBundlers: packageBundlersSchema
422
+ })
423
+ .keys({
424
+ decisions: joi.object()
425
+ })
426
+ .keys({registries: joi.object().pattern(joi.string(), joi.string().uri()).default({})});
427
+ const {error, value} = schema.validate(options);
428
+
554
429
  hoek.assert(!error, error);
430
+
555
431
  return value;
556
432
  }
557
433
 
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
- }] : [])];
434
+ function buildDialectChoices ({babelPreset, typescript}) {
435
+ return [
436
+ {name: 'Common JS (no transpilation)', value: dialects.COMMON_JS, short: 'cjs'},
437
+ ...babelPreset ? [{name: 'Modern JavaScript (transpiled)', value: dialects.BABEL, short: 'modern'}] : [],
438
+ {name: 'ESM-only (no transpilation)', value: dialects.ESM, short: 'esm'},
439
+ ...typescript ? [{name: 'TypeScript', value: dialects.TYPESCRIPT, short: 'ts'}] : []
440
+ ];
579
441
  }
580
442
 
581
443
  function projectIsPackage(answers) {
@@ -601,9 +463,11 @@ function willBePublishedToNpm(answers) {
601
463
  function shouldBeScopedPromptShouldBePresented(answers) {
602
464
  return willBePublishedToNpm(answers);
603
465
  }
466
+
604
467
  function scopePromptShouldBePresentedFactory(visibility) {
605
468
  return answers => willBePublishedToNpm(answers) && packageShouldBeScoped(visibility, answers);
606
469
  }
470
+
607
471
  function lintingPromptShouldBePresented({
608
472
  [questionNames$2.UNIT_TESTS]: unitTested,
609
473
  [questionNames$2.INTEGRATION_TESTS]: integrationTested
@@ -621,38 +485,45 @@ function scope(visibility) {
621
485
  };
622
486
  }
623
487
 
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) {
488
+ function authorQuestions({name, email, url}) {
489
+ return [
490
+ {
491
+ name: questionNames$1.AUTHOR_NAME,
492
+ message: 'What is the author\'s name?',
493
+ default: name
494
+ },
495
+ {
496
+ name: questionNames$1.AUTHOR_EMAIL,
497
+ message: 'What is the author\'s email?',
498
+ default: email
499
+ },
500
+ {
501
+ name: questionNames$1.AUTHOR_URL,
502
+ message: 'What is the author\'s website url?',
503
+ default: url
504
+ }
505
+ ];
506
+ }
507
+
508
+ async function prompt(
509
+ {npmAccount, author},
510
+ ciServices,
511
+ hosts,
512
+ visibility,
513
+ vcs,
514
+ decisions,
515
+ configs,
516
+ pathWithinParent
517
+ ) {
648
518
  const npmConf$1 = npmConf();
649
- let maybeLoggedInNpmUsername;
650
519
 
520
+ let maybeLoggedInNpmUsername;
651
521
  try {
652
522
  maybeLoggedInNpmUsername = (await execa('npm', ['whoami'])).stdout;
653
523
  } catch (failedExecutionResult) {
654
524
  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.');
525
+ warn('No logged in user found with `npm whoami`. Login with `npm login` '
526
+ + 'to use your npm account name as the package scope default.');
656
527
  }
657
528
  }
658
529
 
@@ -670,89 +541,85 @@ async function prompt({
670
541
  [questionNames$1.CONFIGURE_LINTING]: configureLinting,
671
542
  [questionNames$1.PACKAGE_MANAGER]: packageManager,
672
543
  [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
544
+ } = await prompt$1([
545
+ {
546
+ name: questionNames$1.DIALECT,
547
+ message: 'Which JavaScript dialect should this project follow?',
548
+ type: 'list',
549
+ choices: buildDialectChoices(configs),
550
+ default: 'babel'
551
+ },
552
+ ...pathWithinParent ? [] : [{
553
+ name: questionNames$1.NODE_VERSION_CATEGORY,
554
+ message: 'What node.js version should be used?',
555
+ type: 'list',
556
+ choices: ['LTS', 'Latest'],
557
+ default: 'LTS'
558
+ }],
559
+ {
560
+ name: questionNames$1.PACKAGE_MANAGER,
561
+ message: 'Which package manager will be used with this project?',
562
+ type: 'list',
563
+ choices: Object.values(packageManagers),
564
+ default: packageManagers.NPM
565
+ },
566
+ {
567
+ name: questionNames$1.PROJECT_TYPE,
568
+ message: 'What type of JavaScript project is this?',
569
+ type: 'list',
570
+ choices: [...Object.values(projectTypes), new Separator(), 'Other'],
571
+ default: projectTypes.PACKAGE
572
+ },
573
+ ...'Private' === visibility ? [] : [{
574
+ name: questionNames$1.SHOULD_BE_SCOPED,
575
+ message: 'Should this package be scoped?',
576
+ type: 'confirm',
577
+ when: shouldBeScopedPromptShouldBePresented,
578
+ default: true
579
+ }],
580
+ {
581
+ name: questionNames$1.SCOPE,
582
+ message: 'What is the scope?',
583
+ when: scopePromptShouldBePresentedFactory(visibility),
584
+ validate: scope(visibility),
585
+ default: npmAccount || maybeLoggedInNpmUsername
586
+ },
587
+ ...authorQuestions(author || {
588
+ name: npmConf$1.get('init.author.name'),
589
+ email: npmConf$1.get('init.author.email'),
590
+ url: npmConf$1.get('init.author.url')
591
+ }),
592
+ ...questions(({vcs, ciServices, visibility, pathWithinParent})),
593
+ {
594
+ name: questionNames$1.CONFIGURE_LINTING,
595
+ message: 'Will there be source code that should be linted?',
596
+ type: 'confirm',
597
+ when: lintingPromptShouldBePresented
734
598
  },
599
+ {
600
+ name: questionNames$1.HOST,
601
+ type: 'list',
602
+ message: 'Where will the application be hosted?',
603
+ when: projectIsApplication,
604
+ choices: [...Object.keys(hosts), new Separator(), 'Other']
605
+ }
606
+ ], decisions);
607
+
608
+ return {
609
+ tests: {unit: unitTested, integration: integrationTested},
735
610
  projectType,
736
611
  ci,
737
612
  chosenHost,
738
613
  scope: scope$1,
739
614
  nodeVersionCategory,
740
- author: {
741
- name: authorName,
742
- email: authorEmail,
743
- url: authorUrl
744
- },
615
+ author: {name: authorName, email: authorEmail, url: authorUrl},
745
616
  configureLinting: false !== configureLinting,
746
617
  packageManager,
747
618
  dialect
748
619
  };
749
620
  }
750
621
 
751
- async function scaffoldBabel ({
752
- projectRoot,
753
- preset,
754
- buildDirectory
755
- }) {
622
+ async function scaffoldBabel ({projectRoot, preset, buildDirectory}) {
756
623
  if (!preset) {
757
624
  throw new Error('No babel preset provided. Cannot configure babel transpilation');
758
625
  }
@@ -761,74 +628,50 @@ async function scaffoldBabel ({
761
628
  path: projectRoot,
762
629
  name: 'babel',
763
630
  format: fileTypes.JSON,
764
- config: {
765
- presets: [preset.name],
766
- ignore: [`./${buildDirectory}/`]
767
- }
631
+ config: {presets: [preset.name], ignore: [`./${buildDirectory}/`]}
768
632
  });
633
+
769
634
  return {
770
635
  devDependencies: ['@babel/register', preset.packageName],
771
636
  eslint: {}
772
637
  };
773
638
  }
774
639
 
775
- async function scaffoldTypescript ({
776
- config,
777
- projectType,
778
- projectRoot,
779
- testFilenamePattern
780
- }) {
640
+ async function scaffoldTypescript ({config, projectType, projectRoot, testFilenamePattern}) {
781
641
  const eslintConfigs = ['typescript'];
782
642
  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
- })));
643
+
644
+ await promises.writeFile(
645
+ `${projectRoot}/tsconfig.json`,
646
+ JSON.stringify({
647
+ $schema: 'https://json.schemastore.org/tsconfig',
648
+ extends: shareableTsConfigPackage,
649
+ compilerOptions: {
650
+ rootDir: 'src',
651
+ ...projectTypes.PACKAGE === projectType && {
652
+ outDir: 'lib',
653
+ declaration: true
654
+ }
655
+ },
656
+ include: ['src/**/*.ts'],
657
+ ...testFilenamePattern && {exclude: [testFilenamePattern]}
658
+ })
659
+ );
660
+
796
661
  return {
797
- eslint: {
798
- configs: eslintConfigs
799
- },
662
+ eslint: {configs: eslintConfigs},
800
663
  eslintConfigs,
801
664
  devDependencies: ['typescript', shareableTsConfigPackage],
802
- vcsIgnore: {
803
- files: ['tsconfig.tsbuildinfo']
804
- }
665
+ vcsIgnore: {files: ['tsconfig.tsbuildinfo']}
805
666
  };
806
667
  }
807
668
 
808
- function scaffoldDialect ({
809
- dialect,
810
- projectType,
811
- projectRoot,
812
- configs,
813
- buildDirectory,
814
- testFilenamePattern
815
- }) {
669
+ function scaffoldDialect ({dialect, projectType, projectRoot, configs, buildDirectory, testFilenamePattern}) {
816
670
  switch (dialect) {
817
671
  case dialects.BABEL:
818
- return scaffoldBabel({
819
- preset: configs.babelPreset,
820
- projectRoot,
821
- buildDirectory
822
- });
823
-
672
+ return scaffoldBabel({preset: configs.babelPreset, projectRoot, buildDirectory});
824
673
  case dialects.TYPESCRIPT:
825
- return scaffoldTypescript({
826
- config: configs.typescript,
827
- projectType,
828
- projectRoot,
829
- testFilenamePattern
830
- });
831
-
674
+ return scaffoldTypescript({config: configs.typescript, projectType, projectRoot, testFilenamePattern});
832
675
  default:
833
676
  return {};
834
677
  }
@@ -843,34 +686,38 @@ async function scaffoldNpmConfig ({
843
686
  projectType,
844
687
  registries
845
688
  }) {
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
- };
689
+ await promises.writeFile(
690
+ `${projectRoot}/.npmrc`,
691
+ stringify({
692
+ 'update-notifier': false,
693
+ ...projectWillNotBeConsumed(projectType) && {'save-exact': true},
694
+ ...Object.fromEntries(Object.entries(registries)
695
+ .filter(([scope]) => 'publish' !== scope)
696
+ .map(([scope, url]) => {
697
+ if ('registry' === scope) return ['registry', url];
698
+
699
+ return [`@${scope}:registry`, url];
700
+ }))
701
+ })
702
+ );
703
+
704
+ return {scripts: {'lint:peer': 'npm ls >/dev/null'}};
859
705
  }
860
706
 
861
707
  function buildDocumentationCommand (packageManager) {
862
708
  if (packageManagers.NPM === packageManager) return 'npm run generate:md';
863
709
  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.`);
710
+
711
+ throw new Error(
712
+ `The ${packageManager} package manager is currently not supported. `
713
+ + `Only ${Object.values(packageManagers).join(' and ')} are currently supported.`
714
+ );
865
715
  }
866
716
 
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), {}, {
717
+ function scaffoldDocumentation ({projectTypeResults, packageManager}) {
718
+ return {
719
+ toc: `Run \`${buildDocumentationCommand(packageManager)}\` to generate a table of contents`,
720
+ ...projectTypeResults.documentation,
874
721
  contributing: `### Dependencies
875
722
 
876
723
  \`\`\`sh
@@ -883,43 +730,43 @@ $ ${packageManager} install
883
730
  \`\`\`sh
884
731
  $ ${packageManager} test
885
732
  \`\`\``
886
- });
733
+ };
887
734
  }
888
735
 
889
736
  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
- });
737
+ info('Determining version of node', {level: 'secondary'});
738
+
739
+ const {stdout: nvmLsOutput} = await execa(
740
+ `. ~/.nvm/nvm.sh && nvm ls-remote${('LTS' === nodeVersionCategory) ? ' --lts' : ''}`,
741
+ {shell: true}
742
+ );
743
+
898
744
  const lsLines = nvmLsOutput.split('\n');
899
745
  const lsLine = lsLines[lsLines.length - 2];
746
+
900
747
  return lsLine.match(/(v[0-9]+)\.[0-9]+\.[0-9]+/)[1];
901
748
  }
749
+
902
750
  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
- });
751
+ info(`Installing ${nodeVersionCategory} version of node using nvm`, {level: 'secondary'});
752
+
753
+ const subprocess = execa('. ~/.nvm/nvm.sh && nvm install', {shell: true});
909
754
  subprocess.stdout.pipe(process.stdout);
910
755
  return subprocess;
911
756
  }
912
757
 
913
- async function scaffoldNodeVersion ({
914
- projectRoot,
915
- nodeVersionCategory
916
- }) {
758
+ async function scaffoldNodeVersion ({projectRoot, nodeVersionCategory}) {
917
759
  if (!nodeVersionCategory) return undefined;
760
+
918
761
  const lowerCaseCategory = nodeVersionCategory.toLowerCase();
919
762
  info(`Configuring ${lowerCaseCategory} version of node`);
763
+
920
764
  const version = await determineLatestVersionOf(nodeVersionCategory);
765
+
921
766
  await promises.writeFile(`${projectRoot}/.nvmrc`, version);
767
+
922
768
  await install(nodeVersionCategory);
769
+
923
770
  return version;
924
771
  }
925
772
 
@@ -930,54 +777,52 @@ function buildBadgesDetails (contributors) {
930
777
  function buildVcsIgnoreLists (vcsIgnoreLists = {}) {
931
778
  return {
932
779
  files: vcsIgnoreLists.files || [],
933
- directories: ['/node_modules/', ...(vcsIgnoreLists.directories || [])]
780
+ directories: ['/node_modules/', ...vcsIgnoreLists.directories || []]
934
781
  };
935
782
  }
936
783
 
937
784
  function buildPackageName (projectName, scope) {
938
785
  const name = `${scope ? `@${scope}/` : ''}${projectName}`;
939
- const {
940
- validForNewPackages,
941
- errors
942
- } = validatePackageName(name);
786
+
787
+ const {validForNewPackages, errors} = validatePackageName(name);
788
+
943
789
  if (validForNewPackages) return name;
944
790
  if (1 === errors.length && errors.includes('name cannot start with a period')) return projectName.slice(1);
791
+
945
792
  throw new Error(`The package name ${name} is invalid:${EOL}\t* ${errors.join(`${EOL}\t* `)}`);
946
793
  }
947
794
 
948
- async function chooseApplicationType ({
949
- types,
950
- projectType,
951
- decisions
952
- }) {
795
+ async function chooseApplicationType ({types, projectType, decisions}) {
953
796
  if (!Object.keys(types).length) return 'Other';
797
+
954
798
  const answers = await prompt$1([{
955
799
  name: questionNames$1.PROJECT_TYPE_CHOICE,
956
800
  type: 'list',
957
801
  message: `What type of ${projectType} is this?`,
958
802
  choices: [...Object.keys(types), new Separator(), 'Other']
959
803
  }], decisions);
804
+
960
805
  return answers[questionNames$1.PROJECT_TYPE_CHOICE];
961
806
  }
962
807
 
963
808
  function getInstallationCommand(packageManager) {
964
809
  if (packageManagers.NPM === packageManager) return 'npm install';
965
810
  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.`);
811
+
812
+ throw new Error(
813
+ `The ${packageManager} package manager is currently not supported. `
814
+ + `Only ${Object.values(packageManagers).join(' and ')} are currently supported.`
815
+ );
967
816
  }
968
817
 
969
- function scaffoldPackageDocumentation ({
970
- scope,
971
- packageName,
972
- packageManager,
973
- visibility
974
- }) {
818
+ function scaffoldPackageDocumentation ({scope, packageName, packageManager, visibility}) {
975
819
  return {
976
820
  usage: `### Installation
977
821
  ${'Private' === visibility ? `
978
822
  :warning: this is a private package, so you will need to use an npm token with
979
823
  access to private packages under \`@${scope}\`
980
- ` : ''}
824
+ ` : ''
825
+ }
981
826
  \`\`\`sh
982
827
  $ ${getInstallationCommand(packageManager)} ${packageName}
983
828
  \`\`\`
@@ -990,49 +835,56 @@ run \`${buildDocumentationCommand(packageManager)}\` to inject the usage example
990
835
 
991
836
  function defineBadges (packageName, visibility) {
992
837
  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}`
838
+ consumer: {
839
+ ...'Public' === visibility && {
840
+ npm: {
841
+ img: `https://img.shields.io/npm/v/${packageName}?logo=npm`,
842
+ text: 'npm',
843
+ link: `https://www.npmjs.com/package/${packageName}`
844
+ }
998
845
  }
999
- }),
846
+ },
1000
847
  status: {}
1001
848
  };
1002
849
  }
1003
850
 
1004
- async function chooseBundler ({
1005
- bundlers,
1006
- decisions
1007
- }) {
851
+ async function chooseBundler ({bundlers, decisions}) {
1008
852
  if (!Object.keys(bundlers).length) return 'Other';
853
+
1009
854
  const answers = await prompt$1([{
1010
855
  name: questionNames$1.PACKAGE_BUNDLER,
1011
856
  type: 'list',
1012
857
  message: 'Which bundler should be used?',
1013
858
  choices: [...Object.keys(bundlers), new Separator(), 'Other']
1014
859
  }], decisions);
860
+
1015
861
  return answers[questionNames$1.PACKAGE_BUNDLER];
1016
862
  }
1017
863
 
1018
864
  function determinePathToTemplateFile (fileName) {
1019
865
  const [, __dirname] = filedirname();
866
+
1020
867
  return resolve(__dirname, '..', 'templates', fileName);
1021
868
  }
1022
869
 
1023
870
  const defaultBuildDirectory$2 = 'lib';
1024
871
 
1025
872
  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
- }));
873
+ return promises.writeFile(
874
+ `${projectRoot}/example.js`,
875
+ mustache.render(
876
+ await promises.readFile(determinePathToTemplateFile('example.mustache'), 'utf8'),
877
+ {projectName: camelcase(projectName)}
878
+ )
879
+ );
1029
880
  }
1030
881
 
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`)]);
882
+ async function buildDetailsForCommonJsProject({projectRoot, projectName}) {
883
+ await Promise.all([
884
+ touch(`${projectRoot}/index.js`),
885
+ promises.writeFile(`${projectRoot}/example.js`, `const ${camelcase(projectName)} = require('.');\n`)
886
+ ]);
887
+
1036
888
  return {};
1037
889
  }
1038
890
 
@@ -1045,42 +897,42 @@ async function buildDetails ({
1045
897
  dialect,
1046
898
  decisions
1047
899
  }) {
1048
- if (dialects.COMMON_JS === dialect) return buildDetailsForCommonJsProject({
1049
- projectRoot,
1050
- projectName
1051
- });
1052
- const chosenBundler = await chooseBundler({
1053
- bundlers: packageBundlers,
1054
- decisions
1055
- });
900
+ if (dialects.COMMON_JS === dialect) return buildDetailsForCommonJsProject({projectRoot, projectName});
901
+
902
+ const chosenBundler = await chooseBundler({bundlers: packageBundlers, decisions});
903
+
1056
904
  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}`
905
+ const [bundlerResults] = await Promise.all([
906
+ scaffoldChoice(packageBundlers, chosenBundler, {projectRoot, dialect, projectType: projectTypes.PACKAGE}),
907
+ await createExample(projectRoot, projectName),
908
+ touch(`${pathToCreatedSrcDirectory}/index.js`)
909
+ ]);
910
+
911
+ return deepmerge(
912
+ bundlerResults,
913
+ {
914
+ devDependencies: ['rimraf'],
915
+ scripts: {
916
+ clean: `rimraf ./${defaultBuildDirectory$2}`,
917
+ prebuild: 'run-s clean',
918
+ build: 'npm-run-all --print-label --parallel build:*',
919
+ prepack: 'run-s build'
920
+ },
921
+ vcsIgnore: {directories: [`/${defaultBuildDirectory$2}/`]},
922
+ buildDirectory: defaultBuildDirectory$2,
923
+ badges: {
924
+ consumer: {
925
+ ...'Public' === visibility && {
926
+ runkit: {
927
+ img: `https://badge.runkitcdn.com/${packageName}.svg`,
928
+ text: `Try ${packageName} on RunKit`,
929
+ link: `https://npm.runkit.com/${packageName}`
930
+ }
931
+ }
1080
932
  }
1081
- })
933
+ }
1082
934
  }
1083
- });
935
+ );
1084
936
  }
1085
937
 
1086
938
  async function scaffoldPackageType ({
@@ -1098,78 +950,70 @@ async function scaffoldPackageType ({
1098
950
  publishRegistry
1099
951
  }) {
1100
952
  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'
953
+
954
+ const [detailsForBuild] = await Promise.all([
955
+ buildDetails({projectRoot, projectName, packageBundlers, visibility, packageName, dialect, decisions}),
956
+ mergeIntoExistingPackageJson({
957
+ projectRoot,
958
+ config: {
959
+ files: ['example.js', ...dialects.COMMON_JS === dialect ? ['index.js'] : ['lib/']],
960
+ publishConfig: {
961
+ access: 'Public' === visibility ? 'public' : 'restricted',
962
+ ...publishRegistry && {registry: publishRegistry}
963
+ },
964
+ sideEffects: false,
965
+ ...'Public' === visibility && {runkitExampleFilename: './example.js'},
966
+ ...dialects.BABEL === dialect && {
967
+ main: './lib/index.cjs.js',
968
+ module: './lib/index.es.js',
969
+ exports: {
970
+ require: './lib/index.cjs.js',
971
+ import: './lib/index.es.js'
972
+ }
973
+ },
974
+ ...dialects.ESM === dialect && {
975
+ main: './lib/index.es.js',
976
+ exports: './lib/index.es.js'
977
+ },
978
+ ...dialects.TYPESCRIPT === dialect && {
979
+ main: './lib/index.cjs.js',
980
+ module: './lib/index.es.js',
981
+ types: './lib/index.d.ts',
982
+ exports: {
983
+ types: './lib/index.d.ts',
984
+ require: './lib/index.cjs.js',
985
+ import: './lib/index.es.js'
986
+ }
987
+ }
1139
988
  }
1140
989
  })
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]);
990
+ ]);
991
+
992
+ const chosenType = await chooseApplicationType({types: packageTypes, projectType: 'package', decisions});
993
+ const results = await scaffoldChoice(
994
+ packageTypes,
995
+ chosenType,
996
+ {projectRoot, projectName, packageName, tests, scope}
997
+ );
998
+
999
+ return deepmerge.all([
1000
+ {
1001
+ documentation: scaffoldPackageDocumentation({packageName, visibility, scope, packageManager}),
1002
+ eslintConfigs: [],
1003
+ nextSteps: [
1004
+ {summary: 'Add the appropriate `save` flag to the installation instructions in the README'},
1005
+ {summary: 'Publish pre-release versions to npm until package is stable enough to publish v1.0.0'}
1006
+ ],
1007
+ scripts: {},
1008
+ badges: defineBadges(packageName, visibility)
1009
+ },
1010
+ detailsForBuild,
1011
+ results
1012
+ ]);
1170
1013
  }
1171
1014
 
1172
1015
  const defaultBuildDirectory$1 = 'lib';
1016
+
1173
1017
  async function scaffoldApplicationType ({
1174
1018
  applicationTypes,
1175
1019
  projectRoot,
@@ -1180,112 +1024,94 @@ async function scaffoldApplicationType ({
1180
1024
  decisions
1181
1025
  }) {
1182
1026
  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
- });
1027
+
1028
+ const [chosenType] = await Promise.all([
1029
+ chooseApplicationType({types: applicationTypes, projectType: 'application', decisions}),
1030
+ mergeIntoExistingPackageJson({projectRoot, config: {private: true}})
1031
+ ]);
1032
+
1033
+ const results = await scaffoldChoice(
1034
+ applicationTypes,
1035
+ chosenType,
1036
+ {projectRoot, projectName, packageName, packageManager, tests}
1037
+ );
1038
+
1200
1039
  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}/`]
1040
+
1041
+ return deepmerge(
1042
+ {
1043
+ scripts: {
1044
+ clean: `rimraf ./${buildDirectory}`,
1045
+ start: `node ./${buildDirectory}/index.js`,
1046
+ prebuild: 'run-s clean'
1047
+ },
1048
+ dependencies: [],
1049
+ devDependencies: ['rimraf'],
1050
+ vcsIgnore: {files: ['.env'], directories: [`/${buildDirectory}/`]},
1051
+ buildDirectory,
1052
+ eslintConfigs: [],
1053
+ nextSteps: []
1212
1054
  },
1213
- buildDirectory,
1214
- eslintConfigs: [],
1215
- nextSteps: []
1216
- }, results);
1055
+ results
1056
+ );
1217
1057
  }
1218
1058
 
1219
- async function scaffoldMonorepoType ({
1220
- monorepoTypes,
1221
- projectRoot,
1222
- packageManager,
1223
- decisions
1224
- }) {
1059
+ async function scaffoldMonorepoType ({monorepoTypes, projectRoot, packageManager, decisions}) {
1225
1060
  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
1061
+
1062
+ const chosenType = await chooseApplicationType({types: monorepoTypes, projectType: projectTypes.MONOREPO, decisions});
1063
+ const results = await scaffoldChoice(monorepoTypes, chosenType, {projectRoot, packageManager});
1064
+
1065
+ return deepmerge(
1066
+ {
1067
+ eslintConfigs: [],
1068
+ packageProperties: {private: true},
1069
+ nextSteps: [{
1070
+ summary: 'Add packages to your new monorepo',
1071
+ description: 'Leverage [@form8ion/add-package-to-monorepo](https://npm.im/@form8ion/add-package-to-monorepo)'
1072
+ + ' to scaffold new packages into your new monorepo'
1073
+ }]
1239
1074
  },
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);
1075
+ results
1076
+ );
1245
1077
  }
1246
1078
 
1247
1079
  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
- })
1080
+
1081
+ async function scaffoldCliType ({packageName, visibility, projectRoot, dialect, publishRegistry}) {
1082
+ const [rollupResults] = await Promise.all([
1083
+ scaffold$1({projectRoot, dialect, projectType: projectTypes.CLI}),
1084
+ mergeIntoExistingPackageJson({
1085
+ projectRoot,
1086
+ config: {
1087
+ bin: {},
1088
+ files: [`${defaultBuildDirectory}/`],
1089
+ publishConfig: {
1090
+ access: 'Public' === visibility ? 'public' : 'restricted',
1091
+ ...publishRegistry && {registry: publishRegistry}
1092
+ }
1093
+ }
1094
+ })
1095
+ ]);
1096
+
1097
+ return deepmerge(
1098
+ rollupResults,
1099
+ {
1100
+ scripts: {
1101
+ clean: `rimraf ./${defaultBuildDirectory}`,
1102
+ prebuild: 'run-s clean',
1103
+ build: 'npm-run-all --print-label --parallel build:*',
1104
+ prepack: 'run-s build'
1105
+ },
1106
+ dependencies: ['update-notifier'],
1107
+ devDependencies: ['rimraf'],
1108
+ vcsIgnore: {files: [], directories: [`/${defaultBuildDirectory}/`]},
1109
+ buildDirectory: defaultBuildDirectory,
1110
+ badges: defineBadges(packageName, visibility),
1111
+ eslintConfigs: [],
1112
+ nextSteps: []
1269
1113
  }
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
- });
1114
+ );
1289
1115
  }
1290
1116
 
1291
1117
  async function scaffoldProjectType ({
@@ -1323,7 +1149,6 @@ async function scaffoldProjectType ({
1323
1149
  dialect,
1324
1150
  publishRegistry
1325
1151
  });
1326
-
1327
1152
  case projectTypes.APPLICATION:
1328
1153
  return scaffoldApplicationType({
1329
1154
  projectRoot,
@@ -1334,29 +1159,14 @@ async function scaffoldProjectType ({
1334
1159
  tests,
1335
1160
  decisions
1336
1161
  });
1337
-
1338
1162
  case projectTypes.CLI:
1339
- return scaffoldCliType({
1340
- packageName,
1341
- visibility,
1342
- projectRoot,
1343
- dialect,
1344
- publishRegistry
1345
- });
1346
-
1163
+ return scaffoldCliType({packageName, visibility, projectRoot, dialect, publishRegistry});
1347
1164
  case projectTypes.MONOREPO:
1348
- return scaffoldMonorepoType({
1349
- monorepoTypes,
1350
- projectRoot,
1351
- packageManager,
1352
- decisions
1353
- });
1354
-
1165
+ return scaffoldMonorepoType({monorepoTypes, projectRoot, packageManager, decisions});
1355
1166
  case 'Other':
1356
1167
  return {
1357
1168
  eslintConfigs: []
1358
1169
  };
1359
-
1360
1170
  default:
1361
1171
  throw new Error(`The project-type of ${projectType} is invalid`);
1362
1172
  }
@@ -1365,48 +1175,39 @@ async function scaffoldProjectType ({
1365
1175
  async function scaffoldTesting ({
1366
1176
  projectRoot,
1367
1177
  visibility,
1368
- tests: {
1369
- unit,
1370
- integration
1371
- },
1178
+ tests: {unit, integration},
1372
1179
  vcs,
1373
1180
  unitTestFrameworks,
1374
1181
  decisions,
1375
1182
  dialect,
1376
1183
  pathWithinParent
1377
1184
  }) {
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);
1185
+ const unitResults = unit
1186
+ ? await scaffoldUnitTesting({
1187
+ projectRoot,
1188
+ visibility,
1189
+ vcs,
1190
+ frameworks: unitTestFrameworks,
1191
+ decisions,
1192
+ dialect,
1193
+ pathWithinParent
1194
+ })
1195
+ : {};
1196
+
1197
+ return deepmerge({devDependencies: [...(unit || integration) ? ['@travi/any'] : []], eslint: {}}, unitResults);
1391
1198
  }
1392
1199
 
1393
- function scaffoldBanSensitiveFiles ({
1394
- pathWithinParent
1395
- }) {
1200
+ function scaffoldBanSensitiveFiles ({pathWithinParent}) {
1396
1201
  if (pathWithinParent) return {};
1397
- return {
1398
- scripts: {
1399
- 'lint:sensitive': 'ban'
1400
- },
1401
- devDependencies: ['ban-sensitive-files']
1402
- };
1202
+
1203
+ return {scripts: {'lint:sensitive': 'ban'}, devDependencies: ['ban-sensitive-files']};
1403
1204
  }
1404
1205
 
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)))];
1206
+ function buildAllowedHostsList ({packageManager, registries}) {
1207
+ return [
1208
+ ...(!registries || (registries && !registries.registry)) ? [packageManager] : [],
1209
+ ...Object.values(Object.fromEntries(Object.entries(registries).filter(([scope]) => 'publish' !== scope)))
1210
+ ];
1410
1211
  }
1411
1212
 
1412
1213
  const lockfileLintSupportedPackageManagers = [packageManagers.NPM, packageManagers.YARN];
@@ -1416,6 +1217,7 @@ function determineLockfilePathFor(packageManager) {
1416
1217
  [packageManagers.NPM]: 'package-lock.json',
1417
1218
  [packageManagers.YARN]: 'yarn.lock'
1418
1219
  };
1220
+
1419
1221
  return lockfilePaths[packageManager];
1420
1222
  }
1421
1223
 
@@ -1423,46 +1225,35 @@ function lockfileLintSupports(packageManager) {
1423
1225
  return lockfileLintSupportedPackageManagers.includes(packageManager);
1424
1226
  }
1425
1227
 
1426
- async function scaffoldLockfileLint ({
1427
- projectRoot,
1428
- packageManager,
1429
- registries
1430
- }) {
1228
+ async function scaffoldLockfileLint ({projectRoot, packageManager, registries}) {
1431
1229
  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.`);
1230
+ throw new Error(
1231
+ `The ${packageManager} package manager is currently not supported by lockfile-lint. `
1232
+ + `Only ${lockfileLintSupportedPackageManagers.join(' and ')} are currently supported.`
1233
+ );
1433
1234
  }
1434
1235
 
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
1236
+ await promises.writeFile(
1237
+ `${projectRoot}/.lockfile-lintrc.json`,
1238
+ JSON.stringify({
1239
+ path: determineLockfilePathFor(packageManager),
1240
+ type: packageManager,
1241
+ 'validate-https': true,
1242
+ 'allowed-hosts': buildAllowedHostsList({packageManager, registries})
1442
1243
  })
1443
- }));
1244
+ );
1245
+
1444
1246
  return {
1445
1247
  devDependencies: ['lockfile-lint'],
1446
- scripts: {
1447
- 'lint:lockfile': 'lockfile-lint'
1448
- }
1248
+ scripts: {'lint:lockfile': 'lockfile-lint'}
1449
1249
  };
1450
1250
  }
1451
1251
 
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
- }) : {}]));
1252
+ async function scaffoldLinting ({projectRoot, packageManager, registries, vcs, pathWithinParent}) {
1253
+ return deepmerge.all(await Promise.all([
1254
+ scaffoldLockfileLint({projectRoot, packageManager, registries}),
1255
+ vcs ? scaffoldBanSensitiveFiles({pathWithinParent}) : {}
1256
+ ]));
1466
1257
  }
1467
1258
 
1468
1259
  async function scaffoldVerification({
@@ -1477,60 +1268,33 @@ async function scaffoldVerification({
1477
1268
  decisions,
1478
1269
  pathWithinParent
1479
1270
  }) {
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
- })]);
1271
+ const [testingResults, lintingResults, huskyResults] = await Promise.all([
1272
+ scaffoldTesting({
1273
+ projectRoot,
1274
+ tests,
1275
+ visibility,
1276
+ vcs,
1277
+ unitTestFrameworks,
1278
+ decisions,
1279
+ dialect,
1280
+ pathWithinParent
1281
+ }),
1282
+ scaffoldLinting({projectRoot, packageManager, registries, vcs, pathWithinParent}),
1283
+ scaffold$2({projectRoot, packageManager, pathWithinParent})
1284
+ ]);
1285
+
1500
1286
  return deepmerge.all([testingResults, lintingResults, huskyResults]);
1501
1287
  }
1502
1288
 
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
- });
1289
+ async function scaffoldEslint ({config, projectRoot, buildDirectory, additionalConfiguration}) {
1290
+ const {scope} = config;
1291
+ const {ignore} = additionalConfiguration;
1292
+ const ignores = deepmerge(ignore, {directories: [`/${buildDirectory}/`]});
1293
+
1294
+ return scaffold$3({scope, projectRoot, ignore: {directories: ignores.directories}});
1525
1295
  }
1526
1296
 
1527
- async function scaffoldRemark ({
1528
- config,
1529
- projectRoot,
1530
- projectType,
1531
- vcs,
1532
- dialect
1533
- }) {
1297
+ async function scaffoldRemark ({config, projectRoot, projectType, vcs, dialect}) {
1534
1298
  await write({
1535
1299
  format: fileTypes.JSON,
1536
1300
  path: projectRoot,
@@ -1543,28 +1307,30 @@ async function scaffoldRemark ({
1543
1307
  bullet: '*',
1544
1308
  incrementListMarker: false
1545
1309
  },
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
- }]] : [])]
1310
+ plugins: [
1311
+ config,
1312
+ ['remark-toc', {tight: true}],
1313
+ ...projectTypes.PACKAGE === projectType ? [['remark-usage', {heading: 'example'}]] : [],
1314
+ ...!vcs ? [['validate-links', {repository: false}]] : []
1315
+ ]
1553
1316
  }
1554
1317
  });
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'
1318
+
1319
+ return deepmerge(
1320
+ {
1321
+ devDependencies: [config, 'remark-cli', 'remark-toc'],
1322
+ scripts: {
1323
+ 'lint:md': 'remark . --frail',
1324
+ 'generate:md': 'remark . --output'
1325
+ }
1326
+ },
1327
+ {
1328
+ ...projectTypes.PACKAGE === projectType && {
1329
+ devDependencies: ['remark-usage'],
1330
+ ...dialects.COMMON_JS !== dialect && {scripts: {'pregenerate:md': 'run-s build'}}
1331
+ }
1566
1332
  }
1567
- })));
1333
+ );
1568
1334
  }
1569
1335
 
1570
1336
  async function scaffoldCodeStyle ({
@@ -1577,22 +1343,28 @@ async function scaffoldCodeStyle ({
1577
1343
  buildDirectory,
1578
1344
  eslint
1579
1345
  }) {
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
- })]));
1346
+ return deepmerge.all(await Promise.all([
1347
+ configs.eslint && configureLinting
1348
+ && scaffoldEslint({
1349
+ projectRoot,
1350
+ config: configs.eslint,
1351
+ buildDirectory,
1352
+ additionalConfiguration: eslint
1353
+ }),
1354
+ scaffoldRemark({
1355
+ projectRoot,
1356
+ projectType,
1357
+ dialect,
1358
+ vcs,
1359
+ config: configs.remark || '@form8ion/remark-lint-preset'
1360
+ }),
1361
+ scaffold$4({projectRoot, config: configs.prettier})
1362
+ ].filter(Boolean)));
1592
1363
  }
1593
1364
 
1594
1365
  async function scaffolder (options) {
1595
1366
  info('Initializing JavaScript project');
1367
+
1596
1368
  const {
1597
1369
  projectRoot,
1598
1370
  projectName,
@@ -1613,6 +1385,7 @@ async function scaffolder (options) {
1613
1385
  pathWithinParent,
1614
1386
  registries
1615
1387
  } = validate(options);
1388
+
1616
1389
  const {
1617
1390
  tests,
1618
1391
  projectType,
@@ -1625,13 +1398,11 @@ async function scaffolder (options) {
1625
1398
  packageManager,
1626
1399
  dialect
1627
1400
  } = await prompt(overrides, ciServices, hosts, visibility, vcs, decisions, configs, pathWithinParent);
1628
- info('Writing project files', {
1629
- level: 'secondary'
1630
- });
1401
+
1402
+ info('Writing project files', {level: 'secondary'});
1403
+
1631
1404
  const packageName = buildPackageName(projectName, scope);
1632
- const {
1633
- homepage: projectHomepage
1634
- } = await scaffoldPackage({
1405
+ const {homepage: projectHomepage} = await scaffoldPackage({
1635
1406
  projectRoot,
1636
1407
  projectType,
1637
1408
  dialect,
@@ -1642,111 +1413,106 @@ async function scaffolder (options) {
1642
1413
  description,
1643
1414
  pathWithinParent
1644
1415
  });
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]);
1416
+ const [projectTypeResults, verificationResults] = await Promise.all([
1417
+ scaffoldProjectType({
1418
+ projectType,
1419
+ projectRoot,
1420
+ projectName,
1421
+ packageName,
1422
+ packageManager,
1423
+ visibility,
1424
+ applicationTypes,
1425
+ packageTypes,
1426
+ packageBundlers,
1427
+ monorepoTypes,
1428
+ scope,
1429
+ tests,
1430
+ vcs,
1431
+ decisions,
1432
+ dialect,
1433
+ publishRegistry: registries.publish
1434
+ }),
1435
+ scaffoldVerification({
1436
+ projectRoot,
1437
+ dialect,
1438
+ visibility,
1439
+ packageManager,
1440
+ vcs,
1441
+ registries,
1442
+ tests,
1443
+ unitTestFrameworks,
1444
+ decisions,
1445
+ pathWithinParent
1446
+ })
1447
+ ]);
1448
+ const [nodeVersion, npmResults, dialectResults, codeStyleResults] = await Promise.all([
1449
+ scaffoldNodeVersion({projectRoot, nodeVersionCategory}),
1450
+ scaffoldNpmConfig({projectType, projectRoot, registries}),
1451
+ scaffoldDialect({
1452
+ dialect,
1453
+ configs,
1454
+ projectRoot,
1455
+ projectType,
1456
+ buildDirectory: projectTypeResults.buildDirectory,
1457
+ testFilenamePattern: verificationResults.testFilenamePattern
1458
+ }),
1459
+ scaffoldCodeStyle({
1460
+ projectRoot,
1461
+ projectType,
1462
+ dialect,
1463
+ configs,
1464
+ vcs,
1465
+ configureLinting,
1466
+ buildDirectory: projectTypeResults.buildDirectory,
1467
+ eslint: verificationResults.eslint
1468
+ })
1469
+ ]);
1470
+ const mergedContributions = deepmerge.all([
1471
+ ...(await Promise.all([
1472
+ scaffoldChoice(
1473
+ hosts,
1474
+ chosenHost,
1475
+ {buildDirectory: `./${projectTypeResults.buildDirectory}`, projectRoot, projectName, nodeVersion}
1476
+ ),
1477
+ scaffoldChoice(ciServices, ci, {projectRoot, vcs, visibility, projectType, projectName, nodeVersion, tests}),
1478
+ scaffold$5({projectRoot, projectType, configs, pathWithinParent})
1479
+ ])),
1480
+ projectTypeResults,
1481
+ verificationResults,
1482
+ codeStyleResults,
1483
+ npmResults,
1484
+ dialectResults
1485
+ ]);
1486
+
1717
1487
  const liftResults = await lift({
1718
- results: deepmerge({
1719
- devDependencies: ['npm-run-all'],
1720
- packageManager
1721
- }, mergedContributions),
1488
+ results: deepmerge({devDependencies: ['npm-run-all'], packageManager}, mergedContributions),
1722
1489
  projectRoot,
1723
1490
  configs,
1724
1491
  vcs
1725
1492
  });
1493
+
1726
1494
  return {
1727
1495
  badges: buildBadgesDetails([mergedContributions, liftResults]),
1728
- documentation: scaffoldDocumentation({
1729
- projectTypeResults,
1730
- packageManager
1731
- }),
1496
+ documentation: scaffoldDocumentation({projectTypeResults, packageManager}),
1732
1497
  tags: projectTypeResults.tags,
1733
1498
  vcsIgnore: buildVcsIgnoreLists(mergedContributions.vcsIgnore),
1734
1499
  verificationCommand: `${buildDocumentationCommand(packageManager)} && ${packageManager} test`,
1735
- projectDetails: _objectSpread2({}, projectHomepage && {
1736
- homepage: projectHomepage
1737
- }),
1500
+ projectDetails: {...projectHomepage && {homepage: projectHomepage}},
1738
1501
  nextSteps: mergedContributions.nextSteps
1739
1502
  };
1740
1503
  }
1741
1504
 
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`)]);
1505
+ async function test ({projectRoot}) {
1506
+ const [nvmIsConfigured, packageLockExists, yarnLockExists] = await Promise.all([
1507
+ fileExists(`${projectRoot}/.nvmrc`),
1508
+ fileExists(`${projectRoot}/package-lock.json`),
1509
+ fileExists(`${projectRoot}/yarn.lock`)
1510
+ ]);
1511
+
1746
1512
  return nvmIsConfigured || packageLockExists || yarnLockExists;
1747
1513
  }
1748
1514
 
1749
- const questionNames = _objectSpread2(_objectSpread2({}, questionNames$2), questionNames$1);
1515
+ const questionNames = {...questionNames$2, ...questionNames$1};
1750
1516
 
1751
1517
  export { lift, questionNames, scaffolder as scaffold, scaffoldUnitTesting, test };
1752
1518
  //# sourceMappingURL=index.mjs.map