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