@quilted/create 0.1.12 → 0.1.15
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 +18 -0
- package/build/cjs/app.cjs +303 -0
- package/build/cjs/index.cjs +5220 -5198
- package/build/cjs/index2.cjs +374 -0
- package/build/cjs/index3.cjs +7854 -0
- package/build/cjs/minimatch.cjs +1202 -0
- package/build/cjs/package-manager.cjs +300 -0
- package/build/cjs/package.cjs +410 -0
- package/build/cjs/standalone.cjs +151 -0
- package/build/esm/app.mjs +280 -0
- package/build/esm/index.mjs +5206 -5195
- package/build/esm/index2.mjs +365 -0
- package/build/esm/index3.mjs +7852 -0
- package/build/esm/minimatch.mjs +1200 -0
- package/build/esm/package-manager.mjs +270 -0
- package/build/esm/package.mjs +387 -0
- package/build/esm/standalone.mjs +149 -0
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/typescript/app.d.ts +2 -0
- package/build/typescript/app.d.ts.map +1 -0
- package/build/typescript/help.d.ts +6 -0
- package/build/typescript/help.d.ts.map +1 -0
- package/build/typescript/package.d.ts +2 -0
- package/build/typescript/package.d.ts.map +1 -0
- package/build/typescript/shared/package-manager.d.ts +3 -0
- package/build/typescript/shared/package-manager.d.ts.map +1 -0
- package/build/typescript/shared/prompts.d.ts +22 -0
- package/build/typescript/shared/prompts.d.ts.map +1 -0
- package/build/typescript/shared/tsconfig.d.ts +3 -0
- package/build/typescript/shared/tsconfig.d.ts.map +1 -0
- package/build/typescript/shared.d.ts +21 -0
- package/build/typescript/shared.d.ts.map +1 -0
- package/package.json +13 -3
- package/source/app.ts +387 -0
- package/source/create.ts +43 -383
- package/source/help.ts +132 -0
- package/source/package.ts +510 -0
- package/source/shared/package-manager.ts +74 -0
- package/source/shared/prompts.ts +133 -0
- package/source/shared/tsconfig.ts +90 -0
- package/source/shared.ts +165 -0
- package/templates/{app → app-basic}/App.tsx +4 -7
- package/templates/{app → app-basic}/features/Start/Start.module.css +0 -0
- package/templates/{app → app-basic}/features/Start/Start.tsx +1 -1
- package/templates/{app → app-basic}/features/Start/index.ts +0 -0
- package/templates/{app → app-basic}/foundation/Head.tsx +8 -8
- package/templates/{app → app-basic}/foundation/Http.tsx +10 -6
- package/templates/{app → app-basic}/package.json +10 -1
- package/templates/{app → app-basic}/quilt.project.ts +0 -0
- package/templates/{app → app-basic}/server.tsx +0 -0
- package/templates/{app → app-basic}/shared/types.ts +0 -0
- package/templates/{app → app-basic}/tsconfig.json +0 -0
- package/templates/app-single-file/App.tsx +168 -0
- package/templates/app-single-file/package.json +30 -0
- package/templates/app-single-file/quilt.project.ts +6 -0
- package/templates/app-single-file/tsconfig.json +9 -0
- package/templates/{workspace → github}/_github/workflows/actions/prepare/action.yml +0 -0
- package/templates/{workspace → github}/_github/workflows/ci.yml +0 -0
- package/templates/package/package.json +24 -9
- package/templates/package/quilt.project.ts +1 -1
- package/templates/vscode/_vscode/extensions.json +7 -0
- package/templates/vscode/_vscode/settings.json +17 -0
- package/templates/workspace/_gitignore +1 -1
- package/templates/workspace/_prettierignore +1 -0
- package/templates/workspace/package.json +1 -6
- package/templates/workspace/tsconfig.json +6 -1
- package/templates/workspace/pnpm-workspace.yaml +0 -3
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var path = require('path');
|
|
4
|
+
var fs = require('fs');
|
|
5
|
+
var url = require('url');
|
|
6
|
+
require('./index.cjs');
|
|
7
|
+
|
|
8
|
+
function _interopNamespace(e) {
|
|
9
|
+
if (e && e.__esModule) return e;
|
|
10
|
+
var n = Object.create(null);
|
|
11
|
+
if (e) {
|
|
12
|
+
Object.keys(e).forEach(function (k) {
|
|
13
|
+
if (k !== 'default') {
|
|
14
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
15
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
16
|
+
enumerable: true,
|
|
17
|
+
get: function () { return e[k]; }
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
n["default"] = e;
|
|
23
|
+
return Object.freeze(n);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
var path__namespace = /*#__PURE__*/_interopNamespace(path);
|
|
27
|
+
var fs__namespace = /*#__PURE__*/_interopNamespace(fs);
|
|
28
|
+
|
|
29
|
+
function loadTemplate(name) {
|
|
30
|
+
let templateRootPromise;
|
|
31
|
+
return {
|
|
32
|
+
async copy(to, handleFile) {
|
|
33
|
+
templateRootPromise ?? (templateRootPromise = templateDirectory(name));
|
|
34
|
+
const templateRoot = await templateRootPromise;
|
|
35
|
+
const targetRoot = path__namespace.resolve(to);
|
|
36
|
+
const files = fs__namespace.readdirSync(templateRoot).filter(file => !path__namespace.basename(file).startsWith('.'));
|
|
37
|
+
|
|
38
|
+
for (const file of files) {
|
|
39
|
+
if (handleFile) {
|
|
40
|
+
if (!handleFile(file)) {
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const targetPath = path__namespace.join(targetRoot, file.startsWith('_') ? `.${file.slice(1)}` : file);
|
|
46
|
+
copy(path__namespace.join(templateRoot, file), targetPath);
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
async read(file) {
|
|
51
|
+
templateRootPromise ?? (templateRootPromise = templateDirectory(name));
|
|
52
|
+
const templateRoot = await templateRootPromise;
|
|
53
|
+
return fs__namespace.readFileSync(path__namespace.join(templateRoot, file), {
|
|
54
|
+
encoding: 'utf8'
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function createOutputTarget(target) {
|
|
61
|
+
return {
|
|
62
|
+
root: target,
|
|
63
|
+
|
|
64
|
+
read(file) {
|
|
65
|
+
return fs__namespace.promises.readFile(path__namespace.resolve(target, file), {
|
|
66
|
+
encoding: 'utf8'
|
|
67
|
+
});
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
async write(file, content) {
|
|
71
|
+
await writeFile(path__namespace.resolve(target, file), content);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
let packageRootPromise;
|
|
77
|
+
|
|
78
|
+
async function templateDirectory(name) {
|
|
79
|
+
return path__namespace.join(await getPackageRoot(), 'templates', name);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async function getPackageRoot() {
|
|
83
|
+
if (!packageRootPromise) {
|
|
84
|
+
packageRootPromise = (async () => {
|
|
85
|
+
const {
|
|
86
|
+
packageDirectory
|
|
87
|
+
} = await Promise.resolve().then(function () { return require('./index2.cjs'); });
|
|
88
|
+
return packageDirectory({
|
|
89
|
+
cwd: path__namespace.dirname(url.fileURLToPath((typeof document === 'undefined' ? new (require('u' + 'rl').URL)('file:' + __filename).href : (document.currentScript && document.currentScript.src || new URL('package-manager.cjs', document.baseURI).href))))
|
|
90
|
+
});
|
|
91
|
+
})();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return packageRootPromise;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function toValidPackageName(projectName) {
|
|
98
|
+
return projectName.trim().toLowerCase().replace(/\s+/g, '-').replace(/^[._]/, '').replace(/[^a-z0-9-~@/]+/g, '-');
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function copy(source, destination) {
|
|
102
|
+
const stat = fs__namespace.statSync(source);
|
|
103
|
+
|
|
104
|
+
if (stat.isDirectory()) {
|
|
105
|
+
copyDirectory(source, destination);
|
|
106
|
+
} else {
|
|
107
|
+
fs__namespace.copyFileSync(source, destination);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
async function copyDirectory(source, destination) {
|
|
112
|
+
fs__namespace.mkdirSync(destination, {
|
|
113
|
+
recursive: true
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
for (const file of fs__namespace.readdirSync(source)) {
|
|
117
|
+
const srcFile = path__namespace.resolve(source, file);
|
|
118
|
+
const destFile = path__namespace.resolve(destination, file);
|
|
119
|
+
copy(srcFile, destFile);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
async function writeFile(file, content) {
|
|
124
|
+
await fs__namespace.promises.writeFile(file, content);
|
|
125
|
+
}
|
|
126
|
+
async function isEmpty(path) {
|
|
127
|
+
return fs__namespace.readdirSync(path).length === 0;
|
|
128
|
+
}
|
|
129
|
+
async function emptyDirectory(dir) {
|
|
130
|
+
if (!fs__namespace.existsSync(dir)) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
for (const file of fs__namespace.readdirSync(dir)) {
|
|
135
|
+
fs__namespace.rmSync(path__namespace.resolve(dir, file), {
|
|
136
|
+
force: true,
|
|
137
|
+
recursive: true
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
function relativeDirectoryForDisplay(relativeDirectory) {
|
|
142
|
+
return relativeDirectory.startsWith('.') ? relativeDirectory : `.${path__namespace.sep}${relativeDirectory}`;
|
|
143
|
+
}
|
|
144
|
+
async function format(content, {
|
|
145
|
+
as: parser
|
|
146
|
+
}) {
|
|
147
|
+
const [{
|
|
148
|
+
format
|
|
149
|
+
}] = await Promise.all([Promise.resolve().then(function () { return require('./standalone.cjs'); }).then(function (n) { return n.standalone; })]);
|
|
150
|
+
return format(content, {
|
|
151
|
+
arrowParens: 'always',
|
|
152
|
+
bracketSpacing: false,
|
|
153
|
+
singleQuote: true,
|
|
154
|
+
trailingComma: 'all',
|
|
155
|
+
parser
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const ENDS_WITH_TSCONFIG = /[/]?tsconfig[.a-z0-9]*[.]json/i;
|
|
160
|
+
async function addToTsConfig(directory, output) {
|
|
161
|
+
const tsconfig = JSON.parse(await output.read('tsconfig.json'));
|
|
162
|
+
tsconfig.references ?? (tsconfig.references = []);
|
|
163
|
+
const relativePath = path.relative(output.root, directory);
|
|
164
|
+
const relativeForDisplay = relativeDirectoryForDisplay(relativePath);
|
|
165
|
+
|
|
166
|
+
if (tsconfig.references.length === 0) {
|
|
167
|
+
tsconfig.references.push({
|
|
168
|
+
path: relativeForDisplay
|
|
169
|
+
});
|
|
170
|
+
} else {
|
|
171
|
+
let hasExistingReference = false;
|
|
172
|
+
let referenceFormat = 'pretty-relative';
|
|
173
|
+
|
|
174
|
+
for (const {
|
|
175
|
+
path
|
|
176
|
+
} of tsconfig.references) {
|
|
177
|
+
if (path.startsWith('./')) {
|
|
178
|
+
if (ENDS_WITH_TSCONFIG.test(path)) {
|
|
179
|
+
referenceFormat = 'pretty-tsconfig';
|
|
180
|
+
|
|
181
|
+
if (path === `${relativeForDisplay}/tsconfig.json`) {
|
|
182
|
+
hasExistingReference = true;
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
referenceFormat = 'pretty-relative';
|
|
188
|
+
|
|
189
|
+
if (path === relativeForDisplay) {
|
|
190
|
+
hasExistingReference = true;
|
|
191
|
+
break;
|
|
192
|
+
}
|
|
193
|
+
} else if (ENDS_WITH_TSCONFIG.test(path)) {
|
|
194
|
+
referenceFormat = 'tsconfig';
|
|
195
|
+
|
|
196
|
+
if (path === `${relativePath}/tsconfig.json`) {
|
|
197
|
+
hasExistingReference = true;
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
} else {
|
|
201
|
+
referenceFormat = 'relative';
|
|
202
|
+
|
|
203
|
+
if (path === relativePath) {
|
|
204
|
+
hasExistingReference = true;
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (!hasExistingReference) {
|
|
211
|
+
let path;
|
|
212
|
+
|
|
213
|
+
if (referenceFormat === 'pretty-tsconfig') {
|
|
214
|
+
path = `${relativeForDisplay}/tsconfig.json`;
|
|
215
|
+
} else if (referenceFormat === 'pretty-relative') {
|
|
216
|
+
path = relativeForDisplay;
|
|
217
|
+
} else if (referenceFormat === 'tsconfig') {
|
|
218
|
+
path = `${relativePath}/tsconfig.json`;
|
|
219
|
+
} else {
|
|
220
|
+
path = relativePath;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
tsconfig.references.push({
|
|
224
|
+
path
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
tsconfig.references = tsconfig.references.sort(({
|
|
230
|
+
path: pathOne
|
|
231
|
+
}, {
|
|
232
|
+
path: pathTwo
|
|
233
|
+
}) => pathOne.localeCompare(pathTwo));
|
|
234
|
+
await output.write('tsconfig.json', await format(JSON.stringify(tsconfig), {
|
|
235
|
+
as: 'json'
|
|
236
|
+
}));
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
async function addToPackageManagerWorkspaces(directory, output, packageManager) {
|
|
240
|
+
if (packageManager === 'pnpm') {
|
|
241
|
+
const {
|
|
242
|
+
parse,
|
|
243
|
+
stringify
|
|
244
|
+
} = await Promise.resolve().then(function () { return require('./index3.cjs'); }).then(function (n) { return n.index; });
|
|
245
|
+
const workspaceYaml = parse(await output.read('pnpm-workspace.yaml'));
|
|
246
|
+
workspaceYaml.packages = await addToWorkspaces(path.relative(output.root, directory), workspaceYaml.packages ?? []);
|
|
247
|
+
await output.write('pnpm-workspace.yaml', await format(stringify(workspaceYaml), {
|
|
248
|
+
as: 'yaml'
|
|
249
|
+
}));
|
|
250
|
+
} else {
|
|
251
|
+
const packageJson = JSON.parse(await output.read('package.json'));
|
|
252
|
+
packageJson.workspaces = await addToWorkspaces(path.relative(output.root, directory), packageJson.workspaces ?? []);
|
|
253
|
+
await output.write('package.json', await format(JSON.stringify(packageJson), {
|
|
254
|
+
as: 'json-stringify'
|
|
255
|
+
}));
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
async function addToWorkspaces(relative, workspaces) {
|
|
260
|
+
if (workspaces.length === 0) {
|
|
261
|
+
return [relative];
|
|
262
|
+
} // Default documentation seems to generally exclude leading `./` on paths
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
let pretty = false;
|
|
266
|
+
let hasMatch = false;
|
|
267
|
+
const {
|
|
268
|
+
default: minimatch
|
|
269
|
+
} = await Promise.resolve().then(function () { return require('./minimatch.cjs'); }).then(function (n) { return n.minimatch; });
|
|
270
|
+
|
|
271
|
+
for (const pattern of workspaces) {
|
|
272
|
+
let normalizedPattern = pattern;
|
|
273
|
+
|
|
274
|
+
if (pattern.startsWith('./')) {
|
|
275
|
+
pretty = true;
|
|
276
|
+
normalizedPattern = pattern.slice(2);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
if (minimatch(relative, normalizedPattern)) {
|
|
280
|
+
hasMatch = true;
|
|
281
|
+
break;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
if (hasMatch) {
|
|
286
|
+
return workspaces;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
return [...workspaces, pretty ? relativeDirectoryForDisplay(relative) : relative].sort((patternOne, patternTwo) => patternOne.localeCompare(patternTwo));
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
exports.addToPackageManagerWorkspaces = addToPackageManagerWorkspaces;
|
|
293
|
+
exports.addToTsConfig = addToTsConfig;
|
|
294
|
+
exports.createOutputTarget = createOutputTarget;
|
|
295
|
+
exports.emptyDirectory = emptyDirectory;
|
|
296
|
+
exports.format = format;
|
|
297
|
+
exports.isEmpty = isEmpty;
|
|
298
|
+
exports.loadTemplate = loadTemplate;
|
|
299
|
+
exports.relativeDirectoryForDisplay = relativeDirectoryForDisplay;
|
|
300
|
+
exports.toValidPackageName = toValidPackageName;
|
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var fs = require('fs');
|
|
4
|
+
var path = require('path');
|
|
5
|
+
var child_process = require('child_process');
|
|
6
|
+
var index = require('./index.cjs');
|
|
7
|
+
var packageManager = require('./package-manager.cjs');
|
|
8
|
+
require('tty');
|
|
9
|
+
require('url');
|
|
10
|
+
require('readline');
|
|
11
|
+
require('events');
|
|
12
|
+
|
|
13
|
+
function _interopNamespace(e) {
|
|
14
|
+
if (e && e.__esModule) return e;
|
|
15
|
+
var n = Object.create(null);
|
|
16
|
+
if (e) {
|
|
17
|
+
Object.keys(e).forEach(function (k) {
|
|
18
|
+
if (k !== 'default') {
|
|
19
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
20
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
21
|
+
enumerable: true,
|
|
22
|
+
get: function () { return e[k]; }
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
n["default"] = e;
|
|
28
|
+
return Object.freeze(n);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
var fs__namespace = /*#__PURE__*/_interopNamespace(fs);
|
|
32
|
+
var path__namespace = /*#__PURE__*/_interopNamespace(path);
|
|
33
|
+
|
|
34
|
+
async function createPackage() {
|
|
35
|
+
const argv = getArgv();
|
|
36
|
+
|
|
37
|
+
if (argv['--help']) {
|
|
38
|
+
const additionalOptions = index.stripIndent`
|
|
39
|
+
${index.cyan_1(`--react`)}, ${index.cyan_1(`--no-react`)}
|
|
40
|
+
Whether this package will use React. If you don’t provide this option, the command
|
|
41
|
+
will ask you about it later.
|
|
42
|
+
|
|
43
|
+
${index.cyan_1(`--public`)}, ${index.cyan_1(`--private`)}
|
|
44
|
+
Whether this package will be published for other projects to install. If you do not
|
|
45
|
+
provide this option, the command will ask you about it later.
|
|
46
|
+
|
|
47
|
+
${index.cyan_1(`--registry`)}
|
|
48
|
+
The package registry to publish this package to. This option only applies if you create
|
|
49
|
+
a public package. If you do not provide this option, it will use the default NPM registry.
|
|
50
|
+
`;
|
|
51
|
+
index.printHelp({
|
|
52
|
+
kind: 'package',
|
|
53
|
+
options: additionalOptions,
|
|
54
|
+
packageManager: argv['--package-manager']?.toLowerCase()
|
|
55
|
+
});
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const inWorkspace = fs__namespace.existsSync('quilt.workspace.ts');
|
|
60
|
+
const name = await getName(argv);
|
|
61
|
+
const directory = await getDirectory(argv, {
|
|
62
|
+
name,
|
|
63
|
+
inWorkspace
|
|
64
|
+
});
|
|
65
|
+
const isPublic = await getPublic(argv);
|
|
66
|
+
const useReact = await getReact(argv);
|
|
67
|
+
const createAsMonorepo = !inWorkspace && (await index.getCreateAsMonorepo(argv));
|
|
68
|
+
const shouldInstall = await index.getShouldInstall(argv);
|
|
69
|
+
const packageManager$1 = await index.getPackageManager(argv);
|
|
70
|
+
const setupExtras = await index.getExtrasToSetup(argv, {
|
|
71
|
+
inWorkspace
|
|
72
|
+
});
|
|
73
|
+
const partOfMonorepo = inWorkspace || createAsMonorepo;
|
|
74
|
+
const packageDirectory = createAsMonorepo ? path__namespace.join(directory, `packages/${packageManager.toValidPackageName(name.split('/').pop())}`) : directory;
|
|
75
|
+
|
|
76
|
+
if (fs__namespace.existsSync(directory)) {
|
|
77
|
+
await packageManager.emptyDirectory(directory);
|
|
78
|
+
|
|
79
|
+
if (packageDirectory !== directory) {
|
|
80
|
+
fs__namespace.mkdirSync(packageDirectory, {
|
|
81
|
+
recursive: true
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
} else {
|
|
85
|
+
fs__namespace.mkdirSync(packageDirectory, {
|
|
86
|
+
recursive: true
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const rootDirectory = inWorkspace ? process.cwd() : directory;
|
|
91
|
+
const outputRoot = packageManager.createOutputTarget(rootDirectory);
|
|
92
|
+
const packageTemplate = packageManager.loadTemplate('package');
|
|
93
|
+
const workspaceTemplate = packageManager.loadTemplate('workspace');
|
|
94
|
+
let quiltProject = await packageTemplate.read('quilt.project.ts');
|
|
95
|
+
|
|
96
|
+
if (useReact) {
|
|
97
|
+
quiltProject = quiltProject.replace('react: false', 'react: true');
|
|
98
|
+
} // If we aren’t already in a workspace, copy the workspace files over, which
|
|
99
|
+
// are needed if we are making a monorepo or not.
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
if (!inWorkspace) {
|
|
103
|
+
await workspaceTemplate.copy(directory, file => {
|
|
104
|
+
// When this is a single project, we use the project’s Quilt configuration as the base.
|
|
105
|
+
if (file === 'quilt.workspace.ts') return createAsMonorepo; // We need to make some adjustments to the root package.json
|
|
106
|
+
|
|
107
|
+
return file !== 'package.json';
|
|
108
|
+
}); // If we are creating a monorepo, we need to add the root package.json and
|
|
109
|
+
// package manager workspace configuration.
|
|
110
|
+
|
|
111
|
+
if (createAsMonorepo) {
|
|
112
|
+
const workspacePackageJson = JSON.parse(await workspaceTemplate.read('package.json'));
|
|
113
|
+
workspacePackageJson.name = packageManager.toValidPackageName(name);
|
|
114
|
+
|
|
115
|
+
if (packageManager$1 === 'pnpm') {
|
|
116
|
+
await outputRoot.write('pnpm-workspace.yaml', await packageManager.format(`
|
|
117
|
+
packages:
|
|
118
|
+
- './packages/*'
|
|
119
|
+
`, {
|
|
120
|
+
as: 'yaml'
|
|
121
|
+
}));
|
|
122
|
+
} else {
|
|
123
|
+
workspacePackageJson.workspaces = ['packages/*'];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
await outputRoot.write('package.json', await packageManager.format(JSON.stringify(workspacePackageJson), {
|
|
127
|
+
as: 'json-stringify'
|
|
128
|
+
}));
|
|
129
|
+
} else {
|
|
130
|
+
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))]);
|
|
131
|
+
workspacePackageJson.eslintConfig = projectPackageJson.eslintConfig;
|
|
132
|
+
workspacePackageJson.browserslist = projectPackageJson.browserslist;
|
|
133
|
+
const newPackageJson = {}; // We want to put the project’s dependencies in the package.json, respecting
|
|
134
|
+
// the preferred ordering (dependencies, peer dependencies, dev dependencies).
|
|
135
|
+
|
|
136
|
+
for (const [key, value] of Object.entries(projectPackageJson)) {
|
|
137
|
+
if (key !== 'devDependencies') {
|
|
138
|
+
newPackageJson[key] = value;
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
newPackageJson.dependencies = projectPackageJson.dependencies;
|
|
143
|
+
newPackageJson.peerDependencies = projectPackageJson.peerDependencies;
|
|
144
|
+
newPackageJson.peerDependenciesMeta = projectPackageJson.peerDependenciesMeta;
|
|
145
|
+
newPackageJson.devDependencies = sortKeys({ ...workspacePackageJson.devDependencies,
|
|
146
|
+
...projectPackageJson.devDependencies
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
adjustPackageJson(newPackageJson, {
|
|
151
|
+
name: packageManager.toValidPackageName(name),
|
|
152
|
+
react: useReact,
|
|
153
|
+
isPublic,
|
|
154
|
+
registry: argv['--registry']
|
|
155
|
+
});
|
|
156
|
+
const addBackToTSConfigInclude = new Set(['quilt.project.ts', '*.test.ts', '*.test.tsx']);
|
|
157
|
+
projectTSConfig.exclude = projectTSConfig.exclude.filter(excluded => !addBackToTSConfigInclude.has(excluded));
|
|
158
|
+
quiltProject = quiltProject.replace('quiltPackage', 'quiltWorkspace, quiltPackage').replace('quiltPackage(', 'quiltWorkspace(), quiltPackage(');
|
|
159
|
+
await outputRoot.write('quilt.project.ts', await packageManager.format(quiltProject, {
|
|
160
|
+
as: 'typescript'
|
|
161
|
+
}));
|
|
162
|
+
await outputRoot.write('package.json', await packageManager.format(JSON.stringify(newPackageJson), {
|
|
163
|
+
as: 'json-stringify'
|
|
164
|
+
}));
|
|
165
|
+
await outputRoot.write('tsconfig.json', await packageManager.format(JSON.stringify(projectTSConfig), {
|
|
166
|
+
as: 'json'
|
|
167
|
+
}));
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (setupExtras.has('github')) {
|
|
171
|
+
await packageManager.loadTemplate('github').copy(directory);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (setupExtras.has('vscode')) {
|
|
175
|
+
await packageManager.loadTemplate('vscode').copy(directory);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
await packageTemplate.copy(packageDirectory, file => {
|
|
180
|
+
// If we are in a monorepo, we can use all the template files as they are
|
|
181
|
+
if (file === 'tsconfig.json') {
|
|
182
|
+
return partOfMonorepo;
|
|
183
|
+
} // We need to make some adjustments the project’s package.json and Quilt config
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
return file !== 'package.json' && file !== 'quilt.project.ts';
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
if (partOfMonorepo) {
|
|
190
|
+
// Write the package’s package.json (the root one was already created)
|
|
191
|
+
const projectPackageJson = JSON.parse(await packageTemplate.read('package.json'));
|
|
192
|
+
adjustPackageJson(projectPackageJson, {
|
|
193
|
+
name: packageManager.toValidPackageName(name),
|
|
194
|
+
react: useReact,
|
|
195
|
+
isPublic,
|
|
196
|
+
registry: argv['--registry']
|
|
197
|
+
});
|
|
198
|
+
await outputRoot.write(path__namespace.join(packageDirectory, 'package.json'), await packageManager.format(JSON.stringify(projectPackageJson), {
|
|
199
|
+
as: 'json-stringify'
|
|
200
|
+
}));
|
|
201
|
+
await Promise.all([packageManager.addToTsConfig(packageDirectory, outputRoot), packageManager.addToPackageManagerWorkspaces(packageDirectory, outputRoot, packageManager$1)]);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (shouldInstall) {
|
|
205
|
+
process.stdout.write('\nInstalling dependencies...\n'); // TODO: better loading, handle errors
|
|
206
|
+
|
|
207
|
+
child_process.execSync(`${packageManager$1} install`, {
|
|
208
|
+
cwd: rootDirectory
|
|
209
|
+
});
|
|
210
|
+
process.stdout.moveCursor(0, -1);
|
|
211
|
+
process.stdout.clearLine(1);
|
|
212
|
+
console.log('Installed dependencies.');
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const commands = [];
|
|
216
|
+
|
|
217
|
+
if (!inWorkspace && directory !== process.cwd()) {
|
|
218
|
+
commands.push(`cd ${index.cyan_1(packageManager.relativeDirectoryForDisplay(path__namespace.relative(process.cwd(), directory)))} ${index.dim_1('# Move into your new package’s directory')}`);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (!shouldInstall) {
|
|
222
|
+
commands.push(`pnpm install ${index.dim_1('# Install all your dependencies')}`);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (!inWorkspace) {
|
|
226
|
+
// TODO: change this condition to check if git was initialized already
|
|
227
|
+
commands.push(`git init && git add -A && git commit -m "Initial commit" ${index.dim_1('# Start your git history (optional)')}`);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const whatsNext = index.stripIndent`
|
|
231
|
+
Your new package is ready to go! There’s just ${commands.length > 1 ? 'a few more steps' : 'one more step'} you’ll need to take
|
|
232
|
+
in order to start building:
|
|
233
|
+
`;
|
|
234
|
+
console.log();
|
|
235
|
+
console.log(whatsNext);
|
|
236
|
+
console.log();
|
|
237
|
+
console.log(commands.map(command => ` ${command}`).join('\n'));
|
|
238
|
+
const followUp = index.stripIndent`
|
|
239
|
+
Quilt can also help you build, test, lint, and type-check your new package.
|
|
240
|
+
You can learn more about building packages with Quilt by reading the documentation:
|
|
241
|
+
${index.underline_1(index.magenta_1('https://github.com/lemonmade/quilt/tree/main/documentation'))}
|
|
242
|
+
|
|
243
|
+
Have fun! 🎉
|
|
244
|
+
`;
|
|
245
|
+
console.log();
|
|
246
|
+
console.log(followUp);
|
|
247
|
+
} // Argument handling
|
|
248
|
+
|
|
249
|
+
function getArgv() {
|
|
250
|
+
const argv = index.arg_1({
|
|
251
|
+
'--yes': Boolean,
|
|
252
|
+
'-y': '--yes',
|
|
253
|
+
'--name': String,
|
|
254
|
+
'--directory': String,
|
|
255
|
+
'--install': Boolean,
|
|
256
|
+
'--no-install': Boolean,
|
|
257
|
+
'--monorepo': Boolean,
|
|
258
|
+
'--no-monorepo': Boolean,
|
|
259
|
+
'--package-manager': String,
|
|
260
|
+
'--extras': [String],
|
|
261
|
+
'--no-extras': Boolean,
|
|
262
|
+
'--react': Boolean,
|
|
263
|
+
'--no-react': Boolean,
|
|
264
|
+
'--public': Boolean,
|
|
265
|
+
'--private': Boolean,
|
|
266
|
+
'--registry': String,
|
|
267
|
+
'--help': Boolean,
|
|
268
|
+
'-h': '--help'
|
|
269
|
+
}, {
|
|
270
|
+
permissive: true
|
|
271
|
+
});
|
|
272
|
+
return argv;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
async function getName(argv) {
|
|
276
|
+
let {
|
|
277
|
+
'--name': name
|
|
278
|
+
} = argv;
|
|
279
|
+
|
|
280
|
+
if (name == null) {
|
|
281
|
+
name = await index.prompt({
|
|
282
|
+
type: 'text',
|
|
283
|
+
message: 'What would you like to name your new package?',
|
|
284
|
+
initial: '@my-team/package'
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
return name;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
async function getDirectory(argv, {
|
|
292
|
+
name,
|
|
293
|
+
inWorkspace
|
|
294
|
+
}) {
|
|
295
|
+
let directory = argv['--directory'] ? path__namespace.resolve(argv['--directory']) : undefined;
|
|
296
|
+
|
|
297
|
+
if (directory == null) {
|
|
298
|
+
const basePackageName = packageManager.toValidPackageName(name.split('/').pop());
|
|
299
|
+
const defaultDirectory = inWorkspace ? `packages/${basePackageName}` : basePackageName;
|
|
300
|
+
directory = path__namespace.resolve(await index.prompt({
|
|
301
|
+
type: 'text',
|
|
302
|
+
message: 'Where would you like to create your new package?',
|
|
303
|
+
initial: defaultDirectory
|
|
304
|
+
}));
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
while (!argv['--yes']) {
|
|
308
|
+
if (fs__namespace.existsSync(directory) && !(await packageManager.isEmpty(directory))) {
|
|
309
|
+
const relativeDirectory = path__namespace.relative(process.cwd(), directory);
|
|
310
|
+
const empty = await index.prompt({
|
|
311
|
+
type: 'confirm',
|
|
312
|
+
message: `Directory ${index.bold_1(packageManager.relativeDirectoryForDisplay(relativeDirectory))} is not empty, is it safe to empty it?`,
|
|
313
|
+
initial: true
|
|
314
|
+
});
|
|
315
|
+
if (empty) break;
|
|
316
|
+
const promptDirectory = await index.prompt({
|
|
317
|
+
type: 'text',
|
|
318
|
+
message: 'What directory do you want to create your package in?'
|
|
319
|
+
});
|
|
320
|
+
directory = path__namespace.resolve(promptDirectory);
|
|
321
|
+
} else {
|
|
322
|
+
break;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
return directory;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
async function getPublic(argv) {
|
|
330
|
+
let isPublic;
|
|
331
|
+
|
|
332
|
+
if (argv['--public'] || argv['--yes']) {
|
|
333
|
+
isPublic = true;
|
|
334
|
+
} else if (argv['--private']) {
|
|
335
|
+
isPublic = false;
|
|
336
|
+
} else {
|
|
337
|
+
isPublic = await index.prompt({
|
|
338
|
+
type: 'confirm',
|
|
339
|
+
message: 'Will you publish this package to use in other projects?',
|
|
340
|
+
initial: true
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
return isPublic;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
async function getReact(argv) {
|
|
348
|
+
let useReact;
|
|
349
|
+
|
|
350
|
+
if (argv['--react'] || argv['--yes']) {
|
|
351
|
+
useReact = true;
|
|
352
|
+
} else if (argv['--no-react']) {
|
|
353
|
+
useReact = false;
|
|
354
|
+
} else {
|
|
355
|
+
useReact = await index.prompt({
|
|
356
|
+
type: 'confirm',
|
|
357
|
+
message: 'Will this package depend on React?',
|
|
358
|
+
initial: true
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
return useReact;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
function adjustPackageJson(packageJson, {
|
|
366
|
+
name,
|
|
367
|
+
react,
|
|
368
|
+
isPublic,
|
|
369
|
+
registry
|
|
370
|
+
}) {
|
|
371
|
+
packageJson.name = name;
|
|
372
|
+
const packageParts = name.split('/');
|
|
373
|
+
const scope = packageParts[0].startsWith('@') ? packageParts[0] : undefined;
|
|
374
|
+
const finalRegistry = registry ?? 'https://registry.npmjs.org';
|
|
375
|
+
|
|
376
|
+
if (scope) {
|
|
377
|
+
packageJson.publishConfig[`${scope}/registry`] = finalRegistry;
|
|
378
|
+
} else if (registry) {
|
|
379
|
+
packageJson.publishConfig.registry = finalRegistry;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
if (isPublic) {
|
|
383
|
+
delete packageJson.private;
|
|
384
|
+
} else {
|
|
385
|
+
delete packageJson.publishConfig;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
if (!react) {
|
|
389
|
+
delete packageJson.dependencies['@types/react'];
|
|
390
|
+
delete packageJson.devDependencies['react'];
|
|
391
|
+
delete packageJson.peerDependencies['react'];
|
|
392
|
+
delete packageJson.peerDependenciesMeta['react'];
|
|
393
|
+
packageJson.eslintConfig.extends = packageJson.eslintConfig.extends.filter(extend => !extend.includes('react'));
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
return packageJson;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
function sortKeys(object) {
|
|
400
|
+
const newObject = {};
|
|
401
|
+
const sortedEntries = Object.entries(object).sort(([keyOne], [keyTwo]) => keyOne.localeCompare(keyTwo));
|
|
402
|
+
|
|
403
|
+
for (const [key, value] of sortedEntries) {
|
|
404
|
+
newObject[key] = value;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
return newObject;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
exports.createPackage = createPackage;
|