@form8ion/javascript 6.0.8 → 6.1.0-alpha.2

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