create-esa-stack 0.1.0 → 0.1.2
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/cli.js +36 -435
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -367,9 +367,6 @@ function hD(e, u) {
|
|
|
367
367
|
return s;
|
|
368
368
|
}
|
|
369
369
|
var V = Symbol("clack:cancel");
|
|
370
|
-
function lD(e) {
|
|
371
|
-
return e === V;
|
|
372
|
-
}
|
|
373
370
|
function v(e, u) {
|
|
374
371
|
e.isTTY && e.setRawMode(u);
|
|
375
372
|
}
|
|
@@ -603,19 +600,6 @@ ${import_picocolors2.default.cyan($2)}
|
|
|
603
600
|
}
|
|
604
601
|
} }).prompt();
|
|
605
602
|
};
|
|
606
|
-
var R2 = (s) => s.replace(ye(), "");
|
|
607
|
-
var me = (s = "", n = "") => {
|
|
608
|
-
const t = `
|
|
609
|
-
${s}
|
|
610
|
-
`.split(`
|
|
611
|
-
`), i = R2(n).length, r2 = Math.max(t.reduce((c2, l2) => (l2 = R2(l2), l2.length > c2 ? l2.length : c2), 0), i) + 2, o = t.map((c2) => `${import_picocolors2.default.gray(a2)} ${import_picocolors2.default.dim(c2)}${" ".repeat(r2 - R2(c2).length)}${import_picocolors2.default.gray(a2)}`).join(`
|
|
612
|
-
`);
|
|
613
|
-
process.stdout.write(`${import_picocolors2.default.gray(a2)}
|
|
614
|
-
${import_picocolors2.default.green(M2)} ${import_picocolors2.default.reset(n)} ${import_picocolors2.default.gray(G.repeat(Math.max(r2 - i - 1, 1)) + H)}
|
|
615
|
-
${o}
|
|
616
|
-
${import_picocolors2.default.gray(ee + G.repeat(r2 + 2) + te)}
|
|
617
|
-
`);
|
|
618
|
-
};
|
|
619
603
|
var he = (s = "") => {
|
|
620
604
|
process.stdout.write(`${import_picocolors2.default.gray($2)} ${import_picocolors2.default.red(s)}
|
|
621
605
|
|
|
@@ -631,29 +615,6 @@ ${import_picocolors2.default.gray($2)} ${s}
|
|
|
631
615
|
|
|
632
616
|
`);
|
|
633
617
|
};
|
|
634
|
-
var v2 = { message: (s = "", { symbol: n = import_picocolors2.default.gray(a2) } = {}) => {
|
|
635
|
-
const t = [`${import_picocolors2.default.gray(a2)}`];
|
|
636
|
-
if (s) {
|
|
637
|
-
const [i, ...r2] = s.split(`
|
|
638
|
-
`);
|
|
639
|
-
t.push(`${n} ${i}`, ...r2.map((o) => `${import_picocolors2.default.gray(a2)} ${o}`));
|
|
640
|
-
}
|
|
641
|
-
process.stdout.write(`${t.join(`
|
|
642
|
-
`)}
|
|
643
|
-
`);
|
|
644
|
-
}, info: (s) => {
|
|
645
|
-
v2.message(s, { symbol: import_picocolors2.default.blue(se) });
|
|
646
|
-
}, success: (s) => {
|
|
647
|
-
v2.message(s, { symbol: import_picocolors2.default.green(re) });
|
|
648
|
-
}, step: (s) => {
|
|
649
|
-
v2.message(s, { symbol: import_picocolors2.default.green(M2) });
|
|
650
|
-
}, warn: (s) => {
|
|
651
|
-
v2.message(s, { symbol: import_picocolors2.default.yellow(ie) });
|
|
652
|
-
}, warning: (s) => {
|
|
653
|
-
v2.warn(s);
|
|
654
|
-
}, error: (s) => {
|
|
655
|
-
v2.message(s, { symbol: import_picocolors2.default.red(ne) });
|
|
656
|
-
} };
|
|
657
618
|
var _2 = () => {
|
|
658
619
|
const s = C ? ["◒", "◐", "◓", "◑"] : ["•", "o", "O", "0"], n = C ? 80 : 120;
|
|
659
620
|
let t, i, r2 = false, o = "";
|
|
@@ -682,414 +643,54 @@ var _2 = () => {
|
|
|
682
643
|
o = g2 ?? o;
|
|
683
644
|
} };
|
|
684
645
|
};
|
|
685
|
-
function ye() {
|
|
686
|
-
const s = ["[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)", "(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))"].join("|");
|
|
687
|
-
return new RegExp(s, "g");
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
// src/utils/process.ts
|
|
691
|
-
import { spawn } from "child_process";
|
|
692
|
-
async function executeCommand(command, args, options = {}) {
|
|
693
|
-
return new Promise((resolve) => {
|
|
694
|
-
const child = spawn(command, args, {
|
|
695
|
-
cwd: options.cwd || process.cwd(),
|
|
696
|
-
env: { ...process.env, ...options.env },
|
|
697
|
-
stdio: "inherit"
|
|
698
|
-
});
|
|
699
|
-
let output = "";
|
|
700
|
-
let errorOutput = "";
|
|
701
|
-
child.on("close", (code) => {
|
|
702
|
-
resolve({
|
|
703
|
-
success: code === 0,
|
|
704
|
-
code,
|
|
705
|
-
output,
|
|
706
|
-
error: errorOutput || undefined
|
|
707
|
-
});
|
|
708
|
-
});
|
|
709
|
-
child.on("error", (error) => {
|
|
710
|
-
resolve({
|
|
711
|
-
success: false,
|
|
712
|
-
code: null,
|
|
713
|
-
output,
|
|
714
|
-
error: error.message
|
|
715
|
-
});
|
|
716
|
-
});
|
|
717
|
-
});
|
|
718
|
-
}
|
|
719
|
-
async function runCreateNextApp(projectName, options = {}) {
|
|
720
|
-
const args = [
|
|
721
|
-
"create-next-app@latest",
|
|
722
|
-
projectName,
|
|
723
|
-
"--ts",
|
|
724
|
-
"--tailwind",
|
|
725
|
-
"--biome",
|
|
726
|
-
"--react-compiler",
|
|
727
|
-
"--app",
|
|
728
|
-
"--use-pnpm",
|
|
729
|
-
"--turbopack",
|
|
730
|
-
"--yes"
|
|
731
|
-
];
|
|
732
|
-
return executeCommand("npx", args, options);
|
|
733
|
-
}
|
|
734
|
-
|
|
735
|
-
// src/generators/nextjs.ts
|
|
736
|
-
async function generateNextJsProject(config) {
|
|
737
|
-
const s = _2();
|
|
738
|
-
s.start(`Creating Next.js project: ${config.projectName}...`);
|
|
739
|
-
try {
|
|
740
|
-
const result = await runCreateNextApp(config.projectName);
|
|
741
|
-
if (result.success) {
|
|
742
|
-
s.stop(`✓ Project created successfully!`);
|
|
743
|
-
return true;
|
|
744
|
-
} else {
|
|
745
|
-
s.stop(`✗ Failed to create project`);
|
|
746
|
-
if (result.error) {
|
|
747
|
-
v2.error(result.error);
|
|
748
|
-
}
|
|
749
|
-
return false;
|
|
750
|
-
}
|
|
751
|
-
} catch (error) {
|
|
752
|
-
s.stop(`✗ Failed to create project`);
|
|
753
|
-
v2.error(error instanceof Error ? error.message : "Unknown error occurred");
|
|
754
|
-
return false;
|
|
755
|
-
}
|
|
756
|
-
}
|
|
757
|
-
|
|
758
|
-
// src/generators/react-query.ts
|
|
759
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
760
|
-
import { join } from "path";
|
|
761
|
-
async function setupReactQuery(config) {
|
|
762
|
-
const s = _2();
|
|
763
|
-
s.start("Setting up @tanstack/react-query...");
|
|
764
|
-
try {
|
|
765
|
-
const projectPath = config.projectPath;
|
|
766
|
-
s.message("Installing @tanstack/react-query...");
|
|
767
|
-
const installResult = await executeCommand("pnpm", ["add", "@tanstack/react-query"], { cwd: projectPath });
|
|
768
|
-
if (!installResult.success) {
|
|
769
|
-
s.stop("✗ Failed to install @tanstack/react-query");
|
|
770
|
-
return false;
|
|
771
|
-
}
|
|
772
|
-
s.message("Creating RootProviders component...");
|
|
773
|
-
const providersDir = join(projectPath, "src", "components", "templates", "RootProviders");
|
|
774
|
-
if (!existsSync(providersDir)) {
|
|
775
|
-
mkdirSync(providersDir, { recursive: true });
|
|
776
|
-
}
|
|
777
|
-
const providersPath = join(providersDir, "RootProviders.component.tsx");
|
|
778
|
-
const providersTemplate = `'use client'
|
|
779
|
-
|
|
780
|
-
// Since QueryClientProvider relies on useContext under the hood, we have to put 'use client' on top
|
|
781
|
-
import {
|
|
782
|
-
isServer,
|
|
783
|
-
QueryClient,
|
|
784
|
-
QueryClientProvider,
|
|
785
|
-
} from '@tanstack/react-query'
|
|
786
|
-
import { useState } from 'react'
|
|
787
|
-
|
|
788
|
-
function makeQueryClient() {
|
|
789
|
-
return new QueryClient({
|
|
790
|
-
defaultOptions: {
|
|
791
|
-
queries: {
|
|
792
|
-
// With SSR, we usually want to set some default staleTime
|
|
793
|
-
// above 0 to avoid refetching immediately on the client
|
|
794
|
-
staleTime: 60 * 1000,
|
|
795
|
-
},
|
|
796
|
-
},
|
|
797
|
-
})
|
|
798
|
-
}
|
|
799
|
-
|
|
800
|
-
let browserQueryClient: QueryClient | undefined = undefined
|
|
801
|
-
|
|
802
|
-
function getQueryClient() {
|
|
803
|
-
if (isServer) {
|
|
804
|
-
// Server: always make a new query client
|
|
805
|
-
return makeQueryClient()
|
|
806
|
-
} else {
|
|
807
|
-
// Browser: make a new query client if we don't already have one
|
|
808
|
-
// This is very important, so we don't re-make a new client if React
|
|
809
|
-
// suspends during the initial render. This may not be needed if we
|
|
810
|
-
// have a suspense boundary BELOW the creation of the query client
|
|
811
|
-
if (!browserQueryClient) browserQueryClient = makeQueryClient()
|
|
812
|
-
return browserQueryClient
|
|
813
|
-
}
|
|
814
|
-
}
|
|
815
|
-
|
|
816
|
-
export default function RootProviders({ children }: { children: React.ReactNode }) {
|
|
817
|
-
// NOTE: Avoid useState when initializing the query client if you don't
|
|
818
|
-
// have a suspense boundary between this and the code that may
|
|
819
|
-
// suspend because React will throw away the client on the initial
|
|
820
|
-
// render if it suspends and there is no boundary
|
|
821
|
-
const queryClient = getQueryClient()
|
|
822
|
-
|
|
823
|
-
return (
|
|
824
|
-
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
|
|
825
|
-
)
|
|
826
|
-
}
|
|
827
|
-
`;
|
|
828
|
-
writeFileSync(providersPath, providersTemplate);
|
|
829
|
-
s.message("Updating root layout...");
|
|
830
|
-
const layoutPath = join(projectPath, "src", "app", "layout.tsx");
|
|
831
|
-
if (existsSync(layoutPath)) {
|
|
832
|
-
let layoutContent = readFileSync(layoutPath, "utf-8");
|
|
833
|
-
const importStatement = `import RootProviders from "@/components/templates/RootProviders/RootProviders.component";
|
|
834
|
-
`;
|
|
835
|
-
if (!layoutContent.includes("RootProviders")) {
|
|
836
|
-
const importRegex = /(import.*from.*;\n)+/;
|
|
837
|
-
layoutContent = layoutContent.replace(importRegex, (match) => match + importStatement);
|
|
838
|
-
layoutContent = layoutContent.replace(/(<body[^>]*>)([\s\S]*?)(<\/body>)/, (match, openTag, content, closeTag) => {
|
|
839
|
-
if (content.includes("<RootProviders>")) {
|
|
840
|
-
return match;
|
|
841
|
-
}
|
|
842
|
-
return `${openTag}
|
|
843
|
-
<RootProviders>${content}</RootProviders>
|
|
844
|
-
${closeTag}`;
|
|
845
|
-
});
|
|
846
|
-
writeFileSync(layoutPath, layoutContent);
|
|
847
|
-
}
|
|
848
|
-
}
|
|
849
|
-
s.stop("✓ React Query setup complete!");
|
|
850
|
-
return true;
|
|
851
|
-
} catch (error) {
|
|
852
|
-
s.stop("✗ Failed to set up React Query");
|
|
853
|
-
v2.error(error instanceof Error ? error.message : "Unknown error occurred");
|
|
854
|
-
return false;
|
|
855
|
-
}
|
|
856
|
-
}
|
|
857
|
-
|
|
858
|
-
// src/generators/resend.ts
|
|
859
|
-
async function setupResend(config) {
|
|
860
|
-
const s = _2();
|
|
861
|
-
s.start("Setting up Resend...");
|
|
862
|
-
try {
|
|
863
|
-
const projectPath = config.projectPath;
|
|
864
|
-
s.message("Installing resend package...");
|
|
865
|
-
const result = await executeCommand("pnpm", ["add", "resend"], { cwd: projectPath });
|
|
866
|
-
if (result.success) {
|
|
867
|
-
s.stop("✓ Resend setup complete!");
|
|
868
|
-
return true;
|
|
869
|
-
} else {
|
|
870
|
-
s.stop("✗ Failed to install Resend");
|
|
871
|
-
if (result.error) {
|
|
872
|
-
v2.error(result.error);
|
|
873
|
-
}
|
|
874
|
-
return false;
|
|
875
|
-
}
|
|
876
|
-
} catch (error) {
|
|
877
|
-
s.stop("✗ Failed to set up Resend");
|
|
878
|
-
v2.error(error instanceof Error ? error.message : "Unknown error occurred");
|
|
879
|
-
return false;
|
|
880
|
-
}
|
|
881
|
-
}
|
|
882
646
|
|
|
883
|
-
// src/
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
s.message("Running shadcn init...");
|
|
890
|
-
const result = await executeCommand("pnpm", ["dlx", "shadcn@latest", "init", "-y"], { cwd: projectPath });
|
|
891
|
-
if (result.success) {
|
|
892
|
-
s.stop("✓ shadcn/ui setup complete!");
|
|
893
|
-
return true;
|
|
894
|
-
} else {
|
|
895
|
-
s.stop("✗ Failed to set up shadcn/ui");
|
|
896
|
-
if (result.error) {
|
|
897
|
-
v2.error(result.error);
|
|
898
|
-
}
|
|
899
|
-
return false;
|
|
900
|
-
}
|
|
901
|
-
} catch (error) {
|
|
902
|
-
s.stop("✗ Failed to set up shadcn/ui");
|
|
903
|
-
v2.error(error instanceof Error ? error.message : "Unknown error occurred");
|
|
904
|
-
return false;
|
|
905
|
-
}
|
|
906
|
-
}
|
|
907
|
-
|
|
908
|
-
// src/utils/file-system.ts
|
|
909
|
-
import { join as join2, resolve } from "path";
|
|
910
|
-
function resolvePath(path) {
|
|
911
|
-
return resolve(process.cwd(), path);
|
|
912
|
-
}
|
|
913
|
-
function getProjectPath(projectName, targetDir) {
|
|
914
|
-
if (targetDir) {
|
|
915
|
-
return resolvePath(join2(targetDir, projectName));
|
|
916
|
-
}
|
|
917
|
-
return resolvePath(projectName);
|
|
918
|
-
}
|
|
919
|
-
|
|
920
|
-
// src/utils/validators.ts
|
|
921
|
-
import { existsSync as existsSync2 } from "fs";
|
|
922
|
-
function isValidProjectName(name) {
|
|
923
|
-
const validNameRegex = /^(?![@._])[a-z0-9-_]+$/;
|
|
924
|
-
if (!name || name.length === 0) {
|
|
925
|
-
return false;
|
|
926
|
-
}
|
|
927
|
-
if (name.length > 214) {
|
|
928
|
-
return false;
|
|
929
|
-
}
|
|
930
|
-
return validNameRegex.test(name);
|
|
931
|
-
}
|
|
932
|
-
function getProjectNameValidationMessage(name) {
|
|
933
|
-
if (!name || name.length === 0) {
|
|
934
|
-
return "Project name cannot be empty";
|
|
935
|
-
}
|
|
936
|
-
if (name.length > 214) {
|
|
937
|
-
return "Project name must be 214 characters or less";
|
|
938
|
-
}
|
|
939
|
-
if (name.startsWith(".") || name.startsWith("_")) {
|
|
940
|
-
return "Project name cannot start with . or _";
|
|
941
|
-
}
|
|
942
|
-
if (!/^[a-z0-9-_]+$/.test(name)) {
|
|
943
|
-
return "Project name can only contain lowercase letters, numbers, hyphens, and underscores";
|
|
944
|
-
}
|
|
945
|
-
return "Invalid project name";
|
|
946
|
-
}
|
|
947
|
-
function directoryExists(path) {
|
|
948
|
-
return existsSync2(path);
|
|
949
|
-
}
|
|
950
|
-
|
|
951
|
-
// src/prompts.ts
|
|
952
|
-
async function promptForProjectConfig() {
|
|
953
|
-
console.log("");
|
|
954
|
-
pe("\uD83D\uDE80 Create ESA Stack");
|
|
647
|
+
// src/cli.ts
|
|
648
|
+
import { execSync } from "node:child_process";
|
|
649
|
+
import { existsSync } from "node:fs";
|
|
650
|
+
import { join } from "node:path";
|
|
651
|
+
async function main() {
|
|
652
|
+
pe("Welcome to ESA Stack Generator");
|
|
955
653
|
const projectName = await ae({
|
|
956
|
-
message: "What is your project
|
|
957
|
-
placeholder: "my-
|
|
958
|
-
validate
|
|
959
|
-
if (
|
|
960
|
-
return
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
});
|
|
964
|
-
if (lD(projectName)) {
|
|
965
|
-
he("Operation cancelled");
|
|
966
|
-
return null;
|
|
967
|
-
}
|
|
968
|
-
const projectPath = getProjectPath(projectName);
|
|
969
|
-
if (directoryExists(projectPath)) {
|
|
970
|
-
const shouldContinue = await ce({
|
|
971
|
-
message: `Directory "${projectName}" already exists. Continue anyway?`,
|
|
972
|
-
initialValue: false
|
|
973
|
-
});
|
|
974
|
-
if (lD(shouldContinue) || !shouldContinue) {
|
|
975
|
-
he("Operation cancelled");
|
|
976
|
-
return null;
|
|
654
|
+
message: "What is the name of your project?",
|
|
655
|
+
placeholder: "my-app",
|
|
656
|
+
validate(value) {
|
|
657
|
+
if (value.length === 0)
|
|
658
|
+
return "Project name is required";
|
|
659
|
+
if (existsSync(join(process.cwd(), value)))
|
|
660
|
+
return "Directory already exists";
|
|
977
661
|
}
|
|
978
|
-
}
|
|
979
|
-
console.log("");
|
|
980
|
-
me("Select optional integrations to add to your project", "Optional Integrations");
|
|
981
|
-
const reactQuery = await ce({
|
|
982
|
-
message: "Add @tanstack/react-query for data fetching?",
|
|
983
|
-
initialValue: true
|
|
984
662
|
});
|
|
985
|
-
if (
|
|
986
|
-
he("Operation cancelled");
|
|
987
|
-
|
|
663
|
+
if (typeof projectName === "symbol") {
|
|
664
|
+
he("Operation cancelled.");
|
|
665
|
+
process.exit(0);
|
|
988
666
|
}
|
|
989
|
-
const
|
|
990
|
-
message: "
|
|
667
|
+
const installShadcn = await ce({
|
|
668
|
+
message: "Do you want to install shadcn/ui?",
|
|
991
669
|
initialValue: true
|
|
992
670
|
});
|
|
993
|
-
if (
|
|
994
|
-
he("Operation cancelled");
|
|
995
|
-
|
|
996
|
-
}
|
|
997
|
-
const resend = await ce({
|
|
998
|
-
message: "Add Resend for email API?",
|
|
999
|
-
initialValue: false
|
|
1000
|
-
});
|
|
1001
|
-
if (lD(resend)) {
|
|
1002
|
-
he("Operation cancelled");
|
|
1003
|
-
return null;
|
|
671
|
+
if (typeof installShadcn === "symbol") {
|
|
672
|
+
he("Operation cancelled.");
|
|
673
|
+
process.exit(0);
|
|
1004
674
|
}
|
|
1005
|
-
const integrations = {
|
|
1006
|
-
reactQuery,
|
|
1007
|
-
shadcn,
|
|
1008
|
-
resend
|
|
1009
|
-
};
|
|
1010
675
|
const s = _2();
|
|
1011
|
-
s.start("
|
|
1012
|
-
|
|
1013
|
-
s.stop("Configuration ready!");
|
|
1014
|
-
const integrationsText = [
|
|
1015
|
-
integrations.reactQuery && " ✓ @tanstack/react-query",
|
|
1016
|
-
integrations.shadcn && " ✓ shadcn/ui",
|
|
1017
|
-
integrations.resend && " ✓ resend"
|
|
1018
|
-
].filter(Boolean).join(`
|
|
1019
|
-
`);
|
|
1020
|
-
console.log("");
|
|
1021
|
-
me(`Project: ${projectName}
|
|
1022
|
-
Path: ${projectPath}
|
|
1023
|
-
|
|
1024
|
-
Default Tech Stack:
|
|
1025
|
-
✓ Next.js (App Router)
|
|
1026
|
-
✓ TypeScript
|
|
1027
|
-
✓ Tailwind CSS
|
|
1028
|
-
✓ Biome.js
|
|
1029
|
-
✓ React Compiler
|
|
1030
|
-
✓ Turbopack
|
|
1031
|
-
✓ pnpm${integrationsText ? `
|
|
1032
|
-
|
|
1033
|
-
Optional Integrations:
|
|
1034
|
-
${integrationsText}` : ""}`, "Configuration");
|
|
1035
|
-
const shouldProceed = await ce({
|
|
1036
|
-
message: "Create project with this configuration?",
|
|
1037
|
-
initialValue: true
|
|
1038
|
-
});
|
|
1039
|
-
if (lD(shouldProceed) || !shouldProceed) {
|
|
1040
|
-
he("Operation cancelled");
|
|
1041
|
-
return null;
|
|
1042
|
-
}
|
|
1043
|
-
return {
|
|
1044
|
-
projectName,
|
|
1045
|
-
projectPath,
|
|
1046
|
-
integrations
|
|
1047
|
-
};
|
|
1048
|
-
}
|
|
1049
|
-
|
|
1050
|
-
// src/cli.ts
|
|
1051
|
-
async function main() {
|
|
676
|
+
s.start("Scaffolding project...");
|
|
677
|
+
const command = `npx create-next-app@latest ${projectName} --biome --ts --tailwind --react-compiler --app --src-dir --import-alias "@/*" --use-pnpm --turbopack --skip-install --yes`;
|
|
1052
678
|
try {
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
const reactQuerySuccess = await setupReactQuery(config);
|
|
1064
|
-
if (!reactQuerySuccess) {
|
|
1065
|
-
v2.warn("React Query setup failed, but project was created successfully");
|
|
1066
|
-
}
|
|
1067
|
-
}
|
|
1068
|
-
if (config.integrations.shadcn) {
|
|
1069
|
-
const shadcnSuccess = await setupShadcn(config);
|
|
1070
|
-
if (!shadcnSuccess) {
|
|
1071
|
-
v2.warn("shadcn/ui setup failed, but project was created successfully");
|
|
1072
|
-
}
|
|
679
|
+
s.stop("Starting scaffolding...");
|
|
680
|
+
execSync(command, { stdio: "inherit" });
|
|
681
|
+
if (installShadcn) {
|
|
682
|
+
const projectPath = join(process.cwd(), projectName);
|
|
683
|
+
console.log(`
|
|
684
|
+
Setting up shadcn/ui...`);
|
|
685
|
+
console.log("Installing dependencies...");
|
|
686
|
+
execSync("pnpm install", { stdio: "inherit", cwd: projectPath });
|
|
687
|
+
console.log("Initializing shadcn/ui...");
|
|
688
|
+
execSync("npx shadcn@latest init", { stdio: "inherit", cwd: projectPath });
|
|
1073
689
|
}
|
|
1074
|
-
|
|
1075
|
-
const resendSuccess = await setupResend(config);
|
|
1076
|
-
if (!resendSuccess) {
|
|
1077
|
-
v2.warn("Resend setup failed, but project was created successfully");
|
|
1078
|
-
}
|
|
1079
|
-
}
|
|
1080
|
-
console.log("");
|
|
1081
|
-
ge("\uD83C\uDF89 Project created successfully!");
|
|
1082
|
-
const nextSteps = [
|
|
1083
|
-
`cd ${config.projectName}`,
|
|
1084
|
-
config.integrations.reactQuery ? "# React Query is ready to use!" : "",
|
|
1085
|
-
"pnpm dev"
|
|
1086
|
-
].filter(Boolean).join(`
|
|
1087
|
-
`);
|
|
1088
|
-
console.log("");
|
|
1089
|
-
me(nextSteps, "Next steps");
|
|
1090
|
-
process.exit(0);
|
|
690
|
+
ge(`Successfully created ${projectName}!`);
|
|
1091
691
|
} catch (error) {
|
|
1092
|
-
|
|
692
|
+
s.stop("Failed to scaffold project.");
|
|
693
|
+
console.error(error);
|
|
1093
694
|
process.exit(1);
|
|
1094
695
|
}
|
|
1095
696
|
}
|