@quilted/create 0.1.36 → 0.1.38
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/CHANGELOG.md +12 -0
- package/build/cjs/app.cjs +17 -21
- package/build/cjs/index4.cjs +7635 -0
- package/build/cjs/package.cjs +162 -65
- package/build/cjs/shared/package-manager.cjs +57 -7
- package/build/esm/app.mjs +18 -22
- package/build/esm/index4.mjs +7626 -0
- package/build/esm/package.mjs +164 -67
- package/build/esm/shared/package-manager.mjs +57 -8
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/typescript/app.d.ts.map +1 -1
- package/build/typescript/package.d.ts.map +1 -1
- package/build/typescript/shared/prompts.d.ts +9 -2
- package/build/typescript/shared/prompts.d.ts.map +1 -1
- package/build/typescript/shared.d.ts +1 -0
- package/build/typescript/shared.d.ts.map +1 -1
- package/package.json +2 -1
- package/source/app.ts +20 -28
- package/source/package.ts +239 -101
- package/source/shared/prompts.ts +21 -6
- package/source/shared.ts +68 -7
- package/templates/package/README.md +1 -1
- package/templates/package/quilt.project.ts +1 -1
- package/templates/workspace/_nvmrc +1 -1
- package/templates/workspace/package.json +4 -0
package/build/cjs/package.cjs
CHANGED
|
@@ -34,6 +34,11 @@ async function createProject() {
|
|
|
34
34
|
const args = getArguments();
|
|
35
35
|
if (args['--help']) {
|
|
36
36
|
const additionalOptions = index.stripIndent`
|
|
37
|
+
${index.cyan_1(`--description`)}, ${index.cyan_1(`--no-description`)}
|
|
38
|
+
A short description of the package. If you don’t provide this option, the command will ask
|
|
39
|
+
you for a description later.
|
|
40
|
+
${index.dim_1(`@see https://docs.npmjs.com/cli/v9/configuring-npm/package-json#description`)}
|
|
41
|
+
|
|
37
42
|
${index.cyan_1(`--react`)}, ${index.cyan_1(`--no-react`)}
|
|
38
43
|
Whether this package will use React. If you don’t provide this option, the command
|
|
39
44
|
will ask you about it later.
|
|
@@ -42,6 +47,11 @@ async function createProject() {
|
|
|
42
47
|
Whether this package will be published for other projects to install. If you do not
|
|
43
48
|
provide this option, the command will ask you about it later.
|
|
44
49
|
|
|
50
|
+
${index.cyan_1(`--repository`)}, ${index.cyan_1(`--no-repository`)}
|
|
51
|
+
The URL of a git repository where your code lives. If you do not provide this option,
|
|
52
|
+
this command will try to guess the correct repository to use based on existing packages.
|
|
53
|
+
${index.dim_1(`@see https://docs.npmjs.com/cli/v9/configuring-npm/package-json#repository`)}
|
|
54
|
+
|
|
45
55
|
${index.cyan_1(`--registry`)}
|
|
46
56
|
The package registry to publish this package to. This option only applies if you create
|
|
47
57
|
a public package. If you do not provide this option, it will use the default NPM registry.
|
|
@@ -53,22 +63,30 @@ async function createProject() {
|
|
|
53
63
|
});
|
|
54
64
|
return;
|
|
55
65
|
}
|
|
56
|
-
const inWorkspace = fs__namespace.existsSync('quilt.workspace.ts');
|
|
57
66
|
const name = await getName(args);
|
|
67
|
+
const description = await getDescription(args);
|
|
68
|
+
const inWorkspace = await packageManager.getInWorkspace(args);
|
|
58
69
|
const directory = await getDirectory(args, {
|
|
59
70
|
name,
|
|
60
71
|
inWorkspace
|
|
61
72
|
});
|
|
62
73
|
const isPublic = await getPublic(args);
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
const shouldInstall = await packageManager.getShouldInstall(args);
|
|
66
|
-
const packageManager$1 = await packageManager.getPackageManager(args, {
|
|
67
|
-
root: directory
|
|
74
|
+
const repository = await getRepository(args, {
|
|
75
|
+
inWorkspace
|
|
68
76
|
});
|
|
77
|
+
const useReact = await getReact(args);
|
|
78
|
+
const createAsMonorepo = !inWorkspace && (await packageManager.getCreateAsMonorepo(args, {
|
|
79
|
+
type: 'package'
|
|
80
|
+
}));
|
|
69
81
|
const setupExtras = await packageManager.getExtrasToSetup(args, {
|
|
70
82
|
inWorkspace
|
|
71
83
|
});
|
|
84
|
+
const shouldInstall = await packageManager.getShouldInstall(args, {
|
|
85
|
+
type: 'package'
|
|
86
|
+
});
|
|
87
|
+
const packageManager$1 = await packageManager.getPackageManager(args, {
|
|
88
|
+
root: directory
|
|
89
|
+
});
|
|
72
90
|
const partOfMonorepo = inWorkspace || createAsMonorepo;
|
|
73
91
|
const packageDirectory = createAsMonorepo ? path__namespace.join(directory, `packages/${packageManager.toValidPackageName(name.split('/').pop())}`) : directory;
|
|
74
92
|
if (fs__namespace.existsSync(directory)) {
|
|
@@ -88,12 +106,15 @@ async function createProject() {
|
|
|
88
106
|
const packageTemplate = packageManager.loadTemplate('package');
|
|
89
107
|
const workspaceTemplate = packageManager.loadTemplate('workspace');
|
|
90
108
|
let quiltProject = await packageTemplate.read('quilt.project.ts');
|
|
109
|
+
if (!useReact) {
|
|
110
|
+
quiltProject = quiltProject.replace('quiltPackage()', 'quiltPackage({react: false})');
|
|
111
|
+
}
|
|
91
112
|
|
|
92
113
|
// If we aren’t already in a workspace, copy the workspace files over, which
|
|
93
114
|
// are needed if we are making a monorepo or not.
|
|
94
115
|
if (!inWorkspace) {
|
|
95
116
|
await workspaceTemplate.copy(directory, file => {
|
|
96
|
-
// When this is a single project, we use the project’s Quilt
|
|
117
|
+
// When this is a single project, we use the project’s Quilt configuration as the base.
|
|
97
118
|
if (file === 'quilt.workspace.ts') return createAsMonorepo;
|
|
98
119
|
|
|
99
120
|
// We need to make some adjustments to the root package.json
|
|
@@ -103,41 +124,28 @@ async function createProject() {
|
|
|
103
124
|
// If we are creating a monorepo, we need to add the root package.json and
|
|
104
125
|
// package manager workspace configuration.
|
|
105
126
|
if (createAsMonorepo) {
|
|
127
|
+
const packageRelativeToRoot = path__namespace.relative(rootDirectory, packageDirectory);
|
|
128
|
+
const packageGlobRelativeToRoot = packageManager.relativeDirectoryForDisplay(path__namespace.join(packageRelativeToRoot, '*'));
|
|
106
129
|
const workspacePackageJson = JSON.parse(await workspaceTemplate.read('package.json'));
|
|
107
130
|
workspacePackageJson.name = packageManager.toValidPackageName(name);
|
|
131
|
+
workspacePackageJson.workspaces = [packageGlobRelativeToRoot];
|
|
108
132
|
if (packageManager$1.type === 'pnpm') {
|
|
109
133
|
await outputRoot.write('pnpm-workspace.yaml', await packageManager.format(`
|
|
110
134
|
packages:
|
|
111
|
-
- '
|
|
135
|
+
- '${packageGlobRelativeToRoot}'
|
|
112
136
|
`, {
|
|
113
137
|
as: 'yaml'
|
|
114
138
|
}));
|
|
115
|
-
} else {
|
|
116
|
-
workspacePackageJson.workspaces = ['packages/*'];
|
|
117
139
|
}
|
|
118
140
|
await outputRoot.write('package.json', await packageManager.format(JSON.stringify(workspacePackageJson), {
|
|
119
141
|
as: 'json-stringify'
|
|
120
142
|
}));
|
|
121
143
|
} else {
|
|
122
144
|
const [projectPackageJson, projectTSConfig, workspacePackageJson] = await Promise.all([packageTemplate.read('package.json').then(content => JSON.parse(content)), packageTemplate.read('tsconfig.json').then(content => JSON.parse(content)), workspaceTemplate.read('package.json').then(content => JSON.parse(content))]);
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
const newPackageJson = {};
|
|
126
|
-
|
|
127
|
-
// We want to put the project’s dependencies in the package.json, respecting
|
|
128
|
-
// the preferred ordering (dependencies, peer dependencies, dev dependencies).
|
|
129
|
-
for (const [key, value] of Object.entries(projectPackageJson)) {
|
|
130
|
-
if (key !== 'devDependencies') {
|
|
131
|
-
newPackageJson[key] = value;
|
|
132
|
-
continue;
|
|
133
|
-
}
|
|
134
|
-
newPackageJson.dependencies = projectPackageJson.dependencies;
|
|
135
|
-
newPackageJson.peerDependencies = projectPackageJson.peerDependencies;
|
|
136
|
-
newPackageJson.peerDependenciesMeta = projectPackageJson.peerDependenciesMeta;
|
|
137
|
-
newPackageJson.devDependencies = packageManager.mergeDependencies(workspacePackageJson.devDependencies, projectPackageJson.devDependencies);
|
|
138
|
-
}
|
|
139
|
-
adjustPackageJson(newPackageJson, {
|
|
145
|
+
const mergedPackageJson = packageManager.mergeWorkspaceAndProjectPackageJsons(projectPackageJson, workspacePackageJson);
|
|
146
|
+
adjustPackageJson(mergedPackageJson, {
|
|
140
147
|
name: packageManager.toValidPackageName(name),
|
|
148
|
+
description,
|
|
141
149
|
react: useReact,
|
|
142
150
|
isPublic,
|
|
143
151
|
registry: args['--registry']
|
|
@@ -146,7 +154,7 @@ async function createProject() {
|
|
|
146
154
|
await outputRoot.write('quilt.project.ts', await packageManager.format(quiltProject, {
|
|
147
155
|
as: 'typescript'
|
|
148
156
|
}));
|
|
149
|
-
await outputRoot.write('package.json', await packageManager.format(JSON.stringify(
|
|
157
|
+
await outputRoot.write('package.json', await packageManager.format(JSON.stringify(mergedPackageJson), {
|
|
150
158
|
as: 'json-stringify'
|
|
151
159
|
}));
|
|
152
160
|
await outputRoot.write('tsconfig.json', await packageManager.format(JSON.stringify(projectTSConfig), {
|
|
@@ -166,15 +174,36 @@ async function createProject() {
|
|
|
166
174
|
return partOfMonorepo;
|
|
167
175
|
}
|
|
168
176
|
|
|
169
|
-
// We need to make some adjustments the project’s package.json and Quilt config
|
|
170
|
-
return file !== 'package.json' && file !== 'quilt.project.ts';
|
|
177
|
+
// We need to make some adjustments the project’s package.json, README, and Quilt config
|
|
178
|
+
return file !== 'package.json' && file !== 'quilt.project.ts' && file !== 'README.md';
|
|
171
179
|
});
|
|
180
|
+
await outputRoot.write(path__namespace.join(packageDirectory, 'package.json'), (await packageTemplate.read('README.md')).replaceAll('{{name}}', packageManager.toValidPackageName(name)));
|
|
172
181
|
if (partOfMonorepo) {
|
|
173
182
|
// Write the package’s package.json (the root one was already created)
|
|
174
183
|
const projectPackageJson = JSON.parse(await packageTemplate.read('package.json'));
|
|
175
|
-
|
|
184
|
+
if (repository === false) {
|
|
185
|
+
delete projectPackageJson.repository;
|
|
186
|
+
} else {
|
|
187
|
+
const directory = path__namespace.relative(rootDirectory, packageDirectory);
|
|
188
|
+
if (typeof repository === 'string') {
|
|
189
|
+
projectPackageJson.repository = {
|
|
190
|
+
type: 'git',
|
|
191
|
+
url: repository,
|
|
192
|
+
directory
|
|
193
|
+
};
|
|
194
|
+
} else if (repository != null) {
|
|
195
|
+
projectPackageJson.repository = {
|
|
196
|
+
type: 'git',
|
|
197
|
+
...repository,
|
|
198
|
+
directory
|
|
199
|
+
};
|
|
200
|
+
} else {
|
|
201
|
+
projectPackageJson.repository.directory = directory;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
176
204
|
adjustPackageJson(projectPackageJson, {
|
|
177
205
|
name: packageManager.toValidPackageName(name),
|
|
206
|
+
description,
|
|
178
207
|
react: useReact,
|
|
179
208
|
isPublic,
|
|
180
209
|
registry: args['--registry']
|
|
@@ -186,45 +215,58 @@ async function createProject() {
|
|
|
186
215
|
await Promise.all([packageManager.addToTsConfig(packageDirectory, outputRoot), packageManager.addToPackageManagerWorkspaces(packageDirectory, outputRoot, packageManager$1.type)]);
|
|
187
216
|
}
|
|
188
217
|
if (shouldInstall) {
|
|
189
|
-
|
|
218
|
+
console.log();
|
|
190
219
|
// TODO: better loading, handle errors
|
|
191
220
|
await packageManager$1.install();
|
|
192
|
-
process.stdout.moveCursor(0, -1);
|
|
193
|
-
process.stdout.clearLine(1);
|
|
194
|
-
console.log('Installed dependencies.');
|
|
195
221
|
}
|
|
196
|
-
const packageJsonInstructions = index.stripIndent`
|
|
197
|
-
Your new package is ready to go! However, before you go too much further,
|
|
198
|
-
you should update the following fields in ${index.cyan_1(packageManager.relativeDirectoryForDisplay(path__namespace.relative(process.cwd(), path__namespace.join(packageDirectory, 'package.json'))))}:
|
|
199
|
-
|
|
200
|
-
- ${index.bold_1(`"description"`)}, where you provide a description of what your package does
|
|
201
|
-
- ${index.bold_1(`"repository"`)}, where you should include the ${index.bold_1(`"url"`)} of your project’s repo
|
|
202
|
-
|
|
203
|
-
Before you publish your package, you will also want to update the ${index.bold_1(`"version"`)}
|
|
204
|
-
field in the package.json file.
|
|
205
|
-
`;
|
|
206
222
|
console.log();
|
|
207
|
-
console.log(
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
console.log(whatsNext);
|
|
223
|
+
console.log(index.stripIndent`
|
|
224
|
+
Your new package, ${index.bold_1(name)}, is ready to go! You can edit the code
|
|
225
|
+
for your package in ${index.cyan_1(packageManager.relativeDirectoryForDisplay(path__namespace.relative(process.cwd(), path__namespace.join(packageDirectory, 'source'))))}.
|
|
226
|
+
`);
|
|
227
|
+
if (isPublic) {
|
|
228
|
+
const needsPackageJsonKeys = [];
|
|
229
|
+
if (!description) {
|
|
230
|
+
needsPackageJsonKeys.push({
|
|
231
|
+
field: 'description',
|
|
232
|
+
url: 'https://docs.npmjs.com/cli/v9/configuring-npm/package-json#description'
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
if (repository == null) {
|
|
236
|
+
needsPackageJsonKeys.push({
|
|
237
|
+
field: 'repository.url',
|
|
238
|
+
url: 'https://docs.npmjs.com/cli/v9/configuring-npm/package-json#repository'
|
|
239
|
+
});
|
|
240
|
+
}
|
|
226
241
|
console.log();
|
|
227
|
-
|
|
242
|
+
const logPackageJsonField = (field, url) => {
|
|
243
|
+
console.log(` ${index.bold_1(JSON.stringify(field))} ${index.dim_1(`(${index.underline_1(url)})`)}`);
|
|
244
|
+
};
|
|
245
|
+
if (needsPackageJsonKeys.length > 0) {
|
|
246
|
+
console.log(index.stripIndent`
|
|
247
|
+
Before you publish your package, you will need to add the following key${needsPackageJsonKeys.length > 1 ? 's' : ''}
|
|
248
|
+
to ${index.cyan_1(packageManager.relativeDirectoryForDisplay(path__namespace.relative(process.cwd(), path__namespace.join(packageDirectory, 'package.json'))))}:
|
|
249
|
+
`);
|
|
250
|
+
console.log();
|
|
251
|
+
for (const {
|
|
252
|
+
field,
|
|
253
|
+
url
|
|
254
|
+
} of needsPackageJsonKeys) {
|
|
255
|
+
logPackageJsonField(field, url);
|
|
256
|
+
}
|
|
257
|
+
console.log();
|
|
258
|
+
console.log('In that same file, make sure the contents of these fields are right for your package:');
|
|
259
|
+
console.log();
|
|
260
|
+
} else {
|
|
261
|
+
console.log(index.stripIndent`
|
|
262
|
+
Before you publish your package, make the following fields look right
|
|
263
|
+
in ${index.cyan_1(packageManager.relativeDirectoryForDisplay(path__namespace.relative(process.cwd(), path__namespace.join(packageDirectory, 'package.json'))))}:
|
|
264
|
+
`);
|
|
265
|
+
console.log();
|
|
266
|
+
}
|
|
267
|
+
logPackageJsonField('version', 'https://docs.npmjs.com/cli/v9/configuring-npm/package-json#version');
|
|
268
|
+
logPackageJsonField('license', 'https://docs.npmjs.com/cli/v9/configuring-npm/package-json#license');
|
|
269
|
+
logPackageJsonField('exports', 'https://nodejs.org/api/packages.html#package-entry-points');
|
|
228
270
|
}
|
|
229
271
|
const followUp = index.stripIndent`
|
|
230
272
|
Quilt can help you build, test, lint, and type-check your new package. You
|
|
@@ -245,6 +287,10 @@ function getArguments() {
|
|
|
245
287
|
'-y': '--yes',
|
|
246
288
|
'--name': String,
|
|
247
289
|
'--directory': String,
|
|
290
|
+
'--description': String,
|
|
291
|
+
'--no-description': Boolean,
|
|
292
|
+
'--repository': String,
|
|
293
|
+
'--no-repository': Boolean,
|
|
248
294
|
'--install': Boolean,
|
|
249
295
|
'--no-install': Boolean,
|
|
250
296
|
'--monorepo': Boolean,
|
|
@@ -311,6 +357,36 @@ async function getDirectory(args, {
|
|
|
311
357
|
}
|
|
312
358
|
return directory;
|
|
313
359
|
}
|
|
360
|
+
async function getDescription(args) {
|
|
361
|
+
if (args['--description']) return args['--description'];
|
|
362
|
+
if (args['--no-description']) return false;
|
|
363
|
+
const description = await index.prompt({
|
|
364
|
+
type: 'text',
|
|
365
|
+
message: 'What is a short description of what this package will do?'
|
|
366
|
+
});
|
|
367
|
+
return description;
|
|
368
|
+
}
|
|
369
|
+
async function getRepository(args, {
|
|
370
|
+
inWorkspace = false
|
|
371
|
+
} = {}) {
|
|
372
|
+
if (args['--repository']) return args['--repository'];
|
|
373
|
+
if (args['--no-repository']) return false;
|
|
374
|
+
if (!inWorkspace) return;
|
|
375
|
+
const {
|
|
376
|
+
globby
|
|
377
|
+
} = await Promise.resolve().then(function () { return require('./index4.cjs'); });
|
|
378
|
+
const files = await globby('**/package.json', {
|
|
379
|
+
ignore: ['**/node_modules']
|
|
380
|
+
});
|
|
381
|
+
for (const file of files) {
|
|
382
|
+
try {
|
|
383
|
+
const json = JSON.parse(await fs__namespace.promises.readFile(file, 'utf8'));
|
|
384
|
+
if (json.repository) return json.repository;
|
|
385
|
+
} catch {
|
|
386
|
+
// noop
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
314
390
|
async function getPublic(args) {
|
|
315
391
|
let isPublic;
|
|
316
392
|
if (args['--public'] || args['--yes']) {
|
|
@@ -343,6 +419,7 @@ async function getReact(args) {
|
|
|
343
419
|
}
|
|
344
420
|
function adjustPackageJson(packageJson, {
|
|
345
421
|
name,
|
|
422
|
+
description,
|
|
346
423
|
react,
|
|
347
424
|
isPublic,
|
|
348
425
|
registry
|
|
@@ -351,6 +428,11 @@ function adjustPackageJson(packageJson, {
|
|
|
351
428
|
const packageParts = name.split('/');
|
|
352
429
|
const scope = packageParts[0].startsWith('@') ? packageParts[0] : undefined;
|
|
353
430
|
const finalRegistry = registry ?? 'https://registry.npmjs.org';
|
|
431
|
+
if (description) {
|
|
432
|
+
packageJson.description = description;
|
|
433
|
+
} else {
|
|
434
|
+
delete packageJson.description;
|
|
435
|
+
}
|
|
354
436
|
if (scope) {
|
|
355
437
|
packageJson.publishConfig[`${scope}/registry`] = finalRegistry;
|
|
356
438
|
} else if (registry) {
|
|
@@ -359,7 +441,22 @@ function adjustPackageJson(packageJson, {
|
|
|
359
441
|
if (isPublic) {
|
|
360
442
|
delete packageJson.private;
|
|
361
443
|
} else {
|
|
444
|
+
delete packageJson.license;
|
|
445
|
+
delete packageJson.repository;
|
|
362
446
|
delete packageJson.publishConfig;
|
|
447
|
+
|
|
448
|
+
// in private packages, we just need to reference the source.
|
|
449
|
+
const newExports = {};
|
|
450
|
+
for (const [key, value] of Object.entries(packageJson.exports)) {
|
|
451
|
+
if (typeof value === 'string') {
|
|
452
|
+
newExports[key] = value;
|
|
453
|
+
}
|
|
454
|
+
const sourceEntry = value?.['quilt:source'];
|
|
455
|
+
if (typeof sourceEntry === 'string') {
|
|
456
|
+
newExports[key] = sourceEntry;
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
packageJson.exports = newExports;
|
|
363
460
|
}
|
|
364
461
|
if (!react) {
|
|
365
462
|
delete packageJson.dependencies['@types/react'];
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var fs = require('node:fs');
|
|
3
4
|
var require$$0 = require('node:tty');
|
|
4
5
|
var index = require('../index.cjs');
|
|
5
|
-
var fs = require('node:fs');
|
|
6
6
|
var node_child_process = require('node:child_process');
|
|
7
7
|
var path = require('node:path');
|
|
8
8
|
var node_url = require('node:url');
|
|
@@ -175,7 +175,8 @@ async function format(content, {
|
|
|
175
175
|
as: parser
|
|
176
176
|
}) {
|
|
177
177
|
const [{
|
|
178
|
-
format
|
|
178
|
+
format: rootFormat,
|
|
179
|
+
default: prettier
|
|
179
180
|
}, {
|
|
180
181
|
default: babel
|
|
181
182
|
}, {
|
|
@@ -183,6 +184,9 @@ async function format(content, {
|
|
|
183
184
|
}, {
|
|
184
185
|
default: yaml
|
|
185
186
|
}] = await Promise.all([Promise.resolve().then(function () { return require('../standalone.cjs'); }).then(function (n) { return n.standalone; }), Promise.resolve().then(function () { return require('../parser-babel.cjs'); }).then(function (n) { return n.parserBabel; }), Promise.resolve().then(function () { return require('../parser-typescript.cjs'); }).then(function (n) { return n.parserTypescript; }), Promise.resolve().then(function () { return require('../parser-yaml.cjs'); }).then(function (n) { return n.parserYaml; })]);
|
|
187
|
+
|
|
188
|
+
// CJS workaround
|
|
189
|
+
const format = rootFormat ?? prettier.format;
|
|
186
190
|
return format(content, {
|
|
187
191
|
arrowParens: 'always',
|
|
188
192
|
bracketSpacing: false,
|
|
@@ -203,6 +207,42 @@ function mergeDependencies(first = {}, second = {}) {
|
|
|
203
207
|
}
|
|
204
208
|
return merged;
|
|
205
209
|
}
|
|
210
|
+
const PACKAGE_JSON_DEPENDENCY_KEYS = new Set(['dependencies', 'devDependencies', 'peerDependencies', 'peerDependenciesMeta']);
|
|
211
|
+
|
|
212
|
+
// Merges a project and workspace package.json together, with the following nitpicky preferences:
|
|
213
|
+
//
|
|
214
|
+
// - Take all the project’s fields in the order they appear by default
|
|
215
|
+
// - Merge the relevant dependencies together
|
|
216
|
+
// - Projects don’t come with `scripts` by default, but that should go before the first dependency list
|
|
217
|
+
// - If there are other keys in the workspace package.json, they should go last, in the order they appeared
|
|
218
|
+
function mergeWorkspaceAndProjectPackageJsons(projectPackageJson, workspacePackageJson) {
|
|
219
|
+
const newPackageJson = {};
|
|
220
|
+
const seenKeys = new Set();
|
|
221
|
+
let hasHandledScriptsField = false;
|
|
222
|
+
for (const [key, value] of Object.entries(projectPackageJson)) {
|
|
223
|
+
seenKeys.add(key);
|
|
224
|
+
const isDependencyKey = PACKAGE_JSON_DEPENDENCY_KEYS.has(key);
|
|
225
|
+
if (key === 'scripts' || isDependencyKey && !hasHandledScriptsField) {
|
|
226
|
+
newPackageJson.scripts = {
|
|
227
|
+
...workspacePackageJson.scripts,
|
|
228
|
+
...projectPackageJson.scripts
|
|
229
|
+
};
|
|
230
|
+
hasHandledScriptsField = true;
|
|
231
|
+
}
|
|
232
|
+
if (isDependencyKey) {
|
|
233
|
+
newPackageJson[key] = mergeDependencies(value, workspacePackageJson[key]);
|
|
234
|
+
} else {
|
|
235
|
+
newPackageJson[key] = value;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
for (const [key, value] of Object.entries(workspacePackageJson)) {
|
|
239
|
+
if (seenKeys.has(key)) continue;
|
|
240
|
+
// Merged workspace + project package.json means we are not in a monorepo
|
|
241
|
+
if (key === 'workspaces') continue;
|
|
242
|
+
newPackageJson[key] = value;
|
|
243
|
+
}
|
|
244
|
+
return newPackageJson;
|
|
245
|
+
}
|
|
206
246
|
|
|
207
247
|
var colorette = {};
|
|
208
248
|
|
|
@@ -420,7 +460,14 @@ colorette.whiteBright = whiteBright;
|
|
|
420
460
|
colorette.yellow = yellow;
|
|
421
461
|
colorette.yellowBright = yellowBright;
|
|
422
462
|
|
|
423
|
-
async function
|
|
463
|
+
async function getInWorkspace(argv) {
|
|
464
|
+
if (argv['--in-workspace']) return true;
|
|
465
|
+
if (argv['--not-in-workspace']) return false;
|
|
466
|
+
return fs__namespace.existsSync('quilt.workspace.ts');
|
|
467
|
+
}
|
|
468
|
+
async function getCreateAsMonorepo(argv, {
|
|
469
|
+
type
|
|
470
|
+
}) {
|
|
424
471
|
let createAsMonorepo;
|
|
425
472
|
if (argv['--monorepo' ]) {
|
|
426
473
|
createAsMonorepo = true;
|
|
@@ -429,13 +476,15 @@ async function getCreateAsMonorepo(argv) {
|
|
|
429
476
|
} else {
|
|
430
477
|
createAsMonorepo = await index.prompt({
|
|
431
478
|
type: 'confirm',
|
|
432
|
-
message:
|
|
479
|
+
message: `Do you want to create this ${type} as a monorepo, with room for more projects?`,
|
|
433
480
|
initial: true
|
|
434
481
|
});
|
|
435
482
|
}
|
|
436
483
|
return createAsMonorepo;
|
|
437
484
|
}
|
|
438
|
-
async function getShouldInstall(argv
|
|
485
|
+
async function getShouldInstall(argv, {
|
|
486
|
+
type
|
|
487
|
+
}) {
|
|
439
488
|
let shouldInstall;
|
|
440
489
|
if (argv['--install'] || argv['--yes']) {
|
|
441
490
|
shouldInstall = true;
|
|
@@ -444,7 +493,7 @@ async function getShouldInstall(argv) {
|
|
|
444
493
|
} else {
|
|
445
494
|
shouldInstall = await index.prompt({
|
|
446
495
|
type: 'confirm',
|
|
447
|
-
message:
|
|
496
|
+
message: `Do you want to install dependencies for this ${type} after creating it?`,
|
|
448
497
|
initial: true
|
|
449
498
|
});
|
|
450
499
|
}
|
|
@@ -604,12 +653,13 @@ exports.emptyDirectory = emptyDirectory;
|
|
|
604
653
|
exports.format = format;
|
|
605
654
|
exports.getCreateAsMonorepo = getCreateAsMonorepo;
|
|
606
655
|
exports.getExtrasToSetup = getExtrasToSetup;
|
|
656
|
+
exports.getInWorkspace = getInWorkspace;
|
|
607
657
|
exports.getPackageManager = getPackageManager;
|
|
608
658
|
exports.getShouldInstall = getShouldInstall;
|
|
609
659
|
exports.isEmpty = isEmpty;
|
|
610
660
|
exports.loadTemplate = loadTemplate;
|
|
611
661
|
exports.magenta_1 = magenta_1;
|
|
612
|
-
exports.
|
|
662
|
+
exports.mergeWorkspaceAndProjectPackageJsons = mergeWorkspaceAndProjectPackageJsons;
|
|
613
663
|
exports.relativeDirectoryForDisplay = relativeDirectoryForDisplay;
|
|
614
664
|
exports.toValidPackageName = toValidPackageName;
|
|
615
665
|
exports.underline_1 = underline_1;
|
package/build/esm/app.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as fs from 'node:fs';
|
|
2
2
|
import * as path from 'node:path';
|
|
3
|
-
import { c as cyan_1, b as bold_1, g as
|
|
3
|
+
import { c as cyan_1, b as bold_1, g as getInWorkspace, a as getCreateAsMonorepo, d as getExtrasToSetup, e as getShouldInstall, f as getPackageManager, h as emptyDirectory, r as relativeDirectoryForDisplay, t as toValidPackageName, i as format, m as mergeWorkspaceAndProjectPackageJsons, l as loadTemplate, j as addToTsConfig, k as addToPackageManagerWorkspaces, n as dim_1, u as underline_1, o as magenta_1, p as isEmpty, q as createOutputTarget } from './shared/package-manager.mjs';
|
|
4
4
|
import { s as stripIndent, p as printHelp, a as prompt } from './index.mjs';
|
|
5
5
|
import 'node:tty';
|
|
6
6
|
import 'node:child_process';
|
|
@@ -222,7 +222,7 @@ async function createApp() {
|
|
|
222
222
|
});
|
|
223
223
|
return;
|
|
224
224
|
}
|
|
225
|
-
const inWorkspace =
|
|
225
|
+
const inWorkspace = await getInWorkspace(argv);
|
|
226
226
|
const name = await getName(argv, {
|
|
227
227
|
inWorkspace
|
|
228
228
|
});
|
|
@@ -230,14 +230,18 @@ async function createApp() {
|
|
|
230
230
|
name
|
|
231
231
|
});
|
|
232
232
|
const template = await getTemplate(argv);
|
|
233
|
-
const createAsMonorepo = !inWorkspace && (await getCreateAsMonorepo(argv
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
root: directory
|
|
237
|
-
});
|
|
233
|
+
const createAsMonorepo = !inWorkspace && (await getCreateAsMonorepo(argv, {
|
|
234
|
+
type: 'app'
|
|
235
|
+
}));
|
|
238
236
|
const setupExtras = await getExtrasToSetup(argv, {
|
|
239
237
|
inWorkspace
|
|
240
238
|
});
|
|
239
|
+
const shouldInstall = await getShouldInstall(argv, {
|
|
240
|
+
type: 'app'
|
|
241
|
+
});
|
|
242
|
+
const packageManager = await getPackageManager(argv, {
|
|
243
|
+
root: directory
|
|
244
|
+
});
|
|
241
245
|
const partOfMonorepo = inWorkspace || createAsMonorepo;
|
|
242
246
|
const appDirectory = createAsMonorepo ? path.join(directory, 'app') : directory;
|
|
243
247
|
if (fs.existsSync(directory)) {
|
|
@@ -271,33 +275,32 @@ async function createApp() {
|
|
|
271
275
|
// If we are creating a monorepo, we need to add the root package.json and
|
|
272
276
|
// package manager workspace configuration.
|
|
273
277
|
if (createAsMonorepo) {
|
|
278
|
+
const appRelativeToRoot = relativeDirectoryForDisplay(path.relative(directory, appDirectory));
|
|
274
279
|
const workspacePackageJson = JSON.parse(await workspaceTemplate.read('package.json'));
|
|
275
280
|
workspacePackageJson.name = toValidPackageName(name);
|
|
281
|
+
workspacePackageJson.workspaces = [appRelativeToRoot, './packages/*'];
|
|
276
282
|
if (packageManager.type === 'pnpm') {
|
|
277
283
|
await outputRoot.write('pnpm-workspace.yaml', await format(`
|
|
278
284
|
packages:
|
|
285
|
+
- '${appRelativeToRoot}'
|
|
279
286
|
- './packages/*'
|
|
280
287
|
`, {
|
|
281
288
|
as: 'yaml'
|
|
282
289
|
}));
|
|
283
|
-
} else {
|
|
284
|
-
workspacePackageJson.workspaces = ['packages/*'];
|
|
285
290
|
}
|
|
286
291
|
await outputRoot.write('package.json', await format(JSON.stringify(workspacePackageJson), {
|
|
287
292
|
as: 'json-stringify'
|
|
288
293
|
}));
|
|
289
294
|
} else {
|
|
290
295
|
const [projectPackageJson, projectTSConfig, workspacePackageJson] = await Promise.all([appTemplate.read('package.json').then(content => JSON.parse(content)), appTemplate.read('tsconfig.json').then(content => JSON.parse(content)), workspaceTemplate.read('package.json').then(content => JSON.parse(content))]);
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
workspacePackageJson.browserslist = projectPackageJson.browserslist;
|
|
294
|
-
workspacePackageJson.devDependencies = mergeDependencies(workspacePackageJson.devDependencies, projectPackageJson.devDependencies);
|
|
296
|
+
const combinedPackageJson = mergeWorkspaceAndProjectPackageJsons(projectPackageJson, workspacePackageJson);
|
|
297
|
+
combinedPackageJson.name = toValidPackageName(name);
|
|
295
298
|
let quiltProject = await appTemplate.read('quilt.project.ts');
|
|
296
299
|
quiltProject = quiltProject.replace('quiltApp', 'quiltWorkspace, quiltApp').replace('quiltApp(', 'quiltWorkspace(), quiltApp(');
|
|
297
300
|
await outputRoot.write('quilt.project.ts', await format(quiltProject, {
|
|
298
301
|
as: 'typescript'
|
|
299
302
|
}));
|
|
300
|
-
await outputRoot.write('package.json', await format(JSON.stringify(
|
|
303
|
+
await outputRoot.write('package.json', await format(JSON.stringify(combinedPackageJson), {
|
|
301
304
|
as: 'json-stringify'
|
|
302
305
|
}));
|
|
303
306
|
await outputRoot.write('tsconfig.json', await format(JSON.stringify(projectTSConfig), {
|
|
@@ -330,12 +333,9 @@ async function createApp() {
|
|
|
330
333
|
await Promise.all([addToTsConfig(appDirectory, outputRoot), addToPackageManagerWorkspaces(appDirectory, outputRoot, packageManager.type)]);
|
|
331
334
|
}
|
|
332
335
|
if (shouldInstall) {
|
|
333
|
-
|
|
336
|
+
console.log();
|
|
334
337
|
// TODO: better loading, handle errors
|
|
335
338
|
await packageManager.install();
|
|
336
|
-
process.stdout.moveCursor(0, -1);
|
|
337
|
-
process.stdout.clearLine(1);
|
|
338
|
-
console.log('Installed dependencies.');
|
|
339
339
|
}
|
|
340
340
|
const commands = [];
|
|
341
341
|
if (!inWorkspace && directory !== process.cwd()) {
|
|
@@ -344,10 +344,6 @@ async function createApp() {
|
|
|
344
344
|
if (!shouldInstall) {
|
|
345
345
|
commands.push(`${packageManager.commands.install()} ${dim_1('# Install all your dependencies')}`);
|
|
346
346
|
}
|
|
347
|
-
if (!inWorkspace) {
|
|
348
|
-
// TODO: change this condition to check if git was initialized already
|
|
349
|
-
commands.push(`git init && git add -A && git commit -m "Initial commit" ${dim_1('# Start your git history (optional)')}`);
|
|
350
|
-
}
|
|
351
347
|
commands.push(`${packageManager.commands.run('develop')} ${dim_1('# Start the development server')}`);
|
|
352
348
|
const whatsNext = stripIndent`
|
|
353
349
|
Your new app is ready to go! There’s just ${commands.length > 1 ? 'a few more steps' : 'one more step'} you’ll need to take
|