@form8ion/javascript 14.0.0-alpha.9 → 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 +1235 -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,1153 +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
|
-
});
|
|
967
|
+
function getInstallationCommand(packageManager) {
|
|
968
|
+
if (packageManagers$1.NPM === packageManager) return 'npm install';
|
|
969
|
+
if (packageManagers$1.YARN === packageManager) return 'yarn add';
|
|
985
970
|
|
|
986
|
-
|
|
987
|
-
|
|
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
|
+
);
|
|
988
975
|
}
|
|
989
976
|
|
|
990
|
-
function
|
|
991
|
-
return
|
|
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
|
+
` : ''
|
|
992
984
|
}
|
|
985
|
+
\`\`\`sh
|
|
986
|
+
$ ${getInstallationCommand(packageManager)} ${packageName}
|
|
987
|
+
\`\`\`${provideExample
|
|
988
|
+
? `
|
|
993
989
|
|
|
994
|
-
|
|
995
|
-
if (ignore) {
|
|
996
|
-
const existingConfig = await loadConfig({projectRoot});
|
|
990
|
+
### Example
|
|
997
991
|
|
|
998
|
-
|
|
999
|
-
|
|
992
|
+
run \`${buildDocumentationCommand(packageManager)}\` to inject the usage example`
|
|
993
|
+
: ''
|
|
994
|
+
}`
|
|
995
|
+
};
|
|
1000
996
|
}
|
|
1001
997
|
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
}
|
|
1006
|
-
|
|
1007
|
-
await write({projectRoot, config: {presets: [preset.name]}});
|
|
998
|
+
function determinePackageAccessLevelFromProjectVisibility ({projectVisibility}) {
|
|
999
|
+
return 'Public' === projectVisibility ? 'public' : 'restricted';
|
|
1000
|
+
}
|
|
1008
1001
|
|
|
1002
|
+
function defineBadges (packageName, accessLevel) {
|
|
1009
1003
|
return {
|
|
1010
|
-
|
|
1011
|
-
|
|
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: {}
|
|
1012
1014
|
};
|
|
1013
1015
|
}
|
|
1014
1016
|
|
|
1015
|
-
|
|
1016
|
-
|
|
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
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
};
|
|
1030
|
+
}
|
|
1017
1031
|
|
|
1018
1032
|
return {};
|
|
1019
1033
|
}
|
|
1020
1034
|
|
|
1021
|
-
function
|
|
1022
|
-
|
|
1035
|
+
async function liftProvenance ({projectRoot, packageDetails}) {
|
|
1036
|
+
const {publishConfig: {access}} = packageDetails;
|
|
1037
|
+
|
|
1038
|
+
if ('public' === access) {
|
|
1039
|
+
await mergeIntoExistingPackageJson({projectRoot, config: {publishConfig: {provenance: true}}});
|
|
1040
|
+
|
|
1041
|
+
return enhanceSlsa({provenance: true});
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
return {};
|
|
1023
1045
|
}
|
|
1024
1046
|
|
|
1025
|
-
async function
|
|
1026
|
-
const
|
|
1047
|
+
async function liftPublishable ({projectRoot, packageDetails}) {
|
|
1048
|
+
const {name: packageName, publishConfig: {access: packageAccessLevel}} = packageDetails;
|
|
1049
|
+
const homepage = `https://npm.im/${packageName}`;
|
|
1027
1050
|
|
|
1028
|
-
await
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
...projectTypes$1.PACKAGE === projectType && {
|
|
1038
|
-
outDir: 'lib',
|
|
1039
|
-
declaration: true
|
|
1040
|
-
}
|
|
1041
|
-
},
|
|
1042
|
-
include: ['src/**/*.ts'],
|
|
1043
|
-
...testFilenamePattern && {exclude: [testFilenamePattern]}
|
|
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)
|
|
1044
1060
|
}
|
|
1045
|
-
|
|
1061
|
+
);
|
|
1062
|
+
}
|
|
1046
1063
|
|
|
1064
|
+
async function scaffoldPublishable ({packageName, packageAccessLevel}) {
|
|
1047
1065
|
return {
|
|
1048
|
-
|
|
1049
|
-
dependencies: {javascript: {development: ['typescript', shareableTsConfigPackage]}},
|
|
1050
|
-
vcsIgnore: {files: ['tsconfig.tsbuildinfo']}
|
|
1066
|
+
badges: await defineBadges(packageName, packageAccessLevel)
|
|
1051
1067
|
};
|
|
1052
1068
|
}
|
|
1053
1069
|
|
|
1054
|
-
function
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
}
|
|
1070
|
+
async function chooseBundler ({bundlers, decisions}) {
|
|
1071
|
+
if (!Object.keys(bundlers).length) return 'Other';
|
|
1072
|
+
|
|
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);
|
|
1079
|
+
|
|
1080
|
+
return answers[questionNames$1.PACKAGE_BUNDLER];
|
|
1063
1081
|
}
|
|
1064
1082
|
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
lift: lifter,
|
|
1068
|
-
scaffold: scaffoldDialect,
|
|
1069
|
-
test: predicate
|
|
1070
|
-
});
|
|
1083
|
+
async function scaffoldBundler ({projectRoot, projectType, bundlers, dialect, decisions}) {
|
|
1084
|
+
const chosenBundler = await chooseBundler({bundlers, decisions});
|
|
1071
1085
|
|
|
1072
|
-
|
|
1073
|
-
|
|
1086
|
+
return scaffoldChoice(bundlers, chosenBundler, {projectRoot, projectType, dialect});
|
|
1087
|
+
}
|
|
1074
1088
|
|
|
1075
|
-
|
|
1089
|
+
function determinePathToTemplateFile (fileName) {
|
|
1090
|
+
const [, __dirname] = filedirname();
|
|
1076
1091
|
|
|
1077
|
-
|
|
1078
|
-
|
|
1092
|
+
return resolve(__dirname, '..', 'templates', fileName);
|
|
1093
|
+
}
|
|
1079
1094
|
|
|
1080
|
-
|
|
1095
|
+
const defaultBuildDirectory$2 = 'lib';
|
|
1096
|
+
|
|
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
|
+
);
|
|
1081
1105
|
}
|
|
1082
1106
|
|
|
1083
|
-
function
|
|
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
|
+
]);
|
|
1114
|
+
|
|
1115
|
+
return {};
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1118
|
+
async function buildDetails ({
|
|
1119
|
+
projectRoot,
|
|
1120
|
+
projectName,
|
|
1121
|
+
visibility,
|
|
1084
1122
|
packageName,
|
|
1123
|
+
packageBundlers,
|
|
1085
1124
|
dialect,
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
description
|
|
1125
|
+
provideExample,
|
|
1126
|
+
decisions
|
|
1089
1127
|
}) {
|
|
1090
|
-
return {
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1128
|
+
if (dialects$1.COMMON_JS === dialect) return buildDetailsForCommonJsProject({projectRoot, projectName, provideExample});
|
|
1129
|
+
|
|
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`)
|
|
1135
|
+
]);
|
|
1136
|
+
|
|
1137
|
+
return deepmerge(
|
|
1138
|
+
bundlerResults,
|
|
1139
|
+
{
|
|
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
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
);
|
|
1098
1163
|
}
|
|
1099
1164
|
|
|
1100
|
-
async function
|
|
1165
|
+
async function scaffoldPackageType ({
|
|
1101
1166
|
projectRoot,
|
|
1102
1167
|
projectName,
|
|
1168
|
+
packageName,
|
|
1169
|
+
packageManager,
|
|
1170
|
+
visibility,
|
|
1103
1171
|
scope,
|
|
1172
|
+
packageBundlers,
|
|
1173
|
+
decisions,
|
|
1104
1174
|
dialect,
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
description
|
|
1175
|
+
provideExample,
|
|
1176
|
+
publishRegistry
|
|
1108
1177
|
}) {
|
|
1109
|
-
info('
|
|
1110
|
-
|
|
1111
|
-
const packageName = buildPackageName(projectName, scope);
|
|
1178
|
+
info('Scaffolding Package Details');
|
|
1112
1179
|
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1180
|
+
const packageAccessLevel = determinePackageAccessLevelFromProjectVisibility({projectVisibility: visibility});
|
|
1181
|
+
const [detailsForBuild, publishableResults] = await Promise.all([
|
|
1182
|
+
buildDetails({
|
|
1183
|
+
projectRoot,
|
|
1184
|
+
projectName,
|
|
1185
|
+
packageBundlers,
|
|
1186
|
+
visibility,
|
|
1116
1187
|
packageName,
|
|
1117
1188
|
dialect,
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1189
|
+
provideExample,
|
|
1190
|
+
decisions
|
|
1191
|
+
}),
|
|
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
|
+
}
|
|
1121
1227
|
})
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
return {packageName};
|
|
1125
|
-
}
|
|
1228
|
+
]);
|
|
1126
1229
|
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
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
|
-
}
|
|
1163
|
-
|
|
1164
|
-
function defineVcsHostDetails (vcs, pathWithinParent) {
|
|
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
|
-
};
|
|
1175
|
-
}
|
|
1176
|
-
|
|
1177
|
-
const details = {
|
|
1178
|
-
[packageManagers$1.NPM]: {
|
|
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
|
-
};
|
|
1195
|
-
|
|
1196
|
-
function getInstallationCommandFor(manager) {
|
|
1197
|
-
return details[manager].installationCommand;
|
|
1198
|
-
}
|
|
1199
|
-
|
|
1200
|
-
function getDependencyTypeFlag(manager, type) {
|
|
1201
|
-
return details[manager].installationFlags[type];
|
|
1230
|
+
return deepmerge.all([
|
|
1231
|
+
publishableResults,
|
|
1232
|
+
{
|
|
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
|
+
]
|
|
1239
|
+
},
|
|
1240
|
+
detailsForBuild
|
|
1241
|
+
]);
|
|
1202
1242
|
}
|
|
1203
1243
|
|
|
1204
|
-
function
|
|
1205
|
-
return
|
|
1244
|
+
function liftPackage ({projectRoot, packageDetails}) {
|
|
1245
|
+
return liftPublishable({projectRoot, packageDetails});
|
|
1206
1246
|
}
|
|
1207
1247
|
|
|
1208
|
-
async function
|
|
1209
|
-
|
|
1210
|
-
info(`Installing ${dependenciesType} dependencies`, {level: 'secondary'});
|
|
1211
|
-
|
|
1212
|
-
await execa(
|
|
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`);
|
|
1248
|
+
async function isPackage ({packageDetails: {exports, publishConfig, bin}}) {
|
|
1249
|
+
return !!exports || (!!publishConfig && !bin);
|
|
1221
1250
|
}
|
|
1222
1251
|
|
|
1223
|
-
|
|
1224
|
-
info('Processing dependencies');
|
|
1252
|
+
const defaultBuildDirectory$1 = 'public';
|
|
1225
1253
|
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
`devDependencies provided as: ${devDependencies}. Instead, provide under dependencies.javascript.development`
|
|
1229
|
-
);
|
|
1230
|
-
}
|
|
1254
|
+
async function scaffoldApplicationType ({projectRoot}) {
|
|
1255
|
+
info('Scaffolding Application Details');
|
|
1231
1256
|
|
|
1232
|
-
|
|
1233
|
-
throw new Error(`Expected dependencies to be an object. Instead received: ${dependencies}`);
|
|
1234
|
-
}
|
|
1257
|
+
await mergeIntoExistingPackageJson({projectRoot, config: {private: true}});
|
|
1235
1258
|
|
|
1236
|
-
const
|
|
1259
|
+
const buildDirectory = defaultBuildDirectory$1;
|
|
1237
1260
|
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
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: []
|
|
1271
|
+
};
|
|
1245
1272
|
}
|
|
1246
1273
|
|
|
1247
|
-
function
|
|
1248
|
-
return
|
|
1274
|
+
function isApplication ({packageDetails}) {
|
|
1275
|
+
return !!packageDetails.private;
|
|
1249
1276
|
}
|
|
1250
1277
|
|
|
1251
|
-
function
|
|
1252
|
-
|
|
1253
|
-
}
|
|
1278
|
+
async function scaffoldMonorepoType ({projectRoot}) {
|
|
1279
|
+
info('Scaffolding Monorepo Details');
|
|
1254
1280
|
|
|
1255
|
-
|
|
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
|
-
}
|
|
1281
|
+
await mergeIntoExistingPackageJson({projectRoot, config: {private: true}});
|
|
1265
1282
|
|
|
1266
|
-
function liftScripts ({existingScripts, scripts}) {
|
|
1267
1283
|
return {
|
|
1268
|
-
|
|
1269
|
-
|
|
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
|
+
}]
|
|
1270
1289
|
};
|
|
1271
1290
|
}
|
|
1272
1291
|
|
|
1273
|
-
|
|
1292
|
+
const defaultBuildDirectory = 'bin';
|
|
1293
|
+
|
|
1294
|
+
async function scaffoldCliType ({
|
|
1295
|
+
packageName,
|
|
1296
|
+
visibility,
|
|
1274
1297
|
projectRoot,
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
packageManager,
|
|
1280
|
-
vcs,
|
|
1281
|
-
pathWithinParent
|
|
1298
|
+
dialect,
|
|
1299
|
+
publishRegistry,
|
|
1300
|
+
decisions,
|
|
1301
|
+
packageBundlers
|
|
1282
1302
|
}) {
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
scripts: liftedScripts,
|
|
1297
|
-
...tags && {
|
|
1298
|
-
keywords: existingPackageJsonContents.keywords ? [...existingPackageJsonContents.keywords, ...tags] : tags
|
|
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
|
+
}
|
|
1299
1316
|
}
|
|
1300
1317
|
})
|
|
1301
|
-
|
|
1318
|
+
]);
|
|
1302
1319
|
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
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
|
+
]);
|
|
1309
1336
|
}
|
|
1310
1337
|
|
|
1311
|
-
async function
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
const {
|
|
1315
|
-
scripts,
|
|
1316
|
-
tags,
|
|
1317
|
-
dependencies,
|
|
1318
|
-
devDependencies,
|
|
1319
|
-
packageManager: manager
|
|
1320
|
-
} = results;
|
|
1338
|
+
async function isCli ({packageDetails: {bin}}) {
|
|
1339
|
+
return !!bin;
|
|
1340
|
+
}
|
|
1321
1341
|
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
]);
|
|
1342
|
+
function liftCli ({projectRoot, packageDetails}) {
|
|
1343
|
+
return liftPublishable({projectRoot, packageDetails});
|
|
1344
|
+
}
|
|
1326
1345
|
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
coveragePlugin,
|
|
1334
|
-
commitConventionPlugin,
|
|
1335
|
-
dialects,
|
|
1336
|
-
codeStylePlugin,
|
|
1337
|
-
npmConfigPlugin,
|
|
1338
|
-
projectTypes,
|
|
1339
|
-
packageManagers,
|
|
1340
|
-
registriesPlugin
|
|
1341
|
-
},
|
|
1342
|
-
options: {packageManager, projectRoot, vcs, packageDetails: JSON.parse(packageContents), configs}
|
|
1343
|
-
});
|
|
1344
|
-
|
|
1345
|
-
await liftPackage(
|
|
1346
|
-
deepmerge.all([
|
|
1347
|
-
{projectRoot, scripts, tags, dependencies, devDependencies, packageManager, vcs, pathWithinParent},
|
|
1348
|
-
enhancerResults
|
|
1349
|
-
])
|
|
1350
|
-
);
|
|
1351
|
-
|
|
1352
|
-
return enhancerResults;
|
|
1353
|
-
}
|
|
1354
|
-
|
|
1355
|
-
const scopeBasedConfigSchema = joi.object({scope: joi.string().regex(/^@[a-z0-9-]+$/i, 'scope').required()});
|
|
1356
|
-
|
|
1357
|
-
const nameBasedConfigSchema = joi.object({
|
|
1358
|
-
packageName: joi.string().required(),
|
|
1359
|
-
name: joi.string().required()
|
|
1360
|
-
});
|
|
1361
|
-
|
|
1362
|
-
const registriesSchema = joi.object().pattern(joi.string(), joi.string().uri()).default({});
|
|
1363
|
-
|
|
1364
|
-
const visibilitySchema = joi.string().valid('Public', 'Private').required();
|
|
1365
|
-
|
|
1366
|
-
const projectNameSchema = joi.string().regex(/^@\w*\//, {invert: true}).required();
|
|
1367
|
-
|
|
1368
|
-
const vcsSchema = joi.object({
|
|
1369
|
-
host: joi.string().required(),
|
|
1370
|
-
owner: joi.string().required(),
|
|
1371
|
-
name: joi.string().required()
|
|
1372
|
-
});
|
|
1373
|
-
|
|
1374
|
-
function validate(options) {
|
|
1375
|
-
const schema = joi.object({
|
|
1376
|
-
projectRoot: joi.string().required(),
|
|
1377
|
-
projectName: projectNameSchema,
|
|
1378
|
-
visibility: visibilitySchema,
|
|
1379
|
-
license: joi.string().required(),
|
|
1380
|
-
description: joi.string(),
|
|
1381
|
-
pathWithinParent: joi.string(),
|
|
1382
|
-
decisions: joi.object(),
|
|
1383
|
-
vcs: vcsSchema,
|
|
1384
|
-
configs: joi.object({
|
|
1385
|
-
eslint: scopeBasedConfigSchema,
|
|
1386
|
-
typescript: scopeBasedConfigSchema,
|
|
1387
|
-
prettier: scopeBasedConfigSchema,
|
|
1388
|
-
commitlint: nameBasedConfigSchema,
|
|
1389
|
-
babelPreset: nameBasedConfigSchema,
|
|
1390
|
-
remark: joi.string(),
|
|
1391
|
-
registries: registriesSchema
|
|
1392
|
-
}).default({registries: {}}),
|
|
1393
|
-
plugins: {
|
|
1394
|
-
unitTestFrameworks: pluginsSchema,
|
|
1395
|
-
packageBundlers: pluginsSchema,
|
|
1396
|
-
applicationTypes: pluginsSchema,
|
|
1397
|
-
packageTypes: pluginsSchema,
|
|
1398
|
-
monorepoTypes: pluginsSchema,
|
|
1399
|
-
hosts: pluginsSchema,
|
|
1400
|
-
ciServices: pluginsSchema
|
|
1401
|
-
}
|
|
1402
|
-
}).required();
|
|
1403
|
-
|
|
1404
|
-
return validateOptions(schema, options);
|
|
1405
|
-
}
|
|
1406
|
-
|
|
1407
|
-
function buildDialectChoices ({babelPreset, typescript}) {
|
|
1408
|
-
return [
|
|
1409
|
-
{name: 'Common JS (no transpilation)', value: dialects$1.COMMON_JS, short: 'cjs'},
|
|
1410
|
-
...babelPreset ? [{name: 'Modern JavaScript (transpiled)', value: dialects$1.BABEL, short: 'modern'}] : [],
|
|
1411
|
-
{name: 'ESM-only (no transpilation)', value: dialects$1.ESM, short: 'esm'},
|
|
1412
|
-
...typescript ? [{name: 'TypeScript', value: dialects$1.TYPESCRIPT, short: 'ts'}] : []
|
|
1413
|
-
];
|
|
1414
|
-
}
|
|
1415
|
-
|
|
1416
|
-
function projectIsCLI(answers) {
|
|
1417
|
-
return projectTypes$1.CLI === answers[questionNames$1.PROJECT_TYPE];
|
|
1418
|
-
}
|
|
1419
|
-
|
|
1420
|
-
function projectIsPackage(answers) {
|
|
1421
|
-
return projectTypes$1.PACKAGE === answers[questionNames$1.PROJECT_TYPE];
|
|
1422
|
-
}
|
|
1423
|
-
|
|
1424
|
-
function projectIsApplication(answers) {
|
|
1425
|
-
return projectTypes$1.APPLICATION === answers[questionNames$1.PROJECT_TYPE];
|
|
1426
|
-
}
|
|
1427
|
-
|
|
1428
|
-
function packageShouldBeScoped(visibility, answers) {
|
|
1429
|
-
return 'Private' === visibility || answers[questionNames$1.SHOULD_BE_SCOPED];
|
|
1430
|
-
}
|
|
1431
|
-
|
|
1432
|
-
function willBePublishedToNpm(answers) {
|
|
1433
|
-
return projectIsPackage(answers) || projectIsCLI(answers);
|
|
1434
|
-
}
|
|
1435
|
-
|
|
1436
|
-
function shouldBeScopedPromptShouldBePresented(answers) {
|
|
1437
|
-
return willBePublishedToNpm(answers);
|
|
1438
|
-
}
|
|
1439
|
-
|
|
1440
|
-
function scopePromptShouldBePresentedFactory(visibility) {
|
|
1441
|
-
return answers => willBePublishedToNpm(answers) && packageShouldBeScoped(visibility, answers);
|
|
1442
|
-
}
|
|
1443
|
-
|
|
1444
|
-
function lintingPromptShouldBePresented({
|
|
1445
|
-
[questionNames$2.UNIT_TESTS]: unitTested,
|
|
1446
|
-
[questionNames$2.INTEGRATION_TESTS]: integrationTested
|
|
1447
|
-
}) {
|
|
1448
|
-
return !unitTested && !integrationTested;
|
|
1449
|
-
}
|
|
1450
|
-
|
|
1451
|
-
function scope(visibility) {
|
|
1452
|
-
return input => {
|
|
1453
|
-
if (!input && 'Private' === visibility) {
|
|
1454
|
-
return 'Private packages must be scoped (https://docs.npmjs.com/private-modules/intro#setting-up-your-package)';
|
|
1455
|
-
}
|
|
1456
|
-
|
|
1457
|
-
return true;
|
|
1458
|
-
};
|
|
1459
|
-
}
|
|
1460
|
-
|
|
1461
|
-
function authorQuestions({name, email, url}) {
|
|
1462
|
-
return [
|
|
1463
|
-
{
|
|
1464
|
-
name: questionNames$1.AUTHOR_NAME,
|
|
1465
|
-
message: 'What is the author\'s name?',
|
|
1466
|
-
default: name
|
|
1467
|
-
},
|
|
1468
|
-
{
|
|
1469
|
-
name: questionNames$1.AUTHOR_EMAIL,
|
|
1470
|
-
message: 'What is the author\'s email?',
|
|
1471
|
-
default: email
|
|
1472
|
-
},
|
|
1473
|
-
{
|
|
1474
|
-
name: questionNames$1.AUTHOR_URL,
|
|
1475
|
-
message: 'What is the author\'s website url?',
|
|
1476
|
-
default: url
|
|
1477
|
-
}
|
|
1478
|
-
];
|
|
1479
|
-
}
|
|
1480
|
-
|
|
1481
|
-
async function prompt(
|
|
1482
|
-
ciServices,
|
|
1483
|
-
hosts,
|
|
1346
|
+
async function scaffoldProjectType ({
|
|
1347
|
+
projectType,
|
|
1348
|
+
projectRoot,
|
|
1349
|
+
projectName,
|
|
1350
|
+
packageName,
|
|
1351
|
+
packageManager,
|
|
1484
1352
|
visibility,
|
|
1485
|
-
|
|
1353
|
+
packageBundlers,
|
|
1354
|
+
scope,
|
|
1486
1355
|
decisions,
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
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`);
|
|
1500
1393
|
}
|
|
1501
|
-
|
|
1502
|
-
const {
|
|
1503
|
-
[questionNames$2.UNIT_TESTS]: unitTested,
|
|
1504
|
-
[questionNames$2.INTEGRATION_TESTS]: integrationTested,
|
|
1505
|
-
[questionNames$1.PROJECT_TYPE]: projectType,
|
|
1506
|
-
[questionNames$2.CI_SERVICE]: ci,
|
|
1507
|
-
[questionNames$1.HOST]: chosenHost,
|
|
1508
|
-
[questionNames$1.SCOPE]: scope$1,
|
|
1509
|
-
[questionNames$1.NODE_VERSION_CATEGORY]: nodeVersionCategory,
|
|
1510
|
-
[questionNames$1.AUTHOR_NAME]: authorName,
|
|
1511
|
-
[questionNames$1.AUTHOR_EMAIL]: authorEmail,
|
|
1512
|
-
[questionNames$1.AUTHOR_URL]: authorUrl,
|
|
1513
|
-
[questionNames$1.CONFIGURE_LINTING]: configureLinting,
|
|
1514
|
-
[questionNames$1.PROVIDE_EXAMPLE]: provideExample,
|
|
1515
|
-
[questionNames$1.PACKAGE_MANAGER]: packageManager,
|
|
1516
|
-
[questionNames$1.DIALECT]: dialect
|
|
1517
|
-
} = await prompt$1([
|
|
1518
|
-
{
|
|
1519
|
-
name: questionNames$1.DIALECT,
|
|
1520
|
-
message: 'Which JavaScript dialect should this project follow?',
|
|
1521
|
-
type: 'list',
|
|
1522
|
-
choices: buildDialectChoices(configs),
|
|
1523
|
-
default: 'babel'
|
|
1524
|
-
},
|
|
1525
|
-
...pathWithinParent ? [] : [{
|
|
1526
|
-
name: questionNames$1.NODE_VERSION_CATEGORY,
|
|
1527
|
-
message: 'What node.js version should be used?',
|
|
1528
|
-
type: 'list',
|
|
1529
|
-
choices: ['LTS', 'Latest'],
|
|
1530
|
-
default: 'LTS'
|
|
1531
|
-
}],
|
|
1532
|
-
{
|
|
1533
|
-
name: questionNames$1.PACKAGE_MANAGER,
|
|
1534
|
-
message: 'Which package manager will be used with this project?',
|
|
1535
|
-
type: 'list',
|
|
1536
|
-
choices: Object.values(packageManagers$1),
|
|
1537
|
-
default: packageManagers$1.NPM
|
|
1538
|
-
},
|
|
1539
|
-
{
|
|
1540
|
-
name: questionNames$1.PROJECT_TYPE,
|
|
1541
|
-
message: 'What type of JavaScript project is this?',
|
|
1542
|
-
type: 'list',
|
|
1543
|
-
choices: [...Object.values(projectTypes$1), 'Other'],
|
|
1544
|
-
default: projectTypes$1.PACKAGE
|
|
1545
|
-
},
|
|
1546
|
-
...'Private' === visibility ? [] : [{
|
|
1547
|
-
name: questionNames$1.SHOULD_BE_SCOPED,
|
|
1548
|
-
message: 'Should this package be scoped?',
|
|
1549
|
-
type: 'confirm',
|
|
1550
|
-
when: shouldBeScopedPromptShouldBePresented,
|
|
1551
|
-
default: true
|
|
1552
|
-
}],
|
|
1553
|
-
{
|
|
1554
|
-
name: questionNames$1.SCOPE,
|
|
1555
|
-
message: 'What is the scope?',
|
|
1556
|
-
when: scopePromptShouldBePresentedFactory(visibility),
|
|
1557
|
-
validate: scope(visibility),
|
|
1558
|
-
default: maybeLoggedInNpmUsername
|
|
1559
|
-
},
|
|
1560
|
-
...authorQuestions({
|
|
1561
|
-
name: npmConf$1.get('init.author.name'),
|
|
1562
|
-
email: npmConf$1.get('init.author.email'),
|
|
1563
|
-
url: npmConf$1.get('init.author.url')
|
|
1564
|
-
}),
|
|
1565
|
-
...questions(({vcs, ciServices, pathWithinParent})),
|
|
1566
|
-
{
|
|
1567
|
-
name: questionNames$1.CONFIGURE_LINTING,
|
|
1568
|
-
message: 'Will there be source code that should be linted?',
|
|
1569
|
-
type: 'confirm',
|
|
1570
|
-
when: lintingPromptShouldBePresented
|
|
1571
|
-
},
|
|
1572
|
-
{
|
|
1573
|
-
name: questionNames$1.PROVIDE_EXAMPLE,
|
|
1574
|
-
message: 'Should an example be provided in the README?',
|
|
1575
|
-
type: 'confirm',
|
|
1576
|
-
when: projectIsPackage
|
|
1577
|
-
},
|
|
1578
|
-
{
|
|
1579
|
-
name: questionNames$1.HOST,
|
|
1580
|
-
type: 'list',
|
|
1581
|
-
message: 'Where will the application be hosted?',
|
|
1582
|
-
when: projectIsApplication,
|
|
1583
|
-
choices: [...Object.keys(hosts), 'Other']
|
|
1584
|
-
}
|
|
1585
|
-
], decisions);
|
|
1586
|
-
|
|
1587
|
-
return {
|
|
1588
|
-
tests: {unit: unitTested, integration: integrationTested},
|
|
1589
|
-
projectType,
|
|
1590
|
-
ci,
|
|
1591
|
-
chosenHost,
|
|
1592
|
-
scope: scope$1,
|
|
1593
|
-
nodeVersionCategory,
|
|
1594
|
-
author: {name: authorName, email: authorEmail, url: authorUrl},
|
|
1595
|
-
configureLinting: false !== configureLinting,
|
|
1596
|
-
provideExample,
|
|
1597
|
-
packageManager,
|
|
1598
|
-
dialect
|
|
1599
|
-
};
|
|
1600
1394
|
}
|
|
1601
1395
|
|
|
1602
|
-
function
|
|
1603
|
-
return {
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
contributing: `### Dependencies
|
|
1607
|
-
|
|
1608
|
-
\`\`\`sh
|
|
1609
|
-
$ nvm install
|
|
1610
|
-
$ ${packageManager} install
|
|
1611
|
-
\`\`\`
|
|
1612
|
-
|
|
1613
|
-
### Verification
|
|
1614
|
-
|
|
1615
|
-
\`\`\`sh
|
|
1616
|
-
$ ${packageManager} test
|
|
1617
|
-
\`\`\``
|
|
1618
|
-
};
|
|
1619
|
-
}
|
|
1620
|
-
|
|
1621
|
-
function buildBadgesDetails (contributors) {
|
|
1622
|
-
return deepmerge.all(contributors).badges;
|
|
1623
|
-
}
|
|
1624
|
-
|
|
1625
|
-
async function determineLatestVersionOf(nodeVersionCategory) {
|
|
1626
|
-
info('Determining version of node', {level: 'secondary'});
|
|
1627
|
-
|
|
1628
|
-
const {stdout: nvmLsOutput} = await execa(
|
|
1629
|
-
`. ~/.nvm/nvm.sh && nvm ls-remote${('LTS' === nodeVersionCategory) ? ' --lts' : ''}`,
|
|
1630
|
-
{shell: true}
|
|
1631
|
-
);
|
|
1632
|
-
|
|
1633
|
-
const lsLines = nvmLsOutput.split('\n');
|
|
1634
|
-
const lsLine = lsLines[lsLines.length - 2];
|
|
1635
|
-
|
|
1636
|
-
return lsLine.match(/(v[0-9]+)\.[0-9]+\.[0-9]+/)[1];
|
|
1396
|
+
async function tester$3 ({projectRoot, packageDetails}) {
|
|
1397
|
+
return await isPackage({projectRoot, packageDetails})
|
|
1398
|
+
|| await isCli({projectRoot, packageDetails})
|
|
1399
|
+
|| isApplication({projectRoot, packageDetails});
|
|
1637
1400
|
}
|
|
1638
1401
|
|
|
1639
|
-
function
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
const subprocess = execa('. ~/.nvm/nvm.sh && nvm install', {shell: true});
|
|
1643
|
-
subprocess.stdout.pipe(process.stdout);
|
|
1644
|
-
return subprocess;
|
|
1402
|
+
function vcsRepositoryHostedOnGithub(vcs) {
|
|
1403
|
+
return vcs && 'github' === vcs.host;
|
|
1645
1404
|
}
|
|
1646
1405
|
|
|
1647
|
-
async function
|
|
1648
|
-
if (
|
|
1649
|
-
|
|
1650
|
-
const lowerCaseCategory = nodeVersionCategory.toLowerCase();
|
|
1651
|
-
info(`Configuring ${lowerCaseCategory} version of node`);
|
|
1652
|
-
|
|
1653
|
-
const version = await determineLatestVersionOf(nodeVersionCategory);
|
|
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});
|
|
1654
1409
|
|
|
1655
|
-
|
|
1410
|
+
let homepage;
|
|
1656
1411
|
|
|
1657
|
-
|
|
1412
|
+
if (vcsRepositoryHostedOnGithub(vcs)) {
|
|
1413
|
+
homepage = `https://github.com/${vcs.owner}/${vcs.name}#readme`;
|
|
1658
1414
|
|
|
1659
|
-
|
|
1660
|
-
}
|
|
1415
|
+
await mergeIntoExistingPackageJson({projectRoot, config: {homepage}});
|
|
1416
|
+
}
|
|
1661
1417
|
|
|
1662
|
-
|
|
1663
|
-
return fileExists(`${projectRoot}/.nvmrc`);
|
|
1418
|
+
return {homepage};
|
|
1664
1419
|
}
|
|
1665
1420
|
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
}
|
|
1421
|
+
var projectTypes = /*#__PURE__*/Object.freeze({
|
|
1422
|
+
__proto__: null,
|
|
1423
|
+
lift: lifter$2,
|
|
1424
|
+
scaffold: scaffoldProjectType,
|
|
1425
|
+
test: tester$3
|
|
1426
|
+
});
|
|
1672
1427
|
|
|
1673
1428
|
async function chooseProjectTypePlugin ({types, projectType, decisions}) {
|
|
1674
1429
|
if (!Object.keys(types).length) return 'Other';
|
|
@@ -1736,6 +1491,59 @@ async function scaffoldTesting ({
|
|
|
1736
1491
|
);
|
|
1737
1492
|
}
|
|
1738
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
|
+
|
|
1739
1547
|
async function scaffoldLinting ({projectRoot, packageManager, registries}) {
|
|
1740
1548
|
return scaffoldLockfileLint({projectRoot, packageManager, registries});
|
|
1741
1549
|
}
|
|
@@ -1764,12 +1572,82 @@ async function scaffoldVerification({
|
|
|
1764
1572
|
pathWithinParent
|
|
1765
1573
|
}),
|
|
1766
1574
|
scaffoldLinting({projectRoot, packageManager, registries, vcs, pathWithinParent}),
|
|
1767
|
-
scaffold$
|
|
1575
|
+
scaffold$1({projectRoot, packageManager, pathWithinParent})
|
|
1768
1576
|
]);
|
|
1769
1577
|
|
|
1770
1578
|
return deepmerge.all([testingResults, lintingResults, huskyResults]);
|
|
1771
1579
|
}
|
|
1772
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
|
+
|
|
1773
1651
|
async function scaffolder (options) {
|
|
1774
1652
|
info('Initializing JavaScript project');
|
|
1775
1653
|
|
|
@@ -1897,25 +1775,133 @@ async function scaffolder (options) {
|
|
|
1897
1775
|
projectTypePluginResults
|
|
1898
1776
|
]);
|
|
1899
1777
|
|
|
1900
|
-
// const liftResults = await lift({
|
|
1901
|
-
// results: deepmerge({devDependencies: ['npm-run-all2'], packageManager}, mergedContributions),
|
|
1902
|
-
// projectRoot,
|
|
1903
|
-
// configs,
|
|
1904
|
-
// vcs,
|
|
1905
|
-
// pathWithinParent
|
|
1906
|
-
// });
|
|
1907
|
-
|
|
1908
1778
|
return {
|
|
1909
1779
|
...mergedContributions,
|
|
1910
|
-
badges: buildBadgesDetails([mergedContributions/*, liftResults*/]),
|
|
1911
1780
|
documentation: scaffoldDocumentation({projectTypeResults, packageManager}),
|
|
1912
1781
|
tags: projectTypeResults.tags,
|
|
1913
1782
|
vcsIgnore: buildVcsIgnoreLists(mergedContributions.vcsIgnore),
|
|
1914
|
-
verificationCommand: `${buildDocumentationCommand(packageManager)} && ${packageManager} test
|
|
1915
|
-
|
|
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'}}}
|
|
1916
1852
|
};
|
|
1917
1853
|
}
|
|
1918
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
|
+
|
|
1919
1905
|
async function tester ({projectRoot}) {
|
|
1920
1906
|
const [nvmFound, jsPackageManagerFound] = await Promise.all([
|
|
1921
1907
|
nvmIsUsed({projectRoot}),
|