create-nx-workspace 16.8.0-beta.3 → 16.8.0-beta.5
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/bin/create-nx-workspace.js +615 -632
- package/package.json +2 -2
- package/src/create-empty-workspace.js +45 -46
- package/src/create-preset.js +34 -34
- package/src/create-sandbox.js +33 -36
- package/src/create-workspace.js +38 -41
- package/src/internal-utils/prompts.js +119 -128
- package/src/utils/child-process-utils.js +2 -2
- package/src/utils/ci/setup-ci.js +29 -32
- package/src/utils/error-utils.js +1 -2
- package/src/utils/git/default-base.js +1 -1
- package/src/utils/git/git.js +52 -53
- package/src/utils/nx/ab-testing.js +24 -28
- package/src/utils/nx/nx-cloud.js +22 -25
- package/src/utils/preset/get-third-party-preset.js +23 -27
- package/src/utils/preset/point-to-tutorial-and-course.js +0 -2
- package/src/utils/validate-npm-package.js +6 -1
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.commandsObject = void 0;
|
|
4
|
-
const tslib_1 = require("tslib");
|
|
5
4
|
const enquirer = require("enquirer");
|
|
6
5
|
const yargs = require("yargs");
|
|
7
6
|
const chalk = require("chalk");
|
|
@@ -83,49 +82,68 @@ exports.commandsObject = yargs
|
|
|
83
82
|
describe: chalk.dim `Test runner to use for end to end (E2E) tests.`,
|
|
84
83
|
choices: ['cypress', 'playwright', 'none'],
|
|
85
84
|
type: 'string',
|
|
86
|
-
}), yargs_options_1.withNxCloud, yargs_options_1.withCI, yargs_options_1.withAllPrompts, yargs_options_1.withPackageManager, yargs_options_1.withGitOptions), function handler(argv) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
title: `Something went wrong! v${version}`,
|
|
92
|
-
});
|
|
93
|
-
throw error;
|
|
85
|
+
}), yargs_options_1.withNxCloud, yargs_options_1.withCI, yargs_options_1.withAllPrompts, yargs_options_1.withPackageManager, yargs_options_1.withGitOptions), async function handler(argv) {
|
|
86
|
+
await main(argv).catch((error) => {
|
|
87
|
+
const { version } = require('../package.json');
|
|
88
|
+
output_1.output.error({
|
|
89
|
+
title: `Something went wrong! v${version}`,
|
|
94
90
|
});
|
|
91
|
+
throw error;
|
|
95
92
|
});
|
|
96
|
-
}, [
|
|
93
|
+
}, [
|
|
94
|
+
normalizeArgsMiddleware,
|
|
95
|
+
normalizeAndWarnOnDeprecatedPreset({
|
|
96
|
+
// TODO(v18): Remove Empty and Core presets
|
|
97
|
+
[preset_1.Preset.Core]: preset_1.Preset.NPM,
|
|
98
|
+
[preset_1.Preset.Empty]: preset_1.Preset.Apps,
|
|
99
|
+
}),
|
|
100
|
+
])
|
|
97
101
|
.help('help', chalk.dim `Show help`)
|
|
98
102
|
.updateLocale(decorator_1.yargsDecorator)
|
|
99
103
|
.version('version', chalk.dim `Show version`, nx_version_1.nxVersion);
|
|
100
|
-
function main(parsedArgs) {
|
|
101
|
-
|
|
104
|
+
async function main(parsedArgs) {
|
|
105
|
+
output_1.output.log({
|
|
106
|
+
title: `Creating your v${nx_version_1.nxVersion} workspace.`,
|
|
107
|
+
bodyLines: [
|
|
108
|
+
'To make sure the command works reliably in all environments, and that the preset is applied correctly,',
|
|
109
|
+
`Nx will run "${parsedArgs.packageManager} install" several times. Please wait.`,
|
|
110
|
+
],
|
|
111
|
+
});
|
|
112
|
+
const workspaceInfo = await (0, create_workspace_1.createWorkspace)(parsedArgs.preset, parsedArgs);
|
|
113
|
+
(0, show_nx_warning_1.showNxWarning)(parsedArgs.name);
|
|
114
|
+
await (0, ab_testing_1.recordStat)({
|
|
115
|
+
nxVersion: nx_version_1.nxVersion,
|
|
116
|
+
command: 'create-nx-workspace',
|
|
117
|
+
useCloud: parsedArgs.nxCloud,
|
|
118
|
+
meta: ab_testing_1.messages.codeOfSelectedPromptMessage('nxCloudCreation'),
|
|
119
|
+
});
|
|
120
|
+
if (parsedArgs.nxCloud && workspaceInfo.nxCloudInfo) {
|
|
121
|
+
(0, nx_cloud_1.printNxCloudSuccessMessage)(workspaceInfo.nxCloudInfo);
|
|
122
|
+
}
|
|
123
|
+
if ((0, preset_1.isKnownPreset)(parsedArgs.preset)) {
|
|
124
|
+
(0, point_to_tutorial_and_course_1.pointToTutorialAndCourse)(parsedArgs.preset);
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
102
127
|
output_1.output.log({
|
|
103
|
-
title: `
|
|
104
|
-
bodyLines: [
|
|
105
|
-
'To make sure the command works reliably in all environments, and that the preset is applied correctly,',
|
|
106
|
-
`Nx will run "${parsedArgs.packageManager} install" several times. Please wait.`,
|
|
107
|
-
],
|
|
108
|
-
});
|
|
109
|
-
const workspaceInfo = yield (0, create_workspace_1.createWorkspace)(parsedArgs.preset, parsedArgs);
|
|
110
|
-
(0, show_nx_warning_1.showNxWarning)(parsedArgs.name);
|
|
111
|
-
yield (0, ab_testing_1.recordStat)({
|
|
112
|
-
nxVersion: nx_version_1.nxVersion,
|
|
113
|
-
command: 'create-nx-workspace',
|
|
114
|
-
useCloud: parsedArgs.nxCloud,
|
|
115
|
-
meta: ab_testing_1.messages.codeOfSelectedPromptMessage('nxCloudCreation'),
|
|
128
|
+
title: `Successfully applied preset: ${parsedArgs.preset}`,
|
|
116
129
|
});
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
function normalizeAndWarnOnDeprecatedPreset(deprecatedPresets) {
|
|
133
|
+
return async (args) => {
|
|
134
|
+
if (!args.preset)
|
|
135
|
+
return;
|
|
136
|
+
if (deprecatedPresets[args.preset]) {
|
|
137
|
+
args.preset = deprecatedPresets[args.preset];
|
|
138
|
+
output_1.output.addVerticalSeparator();
|
|
139
|
+
output_1.output.note({
|
|
140
|
+
title: `The "${args.preset}" preset is deprecated.`,
|
|
141
|
+
bodyLines: [
|
|
142
|
+
`The "${args.preset}" preset will be removed in a future Nx release. Use the "${deprecatedPresets[args.preset]}" preset instead.`,
|
|
143
|
+
],
|
|
126
144
|
});
|
|
127
145
|
}
|
|
128
|
-
}
|
|
146
|
+
};
|
|
129
147
|
}
|
|
130
148
|
/**
|
|
131
149
|
* This function is used to normalize the arguments passed to the command.
|
|
@@ -133,53 +151,51 @@ function main(parsedArgs) {
|
|
|
133
151
|
* - normalize the preset.
|
|
134
152
|
* @param argv user arguments
|
|
135
153
|
*/
|
|
136
|
-
function normalizeArgsMiddleware(argv) {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
154
|
+
async function normalizeArgsMiddleware(argv) {
|
|
155
|
+
output_1.output.log({
|
|
156
|
+
title: "Let's create a new workspace [https://nx.dev/getting-started/intro]",
|
|
157
|
+
});
|
|
158
|
+
try {
|
|
159
|
+
let thirdPartyPreset;
|
|
160
|
+
// Node options
|
|
161
|
+
let docker;
|
|
141
162
|
try {
|
|
142
|
-
|
|
143
|
-
// Node options
|
|
144
|
-
let docker;
|
|
145
|
-
try {
|
|
146
|
-
thirdPartyPreset = yield (0, get_third_party_preset_1.getThirdPartyPreset)(argv.preset);
|
|
147
|
-
}
|
|
148
|
-
catch (e) {
|
|
149
|
-
output_1.output.error({
|
|
150
|
-
title: `Could not find preset "${argv.preset}"`,
|
|
151
|
-
});
|
|
152
|
-
process.exit(1);
|
|
153
|
-
}
|
|
154
|
-
argv.name = yield determineFolder(argv);
|
|
155
|
-
if (thirdPartyPreset) {
|
|
156
|
-
Object.assign(argv, {
|
|
157
|
-
preset: thirdPartyPreset,
|
|
158
|
-
appName: '',
|
|
159
|
-
style: '',
|
|
160
|
-
});
|
|
161
|
-
}
|
|
162
|
-
else {
|
|
163
|
-
argv.stack = yield determineStack(argv);
|
|
164
|
-
const presetOptions = yield determinePresetOptions(argv);
|
|
165
|
-
Object.assign(argv, presetOptions);
|
|
166
|
-
}
|
|
167
|
-
const packageManager = yield (0, prompts_1.determinePackageManager)(argv);
|
|
168
|
-
const defaultBase = yield (0, prompts_1.determineDefaultBase)(argv);
|
|
169
|
-
const nxCloud = yield (0, prompts_1.determineNxCloud)(argv);
|
|
170
|
-
const ci = yield (0, prompts_1.determineCI)(argv, nxCloud);
|
|
171
|
-
Object.assign(argv, {
|
|
172
|
-
nxCloud,
|
|
173
|
-
packageManager,
|
|
174
|
-
defaultBase,
|
|
175
|
-
ci,
|
|
176
|
-
});
|
|
163
|
+
thirdPartyPreset = await (0, get_third_party_preset_1.getThirdPartyPreset)(argv.preset);
|
|
177
164
|
}
|
|
178
165
|
catch (e) {
|
|
179
|
-
|
|
166
|
+
output_1.output.error({
|
|
167
|
+
title: `Could not find preset "${argv.preset}"`,
|
|
168
|
+
});
|
|
180
169
|
process.exit(1);
|
|
181
170
|
}
|
|
182
|
-
|
|
171
|
+
argv.name = await determineFolder(argv);
|
|
172
|
+
if (thirdPartyPreset) {
|
|
173
|
+
Object.assign(argv, {
|
|
174
|
+
preset: thirdPartyPreset,
|
|
175
|
+
appName: '',
|
|
176
|
+
style: '',
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
argv.stack = await determineStack(argv);
|
|
181
|
+
const presetOptions = await determinePresetOptions(argv);
|
|
182
|
+
Object.assign(argv, presetOptions);
|
|
183
|
+
}
|
|
184
|
+
const packageManager = await (0, prompts_1.determinePackageManager)(argv);
|
|
185
|
+
const defaultBase = await (0, prompts_1.determineDefaultBase)(argv);
|
|
186
|
+
const nxCloud = await (0, prompts_1.determineNxCloud)(argv);
|
|
187
|
+
const ci = await (0, prompts_1.determineCI)(argv, nxCloud);
|
|
188
|
+
Object.assign(argv, {
|
|
189
|
+
nxCloud,
|
|
190
|
+
packageManager,
|
|
191
|
+
defaultBase,
|
|
192
|
+
ci,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
catch (e) {
|
|
196
|
+
console.error(e);
|
|
197
|
+
process.exit(1);
|
|
198
|
+
}
|
|
183
199
|
}
|
|
184
200
|
function invariant(predicate, message) {
|
|
185
201
|
if (!predicate) {
|
|
@@ -187,583 +203,337 @@ function invariant(predicate, message) {
|
|
|
187
203
|
process.exit(1);
|
|
188
204
|
}
|
|
189
205
|
}
|
|
190
|
-
function determineFolder(parsedArgs) {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
title: 'That folder is already taken',
|
|
211
|
-
});
|
|
212
|
-
return reply.folderName;
|
|
206
|
+
async function determineFolder(parsedArgs) {
|
|
207
|
+
const folderName = parsedArgs._[0]
|
|
208
|
+
? parsedArgs._[0].toString()
|
|
209
|
+
: parsedArgs.name;
|
|
210
|
+
if (folderName)
|
|
211
|
+
return folderName;
|
|
212
|
+
const reply = await enquirer.prompt([
|
|
213
|
+
{
|
|
214
|
+
name: 'folderName',
|
|
215
|
+
message: `Where would you like to create your workspace?`,
|
|
216
|
+
initial: 'org',
|
|
217
|
+
type: 'input',
|
|
218
|
+
},
|
|
219
|
+
]);
|
|
220
|
+
invariant(reply.folderName, {
|
|
221
|
+
title: 'Invalid folder name',
|
|
222
|
+
bodyLines: [`Folder name cannot be empty`],
|
|
223
|
+
});
|
|
224
|
+
invariant(!(0, fs_1.existsSync)(reply.folderName), {
|
|
225
|
+
title: 'That folder is already taken',
|
|
213
226
|
});
|
|
227
|
+
return reply.folderName;
|
|
214
228
|
}
|
|
215
|
-
function determineStack(parsedArgs) {
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
case preset_1.Preset.Expo:
|
|
243
|
-
default:
|
|
244
|
-
return 'unknown';
|
|
245
|
-
}
|
|
229
|
+
async function determineStack(parsedArgs) {
|
|
230
|
+
if (parsedArgs.preset) {
|
|
231
|
+
switch (parsedArgs.preset) {
|
|
232
|
+
case preset_1.Preset.Angular:
|
|
233
|
+
case preset_1.Preset.AngularStandalone:
|
|
234
|
+
case preset_1.Preset.AngularMonorepo:
|
|
235
|
+
return 'angular';
|
|
236
|
+
case preset_1.Preset.React:
|
|
237
|
+
case preset_1.Preset.ReactStandalone:
|
|
238
|
+
case preset_1.Preset.ReactMonorepo:
|
|
239
|
+
case preset_1.Preset.NextJs:
|
|
240
|
+
case preset_1.Preset.NextJsStandalone:
|
|
241
|
+
return 'react';
|
|
242
|
+
case preset_1.Preset.Nest:
|
|
243
|
+
case preset_1.Preset.NodeStandalone:
|
|
244
|
+
case preset_1.Preset.Express:
|
|
245
|
+
return 'node';
|
|
246
|
+
case preset_1.Preset.Apps:
|
|
247
|
+
case preset_1.Preset.NPM:
|
|
248
|
+
case preset_1.Preset.TS:
|
|
249
|
+
case preset_1.Preset.TsStandalone:
|
|
250
|
+
return 'none';
|
|
251
|
+
case preset_1.Preset.WebComponents:
|
|
252
|
+
case preset_1.Preset.ReactNative:
|
|
253
|
+
case preset_1.Preset.Expo:
|
|
254
|
+
default:
|
|
255
|
+
return 'unknown';
|
|
246
256
|
}
|
|
247
|
-
|
|
257
|
+
}
|
|
258
|
+
const { stack } = await enquirer.prompt([
|
|
259
|
+
{
|
|
260
|
+
name: 'stack',
|
|
261
|
+
message: `Which stack do you want to use?`,
|
|
262
|
+
type: 'autocomplete',
|
|
263
|
+
choices: [
|
|
264
|
+
{
|
|
265
|
+
name: `none`,
|
|
266
|
+
message: `None: Configures a TypeScript/JavaScript project with minimal structure.`,
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
name: `react`,
|
|
270
|
+
message: `React: Configures a React application with your framework of choice.`,
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
name: `angular`,
|
|
274
|
+
message: `Angular: Configures a Angular application with modern tooling.`,
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
name: `node`,
|
|
278
|
+
message: `Node: Configures a Node API application with your framework of choice.`,
|
|
279
|
+
},
|
|
280
|
+
],
|
|
281
|
+
},
|
|
282
|
+
]);
|
|
283
|
+
return stack;
|
|
284
|
+
}
|
|
285
|
+
async function determinePresetOptions(parsedArgs) {
|
|
286
|
+
switch (parsedArgs.stack) {
|
|
287
|
+
case 'none':
|
|
288
|
+
return determineNoneOptions(parsedArgs);
|
|
289
|
+
case 'react':
|
|
290
|
+
return determineReactOptions(parsedArgs);
|
|
291
|
+
case 'angular':
|
|
292
|
+
return determineAngularOptions(parsedArgs);
|
|
293
|
+
case 'node':
|
|
294
|
+
return determineNodeOptions(parsedArgs);
|
|
295
|
+
default:
|
|
296
|
+
return parsedArgs;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
async function determineNoneOptions(parsedArgs) {
|
|
300
|
+
let preset;
|
|
301
|
+
let workspaceType = undefined;
|
|
302
|
+
let appName = undefined;
|
|
303
|
+
let js;
|
|
304
|
+
if (parsedArgs.preset) {
|
|
305
|
+
preset = parsedArgs.preset;
|
|
306
|
+
}
|
|
307
|
+
else {
|
|
308
|
+
workspaceType = await determinePackageBasedOrIntegratedOrStandalone();
|
|
309
|
+
if (workspaceType === 'standalone') {
|
|
310
|
+
preset = preset_1.Preset.TsStandalone;
|
|
311
|
+
}
|
|
312
|
+
else if (workspaceType === 'integrated') {
|
|
313
|
+
preset = preset_1.Preset.Apps;
|
|
314
|
+
}
|
|
315
|
+
else {
|
|
316
|
+
preset = preset_1.Preset.NPM;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
if (parsedArgs.js !== undefined) {
|
|
320
|
+
js = parsedArgs.js;
|
|
321
|
+
}
|
|
322
|
+
else if (preset === preset_1.Preset.TsStandalone) {
|
|
323
|
+
// Only standalone TS preset generates a default package, so we need to provide --js and --appName options.
|
|
324
|
+
appName = parsedArgs.name;
|
|
325
|
+
const reply = await enquirer.prompt([
|
|
248
326
|
{
|
|
249
|
-
name: '
|
|
250
|
-
message: `
|
|
327
|
+
name: 'ts',
|
|
328
|
+
message: `Would you like to use TypeScript with this project?`,
|
|
251
329
|
type: 'autocomplete',
|
|
252
330
|
choices: [
|
|
253
331
|
{
|
|
254
|
-
name:
|
|
255
|
-
message: `None: Configures a TypeScript/JavaScript project with minimal structure.`,
|
|
256
|
-
},
|
|
257
|
-
{
|
|
258
|
-
name: `react`,
|
|
259
|
-
message: `React: Configures a React application with your framework of choice.`,
|
|
260
|
-
},
|
|
261
|
-
{
|
|
262
|
-
name: `angular`,
|
|
263
|
-
message: `Angular: Configures a Angular application with modern tooling.`,
|
|
332
|
+
name: 'Yes',
|
|
264
333
|
},
|
|
265
334
|
{
|
|
266
|
-
name:
|
|
267
|
-
message: `Node: Configures a Node API application with your framework of choice.`,
|
|
335
|
+
name: 'No',
|
|
268
336
|
},
|
|
269
337
|
],
|
|
338
|
+
initial: 'Yes',
|
|
270
339
|
},
|
|
271
340
|
]);
|
|
272
|
-
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
function determinePresetOptions(parsedArgs) {
|
|
276
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
277
|
-
switch (parsedArgs.stack) {
|
|
278
|
-
case 'none':
|
|
279
|
-
return determineNoneOptions(parsedArgs);
|
|
280
|
-
case 'react':
|
|
281
|
-
return determineReactOptions(parsedArgs);
|
|
282
|
-
case 'angular':
|
|
283
|
-
return determineAngularOptions(parsedArgs);
|
|
284
|
-
case 'node':
|
|
285
|
-
return determineNodeOptions(parsedArgs);
|
|
286
|
-
default:
|
|
287
|
-
return parsedArgs;
|
|
288
|
-
}
|
|
289
|
-
});
|
|
341
|
+
js = reply.ts === 'No';
|
|
342
|
+
}
|
|
343
|
+
return { preset, js, appName };
|
|
290
344
|
}
|
|
291
|
-
function
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
345
|
+
async function determineReactOptions(parsedArgs) {
|
|
346
|
+
let preset;
|
|
347
|
+
let style = undefined;
|
|
348
|
+
let appName;
|
|
349
|
+
let bundler = undefined;
|
|
350
|
+
let e2eTestRunner = undefined;
|
|
351
|
+
let nextAppDir = false;
|
|
352
|
+
if (parsedArgs.preset && parsedArgs.preset !== preset_1.Preset.React) {
|
|
353
|
+
preset = parsedArgs.preset;
|
|
354
|
+
if (preset === preset_1.Preset.ReactStandalone ||
|
|
355
|
+
preset === preset_1.Preset.NextJsStandalone) {
|
|
356
|
+
appName = parsedArgs.appName ?? parsedArgs.name;
|
|
299
357
|
}
|
|
300
358
|
else {
|
|
301
|
-
|
|
302
|
-
if (workspaceType === 'standalone') {
|
|
303
|
-
preset = preset_1.Preset.TsStandalone;
|
|
304
|
-
}
|
|
305
|
-
else if (workspaceType === 'integrated') {
|
|
306
|
-
preset = preset_1.Preset.Apps;
|
|
307
|
-
}
|
|
308
|
-
else {
|
|
309
|
-
preset = preset_1.Preset.NPM;
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
if (parsedArgs.js !== undefined) {
|
|
313
|
-
js = parsedArgs.js;
|
|
359
|
+
appName = await determineAppName(parsedArgs);
|
|
314
360
|
}
|
|
315
|
-
|
|
316
|
-
|
|
361
|
+
}
|
|
362
|
+
else {
|
|
363
|
+
const framework = await determineReactFramework(parsedArgs);
|
|
364
|
+
// React Native and Expo only support integrated monorepos for now.
|
|
365
|
+
// TODO(jack): Add standalone support for React Native and Expo.
|
|
366
|
+
const workspaceType = framework === 'react-native' || framework === 'expo'
|
|
367
|
+
? 'integrated'
|
|
368
|
+
: await determineStandaloneOrMonorepo();
|
|
369
|
+
if (workspaceType === 'standalone') {
|
|
317
370
|
appName = parsedArgs.name;
|
|
318
|
-
const reply = yield enquirer.prompt([
|
|
319
|
-
{
|
|
320
|
-
name: 'ts',
|
|
321
|
-
message: `Would you like to use TypeScript with this project?`,
|
|
322
|
-
type: 'autocomplete',
|
|
323
|
-
choices: [
|
|
324
|
-
{
|
|
325
|
-
name: 'Yes',
|
|
326
|
-
},
|
|
327
|
-
{
|
|
328
|
-
name: 'No',
|
|
329
|
-
},
|
|
330
|
-
],
|
|
331
|
-
initial: 'Yes',
|
|
332
|
-
},
|
|
333
|
-
]);
|
|
334
|
-
js = reply.ts === 'No';
|
|
335
|
-
}
|
|
336
|
-
return { preset, js, appName };
|
|
337
|
-
});
|
|
338
|
-
}
|
|
339
|
-
function determineReactOptions(parsedArgs) {
|
|
340
|
-
var _a;
|
|
341
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
342
|
-
let preset;
|
|
343
|
-
let style = undefined;
|
|
344
|
-
let appName;
|
|
345
|
-
let bundler = undefined;
|
|
346
|
-
let e2eTestRunner = undefined;
|
|
347
|
-
let nextAppDir = false;
|
|
348
|
-
if (parsedArgs.preset && parsedArgs.preset !== preset_1.Preset.React) {
|
|
349
|
-
preset = parsedArgs.preset;
|
|
350
|
-
if (preset === preset_1.Preset.ReactStandalone ||
|
|
351
|
-
preset === preset_1.Preset.NextJsStandalone) {
|
|
352
|
-
appName = (_a = parsedArgs.appName) !== null && _a !== void 0 ? _a : parsedArgs.name;
|
|
353
|
-
}
|
|
354
|
-
else {
|
|
355
|
-
appName = yield determineAppName(parsedArgs);
|
|
356
|
-
}
|
|
357
371
|
}
|
|
358
372
|
else {
|
|
359
|
-
|
|
360
|
-
// React Native and Expo only support integrated monorepos for now.
|
|
361
|
-
// TODO(jack): Add standalone support for React Native and Expo.
|
|
362
|
-
const workspaceType = framework === 'react-native' || framework === 'expo'
|
|
363
|
-
? 'integrated'
|
|
364
|
-
: yield determineStandaloneOrMonorepo();
|
|
365
|
-
if (workspaceType === 'standalone') {
|
|
366
|
-
appName = parsedArgs.name;
|
|
367
|
-
}
|
|
368
|
-
else {
|
|
369
|
-
appName = yield determineAppName(parsedArgs);
|
|
370
|
-
}
|
|
371
|
-
if (framework === 'nextjs') {
|
|
372
|
-
if (workspaceType === 'standalone') {
|
|
373
|
-
preset = preset_1.Preset.NextJsStandalone;
|
|
374
|
-
}
|
|
375
|
-
else {
|
|
376
|
-
preset = preset_1.Preset.NextJs;
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
else if (framework === 'react-native') {
|
|
380
|
-
preset = preset_1.Preset.ReactNative;
|
|
381
|
-
}
|
|
382
|
-
else if (framework === 'expo') {
|
|
383
|
-
preset = preset_1.Preset.Expo;
|
|
384
|
-
}
|
|
385
|
-
else {
|
|
386
|
-
if (workspaceType === 'standalone') {
|
|
387
|
-
preset = preset_1.Preset.ReactStandalone;
|
|
388
|
-
}
|
|
389
|
-
else {
|
|
390
|
-
preset = preset_1.Preset.ReactMonorepo;
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
if (preset === preset_1.Preset.ReactStandalone || preset === preset_1.Preset.ReactMonorepo) {
|
|
395
|
-
bundler = yield determineReactBundler(parsedArgs);
|
|
396
|
-
e2eTestRunner = yield determineE2eTestRunner(parsedArgs);
|
|
397
|
-
}
|
|
398
|
-
else if (preset === preset_1.Preset.NextJs || preset === preset_1.Preset.NextJsStandalone) {
|
|
399
|
-
nextAppDir = yield determineNextAppDir(parsedArgs);
|
|
400
|
-
e2eTestRunner = yield determineE2eTestRunner(parsedArgs);
|
|
401
|
-
}
|
|
402
|
-
if (parsedArgs.style) {
|
|
403
|
-
style = parsedArgs.style;
|
|
404
|
-
}
|
|
405
|
-
else if (preset === preset_1.Preset.ReactStandalone ||
|
|
406
|
-
preset === preset_1.Preset.ReactMonorepo ||
|
|
407
|
-
preset === preset_1.Preset.NextJs ||
|
|
408
|
-
preset === preset_1.Preset.NextJsStandalone) {
|
|
409
|
-
const reply = yield enquirer.prompt([
|
|
410
|
-
{
|
|
411
|
-
name: 'style',
|
|
412
|
-
message: `Default stylesheet format`,
|
|
413
|
-
initial: 'css',
|
|
414
|
-
type: 'autocomplete',
|
|
415
|
-
choices: [
|
|
416
|
-
{
|
|
417
|
-
name: 'css',
|
|
418
|
-
message: 'CSS',
|
|
419
|
-
},
|
|
420
|
-
{
|
|
421
|
-
name: 'scss',
|
|
422
|
-
message: 'SASS(.scss) [ http://sass-lang.com ]',
|
|
423
|
-
},
|
|
424
|
-
{
|
|
425
|
-
name: 'less',
|
|
426
|
-
message: 'LESS [ http://lesscss.org ]',
|
|
427
|
-
},
|
|
428
|
-
{
|
|
429
|
-
name: 'styled-components',
|
|
430
|
-
message: 'styled-components [ https://styled-components.com ]',
|
|
431
|
-
},
|
|
432
|
-
{
|
|
433
|
-
name: '@emotion/styled',
|
|
434
|
-
message: 'emotion [ https://emotion.sh ]',
|
|
435
|
-
},
|
|
436
|
-
{
|
|
437
|
-
name: 'styled-jsx',
|
|
438
|
-
message: 'styled-jsx [ https://www.npmjs.com/package/styled-jsx ]',
|
|
439
|
-
},
|
|
440
|
-
],
|
|
441
|
-
},
|
|
442
|
-
]);
|
|
443
|
-
style = reply.style;
|
|
373
|
+
appName = await determineAppName(parsedArgs);
|
|
444
374
|
}
|
|
445
|
-
|
|
446
|
-
});
|
|
447
|
-
}
|
|
448
|
-
function determineAngularOptions(parsedArgs) {
|
|
449
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
450
|
-
let preset;
|
|
451
|
-
let style;
|
|
452
|
-
let appName;
|
|
453
|
-
let standaloneApi;
|
|
454
|
-
let e2eTestRunner = undefined;
|
|
455
|
-
let routing;
|
|
456
|
-
if (parsedArgs.preset && parsedArgs.preset !== preset_1.Preset.Angular) {
|
|
457
|
-
preset = parsedArgs.preset;
|
|
458
|
-
if (preset === preset_1.Preset.AngularStandalone) {
|
|
459
|
-
appName = parsedArgs.name;
|
|
460
|
-
}
|
|
461
|
-
else {
|
|
462
|
-
appName = yield determineAppName(parsedArgs);
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
else {
|
|
466
|
-
const workspaceType = yield determineStandaloneOrMonorepo();
|
|
375
|
+
if (framework === 'nextjs') {
|
|
467
376
|
if (workspaceType === 'standalone') {
|
|
468
|
-
preset = preset_1.Preset.
|
|
469
|
-
appName = parsedArgs.name;
|
|
377
|
+
preset = preset_1.Preset.NextJsStandalone;
|
|
470
378
|
}
|
|
471
379
|
else {
|
|
472
|
-
preset = preset_1.Preset.
|
|
473
|
-
appName = yield determineAppName(parsedArgs);
|
|
380
|
+
preset = preset_1.Preset.NextJs;
|
|
474
381
|
}
|
|
475
382
|
}
|
|
476
|
-
if (
|
|
477
|
-
|
|
383
|
+
else if (framework === 'react-native') {
|
|
384
|
+
preset = preset_1.Preset.ReactNative;
|
|
478
385
|
}
|
|
479
|
-
else {
|
|
480
|
-
|
|
481
|
-
{
|
|
482
|
-
name: 'style',
|
|
483
|
-
message: `Default stylesheet format`,
|
|
484
|
-
initial: 'css',
|
|
485
|
-
type: 'autocomplete',
|
|
486
|
-
choices: [
|
|
487
|
-
{
|
|
488
|
-
name: 'css',
|
|
489
|
-
message: 'CSS',
|
|
490
|
-
},
|
|
491
|
-
{
|
|
492
|
-
name: 'scss',
|
|
493
|
-
message: 'SASS(.scss) [ http://sass-lang.com ]',
|
|
494
|
-
},
|
|
495
|
-
{
|
|
496
|
-
name: 'less',
|
|
497
|
-
message: 'LESS [ http://lesscss.org ]',
|
|
498
|
-
},
|
|
499
|
-
],
|
|
500
|
-
},
|
|
501
|
-
]);
|
|
502
|
-
style = reply.style;
|
|
503
|
-
}
|
|
504
|
-
e2eTestRunner = yield determineE2eTestRunner(parsedArgs);
|
|
505
|
-
if (parsedArgs.standaloneApi !== undefined) {
|
|
506
|
-
standaloneApi = parsedArgs.standaloneApi;
|
|
386
|
+
else if (framework === 'expo') {
|
|
387
|
+
preset = preset_1.Preset.Expo;
|
|
507
388
|
}
|
|
508
389
|
else {
|
|
509
|
-
const reply = yield enquirer.prompt([
|
|
510
|
-
{
|
|
511
|
-
name: 'standaloneApi',
|
|
512
|
-
message: 'Would you like to use Standalone Components in your application?',
|
|
513
|
-
type: 'autocomplete',
|
|
514
|
-
choices: [
|
|
515
|
-
{
|
|
516
|
-
name: 'No',
|
|
517
|
-
},
|
|
518
|
-
{
|
|
519
|
-
name: 'Yes',
|
|
520
|
-
},
|
|
521
|
-
],
|
|
522
|
-
initial: 'No',
|
|
523
|
-
},
|
|
524
|
-
]);
|
|
525
|
-
standaloneApi = reply.standaloneApi === 'Yes';
|
|
526
|
-
}
|
|
527
|
-
if (parsedArgs.routing !== undefined) {
|
|
528
|
-
routing = parsedArgs.routing;
|
|
529
|
-
}
|
|
530
|
-
else {
|
|
531
|
-
const reply = yield enquirer.prompt([
|
|
532
|
-
{
|
|
533
|
-
name: 'routing',
|
|
534
|
-
message: 'Would you like to add routing?',
|
|
535
|
-
type: 'autocomplete',
|
|
536
|
-
choices: [
|
|
537
|
-
{
|
|
538
|
-
name: 'Yes',
|
|
539
|
-
},
|
|
540
|
-
{
|
|
541
|
-
name: 'No',
|
|
542
|
-
},
|
|
543
|
-
],
|
|
544
|
-
initial: 'Yes',
|
|
545
|
-
},
|
|
546
|
-
]);
|
|
547
|
-
routing = reply.routing === 'Yes';
|
|
548
|
-
}
|
|
549
|
-
return { preset, style, appName, standaloneApi, routing, e2eTestRunner };
|
|
550
|
-
});
|
|
551
|
-
}
|
|
552
|
-
function determineNodeOptions(parsedArgs) {
|
|
553
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
554
|
-
let preset;
|
|
555
|
-
let appName;
|
|
556
|
-
let framework;
|
|
557
|
-
let docker;
|
|
558
|
-
if (parsedArgs.preset) {
|
|
559
|
-
preset = parsedArgs.preset;
|
|
560
|
-
if (preset === preset_1.Preset.Nest ||
|
|
561
|
-
preset === preset_1.Preset.Express ||
|
|
562
|
-
preset === preset_1.Preset.NodeMonorepo) {
|
|
563
|
-
appName = yield determineAppName(parsedArgs);
|
|
564
|
-
}
|
|
565
|
-
else {
|
|
566
|
-
appName = parsedArgs.name;
|
|
567
|
-
}
|
|
568
|
-
if (preset === preset_1.Preset.NodeStandalone || preset === preset_1.Preset.NodeMonorepo) {
|
|
569
|
-
framework = yield determineNodeFramework(parsedArgs);
|
|
570
|
-
}
|
|
571
|
-
else {
|
|
572
|
-
framework = 'none';
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
else {
|
|
576
|
-
framework = yield determineNodeFramework(parsedArgs);
|
|
577
|
-
const workspaceType = yield determineStandaloneOrMonorepo();
|
|
578
390
|
if (workspaceType === 'standalone') {
|
|
579
|
-
preset = preset_1.Preset.
|
|
580
|
-
appName = parsedArgs.name;
|
|
391
|
+
preset = preset_1.Preset.ReactStandalone;
|
|
581
392
|
}
|
|
582
393
|
else {
|
|
583
|
-
preset = preset_1.Preset.
|
|
584
|
-
appName = yield determineAppName(parsedArgs);
|
|
394
|
+
preset = preset_1.Preset.ReactMonorepo;
|
|
585
395
|
}
|
|
586
396
|
}
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
],
|
|
605
|
-
initial: 'No',
|
|
606
|
-
},
|
|
607
|
-
]);
|
|
608
|
-
docker = reply.docker === 'Yes';
|
|
609
|
-
}
|
|
610
|
-
return {
|
|
611
|
-
preset,
|
|
612
|
-
appName,
|
|
613
|
-
framework,
|
|
614
|
-
docker,
|
|
615
|
-
};
|
|
616
|
-
});
|
|
617
|
-
}
|
|
618
|
-
function determinePackageBasedOrIntegratedOrStandalone() {
|
|
619
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
620
|
-
const { workspaceType } = yield enquirer.prompt([
|
|
397
|
+
}
|
|
398
|
+
if (preset === preset_1.Preset.ReactStandalone || preset === preset_1.Preset.ReactMonorepo) {
|
|
399
|
+
bundler = await determineReactBundler(parsedArgs);
|
|
400
|
+
e2eTestRunner = await determineE2eTestRunner(parsedArgs);
|
|
401
|
+
}
|
|
402
|
+
else if (preset === preset_1.Preset.NextJs || preset === preset_1.Preset.NextJsStandalone) {
|
|
403
|
+
nextAppDir = await determineNextAppDir(parsedArgs);
|
|
404
|
+
e2eTestRunner = await determineE2eTestRunner(parsedArgs);
|
|
405
|
+
}
|
|
406
|
+
if (parsedArgs.style) {
|
|
407
|
+
style = parsedArgs.style;
|
|
408
|
+
}
|
|
409
|
+
else if (preset === preset_1.Preset.ReactStandalone ||
|
|
410
|
+
preset === preset_1.Preset.ReactMonorepo ||
|
|
411
|
+
preset === preset_1.Preset.NextJs ||
|
|
412
|
+
preset === preset_1.Preset.NextJsStandalone) {
|
|
413
|
+
const reply = await enquirer.prompt([
|
|
621
414
|
{
|
|
415
|
+
name: 'style',
|
|
416
|
+
message: `Default stylesheet format`,
|
|
417
|
+
initial: 'css',
|
|
622
418
|
type: 'autocomplete',
|
|
623
|
-
name: 'workspaceType',
|
|
624
|
-
message: `Package-based monorepo, integrated monorepo, or standalone project?`,
|
|
625
|
-
initial: 'package-based',
|
|
626
419
|
choices: [
|
|
627
420
|
{
|
|
628
|
-
name: '
|
|
629
|
-
message: '
|
|
421
|
+
name: 'css',
|
|
422
|
+
message: 'CSS',
|
|
630
423
|
},
|
|
631
424
|
{
|
|
632
|
-
name: '
|
|
633
|
-
message: '
|
|
425
|
+
name: 'scss',
|
|
426
|
+
message: 'SASS(.scss) [ http://sass-lang.com ]',
|
|
634
427
|
},
|
|
635
428
|
{
|
|
636
|
-
name: '
|
|
637
|
-
message: '
|
|
429
|
+
name: 'less',
|
|
430
|
+
message: 'LESS [ http://lesscss.org ]',
|
|
638
431
|
},
|
|
639
|
-
],
|
|
640
|
-
},
|
|
641
|
-
]);
|
|
642
|
-
invariant(workspaceType, {
|
|
643
|
-
title: 'Invalid workspace type',
|
|
644
|
-
bodyLines: [
|
|
645
|
-
`It must be one of the following: standalone, integrated. Got ${workspaceType}`,
|
|
646
|
-
],
|
|
647
|
-
});
|
|
648
|
-
return workspaceType;
|
|
649
|
-
});
|
|
650
|
-
}
|
|
651
|
-
function determineStandaloneOrMonorepo() {
|
|
652
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
653
|
-
const { workspaceType } = yield enquirer.prompt([
|
|
654
|
-
{
|
|
655
|
-
type: 'autocomplete',
|
|
656
|
-
name: 'workspaceType',
|
|
657
|
-
message: `Integrated monorepo, or standalone project?`,
|
|
658
|
-
initial: 'standalone',
|
|
659
|
-
choices: [
|
|
660
432
|
{
|
|
661
|
-
name: '
|
|
662
|
-
message: '
|
|
433
|
+
name: 'styled-components',
|
|
434
|
+
message: 'styled-components [ https://styled-components.com ]',
|
|
663
435
|
},
|
|
664
436
|
{
|
|
665
|
-
name: '
|
|
666
|
-
message: '
|
|
437
|
+
name: '@emotion/styled',
|
|
438
|
+
message: 'emotion [ https://emotion.sh ]',
|
|
439
|
+
},
|
|
440
|
+
{
|
|
441
|
+
name: 'styled-jsx',
|
|
442
|
+
message: 'styled-jsx [ https://www.npmjs.com/package/styled-jsx ]',
|
|
667
443
|
},
|
|
668
444
|
],
|
|
669
445
|
},
|
|
670
446
|
]);
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
`It must be one of the following: standalone, integrated. Got ${workspaceType}`,
|
|
675
|
-
],
|
|
676
|
-
});
|
|
677
|
-
return workspaceType;
|
|
678
|
-
});
|
|
679
|
-
}
|
|
680
|
-
function determineAppName(parsedArgs) {
|
|
681
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
682
|
-
if (parsedArgs.appName)
|
|
683
|
-
return parsedArgs.appName;
|
|
684
|
-
const { appName } = yield enquirer.prompt([
|
|
685
|
-
{
|
|
686
|
-
name: 'appName',
|
|
687
|
-
message: `Application name`,
|
|
688
|
-
type: 'input',
|
|
689
|
-
initial: parsedArgs.name,
|
|
690
|
-
},
|
|
691
|
-
]);
|
|
692
|
-
invariant(appName, {
|
|
693
|
-
title: 'Invalid name',
|
|
694
|
-
bodyLines: [`Name cannot be empty`],
|
|
695
|
-
});
|
|
696
|
-
return appName;
|
|
697
|
-
});
|
|
447
|
+
style = reply.style;
|
|
448
|
+
}
|
|
449
|
+
return { preset, style, appName, bundler, nextAppDir, e2eTestRunner };
|
|
698
450
|
}
|
|
699
|
-
function
|
|
700
|
-
|
|
701
|
-
|
|
451
|
+
async function determineAngularOptions(parsedArgs) {
|
|
452
|
+
let preset;
|
|
453
|
+
let style;
|
|
454
|
+
let appName;
|
|
455
|
+
let standaloneApi;
|
|
456
|
+
let e2eTestRunner = undefined;
|
|
457
|
+
let routing;
|
|
458
|
+
if (parsedArgs.preset && parsedArgs.preset !== preset_1.Preset.Angular) {
|
|
459
|
+
preset = parsedArgs.preset;
|
|
460
|
+
if (preset === preset_1.Preset.AngularStandalone) {
|
|
461
|
+
appName = parsedArgs.name;
|
|
462
|
+
}
|
|
463
|
+
else {
|
|
464
|
+
appName = await determineAppName(parsedArgs);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
else {
|
|
468
|
+
const workspaceType = await determineStandaloneOrMonorepo();
|
|
469
|
+
if (workspaceType === 'standalone') {
|
|
470
|
+
preset = preset_1.Preset.AngularStandalone;
|
|
471
|
+
appName = parsedArgs.name;
|
|
472
|
+
}
|
|
473
|
+
else {
|
|
474
|
+
preset = preset_1.Preset.AngularMonorepo;
|
|
475
|
+
appName = await determineAppName(parsedArgs);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
if (parsedArgs.style) {
|
|
479
|
+
style = parsedArgs.style;
|
|
480
|
+
}
|
|
481
|
+
else {
|
|
482
|
+
const reply = await enquirer.prompt([
|
|
702
483
|
{
|
|
703
|
-
name: '
|
|
704
|
-
message:
|
|
484
|
+
name: 'style',
|
|
485
|
+
message: `Default stylesheet format`,
|
|
486
|
+
initial: 'css',
|
|
705
487
|
type: 'autocomplete',
|
|
706
488
|
choices: [
|
|
707
489
|
{
|
|
708
|
-
name: '
|
|
709
|
-
message: '
|
|
710
|
-
hint: ' I only want react and react-dom',
|
|
490
|
+
name: 'css',
|
|
491
|
+
message: 'CSS',
|
|
711
492
|
},
|
|
712
493
|
{
|
|
713
|
-
name: '
|
|
714
|
-
message: '
|
|
494
|
+
name: 'scss',
|
|
495
|
+
message: 'SASS(.scss) [ http://sass-lang.com ]',
|
|
715
496
|
},
|
|
716
497
|
{
|
|
717
|
-
name: '
|
|
718
|
-
message: '
|
|
719
|
-
},
|
|
720
|
-
{
|
|
721
|
-
name: 'react-native',
|
|
722
|
-
message: 'React Native [ https://reactnative.dev/ ]',
|
|
498
|
+
name: 'less',
|
|
499
|
+
message: 'LESS [ http://lesscss.org ]',
|
|
723
500
|
},
|
|
724
501
|
],
|
|
725
|
-
initial: 'none',
|
|
726
502
|
},
|
|
727
503
|
]);
|
|
728
|
-
|
|
729
|
-
}
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
const reply =
|
|
504
|
+
style = reply.style;
|
|
505
|
+
}
|
|
506
|
+
e2eTestRunner = await determineE2eTestRunner(parsedArgs);
|
|
507
|
+
if (parsedArgs.standaloneApi !== undefined) {
|
|
508
|
+
standaloneApi = parsedArgs.standaloneApi;
|
|
509
|
+
}
|
|
510
|
+
else {
|
|
511
|
+
const reply = await enquirer.prompt([
|
|
736
512
|
{
|
|
737
|
-
name: '
|
|
738
|
-
message:
|
|
513
|
+
name: 'standaloneApi',
|
|
514
|
+
message: 'Would you like to use Standalone Components in your application?',
|
|
739
515
|
type: 'autocomplete',
|
|
740
516
|
choices: [
|
|
741
517
|
{
|
|
742
|
-
name: '
|
|
743
|
-
message: 'Vite [ https://vitejs.dev/ ]',
|
|
744
|
-
},
|
|
745
|
-
{
|
|
746
|
-
name: 'webpack',
|
|
747
|
-
message: 'Webpack [ https://webpack.js.org/ ]',
|
|
518
|
+
name: 'No',
|
|
748
519
|
},
|
|
749
520
|
{
|
|
750
|
-
name: '
|
|
751
|
-
message: 'Rspack [ https://www.rspack.dev/ ]',
|
|
521
|
+
name: 'Yes',
|
|
752
522
|
},
|
|
753
523
|
],
|
|
524
|
+
initial: 'No',
|
|
754
525
|
},
|
|
755
526
|
]);
|
|
756
|
-
|
|
757
|
-
}
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
const reply = yield enquirer.prompt([
|
|
527
|
+
standaloneApi = reply.standaloneApi === 'Yes';
|
|
528
|
+
}
|
|
529
|
+
if (parsedArgs.routing !== undefined) {
|
|
530
|
+
routing = parsedArgs.routing;
|
|
531
|
+
}
|
|
532
|
+
else {
|
|
533
|
+
const reply = await enquirer.prompt([
|
|
764
534
|
{
|
|
765
|
-
name: '
|
|
766
|
-
message: 'Would you like to
|
|
535
|
+
name: 'routing',
|
|
536
|
+
message: 'Would you like to add routing?',
|
|
767
537
|
type: 'autocomplete',
|
|
768
538
|
choices: [
|
|
769
539
|
{
|
|
@@ -776,70 +546,283 @@ function determineNextAppDir(parsedArgs) {
|
|
|
776
546
|
initial: 'Yes',
|
|
777
547
|
},
|
|
778
548
|
]);
|
|
779
|
-
|
|
780
|
-
}
|
|
549
|
+
routing = reply.routing === 'Yes';
|
|
550
|
+
}
|
|
551
|
+
return { preset, style, appName, standaloneApi, routing, e2eTestRunner };
|
|
781
552
|
}
|
|
782
|
-
function
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
553
|
+
async function determineNodeOptions(parsedArgs) {
|
|
554
|
+
let preset;
|
|
555
|
+
let appName;
|
|
556
|
+
let framework;
|
|
557
|
+
let docker;
|
|
558
|
+
if (parsedArgs.preset) {
|
|
559
|
+
preset = parsedArgs.preset;
|
|
560
|
+
if (preset === preset_1.Preset.Nest ||
|
|
561
|
+
preset === preset_1.Preset.Express ||
|
|
562
|
+
preset === preset_1.Preset.NodeMonorepo) {
|
|
563
|
+
appName = await determineAppName(parsedArgs);
|
|
564
|
+
}
|
|
565
|
+
else {
|
|
566
|
+
appName = parsedArgs.name;
|
|
567
|
+
}
|
|
568
|
+
if (preset === preset_1.Preset.NodeStandalone || preset === preset_1.Preset.NodeMonorepo) {
|
|
569
|
+
framework = await determineNodeFramework(parsedArgs);
|
|
570
|
+
}
|
|
571
|
+
else {
|
|
572
|
+
framework = 'none';
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
else {
|
|
576
|
+
framework = await determineNodeFramework(parsedArgs);
|
|
577
|
+
const workspaceType = await determineStandaloneOrMonorepo();
|
|
578
|
+
if (workspaceType === 'standalone') {
|
|
579
|
+
preset = preset_1.Preset.NodeStandalone;
|
|
580
|
+
appName = parsedArgs.name;
|
|
581
|
+
}
|
|
582
|
+
else {
|
|
583
|
+
preset = preset_1.Preset.NodeMonorepo;
|
|
584
|
+
appName = await determineAppName(parsedArgs);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
if (parsedArgs.docker !== undefined) {
|
|
588
|
+
docker = parsedArgs.docker;
|
|
589
|
+
}
|
|
590
|
+
else {
|
|
591
|
+
const reply = await enquirer.prompt([
|
|
787
592
|
{
|
|
788
|
-
|
|
593
|
+
name: 'docker',
|
|
594
|
+
message: 'Would you like to generate a Dockerfile? [https://docs.docker.com/]',
|
|
789
595
|
type: 'autocomplete',
|
|
790
|
-
name: 'framework',
|
|
791
596
|
choices: [
|
|
792
597
|
{
|
|
793
|
-
name: '
|
|
794
|
-
|
|
795
|
-
},
|
|
796
|
-
{
|
|
797
|
-
name: 'express',
|
|
798
|
-
message: 'Express [ https://expressjs.com/ ]',
|
|
799
|
-
},
|
|
800
|
-
{
|
|
801
|
-
name: 'fastify',
|
|
802
|
-
message: 'Fastify [ https://www.fastify.dev/ ]',
|
|
803
|
-
},
|
|
804
|
-
{
|
|
805
|
-
name: 'koa',
|
|
806
|
-
message: 'Koa [ https://koajs.com/ ]',
|
|
598
|
+
name: 'Yes',
|
|
599
|
+
hint: 'I want to generate a Dockerfile',
|
|
807
600
|
},
|
|
808
601
|
{
|
|
809
|
-
name: '
|
|
810
|
-
message: 'NestJs [ https://nestjs.com/ ]',
|
|
602
|
+
name: 'No',
|
|
811
603
|
},
|
|
812
604
|
],
|
|
605
|
+
initial: 'No',
|
|
813
606
|
},
|
|
814
607
|
]);
|
|
815
|
-
|
|
608
|
+
docker = reply.docker === 'Yes';
|
|
609
|
+
}
|
|
610
|
+
return {
|
|
611
|
+
preset,
|
|
612
|
+
appName,
|
|
613
|
+
framework,
|
|
614
|
+
docker,
|
|
615
|
+
};
|
|
616
|
+
}
|
|
617
|
+
async function determinePackageBasedOrIntegratedOrStandalone() {
|
|
618
|
+
const { workspaceType } = await enquirer.prompt([
|
|
619
|
+
{
|
|
620
|
+
type: 'autocomplete',
|
|
621
|
+
name: 'workspaceType',
|
|
622
|
+
message: `Package-based monorepo, integrated monorepo, or standalone project?`,
|
|
623
|
+
initial: 'package-based',
|
|
624
|
+
choices: [
|
|
625
|
+
{
|
|
626
|
+
name: 'package-based',
|
|
627
|
+
message: 'Package-based Monorepo: Nx makes it fast, but lets you run things your way.',
|
|
628
|
+
},
|
|
629
|
+
{
|
|
630
|
+
name: 'integrated',
|
|
631
|
+
message: 'Integrated Monorepo: Nx creates a monorepo that contains multiple projects.',
|
|
632
|
+
},
|
|
633
|
+
{
|
|
634
|
+
name: 'standalone',
|
|
635
|
+
message: 'Standalone: Nx creates a single project and makes it fast.',
|
|
636
|
+
},
|
|
637
|
+
],
|
|
638
|
+
},
|
|
639
|
+
]);
|
|
640
|
+
invariant(workspaceType, {
|
|
641
|
+
title: 'Invalid workspace type',
|
|
642
|
+
bodyLines: [
|
|
643
|
+
`It must be one of the following: standalone, integrated. Got ${workspaceType}`,
|
|
644
|
+
],
|
|
816
645
|
});
|
|
646
|
+
return workspaceType;
|
|
817
647
|
}
|
|
818
|
-
function
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
648
|
+
async function determineStandaloneOrMonorepo() {
|
|
649
|
+
const { workspaceType } = await enquirer.prompt([
|
|
650
|
+
{
|
|
651
|
+
type: 'autocomplete',
|
|
652
|
+
name: 'workspaceType',
|
|
653
|
+
message: `Integrated monorepo, or standalone project?`,
|
|
654
|
+
initial: 'standalone',
|
|
655
|
+
choices: [
|
|
656
|
+
{
|
|
657
|
+
name: 'integrated',
|
|
658
|
+
message: 'Integrated Monorepo: Nx creates a monorepo that contains multiple projects.',
|
|
659
|
+
},
|
|
660
|
+
{
|
|
661
|
+
name: 'standalone',
|
|
662
|
+
message: 'Standalone: Nx creates a single project and makes it fast.',
|
|
663
|
+
},
|
|
664
|
+
],
|
|
665
|
+
},
|
|
666
|
+
]);
|
|
667
|
+
invariant(workspaceType, {
|
|
668
|
+
title: 'Invalid workspace type',
|
|
669
|
+
bodyLines: [
|
|
670
|
+
`It must be one of the following: standalone, integrated. Got ${workspaceType}`,
|
|
671
|
+
],
|
|
672
|
+
});
|
|
673
|
+
return workspaceType;
|
|
674
|
+
}
|
|
675
|
+
async function determineAppName(parsedArgs) {
|
|
676
|
+
if (parsedArgs.appName)
|
|
677
|
+
return parsedArgs.appName;
|
|
678
|
+
const { appName } = await enquirer.prompt([
|
|
679
|
+
{
|
|
680
|
+
name: 'appName',
|
|
681
|
+
message: `Application name`,
|
|
682
|
+
type: 'input',
|
|
683
|
+
initial: parsedArgs.name,
|
|
684
|
+
},
|
|
685
|
+
]);
|
|
686
|
+
invariant(appName, {
|
|
687
|
+
title: 'Invalid name',
|
|
688
|
+
bodyLines: [`Name cannot be empty`],
|
|
844
689
|
});
|
|
690
|
+
return appName;
|
|
691
|
+
}
|
|
692
|
+
async function determineReactFramework(parsedArgs) {
|
|
693
|
+
const reply = await enquirer.prompt([
|
|
694
|
+
{
|
|
695
|
+
name: 'framework',
|
|
696
|
+
message: 'What framework would you like to use?',
|
|
697
|
+
type: 'autocomplete',
|
|
698
|
+
choices: [
|
|
699
|
+
{
|
|
700
|
+
name: 'none',
|
|
701
|
+
message: 'None',
|
|
702
|
+
hint: ' I only want react and react-dom',
|
|
703
|
+
},
|
|
704
|
+
{
|
|
705
|
+
name: 'nextjs',
|
|
706
|
+
message: 'Next.js [ https://nextjs.org/ ]',
|
|
707
|
+
},
|
|
708
|
+
{
|
|
709
|
+
name: 'expo',
|
|
710
|
+
message: 'Expo [ https://expo.io/ ]',
|
|
711
|
+
},
|
|
712
|
+
{
|
|
713
|
+
name: 'react-native',
|
|
714
|
+
message: 'React Native [ https://reactnative.dev/ ]',
|
|
715
|
+
},
|
|
716
|
+
],
|
|
717
|
+
initial: 'none',
|
|
718
|
+
},
|
|
719
|
+
]);
|
|
720
|
+
return reply.framework;
|
|
721
|
+
}
|
|
722
|
+
async function determineReactBundler(parsedArgs) {
|
|
723
|
+
if (parsedArgs.bundler)
|
|
724
|
+
return parsedArgs.bundler;
|
|
725
|
+
const reply = await enquirer.prompt([
|
|
726
|
+
{
|
|
727
|
+
name: 'bundler',
|
|
728
|
+
message: `Which bundler would you like to use?`,
|
|
729
|
+
type: 'autocomplete',
|
|
730
|
+
choices: [
|
|
731
|
+
{
|
|
732
|
+
name: 'vite',
|
|
733
|
+
message: 'Vite [ https://vitejs.dev/ ]',
|
|
734
|
+
},
|
|
735
|
+
{
|
|
736
|
+
name: 'webpack',
|
|
737
|
+
message: 'Webpack [ https://webpack.js.org/ ]',
|
|
738
|
+
},
|
|
739
|
+
{
|
|
740
|
+
name: 'rspack',
|
|
741
|
+
message: 'Rspack [ https://www.rspack.dev/ ]',
|
|
742
|
+
},
|
|
743
|
+
],
|
|
744
|
+
},
|
|
745
|
+
]);
|
|
746
|
+
return reply.bundler;
|
|
747
|
+
}
|
|
748
|
+
async function determineNextAppDir(parsedArgs) {
|
|
749
|
+
if (parsedArgs.nextAppDir !== undefined)
|
|
750
|
+
return parsedArgs.nextAppDir;
|
|
751
|
+
const reply = await enquirer.prompt([
|
|
752
|
+
{
|
|
753
|
+
name: 'nextAppDir',
|
|
754
|
+
message: 'Would you like to use the App Router (recommended)?',
|
|
755
|
+
type: 'autocomplete',
|
|
756
|
+
choices: [
|
|
757
|
+
{
|
|
758
|
+
name: 'Yes',
|
|
759
|
+
},
|
|
760
|
+
{
|
|
761
|
+
name: 'No',
|
|
762
|
+
},
|
|
763
|
+
],
|
|
764
|
+
initial: 'Yes',
|
|
765
|
+
},
|
|
766
|
+
]);
|
|
767
|
+
return reply.nextAppDir === 'Yes';
|
|
768
|
+
}
|
|
769
|
+
async function determineNodeFramework(parsedArgs) {
|
|
770
|
+
if (parsedArgs.framework)
|
|
771
|
+
return parsedArgs.framework;
|
|
772
|
+
const reply = await enquirer.prompt([
|
|
773
|
+
{
|
|
774
|
+
message: 'What framework should be used?',
|
|
775
|
+
type: 'autocomplete',
|
|
776
|
+
name: 'framework',
|
|
777
|
+
choices: [
|
|
778
|
+
{
|
|
779
|
+
name: 'none',
|
|
780
|
+
message: 'None',
|
|
781
|
+
},
|
|
782
|
+
{
|
|
783
|
+
name: 'express',
|
|
784
|
+
message: 'Express [ https://expressjs.com/ ]',
|
|
785
|
+
},
|
|
786
|
+
{
|
|
787
|
+
name: 'fastify',
|
|
788
|
+
message: 'Fastify [ https://www.fastify.dev/ ]',
|
|
789
|
+
},
|
|
790
|
+
{
|
|
791
|
+
name: 'koa',
|
|
792
|
+
message: 'Koa [ https://koajs.com/ ]',
|
|
793
|
+
},
|
|
794
|
+
{
|
|
795
|
+
name: 'nest',
|
|
796
|
+
message: 'NestJs [ https://nestjs.com/ ]',
|
|
797
|
+
},
|
|
798
|
+
],
|
|
799
|
+
},
|
|
800
|
+
]);
|
|
801
|
+
return reply.framework;
|
|
802
|
+
}
|
|
803
|
+
async function determineE2eTestRunner(parsedArgs) {
|
|
804
|
+
if (parsedArgs.e2eTestRunner)
|
|
805
|
+
return parsedArgs.e2eTestRunner;
|
|
806
|
+
const reply = await enquirer.prompt([
|
|
807
|
+
{
|
|
808
|
+
message: 'Test runner to use for end to end (E2E) tests',
|
|
809
|
+
type: 'autocomplete',
|
|
810
|
+
name: 'e2eTestRunner',
|
|
811
|
+
choices: [
|
|
812
|
+
{
|
|
813
|
+
name: 'cypress',
|
|
814
|
+
message: 'Cypress [ https://www.cypress.io/ ]',
|
|
815
|
+
},
|
|
816
|
+
{
|
|
817
|
+
name: 'playwright',
|
|
818
|
+
message: 'Playwright [ https://playwright.dev/ ]',
|
|
819
|
+
},
|
|
820
|
+
{
|
|
821
|
+
name: 'none',
|
|
822
|
+
message: 'None',
|
|
823
|
+
},
|
|
824
|
+
],
|
|
825
|
+
},
|
|
826
|
+
]);
|
|
827
|
+
return reply.e2eTestRunner;
|
|
845
828
|
}
|