create-krispya 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/index.cjs +16 -35
- package/dist/chunks/index.mjs +16 -35
- package/dist/cli.cjs +498 -316
- package/dist/cli.mjs +498 -316
- package/dist/index.d.cts +1 -0
- package/dist/index.d.mts +1 -0
- package/dist/index.d.ts +1 -0
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -123,7 +123,32 @@ function formatMonorepoConfigSummary(options) {
|
|
|
123
123
|
return lines.join("\n");
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
-
|
|
126
|
+
const config = new Conf({
|
|
127
|
+
projectName: "create-krispya"
|
|
128
|
+
});
|
|
129
|
+
function getPreferredEditor() {
|
|
130
|
+
return config.get("preferredEditor");
|
|
131
|
+
}
|
|
132
|
+
function setPreferredEditor(editor) {
|
|
133
|
+
config.set("preferredEditor", editor);
|
|
134
|
+
}
|
|
135
|
+
function getReuseWindow() {
|
|
136
|
+
return config.get("reuseWindow") ?? false;
|
|
137
|
+
}
|
|
138
|
+
function setReuseWindow(reuse) {
|
|
139
|
+
config.set("reuseWindow", reuse);
|
|
140
|
+
}
|
|
141
|
+
function clearConfig() {
|
|
142
|
+
config.clear();
|
|
143
|
+
}
|
|
144
|
+
function getConfigPath() {
|
|
145
|
+
return config.path;
|
|
146
|
+
}
|
|
147
|
+
function getCustomTemplates() {
|
|
148
|
+
return config.get("customTemplates") ?? {};
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function getDefaultOptions(template, name, projectType = "app", libraryBundler, integrations, inheritedTooling) {
|
|
127
152
|
const baseTemplate = getBaseTemplate(template);
|
|
128
153
|
const base = {
|
|
129
154
|
name,
|
|
@@ -133,26 +158,26 @@ function getDefaultOptions(template, name, projectType = "app", libraryBundler)
|
|
|
133
158
|
packageManager: "pnpm",
|
|
134
159
|
pnpmManageVersions: true,
|
|
135
160
|
nodeVersion: "latest",
|
|
136
|
-
linter: "oxlint",
|
|
137
|
-
formatter: "oxfmt",
|
|
161
|
+
linter: inheritedTooling?.linter ?? "oxlint",
|
|
162
|
+
formatter: inheritedTooling?.formatter ?? "oxfmt",
|
|
138
163
|
// Libraries get vitest by default, apps don't
|
|
139
164
|
testing: projectType === "library" ? "vitest" : "none"
|
|
140
165
|
};
|
|
141
|
-
if (baseTemplate === "r3f") {
|
|
166
|
+
if (baseTemplate === "r3f" && integrations) {
|
|
142
167
|
return {
|
|
143
168
|
...base,
|
|
144
|
-
drei: {},
|
|
145
|
-
handle: {},
|
|
146
|
-
leva: {},
|
|
147
|
-
postprocessing: {},
|
|
148
|
-
rapier: {},
|
|
149
|
-
xr: {},
|
|
150
|
-
uikit: {},
|
|
151
|
-
offscreen: {},
|
|
152
|
-
zustand: {},
|
|
153
|
-
koota: {},
|
|
154
|
-
triplex: {},
|
|
155
|
-
viverse: {}
|
|
169
|
+
drei: integrations.includes("drei") ? {} : void 0,
|
|
170
|
+
handle: integrations.includes("handle") ? {} : void 0,
|
|
171
|
+
leva: integrations.includes("leva") ? {} : void 0,
|
|
172
|
+
postprocessing: integrations.includes("postprocessing") ? {} : void 0,
|
|
173
|
+
rapier: integrations.includes("rapier") ? {} : void 0,
|
|
174
|
+
xr: integrations.includes("xr") ? {} : void 0,
|
|
175
|
+
uikit: integrations.includes("uikit") ? {} : void 0,
|
|
176
|
+
offscreen: integrations.includes("offscreen") ? {} : void 0,
|
|
177
|
+
zustand: integrations.includes("zustand") ? {} : void 0,
|
|
178
|
+
koota: integrations.includes("koota") ? {} : void 0,
|
|
179
|
+
triplex: integrations.includes("triplex") ? {} : void 0,
|
|
180
|
+
viverse: integrations.includes("viverse") ? {} : void 0
|
|
156
181
|
};
|
|
157
182
|
}
|
|
158
183
|
return base;
|
|
@@ -168,7 +193,33 @@ function getDefaultProjectName(template) {
|
|
|
168
193
|
return `react-three-${generateRandomName()}`;
|
|
169
194
|
}
|
|
170
195
|
}
|
|
171
|
-
async function
|
|
196
|
+
async function promptForR3fIntegrations() {
|
|
197
|
+
const selected = await p.multiselect({
|
|
198
|
+
message: "R3F integrations",
|
|
199
|
+
options: [
|
|
200
|
+
{ value: "drei", label: "Drei" },
|
|
201
|
+
{ value: "handle", label: "Handle" },
|
|
202
|
+
{ value: "leva", label: "Leva" },
|
|
203
|
+
{ value: "postprocessing", label: "Postprocessing" },
|
|
204
|
+
{ value: "rapier", label: "Rapier" },
|
|
205
|
+
{ value: "xr", label: "XR" },
|
|
206
|
+
{ value: "uikit", label: "UIKit" },
|
|
207
|
+
{ value: "offscreen", label: "Offscreen" },
|
|
208
|
+
{ value: "zustand", label: "Zustand" },
|
|
209
|
+
{ value: "koota", label: "Koota" },
|
|
210
|
+
{ value: "triplex", label: "Triplex" },
|
|
211
|
+
{ value: "viverse", label: "Viverse" }
|
|
212
|
+
],
|
|
213
|
+
initialValues: ["drei"],
|
|
214
|
+
required: false
|
|
215
|
+
});
|
|
216
|
+
if (p.isCancel(selected)) {
|
|
217
|
+
p.cancel("Operation cancelled.");
|
|
218
|
+
process.exit(0);
|
|
219
|
+
}
|
|
220
|
+
return selected;
|
|
221
|
+
}
|
|
222
|
+
async function promptForCustomization(template, name, projectType, integrations, inheritedTooling) {
|
|
172
223
|
let libraryBundler;
|
|
173
224
|
if (projectType === "library") {
|
|
174
225
|
const bundler = await p.select({
|
|
@@ -240,31 +291,39 @@ async function promptForCustomization(template, name, projectType) {
|
|
|
240
291
|
}
|
|
241
292
|
pnpmManageVersions = managePnpm;
|
|
242
293
|
}
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
294
|
+
let linter = inheritedTooling?.linter ?? "oxlint";
|
|
295
|
+
let formatter = inheritedTooling?.formatter ?? "oxfmt";
|
|
296
|
+
if (!inheritedTooling?.linter) {
|
|
297
|
+
const linterChoice = await p.select({
|
|
298
|
+
message: "Linter",
|
|
299
|
+
options: [
|
|
300
|
+
{ value: "oxlint", label: "Oxlint", hint: "fast, from OXC" },
|
|
301
|
+
{ value: "eslint", label: "ESLint", hint: "classic" },
|
|
302
|
+
{ value: "biome", label: "Biome", hint: "all-in-one" }
|
|
303
|
+
],
|
|
304
|
+
initialValue: "oxlint"
|
|
305
|
+
});
|
|
306
|
+
if (p.isCancel(linterChoice)) {
|
|
307
|
+
p.cancel("Operation cancelled.");
|
|
308
|
+
process.exit(0);
|
|
309
|
+
}
|
|
310
|
+
linter = linterChoice;
|
|
255
311
|
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
p.
|
|
267
|
-
|
|
312
|
+
if (!inheritedTooling?.formatter) {
|
|
313
|
+
const formatterChoice = await p.select({
|
|
314
|
+
message: "Formatter",
|
|
315
|
+
options: [
|
|
316
|
+
{ value: "oxfmt", label: "Oxfmt", hint: "fast, Prettier-compatible" },
|
|
317
|
+
{ value: "prettier", label: "Prettier", hint: "classic" },
|
|
318
|
+
{ value: "biome", label: "Biome", hint: "all-in-one" }
|
|
319
|
+
],
|
|
320
|
+
initialValue: "oxfmt"
|
|
321
|
+
});
|
|
322
|
+
if (p.isCancel(formatterChoice)) {
|
|
323
|
+
p.cancel("Operation cancelled.");
|
|
324
|
+
process.exit(0);
|
|
325
|
+
}
|
|
326
|
+
formatter = formatterChoice;
|
|
268
327
|
}
|
|
269
328
|
const testing = await p.select({
|
|
270
329
|
message: "Testing",
|
|
@@ -292,47 +351,7 @@ async function promptForCustomization(template, name, projectType) {
|
|
|
292
351
|
}
|
|
293
352
|
const baseTemplate = getBaseTemplate(template);
|
|
294
353
|
const finalTemplate = language === "javascript" ? `${baseTemplate}-js` : baseTemplate;
|
|
295
|
-
|
|
296
|
-
if (baseTemplate === "r3f") {
|
|
297
|
-
const selected = await p.multiselect({
|
|
298
|
-
message: "R3F integrations",
|
|
299
|
-
options: [
|
|
300
|
-
{ value: "drei", label: "Drei" },
|
|
301
|
-
{ value: "handle", label: "Handle" },
|
|
302
|
-
{ value: "leva", label: "Leva" },
|
|
303
|
-
{ value: "postprocessing", label: "Postprocessing" },
|
|
304
|
-
{ value: "rapier", label: "Rapier" },
|
|
305
|
-
{ value: "xr", label: "XR" },
|
|
306
|
-
{ value: "uikit", label: "UIKit" },
|
|
307
|
-
{ value: "offscreen", label: "Offscreen" },
|
|
308
|
-
{ value: "zustand", label: "Zustand" },
|
|
309
|
-
{ value: "koota", label: "Koota" },
|
|
310
|
-
{ value: "triplex", label: "Triplex" },
|
|
311
|
-
{ value: "viverse", label: "Viverse" }
|
|
312
|
-
],
|
|
313
|
-
initialValues: [
|
|
314
|
-
"drei",
|
|
315
|
-
"handle",
|
|
316
|
-
"leva",
|
|
317
|
-
"postprocessing",
|
|
318
|
-
"rapier",
|
|
319
|
-
"xr",
|
|
320
|
-
"uikit",
|
|
321
|
-
"offscreen",
|
|
322
|
-
"zustand",
|
|
323
|
-
"koota",
|
|
324
|
-
"triplex",
|
|
325
|
-
"viverse"
|
|
326
|
-
],
|
|
327
|
-
required: false
|
|
328
|
-
});
|
|
329
|
-
if (p.isCancel(selected)) {
|
|
330
|
-
p.cancel("Operation cancelled.");
|
|
331
|
-
process.exit(0);
|
|
332
|
-
}
|
|
333
|
-
integrations = selected;
|
|
334
|
-
}
|
|
335
|
-
return {
|
|
354
|
+
const base = {
|
|
336
355
|
name,
|
|
337
356
|
template: finalTemplate,
|
|
338
357
|
projectType,
|
|
@@ -342,8 +361,11 @@ async function promptForCustomization(template, name, projectType) {
|
|
|
342
361
|
pnpmManageVersions,
|
|
343
362
|
linter,
|
|
344
363
|
formatter,
|
|
345
|
-
testing
|
|
346
|
-
|
|
364
|
+
testing
|
|
365
|
+
};
|
|
366
|
+
if (baseTemplate === "r3f" && integrations) {
|
|
367
|
+
return {
|
|
368
|
+
...base,
|
|
347
369
|
drei: integrations.includes("drei") ? {} : void 0,
|
|
348
370
|
handle: integrations.includes("handle") ? {} : void 0,
|
|
349
371
|
leva: integrations.includes("leva") ? {} : void 0,
|
|
@@ -356,8 +378,9 @@ async function promptForCustomization(template, name, projectType) {
|
|
|
356
378
|
koota: integrations.includes("koota") ? {} : void 0,
|
|
357
379
|
triplex: integrations.includes("triplex") ? {} : void 0,
|
|
358
380
|
viverse: integrations.includes("viverse") ? {} : void 0
|
|
359
|
-
}
|
|
360
|
-
}
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
return base;
|
|
361
384
|
}
|
|
362
385
|
async function promptForInitialPackage() {
|
|
363
386
|
const choice = await p.select({
|
|
@@ -476,19 +499,15 @@ async function promptForMonorepo(workspaceName) {
|
|
|
476
499
|
}),
|
|
477
500
|
"Workspace Configuration"
|
|
478
501
|
);
|
|
479
|
-
const
|
|
502
|
+
const proceed = await p.confirm({
|
|
480
503
|
message: "Proceed with these settings?",
|
|
481
|
-
|
|
482
|
-
{ value: "confirm", label: "Yes, create workspace" },
|
|
483
|
-
{ value: "customize", label: "No, let me customize" }
|
|
484
|
-
],
|
|
485
|
-
initialValue: "confirm"
|
|
504
|
+
initialValue: true
|
|
486
505
|
});
|
|
487
|
-
if (p.isCancel(
|
|
506
|
+
if (p.isCancel(proceed)) {
|
|
488
507
|
p.cancel("Operation cancelled.");
|
|
489
508
|
process.exit(0);
|
|
490
509
|
}
|
|
491
|
-
if (
|
|
510
|
+
if (proceed) {
|
|
492
511
|
return defaultOptions;
|
|
493
512
|
}
|
|
494
513
|
return promptForMonorepoCustomization(workspaceName);
|
|
@@ -528,65 +547,122 @@ async function promptForOptions(name) {
|
|
|
528
547
|
}
|
|
529
548
|
return promptForPackageOptions(projectName, projectType);
|
|
530
549
|
}
|
|
531
|
-
|
|
532
|
-
const
|
|
550
|
+
function customTemplateToOptions(customTemplate, name, projectType) {
|
|
551
|
+
const baseTemplate = customTemplate.baseTemplate;
|
|
552
|
+
const template = baseTemplate;
|
|
553
|
+
const base = {
|
|
554
|
+
name,
|
|
555
|
+
template,
|
|
556
|
+
projectType,
|
|
557
|
+
packageManager: "pnpm",
|
|
558
|
+
pnpmManageVersions: true,
|
|
559
|
+
nodeVersion: "latest",
|
|
560
|
+
linter: customTemplate.linter,
|
|
561
|
+
formatter: customTemplate.formatter,
|
|
562
|
+
testing: customTemplate.testing
|
|
563
|
+
};
|
|
564
|
+
if (baseTemplate === "r3f" && customTemplate.integrations) {
|
|
565
|
+
const integrations = customTemplate.integrations;
|
|
566
|
+
return {
|
|
567
|
+
...base,
|
|
568
|
+
drei: integrations.includes("drei") ? {} : void 0,
|
|
569
|
+
handle: integrations.includes("handle") ? {} : void 0,
|
|
570
|
+
leva: integrations.includes("leva") ? {} : void 0,
|
|
571
|
+
postprocessing: integrations.includes("postprocessing") ? {} : void 0,
|
|
572
|
+
rapier: integrations.includes("rapier") ? {} : void 0,
|
|
573
|
+
xr: integrations.includes("xr") ? {} : void 0,
|
|
574
|
+
uikit: integrations.includes("uikit") ? {} : void 0,
|
|
575
|
+
offscreen: integrations.includes("offscreen") ? {} : void 0,
|
|
576
|
+
zustand: integrations.includes("zustand") ? {} : void 0,
|
|
577
|
+
koota: integrations.includes("koota") ? {} : void 0,
|
|
578
|
+
triplex: integrations.includes("triplex") ? {} : void 0,
|
|
579
|
+
viverse: integrations.includes("viverse") ? {} : void 0
|
|
580
|
+
};
|
|
581
|
+
}
|
|
582
|
+
return base;
|
|
583
|
+
}
|
|
584
|
+
async function promptForPackageOptions(projectName, projectType, inheritedTooling) {
|
|
585
|
+
const builtInOptions = [
|
|
586
|
+
{ value: "vanilla", label: "Vanilla" },
|
|
587
|
+
{ value: "react", label: "React" },
|
|
588
|
+
{ value: "r3f", label: "React Three Fiber" }
|
|
589
|
+
];
|
|
590
|
+
const customTemplates = getCustomTemplates();
|
|
591
|
+
const customOptions = Object.keys(customTemplates).map((name) => ({
|
|
592
|
+
value: `custom:${name}`,
|
|
593
|
+
label: name,
|
|
594
|
+
hint: "saved template"
|
|
595
|
+
}));
|
|
596
|
+
const allOptions = [...builtInOptions, ...customOptions];
|
|
597
|
+
const templateSelection = await p.select({
|
|
533
598
|
message: "Select a template",
|
|
534
|
-
options:
|
|
535
|
-
{ value: "vanilla", label: "Vanilla" },
|
|
536
|
-
{ value: "react", label: "React" },
|
|
537
|
-
{ value: "r3f", label: "React Three Fiber" }
|
|
538
|
-
],
|
|
599
|
+
options: allOptions,
|
|
539
600
|
initialValue: "vanilla"
|
|
540
601
|
});
|
|
541
|
-
if (p.isCancel(
|
|
602
|
+
if (p.isCancel(templateSelection)) {
|
|
542
603
|
p.cancel("Operation cancelled.");
|
|
543
604
|
process.exit(0);
|
|
544
605
|
}
|
|
606
|
+
const selection = templateSelection;
|
|
607
|
+
if (selection.startsWith("custom:")) {
|
|
608
|
+
const customName = selection.slice(7);
|
|
609
|
+
const customTemplate = customTemplates[customName];
|
|
610
|
+
const defaultOptions2 = customTemplateToOptions(customTemplate, projectName, projectType);
|
|
611
|
+
if (inheritedTooling?.linter) {
|
|
612
|
+
defaultOptions2.linter = inheritedTooling.linter;
|
|
613
|
+
}
|
|
614
|
+
if (inheritedTooling?.formatter) {
|
|
615
|
+
defaultOptions2.formatter = inheritedTooling.formatter;
|
|
616
|
+
}
|
|
617
|
+
const configTitle2 = inheritedTooling ? `Template: ${customName} (using workspace tooling)` : `Template: ${customName}`;
|
|
618
|
+
p.note(formatConfigSummary(defaultOptions2), configTitle2);
|
|
619
|
+
const proceed2 = await p.confirm({
|
|
620
|
+
message: "Proceed with these settings?",
|
|
621
|
+
initialValue: true
|
|
622
|
+
});
|
|
623
|
+
if (p.isCancel(proceed2)) {
|
|
624
|
+
p.cancel("Operation cancelled.");
|
|
625
|
+
process.exit(0);
|
|
626
|
+
}
|
|
627
|
+
if (proceed2) {
|
|
628
|
+
return defaultOptions2;
|
|
629
|
+
}
|
|
630
|
+
return promptForCustomization(
|
|
631
|
+
customTemplate.baseTemplate,
|
|
632
|
+
projectName,
|
|
633
|
+
projectType,
|
|
634
|
+
customTemplate.integrations,
|
|
635
|
+
inheritedTooling
|
|
636
|
+
);
|
|
637
|
+
}
|
|
638
|
+
const template = selection;
|
|
639
|
+
const baseTemplate = getBaseTemplate(template);
|
|
640
|
+
let integrations;
|
|
641
|
+
if (baseTemplate === "r3f") {
|
|
642
|
+
integrations = await promptForR3fIntegrations();
|
|
643
|
+
}
|
|
545
644
|
const defaultOptions = getDefaultOptions(
|
|
546
645
|
template,
|
|
547
646
|
projectName,
|
|
548
|
-
projectType
|
|
647
|
+
projectType,
|
|
648
|
+
void 0,
|
|
649
|
+
integrations,
|
|
650
|
+
inheritedTooling
|
|
549
651
|
);
|
|
550
|
-
|
|
551
|
-
|
|
652
|
+
const configTitle = inheritedTooling ? "Template Configuration (using workspace tooling)" : "Template Configuration";
|
|
653
|
+
p.note(formatConfigSummary(defaultOptions), configTitle);
|
|
654
|
+
const proceed = await p.confirm({
|
|
552
655
|
message: "Proceed with these settings?",
|
|
553
|
-
|
|
554
|
-
{ value: "confirm", label: "Yes, create project" },
|
|
555
|
-
{ value: "customize", label: "No, let me customize" }
|
|
556
|
-
],
|
|
557
|
-
initialValue: "confirm"
|
|
656
|
+
initialValue: true
|
|
558
657
|
});
|
|
559
|
-
if (p.isCancel(
|
|
658
|
+
if (p.isCancel(proceed)) {
|
|
560
659
|
p.cancel("Operation cancelled.");
|
|
561
660
|
process.exit(0);
|
|
562
661
|
}
|
|
563
|
-
if (
|
|
662
|
+
if (proceed) {
|
|
564
663
|
return defaultOptions;
|
|
565
664
|
}
|
|
566
|
-
return promptForCustomization(
|
|
567
|
-
template,
|
|
568
|
-
projectName,
|
|
569
|
-
projectType
|
|
570
|
-
);
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
const config = new Conf({
|
|
574
|
-
projectName: "create-krispya"
|
|
575
|
-
});
|
|
576
|
-
function getPreferredEditor() {
|
|
577
|
-
return config.get("preferredEditor");
|
|
578
|
-
}
|
|
579
|
-
function setPreferredEditor(editor) {
|
|
580
|
-
config.set("preferredEditor", editor);
|
|
581
|
-
}
|
|
582
|
-
function getReuseWindow() {
|
|
583
|
-
return config.get("reuseWindow") ?? false;
|
|
584
|
-
}
|
|
585
|
-
function setReuseWindow(reuse) {
|
|
586
|
-
config.set("reuseWindow", reuse);
|
|
587
|
-
}
|
|
588
|
-
function clearConfig() {
|
|
589
|
-
config.clear();
|
|
665
|
+
return promptForCustomization(template, projectName, projectType, integrations, inheritedTooling);
|
|
590
666
|
}
|
|
591
667
|
|
|
592
668
|
const require$1 = createRequire(import.meta.url);
|
|
@@ -608,6 +684,258 @@ async function detectMonorepoRoot() {
|
|
|
608
684
|
}
|
|
609
685
|
return null;
|
|
610
686
|
}
|
|
687
|
+
async function detectWorkspaceTooling(monorepoRoot) {
|
|
688
|
+
try {
|
|
689
|
+
const pkgPath = join(monorepoRoot, "package.json");
|
|
690
|
+
const content = await readFile(pkgPath, "utf-8");
|
|
691
|
+
const pkg2 = JSON.parse(content);
|
|
692
|
+
const devDeps = pkg2.devDependencies ?? {};
|
|
693
|
+
const linter = devDeps.oxlint ? "oxlint" : devDeps.eslint ? "eslint" : devDeps["@biomejs/biome"] ? "biome" : void 0;
|
|
694
|
+
const formatter = devDeps.oxfmt ? "oxfmt" : devDeps.prettier ? "prettier" : devDeps["@biomejs/biome"] ? "biome" : void 0;
|
|
695
|
+
return { linter, formatter };
|
|
696
|
+
} catch {
|
|
697
|
+
return {};
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
async function getMonorepoScope(monorepoRoot) {
|
|
701
|
+
try {
|
|
702
|
+
const pkgPath = join(monorepoRoot, "package.json");
|
|
703
|
+
const content = await readFile(pkgPath, "utf-8");
|
|
704
|
+
const pkg2 = JSON.parse(content);
|
|
705
|
+
if (pkg2.name) {
|
|
706
|
+
return pkg2.name.replace(/^@/, "").replace(/\/.*$/, "");
|
|
707
|
+
}
|
|
708
|
+
} catch {
|
|
709
|
+
}
|
|
710
|
+
return monorepoRoot.split(/[/\\]/).pop() ?? "workspace";
|
|
711
|
+
}
|
|
712
|
+
async function getWorkspacePackages(monorepoRoot) {
|
|
713
|
+
const packagesDir = join(monorepoRoot, "packages");
|
|
714
|
+
const packages = [];
|
|
715
|
+
try {
|
|
716
|
+
const { readdir } = await import('fs/promises');
|
|
717
|
+
const entries = await readdir(packagesDir, { withFileTypes: true });
|
|
718
|
+
for (const entry of entries) {
|
|
719
|
+
if (entry.isDirectory()) {
|
|
720
|
+
try {
|
|
721
|
+
const pkgJsonPath = join(packagesDir, entry.name, "package.json");
|
|
722
|
+
const content = await readFile(pkgJsonPath, "utf-8");
|
|
723
|
+
const pkg2 = JSON.parse(content);
|
|
724
|
+
if (pkg2.name) {
|
|
725
|
+
packages.push({ name: pkg2.name, path: `packages/${entry.name}` });
|
|
726
|
+
}
|
|
727
|
+
} catch {
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
} catch {
|
|
732
|
+
}
|
|
733
|
+
return packages;
|
|
734
|
+
}
|
|
735
|
+
async function createPackageInWorkspace(monorepoRoot, packageManager, inheritedTooling, scope) {
|
|
736
|
+
const packageType = await promptForInitialPackage();
|
|
737
|
+
if (packageType === "skip") {
|
|
738
|
+
return false;
|
|
739
|
+
}
|
|
740
|
+
const packageNameInput = await p.text({
|
|
741
|
+
message: "Package name?",
|
|
742
|
+
placeholder: `Scoped to @${scope}/`,
|
|
743
|
+
validate: (value) => {
|
|
744
|
+
if (!value.length) return "Package name is required";
|
|
745
|
+
}
|
|
746
|
+
});
|
|
747
|
+
if (p.isCancel(packageNameInput)) {
|
|
748
|
+
return false;
|
|
749
|
+
}
|
|
750
|
+
const shortName = packageNameInput;
|
|
751
|
+
const scopedName = `@${scope}/${shortName}`;
|
|
752
|
+
const targetDir = packageType === "app" ? "apps" : "packages";
|
|
753
|
+
const packagePath = join(targetDir, shortName);
|
|
754
|
+
const workspaceRoot = "../..";
|
|
755
|
+
const packageOptions = await promptForPackageOptions(
|
|
756
|
+
scopedName,
|
|
757
|
+
packageType,
|
|
758
|
+
inheritedTooling
|
|
759
|
+
);
|
|
760
|
+
packageOptions.workspaceRoot = workspaceRoot;
|
|
761
|
+
packageOptions.name = scopedName;
|
|
762
|
+
if (packageManager === "pnpm") {
|
|
763
|
+
packageOptions.pnpmVersion = await getLatestPnpmVersion();
|
|
764
|
+
}
|
|
765
|
+
const nodeVersion = packageOptions.nodeVersion ?? "latest";
|
|
766
|
+
if (nodeVersion === "latest") {
|
|
767
|
+
packageOptions.nodeVersion = await getLatestNodeVersion();
|
|
768
|
+
}
|
|
769
|
+
const versions = {};
|
|
770
|
+
const versionPromises = [];
|
|
771
|
+
const pkgIsLibrary = packageOptions.projectType === "library";
|
|
772
|
+
const pkgTesting = packageOptions.testing ?? (pkgIsLibrary ? "vitest" : "none");
|
|
773
|
+
if (pkgTesting === "vitest") {
|
|
774
|
+
versionPromises.push(
|
|
775
|
+
getLatestNpmVersion("vitest", "4.0.0").then((v) => {
|
|
776
|
+
versions.vitest = v;
|
|
777
|
+
})
|
|
778
|
+
);
|
|
779
|
+
}
|
|
780
|
+
if (!pkgIsLibrary) {
|
|
781
|
+
versionPromises.push(
|
|
782
|
+
getLatestNpmVersion("vite", "6.3.4").then((v) => {
|
|
783
|
+
versions.vite = v;
|
|
784
|
+
})
|
|
785
|
+
);
|
|
786
|
+
}
|
|
787
|
+
const linter = packageOptions.linter ?? "oxlint";
|
|
788
|
+
if (linter === "eslint") {
|
|
789
|
+
versionPromises.push(
|
|
790
|
+
getLatestNpmVersion("eslint", "9.17.0").then((v) => {
|
|
791
|
+
versions.eslint = v;
|
|
792
|
+
})
|
|
793
|
+
);
|
|
794
|
+
} else if (linter === "oxlint") {
|
|
795
|
+
versionPromises.push(
|
|
796
|
+
getLatestNpmVersion("oxlint", "0.16.0").then((v) => {
|
|
797
|
+
versions.oxlint = v;
|
|
798
|
+
})
|
|
799
|
+
);
|
|
800
|
+
} else if (linter === "biome") {
|
|
801
|
+
versionPromises.push(
|
|
802
|
+
getLatestNpmVersion("@biomejs/biome", "1.9.4").then((v) => {
|
|
803
|
+
versions.biome = v;
|
|
804
|
+
})
|
|
805
|
+
);
|
|
806
|
+
}
|
|
807
|
+
const formatter = packageOptions.formatter ?? "oxfmt";
|
|
808
|
+
if (formatter === "prettier") {
|
|
809
|
+
versionPromises.push(
|
|
810
|
+
getLatestNpmVersion("prettier", "3.4.2").then((v) => {
|
|
811
|
+
versions.prettier = v;
|
|
812
|
+
})
|
|
813
|
+
);
|
|
814
|
+
} else if (formatter === "oxfmt") {
|
|
815
|
+
versionPromises.push(
|
|
816
|
+
getLatestNpmVersion("oxfmt", "0.1.0").then((v) => {
|
|
817
|
+
versions.oxfmt = v;
|
|
818
|
+
})
|
|
819
|
+
);
|
|
820
|
+
} else if (formatter === "biome" && linter !== "biome") {
|
|
821
|
+
versionPromises.push(
|
|
822
|
+
getLatestNpmVersion("@biomejs/biome", "1.9.4").then((v) => {
|
|
823
|
+
versions.biome = v;
|
|
824
|
+
})
|
|
825
|
+
);
|
|
826
|
+
}
|
|
827
|
+
await Promise.all(versionPromises);
|
|
828
|
+
packageOptions.versions = versions;
|
|
829
|
+
if (packageType === "app") {
|
|
830
|
+
const workspacePackages = await getWorkspacePackages(monorepoRoot);
|
|
831
|
+
if (workspacePackages.length > 0) {
|
|
832
|
+
const selectedDeps = await p.multiselect({
|
|
833
|
+
message: "Add workspace dependencies?",
|
|
834
|
+
options: workspacePackages.map((pkg2) => ({
|
|
835
|
+
value: pkg2.name,
|
|
836
|
+
label: pkg2.name.replace(/^@[^/]+\//, "")
|
|
837
|
+
})),
|
|
838
|
+
required: false
|
|
839
|
+
});
|
|
840
|
+
if (!p.isCancel(selectedDeps) && selectedDeps.length > 0) {
|
|
841
|
+
packageOptions.workspaceDependencies = selectedDeps;
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
const basePath = join(monorepoRoot, packagePath);
|
|
846
|
+
const s = p.spinner();
|
|
847
|
+
s.start("Creating package...");
|
|
848
|
+
try {
|
|
849
|
+
const files = generate(packageOptions);
|
|
850
|
+
const filePaths = Object.keys(files).sort();
|
|
851
|
+
for (const filePath of filePaths) {
|
|
852
|
+
const fullFilePath = join(basePath, filePath);
|
|
853
|
+
await mkdir(dirname(fullFilePath), { recursive: true });
|
|
854
|
+
const file = files[filePath];
|
|
855
|
+
if (file.type === "text") {
|
|
856
|
+
await writeFile(fullFilePath, file.content);
|
|
857
|
+
} else {
|
|
858
|
+
const response = await fetch(file.url);
|
|
859
|
+
await writeFile(fullFilePath, response.body);
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
s.stop(color.green.inverse(` \u2713 Package created at ${packagePath}! `));
|
|
863
|
+
const addAnother = await p.select({
|
|
864
|
+
message: "Add another package?",
|
|
865
|
+
options: [
|
|
866
|
+
{ value: "no", label: "No, I'm done" },
|
|
867
|
+
{ value: "yes", label: "Yes, add another" }
|
|
868
|
+
],
|
|
869
|
+
initialValue: "no"
|
|
870
|
+
});
|
|
871
|
+
return !p.isCancel(addAnother) && addAnother === "yes";
|
|
872
|
+
} catch (error) {
|
|
873
|
+
s.stop("Failed to create package");
|
|
874
|
+
p.log.error(String(error));
|
|
875
|
+
return false;
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
async function promptAndOpenEditor(basePath) {
|
|
879
|
+
const savedEditor = getPreferredEditor();
|
|
880
|
+
let selectedEditor;
|
|
881
|
+
if (savedEditor && savedEditor !== "skip") {
|
|
882
|
+
const useDefault = await p.confirm({
|
|
883
|
+
message: `Open in editor? ${color.dim(`(${editorNames[savedEditor]})`)}`,
|
|
884
|
+
initialValue: true
|
|
885
|
+
});
|
|
886
|
+
if (p.isCancel(useDefault)) {
|
|
887
|
+
selectedEditor = void 0;
|
|
888
|
+
} else if (useDefault) {
|
|
889
|
+
selectedEditor = savedEditor;
|
|
890
|
+
} else {
|
|
891
|
+
selectedEditor = "skip";
|
|
892
|
+
}
|
|
893
|
+
} else {
|
|
894
|
+
const openEditor = await p.select({
|
|
895
|
+
message: "Open project in editor?",
|
|
896
|
+
options: [
|
|
897
|
+
{ value: "skip", label: "Skip" },
|
|
898
|
+
{ value: "cursor", label: "Cursor" },
|
|
899
|
+
{ value: "code", label: "VS Code" },
|
|
900
|
+
{ value: "webstorm", label: "WebStorm" }
|
|
901
|
+
],
|
|
902
|
+
initialValue: "skip"
|
|
903
|
+
});
|
|
904
|
+
if (!p.isCancel(openEditor)) {
|
|
905
|
+
selectedEditor = openEditor;
|
|
906
|
+
const saveChoice = await p.confirm({
|
|
907
|
+
message: `Save ${editorNames[selectedEditor] ?? "Skip"} as default editor?`,
|
|
908
|
+
initialValue: true
|
|
909
|
+
});
|
|
910
|
+
if (!p.isCancel(saveChoice) && saveChoice) {
|
|
911
|
+
setPreferredEditor(selectedEditor);
|
|
912
|
+
if (selectedEditor === "cursor" || selectedEditor === "code") {
|
|
913
|
+
const reuseChoice = await p.confirm({
|
|
914
|
+
message: "Reuse current window when opening projects?",
|
|
915
|
+
initialValue: false
|
|
916
|
+
});
|
|
917
|
+
if (!p.isCancel(reuseChoice)) {
|
|
918
|
+
setReuseWindow(reuseChoice);
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
if (selectedEditor && selectedEditor !== "skip") {
|
|
925
|
+
try {
|
|
926
|
+
await openInEditor(
|
|
927
|
+
selectedEditor,
|
|
928
|
+
basePath,
|
|
929
|
+
getReuseWindow()
|
|
930
|
+
);
|
|
931
|
+
p.log.success(`Opening in ${editorNames[selectedEditor]}...`);
|
|
932
|
+
} catch {
|
|
933
|
+
p.log.warn(
|
|
934
|
+
`Could not open ${editorNames[selectedEditor]}. Make sure the CLI command is in your PATH.`
|
|
935
|
+
);
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
}
|
|
611
939
|
async function main() {
|
|
612
940
|
const program = new Command().name("create-krispya").description("CLI for creating Vanilla, React, and React Three Fiber projects").argument("[name]", "name for the project").option("--type <type>", "project type: app or library (default: app)").option(
|
|
613
941
|
"--bundler <bundler>",
|
|
@@ -624,12 +952,16 @@ async function main() {
|
|
|
624
952
|
).option(
|
|
625
953
|
"--node-version <version>",
|
|
626
954
|
'set Node.js version for engines.node field (default: "latest")'
|
|
627
|
-
).option("-y, --yes", "Skip prompts and use default values").option("--clear-config", "Clear saved preferences (e.g. editor choice)").action(async (name, options) => {
|
|
955
|
+
).option("-y, --yes", "Skip prompts and use default values").option("--clear-config", "Clear saved preferences (e.g. editor choice)").option("--config-path", "Print the path to the config file").action(async (name, options) => {
|
|
628
956
|
if (options.clearConfig) {
|
|
629
957
|
clearConfig();
|
|
630
958
|
console.log("Configuration cleared.");
|
|
631
959
|
process.exit(0);
|
|
632
960
|
}
|
|
961
|
+
if (options.configPath) {
|
|
962
|
+
console.log(getConfigPath());
|
|
963
|
+
process.exit(0);
|
|
964
|
+
}
|
|
633
965
|
console.clear();
|
|
634
966
|
p.intro(color.bgCyan(color.black(` create-krispya v${pkg.version} `)));
|
|
635
967
|
const monorepoRoot = await detectMonorepoRoot();
|
|
@@ -647,132 +979,26 @@ async function main() {
|
|
|
647
979
|
process.exit(0);
|
|
648
980
|
}
|
|
649
981
|
if (choice === "add") {
|
|
650
|
-
const
|
|
651
|
-
if (
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
placeholder: packageType === "app" ? "my-app" : "my-package",
|
|
658
|
-
validate: (value) => {
|
|
659
|
-
if (!value.length) return "Package name is required";
|
|
660
|
-
}
|
|
661
|
-
});
|
|
662
|
-
if (p.isCancel(packageName)) {
|
|
663
|
-
p.cancel("Operation cancelled.");
|
|
664
|
-
process.exit(0);
|
|
665
|
-
}
|
|
666
|
-
const targetDir = packageType === "app" ? "apps" : "packages";
|
|
667
|
-
const packagePath = join(targetDir, packageName);
|
|
668
|
-
const workspaceRoot = "../..";
|
|
669
|
-
const packageOptions = await promptForPackageOptions(packageName, packageType);
|
|
670
|
-
packageOptions.workspaceRoot = workspaceRoot;
|
|
671
|
-
packageOptions.name = packageName;
|
|
672
|
-
const packageManager2 = packageOptions.packageManager || "pnpm";
|
|
673
|
-
if (packageManager2 === "pnpm") {
|
|
674
|
-
packageOptions.pnpmVersion = await getLatestPnpmVersion();
|
|
675
|
-
}
|
|
676
|
-
const nodeVersion2 = packageOptions.nodeVersion ?? "latest";
|
|
677
|
-
if (nodeVersion2 === "latest") {
|
|
678
|
-
packageOptions.nodeVersion = await getLatestNodeVersion();
|
|
679
|
-
}
|
|
680
|
-
const versions2 = {};
|
|
681
|
-
const versionPromises2 = [];
|
|
682
|
-
const pkgIsLibrary = packageOptions.projectType === "library";
|
|
683
|
-
const pkgTesting = packageOptions.testing ?? (pkgIsLibrary ? "vitest" : "none");
|
|
684
|
-
if (pkgTesting === "vitest") {
|
|
685
|
-
versionPromises2.push(
|
|
686
|
-
getLatestNpmVersion("vitest", "4.0.0").then((v) => {
|
|
687
|
-
versions2.vitest = v;
|
|
688
|
-
})
|
|
689
|
-
);
|
|
690
|
-
}
|
|
691
|
-
if (!pkgIsLibrary) {
|
|
692
|
-
versionPromises2.push(
|
|
693
|
-
getLatestNpmVersion("vite", "6.3.4").then((v) => {
|
|
694
|
-
versions2.vite = v;
|
|
695
|
-
})
|
|
696
|
-
);
|
|
982
|
+
const inheritedTooling = await detectWorkspaceTooling(monorepoRoot);
|
|
983
|
+
if (inheritedTooling.linter || inheritedTooling.formatter) {
|
|
984
|
+
const toolingInfo = [
|
|
985
|
+
inheritedTooling.linter && `linter: ${inheritedTooling.linter}`,
|
|
986
|
+
inheritedTooling.formatter && `formatter: ${inheritedTooling.formatter}`
|
|
987
|
+
].filter(Boolean).join(", ");
|
|
988
|
+
p.log.info(`Using workspace tooling (${toolingInfo})`);
|
|
697
989
|
}
|
|
698
|
-
const
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
versions2.eslint = v;
|
|
703
|
-
})
|
|
704
|
-
);
|
|
705
|
-
} else if (linter2 === "oxlint") {
|
|
706
|
-
versionPromises2.push(
|
|
707
|
-
getLatestNpmVersion("oxlint", "0.16.0").then((v) => {
|
|
708
|
-
versions2.oxlint = v;
|
|
709
|
-
})
|
|
710
|
-
);
|
|
711
|
-
} else if (linter2 === "biome") {
|
|
712
|
-
versionPromises2.push(
|
|
713
|
-
getLatestNpmVersion("@biomejs/biome", "1.9.4").then((v) => {
|
|
714
|
-
versions2.biome = v;
|
|
715
|
-
})
|
|
716
|
-
);
|
|
717
|
-
}
|
|
718
|
-
const formatter2 = packageOptions.formatter ?? "oxfmt";
|
|
719
|
-
if (formatter2 === "prettier") {
|
|
720
|
-
versionPromises2.push(
|
|
721
|
-
getLatestNpmVersion("prettier", "3.4.2").then((v) => {
|
|
722
|
-
versions2.prettier = v;
|
|
723
|
-
})
|
|
724
|
-
);
|
|
725
|
-
} else if (formatter2 === "oxfmt") {
|
|
726
|
-
versionPromises2.push(
|
|
727
|
-
getLatestNpmVersion("oxfmt", "0.1.0").then((v) => {
|
|
728
|
-
versions2.oxfmt = v;
|
|
729
|
-
})
|
|
730
|
-
);
|
|
731
|
-
} else if (formatter2 === "biome" && linter2 !== "biome") {
|
|
732
|
-
versionPromises2.push(
|
|
733
|
-
getLatestNpmVersion("@biomejs/biome", "1.9.4").then((v) => {
|
|
734
|
-
versions2.biome = v;
|
|
735
|
-
})
|
|
736
|
-
);
|
|
737
|
-
}
|
|
738
|
-
await Promise.all(versionPromises2);
|
|
739
|
-
packageOptions.versions = versions2;
|
|
740
|
-
const basePath2 = join(monorepoRoot, packagePath);
|
|
741
|
-
const s2 = p.spinner();
|
|
742
|
-
s2.start("Creating package...");
|
|
743
|
-
try {
|
|
744
|
-
const files = generate(packageOptions);
|
|
745
|
-
const filePaths = Object.keys(files).sort();
|
|
746
|
-
for (const filePath of filePaths) {
|
|
747
|
-
const fullFilePath = join(basePath2, filePath);
|
|
748
|
-
await mkdir(dirname(fullFilePath), { recursive: true });
|
|
749
|
-
const file = files[filePath];
|
|
750
|
-
if (file.type === "text") {
|
|
751
|
-
await writeFile(fullFilePath, file.content);
|
|
752
|
-
} else {
|
|
753
|
-
const response = await fetch(file.url);
|
|
754
|
-
await writeFile(fullFilePath, response.body);
|
|
755
|
-
}
|
|
756
|
-
}
|
|
757
|
-
s2.stop("Package created!");
|
|
758
|
-
const isLibrary2 = packageOptions.projectType === "library";
|
|
759
|
-
const nextSteps = isLibrary2 ? [
|
|
760
|
-
`cd ${packagePath}`,
|
|
761
|
-
`${packageManager2} install`,
|
|
762
|
-
`${packageManager2} run build`
|
|
763
|
-
].join("\n") : [
|
|
764
|
-
`cd ${packagePath}`,
|
|
765
|
-
`${packageManager2} install`,
|
|
766
|
-
`${packageManager2} run dev`
|
|
767
|
-
].join("\n");
|
|
768
|
-
p.note(nextSteps, "Next steps");
|
|
769
|
-
p.outro(color.green("Happy coding! \u2728"));
|
|
770
|
-
process.exit(0);
|
|
771
|
-
} catch (error) {
|
|
772
|
-
s2.stop("Failed to create package");
|
|
773
|
-
p.log.error(String(error));
|
|
774
|
-
process.exit(1);
|
|
990
|
+
const scope = await getMonorepoScope(monorepoRoot);
|
|
991
|
+
let addMore = true;
|
|
992
|
+
while (addMore) {
|
|
993
|
+
addMore = await createPackageInWorkspace(monorepoRoot, "pnpm", inheritedTooling, scope);
|
|
775
994
|
}
|
|
995
|
+
p.note(
|
|
996
|
+
[`cd ${monorepoRoot}`, "pnpm install", "pnpm run dev"].join("\n"),
|
|
997
|
+
"Next steps"
|
|
998
|
+
);
|
|
999
|
+
await promptAndOpenEditor(monorepoRoot);
|
|
1000
|
+
p.outro(color.green("Happy coding! \u2728"));
|
|
1001
|
+
process.exit(0);
|
|
776
1002
|
}
|
|
777
1003
|
}
|
|
778
1004
|
let generateOptions;
|
|
@@ -841,60 +1067,15 @@ async function main() {
|
|
|
841
1067
|
await writeFile(fullFilePath, file.content);
|
|
842
1068
|
}
|
|
843
1069
|
}
|
|
844
|
-
s2.stop("Monorepo workspace created!");
|
|
845
|
-
const
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
});
|
|
854
|
-
if (!p.isCancel(packageName)) {
|
|
855
|
-
const targetDir = initialPackage === "app" ? "apps" : "packages";
|
|
856
|
-
const packagePath = join(targetDir, packageName);
|
|
857
|
-
const packageOptions = await promptForPackageOptions(packageName, initialPackage);
|
|
858
|
-
packageOptions.workspaceRoot = "../..";
|
|
859
|
-
packageOptions.name = packageName;
|
|
860
|
-
const pkgManager = packageOptions.packageManager || "pnpm";
|
|
861
|
-
const versions2 = {};
|
|
862
|
-
const versionPromises2 = [];
|
|
863
|
-
const initPkgIsLibrary = packageOptions.projectType === "library";
|
|
864
|
-
const initPkgTesting = packageOptions.testing ?? (initPkgIsLibrary ? "vitest" : "none");
|
|
865
|
-
if (initPkgTesting === "vitest") {
|
|
866
|
-
versionPromises2.push(
|
|
867
|
-
getLatestNpmVersion("vitest", "4.0.0").then((v) => {
|
|
868
|
-
versions2.vitest = v;
|
|
869
|
-
})
|
|
870
|
-
);
|
|
871
|
-
}
|
|
872
|
-
if (!initPkgIsLibrary) {
|
|
873
|
-
versionPromises2.push(
|
|
874
|
-
getLatestNpmVersion("vite", "6.3.4").then((v) => {
|
|
875
|
-
versions2.vite = v;
|
|
876
|
-
})
|
|
877
|
-
);
|
|
878
|
-
}
|
|
879
|
-
await Promise.all(versionPromises2);
|
|
880
|
-
packageOptions.versions = versions2;
|
|
881
|
-
s2.start("Creating initial package...");
|
|
882
|
-
const packageFiles = generate(packageOptions);
|
|
883
|
-
const packageFilePaths = Object.keys(packageFiles).sort();
|
|
884
|
-
const packageBasePath = join(basePath2, packagePath);
|
|
885
|
-
for (const filePath of packageFilePaths) {
|
|
886
|
-
const fullFilePath = join(packageBasePath, filePath);
|
|
887
|
-
await mkdir(dirname(fullFilePath), { recursive: true });
|
|
888
|
-
const file = packageFiles[filePath];
|
|
889
|
-
if (file.type === "text") {
|
|
890
|
-
await writeFile(fullFilePath, file.content);
|
|
891
|
-
} else {
|
|
892
|
-
const response = await fetch(file.url);
|
|
893
|
-
await writeFile(fullFilePath, response.body);
|
|
894
|
-
}
|
|
895
|
-
}
|
|
896
|
-
s2.stop("Initial package created!");
|
|
897
|
-
}
|
|
1070
|
+
s2.stop(color.green.inverse(" \u2713 Monorepo workspace created! "));
|
|
1071
|
+
const newMonorepoTooling = {
|
|
1072
|
+
linter: generateOptions.linter,
|
|
1073
|
+
formatter: generateOptions.formatter
|
|
1074
|
+
};
|
|
1075
|
+
const scope = generateOptions.name;
|
|
1076
|
+
let addMore = true;
|
|
1077
|
+
while (addMore) {
|
|
1078
|
+
addMore = await createPackageInWorkspace(basePath2, packageManager2, newMonorepoTooling, scope);
|
|
898
1079
|
}
|
|
899
1080
|
const nextSteps = [
|
|
900
1081
|
`cd ${generateOptions.name}`,
|
|
@@ -902,6 +1083,7 @@ async function main() {
|
|
|
902
1083
|
`${packageManager2} run dev`
|
|
903
1084
|
].join("\n");
|
|
904
1085
|
p.note(nextSteps, "Next steps");
|
|
1086
|
+
await promptAndOpenEditor(basePath2);
|
|
905
1087
|
p.outro(color.green("Happy coding! \u2728"));
|
|
906
1088
|
process.exit(0);
|
|
907
1089
|
} catch (error) {
|
|
@@ -998,7 +1180,7 @@ async function main() {
|
|
|
998
1180
|
await writeFile(fullFilePath, response.body);
|
|
999
1181
|
}
|
|
1000
1182
|
}
|
|
1001
|
-
s.stop("Project created!");
|
|
1183
|
+
s.stop(color.green.inverse(" \u2713 Project created! "));
|
|
1002
1184
|
const isLibrary2 = generateOptions.projectType === "library";
|
|
1003
1185
|
const nextSteps = isLibrary2 ? [
|
|
1004
1186
|
`cd ${generateOptions.name}`,
|