@form8ion/javascript 14.0.0-alpha.8 → 14.0.0-beta.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.js +1244 -1249
- package/lib/index.js.map +1 -1
- package/package.json +3 -3
package/lib/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { questionNames as questionNames$2, questions } from '@travi/language-scaffolder-prompts';
|
|
2
2
|
import deepmerge from 'deepmerge';
|
|
3
|
-
import { fileTypes, fileExists, optionsSchemas, validateOptions, loadConfigFile,
|
|
4
|
-
import { scaffoldChoice,
|
|
3
|
+
import { fileTypes, fileExists, optionsSchemas, validateOptions, loadConfigFile, writeConfigFile, applyEnhancers } from '@form8ion/core';
|
|
4
|
+
import { scaffoldChoice, dialects as dialects$1, projectTypes as projectTypes$1, packageManagers as packageManagers$1, writePackageJson, DEV_DEPENDENCY_TYPE, PROD_DEPENDENCY_TYPE, mergeIntoExistingPackageJson } from '@form8ion/javascript-core';
|
|
5
5
|
import { prompt as prompt$1 } from '@form8ion/overridable-prompts';
|
|
6
6
|
import joi from 'joi';
|
|
7
7
|
import { scaffold, lift as lift$3 } from '@form8ion/codecov';
|
|
8
8
|
import { write as write$2 } from '@form8ion/config-file';
|
|
9
|
-
import {
|
|
9
|
+
import { warn, info, error } from '@travi/cli-messages';
|
|
10
10
|
import * as commitConventionPlugin from '@form8ion/commit-convention';
|
|
11
11
|
import { scaffold as scaffold$4 } from '@form8ion/commit-convention';
|
|
12
12
|
import { execa } from 'execa';
|
|
@@ -21,12 +21,12 @@ import camelcase from 'camelcase';
|
|
|
21
21
|
import { resolve } from 'path';
|
|
22
22
|
import filedirname from 'filedirname';
|
|
23
23
|
import * as huskyPlugin from '@form8ion/husky';
|
|
24
|
-
import { scaffold as scaffold$
|
|
24
|
+
import { scaffold as scaffold$1 } from '@form8ion/husky';
|
|
25
25
|
import { promises as promises$1 } from 'node:fs';
|
|
26
26
|
import { stringify, parse } from 'ini';
|
|
27
|
-
import { scaffold as scaffold$
|
|
27
|
+
import { scaffold as scaffold$3 } from '@form8ion/prettier';
|
|
28
28
|
import * as eslintPlugin from '@form8ion/eslint';
|
|
29
|
-
import { scaffold as scaffold$
|
|
29
|
+
import { scaffold as scaffold$2, test as test$1 } from '@form8ion/eslint';
|
|
30
30
|
import sortProperties from 'sort-object-keys';
|
|
31
31
|
|
|
32
32
|
const questionNames$1 = {
|
|
@@ -157,189 +157,357 @@ async function scaffoldUnitTesting ({projectRoot, frameworks, decisions, visibil
|
|
|
157
157
|
]);
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
-
|
|
161
|
-
return true;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
function buildAllowedHostsList ({packageManager, registries = {}}) {
|
|
165
|
-
return [
|
|
166
|
-
...!registries.registry ? [packageManager] : [],
|
|
167
|
-
...Object.values(Object.fromEntries(Object.entries(registries).filter(([scope]) => 'publish' !== scope)))
|
|
168
|
-
];
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
async function scaffoldNpm ({projectRoot}) {
|
|
172
|
-
const [packageContents, {stdout}] = await Promise.all([
|
|
173
|
-
promises$1.readFile(`${projectRoot}/package.json`, 'utf-8'),
|
|
174
|
-
execa('npm', ['--version'])
|
|
175
|
-
]);
|
|
176
|
-
const existingPackageJsonContents = JSON.parse(packageContents);
|
|
177
|
-
|
|
178
|
-
await writePackageJson({
|
|
179
|
-
projectRoot,
|
|
180
|
-
config: {
|
|
181
|
-
...existingPackageJsonContents,
|
|
182
|
-
packageManager: `npm@${stdout}`
|
|
183
|
-
}
|
|
184
|
-
});
|
|
185
|
-
}
|
|
160
|
+
const scopeBasedConfigSchema = joi.object({scope: joi.string().regex(/^@[a-z0-9-]+$/i, 'scope').required()});
|
|
186
161
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
};
|
|
162
|
+
const nameBasedConfigSchema = joi.object({
|
|
163
|
+
packageName: joi.string().required(),
|
|
164
|
+
name: joi.string().required()
|
|
165
|
+
});
|
|
192
166
|
|
|
193
|
-
|
|
194
|
-
}
|
|
167
|
+
const registriesSchema = joi.object().pattern(joi.string(), joi.string().uri()).default({});
|
|
195
168
|
|
|
196
|
-
|
|
197
|
-
const [packageManager] = pinnedPackageManager.split('@');
|
|
169
|
+
const visibilitySchema = joi.string().valid('Public', 'Private').required();
|
|
198
170
|
|
|
199
|
-
|
|
200
|
-
|| fileExists(`${projectRoot}/${determineLockfilePathFor(packageManagers$1.NPM)}`);
|
|
201
|
-
}
|
|
171
|
+
const projectNameSchema = joi.string().regex(/^@\w*\//, {invert: true}).required();
|
|
202
172
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
const existingPackageJsonContents = JSON.parse(packageContents);
|
|
173
|
+
const vcsSchema = joi.object({
|
|
174
|
+
host: joi.string().required(),
|
|
175
|
+
owner: joi.string().required(),
|
|
176
|
+
name: joi.string().required()
|
|
177
|
+
});
|
|
209
178
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
179
|
+
function validate(options) {
|
|
180
|
+
const schema = joi.object({
|
|
181
|
+
projectRoot: joi.string().required(),
|
|
182
|
+
projectName: projectNameSchema,
|
|
183
|
+
visibility: visibilitySchema,
|
|
184
|
+
license: joi.string().required(),
|
|
185
|
+
description: joi.string(),
|
|
186
|
+
pathWithinParent: joi.string(),
|
|
187
|
+
decisions: joi.object(),
|
|
188
|
+
vcs: vcsSchema,
|
|
189
|
+
configs: joi.object({
|
|
190
|
+
eslint: scopeBasedConfigSchema,
|
|
191
|
+
typescript: scopeBasedConfigSchema,
|
|
192
|
+
prettier: scopeBasedConfigSchema,
|
|
193
|
+
commitlint: nameBasedConfigSchema,
|
|
194
|
+
babelPreset: nameBasedConfigSchema,
|
|
195
|
+
remark: joi.string(),
|
|
196
|
+
registries: registriesSchema
|
|
197
|
+
}).default({registries: {}}),
|
|
198
|
+
plugins: {
|
|
199
|
+
unitTestFrameworks: pluginsSchema,
|
|
200
|
+
packageBundlers: pluginsSchema,
|
|
201
|
+
applicationTypes: pluginsSchema,
|
|
202
|
+
packageTypes: pluginsSchema,
|
|
203
|
+
monorepoTypes: pluginsSchema,
|
|
204
|
+
hosts: pluginsSchema,
|
|
205
|
+
ciServices: pluginsSchema
|
|
215
206
|
}
|
|
216
|
-
});
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
function yarnIsUsed ({projectRoot, pinnedPackageManager = ''}) {
|
|
220
|
-
const [packageManager] = pinnedPackageManager.split('@');
|
|
207
|
+
}).required();
|
|
221
208
|
|
|
222
|
-
return
|
|
223
|
-
|| fileExists(`${projectRoot}/${determineLockfilePathFor(packageManagers$1.YARN)}`);
|
|
209
|
+
return validateOptions(schema, options);
|
|
224
210
|
}
|
|
225
211
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
212
|
+
function buildDialectChoices ({babelPreset, typescript}) {
|
|
213
|
+
return [
|
|
214
|
+
{name: 'Common JS (no transpilation)', value: dialects$1.COMMON_JS, short: 'cjs'},
|
|
215
|
+
...babelPreset ? [{name: 'Modern JavaScript (transpiled)', value: dialects$1.BABEL, short: 'modern'}] : [],
|
|
216
|
+
{name: 'ESM-only (no transpilation)', value: dialects$1.ESM, short: 'esm'},
|
|
217
|
+
...typescript ? [{name: 'TypeScript', value: dialects$1.TYPESCRIPT, short: 'ts'}] : []
|
|
218
|
+
];
|
|
233
219
|
}
|
|
234
220
|
|
|
235
|
-
|
|
236
|
-
|
|
221
|
+
function projectIsCLI(answers) {
|
|
222
|
+
return projectTypes$1.CLI === answers[questionNames$1.PROJECT_TYPE];
|
|
237
223
|
}
|
|
238
224
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
return {};
|
|
225
|
+
function projectIsPackage(answers) {
|
|
226
|
+
return projectTypes$1.PACKAGE === answers[questionNames$1.PROJECT_TYPE];
|
|
243
227
|
}
|
|
244
228
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
yarn: scaffoldYarn
|
|
248
|
-
};
|
|
249
|
-
|
|
250
|
-
function scaffoldPackageManager ({projectRoot, packageManager}) {
|
|
251
|
-
return scaffolders[packageManager]({projectRoot});
|
|
229
|
+
function projectIsApplication(answers) {
|
|
230
|
+
return projectTypes$1.APPLICATION === answers[questionNames$1.PROJECT_TYPE];
|
|
252
231
|
}
|
|
253
232
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
const {packageManager: pinnedPackageManager} = JSON.parse(await promises$1.readFile(`${projectRoot}/package.json`, 'utf-8'));
|
|
258
|
-
|
|
259
|
-
if (await npmIsUsed({projectRoot, pinnedPackageManager})) {
|
|
260
|
-
return packageManagers$1.NPM;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
if (await yarnIsUsed({projectRoot, pinnedPackageManager})) {
|
|
264
|
-
return packageManagers$1.YARN;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
throw new Error('Package-manager could not be determined');
|
|
233
|
+
function packageShouldBeScoped(visibility, answers) {
|
|
234
|
+
return 'Private' === visibility || answers[questionNames$1.SHOULD_BE_SCOPED];
|
|
268
235
|
}
|
|
269
236
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
defineLockfilePath: determineLockfilePathFor,
|
|
273
|
-
determineCurrent: resolvePackageManager,
|
|
274
|
-
lift: lifter$5,
|
|
275
|
-
scaffold: scaffoldPackageManager,
|
|
276
|
-
test: jsPackageManagerIsUsed
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
const lockfileLintSupportedPackageManagers = [packageManagers$1.NPM, packageManagers$1.YARN];
|
|
280
|
-
|
|
281
|
-
function lockfileLintSupports(packageManager) {
|
|
282
|
-
return lockfileLintSupportedPackageManagers.includes(packageManager);
|
|
237
|
+
function willBePublishedToNpm(answers) {
|
|
238
|
+
return projectIsPackage(answers) || projectIsCLI(answers);
|
|
283
239
|
}
|
|
284
240
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
throw new Error(
|
|
288
|
-
`The ${packageManager} package manager is currently not supported by lockfile-lint. `
|
|
289
|
-
+ `Only ${lockfileLintSupportedPackageManagers.join(' and ')} are currently supported.`
|
|
290
|
-
);
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
await write$2({
|
|
294
|
-
name: 'lockfile-lint',
|
|
295
|
-
format: fileTypes.JSON,
|
|
296
|
-
path: projectRoot,
|
|
297
|
-
config: {
|
|
298
|
-
path: determineLockfilePathFor(packageManager),
|
|
299
|
-
type: packageManager,
|
|
300
|
-
'validate-https': true,
|
|
301
|
-
'allowed-hosts': buildAllowedHostsList({packageManager, registries})
|
|
302
|
-
}
|
|
303
|
-
});
|
|
304
|
-
|
|
305
|
-
return {
|
|
306
|
-
dependencies: {javascript: {development: ['lockfile-lint']}},
|
|
307
|
-
scripts: {'lint:lockfile': 'lockfile-lint'}
|
|
308
|
-
};
|
|
241
|
+
function shouldBeScopedPromptShouldBePresented(answers) {
|
|
242
|
+
return willBePublishedToNpm(answers);
|
|
309
243
|
}
|
|
310
244
|
|
|
311
|
-
function
|
|
312
|
-
return
|
|
245
|
+
function scopePromptShouldBePresentedFactory(visibility) {
|
|
246
|
+
return answers => willBePublishedToNpm(answers) && packageShouldBeScoped(visibility, answers);
|
|
313
247
|
}
|
|
314
248
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
249
|
+
function lintingPromptShouldBePresented({
|
|
250
|
+
[questionNames$2.UNIT_TESTS]: unitTested,
|
|
251
|
+
[questionNames$2.INTEGRATION_TESTS]: integrationTested
|
|
252
|
+
}) {
|
|
253
|
+
return !unitTested && !integrationTested;
|
|
319
254
|
}
|
|
320
255
|
|
|
321
|
-
function
|
|
322
|
-
return
|
|
323
|
-
|
|
256
|
+
function scope(visibility) {
|
|
257
|
+
return input => {
|
|
258
|
+
if (!input && 'Private' === visibility) {
|
|
259
|
+
return 'Private packages must be scoped (https://docs.npmjs.com/private-modules/intro#setting-up-your-package)';
|
|
260
|
+
}
|
|
324
261
|
|
|
325
|
-
|
|
326
|
-
|
|
262
|
+
return true;
|
|
263
|
+
};
|
|
327
264
|
}
|
|
328
265
|
|
|
329
|
-
function
|
|
330
|
-
return
|
|
266
|
+
function authorQuestions({name, email, url}) {
|
|
267
|
+
return [
|
|
268
|
+
{
|
|
269
|
+
name: questionNames$1.AUTHOR_NAME,
|
|
270
|
+
message: 'What is the author\'s name?',
|
|
271
|
+
default: name
|
|
272
|
+
},
|
|
273
|
+
{
|
|
274
|
+
name: questionNames$1.AUTHOR_EMAIL,
|
|
275
|
+
message: 'What is the author\'s email?',
|
|
276
|
+
default: email
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
name: questionNames$1.AUTHOR_URL,
|
|
280
|
+
message: 'What is the author\'s website url?',
|
|
281
|
+
default: url
|
|
282
|
+
}
|
|
283
|
+
];
|
|
331
284
|
}
|
|
332
285
|
|
|
333
|
-
async function
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
286
|
+
async function prompt(
|
|
287
|
+
ciServices,
|
|
288
|
+
hosts,
|
|
289
|
+
visibility,
|
|
290
|
+
vcs,
|
|
291
|
+
decisions,
|
|
292
|
+
configs,
|
|
293
|
+
pathWithinParent
|
|
294
|
+
) {
|
|
295
|
+
const npmConf$1 = npmConf();
|
|
338
296
|
|
|
339
|
-
|
|
340
|
-
|
|
297
|
+
let maybeLoggedInNpmUsername;
|
|
298
|
+
try {
|
|
299
|
+
maybeLoggedInNpmUsername = (await execa('npm', ['whoami'])).stdout;
|
|
300
|
+
} catch (failedExecutionResult) {
|
|
301
|
+
if (!decisions[questionNames$1.SCOPE]) {
|
|
302
|
+
warn('No logged in user found with `npm whoami`. Login with `npm login` '
|
|
303
|
+
+ 'to use your npm account name as the package scope default.');
|
|
304
|
+
}
|
|
305
|
+
}
|
|
341
306
|
|
|
342
|
-
|
|
307
|
+
const {
|
|
308
|
+
[questionNames$2.UNIT_TESTS]: unitTested,
|
|
309
|
+
[questionNames$2.INTEGRATION_TESTS]: integrationTested,
|
|
310
|
+
[questionNames$1.PROJECT_TYPE]: projectType,
|
|
311
|
+
[questionNames$2.CI_SERVICE]: ci,
|
|
312
|
+
[questionNames$1.HOST]: chosenHost,
|
|
313
|
+
[questionNames$1.SCOPE]: scope$1,
|
|
314
|
+
[questionNames$1.NODE_VERSION_CATEGORY]: nodeVersionCategory,
|
|
315
|
+
[questionNames$1.AUTHOR_NAME]: authorName,
|
|
316
|
+
[questionNames$1.AUTHOR_EMAIL]: authorEmail,
|
|
317
|
+
[questionNames$1.AUTHOR_URL]: authorUrl,
|
|
318
|
+
[questionNames$1.CONFIGURE_LINTING]: configureLinting,
|
|
319
|
+
[questionNames$1.PROVIDE_EXAMPLE]: provideExample,
|
|
320
|
+
[questionNames$1.PACKAGE_MANAGER]: packageManager,
|
|
321
|
+
[questionNames$1.DIALECT]: dialect
|
|
322
|
+
} = await prompt$1([
|
|
323
|
+
{
|
|
324
|
+
name: questionNames$1.DIALECT,
|
|
325
|
+
message: 'Which JavaScript dialect should this project follow?',
|
|
326
|
+
type: 'list',
|
|
327
|
+
choices: buildDialectChoices(configs),
|
|
328
|
+
default: 'babel'
|
|
329
|
+
},
|
|
330
|
+
...pathWithinParent ? [] : [{
|
|
331
|
+
name: questionNames$1.NODE_VERSION_CATEGORY,
|
|
332
|
+
message: 'What node.js version should be used?',
|
|
333
|
+
type: 'list',
|
|
334
|
+
choices: ['LTS', 'Latest'],
|
|
335
|
+
default: 'LTS'
|
|
336
|
+
}],
|
|
337
|
+
{
|
|
338
|
+
name: questionNames$1.PACKAGE_MANAGER,
|
|
339
|
+
message: 'Which package manager will be used with this project?',
|
|
340
|
+
type: 'list',
|
|
341
|
+
choices: Object.values(packageManagers$1),
|
|
342
|
+
default: packageManagers$1.NPM
|
|
343
|
+
},
|
|
344
|
+
{
|
|
345
|
+
name: questionNames$1.PROJECT_TYPE,
|
|
346
|
+
message: 'What type of JavaScript project is this?',
|
|
347
|
+
type: 'list',
|
|
348
|
+
choices: [...Object.values(projectTypes$1), 'Other'],
|
|
349
|
+
default: projectTypes$1.PACKAGE
|
|
350
|
+
},
|
|
351
|
+
...'Private' === visibility ? [] : [{
|
|
352
|
+
name: questionNames$1.SHOULD_BE_SCOPED,
|
|
353
|
+
message: 'Should this package be scoped?',
|
|
354
|
+
type: 'confirm',
|
|
355
|
+
when: shouldBeScopedPromptShouldBePresented,
|
|
356
|
+
default: true
|
|
357
|
+
}],
|
|
358
|
+
{
|
|
359
|
+
name: questionNames$1.SCOPE,
|
|
360
|
+
message: 'What is the scope?',
|
|
361
|
+
when: scopePromptShouldBePresentedFactory(visibility),
|
|
362
|
+
validate: scope(visibility),
|
|
363
|
+
default: maybeLoggedInNpmUsername
|
|
364
|
+
},
|
|
365
|
+
...authorQuestions({
|
|
366
|
+
name: npmConf$1.get('init.author.name'),
|
|
367
|
+
email: npmConf$1.get('init.author.email'),
|
|
368
|
+
url: npmConf$1.get('init.author.url')
|
|
369
|
+
}),
|
|
370
|
+
...questions(({vcs, ciServices, pathWithinParent})),
|
|
371
|
+
{
|
|
372
|
+
name: questionNames$1.CONFIGURE_LINTING,
|
|
373
|
+
message: 'Will there be source code that should be linted?',
|
|
374
|
+
type: 'confirm',
|
|
375
|
+
when: lintingPromptShouldBePresented
|
|
376
|
+
},
|
|
377
|
+
{
|
|
378
|
+
name: questionNames$1.PROVIDE_EXAMPLE,
|
|
379
|
+
message: 'Should an example be provided in the README?',
|
|
380
|
+
type: 'confirm',
|
|
381
|
+
when: projectIsPackage
|
|
382
|
+
},
|
|
383
|
+
{
|
|
384
|
+
name: questionNames$1.HOST,
|
|
385
|
+
type: 'list',
|
|
386
|
+
message: 'Where will the application be hosted?',
|
|
387
|
+
when: projectIsApplication,
|
|
388
|
+
choices: [...Object.keys(hosts), 'Other']
|
|
389
|
+
}
|
|
390
|
+
], decisions);
|
|
391
|
+
|
|
392
|
+
return {
|
|
393
|
+
tests: {unit: unitTested, integration: integrationTested},
|
|
394
|
+
projectType,
|
|
395
|
+
ci,
|
|
396
|
+
chosenHost,
|
|
397
|
+
scope: scope$1,
|
|
398
|
+
nodeVersionCategory,
|
|
399
|
+
author: {name: authorName, email: authorEmail, url: authorUrl},
|
|
400
|
+
configureLinting: false !== configureLinting,
|
|
401
|
+
provideExample,
|
|
402
|
+
packageManager,
|
|
403
|
+
dialect
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
function write$1 ({projectRoot, config}) {
|
|
408
|
+
return write$2({path: projectRoot, name: 'babel', format: fileTypes.JSON, config});
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
function loadConfig ({projectRoot}) {
|
|
412
|
+
return loadConfigFile({path: projectRoot, name: '.babelrc', format: fileTypes.JSON});
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
async function addIgnore ({projectRoot, ignore}) {
|
|
416
|
+
if (ignore) {
|
|
417
|
+
const existingConfig = await loadConfig({projectRoot});
|
|
418
|
+
|
|
419
|
+
await write$1({projectRoot, config: {...existingConfig, ignore: [`./${ignore}/`]}});
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
async function scaffoldBabel ({projectRoot, preset}) {
|
|
424
|
+
if (!preset) {
|
|
425
|
+
throw new Error('No babel preset provided. Cannot configure babel transpilation');
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
await write$1({projectRoot, config: {presets: [preset.name]}});
|
|
429
|
+
|
|
430
|
+
return {
|
|
431
|
+
dependencies: {javascript: {development: ['@babel/register', preset.packageName]}},
|
|
432
|
+
eslint: {}
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
async function lifter$5 ({results, projectRoot}) {
|
|
437
|
+
await addIgnore({ignore: results.buildDirectory, projectRoot});
|
|
438
|
+
|
|
439
|
+
return {};
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
function predicate ({projectRoot}) {
|
|
443
|
+
return fileExists(`${projectRoot}/.babelrc.json`);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
async function scaffoldTypescript ({config, projectType, projectRoot, testFilenamePattern}) {
|
|
447
|
+
const shareableTsConfigPackage = `${config.scope}/tsconfig`;
|
|
448
|
+
|
|
449
|
+
await writeConfigFile({
|
|
450
|
+
path: projectRoot,
|
|
451
|
+
name: 'tsconfig',
|
|
452
|
+
format: fileTypes.JSON,
|
|
453
|
+
config: {
|
|
454
|
+
$schema: 'https://json.schemastore.org/tsconfig',
|
|
455
|
+
extends: shareableTsConfigPackage,
|
|
456
|
+
compilerOptions: {
|
|
457
|
+
rootDir: 'src',
|
|
458
|
+
...projectTypes$1.PACKAGE === projectType && {
|
|
459
|
+
outDir: 'lib',
|
|
460
|
+
declaration: true
|
|
461
|
+
}
|
|
462
|
+
},
|
|
463
|
+
include: ['src/**/*.ts'],
|
|
464
|
+
...testFilenamePattern && {exclude: [testFilenamePattern]}
|
|
465
|
+
}
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
return {
|
|
469
|
+
eslint: {configs: ['typescript']},
|
|
470
|
+
dependencies: {javascript: {development: ['typescript', shareableTsConfigPackage]}},
|
|
471
|
+
vcsIgnore: {files: ['tsconfig.tsbuildinfo']}
|
|
472
|
+
};
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
function scaffoldDialect ({dialect, projectType, projectRoot, configs, testFilenamePattern}) {
|
|
476
|
+
switch (dialect) {
|
|
477
|
+
case dialects$1.BABEL:
|
|
478
|
+
return scaffoldBabel({preset: configs.babelPreset, projectRoot});
|
|
479
|
+
case dialects$1.TYPESCRIPT:
|
|
480
|
+
return scaffoldTypescript({config: configs.typescript, projectType, projectRoot, testFilenamePattern});
|
|
481
|
+
default:
|
|
482
|
+
return {};
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
var dialects = /*#__PURE__*/Object.freeze({
|
|
487
|
+
__proto__: null,
|
|
488
|
+
lift: lifter$5,
|
|
489
|
+
scaffold: scaffoldDialect,
|
|
490
|
+
test: predicate
|
|
491
|
+
});
|
|
492
|
+
|
|
493
|
+
async function writeNpmConfig ({projectRoot, config}) {
|
|
494
|
+
await promises$1.writeFile(`${projectRoot}/.npmrc`, stringify(config));
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
function projectWillNotBeConsumed(projectType) {
|
|
498
|
+
return projectTypes$1.APPLICATION === projectType || projectTypes$1.CLI === projectType;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
async function scaffoldNpmConfig ({projectRoot, projectType}) {
|
|
502
|
+
await writeNpmConfig({
|
|
503
|
+
projectRoot,
|
|
504
|
+
config: {'update-notifier': false, ...projectWillNotBeConsumed(projectType) && {'save-exact': true}}
|
|
505
|
+
});
|
|
506
|
+
|
|
507
|
+
return {scripts: {'lint:peer': 'npm ls >/dev/null'}};
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
function tester$4 ({projectRoot}) {
|
|
343
511
|
return fileExists(`${projectRoot}/.npmrc`);
|
|
344
512
|
}
|
|
345
513
|
|
|
@@ -368,148 +536,116 @@ var npmConfigPlugin = /*#__PURE__*/Object.freeze({
|
|
|
368
536
|
lift: lifter$4,
|
|
369
537
|
read: readNpmConfig,
|
|
370
538
|
scaffold: scaffoldNpmConfig,
|
|
371
|
-
test: tester$
|
|
539
|
+
test: tester$4,
|
|
372
540
|
write: writeNpmConfig
|
|
373
541
|
});
|
|
374
542
|
|
|
375
|
-
function
|
|
376
|
-
|
|
377
|
-
.
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
return {...acc, [`@${scope}:registry`]: url};
|
|
382
|
-
}, {registry: 'https://registry.npmjs.org'});
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
async function updateRegistriesInNpmConfig(registries, projectRoot) {
|
|
386
|
-
const registriesForNpmConfig = buildRegistriesConfig(registries);
|
|
543
|
+
async function scaffoldNpm ({projectRoot}) {
|
|
544
|
+
const [packageContents, {stdout}] = await Promise.all([
|
|
545
|
+
promises$1.readFile(`${projectRoot}/package.json`, 'utf-8'),
|
|
546
|
+
execa('npm', ['--version'])
|
|
547
|
+
]);
|
|
548
|
+
const existingPackageJsonContents = JSON.parse(packageContents);
|
|
387
549
|
|
|
388
|
-
await
|
|
550
|
+
await writePackageJson({
|
|
389
551
|
projectRoot,
|
|
390
552
|
config: {
|
|
391
|
-
...
|
|
392
|
-
|
|
553
|
+
...existingPackageJsonContents,
|
|
554
|
+
packageManager: `npm@${stdout}`
|
|
393
555
|
}
|
|
394
556
|
});
|
|
395
557
|
}
|
|
396
558
|
|
|
397
|
-
|
|
398
|
-
|
|
559
|
+
function determineLockfilePathFor (packageManager) {
|
|
560
|
+
const lockfilePaths = {
|
|
561
|
+
[packageManagers$1.NPM]: 'package-lock.json',
|
|
562
|
+
[packageManagers$1.YARN]: 'yarn.lock'
|
|
563
|
+
};
|
|
564
|
+
|
|
565
|
+
return lockfilePaths[packageManager];
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
function npmIsUsed ({projectRoot, pinnedPackageManager = ''}) {
|
|
569
|
+
const [packageManager] = pinnedPackageManager.split('@');
|
|
570
|
+
|
|
571
|
+
return packageManagers$1.NPM === packageManager
|
|
572
|
+
|| fileExists(`${projectRoot}/${determineLockfilePathFor(packageManagers$1.NPM)}`);
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
async function scaffoldYarn ({projectRoot}) {
|
|
576
|
+
const [packageContents, {stdout}] = await Promise.all([
|
|
577
|
+
promises$1.readFile(`${projectRoot}/package.json`, 'utf-8'),
|
|
578
|
+
execa('yarn', ['--version'])
|
|
579
|
+
]);
|
|
580
|
+
const existingPackageJsonContents = JSON.parse(packageContents);
|
|
581
|
+
|
|
582
|
+
await writePackageJson({
|
|
399
583
|
projectRoot,
|
|
400
584
|
config: {
|
|
401
|
-
...
|
|
402
|
-
|
|
585
|
+
...existingPackageJsonContents,
|
|
586
|
+
packageManager: `yarn@${stdout}`
|
|
403
587
|
}
|
|
404
588
|
});
|
|
405
589
|
}
|
|
406
590
|
|
|
407
|
-
|
|
408
|
-
|
|
591
|
+
function yarnIsUsed ({projectRoot, pinnedPackageManager = ''}) {
|
|
592
|
+
const [packageManager] = pinnedPackageManager.split('@');
|
|
409
593
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
594
|
+
return packageManagers$1.YARN === packageManager
|
|
595
|
+
|| fileExists(`${projectRoot}/${determineLockfilePathFor(packageManagers$1.YARN)}`);
|
|
596
|
+
}
|
|
413
597
|
|
|
414
|
-
|
|
598
|
+
async function jsPackageManagerIsUsed ({projectRoot}) {
|
|
599
|
+
const [npmFound, yarnFound] = await Promise.all([
|
|
600
|
+
npmIsUsed({projectRoot}),
|
|
601
|
+
yarnIsUsed({projectRoot})
|
|
602
|
+
]);
|
|
415
603
|
|
|
416
|
-
return
|
|
604
|
+
return npmFound || yarnFound;
|
|
417
605
|
}
|
|
418
606
|
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
test: tester$4
|
|
423
|
-
});
|
|
607
|
+
async function liftCorepack () {
|
|
608
|
+
await execa('corepack', ['use', 'npm@latest']);
|
|
609
|
+
}
|
|
424
610
|
|
|
425
|
-
async function
|
|
426
|
-
await
|
|
427
|
-
format: fileTypes.JSON,
|
|
428
|
-
path: projectRoot,
|
|
429
|
-
name: 'remark',
|
|
430
|
-
config: {
|
|
431
|
-
settings: {
|
|
432
|
-
listItemIndent: 'one',
|
|
433
|
-
emphasis: '_',
|
|
434
|
-
strong: '_',
|
|
435
|
-
bullet: '*',
|
|
436
|
-
incrementListMarker: false
|
|
437
|
-
},
|
|
438
|
-
plugins: [
|
|
439
|
-
config,
|
|
440
|
-
['remark-toc', {tight: true}],
|
|
441
|
-
...projectTypes$1.PACKAGE === projectType ? [['remark-usage', {heading: 'example'}]] : [],
|
|
442
|
-
...!vcs ? [['validate-links', {repository: false}]] : []
|
|
443
|
-
]
|
|
444
|
-
}
|
|
445
|
-
});
|
|
611
|
+
async function lifter$3 () {
|
|
612
|
+
await liftCorepack();
|
|
446
613
|
|
|
447
|
-
return
|
|
448
|
-
{
|
|
449
|
-
dependencies: {javascript: {development: [config, 'remark-cli', 'remark-toc']}},
|
|
450
|
-
scripts: {
|
|
451
|
-
'lint:md': 'remark . --frail',
|
|
452
|
-
'generate:md': 'remark . --output'
|
|
453
|
-
}
|
|
454
|
-
},
|
|
455
|
-
{...projectTypes$1.PACKAGE === projectType && {dependencies: {javascript: {development: ['remark-usage']}}}}
|
|
456
|
-
);
|
|
614
|
+
return {};
|
|
457
615
|
}
|
|
458
616
|
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
vcs,
|
|
464
|
-
configureLinting
|
|
465
|
-
}) {
|
|
466
|
-
return deepmerge.all(await Promise.all([
|
|
467
|
-
configs.eslint
|
|
468
|
-
&& configureLinting
|
|
469
|
-
&& scaffold$1({projectRoot, config: configs.eslint}),
|
|
470
|
-
scaffoldRemark({
|
|
471
|
-
projectRoot,
|
|
472
|
-
projectType,
|
|
473
|
-
vcs,
|
|
474
|
-
config: configs.remark || '@form8ion/remark-lint-preset'
|
|
475
|
-
}),
|
|
476
|
-
scaffold$2({projectRoot, config: configs.prettier})
|
|
477
|
-
].filter(Boolean)));
|
|
478
|
-
}
|
|
617
|
+
const scaffolders = {
|
|
618
|
+
npm: scaffoldNpm,
|
|
619
|
+
yarn: scaffoldYarn
|
|
620
|
+
};
|
|
479
621
|
|
|
480
|
-
function
|
|
481
|
-
return
|
|
622
|
+
function scaffoldPackageManager ({projectRoot, packageManager}) {
|
|
623
|
+
return scaffolders[packageManager]({projectRoot});
|
|
482
624
|
}
|
|
483
625
|
|
|
484
|
-
function
|
|
485
|
-
|
|
486
|
-
}
|
|
626
|
+
async function resolvePackageManager ({projectRoot, packageManager}) {
|
|
627
|
+
if (packageManager) return packageManager;
|
|
487
628
|
|
|
488
|
-
|
|
489
|
-
__proto__: null,
|
|
490
|
-
lift: lifter$2,
|
|
491
|
-
scaffold: scaffoldCodeStyle,
|
|
492
|
-
test: tester$2
|
|
493
|
-
});
|
|
629
|
+
const {packageManager: pinnedPackageManager} = JSON.parse(await promises$1.readFile(`${projectRoot}/package.json`, 'utf-8'));
|
|
494
630
|
|
|
495
|
-
|
|
496
|
-
|
|
631
|
+
if (await npmIsUsed({projectRoot, pinnedPackageManager})) {
|
|
632
|
+
return packageManagers$1.NPM;
|
|
633
|
+
}
|
|
497
634
|
|
|
498
|
-
|
|
499
|
-
|
|
635
|
+
if (await yarnIsUsed({projectRoot, pinnedPackageManager})) {
|
|
636
|
+
return packageManagers$1.YARN;
|
|
637
|
+
}
|
|
500
638
|
|
|
501
|
-
|
|
502
|
-
return {
|
|
503
|
-
dependencies: {javascript: {development: ['ls-engines']}},
|
|
504
|
-
scripts: {'lint:engines': 'ls-engines'},
|
|
505
|
-
badges: {consumer: {node: {img: `https://img.shields.io/node/v/${name}?logo=node.js`, text: 'node'}}}
|
|
506
|
-
};
|
|
639
|
+
throw new Error('Package-manager could not be determined');
|
|
507
640
|
}
|
|
508
641
|
|
|
509
|
-
var
|
|
642
|
+
var packageManagers = /*#__PURE__*/Object.freeze({
|
|
510
643
|
__proto__: null,
|
|
511
|
-
|
|
512
|
-
|
|
644
|
+
defineLockfilePath: determineLockfilePathFor,
|
|
645
|
+
determineCurrent: resolvePackageManager,
|
|
646
|
+
lift: lifter$3,
|
|
647
|
+
scaffold: scaffoldPackageManager,
|
|
648
|
+
test: jsPackageManagerIsUsed
|
|
513
649
|
});
|
|
514
650
|
|
|
515
651
|
function buildDocumentationCommand (packageManager) {
|
|
@@ -522,1144 +658,772 @@ function buildDocumentationCommand (packageManager) {
|
|
|
522
658
|
);
|
|
523
659
|
}
|
|
524
660
|
|
|
525
|
-
function
|
|
526
|
-
if (packageManagers$1.NPM === packageManager) return 'npm install';
|
|
527
|
-
if (packageManagers$1.YARN === packageManager) return 'yarn add';
|
|
528
|
-
|
|
529
|
-
throw new Error(
|
|
530
|
-
`The ${packageManager} package manager is currently not supported. `
|
|
531
|
-
+ `Only ${Object.values(packageManagers$1).join(' and ')} are currently supported.`
|
|
532
|
-
);
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
function scaffoldPackageDocumentation ({scope, packageName, packageManager, visibility, provideExample}) {
|
|
661
|
+
function scaffoldDocumentation ({projectTypeResults, packageManager}) {
|
|
536
662
|
return {
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
:
|
|
540
|
-
|
|
541
|
-
` : ''
|
|
542
|
-
}
|
|
663
|
+
toc: `Run \`${buildDocumentationCommand(packageManager)}\` to generate a table of contents`,
|
|
664
|
+
...projectTypeResults.documentation,
|
|
665
|
+
contributing: `### Dependencies
|
|
666
|
+
|
|
543
667
|
\`\`\`sh
|
|
544
|
-
$
|
|
545
|
-
|
|
546
|
-
|
|
668
|
+
$ nvm install
|
|
669
|
+
$ ${packageManager} install
|
|
670
|
+
\`\`\`
|
|
547
671
|
|
|
548
|
-
###
|
|
672
|
+
### Verification
|
|
549
673
|
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
674
|
+
\`\`\`sh
|
|
675
|
+
$ ${packageManager} test
|
|
676
|
+
\`\`\``
|
|
553
677
|
};
|
|
554
678
|
}
|
|
555
679
|
|
|
556
|
-
function
|
|
557
|
-
|
|
558
|
-
}
|
|
680
|
+
async function determineLatestVersionOf(nodeVersionCategory) {
|
|
681
|
+
info('Determining version of node', {level: 'secondary'});
|
|
559
682
|
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
}
|
|
570
|
-
},
|
|
571
|
-
status: {}
|
|
572
|
-
};
|
|
683
|
+
const {stdout: nvmLsOutput} = await execa(
|
|
684
|
+
`. ~/.nvm/nvm.sh && nvm ls-remote${('LTS' === nodeVersionCategory) ? ' --lts' : ''}`,
|
|
685
|
+
{shell: true}
|
|
686
|
+
);
|
|
687
|
+
|
|
688
|
+
const lsLines = nvmLsOutput.split('\n');
|
|
689
|
+
const lsLine = lsLines[lsLines.length - 2];
|
|
690
|
+
|
|
691
|
+
return lsLine.match(/(v[0-9]+)\.[0-9]+\.[0-9]+/)[1];
|
|
573
692
|
}
|
|
574
693
|
|
|
575
|
-
function
|
|
576
|
-
|
|
577
|
-
return {
|
|
578
|
-
badges: {
|
|
579
|
-
status: {
|
|
580
|
-
slsa: {
|
|
581
|
-
img: 'https://slsa.dev/images/gh-badge-level2.svg',
|
|
582
|
-
url: 'https://slsa.dev',
|
|
583
|
-
text: 'SLSA Level 2'
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
};
|
|
588
|
-
}
|
|
694
|
+
function install$1(nodeVersionCategory) {
|
|
695
|
+
info(`Installing ${nodeVersionCategory} version of node using nvm`, {level: 'secondary'});
|
|
589
696
|
|
|
590
|
-
|
|
697
|
+
const subprocess = execa('. ~/.nvm/nvm.sh && nvm install', {shell: true});
|
|
698
|
+
subprocess.stdout.pipe(process.stdout);
|
|
699
|
+
return subprocess;
|
|
591
700
|
}
|
|
592
701
|
|
|
593
|
-
async function
|
|
594
|
-
|
|
702
|
+
async function scaffoldNodeVersion ({projectRoot, nodeVersionCategory}) {
|
|
703
|
+
if (!nodeVersionCategory) return undefined;
|
|
595
704
|
|
|
596
|
-
|
|
597
|
-
|
|
705
|
+
const lowerCaseCategory = nodeVersionCategory.toLowerCase();
|
|
706
|
+
info(`Configuring ${lowerCaseCategory} version of node`);
|
|
598
707
|
|
|
599
|
-
|
|
600
|
-
}
|
|
708
|
+
const version = await determineLatestVersionOf(nodeVersionCategory);
|
|
601
709
|
|
|
602
|
-
|
|
603
|
-
}
|
|
710
|
+
await promises$1.writeFile(`${projectRoot}/.nvmrc`, version);
|
|
604
711
|
|
|
605
|
-
|
|
606
|
-
const {name: packageName, publishConfig: {access: packageAccessLevel}} = packageDetails;
|
|
607
|
-
const homepage = `https://npm.im/${packageName}`;
|
|
712
|
+
await install$1(nodeVersionCategory);
|
|
608
713
|
|
|
609
|
-
|
|
714
|
+
return version;
|
|
715
|
+
}
|
|
610
716
|
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
{
|
|
614
|
-
homepage,
|
|
615
|
-
dependencies: {javascript: {development: ['publint']}},
|
|
616
|
-
scripts: {'lint:publish': 'publint --strict'},
|
|
617
|
-
badges: defineBadges(packageName, packageAccessLevel)
|
|
618
|
-
}
|
|
619
|
-
);
|
|
717
|
+
function nvmIsUsed ({projectRoot}) {
|
|
718
|
+
return fileExists(`${projectRoot}/.nvmrc`);
|
|
620
719
|
}
|
|
621
720
|
|
|
622
|
-
|
|
721
|
+
function buildVcsIgnoreLists (vcsIgnoreLists = {}) {
|
|
623
722
|
return {
|
|
624
|
-
|
|
723
|
+
files: vcsIgnoreLists.files || [],
|
|
724
|
+
directories: ['/node_modules/', ...vcsIgnoreLists.directories || []]
|
|
625
725
|
};
|
|
626
726
|
}
|
|
627
727
|
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
const answers = await prompt$1([{
|
|
632
|
-
name: questionNames$1.PACKAGE_BUNDLER,
|
|
633
|
-
type: 'list',
|
|
634
|
-
message: 'Which bundler should be used?',
|
|
635
|
-
choices: [...Object.keys(bundlers), 'Other']
|
|
636
|
-
}], decisions);
|
|
728
|
+
function buildPackageName (projectName, scope) {
|
|
729
|
+
const name = `${scope ? `@${scope}/` : ''}${projectName}`;
|
|
637
730
|
|
|
638
|
-
|
|
639
|
-
}
|
|
731
|
+
const {validForNewPackages, errors} = validatePackageName(name);
|
|
640
732
|
|
|
641
|
-
|
|
642
|
-
|
|
733
|
+
if (validForNewPackages) return name;
|
|
734
|
+
if (1 === errors.length && errors.includes('name cannot start with a period')) return projectName.slice(1);
|
|
643
735
|
|
|
644
|
-
|
|
736
|
+
throw new Error(`The package name ${name} is invalid:${EOL}\t* ${errors.join(`${EOL}\t* `)}`);
|
|
645
737
|
}
|
|
646
738
|
|
|
647
|
-
function
|
|
648
|
-
const [, __dirname] = filedirname();
|
|
649
|
-
|
|
650
|
-
return resolve(__dirname, '..', 'templates', fileName);
|
|
651
|
-
}
|
|
652
|
-
|
|
653
|
-
const defaultBuildDirectory$2 = 'lib';
|
|
654
|
-
|
|
655
|
-
async function createExample(projectRoot, projectName, dialect) {
|
|
656
|
-
return promises.writeFile(
|
|
657
|
-
`${projectRoot}/example.js`,
|
|
658
|
-
mustache.render(
|
|
659
|
-
await promises.readFile(determinePathToTemplateFile('example.mustache'), 'utf8'),
|
|
660
|
-
{projectName: camelcase(projectName), esm: dialect === dialects$1.ESM}
|
|
661
|
-
)
|
|
662
|
-
);
|
|
663
|
-
}
|
|
664
|
-
|
|
665
|
-
async function buildDetailsForCommonJsProject({projectRoot, projectName, provideExample}) {
|
|
666
|
-
await Promise.all([
|
|
667
|
-
touch(`${projectRoot}/index.js`),
|
|
668
|
-
provideExample
|
|
669
|
-
? promises.writeFile(`${projectRoot}/example.js`, `const ${camelcase(projectName)} = require('.');\n`)
|
|
670
|
-
: Promise.resolve()
|
|
671
|
-
]);
|
|
672
|
-
|
|
673
|
-
return {};
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
async function buildDetails ({
|
|
677
|
-
projectRoot,
|
|
678
|
-
projectName,
|
|
679
|
-
visibility,
|
|
739
|
+
function buildPackageDetails ({
|
|
680
740
|
packageName,
|
|
681
|
-
packageBundlers,
|
|
682
741
|
dialect,
|
|
683
|
-
|
|
684
|
-
|
|
742
|
+
license,
|
|
743
|
+
author,
|
|
744
|
+
description
|
|
685
745
|
}) {
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
return deepmerge(
|
|
696
|
-
bundlerResults,
|
|
697
|
-
{
|
|
698
|
-
dependencies: {javascript: {development: ['rimraf']}},
|
|
699
|
-
scripts: {
|
|
700
|
-
clean: `rimraf ./${defaultBuildDirectory$2}`,
|
|
701
|
-
prebuild: 'run-s clean',
|
|
702
|
-
build: 'npm-run-all --print-label --parallel build:*',
|
|
703
|
-
prepack: 'run-s build',
|
|
704
|
-
...provideExample && {'pregenerate:md': 'run-s build'}
|
|
705
|
-
},
|
|
706
|
-
vcsIgnore: {directories: [`/${defaultBuildDirectory$2}/`]},
|
|
707
|
-
buildDirectory: defaultBuildDirectory$2,
|
|
708
|
-
badges: {
|
|
709
|
-
consumer: {
|
|
710
|
-
...'Public' === visibility && {
|
|
711
|
-
runkit: {
|
|
712
|
-
img: `https://badge.runkitcdn.com/${packageName}.svg`,
|
|
713
|
-
text: `Try ${packageName} on RunKit`,
|
|
714
|
-
link: `https://npm.runkit.com/${packageName}`
|
|
715
|
-
}
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
}
|
|
719
|
-
}
|
|
720
|
-
);
|
|
746
|
+
return {
|
|
747
|
+
name: packageName,
|
|
748
|
+
description,
|
|
749
|
+
license,
|
|
750
|
+
type: dialects$1.ESM === dialect ? 'module' : 'commonjs',
|
|
751
|
+
author: `${author.name}${author.email ? ` <${author.email}>` : ''}${author.url ? ` (${author.url})` : ''}`,
|
|
752
|
+
scripts: {}
|
|
753
|
+
};
|
|
721
754
|
}
|
|
722
755
|
|
|
723
|
-
async function
|
|
756
|
+
async function scaffoldPackage ({
|
|
724
757
|
projectRoot,
|
|
725
758
|
projectName,
|
|
726
|
-
packageName,
|
|
727
|
-
packageManager,
|
|
728
|
-
visibility,
|
|
729
759
|
scope,
|
|
730
|
-
packageBundlers,
|
|
731
|
-
decisions,
|
|
732
760
|
dialect,
|
|
733
|
-
|
|
734
|
-
|
|
761
|
+
license,
|
|
762
|
+
author,
|
|
763
|
+
description
|
|
735
764
|
}) {
|
|
736
|
-
info('
|
|
765
|
+
info('Configuring package.json');
|
|
737
766
|
|
|
738
|
-
const
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
packageBundlers,
|
|
744
|
-
visibility,
|
|
767
|
+
const packageName = buildPackageName(projectName, scope);
|
|
768
|
+
|
|
769
|
+
await writePackageJson({
|
|
770
|
+
projectRoot,
|
|
771
|
+
config: await buildPackageDetails({
|
|
745
772
|
packageName,
|
|
746
773
|
dialect,
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
scaffoldPublishable({packageName, packageAccessLevel}),
|
|
751
|
-
mergeIntoExistingPackageJson({
|
|
752
|
-
projectRoot,
|
|
753
|
-
config: {
|
|
754
|
-
files: ['example.js', ...dialects$1.COMMON_JS === dialect ? ['index.js'] : ['lib/']],
|
|
755
|
-
publishConfig: {
|
|
756
|
-
access: packageAccessLevel,
|
|
757
|
-
...publishRegistry && {registry: publishRegistry}
|
|
758
|
-
},
|
|
759
|
-
sideEffects: false,
|
|
760
|
-
...'Public' === visibility && {runkitExampleFilename: './example.js'},
|
|
761
|
-
...dialects$1.BABEL === dialect && {
|
|
762
|
-
main: './lib/index.js',
|
|
763
|
-
module: './lib/index.mjs',
|
|
764
|
-
exports: {
|
|
765
|
-
module: './lib/index.mjs',
|
|
766
|
-
require: './lib/index.js',
|
|
767
|
-
import: './lib/index.mjs'
|
|
768
|
-
}
|
|
769
|
-
},
|
|
770
|
-
...dialects$1.ESM === dialect && {
|
|
771
|
-
main: './lib/index.js',
|
|
772
|
-
exports: './lib/index.js'
|
|
773
|
-
},
|
|
774
|
-
...dialects$1.TYPESCRIPT === dialect && {
|
|
775
|
-
main: './lib/index.js',
|
|
776
|
-
module: './lib/index.mjs',
|
|
777
|
-
types: './lib/index.d.ts',
|
|
778
|
-
exports: {
|
|
779
|
-
types: './lib/index.d.ts',
|
|
780
|
-
require: './lib/index.js',
|
|
781
|
-
import: './lib/index.mjs'
|
|
782
|
-
}
|
|
783
|
-
}
|
|
784
|
-
}
|
|
774
|
+
license,
|
|
775
|
+
author,
|
|
776
|
+
description
|
|
785
777
|
})
|
|
786
|
-
|
|
778
|
+
});
|
|
787
779
|
|
|
788
|
-
return
|
|
789
|
-
publishableResults,
|
|
790
|
-
{
|
|
791
|
-
documentation: scaffoldPackageDocumentation({packageName, visibility, scope, packageManager, provideExample}),
|
|
792
|
-
nextSteps: [
|
|
793
|
-
{summary: 'Add the appropriate `save` flag to the installation instructions in the README'},
|
|
794
|
-
{summary: 'Define supported node.js versions as `engines.node` in the `package.json` file'},
|
|
795
|
-
{summary: 'Publish pre-release versions to npm until package is stable enough to publish v1.0.0'}
|
|
796
|
-
]
|
|
797
|
-
},
|
|
798
|
-
detailsForBuild
|
|
799
|
-
]);
|
|
780
|
+
return {packageName};
|
|
800
781
|
}
|
|
801
782
|
|
|
802
|
-
function
|
|
803
|
-
return
|
|
783
|
+
function sortPackageProperties (packageContents) {
|
|
784
|
+
return sortProperties(
|
|
785
|
+
packageContents,
|
|
786
|
+
[
|
|
787
|
+
'name',
|
|
788
|
+
'description',
|
|
789
|
+
'license',
|
|
790
|
+
'version',
|
|
791
|
+
'private',
|
|
792
|
+
'type',
|
|
793
|
+
'engines',
|
|
794
|
+
'author',
|
|
795
|
+
'contributors',
|
|
796
|
+
'repository',
|
|
797
|
+
'bugs',
|
|
798
|
+
'homepage',
|
|
799
|
+
'funding',
|
|
800
|
+
'keywords',
|
|
801
|
+
'runkitExampleFilename',
|
|
802
|
+
'exports',
|
|
803
|
+
'bin',
|
|
804
|
+
'main',
|
|
805
|
+
'module',
|
|
806
|
+
'types',
|
|
807
|
+
'sideEffects',
|
|
808
|
+
'scripts',
|
|
809
|
+
'files',
|
|
810
|
+
'publishConfig',
|
|
811
|
+
'packageManager',
|
|
812
|
+
'config',
|
|
813
|
+
'dependencies',
|
|
814
|
+
'devDependencies',
|
|
815
|
+
'peerDependencies'
|
|
816
|
+
]
|
|
817
|
+
);
|
|
804
818
|
}
|
|
805
819
|
|
|
806
|
-
|
|
807
|
-
return
|
|
820
|
+
function defineVcsHostDetails (vcs, pathWithinParent) {
|
|
821
|
+
return vcs && 'github' === vcs.host && {
|
|
822
|
+
repository: pathWithinParent
|
|
823
|
+
? {
|
|
824
|
+
type: 'git',
|
|
825
|
+
url: `https://github.com/${vcs.owner}/${vcs.name}.git`,
|
|
826
|
+
directory: pathWithinParent
|
|
827
|
+
}
|
|
828
|
+
: `${vcs.owner}/${vcs.name}`,
|
|
829
|
+
bugs: `https://github.com/${vcs.owner}/${vcs.name}/issues`
|
|
830
|
+
};
|
|
808
831
|
}
|
|
809
832
|
|
|
810
|
-
const
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
833
|
+
const details = {
|
|
834
|
+
[packageManagers$1.NPM]: {
|
|
835
|
+
installationCommand: 'install',
|
|
836
|
+
installationFlags: {
|
|
837
|
+
[DEV_DEPENDENCY_TYPE]: `save-${DEV_DEPENDENCY_TYPE}`,
|
|
838
|
+
[PROD_DEPENDENCY_TYPE]: `save-${PROD_DEPENDENCY_TYPE}`,
|
|
839
|
+
exact: 'save-exact'
|
|
840
|
+
}
|
|
841
|
+
},
|
|
842
|
+
[packageManagers$1.YARN]: {
|
|
843
|
+
installationCommand: 'add',
|
|
844
|
+
installationFlags: {
|
|
845
|
+
[DEV_DEPENDENCY_TYPE]: DEV_DEPENDENCY_TYPE,
|
|
846
|
+
[PROD_DEPENDENCY_TYPE]: PROD_DEPENDENCY_TYPE,
|
|
847
|
+
exact: 'exact'
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
};
|
|
818
851
|
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
clean: `rimraf ./${buildDirectory}`,
|
|
822
|
-
start: `node ./${buildDirectory}/index.js`,
|
|
823
|
-
prebuild: 'run-s clean'
|
|
824
|
-
},
|
|
825
|
-
dependencies: {javascript: {development: ['rimraf']}},
|
|
826
|
-
vcsIgnore: {files: ['.env'], directories: [`/${buildDirectory}/`]},
|
|
827
|
-
buildDirectory,
|
|
828
|
-
nextSteps: []
|
|
829
|
-
};
|
|
852
|
+
function getInstallationCommandFor(manager) {
|
|
853
|
+
return details[manager].installationCommand;
|
|
830
854
|
}
|
|
831
855
|
|
|
832
|
-
function
|
|
833
|
-
return
|
|
856
|
+
function getDependencyTypeFlag(manager, type) {
|
|
857
|
+
return details[manager].installationFlags[type];
|
|
834
858
|
}
|
|
835
859
|
|
|
836
|
-
|
|
837
|
-
|
|
860
|
+
function getExactFlag(manager) {
|
|
861
|
+
return details[manager].installationFlags.exact;
|
|
862
|
+
}
|
|
838
863
|
|
|
839
|
-
|
|
864
|
+
async function install (dependencies, dependenciesType, projectRoot, packageManager = packageManagers$1.NPM) {
|
|
865
|
+
if (dependencies.length) {
|
|
866
|
+
info(`Installing ${dependenciesType} dependencies`, {level: 'secondary'});
|
|
840
867
|
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
868
|
+
await execa(
|
|
869
|
+
`. ~/.nvm/nvm.sh && nvm use && ${packageManager} ${
|
|
870
|
+
getInstallationCommandFor(packageManager)
|
|
871
|
+
} ${[...new Set(dependencies)].join(' ')} --${getDependencyTypeFlag(packageManager, dependenciesType)}${
|
|
872
|
+
DEV_DEPENDENCY_TYPE === dependenciesType ? ` --${getExactFlag(packageManager)}` : ''
|
|
873
|
+
}`,
|
|
874
|
+
{shell: true, cwd: projectRoot}
|
|
875
|
+
);
|
|
876
|
+
} else warn(`No ${dependenciesType} dependencies to install`);
|
|
848
877
|
}
|
|
849
878
|
|
|
850
|
-
|
|
879
|
+
async function processDependencies ({dependencies = {}, devDependencies, projectRoot, packageManager}) {
|
|
880
|
+
info('Processing dependencies');
|
|
851
881
|
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
publishRegistry,
|
|
858
|
-
decisions,
|
|
859
|
-
packageBundlers
|
|
860
|
-
}) {
|
|
861
|
-
const packageAccessLevel = determinePackageAccessLevelFromProjectVisibility({projectVisibility: visibility});
|
|
862
|
-
const [bundlerResults, publishableResults] = await Promise.all([
|
|
863
|
-
scaffoldBundler({bundlers: packageBundlers, projectRoot, dialect, decisions, projectType: projectTypes$1.CLI}),
|
|
864
|
-
scaffoldPublishable({packageName, packageAccessLevel}),
|
|
865
|
-
mergeIntoExistingPackageJson({
|
|
866
|
-
projectRoot,
|
|
867
|
-
config: {
|
|
868
|
-
bin: {},
|
|
869
|
-
files: [`${defaultBuildDirectory}/`],
|
|
870
|
-
publishConfig: {
|
|
871
|
-
access: packageAccessLevel,
|
|
872
|
-
...publishRegistry && {registry: publishRegistry}
|
|
873
|
-
}
|
|
874
|
-
}
|
|
875
|
-
})
|
|
876
|
-
]);
|
|
882
|
+
if (Array.isArray(devDependencies)) {
|
|
883
|
+
throw new Error(
|
|
884
|
+
`devDependencies provided as: ${devDependencies}. Instead, provide under dependencies.javascript.development`
|
|
885
|
+
);
|
|
886
|
+
}
|
|
877
887
|
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
{
|
|
882
|
-
scripts: {
|
|
883
|
-
clean: `rimraf ./${defaultBuildDirectory}`,
|
|
884
|
-
prebuild: 'run-s clean',
|
|
885
|
-
build: 'npm-run-all --print-label --parallel build:*',
|
|
886
|
-
prepack: 'run-s build'
|
|
887
|
-
},
|
|
888
|
-
dependencies: {javascript: {production: ['update-notifier'], development: ['rimraf']}},
|
|
889
|
-
vcsIgnore: {files: [], directories: [`/${defaultBuildDirectory}/`]},
|
|
890
|
-
buildDirectory: defaultBuildDirectory,
|
|
891
|
-
nextSteps: [{summary: 'Define supported node.js versions as `engines.node` in the `package.json` file'}]
|
|
892
|
-
}
|
|
893
|
-
]);
|
|
894
|
-
}
|
|
888
|
+
if (Array.isArray(dependencies)) {
|
|
889
|
+
throw new Error(`Expected dependencies to be an object. Instead received: ${dependencies}`);
|
|
890
|
+
}
|
|
895
891
|
|
|
896
|
-
|
|
897
|
-
return !!bin;
|
|
898
|
-
}
|
|
892
|
+
const {javascript: {production = [], development = []} = {}} = dependencies;
|
|
899
893
|
|
|
900
|
-
|
|
901
|
-
|
|
894
|
+
try {
|
|
895
|
+
await install(production, PROD_DEPENDENCY_TYPE, projectRoot, packageManager);
|
|
896
|
+
await install(development, DEV_DEPENDENCY_TYPE, projectRoot, packageManager);
|
|
897
|
+
} catch (e) {
|
|
898
|
+
error('Failed to update dependencies');
|
|
899
|
+
error(e, {level: 'secondary'});
|
|
900
|
+
}
|
|
902
901
|
}
|
|
903
902
|
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
projectRoot,
|
|
907
|
-
projectName,
|
|
908
|
-
packageName,
|
|
909
|
-
packageManager,
|
|
910
|
-
visibility,
|
|
911
|
-
packageBundlers,
|
|
912
|
-
scope,
|
|
913
|
-
decisions,
|
|
914
|
-
dialect,
|
|
915
|
-
provideExample,
|
|
916
|
-
publishRegistry
|
|
917
|
-
}) {
|
|
918
|
-
switch (projectType) {
|
|
919
|
-
case projectTypes$1.PACKAGE:
|
|
920
|
-
return scaffoldPackageType({
|
|
921
|
-
projectRoot,
|
|
922
|
-
projectName,
|
|
923
|
-
packageName,
|
|
924
|
-
packageManager,
|
|
925
|
-
visibility,
|
|
926
|
-
scope,
|
|
927
|
-
packageBundlers,
|
|
928
|
-
decisions,
|
|
929
|
-
dialect,
|
|
930
|
-
provideExample,
|
|
931
|
-
publishRegistry
|
|
932
|
-
});
|
|
933
|
-
case projectTypes$1.APPLICATION:
|
|
934
|
-
return scaffoldApplicationType({projectRoot});
|
|
935
|
-
case projectTypes$1.CLI:
|
|
936
|
-
return scaffoldCliType({
|
|
937
|
-
packageName,
|
|
938
|
-
visibility,
|
|
939
|
-
projectRoot,
|
|
940
|
-
dialect,
|
|
941
|
-
publishRegistry,
|
|
942
|
-
decisions,
|
|
943
|
-
packageBundlers
|
|
944
|
-
});
|
|
945
|
-
case projectTypes$1.MONOREPO:
|
|
946
|
-
return scaffoldMonorepoType({projectRoot});
|
|
947
|
-
case 'Other':
|
|
948
|
-
return {};
|
|
949
|
-
default:
|
|
950
|
-
throw new Error(`The project-type of ${projectType} is invalid`);
|
|
951
|
-
}
|
|
903
|
+
function projectWillBeTested(scripts) {
|
|
904
|
+
return Object.keys(scripts).find(scriptName => scriptName.startsWith('test:'));
|
|
952
905
|
}
|
|
953
906
|
|
|
954
|
-
|
|
955
|
-
return
|
|
956
|
-
|| await isCli({projectRoot, packageDetails})
|
|
957
|
-
|| isApplication({projectRoot, packageDetails});
|
|
907
|
+
function projectShouldBeBuiltForVerification(scripts) {
|
|
908
|
+
return 'run-s build' === scripts['pregenerate:md'];
|
|
958
909
|
}
|
|
959
910
|
|
|
960
|
-
function
|
|
961
|
-
return
|
|
911
|
+
function updateTestScript (scripts) {
|
|
912
|
+
return {
|
|
913
|
+
...scripts,
|
|
914
|
+
test: `npm-run-all --print-label${
|
|
915
|
+
projectShouldBeBuiltForVerification(scripts) ? ' build' : ''
|
|
916
|
+
} --parallel lint:*${
|
|
917
|
+
projectWillBeTested(scripts) ? ' --parallel test:*' : ''
|
|
918
|
+
}`
|
|
919
|
+
};
|
|
962
920
|
}
|
|
963
921
|
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
922
|
+
function liftScripts ({existingScripts, scripts}) {
|
|
923
|
+
return {
|
|
924
|
+
scripts: updateTestScript({...existingScripts, ...scripts}),
|
|
925
|
+
dependencies: {javascript: {development: ['npm-run-all2']}}
|
|
926
|
+
};
|
|
927
|
+
}
|
|
967
928
|
|
|
968
|
-
|
|
929
|
+
async function liftPackage$1 ({
|
|
930
|
+
projectRoot,
|
|
931
|
+
scripts,
|
|
932
|
+
tags,
|
|
933
|
+
dependencies,
|
|
934
|
+
devDependencies,
|
|
935
|
+
packageManager,
|
|
936
|
+
vcs,
|
|
937
|
+
pathWithinParent
|
|
938
|
+
}) {
|
|
939
|
+
info('Updating `package.json`', {level: 'secondary'});
|
|
969
940
|
|
|
970
|
-
|
|
971
|
-
|
|
941
|
+
const existingPackageJsonContents = JSON.parse(await promises$1.readFile(`${projectRoot}/package.json`, 'utf-8'));
|
|
942
|
+
const {scripts: liftedScripts, dependencies: scriptDependencies} = liftScripts({
|
|
943
|
+
existingScripts: existingPackageJsonContents.scripts,
|
|
944
|
+
scripts
|
|
945
|
+
});
|
|
972
946
|
|
|
973
|
-
|
|
974
|
-
|
|
947
|
+
await writePackageJson({
|
|
948
|
+
projectRoot,
|
|
949
|
+
config: sortPackageProperties({
|
|
950
|
+
...existingPackageJsonContents,
|
|
951
|
+
...defineVcsHostDetails(vcs, pathWithinParent),
|
|
952
|
+
scripts: liftedScripts,
|
|
953
|
+
...tags && {
|
|
954
|
+
keywords: existingPackageJsonContents.keywords ? [...existingPackageJsonContents.keywords, ...tags] : tags
|
|
955
|
+
}
|
|
956
|
+
})
|
|
957
|
+
});
|
|
975
958
|
|
|
976
|
-
|
|
959
|
+
await processDependencies({
|
|
960
|
+
dependencies: deepmerge(dependencies, scriptDependencies),
|
|
961
|
+
devDependencies,
|
|
962
|
+
projectRoot,
|
|
963
|
+
packageManager
|
|
964
|
+
});
|
|
977
965
|
}
|
|
978
966
|
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
scaffold: scaffoldProjectType,
|
|
983
|
-
test: tester$1
|
|
984
|
-
});
|
|
985
|
-
|
|
986
|
-
function write ({projectRoot, config}) {
|
|
987
|
-
return write$2({path: projectRoot, name: 'babel', format: fileTypes.JSON, config});
|
|
988
|
-
}
|
|
967
|
+
function getInstallationCommand(packageManager) {
|
|
968
|
+
if (packageManagers$1.NPM === packageManager) return 'npm install';
|
|
969
|
+
if (packageManagers$1.YARN === packageManager) return 'yarn add';
|
|
989
970
|
|
|
990
|
-
|
|
991
|
-
|
|
971
|
+
throw new Error(
|
|
972
|
+
`The ${packageManager} package manager is currently not supported. `
|
|
973
|
+
+ `Only ${Object.values(packageManagers$1).join(' and ')} are currently supported.`
|
|
974
|
+
);
|
|
992
975
|
}
|
|
993
976
|
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
977
|
+
function scaffoldPackageDocumentation ({scope, packageName, packageManager, visibility, provideExample}) {
|
|
978
|
+
return {
|
|
979
|
+
usage: `### Installation
|
|
980
|
+
${'Private' === visibility ? `
|
|
981
|
+
:warning: this is a private package, so you will need to use an npm token with
|
|
982
|
+
access to private packages under \`@${scope}\`
|
|
983
|
+
` : ''
|
|
1000
984
|
}
|
|
985
|
+
\`\`\`sh
|
|
986
|
+
$ ${getInstallationCommand(packageManager)} ${packageName}
|
|
987
|
+
\`\`\`${provideExample
|
|
988
|
+
? `
|
|
1001
989
|
|
|
1002
|
-
|
|
1003
|
-
if (!preset) {
|
|
1004
|
-
throw new Error('No babel preset provided. Cannot configure babel transpilation');
|
|
1005
|
-
}
|
|
1006
|
-
|
|
1007
|
-
await write({projectRoot, config: {presets: [preset.name]}});
|
|
990
|
+
### Example
|
|
1008
991
|
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
992
|
+
run \`${buildDocumentationCommand(packageManager)}\` to inject the usage example`
|
|
993
|
+
: ''
|
|
994
|
+
}`
|
|
1012
995
|
};
|
|
1013
996
|
}
|
|
1014
997
|
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
return {};
|
|
998
|
+
function determinePackageAccessLevelFromProjectVisibility ({projectVisibility}) {
|
|
999
|
+
return 'Public' === projectVisibility ? 'public' : 'restricted';
|
|
1019
1000
|
}
|
|
1020
1001
|
|
|
1021
|
-
function
|
|
1022
|
-
return
|
|
1002
|
+
function defineBadges (packageName, accessLevel) {
|
|
1003
|
+
return {
|
|
1004
|
+
consumer: {
|
|
1005
|
+
...'public' === accessLevel && {
|
|
1006
|
+
npm: {
|
|
1007
|
+
img: `https://img.shields.io/npm/v/${packageName}?logo=npm`,
|
|
1008
|
+
text: 'npm',
|
|
1009
|
+
link: `https://www.npmjs.com/package/${packageName}`
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
},
|
|
1013
|
+
status: {}
|
|
1014
|
+
};
|
|
1023
1015
|
}
|
|
1024
1016
|
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
compilerOptions: {
|
|
1036
|
-
rootDir: 'src',
|
|
1037
|
-
...projectTypes$1.PACKAGE === projectType && {
|
|
1038
|
-
outDir: 'lib',
|
|
1039
|
-
declaration: true
|
|
1017
|
+
function enhanceSlsa ({provenance}) {
|
|
1018
|
+
if (provenance) {
|
|
1019
|
+
return {
|
|
1020
|
+
badges: {
|
|
1021
|
+
status: {
|
|
1022
|
+
slsa: {
|
|
1023
|
+
img: 'https://slsa.dev/images/gh-badge-level2.svg',
|
|
1024
|
+
url: 'https://slsa.dev',
|
|
1025
|
+
text: 'SLSA Level 2'
|
|
1026
|
+
}
|
|
1040
1027
|
}
|
|
1041
|
-
}
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
}
|
|
1045
|
-
});
|
|
1028
|
+
}
|
|
1029
|
+
};
|
|
1030
|
+
}
|
|
1046
1031
|
|
|
1047
|
-
return {
|
|
1048
|
-
eslint: {configs: ['typescript']},
|
|
1049
|
-
dependencies: {javascript: {development: ['typescript', shareableTsConfigPackage]}},
|
|
1050
|
-
vcsIgnore: {files: ['tsconfig.tsbuildinfo']}
|
|
1051
|
-
};
|
|
1032
|
+
return {};
|
|
1052
1033
|
}
|
|
1053
1034
|
|
|
1054
|
-
function
|
|
1055
|
-
|
|
1056
|
-
case dialects$1.BABEL:
|
|
1057
|
-
return scaffoldBabel({preset: configs.babelPreset, projectRoot});
|
|
1058
|
-
case dialects$1.TYPESCRIPT:
|
|
1059
|
-
return scaffoldTypescript({config: configs.typescript, projectType, projectRoot, testFilenamePattern});
|
|
1060
|
-
default:
|
|
1061
|
-
return {};
|
|
1062
|
-
}
|
|
1063
|
-
}
|
|
1035
|
+
async function liftProvenance ({projectRoot, packageDetails}) {
|
|
1036
|
+
const {publishConfig: {access}} = packageDetails;
|
|
1064
1037
|
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
lift: lifter,
|
|
1068
|
-
scaffold: scaffoldDialect,
|
|
1069
|
-
test: predicate
|
|
1070
|
-
});
|
|
1038
|
+
if ('public' === access) {
|
|
1039
|
+
await mergeIntoExistingPackageJson({projectRoot, config: {publishConfig: {provenance: true}}});
|
|
1071
1040
|
|
|
1072
|
-
|
|
1073
|
-
|
|
1041
|
+
return enhanceSlsa({provenance: true});
|
|
1042
|
+
}
|
|
1074
1043
|
|
|
1075
|
-
|
|
1044
|
+
return {};
|
|
1045
|
+
}
|
|
1076
1046
|
|
|
1077
|
-
|
|
1078
|
-
|
|
1047
|
+
async function liftPublishable ({projectRoot, packageDetails}) {
|
|
1048
|
+
const {name: packageName, publishConfig: {access: packageAccessLevel}} = packageDetails;
|
|
1049
|
+
const homepage = `https://npm.im/${packageName}`;
|
|
1079
1050
|
|
|
1080
|
-
|
|
1051
|
+
await mergeIntoExistingPackageJson({projectRoot, config: {homepage}});
|
|
1052
|
+
|
|
1053
|
+
return deepmerge(
|
|
1054
|
+
await liftProvenance({packageDetails, projectRoot}),
|
|
1055
|
+
{
|
|
1056
|
+
homepage,
|
|
1057
|
+
dependencies: {javascript: {development: ['publint']}},
|
|
1058
|
+
scripts: {'lint:publish': 'publint --strict'},
|
|
1059
|
+
badges: defineBadges(packageName, packageAccessLevel)
|
|
1060
|
+
}
|
|
1061
|
+
);
|
|
1081
1062
|
}
|
|
1082
1063
|
|
|
1083
|
-
function
|
|
1084
|
-
packageName,
|
|
1085
|
-
dialect,
|
|
1086
|
-
license,
|
|
1087
|
-
author,
|
|
1088
|
-
description
|
|
1089
|
-
}) {
|
|
1064
|
+
async function scaffoldPublishable ({packageName, packageAccessLevel}) {
|
|
1090
1065
|
return {
|
|
1091
|
-
|
|
1092
|
-
description,
|
|
1093
|
-
license,
|
|
1094
|
-
type: dialects$1.ESM === dialect ? 'module' : 'commonjs',
|
|
1095
|
-
author: `${author.name}${author.email ? ` <${author.email}>` : ''}${author.url ? ` (${author.url})` : ''}`,
|
|
1096
|
-
scripts: {}
|
|
1066
|
+
badges: await defineBadges(packageName, packageAccessLevel)
|
|
1097
1067
|
};
|
|
1098
1068
|
}
|
|
1099
1069
|
|
|
1100
|
-
async function
|
|
1101
|
-
|
|
1102
|
-
projectName,
|
|
1103
|
-
scope,
|
|
1104
|
-
dialect,
|
|
1105
|
-
license,
|
|
1106
|
-
author,
|
|
1107
|
-
description
|
|
1108
|
-
}) {
|
|
1109
|
-
info('Configuring package.json');
|
|
1110
|
-
|
|
1111
|
-
const packageName = buildPackageName(projectName, scope);
|
|
1070
|
+
async function chooseBundler ({bundlers, decisions}) {
|
|
1071
|
+
if (!Object.keys(bundlers).length) return 'Other';
|
|
1112
1072
|
|
|
1113
|
-
await
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
author,
|
|
1120
|
-
description
|
|
1121
|
-
})
|
|
1122
|
-
});
|
|
1073
|
+
const answers = await prompt$1([{
|
|
1074
|
+
name: questionNames$1.PACKAGE_BUNDLER,
|
|
1075
|
+
type: 'list',
|
|
1076
|
+
message: 'Which bundler should be used?',
|
|
1077
|
+
choices: [...Object.keys(bundlers), 'Other']
|
|
1078
|
+
}], decisions);
|
|
1123
1079
|
|
|
1124
|
-
return
|
|
1080
|
+
return answers[questionNames$1.PACKAGE_BUNDLER];
|
|
1125
1081
|
}
|
|
1126
1082
|
|
|
1127
|
-
function
|
|
1128
|
-
|
|
1129
|
-
packageContents,
|
|
1130
|
-
[
|
|
1131
|
-
'name',
|
|
1132
|
-
'description',
|
|
1133
|
-
'license',
|
|
1134
|
-
'version',
|
|
1135
|
-
'private',
|
|
1136
|
-
'type',
|
|
1137
|
-
'engines',
|
|
1138
|
-
'author',
|
|
1139
|
-
'contributors',
|
|
1140
|
-
'repository',
|
|
1141
|
-
'bugs',
|
|
1142
|
-
'homepage',
|
|
1143
|
-
'funding',
|
|
1144
|
-
'keywords',
|
|
1145
|
-
'runkitExampleFilename',
|
|
1146
|
-
'exports',
|
|
1147
|
-
'bin',
|
|
1148
|
-
'main',
|
|
1149
|
-
'module',
|
|
1150
|
-
'types',
|
|
1151
|
-
'sideEffects',
|
|
1152
|
-
'scripts',
|
|
1153
|
-
'files',
|
|
1154
|
-
'publishConfig',
|
|
1155
|
-
'packageManager',
|
|
1156
|
-
'config',
|
|
1157
|
-
'dependencies',
|
|
1158
|
-
'devDependencies',
|
|
1159
|
-
'peerDependencies'
|
|
1160
|
-
]
|
|
1161
|
-
);
|
|
1162
|
-
}
|
|
1083
|
+
async function scaffoldBundler ({projectRoot, projectType, bundlers, dialect, decisions}) {
|
|
1084
|
+
const chosenBundler = await chooseBundler({bundlers, decisions});
|
|
1163
1085
|
|
|
1164
|
-
|
|
1165
|
-
return vcs && 'github' === vcs.host && {
|
|
1166
|
-
repository: pathWithinParent
|
|
1167
|
-
? {
|
|
1168
|
-
type: 'git',
|
|
1169
|
-
url: `https://github.com/${vcs.owner}/${vcs.name}.git`,
|
|
1170
|
-
directory: pathWithinParent
|
|
1171
|
-
}
|
|
1172
|
-
: `${vcs.owner}/${vcs.name}`,
|
|
1173
|
-
bugs: `https://github.com/${vcs.owner}/${vcs.name}/issues`
|
|
1174
|
-
};
|
|
1086
|
+
return scaffoldChoice(bundlers, chosenBundler, {projectRoot, projectType, dialect});
|
|
1175
1087
|
}
|
|
1176
1088
|
|
|
1177
|
-
|
|
1178
|
-
[
|
|
1179
|
-
installationCommand: 'install',
|
|
1180
|
-
installationFlags: {
|
|
1181
|
-
[DEV_DEPENDENCY_TYPE]: `save-${DEV_DEPENDENCY_TYPE}`,
|
|
1182
|
-
[PROD_DEPENDENCY_TYPE]: `save-${PROD_DEPENDENCY_TYPE}`,
|
|
1183
|
-
exact: 'save-exact'
|
|
1184
|
-
}
|
|
1185
|
-
},
|
|
1186
|
-
[packageManagers$1.YARN]: {
|
|
1187
|
-
installationCommand: 'add',
|
|
1188
|
-
installationFlags: {
|
|
1189
|
-
[DEV_DEPENDENCY_TYPE]: DEV_DEPENDENCY_TYPE,
|
|
1190
|
-
[PROD_DEPENDENCY_TYPE]: PROD_DEPENDENCY_TYPE,
|
|
1191
|
-
exact: 'exact'
|
|
1192
|
-
}
|
|
1193
|
-
}
|
|
1194
|
-
};
|
|
1089
|
+
function determinePathToTemplateFile (fileName) {
|
|
1090
|
+
const [, __dirname] = filedirname();
|
|
1195
1091
|
|
|
1196
|
-
|
|
1197
|
-
return details[manager].installationCommand;
|
|
1092
|
+
return resolve(__dirname, '..', 'templates', fileName);
|
|
1198
1093
|
}
|
|
1199
1094
|
|
|
1200
|
-
|
|
1201
|
-
return details[manager].installationFlags[type];
|
|
1202
|
-
}
|
|
1095
|
+
const defaultBuildDirectory$2 = 'lib';
|
|
1203
1096
|
|
|
1204
|
-
function
|
|
1205
|
-
return
|
|
1097
|
+
async function createExample(projectRoot, projectName, dialect) {
|
|
1098
|
+
return promises.writeFile(
|
|
1099
|
+
`${projectRoot}/example.js`,
|
|
1100
|
+
mustache.render(
|
|
1101
|
+
await promises.readFile(determinePathToTemplateFile('example.mustache'), 'utf8'),
|
|
1102
|
+
{projectName: camelcase(projectName), esm: dialect === dialects$1.ESM}
|
|
1103
|
+
)
|
|
1104
|
+
);
|
|
1206
1105
|
}
|
|
1207
1106
|
|
|
1208
|
-
async function
|
|
1209
|
-
|
|
1210
|
-
|
|
1107
|
+
async function buildDetailsForCommonJsProject({projectRoot, projectName, provideExample}) {
|
|
1108
|
+
await Promise.all([
|
|
1109
|
+
touch(`${projectRoot}/index.js`),
|
|
1110
|
+
provideExample
|
|
1111
|
+
? promises.writeFile(`${projectRoot}/example.js`, `const ${camelcase(projectName)} = require('.');\n`)
|
|
1112
|
+
: Promise.resolve()
|
|
1113
|
+
]);
|
|
1211
1114
|
|
|
1212
|
-
|
|
1213
|
-
`. ~/.nvm/nvm.sh && nvm use && ${packageManager} ${
|
|
1214
|
-
getInstallationCommandFor(packageManager)
|
|
1215
|
-
} ${[...new Set(dependencies)].join(' ')} --${getDependencyTypeFlag(packageManager, dependenciesType)}${
|
|
1216
|
-
DEV_DEPENDENCY_TYPE === dependenciesType ? ` --${getExactFlag(packageManager)}` : ''
|
|
1217
|
-
}`,
|
|
1218
|
-
{shell: true, cwd: projectRoot}
|
|
1219
|
-
);
|
|
1220
|
-
} else warn(`No ${dependenciesType} dependencies to install`);
|
|
1115
|
+
return {};
|
|
1221
1116
|
}
|
|
1222
1117
|
|
|
1223
|
-
async function
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1118
|
+
async function buildDetails ({
|
|
1119
|
+
projectRoot,
|
|
1120
|
+
projectName,
|
|
1121
|
+
visibility,
|
|
1122
|
+
packageName,
|
|
1123
|
+
packageBundlers,
|
|
1124
|
+
dialect,
|
|
1125
|
+
provideExample,
|
|
1126
|
+
decisions
|
|
1127
|
+
}) {
|
|
1128
|
+
if (dialects$1.COMMON_JS === dialect) return buildDetailsForCommonJsProject({projectRoot, projectName, provideExample});
|
|
1231
1129
|
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
try {
|
|
1239
|
-
await install$1(production, PROD_DEPENDENCY_TYPE, projectRoot, packageManager);
|
|
1240
|
-
await install$1(development, DEV_DEPENDENCY_TYPE, projectRoot, packageManager);
|
|
1241
|
-
} catch (e) {
|
|
1242
|
-
error('Failed to update dependencies');
|
|
1243
|
-
error(e, {level: 'secondary'});
|
|
1244
|
-
}
|
|
1245
|
-
}
|
|
1246
|
-
|
|
1247
|
-
function projectWillBeTested(scripts) {
|
|
1248
|
-
return Object.keys(scripts).find(scriptName => scriptName.startsWith('test:'));
|
|
1249
|
-
}
|
|
1250
|
-
|
|
1251
|
-
function projectShouldBeBuiltForVerification(scripts) {
|
|
1252
|
-
return 'run-s build' === scripts['pregenerate:md'];
|
|
1253
|
-
}
|
|
1254
|
-
|
|
1255
|
-
function updateTestScript (scripts) {
|
|
1256
|
-
return {
|
|
1257
|
-
...scripts,
|
|
1258
|
-
test: `npm-run-all --print-label${
|
|
1259
|
-
projectShouldBeBuiltForVerification(scripts) ? ' build' : ''
|
|
1260
|
-
} --parallel lint:*${
|
|
1261
|
-
projectWillBeTested(scripts) ? ' --parallel test:*' : ''
|
|
1262
|
-
}`
|
|
1263
|
-
};
|
|
1264
|
-
}
|
|
1265
|
-
|
|
1266
|
-
function liftScripts ({existingScripts, scripts}) {
|
|
1267
|
-
return updateTestScript({...existingScripts, ...scripts});
|
|
1268
|
-
}
|
|
1269
|
-
|
|
1270
|
-
async function liftPackage ({
|
|
1271
|
-
projectRoot,
|
|
1272
|
-
scripts,
|
|
1273
|
-
tags,
|
|
1274
|
-
dependencies,
|
|
1275
|
-
devDependencies,
|
|
1276
|
-
packageManager,
|
|
1277
|
-
vcs,
|
|
1278
|
-
pathWithinParent
|
|
1279
|
-
}) {
|
|
1280
|
-
info('Updating `package.json`', {level: 'secondary'});
|
|
1281
|
-
|
|
1282
|
-
const existingPackageJsonContents = JSON.parse(await promises$1.readFile(`${projectRoot}/package.json`, 'utf-8'));
|
|
1283
|
-
|
|
1284
|
-
await writePackageJson({
|
|
1285
|
-
projectRoot,
|
|
1286
|
-
config: sortPackageProperties({
|
|
1287
|
-
...existingPackageJsonContents,
|
|
1288
|
-
...defineVcsHostDetails(vcs, pathWithinParent),
|
|
1289
|
-
scripts: liftScripts({
|
|
1290
|
-
existingScripts: existingPackageJsonContents.scripts,
|
|
1291
|
-
scripts
|
|
1292
|
-
}),
|
|
1293
|
-
...tags && {
|
|
1294
|
-
keywords: existingPackageJsonContents.keywords ? [...existingPackageJsonContents.keywords, ...tags] : tags
|
|
1295
|
-
}
|
|
1296
|
-
})
|
|
1297
|
-
});
|
|
1298
|
-
|
|
1299
|
-
await processDependencies({dependencies, devDependencies, projectRoot, packageManager});
|
|
1300
|
-
}
|
|
1301
|
-
|
|
1302
|
-
async function lift ({projectRoot, vcs, results, pathWithinParent, enhancers = {}, configs = {}}) {
|
|
1303
|
-
info('Lifting JavaScript-specific details');
|
|
1304
|
-
|
|
1305
|
-
const {
|
|
1306
|
-
scripts,
|
|
1307
|
-
tags,
|
|
1308
|
-
dependencies,
|
|
1309
|
-
devDependencies,
|
|
1310
|
-
packageManager: manager
|
|
1311
|
-
} = results;
|
|
1312
|
-
|
|
1313
|
-
const [packageManager, packageContents] = await Promise.all([
|
|
1314
|
-
resolvePackageManager({projectRoot, packageManager: manager}),
|
|
1315
|
-
promises$1.readFile(`${projectRoot}/package.json`, 'utf8')
|
|
1130
|
+
const pathToCreatedSrcDirectory = await mkdir(`${projectRoot}/src`);
|
|
1131
|
+
const [bundlerResults] = await Promise.all([
|
|
1132
|
+
scaffoldBundler({bundlers: packageBundlers, projectRoot, dialect, decisions, projectType: projectTypes$1.PACKAGE}),
|
|
1133
|
+
provideExample ? await createExample(projectRoot, projectName, dialect) : Promise.resolve,
|
|
1134
|
+
touch(`${pathToCreatedSrcDirectory}/index.js`)
|
|
1316
1135
|
]);
|
|
1317
1136
|
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
enhancers: {
|
|
1321
|
-
...enhancers,
|
|
1322
|
-
huskyPlugin,
|
|
1323
|
-
enginesEnhancer,
|
|
1324
|
-
coveragePlugin,
|
|
1325
|
-
commitConventionPlugin,
|
|
1326
|
-
dialects,
|
|
1327
|
-
codeStylePlugin,
|
|
1328
|
-
npmConfigPlugin,
|
|
1329
|
-
projectTypes,
|
|
1330
|
-
packageManagers,
|
|
1331
|
-
registriesPlugin
|
|
1332
|
-
},
|
|
1333
|
-
options: {packageManager, projectRoot, vcs, packageDetails: JSON.parse(packageContents), configs}
|
|
1334
|
-
});
|
|
1335
|
-
|
|
1336
|
-
await liftPackage(
|
|
1337
|
-
deepmerge.all([
|
|
1338
|
-
{projectRoot, scripts, tags, dependencies, devDependencies, packageManager, vcs, pathWithinParent},
|
|
1339
|
-
enhancerResults
|
|
1340
|
-
])
|
|
1341
|
-
);
|
|
1342
|
-
|
|
1343
|
-
return enhancerResults;
|
|
1344
|
-
}
|
|
1345
|
-
|
|
1346
|
-
const scopeBasedConfigSchema = joi.object({scope: joi.string().regex(/^@[a-z0-9-]+$/i, 'scope').required()});
|
|
1347
|
-
|
|
1348
|
-
const nameBasedConfigSchema = joi.object({
|
|
1349
|
-
packageName: joi.string().required(),
|
|
1350
|
-
name: joi.string().required()
|
|
1351
|
-
});
|
|
1352
|
-
|
|
1353
|
-
const registriesSchema = joi.object().pattern(joi.string(), joi.string().uri()).default({});
|
|
1354
|
-
|
|
1355
|
-
const visibilitySchema = joi.string().valid('Public', 'Private').required();
|
|
1356
|
-
|
|
1357
|
-
const projectNameSchema = joi.string().regex(/^@\w*\//, {invert: true}).required();
|
|
1358
|
-
|
|
1359
|
-
const vcsSchema = joi.object({
|
|
1360
|
-
host: joi.string().required(),
|
|
1361
|
-
owner: joi.string().required(),
|
|
1362
|
-
name: joi.string().required()
|
|
1363
|
-
});
|
|
1364
|
-
|
|
1365
|
-
function validate(options) {
|
|
1366
|
-
const schema = joi.object({
|
|
1367
|
-
projectRoot: joi.string().required(),
|
|
1368
|
-
projectName: projectNameSchema,
|
|
1369
|
-
visibility: visibilitySchema,
|
|
1370
|
-
license: joi.string().required(),
|
|
1371
|
-
description: joi.string(),
|
|
1372
|
-
pathWithinParent: joi.string(),
|
|
1373
|
-
decisions: joi.object(),
|
|
1374
|
-
vcs: vcsSchema,
|
|
1375
|
-
configs: joi.object({
|
|
1376
|
-
eslint: scopeBasedConfigSchema,
|
|
1377
|
-
typescript: scopeBasedConfigSchema,
|
|
1378
|
-
prettier: scopeBasedConfigSchema,
|
|
1379
|
-
commitlint: nameBasedConfigSchema,
|
|
1380
|
-
babelPreset: nameBasedConfigSchema,
|
|
1381
|
-
remark: joi.string(),
|
|
1382
|
-
registries: registriesSchema
|
|
1383
|
-
}).default({registries: {}}),
|
|
1384
|
-
plugins: {
|
|
1385
|
-
unitTestFrameworks: pluginsSchema,
|
|
1386
|
-
packageBundlers: pluginsSchema,
|
|
1387
|
-
applicationTypes: pluginsSchema,
|
|
1388
|
-
packageTypes: pluginsSchema,
|
|
1389
|
-
monorepoTypes: pluginsSchema,
|
|
1390
|
-
hosts: pluginsSchema,
|
|
1391
|
-
ciServices: pluginsSchema
|
|
1392
|
-
}
|
|
1393
|
-
}).required();
|
|
1394
|
-
|
|
1395
|
-
return validateOptions(schema, options);
|
|
1396
|
-
}
|
|
1397
|
-
|
|
1398
|
-
function buildDialectChoices ({babelPreset, typescript}) {
|
|
1399
|
-
return [
|
|
1400
|
-
{name: 'Common JS (no transpilation)', value: dialects$1.COMMON_JS, short: 'cjs'},
|
|
1401
|
-
...babelPreset ? [{name: 'Modern JavaScript (transpiled)', value: dialects$1.BABEL, short: 'modern'}] : [],
|
|
1402
|
-
{name: 'ESM-only (no transpilation)', value: dialects$1.ESM, short: 'esm'},
|
|
1403
|
-
...typescript ? [{name: 'TypeScript', value: dialects$1.TYPESCRIPT, short: 'ts'}] : []
|
|
1404
|
-
];
|
|
1405
|
-
}
|
|
1406
|
-
|
|
1407
|
-
function projectIsCLI(answers) {
|
|
1408
|
-
return projectTypes$1.CLI === answers[questionNames$1.PROJECT_TYPE];
|
|
1409
|
-
}
|
|
1410
|
-
|
|
1411
|
-
function projectIsPackage(answers) {
|
|
1412
|
-
return projectTypes$1.PACKAGE === answers[questionNames$1.PROJECT_TYPE];
|
|
1413
|
-
}
|
|
1414
|
-
|
|
1415
|
-
function projectIsApplication(answers) {
|
|
1416
|
-
return projectTypes$1.APPLICATION === answers[questionNames$1.PROJECT_TYPE];
|
|
1417
|
-
}
|
|
1418
|
-
|
|
1419
|
-
function packageShouldBeScoped(visibility, answers) {
|
|
1420
|
-
return 'Private' === visibility || answers[questionNames$1.SHOULD_BE_SCOPED];
|
|
1421
|
-
}
|
|
1422
|
-
|
|
1423
|
-
function willBePublishedToNpm(answers) {
|
|
1424
|
-
return projectIsPackage(answers) || projectIsCLI(answers);
|
|
1425
|
-
}
|
|
1426
|
-
|
|
1427
|
-
function shouldBeScopedPromptShouldBePresented(answers) {
|
|
1428
|
-
return willBePublishedToNpm(answers);
|
|
1429
|
-
}
|
|
1430
|
-
|
|
1431
|
-
function scopePromptShouldBePresentedFactory(visibility) {
|
|
1432
|
-
return answers => willBePublishedToNpm(answers) && packageShouldBeScoped(visibility, answers);
|
|
1433
|
-
}
|
|
1434
|
-
|
|
1435
|
-
function lintingPromptShouldBePresented({
|
|
1436
|
-
[questionNames$2.UNIT_TESTS]: unitTested,
|
|
1437
|
-
[questionNames$2.INTEGRATION_TESTS]: integrationTested
|
|
1438
|
-
}) {
|
|
1439
|
-
return !unitTested && !integrationTested;
|
|
1440
|
-
}
|
|
1441
|
-
|
|
1442
|
-
function scope(visibility) {
|
|
1443
|
-
return input => {
|
|
1444
|
-
if (!input && 'Private' === visibility) {
|
|
1445
|
-
return 'Private packages must be scoped (https://docs.npmjs.com/private-modules/intro#setting-up-your-package)';
|
|
1446
|
-
}
|
|
1447
|
-
|
|
1448
|
-
return true;
|
|
1449
|
-
};
|
|
1450
|
-
}
|
|
1451
|
-
|
|
1452
|
-
function authorQuestions({name, email, url}) {
|
|
1453
|
-
return [
|
|
1454
|
-
{
|
|
1455
|
-
name: questionNames$1.AUTHOR_NAME,
|
|
1456
|
-
message: 'What is the author\'s name?',
|
|
1457
|
-
default: name
|
|
1458
|
-
},
|
|
1459
|
-
{
|
|
1460
|
-
name: questionNames$1.AUTHOR_EMAIL,
|
|
1461
|
-
message: 'What is the author\'s email?',
|
|
1462
|
-
default: email
|
|
1463
|
-
},
|
|
1137
|
+
return deepmerge(
|
|
1138
|
+
bundlerResults,
|
|
1464
1139
|
{
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1140
|
+
dependencies: {javascript: {development: ['rimraf']}},
|
|
1141
|
+
scripts: {
|
|
1142
|
+
clean: `rimraf ./${defaultBuildDirectory$2}`,
|
|
1143
|
+
prebuild: 'run-s clean',
|
|
1144
|
+
build: 'npm-run-all --print-label --parallel build:*',
|
|
1145
|
+
prepack: 'run-s build',
|
|
1146
|
+
...provideExample && {'pregenerate:md': 'run-s build'}
|
|
1147
|
+
},
|
|
1148
|
+
vcsIgnore: {directories: [`/${defaultBuildDirectory$2}/`]},
|
|
1149
|
+
buildDirectory: defaultBuildDirectory$2,
|
|
1150
|
+
badges: {
|
|
1151
|
+
consumer: {
|
|
1152
|
+
...'Public' === visibility && {
|
|
1153
|
+
runkit: {
|
|
1154
|
+
img: `https://badge.runkitcdn.com/${packageName}.svg`,
|
|
1155
|
+
text: `Try ${packageName} on RunKit`,
|
|
1156
|
+
link: `https://npm.runkit.com/${packageName}`
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
1468
1161
|
}
|
|
1469
|
-
|
|
1162
|
+
);
|
|
1470
1163
|
}
|
|
1471
1164
|
|
|
1472
|
-
async function
|
|
1473
|
-
|
|
1474
|
-
|
|
1165
|
+
async function scaffoldPackageType ({
|
|
1166
|
+
projectRoot,
|
|
1167
|
+
projectName,
|
|
1168
|
+
packageName,
|
|
1169
|
+
packageManager,
|
|
1475
1170
|
visibility,
|
|
1476
|
-
|
|
1171
|
+
scope,
|
|
1172
|
+
packageBundlers,
|
|
1477
1173
|
decisions,
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
let maybeLoggedInNpmUsername;
|
|
1484
|
-
try {
|
|
1485
|
-
maybeLoggedInNpmUsername = (await execa('npm', ['whoami'])).stdout;
|
|
1486
|
-
} catch (failedExecutionResult) {
|
|
1487
|
-
if (!decisions[questionNames$1.SCOPE]) {
|
|
1488
|
-
warn('No logged in user found with `npm whoami`. Login with `npm login` '
|
|
1489
|
-
+ 'to use your npm account name as the package scope default.');
|
|
1490
|
-
}
|
|
1491
|
-
}
|
|
1174
|
+
dialect,
|
|
1175
|
+
provideExample,
|
|
1176
|
+
publishRegistry
|
|
1177
|
+
}) {
|
|
1178
|
+
info('Scaffolding Package Details');
|
|
1492
1179
|
|
|
1493
|
-
const {
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
[questionNames$1.CONFIGURE_LINTING]: configureLinting,
|
|
1505
|
-
[questionNames$1.PROVIDE_EXAMPLE]: provideExample,
|
|
1506
|
-
[questionNames$1.PACKAGE_MANAGER]: packageManager,
|
|
1507
|
-
[questionNames$1.DIALECT]: dialect
|
|
1508
|
-
} = await prompt$1([
|
|
1509
|
-
{
|
|
1510
|
-
name: questionNames$1.DIALECT,
|
|
1511
|
-
message: 'Which JavaScript dialect should this project follow?',
|
|
1512
|
-
type: 'list',
|
|
1513
|
-
choices: buildDialectChoices(configs),
|
|
1514
|
-
default: 'babel'
|
|
1515
|
-
},
|
|
1516
|
-
...pathWithinParent ? [] : [{
|
|
1517
|
-
name: questionNames$1.NODE_VERSION_CATEGORY,
|
|
1518
|
-
message: 'What node.js version should be used?',
|
|
1519
|
-
type: 'list',
|
|
1520
|
-
choices: ['LTS', 'Latest'],
|
|
1521
|
-
default: 'LTS'
|
|
1522
|
-
}],
|
|
1523
|
-
{
|
|
1524
|
-
name: questionNames$1.PACKAGE_MANAGER,
|
|
1525
|
-
message: 'Which package manager will be used with this project?',
|
|
1526
|
-
type: 'list',
|
|
1527
|
-
choices: Object.values(packageManagers$1),
|
|
1528
|
-
default: packageManagers$1.NPM
|
|
1529
|
-
},
|
|
1530
|
-
{
|
|
1531
|
-
name: questionNames$1.PROJECT_TYPE,
|
|
1532
|
-
message: 'What type of JavaScript project is this?',
|
|
1533
|
-
type: 'list',
|
|
1534
|
-
choices: [...Object.values(projectTypes$1), 'Other'],
|
|
1535
|
-
default: projectTypes$1.PACKAGE
|
|
1536
|
-
},
|
|
1537
|
-
...'Private' === visibility ? [] : [{
|
|
1538
|
-
name: questionNames$1.SHOULD_BE_SCOPED,
|
|
1539
|
-
message: 'Should this package be scoped?',
|
|
1540
|
-
type: 'confirm',
|
|
1541
|
-
when: shouldBeScopedPromptShouldBePresented,
|
|
1542
|
-
default: true
|
|
1543
|
-
}],
|
|
1544
|
-
{
|
|
1545
|
-
name: questionNames$1.SCOPE,
|
|
1546
|
-
message: 'What is the scope?',
|
|
1547
|
-
when: scopePromptShouldBePresentedFactory(visibility),
|
|
1548
|
-
validate: scope(visibility),
|
|
1549
|
-
default: maybeLoggedInNpmUsername
|
|
1550
|
-
},
|
|
1551
|
-
...authorQuestions({
|
|
1552
|
-
name: npmConf$1.get('init.author.name'),
|
|
1553
|
-
email: npmConf$1.get('init.author.email'),
|
|
1554
|
-
url: npmConf$1.get('init.author.url')
|
|
1180
|
+
const packageAccessLevel = determinePackageAccessLevelFromProjectVisibility({projectVisibility: visibility});
|
|
1181
|
+
const [detailsForBuild, publishableResults] = await Promise.all([
|
|
1182
|
+
buildDetails({
|
|
1183
|
+
projectRoot,
|
|
1184
|
+
projectName,
|
|
1185
|
+
packageBundlers,
|
|
1186
|
+
visibility,
|
|
1187
|
+
packageName,
|
|
1188
|
+
dialect,
|
|
1189
|
+
provideExample,
|
|
1190
|
+
decisions
|
|
1555
1191
|
}),
|
|
1556
|
-
|
|
1557
|
-
{
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1192
|
+
scaffoldPublishable({packageName, packageAccessLevel}),
|
|
1193
|
+
mergeIntoExistingPackageJson({
|
|
1194
|
+
projectRoot,
|
|
1195
|
+
config: {
|
|
1196
|
+
files: ['example.js', ...dialects$1.COMMON_JS === dialect ? ['index.js'] : ['lib/']],
|
|
1197
|
+
publishConfig: {
|
|
1198
|
+
access: packageAccessLevel,
|
|
1199
|
+
...publishRegistry && {registry: publishRegistry}
|
|
1200
|
+
},
|
|
1201
|
+
sideEffects: false,
|
|
1202
|
+
...'Public' === visibility && {runkitExampleFilename: './example.js'},
|
|
1203
|
+
...dialects$1.BABEL === dialect && {
|
|
1204
|
+
main: './lib/index.js',
|
|
1205
|
+
module: './lib/index.mjs',
|
|
1206
|
+
exports: {
|
|
1207
|
+
module: './lib/index.mjs',
|
|
1208
|
+
require: './lib/index.js',
|
|
1209
|
+
import: './lib/index.mjs'
|
|
1210
|
+
}
|
|
1211
|
+
},
|
|
1212
|
+
...dialects$1.ESM === dialect && {
|
|
1213
|
+
main: './lib/index.js',
|
|
1214
|
+
exports: './lib/index.js'
|
|
1215
|
+
},
|
|
1216
|
+
...dialects$1.TYPESCRIPT === dialect && {
|
|
1217
|
+
main: './lib/index.js',
|
|
1218
|
+
module: './lib/index.mjs',
|
|
1219
|
+
types: './lib/index.d.ts',
|
|
1220
|
+
exports: {
|
|
1221
|
+
types: './lib/index.d.ts',
|
|
1222
|
+
require: './lib/index.js',
|
|
1223
|
+
import: './lib/index.mjs'
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
})
|
|
1228
|
+
]);
|
|
1229
|
+
|
|
1230
|
+
return deepmerge.all([
|
|
1231
|
+
publishableResults,
|
|
1563
1232
|
{
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1233
|
+
documentation: scaffoldPackageDocumentation({packageName, visibility, scope, packageManager, provideExample}),
|
|
1234
|
+
nextSteps: [
|
|
1235
|
+
{summary: 'Add the appropriate `save` flag to the installation instructions in the README'},
|
|
1236
|
+
{summary: 'Define supported node.js versions as `engines.node` in the `package.json` file'},
|
|
1237
|
+
{summary: 'Publish pre-release versions to npm until package is stable enough to publish v1.0.0'}
|
|
1238
|
+
]
|
|
1568
1239
|
},
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
message: 'Where will the application be hosted?',
|
|
1573
|
-
when: projectIsApplication,
|
|
1574
|
-
choices: [...Object.keys(hosts), 'Other']
|
|
1575
|
-
}
|
|
1576
|
-
], decisions);
|
|
1240
|
+
detailsForBuild
|
|
1241
|
+
]);
|
|
1242
|
+
}
|
|
1577
1243
|
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
projectType,
|
|
1581
|
-
ci,
|
|
1582
|
-
chosenHost,
|
|
1583
|
-
scope: scope$1,
|
|
1584
|
-
nodeVersionCategory,
|
|
1585
|
-
author: {name: authorName, email: authorEmail, url: authorUrl},
|
|
1586
|
-
configureLinting: false !== configureLinting,
|
|
1587
|
-
provideExample,
|
|
1588
|
-
packageManager,
|
|
1589
|
-
dialect
|
|
1590
|
-
};
|
|
1244
|
+
function liftPackage ({projectRoot, packageDetails}) {
|
|
1245
|
+
return liftPublishable({projectRoot, packageDetails});
|
|
1591
1246
|
}
|
|
1592
1247
|
|
|
1593
|
-
function
|
|
1594
|
-
return
|
|
1595
|
-
|
|
1596
|
-
...projectTypeResults.documentation,
|
|
1597
|
-
contributing: `### Dependencies
|
|
1248
|
+
async function isPackage ({packageDetails: {exports, publishConfig, bin}}) {
|
|
1249
|
+
return !!exports || (!!publishConfig && !bin);
|
|
1250
|
+
}
|
|
1598
1251
|
|
|
1599
|
-
|
|
1600
|
-
$ nvm install
|
|
1601
|
-
$ ${packageManager} install
|
|
1602
|
-
\`\`\`
|
|
1252
|
+
const defaultBuildDirectory$1 = 'public';
|
|
1603
1253
|
|
|
1604
|
-
|
|
1254
|
+
async function scaffoldApplicationType ({projectRoot}) {
|
|
1255
|
+
info('Scaffolding Application Details');
|
|
1605
1256
|
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1257
|
+
await mergeIntoExistingPackageJson({projectRoot, config: {private: true}});
|
|
1258
|
+
|
|
1259
|
+
const buildDirectory = defaultBuildDirectory$1;
|
|
1260
|
+
|
|
1261
|
+
return {
|
|
1262
|
+
scripts: {
|
|
1263
|
+
clean: `rimraf ./${buildDirectory}`,
|
|
1264
|
+
start: `node ./${buildDirectory}/index.js`,
|
|
1265
|
+
prebuild: 'run-s clean'
|
|
1266
|
+
},
|
|
1267
|
+
dependencies: {javascript: {development: ['rimraf']}},
|
|
1268
|
+
vcsIgnore: {files: ['.env'], directories: [`/${buildDirectory}/`]},
|
|
1269
|
+
buildDirectory,
|
|
1270
|
+
nextSteps: []
|
|
1609
1271
|
};
|
|
1610
1272
|
}
|
|
1611
1273
|
|
|
1612
|
-
function
|
|
1613
|
-
return
|
|
1274
|
+
function isApplication ({packageDetails}) {
|
|
1275
|
+
return !!packageDetails.private;
|
|
1614
1276
|
}
|
|
1615
1277
|
|
|
1616
|
-
async function
|
|
1617
|
-
info('
|
|
1278
|
+
async function scaffoldMonorepoType ({projectRoot}) {
|
|
1279
|
+
info('Scaffolding Monorepo Details');
|
|
1618
1280
|
|
|
1619
|
-
|
|
1620
|
-
`. ~/.nvm/nvm.sh && nvm ls-remote${('LTS' === nodeVersionCategory) ? ' --lts' : ''}`,
|
|
1621
|
-
{shell: true}
|
|
1622
|
-
);
|
|
1281
|
+
await mergeIntoExistingPackageJson({projectRoot, config: {private: true}});
|
|
1623
1282
|
|
|
1624
|
-
|
|
1625
|
-
|
|
1283
|
+
return {
|
|
1284
|
+
nextSteps: [{
|
|
1285
|
+
summary: 'Add packages to your new monorepo',
|
|
1286
|
+
description: 'Leverage [@form8ion/add-package-to-monorepo](https://npm.im/@form8ion/add-package-to-monorepo)'
|
|
1287
|
+
+ ' to scaffold new packages into your new monorepo'
|
|
1288
|
+
}]
|
|
1289
|
+
};
|
|
1290
|
+
}
|
|
1626
1291
|
|
|
1627
|
-
|
|
1292
|
+
const defaultBuildDirectory = 'bin';
|
|
1293
|
+
|
|
1294
|
+
async function scaffoldCliType ({
|
|
1295
|
+
packageName,
|
|
1296
|
+
visibility,
|
|
1297
|
+
projectRoot,
|
|
1298
|
+
dialect,
|
|
1299
|
+
publishRegistry,
|
|
1300
|
+
decisions,
|
|
1301
|
+
packageBundlers
|
|
1302
|
+
}) {
|
|
1303
|
+
const packageAccessLevel = determinePackageAccessLevelFromProjectVisibility({projectVisibility: visibility});
|
|
1304
|
+
const [bundlerResults, publishableResults] = await Promise.all([
|
|
1305
|
+
scaffoldBundler({bundlers: packageBundlers, projectRoot, dialect, decisions, projectType: projectTypes$1.CLI}),
|
|
1306
|
+
scaffoldPublishable({packageName, packageAccessLevel}),
|
|
1307
|
+
mergeIntoExistingPackageJson({
|
|
1308
|
+
projectRoot,
|
|
1309
|
+
config: {
|
|
1310
|
+
bin: {},
|
|
1311
|
+
files: [`${defaultBuildDirectory}/`],
|
|
1312
|
+
publishConfig: {
|
|
1313
|
+
access: packageAccessLevel,
|
|
1314
|
+
...publishRegistry && {registry: publishRegistry}
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
})
|
|
1318
|
+
]);
|
|
1319
|
+
|
|
1320
|
+
return deepmerge.all([
|
|
1321
|
+
publishableResults,
|
|
1322
|
+
bundlerResults,
|
|
1323
|
+
{
|
|
1324
|
+
scripts: {
|
|
1325
|
+
clean: `rimraf ./${defaultBuildDirectory}`,
|
|
1326
|
+
prebuild: 'run-s clean',
|
|
1327
|
+
build: 'npm-run-all --print-label --parallel build:*',
|
|
1328
|
+
prepack: 'run-s build'
|
|
1329
|
+
},
|
|
1330
|
+
dependencies: {javascript: {production: ['update-notifier'], development: ['rimraf']}},
|
|
1331
|
+
vcsIgnore: {files: [], directories: [`/${defaultBuildDirectory}/`]},
|
|
1332
|
+
buildDirectory: defaultBuildDirectory,
|
|
1333
|
+
nextSteps: [{summary: 'Define supported node.js versions as `engines.node` in the `package.json` file'}]
|
|
1334
|
+
}
|
|
1335
|
+
]);
|
|
1628
1336
|
}
|
|
1629
1337
|
|
|
1630
|
-
function
|
|
1631
|
-
|
|
1338
|
+
async function isCli ({packageDetails: {bin}}) {
|
|
1339
|
+
return !!bin;
|
|
1340
|
+
}
|
|
1632
1341
|
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
return subprocess;
|
|
1342
|
+
function liftCli ({projectRoot, packageDetails}) {
|
|
1343
|
+
return liftPublishable({projectRoot, packageDetails});
|
|
1636
1344
|
}
|
|
1637
1345
|
|
|
1638
|
-
async function
|
|
1639
|
-
|
|
1346
|
+
async function scaffoldProjectType ({
|
|
1347
|
+
projectType,
|
|
1348
|
+
projectRoot,
|
|
1349
|
+
projectName,
|
|
1350
|
+
packageName,
|
|
1351
|
+
packageManager,
|
|
1352
|
+
visibility,
|
|
1353
|
+
packageBundlers,
|
|
1354
|
+
scope,
|
|
1355
|
+
decisions,
|
|
1356
|
+
dialect,
|
|
1357
|
+
provideExample,
|
|
1358
|
+
publishRegistry
|
|
1359
|
+
}) {
|
|
1360
|
+
switch (projectType) {
|
|
1361
|
+
case projectTypes$1.PACKAGE:
|
|
1362
|
+
return scaffoldPackageType({
|
|
1363
|
+
projectRoot,
|
|
1364
|
+
projectName,
|
|
1365
|
+
packageName,
|
|
1366
|
+
packageManager,
|
|
1367
|
+
visibility,
|
|
1368
|
+
scope,
|
|
1369
|
+
packageBundlers,
|
|
1370
|
+
decisions,
|
|
1371
|
+
dialect,
|
|
1372
|
+
provideExample,
|
|
1373
|
+
publishRegistry
|
|
1374
|
+
});
|
|
1375
|
+
case projectTypes$1.APPLICATION:
|
|
1376
|
+
return scaffoldApplicationType({projectRoot});
|
|
1377
|
+
case projectTypes$1.CLI:
|
|
1378
|
+
return scaffoldCliType({
|
|
1379
|
+
packageName,
|
|
1380
|
+
visibility,
|
|
1381
|
+
projectRoot,
|
|
1382
|
+
dialect,
|
|
1383
|
+
publishRegistry,
|
|
1384
|
+
decisions,
|
|
1385
|
+
packageBundlers
|
|
1386
|
+
});
|
|
1387
|
+
case projectTypes$1.MONOREPO:
|
|
1388
|
+
return scaffoldMonorepoType({projectRoot});
|
|
1389
|
+
case 'Other':
|
|
1390
|
+
return {};
|
|
1391
|
+
default:
|
|
1392
|
+
throw new Error(`The project-type of ${projectType} is invalid`);
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
1640
1395
|
|
|
1641
|
-
|
|
1642
|
-
|
|
1396
|
+
async function tester$3 ({projectRoot, packageDetails}) {
|
|
1397
|
+
return await isPackage({projectRoot, packageDetails})
|
|
1398
|
+
|| await isCli({projectRoot, packageDetails})
|
|
1399
|
+
|| isApplication({projectRoot, packageDetails});
|
|
1400
|
+
}
|
|
1643
1401
|
|
|
1644
|
-
|
|
1402
|
+
function vcsRepositoryHostedOnGithub(vcs) {
|
|
1403
|
+
return vcs && 'github' === vcs.host;
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1406
|
+
async function lifter$2 ({projectRoot, packageDetails, vcs}) {
|
|
1407
|
+
if (await isPackage({projectRoot, packageDetails})) return liftPackage({projectRoot, packageDetails});
|
|
1408
|
+
if (await isCli({projectRoot, packageDetails})) return liftCli({projectRoot, packageDetails});
|
|
1645
1409
|
|
|
1646
|
-
|
|
1410
|
+
let homepage;
|
|
1647
1411
|
|
|
1648
|
-
|
|
1412
|
+
if (vcsRepositoryHostedOnGithub(vcs)) {
|
|
1413
|
+
homepage = `https://github.com/${vcs.owner}/${vcs.name}#readme`;
|
|
1649
1414
|
|
|
1650
|
-
|
|
1651
|
-
}
|
|
1415
|
+
await mergeIntoExistingPackageJson({projectRoot, config: {homepage}});
|
|
1416
|
+
}
|
|
1652
1417
|
|
|
1653
|
-
|
|
1654
|
-
return fileExists(`${projectRoot}/.nvmrc`);
|
|
1418
|
+
return {homepage};
|
|
1655
1419
|
}
|
|
1656
1420
|
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
}
|
|
1421
|
+
var projectTypes = /*#__PURE__*/Object.freeze({
|
|
1422
|
+
__proto__: null,
|
|
1423
|
+
lift: lifter$2,
|
|
1424
|
+
scaffold: scaffoldProjectType,
|
|
1425
|
+
test: tester$3
|
|
1426
|
+
});
|
|
1663
1427
|
|
|
1664
1428
|
async function chooseProjectTypePlugin ({types, projectType, decisions}) {
|
|
1665
1429
|
if (!Object.keys(types).length) return 'Other';
|
|
@@ -1727,6 +1491,59 @@ async function scaffoldTesting ({
|
|
|
1727
1491
|
);
|
|
1728
1492
|
}
|
|
1729
1493
|
|
|
1494
|
+
function buildAllowedHostsList ({packageManager, registries = {}}) {
|
|
1495
|
+
return [
|
|
1496
|
+
...!registries.registry ? [packageManager] : [],
|
|
1497
|
+
...Object.values(Object.fromEntries(Object.entries(registries).filter(([scope]) => 'publish' !== scope)))
|
|
1498
|
+
];
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
const lockfileLintSupportedPackageManagers = [packageManagers$1.NPM, packageManagers$1.YARN];
|
|
1502
|
+
|
|
1503
|
+
function lockfileLintSupports(packageManager) {
|
|
1504
|
+
return lockfileLintSupportedPackageManagers.includes(packageManager);
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1507
|
+
async function scaffoldLockfileLint ({projectRoot, packageManager, registries}) {
|
|
1508
|
+
if (!lockfileLintSupports(packageManager)) {
|
|
1509
|
+
throw new Error(
|
|
1510
|
+
`The ${packageManager} package manager is currently not supported by lockfile-lint. `
|
|
1511
|
+
+ `Only ${lockfileLintSupportedPackageManagers.join(' and ')} are currently supported.`
|
|
1512
|
+
);
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1515
|
+
await write$2({
|
|
1516
|
+
name: 'lockfile-lint',
|
|
1517
|
+
format: fileTypes.JSON,
|
|
1518
|
+
path: projectRoot,
|
|
1519
|
+
config: {
|
|
1520
|
+
path: determineLockfilePathFor(packageManager),
|
|
1521
|
+
type: packageManager,
|
|
1522
|
+
'validate-https': true,
|
|
1523
|
+
'allowed-hosts': buildAllowedHostsList({packageManager, registries})
|
|
1524
|
+
}
|
|
1525
|
+
});
|
|
1526
|
+
|
|
1527
|
+
return {
|
|
1528
|
+
dependencies: {javascript: {development: ['lockfile-lint']}},
|
|
1529
|
+
scripts: {'lint:lockfile': 'lockfile-lint'}
|
|
1530
|
+
};
|
|
1531
|
+
}
|
|
1532
|
+
|
|
1533
|
+
function lockfileLintIsAlreadyConfigured ({projectRoot}) {
|
|
1534
|
+
return fileExists(`${projectRoot}/.lockfile-lintrc.json`);
|
|
1535
|
+
}
|
|
1536
|
+
|
|
1537
|
+
const configName = 'lockfile-lint';
|
|
1538
|
+
|
|
1539
|
+
function read({projectRoot}) {
|
|
1540
|
+
return loadConfigFile({name: `.${configName}rc`, format: fileTypes.JSON, path: projectRoot});
|
|
1541
|
+
}
|
|
1542
|
+
|
|
1543
|
+
function write({projectRoot, config}) {
|
|
1544
|
+
return write$2({name: configName, format: fileTypes.JSON, path: projectRoot, config});
|
|
1545
|
+
}
|
|
1546
|
+
|
|
1730
1547
|
async function scaffoldLinting ({projectRoot, packageManager, registries}) {
|
|
1731
1548
|
return scaffoldLockfileLint({projectRoot, packageManager, registries});
|
|
1732
1549
|
}
|
|
@@ -1755,12 +1572,82 @@ async function scaffoldVerification({
|
|
|
1755
1572
|
pathWithinParent
|
|
1756
1573
|
}),
|
|
1757
1574
|
scaffoldLinting({projectRoot, packageManager, registries, vcs, pathWithinParent}),
|
|
1758
|
-
scaffold$
|
|
1575
|
+
scaffold$1({projectRoot, packageManager, pathWithinParent})
|
|
1759
1576
|
]);
|
|
1760
1577
|
|
|
1761
1578
|
return deepmerge.all([testingResults, lintingResults, huskyResults]);
|
|
1762
1579
|
}
|
|
1763
1580
|
|
|
1581
|
+
async function scaffoldRemark ({config, projectRoot, projectType, vcs}) {
|
|
1582
|
+
await write$2({
|
|
1583
|
+
format: fileTypes.JSON,
|
|
1584
|
+
path: projectRoot,
|
|
1585
|
+
name: 'remark',
|
|
1586
|
+
config: {
|
|
1587
|
+
settings: {
|
|
1588
|
+
listItemIndent: 'one',
|
|
1589
|
+
emphasis: '_',
|
|
1590
|
+
strong: '_',
|
|
1591
|
+
bullet: '*',
|
|
1592
|
+
incrementListMarker: false
|
|
1593
|
+
},
|
|
1594
|
+
plugins: [
|
|
1595
|
+
config,
|
|
1596
|
+
['remark-toc', {tight: true}],
|
|
1597
|
+
...projectTypes$1.PACKAGE === projectType ? [['remark-usage', {heading: 'example'}]] : [],
|
|
1598
|
+
...!vcs ? [['validate-links', {repository: false}]] : []
|
|
1599
|
+
]
|
|
1600
|
+
}
|
|
1601
|
+
});
|
|
1602
|
+
|
|
1603
|
+
return deepmerge(
|
|
1604
|
+
{
|
|
1605
|
+
dependencies: {javascript: {development: [config, 'remark-cli', 'remark-toc']}},
|
|
1606
|
+
scripts: {
|
|
1607
|
+
'lint:md': 'remark . --frail',
|
|
1608
|
+
'generate:md': 'remark . --output'
|
|
1609
|
+
}
|
|
1610
|
+
},
|
|
1611
|
+
{...projectTypes$1.PACKAGE === projectType && {dependencies: {javascript: {development: ['remark-usage']}}}}
|
|
1612
|
+
);
|
|
1613
|
+
}
|
|
1614
|
+
|
|
1615
|
+
async function scaffoldCodeStyle ({
|
|
1616
|
+
projectRoot,
|
|
1617
|
+
projectType,
|
|
1618
|
+
configs,
|
|
1619
|
+
vcs,
|
|
1620
|
+
configureLinting
|
|
1621
|
+
}) {
|
|
1622
|
+
return deepmerge.all(await Promise.all([
|
|
1623
|
+
configs.eslint
|
|
1624
|
+
&& configureLinting
|
|
1625
|
+
&& scaffold$2({projectRoot, config: configs.eslint}),
|
|
1626
|
+
scaffoldRemark({
|
|
1627
|
+
projectRoot,
|
|
1628
|
+
projectType,
|
|
1629
|
+
vcs,
|
|
1630
|
+
config: configs.remark || '@form8ion/remark-lint-preset'
|
|
1631
|
+
}),
|
|
1632
|
+
scaffold$3({projectRoot, config: configs.prettier})
|
|
1633
|
+
].filter(Boolean)));
|
|
1634
|
+
}
|
|
1635
|
+
|
|
1636
|
+
function lifter$1 (options) {
|
|
1637
|
+
return applyEnhancers({options, enhancers: [eslintPlugin]});
|
|
1638
|
+
}
|
|
1639
|
+
|
|
1640
|
+
function tester$2 (options) {
|
|
1641
|
+
return test$1(options);
|
|
1642
|
+
}
|
|
1643
|
+
|
|
1644
|
+
var codeStylePlugin = /*#__PURE__*/Object.freeze({
|
|
1645
|
+
__proto__: null,
|
|
1646
|
+
lift: lifter$1,
|
|
1647
|
+
scaffold: scaffoldCodeStyle,
|
|
1648
|
+
test: tester$2
|
|
1649
|
+
});
|
|
1650
|
+
|
|
1764
1651
|
async function scaffolder (options) {
|
|
1765
1652
|
info('Initializing JavaScript project');
|
|
1766
1653
|
|
|
@@ -1888,25 +1775,133 @@ async function scaffolder (options) {
|
|
|
1888
1775
|
projectTypePluginResults
|
|
1889
1776
|
]);
|
|
1890
1777
|
|
|
1891
|
-
// const liftResults = await lift({
|
|
1892
|
-
// results: deepmerge({devDependencies: ['npm-run-all2'], packageManager}, mergedContributions),
|
|
1893
|
-
// projectRoot,
|
|
1894
|
-
// configs,
|
|
1895
|
-
// vcs,
|
|
1896
|
-
// pathWithinParent
|
|
1897
|
-
// });
|
|
1898
|
-
|
|
1899
1778
|
return {
|
|
1900
1779
|
...mergedContributions,
|
|
1901
|
-
badges: buildBadgesDetails([mergedContributions/*, liftResults*/]),
|
|
1902
1780
|
documentation: scaffoldDocumentation({projectTypeResults, packageManager}),
|
|
1903
1781
|
tags: projectTypeResults.tags,
|
|
1904
1782
|
vcsIgnore: buildVcsIgnoreLists(mergedContributions.vcsIgnore),
|
|
1905
|
-
verificationCommand: `${buildDocumentationCommand(packageManager)} && ${packageManager} test
|
|
1906
|
-
|
|
1783
|
+
verificationCommand: `${buildDocumentationCommand(packageManager)} && ${packageManager} test`
|
|
1784
|
+
};
|
|
1785
|
+
}
|
|
1786
|
+
|
|
1787
|
+
function tester$1 () {
|
|
1788
|
+
return true;
|
|
1789
|
+
}
|
|
1790
|
+
|
|
1791
|
+
function buildRegistriesConfig (registries = {}) {
|
|
1792
|
+
return Object.entries(registries)
|
|
1793
|
+
.filter(([scope]) => 'publish' !== scope)
|
|
1794
|
+
.reduce((acc, [scope, url]) => {
|
|
1795
|
+
if ('registry' === scope) return {...acc, registry: url};
|
|
1796
|
+
|
|
1797
|
+
return {...acc, [`@${scope}:registry`]: url};
|
|
1798
|
+
}, {registry: 'https://registry.npmjs.org'});
|
|
1799
|
+
}
|
|
1800
|
+
|
|
1801
|
+
async function updateRegistriesInNpmConfig(registries, projectRoot) {
|
|
1802
|
+
const registriesForNpmConfig = buildRegistriesConfig(registries);
|
|
1803
|
+
|
|
1804
|
+
await writeNpmConfig({
|
|
1805
|
+
projectRoot,
|
|
1806
|
+
config: {
|
|
1807
|
+
...(await readNpmConfig({projectRoot})),
|
|
1808
|
+
...registriesForNpmConfig
|
|
1809
|
+
}
|
|
1810
|
+
});
|
|
1811
|
+
}
|
|
1812
|
+
|
|
1813
|
+
async function updateRegistriesInLockfileLintConfig(projectRoot, packageManager, registries) {
|
|
1814
|
+
await write({
|
|
1815
|
+
projectRoot,
|
|
1816
|
+
config: {
|
|
1817
|
+
...await read({projectRoot}),
|
|
1818
|
+
'allowed-hosts': buildAllowedHostsList({packageManager, registries})
|
|
1819
|
+
}
|
|
1820
|
+
});
|
|
1821
|
+
}
|
|
1822
|
+
|
|
1823
|
+
async function lifter ({projectRoot, packageManager, configs: {registries}}) {
|
|
1824
|
+
await updateRegistriesInNpmConfig(registries, projectRoot);
|
|
1825
|
+
|
|
1826
|
+
if (!(await lockfileLintIsAlreadyConfigured({projectRoot}))) {
|
|
1827
|
+
return scaffoldLockfileLint({projectRoot, packageManager, registries});
|
|
1828
|
+
}
|
|
1829
|
+
|
|
1830
|
+
await updateRegistriesInLockfileLintConfig(projectRoot, packageManager, registries);
|
|
1831
|
+
|
|
1832
|
+
return {};
|
|
1833
|
+
}
|
|
1834
|
+
|
|
1835
|
+
var registriesPlugin = /*#__PURE__*/Object.freeze({
|
|
1836
|
+
__proto__: null,
|
|
1837
|
+
lift: lifter,
|
|
1838
|
+
test: tester$1
|
|
1839
|
+
});
|
|
1840
|
+
|
|
1841
|
+
async function test({projectRoot}) {
|
|
1842
|
+
const {engines} = JSON.parse(await promises.readFile(`${projectRoot}/package.json`, 'utf8'));
|
|
1843
|
+
|
|
1844
|
+
return !!engines?.node;
|
|
1845
|
+
}
|
|
1846
|
+
|
|
1847
|
+
async function lift$1({packageDetails: {name}}) {
|
|
1848
|
+
return {
|
|
1849
|
+
dependencies: {javascript: {development: ['ls-engines']}},
|
|
1850
|
+
scripts: {'lint:engines': 'ls-engines'},
|
|
1851
|
+
badges: {consumer: {node: {img: `https://img.shields.io/node/v/${name}?logo=node.js`, text: 'node'}}}
|
|
1907
1852
|
};
|
|
1908
1853
|
}
|
|
1909
1854
|
|
|
1855
|
+
var enginesEnhancer = /*#__PURE__*/Object.freeze({
|
|
1856
|
+
__proto__: null,
|
|
1857
|
+
lift: lift$1,
|
|
1858
|
+
test: test
|
|
1859
|
+
});
|
|
1860
|
+
|
|
1861
|
+
async function lift ({projectRoot, vcs, results, pathWithinParent, enhancers = {}, configs = {}}) {
|
|
1862
|
+
info('Lifting JavaScript-specific details');
|
|
1863
|
+
|
|
1864
|
+
const {
|
|
1865
|
+
scripts,
|
|
1866
|
+
tags,
|
|
1867
|
+
dependencies,
|
|
1868
|
+
devDependencies,
|
|
1869
|
+
packageManager: manager
|
|
1870
|
+
} = results;
|
|
1871
|
+
|
|
1872
|
+
const [packageManager, packageContents] = await Promise.all([
|
|
1873
|
+
resolvePackageManager({projectRoot, packageManager: manager}),
|
|
1874
|
+
promises$1.readFile(`${projectRoot}/package.json`, 'utf8')
|
|
1875
|
+
]);
|
|
1876
|
+
|
|
1877
|
+
const enhancerResults = await applyEnhancers({
|
|
1878
|
+
results,
|
|
1879
|
+
enhancers: {
|
|
1880
|
+
...enhancers,
|
|
1881
|
+
huskyPlugin,
|
|
1882
|
+
enginesEnhancer,
|
|
1883
|
+
coveragePlugin,
|
|
1884
|
+
commitConventionPlugin,
|
|
1885
|
+
dialects,
|
|
1886
|
+
codeStylePlugin,
|
|
1887
|
+
npmConfigPlugin,
|
|
1888
|
+
projectTypes,
|
|
1889
|
+
packageManagers,
|
|
1890
|
+
registriesPlugin
|
|
1891
|
+
},
|
|
1892
|
+
options: {packageManager, projectRoot, vcs, packageDetails: JSON.parse(packageContents), configs}
|
|
1893
|
+
});
|
|
1894
|
+
|
|
1895
|
+
await liftPackage$1(
|
|
1896
|
+
deepmerge.all([
|
|
1897
|
+
{projectRoot, scripts, tags, dependencies, devDependencies, packageManager, vcs, pathWithinParent},
|
|
1898
|
+
enhancerResults
|
|
1899
|
+
])
|
|
1900
|
+
);
|
|
1901
|
+
|
|
1902
|
+
return enhancerResults;
|
|
1903
|
+
}
|
|
1904
|
+
|
|
1910
1905
|
async function tester ({projectRoot}) {
|
|
1911
1906
|
const [nvmFound, jsPackageManagerFound] = await Promise.all([
|
|
1912
1907
|
nvmIsUsed({projectRoot}),
|