@flexireact/core 4.0.0 → 4.1.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/README.md +147 -770
- package/dist/cli/index.d.ts +8 -0
- package/dist/cli/index.js +441 -701
- package/dist/cli/index.js.map +1 -1
- package/dist/core/build/index.d.ts +99 -0
- package/dist/core/build/index.js +2 -2
- package/dist/core/build/index.js.map +1 -1
- package/dist/core/client/index.d.ts +164 -0
- package/dist/core/client/index.js.map +1 -1
- package/dist/core/config.d.ts +165 -0
- package/dist/core/config.js +62 -32
- package/dist/core/config.js.map +1 -1
- package/dist/core/index.d.ts +1978 -0
- package/dist/core/index.js +309 -202
- package/dist/core/index.js.map +1 -1
- package/dist/core/server/index.d.ts +16 -0
- package/dist/core/server/index.js +305 -198
- package/dist/core/server/index.js.map +1 -1
- package/dist/core/start-dev.d.ts +2 -0
- package/dist/core/start-dev.js +305 -198
- package/dist/core/start-dev.js.map +1 -1
- package/dist/core/start-prod.d.ts +2 -0
- package/dist/core/start-prod.js +305 -198
- package/dist/core/start-prod.js.map +1 -1
- package/package.json +23 -11
package/dist/cli/index.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import fs2 from "fs";
|
|
5
5
|
import path2 from "path";
|
|
6
6
|
import { fileURLToPath, pathToFileURL } from "url";
|
|
7
|
-
import { spawn } from "child_process";
|
|
7
|
+
import { execSync, spawn } from "child_process";
|
|
8
8
|
import pc2 from "picocolors";
|
|
9
9
|
import prompts2 from "prompts";
|
|
10
10
|
import ora from "ora";
|
|
@@ -15,10 +15,10 @@ import path from "path";
|
|
|
15
15
|
import pc from "picocolors";
|
|
16
16
|
import prompts from "prompts";
|
|
17
17
|
var log = {
|
|
18
|
-
info: (msg) => console.log(
|
|
19
|
-
success: (msg) => console.log(
|
|
20
|
-
warn: (msg) => console.log(
|
|
21
|
-
error: (msg) => console.log(
|
|
18
|
+
info: (msg) => console.log(` ${pc.cyan("\u2139")} ${msg}`),
|
|
19
|
+
success: (msg) => console.log(` ${pc.green("\u2714")} ${msg}`),
|
|
20
|
+
warn: (msg) => console.log(` ${pc.yellow("\u26A0")} ${pc.yellow(msg)}`),
|
|
21
|
+
error: (msg) => console.log(` ${pc.red("\u2716")} ${pc.red(msg)}`),
|
|
22
22
|
blank: () => console.log("")
|
|
23
23
|
};
|
|
24
24
|
var templates = {
|
|
@@ -516,72 +516,383 @@ async function generateSpecialFile(type, cwd) {
|
|
|
516
516
|
log.success(`Created ${pc.cyan(path.relative(cwd, filePath))}`);
|
|
517
517
|
}
|
|
518
518
|
function listGenerators() {
|
|
519
|
-
console.log(`
|
|
520
|
-
|
|
519
|
+
console.log(` ${pc.bold("Available Generators")}`);
|
|
520
|
+
log.blank();
|
|
521
|
+
console.log(` ${pc.cyan("page")} ${pc.dim("Create a new page")}`);
|
|
522
|
+
console.log(` ${pc.cyan("layout")} ${pc.dim("Create a layout wrapper")}`);
|
|
523
|
+
console.log(` ${pc.cyan("component")} ${pc.dim("Create a React component")}`);
|
|
524
|
+
console.log(` ${pc.cyan("hook")} ${pc.dim("Create a custom hook")}`);
|
|
525
|
+
console.log(` ${pc.cyan("api")} ${pc.dim("Create an API route")}`);
|
|
526
|
+
console.log(` ${pc.cyan("action")} ${pc.dim("Create a server action")}`);
|
|
527
|
+
console.log(` ${pc.cyan("middleware")} ${pc.dim("Create request middleware")}`);
|
|
528
|
+
log.blank();
|
|
529
|
+
console.log(` ${pc.bold("Usage")}`);
|
|
530
|
+
console.log(` $ flexi g <type> [name]`);
|
|
531
|
+
log.blank();
|
|
532
|
+
}
|
|
521
533
|
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
534
|
+
// packages/create-flexireact/src/templates/default.ts
|
|
535
|
+
function defaultTemplate(projectName, options = {}) {
|
|
536
|
+
return {
|
|
537
|
+
"package.json": JSON.stringify({
|
|
538
|
+
name: projectName,
|
|
539
|
+
version: "1.0.0",
|
|
540
|
+
private: true,
|
|
541
|
+
type: "module",
|
|
542
|
+
scripts: {
|
|
543
|
+
dev: "flexireact dev",
|
|
544
|
+
build: "flexireact build",
|
|
545
|
+
start: "flexireact start"
|
|
546
|
+
},
|
|
547
|
+
dependencies: {
|
|
548
|
+
"react": "^19.2.1",
|
|
549
|
+
"react-dom": "^19.2.1",
|
|
550
|
+
"@flexireact/core": "^4.1.0"
|
|
551
|
+
},
|
|
552
|
+
devDependencies: {
|
|
553
|
+
"@types/react": "^19.0.0",
|
|
554
|
+
"@types/react-dom": "^19.0.0",
|
|
555
|
+
"typescript": "^5.7.0"
|
|
556
|
+
}
|
|
557
|
+
}, null, 2),
|
|
558
|
+
"tsconfig.json": JSON.stringify({
|
|
559
|
+
compilerOptions: {
|
|
560
|
+
target: "ES2022",
|
|
561
|
+
lib: ["DOM", "DOM.Iterable", "ES2022"],
|
|
562
|
+
module: "ESNext",
|
|
563
|
+
moduleResolution: "bundler",
|
|
564
|
+
jsx: "react-jsx",
|
|
565
|
+
strict: true,
|
|
566
|
+
skipLibCheck: true,
|
|
567
|
+
noEmit: true,
|
|
568
|
+
baseUrl: ".",
|
|
569
|
+
paths: { "@/*": ["./*"] }
|
|
570
|
+
},
|
|
571
|
+
include: ["**/*.ts", "**/*.tsx"],
|
|
572
|
+
exclude: ["node_modules", ".flexi"]
|
|
573
|
+
}, null, 2),
|
|
574
|
+
"flexireact.config.js": `export default {
|
|
575
|
+
server: { port: 3000 },
|
|
576
|
+
styles: ['/styles.css'],
|
|
577
|
+
};
|
|
578
|
+
`,
|
|
579
|
+
"pages/index.tsx": `import React from 'react';
|
|
533
580
|
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
581
|
+
export default function HomePage() {
|
|
582
|
+
return (
|
|
583
|
+
<div style={styles.container}>
|
|
584
|
+
<div style={styles.card}>
|
|
585
|
+
<div style={styles.logo}>F</div>
|
|
586
|
+
<h1 style={styles.title}>Welcome to FlexiReact</h1>
|
|
587
|
+
<p style={styles.subtitle}>
|
|
588
|
+
Edit <code style={styles.code}>pages/index.tsx</code> to get started
|
|
589
|
+
</p>
|
|
590
|
+
<div style={styles.links}>
|
|
591
|
+
<a href="https://github.com/aspect-dev/flexireact" style={styles.link}>GitHub</a>
|
|
592
|
+
<a href="/about" style={styles.link}>About</a>
|
|
593
|
+
</div>
|
|
594
|
+
</div>
|
|
595
|
+
</div>
|
|
596
|
+
);
|
|
597
|
+
}
|
|
537
598
|
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
599
|
+
const styles: Record<string, React.CSSProperties> = {
|
|
600
|
+
container: {
|
|
601
|
+
minHeight: '100vh',
|
|
602
|
+
display: 'flex',
|
|
603
|
+
alignItems: 'center',
|
|
604
|
+
justifyContent: 'center',
|
|
605
|
+
background: 'linear-gradient(135deg, #0a0a0a 0%, #1a1a2e 100%)',
|
|
606
|
+
fontFamily: 'system-ui, -apple-system, sans-serif',
|
|
607
|
+
},
|
|
608
|
+
card: {
|
|
609
|
+
textAlign: 'center',
|
|
610
|
+
padding: '60px 40px',
|
|
611
|
+
background: 'rgba(255, 255, 255, 0.03)',
|
|
612
|
+
borderRadius: '24px',
|
|
613
|
+
border: '1px solid rgba(255, 255, 255, 0.1)',
|
|
614
|
+
maxWidth: '500px',
|
|
615
|
+
},
|
|
616
|
+
logo: {
|
|
617
|
+
width: '80px',
|
|
618
|
+
height: '80px',
|
|
619
|
+
background: 'linear-gradient(135deg, #00FF9C 0%, #00D68F 100%)',
|
|
620
|
+
borderRadius: '20px',
|
|
621
|
+
display: 'flex',
|
|
622
|
+
alignItems: 'center',
|
|
623
|
+
justifyContent: 'center',
|
|
624
|
+
fontSize: '40px',
|
|
625
|
+
fontWeight: 900,
|
|
626
|
+
color: '#000',
|
|
627
|
+
margin: '0 auto 30px',
|
|
628
|
+
},
|
|
629
|
+
title: { fontSize: '2.5rem', fontWeight: 700, color: '#fff', margin: '0 0 16px' },
|
|
630
|
+
subtitle: { fontSize: '1.1rem', color: '#888', margin: '0 0 32px' },
|
|
631
|
+
code: { background: 'rgba(0, 255, 156, 0.1)', color: '#00FF9C', padding: '4px 8px', borderRadius: '6px' },
|
|
632
|
+
links: { display: 'flex', gap: '16px', justifyContent: 'center' },
|
|
633
|
+
link: { color: '#00FF9C', textDecoration: 'none', padding: '12px 24px', borderRadius: '12px', background: 'rgba(0, 255, 156, 0.1)' },
|
|
634
|
+
};
|
|
635
|
+
`,
|
|
636
|
+
"pages/about.tsx": `import React from 'react';
|
|
637
|
+
|
|
638
|
+
export default function AboutPage() {
|
|
639
|
+
return (
|
|
640
|
+
<div style={{ padding: 40, fontFamily: 'system-ui', background: '#0a0a0a', color: '#fff', minHeight: '100vh' }}>
|
|
641
|
+
<a href="/" style={{ color: '#00FF9C', textDecoration: 'none' }}>Back</a>
|
|
642
|
+
<h1 style={{ marginTop: 40 }}>About</h1>
|
|
643
|
+
<p style={{ color: '#888' }}>FlexiReact - Modern React Framework</p>
|
|
644
|
+
</div>
|
|
645
|
+
);
|
|
646
|
+
}
|
|
647
|
+
`,
|
|
648
|
+
"pages/api/hello.ts": `export async function GET() {
|
|
649
|
+
return Response.json({ message: 'Hello from FlexiReact!' });
|
|
650
|
+
}
|
|
651
|
+
`,
|
|
652
|
+
"public/styles.css": `* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
653
|
+
`,
|
|
654
|
+
"public/favicon.svg": `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><rect width="100" height="100" rx="20" fill="#0a0a0a"/><text x="50" y="68" font-family="system-ui" font-size="50" font-weight="900" fill="#00FF9C" text-anchor="middle">F</text></svg>`,
|
|
655
|
+
".gitignore": `node_modules/
|
|
656
|
+
.flexi/
|
|
657
|
+
dist/
|
|
658
|
+
.env
|
|
659
|
+
`
|
|
660
|
+
};
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
// packages/create-flexireact/src/templates/minimal.ts
|
|
664
|
+
function minimalTemplate(projectName, options = {}) {
|
|
665
|
+
return {
|
|
666
|
+
"package.json": JSON.stringify({
|
|
667
|
+
name: projectName,
|
|
668
|
+
version: "1.0.0",
|
|
669
|
+
private: true,
|
|
670
|
+
type: "module",
|
|
671
|
+
scripts: {
|
|
672
|
+
dev: "flexireact dev",
|
|
673
|
+
build: "flexireact build",
|
|
674
|
+
start: "flexireact start"
|
|
675
|
+
},
|
|
676
|
+
dependencies: {
|
|
677
|
+
"react": "^19.2.1",
|
|
678
|
+
"react-dom": "^19.2.1",
|
|
679
|
+
"@flexireact/core": "^4.1.0"
|
|
680
|
+
},
|
|
681
|
+
devDependencies: {
|
|
682
|
+
"@types/react": "^19.0.0",
|
|
683
|
+
"@types/react-dom": "^19.0.0",
|
|
684
|
+
"typescript": "^5.7.0"
|
|
685
|
+
}
|
|
686
|
+
}, null, 2),
|
|
687
|
+
"tsconfig.json": JSON.stringify({
|
|
688
|
+
compilerOptions: {
|
|
689
|
+
target: "ES2022",
|
|
690
|
+
lib: ["DOM", "ES2022"],
|
|
691
|
+
module: "ESNext",
|
|
692
|
+
moduleResolution: "bundler",
|
|
693
|
+
jsx: "react-jsx",
|
|
694
|
+
strict: true,
|
|
695
|
+
skipLibCheck: true,
|
|
696
|
+
noEmit: true
|
|
697
|
+
},
|
|
698
|
+
include: ["**/*.ts", "**/*.tsx"],
|
|
699
|
+
exclude: ["node_modules"]
|
|
700
|
+
}, null, 2),
|
|
701
|
+
"flexireact.config.js": `export default { server: { port: 3000 } };
|
|
702
|
+
`,
|
|
703
|
+
"pages/index.tsx": `import React from 'react';
|
|
704
|
+
|
|
705
|
+
export default function Home() {
|
|
706
|
+
return (
|
|
707
|
+
<div style={{ padding: 40, fontFamily: 'system-ui', background: '#0a0a0a', color: '#fff', minHeight: '100vh' }}>
|
|
708
|
+
<h1 style={{ color: '#00FF9C' }}>FlexiReact</h1>
|
|
709
|
+
<p>Edit pages/index.tsx to start</p>
|
|
710
|
+
</div>
|
|
711
|
+
);
|
|
712
|
+
}
|
|
713
|
+
`,
|
|
714
|
+
".gitignore": `node_modules/
|
|
715
|
+
.flexi/
|
|
716
|
+
`
|
|
717
|
+
};
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
// packages/create-flexireact/src/templates/app-router.ts
|
|
721
|
+
function appRouterTemplate(projectName) {
|
|
722
|
+
return {
|
|
723
|
+
"package.json": JSON.stringify({
|
|
724
|
+
name: projectName,
|
|
725
|
+
version: "1.0.0",
|
|
726
|
+
private: true,
|
|
727
|
+
type: "module",
|
|
728
|
+
scripts: {
|
|
729
|
+
dev: "flexireact dev",
|
|
730
|
+
build: "flexireact build",
|
|
731
|
+
start: "flexireact start"
|
|
732
|
+
},
|
|
733
|
+
dependencies: {
|
|
734
|
+
"react": "^19.2.1",
|
|
735
|
+
"react-dom": "^19.2.1",
|
|
736
|
+
"@flexireact/core": "^4.1.0"
|
|
737
|
+
},
|
|
738
|
+
devDependencies: {
|
|
739
|
+
"@types/react": "^19.0.0",
|
|
740
|
+
"@types/react-dom": "^19.0.0",
|
|
741
|
+
"typescript": "^5.7.0"
|
|
742
|
+
}
|
|
743
|
+
}, null, 2),
|
|
744
|
+
"tsconfig.json": JSON.stringify({
|
|
745
|
+
compilerOptions: {
|
|
746
|
+
target: "ES2022",
|
|
747
|
+
lib: ["DOM", "DOM.Iterable", "ES2022"],
|
|
748
|
+
module: "ESNext",
|
|
749
|
+
moduleResolution: "bundler",
|
|
750
|
+
jsx: "react-jsx",
|
|
751
|
+
strict: true,
|
|
752
|
+
skipLibCheck: true,
|
|
753
|
+
noEmit: true,
|
|
754
|
+
baseUrl: ".",
|
|
755
|
+
paths: { "@/*": ["./*"] }
|
|
756
|
+
},
|
|
757
|
+
include: ["**/*.ts", "**/*.tsx"],
|
|
758
|
+
exclude: ["node_modules", ".flexi"]
|
|
759
|
+
}, null, 2),
|
|
760
|
+
"flexireact.config.js": `export default {
|
|
761
|
+
server: { port: 3000 },
|
|
762
|
+
appDir: 'app',
|
|
763
|
+
};
|
|
764
|
+
`,
|
|
765
|
+
"app/layout.tsx": `import React from 'react';
|
|
766
|
+
|
|
767
|
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
768
|
+
return (
|
|
769
|
+
<html lang="en">
|
|
770
|
+
<head>
|
|
771
|
+
<meta charSet="UTF-8" />
|
|
772
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
773
|
+
<title>FlexiReact App</title>
|
|
774
|
+
<style>{\`
|
|
775
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
776
|
+
body { font-family: system-ui, sans-serif; background: #0a0a0a; color: #fff; }
|
|
777
|
+
\`}</style>
|
|
778
|
+
</head>
|
|
779
|
+
<body>{children}</body>
|
|
780
|
+
</html>
|
|
781
|
+
);
|
|
782
|
+
}
|
|
783
|
+
`,
|
|
784
|
+
"app/page.tsx": `import React from 'react';
|
|
785
|
+
|
|
786
|
+
export default function HomePage() {
|
|
787
|
+
return (
|
|
788
|
+
<main style={styles.main}>
|
|
789
|
+
<div style={styles.logo}>F</div>
|
|
790
|
+
<h1 style={styles.title}>FlexiReact App Router</h1>
|
|
791
|
+
<p style={styles.text}>Next.js style routing with app/ directory</p>
|
|
792
|
+
<div style={styles.links}>
|
|
793
|
+
<a href="/dashboard" style={styles.link}>Dashboard \u2192</a>
|
|
794
|
+
</div>
|
|
795
|
+
</main>
|
|
796
|
+
);
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
const styles: Record<string, React.CSSProperties> = {
|
|
800
|
+
main: {
|
|
801
|
+
minHeight: '100vh',
|
|
802
|
+
display: 'flex',
|
|
803
|
+
flexDirection: 'column',
|
|
804
|
+
alignItems: 'center',
|
|
805
|
+
justifyContent: 'center',
|
|
806
|
+
textAlign: 'center',
|
|
807
|
+
padding: '20px',
|
|
808
|
+
},
|
|
809
|
+
logo: {
|
|
810
|
+
width: '80px',
|
|
811
|
+
height: '80px',
|
|
812
|
+
background: '#00FF9C',
|
|
813
|
+
borderRadius: '20px',
|
|
814
|
+
display: 'flex',
|
|
815
|
+
alignItems: 'center',
|
|
816
|
+
justifyContent: 'center',
|
|
817
|
+
fontSize: '40px',
|
|
818
|
+
fontWeight: 900,
|
|
819
|
+
color: '#000',
|
|
820
|
+
marginBottom: '30px',
|
|
821
|
+
},
|
|
822
|
+
title: {
|
|
823
|
+
fontSize: '2.5rem',
|
|
824
|
+
marginBottom: '16px',
|
|
825
|
+
},
|
|
826
|
+
text: {
|
|
827
|
+
color: '#888',
|
|
828
|
+
marginBottom: '32px',
|
|
829
|
+
},
|
|
830
|
+
links: {
|
|
831
|
+
display: 'flex',
|
|
832
|
+
gap: '16px',
|
|
833
|
+
},
|
|
834
|
+
link: {
|
|
835
|
+
color: '#00FF9C',
|
|
836
|
+
textDecoration: 'none',
|
|
837
|
+
padding: '12px 24px',
|
|
838
|
+
borderRadius: '12px',
|
|
839
|
+
background: 'rgba(0, 255, 156, 0.1)',
|
|
840
|
+
},
|
|
841
|
+
};
|
|
842
|
+
`,
|
|
843
|
+
"app/dashboard/page.tsx": `import React from 'react';
|
|
844
|
+
|
|
845
|
+
export default function DashboardPage() {
|
|
846
|
+
return (
|
|
847
|
+
<div style={{ padding: 40 }}>
|
|
848
|
+
<a href="/" style={{ color: '#00FF9C', textDecoration: 'none' }}>\u2190 Back</a>
|
|
849
|
+
<h1 style={{ marginTop: 30, marginBottom: 20 }}>Dashboard</h1>
|
|
850
|
+
<p style={{ color: '#888' }}>This is a nested route: app/dashboard/page.tsx</p>
|
|
851
|
+
</div>
|
|
852
|
+
);
|
|
853
|
+
}
|
|
854
|
+
`,
|
|
855
|
+
"app/api/hello/route.ts": `export async function GET() {
|
|
856
|
+
return Response.json({ message: 'Hello from App Router API!' });
|
|
857
|
+
}
|
|
858
|
+
`,
|
|
859
|
+
".gitignore": `node_modules/
|
|
860
|
+
.flexi/
|
|
861
|
+
dist/
|
|
862
|
+
.env
|
|
863
|
+
`
|
|
864
|
+
};
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
// packages/create-flexireact/src/templates/index.ts
|
|
868
|
+
function getTemplateFiles(templateKey, projectName, options = {}) {
|
|
869
|
+
switch (templateKey) {
|
|
870
|
+
case "minimal":
|
|
871
|
+
return minimalTemplate(projectName, options);
|
|
872
|
+
case "app-router":
|
|
873
|
+
return appRouterTemplate(projectName);
|
|
874
|
+
default:
|
|
875
|
+
return defaultTemplate(projectName, options);
|
|
876
|
+
}
|
|
544
877
|
}
|
|
545
878
|
|
|
546
879
|
// cli/index.ts
|
|
547
880
|
var __filename2 = fileURLToPath(import.meta.url);
|
|
548
881
|
var __dirname2 = path2.dirname(__filename2);
|
|
549
|
-
var VERSION = "
|
|
882
|
+
var VERSION = "4.1.0";
|
|
550
883
|
var LOGO = `
|
|
551
|
-
${pc2.
|
|
552
|
-
${pc2.cyan("\u2551")} ${pc2.cyan("\u2551")}
|
|
553
|
-
${pc2.cyan("\u2551")} ${pc2.bold(pc2.magenta("\u26A1"))} ${pc2.bold(pc2.white("F L E X I R E A C T"))} ${pc2.cyan("\u2551")}
|
|
554
|
-
${pc2.cyan("\u2551")} ${pc2.cyan("\u2551")}
|
|
555
|
-
${pc2.cyan("\u2551")} ${pc2.dim("The Modern React Framework")} ${pc2.cyan("\u2551")}
|
|
556
|
-
${pc2.cyan("\u2551")} ${pc2.dim("TypeScript \u2022 Tailwind \u2022 SSR \u2022 Islands")} ${pc2.cyan("\u2551")}
|
|
557
|
-
${pc2.cyan("\u2551")} ${pc2.cyan("\u2551")}
|
|
558
|
-
${pc2.cyan("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D")}
|
|
884
|
+
${pc2.white("\u25B2")} ${pc2.bold("FlexiReact")} ${pc2.dim(VERSION)}
|
|
559
885
|
`;
|
|
560
|
-
var MINI_LOGO = `${pc2.
|
|
886
|
+
var MINI_LOGO = `${pc2.white("\u25B2")} ${pc2.bold("FlexiReact")}`;
|
|
561
887
|
var log2 = {
|
|
562
|
-
info: (msg) => console.log(
|
|
563
|
-
success: (msg) => console.log(
|
|
564
|
-
warn: (msg) => console.log(
|
|
565
|
-
error: (msg) => console.log(
|
|
566
|
-
step: (
|
|
888
|
+
info: (msg) => console.log(` ${pc2.cyan("\u2139")} ${msg}`),
|
|
889
|
+
success: (msg) => console.log(` ${pc2.green("\u2714")} ${msg}`),
|
|
890
|
+
warn: (msg) => console.log(` ${pc2.yellow("\u26A0")} ${pc2.yellow(msg)}`),
|
|
891
|
+
error: (msg) => console.log(` ${pc2.red("\u2716")} ${pc2.red(msg)}`),
|
|
892
|
+
step: (msg) => console.log(` ${pc2.dim("\u25CB")} ${msg}`),
|
|
567
893
|
blank: () => console.log(""),
|
|
568
|
-
divider: () => console.log(pc2.dim("\u2500"
|
|
894
|
+
divider: () => console.log(pc2.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"))
|
|
569
895
|
};
|
|
570
|
-
function copyDirectory(src, dest) {
|
|
571
|
-
if (!fs2.existsSync(dest)) {
|
|
572
|
-
fs2.mkdirSync(dest, { recursive: true });
|
|
573
|
-
}
|
|
574
|
-
const entries = fs2.readdirSync(src, { withFileTypes: true });
|
|
575
|
-
for (const entry of entries) {
|
|
576
|
-
const srcPath = path2.join(src, entry.name);
|
|
577
|
-
const destPath = path2.join(dest, entry.name);
|
|
578
|
-
if (entry.isDirectory()) {
|
|
579
|
-
copyDirectory(srcPath, destPath);
|
|
580
|
-
} else {
|
|
581
|
-
fs2.copyFileSync(srcPath, destPath);
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
}
|
|
585
896
|
async function runCommand(cmd, cwd) {
|
|
586
897
|
return new Promise((resolve, reject) => {
|
|
587
898
|
const child = spawn(cmd, {
|
|
@@ -622,638 +933,73 @@ async function createProject(projectName) {
|
|
|
622
933
|
name: "template",
|
|
623
934
|
message: "Select a template:",
|
|
624
935
|
choices: [
|
|
625
|
-
{ title:
|
|
626
|
-
{ title:
|
|
627
|
-
{ title:
|
|
936
|
+
{ title: `\u26A1 Default ${pc2.dim("(Pages routing)")}`, value: "default" },
|
|
937
|
+
{ title: `\u{1F4C2} App Router ${pc2.dim("(Next.js style)")}`, value: "app-router" },
|
|
938
|
+
{ title: `\u{1F4E6} Minimal ${pc2.dim("(Bare starter)")}`, value: "minimal" }
|
|
628
939
|
],
|
|
629
940
|
initial: 0
|
|
630
|
-
},
|
|
631
|
-
{
|
|
632
|
-
type: "toggle",
|
|
633
|
-
name: "typescript",
|
|
634
|
-
message: "Use TypeScript?",
|
|
635
|
-
initial: true,
|
|
636
|
-
active: "Yes",
|
|
637
|
-
inactive: "No"
|
|
638
941
|
}
|
|
639
942
|
]);
|
|
640
943
|
if (options.template === void 0) process.exit(1);
|
|
641
944
|
log2.blank();
|
|
642
|
-
|
|
643
|
-
log2.blank();
|
|
644
|
-
const totalSteps = options.template === "default" ? 6 : options.template === "flexi-ui" ? 5 : 4;
|
|
945
|
+
const totalSteps = 5;
|
|
645
946
|
let currentStep = 0;
|
|
646
947
|
currentStep++;
|
|
647
|
-
log2.step(
|
|
948
|
+
log2.step("Creating project directory...");
|
|
648
949
|
fs2.mkdirSync(projectPath, { recursive: true });
|
|
649
|
-
log2.success(`Created ${pc2.cyan(name)}/`);
|
|
650
950
|
currentStep++;
|
|
651
|
-
log2.step(
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
951
|
+
log2.step("Generating files...");
|
|
952
|
+
try {
|
|
953
|
+
const files = getTemplateFiles(options.template, name, {});
|
|
954
|
+
for (const [filePath, content] of Object.entries(files)) {
|
|
955
|
+
const fullPath = path2.join(projectPath, filePath);
|
|
956
|
+
const dir = path2.dirname(fullPath);
|
|
957
|
+
if (!fs2.existsSync(dir)) {
|
|
958
|
+
fs2.mkdirSync(dir, { recursive: true });
|
|
959
|
+
}
|
|
960
|
+
fs2.writeFileSync(fullPath, content);
|
|
961
|
+
}
|
|
962
|
+
} catch (err) {
|
|
963
|
+
log2.error(`Failed to generate template: ${err.message}`);
|
|
964
|
+
process.exit(1);
|
|
660
965
|
}
|
|
661
966
|
currentStep++;
|
|
662
|
-
log2.step(
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
967
|
+
log2.step("Initializing git...");
|
|
968
|
+
try {
|
|
969
|
+
execSync("git init", { cwd: projectPath, stdio: "ignore" });
|
|
970
|
+
execSync("git add .", { cwd: projectPath, stdio: "ignore" });
|
|
971
|
+
execSync('git commit -m "Initial commit from FlexiReact CLI"', { cwd: projectPath, stdio: "ignore" });
|
|
972
|
+
} catch {
|
|
668
973
|
}
|
|
669
|
-
log2.success("Project configured");
|
|
670
974
|
currentStep++;
|
|
671
|
-
log2.step(
|
|
672
|
-
const spinner = ora({ text: "Installing packages...", color: "cyan" }).start();
|
|
975
|
+
log2.step("Installing dependencies...");
|
|
976
|
+
const spinner = ora({ text: "Installing packages...", color: "cyan", indent: 2 }).start();
|
|
673
977
|
try {
|
|
674
978
|
await runCommand("npm install", projectPath);
|
|
675
|
-
spinner.
|
|
979
|
+
spinner.stop();
|
|
980
|
+
log2.success("Dependencies installed");
|
|
676
981
|
} catch {
|
|
677
|
-
spinner.
|
|
678
|
-
log2.warn('Run "npm install" manually
|
|
982
|
+
spinner.stop();
|
|
983
|
+
log2.warn('Run "npm install" manually');
|
|
679
984
|
}
|
|
680
985
|
currentStep++;
|
|
681
|
-
log2.step(
|
|
682
|
-
const linkSpinner = ora({ text: "Linking framework...", color: "cyan" }).start();
|
|
986
|
+
log2.step("Linking FlexiReact...");
|
|
683
987
|
try {
|
|
684
988
|
const frameworkRoot = path2.resolve(__dirname2, "..");
|
|
685
989
|
await runCommand(`npm link "${frameworkRoot}"`, projectPath);
|
|
686
|
-
linkSpinner.succeed("FlexiReact linked");
|
|
687
990
|
} catch {
|
|
688
|
-
linkSpinner.fail("Failed to link FlexiReact");
|
|
689
991
|
log2.warn('Run "npm link flexireact" manually');
|
|
690
992
|
}
|
|
691
|
-
if (options.template === "default") {
|
|
692
|
-
currentStep++;
|
|
693
|
-
log2.step(currentStep, totalSteps, "Setting up shadcn/ui components...");
|
|
694
|
-
log2.success("shadcn/ui configured");
|
|
695
|
-
}
|
|
696
|
-
log2.blank();
|
|
697
|
-
log2.divider();
|
|
698
|
-
log2.blank();
|
|
699
|
-
console.log(` ${pc2.green("\u2728")} ${pc2.bold("Success!")} Your FlexiReact app is ready.`);
|
|
700
|
-
log2.blank();
|
|
701
|
-
console.log(` ${pc2.dim("$")} ${pc2.cyan(`cd ${name}`)}`);
|
|
702
|
-
console.log(` ${pc2.dim("$")} ${pc2.cyan("npm run dev")}`);
|
|
703
993
|
log2.blank();
|
|
704
|
-
console.log(` ${pc2.
|
|
994
|
+
console.log(` ${pc2.green("\u2714")} ${pc2.bold("Success!")} Created ${name} at ${projectPath}`);
|
|
705
995
|
log2.blank();
|
|
706
|
-
console.log(`
|
|
996
|
+
console.log(` Next steps:`);
|
|
997
|
+
console.log(` ${pc2.dim("1.")} ${pc2.cyan(`cd ${name}`)}`);
|
|
998
|
+
console.log(` ${pc2.dim("2.")} ${pc2.cyan("npm run dev")}`);
|
|
707
999
|
log2.blank();
|
|
708
1000
|
}
|
|
709
|
-
async function createDefaultTemplate(projectPath, name, useTypeScript) {
|
|
710
|
-
const ext = useTypeScript ? "tsx" : "jsx";
|
|
711
|
-
const configExt = useTypeScript ? "ts" : "js";
|
|
712
|
-
const dirs = [
|
|
713
|
-
"app/components",
|
|
714
|
-
"app/styles",
|
|
715
|
-
"pages/api",
|
|
716
|
-
"public"
|
|
717
|
-
];
|
|
718
|
-
for (const dir of dirs) {
|
|
719
|
-
fs2.mkdirSync(path2.join(projectPath, dir), { recursive: true });
|
|
720
|
-
}
|
|
721
|
-
const packageJson = {
|
|
722
|
-
name,
|
|
723
|
-
version: "0.1.0",
|
|
724
|
-
private: true,
|
|
725
|
-
type: "module",
|
|
726
|
-
scripts: {
|
|
727
|
-
dev: "flexi dev",
|
|
728
|
-
build: "flexi build",
|
|
729
|
-
start: "flexi start",
|
|
730
|
-
doctor: "flexi doctor"
|
|
731
|
-
},
|
|
732
|
-
dependencies: {
|
|
733
|
-
react: "^19.0.0",
|
|
734
|
-
"react-dom": "^19.0.0",
|
|
735
|
-
"class-variance-authority": "^0.7.0",
|
|
736
|
-
clsx: "^2.1.1",
|
|
737
|
-
"tailwind-merge": "^2.5.5",
|
|
738
|
-
"lucide-react": "^0.468.0"
|
|
739
|
-
},
|
|
740
|
-
devDependencies: {
|
|
741
|
-
tailwindcss: "^3.4.16",
|
|
742
|
-
postcss: "^8.4.49",
|
|
743
|
-
autoprefixer: "^10.4.20",
|
|
744
|
-
...useTypeScript ? {
|
|
745
|
-
typescript: "^5.7.2",
|
|
746
|
-
"@types/react": "^19.0.0",
|
|
747
|
-
"@types/react-dom": "^19.0.0",
|
|
748
|
-
"@types/node": "^22.10.1"
|
|
749
|
-
} : {}
|
|
750
|
-
}
|
|
751
|
-
};
|
|
752
|
-
fs2.writeFileSync(
|
|
753
|
-
path2.join(projectPath, "package.json"),
|
|
754
|
-
JSON.stringify(packageJson, null, 2)
|
|
755
|
-
);
|
|
756
|
-
if (useTypeScript) {
|
|
757
|
-
const tsconfig = {
|
|
758
|
-
compilerOptions: {
|
|
759
|
-
target: "ES2022",
|
|
760
|
-
lib: ["dom", "dom.iterable", "ES2022"],
|
|
761
|
-
allowJs: true,
|
|
762
|
-
skipLibCheck: true,
|
|
763
|
-
strict: true,
|
|
764
|
-
noEmit: true,
|
|
765
|
-
esModuleInterop: true,
|
|
766
|
-
module: "ESNext",
|
|
767
|
-
moduleResolution: "bundler",
|
|
768
|
-
resolveJsonModule: true,
|
|
769
|
-
isolatedModules: true,
|
|
770
|
-
jsx: "react-jsx",
|
|
771
|
-
baseUrl: ".",
|
|
772
|
-
paths: {
|
|
773
|
-
"@/*": ["./*"],
|
|
774
|
-
"@/components/*": ["./app/components/*"]
|
|
775
|
-
}
|
|
776
|
-
},
|
|
777
|
-
include: ["**/*.ts", "**/*.tsx"],
|
|
778
|
-
exclude: ["node_modules"]
|
|
779
|
-
};
|
|
780
|
-
fs2.writeFileSync(
|
|
781
|
-
path2.join(projectPath, "tsconfig.json"),
|
|
782
|
-
JSON.stringify(tsconfig, null, 2)
|
|
783
|
-
);
|
|
784
|
-
}
|
|
785
|
-
const tailwindConfig = `/** @type {import('tailwindcss').Config} */
|
|
786
|
-
export default {
|
|
787
|
-
content: [
|
|
788
|
-
'./app/**/*.{js,ts,jsx,tsx}',
|
|
789
|
-
'./pages/**/*.{js,ts,jsx,tsx}',
|
|
790
|
-
'./components/**/*.{js,ts,jsx,tsx}',
|
|
791
|
-
],
|
|
792
|
-
darkMode: 'class',
|
|
793
|
-
theme: {
|
|
794
|
-
extend: {
|
|
795
|
-
colors: {
|
|
796
|
-
border: 'hsl(var(--border))',
|
|
797
|
-
background: 'hsl(var(--background))',
|
|
798
|
-
foreground: 'hsl(var(--foreground))',
|
|
799
|
-
primary: {
|
|
800
|
-
DEFAULT: 'hsl(var(--primary))',
|
|
801
|
-
foreground: 'hsl(var(--primary-foreground))',
|
|
802
|
-
},
|
|
803
|
-
secondary: {
|
|
804
|
-
DEFAULT: 'hsl(var(--secondary))',
|
|
805
|
-
foreground: 'hsl(var(--secondary-foreground))',
|
|
806
|
-
},
|
|
807
|
-
muted: {
|
|
808
|
-
DEFAULT: 'hsl(var(--muted))',
|
|
809
|
-
foreground: 'hsl(var(--muted-foreground))',
|
|
810
|
-
},
|
|
811
|
-
accent: {
|
|
812
|
-
DEFAULT: 'hsl(var(--accent))',
|
|
813
|
-
foreground: 'hsl(var(--accent-foreground))',
|
|
814
|
-
},
|
|
815
|
-
},
|
|
816
|
-
borderRadius: {
|
|
817
|
-
lg: 'var(--radius)',
|
|
818
|
-
md: 'calc(var(--radius) - 2px)',
|
|
819
|
-
sm: 'calc(var(--radius) - 4px)',
|
|
820
|
-
},
|
|
821
|
-
},
|
|
822
|
-
},
|
|
823
|
-
plugins: [],
|
|
824
|
-
};
|
|
825
|
-
`;
|
|
826
|
-
fs2.writeFileSync(path2.join(projectPath, "tailwind.config.js"), tailwindConfig);
|
|
827
|
-
const postcssConfig = `export default {
|
|
828
|
-
plugins: {
|
|
829
|
-
tailwindcss: {},
|
|
830
|
-
autoprefixer: {},
|
|
831
|
-
},
|
|
832
|
-
};
|
|
833
|
-
`;
|
|
834
|
-
fs2.writeFileSync(path2.join(projectPath, "postcss.config.js"), postcssConfig);
|
|
835
|
-
const globalsCss = `@tailwind base;
|
|
836
|
-
@tailwind components;
|
|
837
|
-
@tailwind utilities;
|
|
838
|
-
|
|
839
|
-
@layer base {
|
|
840
|
-
:root {
|
|
841
|
-
--background: 222 47% 11%;
|
|
842
|
-
--foreground: 210 40% 98%;
|
|
843
|
-
--primary: 263 70% 50%;
|
|
844
|
-
--primary-foreground: 210 40% 98%;
|
|
845
|
-
--secondary: 217 33% 17%;
|
|
846
|
-
--secondary-foreground: 210 40% 98%;
|
|
847
|
-
--muted: 217 33% 17%;
|
|
848
|
-
--muted-foreground: 215 20% 65%;
|
|
849
|
-
--accent: 263 70% 50%;
|
|
850
|
-
--accent-foreground: 210 40% 98%;
|
|
851
|
-
--border: 217 33% 17%;
|
|
852
|
-
--radius: 0.5rem;
|
|
853
|
-
}
|
|
854
|
-
}
|
|
855
|
-
|
|
856
|
-
@layer base {
|
|
857
|
-
* {
|
|
858
|
-
@apply border-border;
|
|
859
|
-
}
|
|
860
|
-
body {
|
|
861
|
-
@apply bg-background text-foreground antialiased;
|
|
862
|
-
font-feature-settings: "rlig" 1, "calt" 1;
|
|
863
|
-
}
|
|
864
|
-
}
|
|
865
|
-
`;
|
|
866
|
-
fs2.writeFileSync(path2.join(projectPath, "app/styles/globals.css"), globalsCss);
|
|
867
|
-
const flexiConfig = `export default {
|
|
868
|
-
server: {
|
|
869
|
-
port: 3000,
|
|
870
|
-
host: 'localhost'
|
|
871
|
-
},
|
|
872
|
-
islands: {
|
|
873
|
-
enabled: true
|
|
874
|
-
},
|
|
875
|
-
rsc: {
|
|
876
|
-
enabled: true
|
|
877
|
-
}
|
|
878
|
-
};
|
|
879
|
-
`;
|
|
880
|
-
fs2.writeFileSync(path2.join(projectPath, `flexireact.config.${configExt}`), flexiConfig);
|
|
881
|
-
await createComponents(projectPath, ext);
|
|
882
|
-
await createPages(projectPath, ext);
|
|
883
|
-
}
|
|
884
|
-
async function createComponents(projectPath, ext) {
|
|
885
|
-
const buttonComponent = `import React from 'react';
|
|
886
|
-
import { cva, type VariantProps } from 'class-variance-authority';
|
|
887
|
-
import { clsx } from 'clsx';
|
|
888
|
-
import { twMerge } from 'tailwind-merge';
|
|
889
|
-
|
|
890
|
-
function cn(...inputs${ext === "tsx" ? ": (string | undefined)[]" : ""}) {
|
|
891
|
-
return twMerge(clsx(inputs));
|
|
892
|
-
}
|
|
893
|
-
|
|
894
|
-
const buttonVariants = cva(
|
|
895
|
-
'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
|
|
896
|
-
{
|
|
897
|
-
variants: {
|
|
898
|
-
variant: {
|
|
899
|
-
default: 'bg-primary text-primary-foreground hover:bg-primary/90',
|
|
900
|
-
secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
|
|
901
|
-
outline: 'border border-border bg-transparent hover:bg-accent hover:text-accent-foreground',
|
|
902
|
-
ghost: 'hover:bg-accent hover:text-accent-foreground',
|
|
903
|
-
},
|
|
904
|
-
size: {
|
|
905
|
-
default: 'h-10 px-4 py-2',
|
|
906
|
-
sm: 'h-9 rounded-md px-3',
|
|
907
|
-
lg: 'h-11 rounded-md px-8',
|
|
908
|
-
icon: 'h-10 w-10',
|
|
909
|
-
},
|
|
910
|
-
},
|
|
911
|
-
defaultVariants: {
|
|
912
|
-
variant: 'default',
|
|
913
|
-
size: 'default',
|
|
914
|
-
},
|
|
915
|
-
}
|
|
916
|
-
);
|
|
917
|
-
|
|
918
|
-
${ext === "tsx" ? `interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {}` : ""}
|
|
919
|
-
|
|
920
|
-
export function Button({ className, variant, size, ...props }${ext === "tsx" ? ": ButtonProps" : ""}) {
|
|
921
|
-
return (
|
|
922
|
-
<button
|
|
923
|
-
className={cn(buttonVariants({ variant, size, className }))}
|
|
924
|
-
{...props}
|
|
925
|
-
/>
|
|
926
|
-
);
|
|
927
|
-
}
|
|
928
|
-
`;
|
|
929
|
-
fs2.writeFileSync(path2.join(projectPath, `app/components/Button.${ext}`), buttonComponent);
|
|
930
|
-
const cardComponent = `import React from 'react';
|
|
931
|
-
|
|
932
|
-
${ext === "tsx" ? `interface CardProps {
|
|
933
|
-
children: React.ReactNode;
|
|
934
|
-
className?: string;
|
|
935
|
-
}` : ""}
|
|
936
|
-
|
|
937
|
-
export function Card({ children, className = '' }${ext === "tsx" ? ": CardProps" : ""}) {
|
|
938
|
-
return (
|
|
939
|
-
<div className={\`rounded-lg border border-border bg-secondary/50 p-6 backdrop-blur-sm \${className}\`}>
|
|
940
|
-
{children}
|
|
941
|
-
</div>
|
|
942
|
-
);
|
|
943
|
-
}
|
|
944
|
-
|
|
945
|
-
export function CardHeader({ children, className = '' }${ext === "tsx" ? ": CardProps" : ""}) {
|
|
946
|
-
return <div className={\`mb-4 \${className}\`}>{children}</div>;
|
|
947
|
-
}
|
|
948
|
-
|
|
949
|
-
export function CardTitle({ children, className = '' }${ext === "tsx" ? ": CardProps" : ""}) {
|
|
950
|
-
return <h3 className={\`text-xl font-semibold \${className}\`}>{children}</h3>;
|
|
951
|
-
}
|
|
952
|
-
|
|
953
|
-
export function CardDescription({ children, className = '' }${ext === "tsx" ? ": CardProps" : ""}) {
|
|
954
|
-
return <p className={\`text-muted-foreground \${className}\`}>{children}</p>;
|
|
955
|
-
}
|
|
956
|
-
|
|
957
|
-
export function CardContent({ children, className = '' }${ext === "tsx" ? ": CardProps" : ""}) {
|
|
958
|
-
return <div className={className}>{children}</div>;
|
|
959
|
-
}
|
|
960
|
-
`;
|
|
961
|
-
fs2.writeFileSync(path2.join(projectPath, `app/components/Card.${ext}`), cardComponent);
|
|
962
|
-
const navbarComponent = `import React from 'react';
|
|
963
|
-
|
|
964
|
-
export function Navbar() {
|
|
965
|
-
return (
|
|
966
|
-
<nav className="fixed top-0 left-0 right-0 z-50 border-b border-border bg-background/80 backdrop-blur-md">
|
|
967
|
-
<div className="mx-auto flex h-16 max-w-7xl items-center justify-between px-4">
|
|
968
|
-
<a href="/" className="flex items-center gap-2 text-xl font-bold">
|
|
969
|
-
<span className="text-2xl">\u26A1</span>
|
|
970
|
-
<span className="bg-gradient-to-r from-purple-400 to-pink-400 bg-clip-text text-transparent">
|
|
971
|
-
FlexiReact
|
|
972
|
-
</span>
|
|
973
|
-
</a>
|
|
974
|
-
|
|
975
|
-
<div className="flex items-center gap-6">
|
|
976
|
-
<a href="/" className="text-muted-foreground hover:text-foreground transition-colors">
|
|
977
|
-
Home
|
|
978
|
-
</a>
|
|
979
|
-
<a href="/docs" className="text-muted-foreground hover:text-foreground transition-colors">
|
|
980
|
-
Docs
|
|
981
|
-
</a>
|
|
982
|
-
<a href="/api/hello" className="text-muted-foreground hover:text-foreground transition-colors">
|
|
983
|
-
API
|
|
984
|
-
</a>
|
|
985
|
-
<a
|
|
986
|
-
href="https://github.com/flexireact/flexireact"
|
|
987
|
-
target="_blank"
|
|
988
|
-
rel="noopener noreferrer"
|
|
989
|
-
className="text-muted-foreground hover:text-foreground transition-colors"
|
|
990
|
-
>
|
|
991
|
-
GitHub
|
|
992
|
-
</a>
|
|
993
|
-
</div>
|
|
994
|
-
</div>
|
|
995
|
-
</nav>
|
|
996
|
-
);
|
|
997
|
-
}
|
|
998
|
-
`;
|
|
999
|
-
fs2.writeFileSync(path2.join(projectPath, `app/components/Navbar.${ext}`), navbarComponent);
|
|
1000
|
-
}
|
|
1001
|
-
async function createPages(projectPath, ext) {
|
|
1002
|
-
const homePage = `import React from 'react';
|
|
1003
|
-
|
|
1004
|
-
export const title = 'FlexiReact - The Modern React Framework';
|
|
1005
|
-
|
|
1006
|
-
const features = [
|
|
1007
|
-
{ icon: '\u26A1', title: 'Lightning Fast', desc: 'Powered by esbuild for instant builds.' },
|
|
1008
|
-
{ icon: '\u{1F4D8}', title: 'TypeScript', desc: 'First-class TypeScript support.' },
|
|
1009
|
-
{ icon: '\u{1F3DD}\uFE0F', title: 'Islands', desc: 'Partial hydration for minimal JS.' },
|
|
1010
|
-
{ icon: '\u{1F4C1}', title: 'File Routing', desc: 'Create a file, get a route.' },
|
|
1011
|
-
{ icon: '\u{1F50C}', title: 'API Routes', desc: 'Build your API alongside frontend.' },
|
|
1012
|
-
{ icon: '\u{1F680}', title: 'SSR/SSG', desc: 'Server rendering and static generation.' },
|
|
1013
|
-
];
|
|
1014
|
-
|
|
1015
|
-
export default function HomePage() {
|
|
1016
|
-
return (
|
|
1017
|
-
<div style={styles.container}>
|
|
1018
|
-
{/* Navbar */}
|
|
1019
|
-
<nav style={styles.nav}>
|
|
1020
|
-
<a href="/" style={styles.logo}>
|
|
1021
|
-
<svg style={{ width: 32, height: 32 }} viewBox="0 0 200 200" fill="none">
|
|
1022
|
-
<defs>
|
|
1023
|
-
<linearGradient id="g" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
1024
|
-
<stop offset="0%" stopColor="#61DAFB"/>
|
|
1025
|
-
<stop offset="100%" stopColor="#21A1F1"/>
|
|
1026
|
-
</linearGradient>
|
|
1027
|
-
</defs>
|
|
1028
|
-
<circle cx="100" cy="100" r="12" fill="url(#g)"/>
|
|
1029
|
-
<ellipse cx="100" cy="100" rx="80" ry="30" fill="none" stroke="url(#g)" strokeWidth="6" transform="rotate(-30 100 100)"/>
|
|
1030
|
-
<ellipse cx="100" cy="100" rx="80" ry="30" fill="none" stroke="url(#g)" strokeWidth="6" transform="rotate(30 100 100)"/>
|
|
1031
|
-
<ellipse cx="100" cy="100" rx="80" ry="30" fill="none" stroke="url(#g)" strokeWidth="6" transform="rotate(90 100 100)"/>
|
|
1032
|
-
</svg>
|
|
1033
|
-
<span style={styles.logoText}>FlexiReact</span>
|
|
1034
|
-
</a>
|
|
1035
|
-
<div style={styles.navLinks}>
|
|
1036
|
-
<a href="/" style={styles.navLink}>Home</a>
|
|
1037
|
-
<a href="/api/hello" style={styles.navLink}>API</a>
|
|
1038
|
-
</div>
|
|
1039
|
-
</nav>
|
|
1040
|
-
|
|
1041
|
-
{/* Hero */}
|
|
1042
|
-
<section style={styles.hero}>
|
|
1043
|
-
<svg style={{ width: 120, height: 120, marginBottom: 24 }} viewBox="0 0 200 200" fill="none">
|
|
1044
|
-
<defs>
|
|
1045
|
-
<linearGradient id="hero" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
1046
|
-
<stop offset="0%" stopColor="#61DAFB"/>
|
|
1047
|
-
<stop offset="100%" stopColor="#21A1F1"/>
|
|
1048
|
-
</linearGradient>
|
|
1049
|
-
</defs>
|
|
1050
|
-
<circle cx="100" cy="100" r="12" fill="url(#hero)"/>
|
|
1051
|
-
<ellipse cx="100" cy="100" rx="80" ry="30" fill="none" stroke="url(#hero)" strokeWidth="6" transform="rotate(-30 100 100)"/>
|
|
1052
|
-
<ellipse cx="100" cy="100" rx="80" ry="30" fill="none" stroke="url(#hero)" strokeWidth="6" transform="rotate(30 100 100)"/>
|
|
1053
|
-
<ellipse cx="100" cy="100" rx="80" ry="30" fill="none" stroke="url(#hero)" strokeWidth="6" transform="rotate(90 100 100)"/>
|
|
1054
|
-
<circle cx="28" cy="70" r="8" fill="url(#hero)"/>
|
|
1055
|
-
<circle cx="172" cy="130" r="8" fill="url(#hero)"/>
|
|
1056
|
-
<circle cx="100" cy="20" r="8" fill="url(#hero)"/>
|
|
1057
|
-
</svg>
|
|
1058
|
-
|
|
1059
|
-
<div style={styles.badge}>\u{1F680} v2.1 \u2014 TypeScript & Islands</div>
|
|
1060
|
-
|
|
1061
|
-
<h1 style={styles.title}>
|
|
1062
|
-
Build faster with<br/>
|
|
1063
|
-
<span style={styles.titleGradient}>FlexiReact</span>
|
|
1064
|
-
</h1>
|
|
1065
|
-
|
|
1066
|
-
<p style={styles.subtitle}>
|
|
1067
|
-
The modern React framework with SSR, SSG, Islands architecture,<br/>
|
|
1068
|
-
and file-based routing. Simple and powerful.
|
|
1069
|
-
</p>
|
|
1070
|
-
|
|
1071
|
-
<div style={styles.buttons}>
|
|
1072
|
-
<a href="/docs" style={styles.primaryBtn}>Get Started \u2192</a>
|
|
1073
|
-
<a href="/api/hello" style={styles.secondaryBtn}>View API</a>
|
|
1074
|
-
</div>
|
|
1075
|
-
</section>
|
|
1076
|
-
|
|
1077
|
-
{/* Features */}
|
|
1078
|
-
<section style={styles.features}>
|
|
1079
|
-
<h2 style={styles.featuresTitle}>Everything you need</h2>
|
|
1080
|
-
<div style={styles.grid}>
|
|
1081
|
-
{features.map((f, i) => (
|
|
1082
|
-
<div key={i} style={styles.card}>
|
|
1083
|
-
<div style={styles.cardIcon}>{f.icon}</div>
|
|
1084
|
-
<h3 style={styles.cardTitle}>{f.title}</h3>
|
|
1085
|
-
<p style={styles.cardDesc}>{f.desc}</p>
|
|
1086
|
-
</div>
|
|
1087
|
-
))}
|
|
1088
|
-
</div>
|
|
1089
|
-
</section>
|
|
1090
|
-
|
|
1091
|
-
{/* Footer */}
|
|
1092
|
-
<footer style={styles.footer}>
|
|
1093
|
-
Built with \u2764\uFE0F using FlexiReact
|
|
1094
|
-
</footer>
|
|
1095
|
-
</div>
|
|
1096
|
-
);
|
|
1097
|
-
}
|
|
1098
|
-
|
|
1099
|
-
const styles = {
|
|
1100
|
-
container: {
|
|
1101
|
-
minHeight: '100vh',
|
|
1102
|
-
background: 'linear-gradient(180deg, #0f172a 0%, #1e293b 100%)',
|
|
1103
|
-
color: '#f8fafc',
|
|
1104
|
-
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
|
|
1105
|
-
},
|
|
1106
|
-
nav: {
|
|
1107
|
-
position: 'fixed',
|
|
1108
|
-
top: 0,
|
|
1109
|
-
left: 0,
|
|
1110
|
-
right: 0,
|
|
1111
|
-
height: 64,
|
|
1112
|
-
display: 'flex',
|
|
1113
|
-
alignItems: 'center',
|
|
1114
|
-
justifyContent: 'space-between',
|
|
1115
|
-
padding: '0 24px',
|
|
1116
|
-
background: 'rgba(15, 23, 42, 0.8)',
|
|
1117
|
-
backdropFilter: 'blur(12px)',
|
|
1118
|
-
borderBottom: '1px solid rgba(255,255,255,0.1)',
|
|
1119
|
-
zIndex: 100,
|
|
1120
|
-
},
|
|
1121
|
-
logo: {
|
|
1122
|
-
display: 'flex',
|
|
1123
|
-
alignItems: 'center',
|
|
1124
|
-
gap: 8,
|
|
1125
|
-
textDecoration: 'none',
|
|
1126
|
-
color: '#f8fafc',
|
|
1127
|
-
},
|
|
1128
|
-
logoText: {
|
|
1129
|
-
fontSize: 20,
|
|
1130
|
-
fontWeight: 700,
|
|
1131
|
-
background: 'linear-gradient(90deg, #61DAFB, #21A1F1)',
|
|
1132
|
-
WebkitBackgroundClip: 'text',
|
|
1133
|
-
WebkitTextFillColor: 'transparent',
|
|
1134
|
-
},
|
|
1135
|
-
navLinks: { display: 'flex', gap: 24 },
|
|
1136
|
-
navLink: { color: '#94a3b8', textDecoration: 'none', fontSize: 14 },
|
|
1137
|
-
hero: {
|
|
1138
|
-
display: 'flex',
|
|
1139
|
-
flexDirection: 'column',
|
|
1140
|
-
alignItems: 'center',
|
|
1141
|
-
justifyContent: 'center',
|
|
1142
|
-
textAlign: 'center',
|
|
1143
|
-
padding: '140px 24px 80px',
|
|
1144
|
-
},
|
|
1145
|
-
badge: {
|
|
1146
|
-
background: 'rgba(99, 102, 241, 0.2)',
|
|
1147
|
-
border: '1px solid rgba(99, 102, 241, 0.3)',
|
|
1148
|
-
borderRadius: 9999,
|
|
1149
|
-
padding: '8px 16px',
|
|
1150
|
-
fontSize: 14,
|
|
1151
|
-
marginBottom: 24,
|
|
1152
|
-
},
|
|
1153
|
-
title: {
|
|
1154
|
-
fontSize: 'clamp(2.5rem, 8vw, 4.5rem)',
|
|
1155
|
-
fontWeight: 800,
|
|
1156
|
-
lineHeight: 1.1,
|
|
1157
|
-
marginBottom: 24,
|
|
1158
|
-
},
|
|
1159
|
-
titleGradient: {
|
|
1160
|
-
background: 'linear-gradient(90deg, #61DAFB, #a78bfa, #61DAFB)',
|
|
1161
|
-
WebkitBackgroundClip: 'text',
|
|
1162
|
-
WebkitTextFillColor: 'transparent',
|
|
1163
|
-
},
|
|
1164
|
-
subtitle: {
|
|
1165
|
-
fontSize: 18,
|
|
1166
|
-
color: '#94a3b8',
|
|
1167
|
-
maxWidth: 600,
|
|
1168
|
-
lineHeight: 1.6,
|
|
1169
|
-
marginBottom: 32,
|
|
1170
|
-
},
|
|
1171
|
-
buttons: { display: 'flex', gap: 16, flexWrap: 'wrap', justifyContent: 'center' },
|
|
1172
|
-
primaryBtn: {
|
|
1173
|
-
background: 'linear-gradient(135deg, #6366f1, #8b5cf6)',
|
|
1174
|
-
color: '#fff',
|
|
1175
|
-
padding: '14px 28px',
|
|
1176
|
-
borderRadius: 12,
|
|
1177
|
-
textDecoration: 'none',
|
|
1178
|
-
fontWeight: 600,
|
|
1179
|
-
boxShadow: '0 4px 20px rgba(99, 102, 241, 0.4)',
|
|
1180
|
-
},
|
|
1181
|
-
secondaryBtn: {
|
|
1182
|
-
background: 'transparent',
|
|
1183
|
-
color: '#f8fafc',
|
|
1184
|
-
padding: '14px 28px',
|
|
1185
|
-
borderRadius: 12,
|
|
1186
|
-
textDecoration: 'none',
|
|
1187
|
-
fontWeight: 600,
|
|
1188
|
-
border: '1px solid rgba(255,255,255,0.2)',
|
|
1189
|
-
},
|
|
1190
|
-
features: {
|
|
1191
|
-
padding: '80px 24px',
|
|
1192
|
-
maxWidth: 1200,
|
|
1193
|
-
margin: '0 auto',
|
|
1194
|
-
},
|
|
1195
|
-
featuresTitle: {
|
|
1196
|
-
fontSize: 32,
|
|
1197
|
-
fontWeight: 700,
|
|
1198
|
-
textAlign: 'center',
|
|
1199
|
-
marginBottom: 48,
|
|
1200
|
-
},
|
|
1201
|
-
grid: {
|
|
1202
|
-
display: 'grid',
|
|
1203
|
-
gridTemplateColumns: 'repeat(auto-fit, minmax(280px, 1fr))',
|
|
1204
|
-
gap: 24,
|
|
1205
|
-
},
|
|
1206
|
-
card: {
|
|
1207
|
-
background: 'rgba(255,255,255,0.05)',
|
|
1208
|
-
border: '1px solid rgba(255,255,255,0.1)',
|
|
1209
|
-
borderRadius: 16,
|
|
1210
|
-
padding: 24,
|
|
1211
|
-
},
|
|
1212
|
-
cardIcon: { fontSize: 32, marginBottom: 12 },
|
|
1213
|
-
cardTitle: { fontSize: 18, fontWeight: 600, marginBottom: 8 },
|
|
1214
|
-
cardDesc: { fontSize: 14, color: '#94a3b8', lineHeight: 1.5 },
|
|
1215
|
-
footer: {
|
|
1216
|
-
textAlign: 'center',
|
|
1217
|
-
padding: 32,
|
|
1218
|
-
color: '#64748b',
|
|
1219
|
-
borderTop: '1px solid rgba(255,255,255,0.1)',
|
|
1220
|
-
},
|
|
1221
|
-
};
|
|
1222
|
-
`;
|
|
1223
|
-
fs2.writeFileSync(path2.join(projectPath, "pages/index.jsx"), homePage);
|
|
1224
|
-
const apiRoute = `/**
|
|
1225
|
-
* API Route: /api/hello
|
|
1226
|
-
*/
|
|
1227
|
-
|
|
1228
|
-
export function get(req${ext === "tsx" ? ": any" : ""}, res${ext === "tsx" ? ": any" : ""}) {
|
|
1229
|
-
res.json({
|
|
1230
|
-
message: 'Hello from FlexiReact API! \u{1F680}',
|
|
1231
|
-
timestamp: new Date().toISOString(),
|
|
1232
|
-
framework: 'FlexiReact v3.1'
|
|
1233
|
-
});
|
|
1234
|
-
}
|
|
1235
|
-
|
|
1236
|
-
export function post(req${ext === "tsx" ? ": any" : ""}, res${ext === "tsx" ? ": any" : ""}) {
|
|
1237
|
-
const { name } = req.body || {};
|
|
1238
|
-
res.json({
|
|
1239
|
-
message: \`Hello, \${name || 'World'}!\`,
|
|
1240
|
-
timestamp: new Date().toISOString()
|
|
1241
|
-
});
|
|
1242
|
-
}
|
|
1243
|
-
`;
|
|
1244
|
-
fs2.writeFileSync(path2.join(projectPath, `pages/api/hello.${ext === "tsx" ? "ts" : "js"}`), apiRoute);
|
|
1245
|
-
fs2.writeFileSync(path2.join(projectPath, "public/.gitkeep"), "");
|
|
1246
|
-
}
|
|
1247
1001
|
async function runDev() {
|
|
1248
|
-
console.log(
|
|
1249
|
-
${pc2.cyan(" \u256D\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256E")}
|
|
1250
|
-
${pc2.cyan(" \u2502")} ${pc2.cyan("\u2502")}
|
|
1251
|
-
${pc2.cyan(" \u2502")} ${pc2.bold(pc2.cyan("\u269B"))} ${pc2.bold(pc2.white("F L E X I R E A C T"))} ${pc2.cyan("\u2502")}
|
|
1252
|
-
${pc2.cyan(" \u2502")} ${pc2.cyan("\u2502")}
|
|
1253
|
-
${pc2.cyan(" \u2502")} ${pc2.dim("The Modern React Framework")} ${pc2.cyan("\u2502")}
|
|
1254
|
-
${pc2.cyan(" \u2502")} ${pc2.cyan("\u2502")}
|
|
1255
|
-
${pc2.cyan(" \u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256F")}
|
|
1256
|
-
`);
|
|
1002
|
+
console.log("");
|
|
1257
1003
|
const isBuilt = __dirname2.includes("dist");
|
|
1258
1004
|
const ext = isBuilt ? "js" : "ts";
|
|
1259
1005
|
const startDevDir = isBuilt ? path2.join(__dirname2, "..", "core") : path2.join(__dirname2, "..", "core");
|
|
@@ -1307,30 +1053,29 @@ async function runBuild(options = {}) {
|
|
|
1307
1053
|
mode: "production",
|
|
1308
1054
|
analyze: options.analyze
|
|
1309
1055
|
});
|
|
1310
|
-
spinner.
|
|
1056
|
+
spinner.stop();
|
|
1057
|
+
log2.success("Build complete");
|
|
1311
1058
|
log2.blank();
|
|
1312
|
-
|
|
1059
|
+
console.log(` ${pc2.dim("Output in")} ${pc2.cyan(".flexi/")}`);
|
|
1313
1060
|
if (options.analyze && result?.analysis) {
|
|
1314
1061
|
log2.blank();
|
|
1315
|
-
|
|
1062
|
+
console.log(` ${pc2.bold("Bundle Analysis")}`);
|
|
1316
1063
|
log2.blank();
|
|
1317
1064
|
const analysis = result.analysis;
|
|
1318
1065
|
const sorted = Object.entries(analysis.files || {}).sort((a, b) => b[1].size - a[1].size);
|
|
1319
|
-
console.log(pc2.dim("
|
|
1320
|
-
console.log(
|
|
1321
|
-
console.log(pc2.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
1066
|
+
console.log(` ${pc2.dim("File")} ${pc2.dim("Size")} ${pc2.dim("Gzip")}`);
|
|
1067
|
+
console.log(pc2.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
1322
1068
|
for (const [file, info] of sorted.slice(0, 15)) {
|
|
1323
|
-
const name = file.length >
|
|
1069
|
+
const name = file.length > 40 ? "..." + file.slice(-37) : file;
|
|
1324
1070
|
const size = formatBytes(info.size);
|
|
1325
|
-
const gzip = info.gzipSize ?
|
|
1326
|
-
console.log(` ${name.padEnd(
|
|
1327
|
-
}
|
|
1328
|
-
console.log(pc2.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
1329
|
-
console.log(` ${pc2.bold("Total:")}${" ".repeat(31)} ${pc2.green(formatBytes(analysis.totalSize || 0))}`);
|
|
1330
|
-
if (analysis.totalGzipSize) {
|
|
1331
|
-
console.log(` ${pc2.dim("Gzipped:")}${" ".repeat(29)} ${pc2.dim(formatBytes(analysis.totalGzipSize))}`);
|
|
1071
|
+
const gzip = info.gzipSize ? formatBytes(info.gzipSize) : "-";
|
|
1072
|
+
console.log(` ${name.padEnd(43)} ${size.padEnd(12)} ${pc2.dim(gzip)}`);
|
|
1332
1073
|
}
|
|
1333
1074
|
log2.blank();
|
|
1075
|
+
const total = formatBytes(analysis.totalSize || 0);
|
|
1076
|
+
const totalGzip = analysis.totalGzipSize ? formatBytes(analysis.totalGzipSize) : "-";
|
|
1077
|
+
console.log(` ${pc2.dim("Total:")} ${pc2.bold(total)} ${pc2.dim(`(Gzip: ${totalGzip})`)}`);
|
|
1078
|
+
log2.blank();
|
|
1334
1079
|
}
|
|
1335
1080
|
} catch (error) {
|
|
1336
1081
|
spinner.fail("Build failed");
|
|
@@ -1371,9 +1116,8 @@ async function runStart() {
|
|
|
1371
1116
|
process.on("SIGTERM", () => child.kill("SIGTERM"));
|
|
1372
1117
|
}
|
|
1373
1118
|
async function runDoctor() {
|
|
1374
|
-
console.log(MINI_LOGO);
|
|
1375
1119
|
log2.blank();
|
|
1376
|
-
|
|
1120
|
+
console.log(` ${pc2.bold("Health Check")}`);
|
|
1377
1121
|
log2.blank();
|
|
1378
1122
|
const checks = [];
|
|
1379
1123
|
const projectRoot = process.cwd();
|
|
@@ -1436,7 +1180,7 @@ async function runDoctor() {
|
|
|
1436
1180
|
icon = "\u25CB";
|
|
1437
1181
|
color = pc2.cyan;
|
|
1438
1182
|
}
|
|
1439
|
-
console.log(` ${color(icon)} ${check.name}
|
|
1183
|
+
console.log(` ${color(icon)} ${check.name.padEnd(20)} ${pc2.dim(check.message)}`);
|
|
1440
1184
|
}
|
|
1441
1185
|
log2.blank();
|
|
1442
1186
|
if (hasErrors) {
|
|
@@ -1450,28 +1194,19 @@ async function runDoctor() {
|
|
|
1450
1194
|
}
|
|
1451
1195
|
function showHelp() {
|
|
1452
1196
|
console.log(LOGO);
|
|
1453
|
-
console.log(` ${pc2.bold("Usage
|
|
1454
|
-
console.log(` $
|
|
1455
|
-
log2.blank();
|
|
1456
|
-
console.log(` ${pc2.bold("Commands:")}`);
|
|
1457
|
-
console.log(` ${pc2.cyan("create")} ${pc2.dim("<name>")} Create a new FlexiReact project`);
|
|
1458
|
-
console.log(` ${pc2.cyan("dev")} Start development server`);
|
|
1459
|
-
console.log(` ${pc2.cyan("build")} Build for production`);
|
|
1460
|
-
console.log(` ${pc2.cyan("start")} Start production server`);
|
|
1461
|
-
console.log(` ${pc2.cyan("generate")} ${pc2.dim("<type>")} Generate component/page/hook/etc (alias: g)`);
|
|
1462
|
-
console.log(` ${pc2.cyan("doctor")} Check project health`);
|
|
1463
|
-
console.log(` ${pc2.cyan("help")} Show this help message`);
|
|
1197
|
+
console.log(` ${pc2.bold("Usage")}`);
|
|
1198
|
+
console.log(` $ flexi <command> [options]`);
|
|
1464
1199
|
log2.blank();
|
|
1465
|
-
console.log(` ${pc2.bold("
|
|
1466
|
-
console.log(` ${pc2.dim("
|
|
1467
|
-
console.log(` ${pc2.dim("
|
|
1200
|
+
console.log(` ${pc2.bold("Commands")}`);
|
|
1201
|
+
console.log(` ${pc2.cyan("create")} ${pc2.dim("Create a new project")}`);
|
|
1202
|
+
console.log(` ${pc2.cyan("dev")} ${pc2.dim("Start development server")}`);
|
|
1203
|
+
console.log(` ${pc2.cyan("build")} ${pc2.dim("Build for production")}`);
|
|
1204
|
+
console.log(` ${pc2.cyan("start")} ${pc2.dim("Start production server")}`);
|
|
1205
|
+
console.log(` ${pc2.cyan("doctor")} ${pc2.dim("Check project health")}`);
|
|
1468
1206
|
log2.blank();
|
|
1469
|
-
console.log(` ${pc2.bold("
|
|
1470
|
-
console.log(` $
|
|
1471
|
-
console.log(` ${pc2.dim("
|
|
1472
|
-
console.log(` ${pc2.dim("$")} flexi g component Button`);
|
|
1473
|
-
console.log(` ${pc2.dim("$")} flexi g page dashboard`);
|
|
1474
|
-
console.log(` ${pc2.dim("$")} flexi build --analyze`);
|
|
1207
|
+
console.log(` ${pc2.bold("Generators")}`);
|
|
1208
|
+
console.log(` $ flexi g <type> [name]`);
|
|
1209
|
+
console.log(` ${pc2.dim("Types:")} page, component, hook, api, action, middleware`);
|
|
1475
1210
|
log2.blank();
|
|
1476
1211
|
}
|
|
1477
1212
|
async function main() {
|
|
@@ -1521,8 +1256,13 @@ async function main() {
|
|
|
1521
1256
|
process.exit(command ? 1 : 0);
|
|
1522
1257
|
}
|
|
1523
1258
|
}
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1259
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
1260
|
+
main().catch((error) => {
|
|
1261
|
+
log2.error(error.message);
|
|
1262
|
+
process.exit(1);
|
|
1263
|
+
});
|
|
1264
|
+
}
|
|
1265
|
+
export {
|
|
1266
|
+
createProject
|
|
1267
|
+
};
|
|
1528
1268
|
//# sourceMappingURL=index.js.map
|