revine 0.8.0 → 0.9.0
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 +81 -81
- package/dist/commands/createProject.js +20 -2
- package/dist/config/package.js +4 -0
- package/dist/index.js +64 -2
- package/dist/prompts/project.js +11 -8
- package/dist/runtime/bundler/defaults/vite.js +17 -0
- package/dist/runtime/bundler/generateConfig.js +27 -0
- package/dist/runtime/bundler/revinePlugin.js +68 -0
- package/dist/runtime/bundler/utils/loadUserConfig.js +20 -0
- package/dist/runtime/bundler/vite.config.js +7 -0
- package/dist/runtime/bundler/viteLoggerPlugin.js +27 -0
- package/dist/runtime/routing/fileBased.js +29 -0
- package/dist/setup/dependencies.js +8 -0
- package/dist/setup/tailwind.js +128 -133
- package/package.json +44 -29
- package/src/commands/createProject.ts +88 -65
- package/src/config/package.ts +28 -23
- package/src/config/readme.ts +7 -7
- package/src/config/vite.ts +19 -19
- package/src/index.ts +91 -15
- package/src/prompts/git.ts +61 -61
- package/src/prompts/index.ts +3 -3
- package/src/prompts/project.ts +34 -31
- package/src/prompts/tailwind.ts +13 -13
- package/{template/.revine → src/runtime}/bundler/defaults/vite.ts +18 -18
- package/src/runtime/bundler/generateConfig.ts +36 -0
- package/src/runtime/bundler/revinePlugin.ts +71 -0
- package/src/runtime/bundler/utils/loadUserConfig.ts +19 -0
- package/{template/.revine → src/runtime}/bundler/vite.config.ts +8 -8
- package/{template/.revine → src/runtime}/bundler/viteLoggerPlugin.ts +33 -33
- package/{template/.revine → src/runtime}/routing/fileBased.tsx +46 -44
- package/src/setup/dependencies.ts +26 -16
- package/src/setup/tailwind.ts +151 -163
- package/src/utils/file.ts +9 -9
- package/src/utils/logger.ts +9 -9
- package/template/README.md +62 -62
- package/template/index.html +19 -19
- package/template/package.json +21 -24
- package/template/revine.config.ts +13 -13
- package/template/src/NotFound.tsx +13 -13
- package/template/src/pages/index.tsx +62 -62
- package/template/src/root.tsx +14 -14
- package/template/src/styles/global.css +191 -191
- package/template/tsconfig.json +20 -24
- package/tsconfig.json +15 -14
- package/dist/commands/create.js +0 -65
- package/dist/installers/dependencies.js +0 -15
- package/dist/lib/setup/directory.js +0 -21
- package/dist/lib/setup/package.js +0 -17
- package/dist/lib/setup/tailwind.js +0 -22
- package/dist/lib/utils/exec.js +0 -15
- package/dist/lib/utils/paths.js +0 -6
- package/template/.revine/bundler/generateConfig.ts +0 -18
- package/template/.revine/bundler/utils/loadUserConfig.ts +0 -13
- /package/{template/.revine → src/runtime}/bundler/types/vite-env.d.ts +0 -0
package/dist/setup/tailwind.js
CHANGED
|
@@ -1,151 +1,146 @@
|
|
|
1
1
|
import path from "path";
|
|
2
2
|
import fs from "fs-extra";
|
|
3
|
-
import { updateViteConfig } from "../config/vite.js";
|
|
4
3
|
import { logInfo } from "../utils/logger.js";
|
|
5
4
|
export async function setupTailwind(projectDir) {
|
|
6
5
|
logInfo("\nSetting up Tailwind CSS...");
|
|
7
|
-
// Point to the hidden Vite config
|
|
8
|
-
const viteConfigPath = path.join(projectDir, ".revine", "bundler", "defaults", "vite.ts");
|
|
9
|
-
// Use existing updateViteConfig logic on this new path
|
|
10
|
-
await updateViteConfig(viteConfigPath);
|
|
11
6
|
// Write the Tailwind CSS import into the existing global.css file
|
|
12
7
|
const cssFile = path.join(projectDir, "src", "styles", "global.css");
|
|
13
8
|
const cssFileContent = `@import 'tailwindcss';\n`;
|
|
14
9
|
await fs.writeFile(cssFile, cssFileContent);
|
|
15
10
|
// Update the starter file for Tailwind classes
|
|
16
11
|
const starterFile = path.join(projectDir, "src", "pages", "index.tsx");
|
|
17
|
-
const starterFileContent = `
|
|
18
|
-
export default function HomePage() {
|
|
19
|
-
return (
|
|
20
|
-
<main className="flex min-h-screen flex-col items-center justify-center p-6 bg-gradient-to-b from-white via-white to-indigo-200">
|
|
21
|
-
{/* Hero Section */}
|
|
22
|
-
<div className="max-w-screen-lg w-full text-center space-y-6">
|
|
23
|
-
<h1 className="text-4xl sm:text-6xl font-extrabold text-gray-900 tracking-tight leading-tight">
|
|
24
|
-
Welcome to{" "}
|
|
25
|
-
<span className="text-transparent bg-clip-text bg-gradient-to-r from-indigo-500 via-indigo-600 to-black">
|
|
26
|
-
Revine
|
|
27
|
-
</span>
|
|
28
|
-
</h1>
|
|
29
|
-
<p className="text-xl sm:text-2xl text-gray-600 font-light">
|
|
30
|
-
The modern, powerful, and streamlined React framework.
|
|
31
|
-
</p>
|
|
32
|
-
</div>
|
|
33
|
-
|
|
34
|
-
{/* CTA Buttons */}
|
|
35
|
-
<div className="mt-8 flex space-x-4">
|
|
36
|
-
<a
|
|
37
|
-
href="#get-started"
|
|
38
|
-
className="rounded-md bg-indigo-600 px-6 py-3 text-white font-semibold shadow-md hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 transition-colors"
|
|
39
|
-
>
|
|
40
|
-
Get Started
|
|
41
|
-
</a>
|
|
42
|
-
<a
|
|
43
|
-
href="#docs"
|
|
44
|
-
className="rounded-md bg-white px-6 py-3 text-indigo-600 font-semibold border border-indigo-200 shadow hover:bg-gray-100 transition-colors focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
|
|
45
|
-
>
|
|
46
|
-
Read Docs
|
|
47
|
-
</a>
|
|
48
|
-
</div>
|
|
49
|
-
|
|
50
|
-
{/* Features Section */}
|
|
51
|
-
<div className="mt-12 grid gap-6 sm:grid-cols-2 lg:grid-cols-3 max-w-screen-lg w-full">
|
|
52
|
-
<a
|
|
53
|
-
href="#fast"
|
|
54
|
-
className="block rounded-xl border border-gray-200 bg-white p-6 shadow transition hover:shadow-xl hover:-translate-y-1"
|
|
55
|
-
>
|
|
56
|
-
<h3 className="text-lg font-semibold text-gray-900 mb-2">
|
|
57
|
-
Lightning Fast
|
|
58
|
-
</h3>
|
|
59
|
-
<p className="text-gray-600">
|
|
60
|
-
Built on Vite for ultra-fast development and instant HMR.
|
|
61
|
-
</p>
|
|
62
|
-
</a>
|
|
63
|
-
|
|
64
|
-
<a
|
|
65
|
-
href="#routing"
|
|
66
|
-
className="block rounded-xl border border-gray-200 bg-white p-6 shadow transition hover:shadow-xl hover:-translate-y-1"
|
|
67
|
-
>
|
|
68
|
-
<h3 className="text-lg font-semibold text-gray-900 mb-2">
|
|
69
|
-
Simple File-based Routing
|
|
70
|
-
</h3>
|
|
71
|
-
<p className="text-gray-600">
|
|
72
|
-
Create pages in <code>src/pages</code> and Revine will handle the
|
|
73
|
-
rest.
|
|
74
|
-
</p>
|
|
75
|
-
</a>
|
|
76
|
-
|
|
77
|
-
<a
|
|
78
|
-
href="#tailwind"
|
|
79
|
-
className="block rounded-xl border border-gray-200 bg-white p-6 shadow transition hover:shadow-xl hover:-translate-y-1"
|
|
80
|
-
>
|
|
81
|
-
<h3 className="text-lg font-semibold text-gray-900 mb-2">
|
|
82
|
-
Tailwind Integration
|
|
83
|
-
</h3>
|
|
84
|
-
<p className="text-gray-600">
|
|
85
|
-
Pre-configured for Tailwind CSS, so you can style quickly and
|
|
86
|
-
easily.
|
|
87
|
-
</p>
|
|
88
|
-
</a>
|
|
89
|
-
|
|
90
|
-
<a
|
|
91
|
-
href="#dev-experience"
|
|
92
|
-
className="block rounded-xl border border-gray-200 bg-white p-6 shadow transition hover:shadow-xl hover:-translate-y-1"
|
|
93
|
-
>
|
|
94
|
-
<h3 className="text-lg font-semibold text-gray-900 mb-2">Great DX</h3>
|
|
95
|
-
<p className="text-gray-600">
|
|
96
|
-
Minimal config, fast builds, custom logging, and more.
|
|
97
|
-
</p>
|
|
98
|
-
</a>
|
|
99
|
-
|
|
100
|
-
<a
|
|
101
|
-
href="#abstract"
|
|
102
|
-
className="block rounded-xl border border-gray-200 bg-white p-6 shadow transition hover:shadow-xl hover:-translate-y-1"
|
|
103
|
-
>
|
|
104
|
-
<h3 className="text-lg font-semibold text-gray-900 mb-2">
|
|
105
|
-
Abstracted Internals
|
|
106
|
-
</h3>
|
|
107
|
-
<p className="text-gray-600">
|
|
108
|
-
A .revine folder houses the complex Vite config. Keep your root
|
|
109
|
-
clean.
|
|
110
|
-
</p>
|
|
111
|
-
</a>
|
|
112
|
-
|
|
113
|
-
<a
|
|
114
|
-
href="#customize"
|
|
115
|
-
className="block rounded-xl border border-gray-200 bg-white p-6 shadow transition hover:shadow-xl hover:-translate-y-1"
|
|
116
|
-
>
|
|
117
|
-
<h3 className="text-lg font-semibold text-gray-900 mb-2">
|
|
118
|
-
Fully Customizable
|
|
119
|
-
</h3>
|
|
120
|
-
<p className="text-gray-600">
|
|
121
|
-
Easily extend or override settings in <code>revine.config.ts</code>.
|
|
122
|
-
</p>
|
|
123
|
-
</a>
|
|
124
|
-
</div>
|
|
125
|
-
</main>
|
|
126
|
-
);
|
|
127
|
-
}
|
|
12
|
+
const starterFileContent = `
|
|
13
|
+
export default function HomePage() {
|
|
14
|
+
return (
|
|
15
|
+
<main className="flex min-h-screen flex-col items-center justify-center p-6 bg-gradient-to-b from-white via-white to-indigo-200">
|
|
16
|
+
{/* Hero Section */}
|
|
17
|
+
<div className="max-w-screen-lg w-full text-center space-y-6">
|
|
18
|
+
<h1 className="text-4xl sm:text-6xl font-extrabold text-gray-900 tracking-tight leading-tight">
|
|
19
|
+
Welcome to{" "}
|
|
20
|
+
<span className="text-transparent bg-clip-text bg-gradient-to-r from-indigo-500 via-indigo-600 to-black">
|
|
21
|
+
Revine
|
|
22
|
+
</span>
|
|
23
|
+
</h1>
|
|
24
|
+
<p className="text-xl sm:text-2xl text-gray-600 font-light">
|
|
25
|
+
The modern, powerful, and streamlined React framework.
|
|
26
|
+
</p>
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
{/* CTA Buttons */}
|
|
30
|
+
<div className="mt-8 flex space-x-4">
|
|
31
|
+
<a
|
|
32
|
+
href="#get-started"
|
|
33
|
+
className="rounded-md bg-indigo-600 px-6 py-3 text-white font-semibold shadow-md hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 transition-colors"
|
|
34
|
+
>
|
|
35
|
+
Get Started
|
|
36
|
+
</a>
|
|
37
|
+
<a
|
|
38
|
+
href="#docs"
|
|
39
|
+
className="rounded-md bg-white px-6 py-3 text-indigo-600 font-semibold border border-indigo-200 shadow hover:bg-gray-100 transition-colors focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
|
|
40
|
+
>
|
|
41
|
+
Read Docs
|
|
42
|
+
</a>
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
{/* Features Section */}
|
|
46
|
+
<div className="mt-12 grid gap-6 sm:grid-cols-2 lg:grid-cols-3 max-w-screen-lg w-full">
|
|
47
|
+
<a
|
|
48
|
+
href="#fast"
|
|
49
|
+
className="block rounded-xl border border-gray-200 bg-white p-6 shadow transition hover:shadow-xl hover:-translate-y-1"
|
|
50
|
+
>
|
|
51
|
+
<h3 className="text-lg font-semibold text-gray-900 mb-2">
|
|
52
|
+
Lightning Fast
|
|
53
|
+
</h3>
|
|
54
|
+
<p className="text-gray-600">
|
|
55
|
+
Built on Vite for ultra-fast development and instant HMR.
|
|
56
|
+
</p>
|
|
57
|
+
</a>
|
|
58
|
+
|
|
59
|
+
<a
|
|
60
|
+
href="#routing"
|
|
61
|
+
className="block rounded-xl border border-gray-200 bg-white p-6 shadow transition hover:shadow-xl hover:-translate-y-1"
|
|
62
|
+
>
|
|
63
|
+
<h3 className="text-lg font-semibold text-gray-900 mb-2">
|
|
64
|
+
Simple File-based Routing
|
|
65
|
+
</h3>
|
|
66
|
+
<p className="text-gray-600">
|
|
67
|
+
Create pages in <code>src/pages</code> and Revine will handle the
|
|
68
|
+
rest.
|
|
69
|
+
</p>
|
|
70
|
+
</a>
|
|
71
|
+
|
|
72
|
+
<a
|
|
73
|
+
href="#tailwind"
|
|
74
|
+
className="block rounded-xl border border-gray-200 bg-white p-6 shadow transition hover:shadow-xl hover:-translate-y-1"
|
|
75
|
+
>
|
|
76
|
+
<h3 className="text-lg font-semibold text-gray-900 mb-2">
|
|
77
|
+
Tailwind Integration
|
|
78
|
+
</h3>
|
|
79
|
+
<p className="text-gray-600">
|
|
80
|
+
Pre-configured for Tailwind CSS, so you can style quickly and
|
|
81
|
+
easily.
|
|
82
|
+
</p>
|
|
83
|
+
</a>
|
|
84
|
+
|
|
85
|
+
<a
|
|
86
|
+
href="#dev-experience"
|
|
87
|
+
className="block rounded-xl border border-gray-200 bg-white p-6 shadow transition hover:shadow-xl hover:-translate-y-1"
|
|
88
|
+
>
|
|
89
|
+
<h3 className="text-lg font-semibold text-gray-900 mb-2">Great DX</h3>
|
|
90
|
+
<p className="text-gray-600">
|
|
91
|
+
Minimal config, fast builds, custom logging, and more.
|
|
92
|
+
</p>
|
|
93
|
+
</a>
|
|
94
|
+
|
|
95
|
+
<a
|
|
96
|
+
href="#abstract"
|
|
97
|
+
className="block rounded-xl border border-gray-200 bg-white p-6 shadow transition hover:shadow-xl hover:-translate-y-1"
|
|
98
|
+
>
|
|
99
|
+
<h3 className="text-lg font-semibold text-gray-900 mb-2">
|
|
100
|
+
Abstracted Internals
|
|
101
|
+
</h3>
|
|
102
|
+
<p className="text-gray-600">
|
|
103
|
+
A .revine folder houses the complex Vite config. Keep your root
|
|
104
|
+
clean.
|
|
105
|
+
</p>
|
|
106
|
+
</a>
|
|
107
|
+
|
|
108
|
+
<a
|
|
109
|
+
href="#customize"
|
|
110
|
+
className="block rounded-xl border border-gray-200 bg-white p-6 shadow transition hover:shadow-xl hover:-translate-y-1"
|
|
111
|
+
>
|
|
112
|
+
<h3 className="text-lg font-semibold text-gray-900 mb-2">
|
|
113
|
+
Fully Customizable
|
|
114
|
+
</h3>
|
|
115
|
+
<p className="text-gray-600">
|
|
116
|
+
Easily extend or override settings in <code>revine.config.ts</code>.
|
|
117
|
+
</p>
|
|
118
|
+
</a>
|
|
119
|
+
</div>
|
|
120
|
+
</main>
|
|
121
|
+
);
|
|
122
|
+
}
|
|
128
123
|
`;
|
|
129
124
|
await fs.writeFile(starterFile, starterFileContent);
|
|
130
125
|
// Replace the NotFound.tsx content
|
|
131
126
|
const notFoundFile = path.join(projectDir, "src", "NotFound.tsx");
|
|
132
|
-
const notFoundContent = `
|
|
133
|
-
export default function NotFound() {
|
|
134
|
-
return (
|
|
135
|
-
<div className="min-h-screen flex items-center justify-center bg-gray-100">
|
|
136
|
-
<div className="text-center space-y-4">
|
|
137
|
-
<h1 className="text-6xl font-bold text-gray-900">404</h1>
|
|
138
|
-
<p className="text-xl text-gray-600">Page Not Found</p>
|
|
139
|
-
<a
|
|
140
|
-
href="/"
|
|
141
|
-
className="mt-6 inline-block bg-indigo-600 text-white font-semibold px-6 py-3 rounded-md shadow hover:bg-indigo-700"
|
|
142
|
-
>
|
|
143
|
-
Go Back Home
|
|
144
|
-
</a>
|
|
145
|
-
</div>
|
|
146
|
-
</div>
|
|
147
|
-
);
|
|
148
|
-
}
|
|
127
|
+
const notFoundContent = `
|
|
128
|
+
export default function NotFound() {
|
|
129
|
+
return (
|
|
130
|
+
<div className="min-h-screen flex items-center justify-center bg-gray-100">
|
|
131
|
+
<div className="text-center space-y-4">
|
|
132
|
+
<h1 className="text-6xl font-bold text-gray-900">404</h1>
|
|
133
|
+
<p className="text-xl text-gray-600">Page Not Found</p>
|
|
134
|
+
<a
|
|
135
|
+
href="/"
|
|
136
|
+
className="mt-6 inline-block bg-indigo-600 text-white font-semibold px-6 py-3 rounded-md shadow hover:bg-indigo-700"
|
|
137
|
+
>
|
|
138
|
+
Go Back Home
|
|
139
|
+
</a>
|
|
140
|
+
</div>
|
|
141
|
+
</div>
|
|
142
|
+
);
|
|
143
|
+
}
|
|
149
144
|
`;
|
|
150
145
|
await fs.writeFile(notFoundFile, notFoundContent);
|
|
151
146
|
}
|
package/package.json
CHANGED
|
@@ -1,29 +1,44 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "revine",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "A react framework, but better.",
|
|
5
|
-
"license": "ISC",
|
|
6
|
-
"author": "Rachit Bharadwaj",
|
|
7
|
-
"type": "module",
|
|
8
|
-
"main": "dist/index.js",
|
|
9
|
-
"bin": {
|
|
10
|
-
"revine": "dist/index.js"
|
|
11
|
-
},
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
},
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
|
|
29
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "revine",
|
|
3
|
+
"version": "0.9.0",
|
|
4
|
+
"description": "A react framework, but better.",
|
|
5
|
+
"license": "ISC",
|
|
6
|
+
"author": "Rachit Bharadwaj",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "dist/index.js",
|
|
9
|
+
"bin": {
|
|
10
|
+
"revine": "dist/index.js"
|
|
11
|
+
},
|
|
12
|
+
"exports": {
|
|
13
|
+
".": "./dist/index.js",
|
|
14
|
+
"./routing": "./dist/runtime/routing/fileBased.js",
|
|
15
|
+
"./bundler/*": "./dist/runtime/bundler/*.js"
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc",
|
|
19
|
+
"dev": "tsc -w",
|
|
20
|
+
"prepublishOnly": "npm run build"
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@vitejs/plugin-react": "^4.2.1",
|
|
24
|
+
"chalk": "^5.4.1",
|
|
25
|
+
"commander": "^13.1.0",
|
|
26
|
+
"cross-spawn": "^7.0.6",
|
|
27
|
+
"fs-extra": "^11.3.0",
|
|
28
|
+
"inquirer": "^12.4.1",
|
|
29
|
+
"lodash-es": "^4.17.21",
|
|
30
|
+
"react": "^18.2.0",
|
|
31
|
+
"react-dom": "^18.2.0",
|
|
32
|
+
"react-router-dom": "^6.22.3",
|
|
33
|
+
"vite": "^5.0.12"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@tailwindcss/vite": "^4.2.0",
|
|
37
|
+
"@types/fs-extra": "^11.0.4",
|
|
38
|
+
"@types/lodash-es": "^4.17.9",
|
|
39
|
+
"@types/node": "^22.13.0",
|
|
40
|
+
"@types/react": "^18.2.45",
|
|
41
|
+
"@types/react-dom": "^18.2.18",
|
|
42
|
+
"typescript": "^5.7.3"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -1,65 +1,88 @@
|
|
|
1
|
-
import path from "path";
|
|
2
|
-
import { fileURLToPath } from "url";
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
//
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
//
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
// Check if
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
1
|
+
import path from "path";
|
|
2
|
+
import { fileURLToPath } from "url";
|
|
3
|
+
import fs from "fs-extra";
|
|
4
|
+
import { updatePackageJson } from "../config/package.js";
|
|
5
|
+
import { updateReadme } from "../config/readme.js";
|
|
6
|
+
import { askForTailwindSetup, initGit, runProject } from "../prompts/index.js";
|
|
7
|
+
import { installDependencies } from "../setup/dependencies.js";
|
|
8
|
+
import { setupTailwind } from "../setup/tailwind.js";
|
|
9
|
+
import { copyTemplate } from "../utils/file.js";
|
|
10
|
+
import { logError, logInfo } from "../utils/logger.js";
|
|
11
|
+
|
|
12
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
13
|
+
const __dirname = path.dirname(__filename);
|
|
14
|
+
|
|
15
|
+
export async function createProject(
|
|
16
|
+
projectName: string,
|
|
17
|
+
options: { force?: boolean }
|
|
18
|
+
) {
|
|
19
|
+
// Calculate directories. This uses "../../template" for your template folder.
|
|
20
|
+
const templateDir = path.join(__dirname, "../../template");
|
|
21
|
+
const projectDir = path.resolve(projectName);
|
|
22
|
+
const isCurrentDir = [".", "./"].includes(projectName);
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
logInfo(`Creating project in ${projectDir}...`);
|
|
26
|
+
|
|
27
|
+
// Ensure the project directory exists
|
|
28
|
+
await fs.ensureDir(projectDir);
|
|
29
|
+
|
|
30
|
+
// This copies everything, including hidden directories like .revine
|
|
31
|
+
await copyTemplate(templateDir, projectDir, options.force);
|
|
32
|
+
|
|
33
|
+
// Derive final project name
|
|
34
|
+
const finalProjectName = isCurrentDir
|
|
35
|
+
? path.basename(projectDir)
|
|
36
|
+
: projectName;
|
|
37
|
+
|
|
38
|
+
// Check if package.json exists after template copy
|
|
39
|
+
const packageJsonPath = path.join(projectDir, "package.json");
|
|
40
|
+
|
|
41
|
+
// Create basic package.json if it doesn't exist
|
|
42
|
+
if (!await fs.pathExists(packageJsonPath)) {
|
|
43
|
+
const basicPackageJson = {
|
|
44
|
+
name: finalProjectName,
|
|
45
|
+
version: "0.1.0",
|
|
46
|
+
private: true,
|
|
47
|
+
type: "module"
|
|
48
|
+
};
|
|
49
|
+
await fs.writeJSON(packageJsonPath, basicPackageJson, { spaces: 2 });
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Update package.json with the correct details
|
|
53
|
+
const useTailwind = await askForTailwindSetup();
|
|
54
|
+
await updatePackageJson(packageJsonPath, finalProjectName, { useTailwind });
|
|
55
|
+
|
|
56
|
+
// Check if README exists, create it if it doesn't
|
|
57
|
+
const readmePath = path.join(projectDir, "README.md");
|
|
58
|
+
if (!await fs.pathExists(readmePath)) {
|
|
59
|
+
await fs.writeFile(readmePath, `# ${finalProjectName}\n\nCreated with Revine`);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Update README with the project name
|
|
63
|
+
await updateReadme(readmePath, finalProjectName);
|
|
64
|
+
|
|
65
|
+
// Install dependencies
|
|
66
|
+
logInfo("\nInstalling dependencies...");
|
|
67
|
+
await installDependencies(projectDir);
|
|
68
|
+
|
|
69
|
+
// If Tailwind is selected, set it up
|
|
70
|
+
if (useTailwind) {
|
|
71
|
+
await setupTailwind(projectDir);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
logInfo(`\nSuccess! Created project at ${projectDir}`);
|
|
75
|
+
logInfo("\nStart developing with:");
|
|
76
|
+
if (!isCurrentDir) console.log(` cd ${projectName}`);
|
|
77
|
+
console.log(" npm run dev\n");
|
|
78
|
+
|
|
79
|
+
// Check if Git exists and initialize repository if user agrees
|
|
80
|
+
await initGit(projectDir);
|
|
81
|
+
|
|
82
|
+
// Prompt to run project
|
|
83
|
+
await runProject(projectDir);
|
|
84
|
+
} catch (error) {
|
|
85
|
+
logError("Error during project creation:", error);
|
|
86
|
+
process.exit(1);
|
|
87
|
+
}
|
|
88
|
+
}
|
package/src/config/package.ts
CHANGED
|
@@ -1,23 +1,28 @@
|
|
|
1
|
-
import fs from "fs-extra";
|
|
2
|
-
|
|
3
|
-
interface UpdatePackageOptions {
|
|
4
|
-
useTailwind?: boolean;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export async function updatePackageJson(
|
|
8
|
-
filePath: string,
|
|
9
|
-
projectName: string,
|
|
10
|
-
options: UpdatePackageOptions = {}
|
|
11
|
-
) {
|
|
12
|
-
const packageJson = await fs.readJson(filePath);
|
|
13
|
-
packageJson.name = projectName;
|
|
14
|
-
packageJson.type = "module";
|
|
15
|
-
|
|
16
|
-
packageJson.
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
1
|
+
import fs from "fs-extra";
|
|
2
|
+
|
|
3
|
+
interface UpdatePackageOptions {
|
|
4
|
+
useTailwind?: boolean;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export async function updatePackageJson(
|
|
8
|
+
filePath: string,
|
|
9
|
+
projectName: string,
|
|
10
|
+
options: UpdatePackageOptions = {},
|
|
11
|
+
) {
|
|
12
|
+
const packageJson = await fs.readJson(filePath);
|
|
13
|
+
packageJson.name = projectName;
|
|
14
|
+
packageJson.type = "module";
|
|
15
|
+
packageJson.dependencies = {
|
|
16
|
+
...packageJson.dependencies,
|
|
17
|
+
revine: "latest",
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
if (options.useTailwind) {
|
|
21
|
+
packageJson.devDependencies = {
|
|
22
|
+
...packageJson.devDependencies,
|
|
23
|
+
tailwindcss: "^4.0.0",
|
|
24
|
+
"@tailwindcss/vite": "^4.0.0",
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
await fs.writeJson(filePath, packageJson, { spaces: 2 });
|
|
28
|
+
}
|
package/src/config/readme.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import fs from "fs-extra";
|
|
2
|
-
|
|
3
|
-
export async function updateReadme(filePath: string, projectName: string) {
|
|
4
|
-
let readmeContent = await fs.readFile(filePath, "utf-8");
|
|
5
|
-
readmeContent = readmeContent.replace(/%PROJECT_NAME%/g, projectName);
|
|
6
|
-
await fs.writeFile(filePath, readmeContent);
|
|
7
|
-
}
|
|
1
|
+
import fs from "fs-extra";
|
|
2
|
+
|
|
3
|
+
export async function updateReadme(filePath: string, projectName: string) {
|
|
4
|
+
let readmeContent = await fs.readFile(filePath, "utf-8");
|
|
5
|
+
readmeContent = readmeContent.replace(/%PROJECT_NAME%/g, projectName);
|
|
6
|
+
await fs.writeFile(filePath, readmeContent);
|
|
7
|
+
}
|
package/src/config/vite.ts
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import fs from "fs-extra";
|
|
2
|
-
|
|
3
|
-
export async function updateViteConfig(filePath: string) {
|
|
4
|
-
let viteConfigContent = await fs.readFile(filePath, "utf-8");
|
|
5
|
-
|
|
6
|
-
// Insert Tailwind import after the React plugin import.
|
|
7
|
-
viteConfigContent = viteConfigContent.replace(
|
|
8
|
-
'import react from "@vitejs/plugin-react";',
|
|
9
|
-
"import react from '@vitejs/plugin-react';\nimport tailwindcss from '@tailwindcss/vite';"
|
|
10
|
-
);
|
|
11
|
-
|
|
12
|
-
// Insert Tailwind plugin into the plugins array.
|
|
13
|
-
viteConfigContent = viteConfigContent.replace(
|
|
14
|
-
"plugins: [react(), revineLoggerPlugin()]",
|
|
15
|
-
"plugins: [\n react(),\n revineLoggerPlugin(),\n tailwindcss()\n ]"
|
|
16
|
-
);
|
|
17
|
-
|
|
18
|
-
await fs.writeFile(filePath, viteConfigContent);
|
|
19
|
-
}
|
|
1
|
+
import fs from "fs-extra";
|
|
2
|
+
|
|
3
|
+
export async function updateViteConfig(filePath: string) {
|
|
4
|
+
let viteConfigContent = await fs.readFile(filePath, "utf-8");
|
|
5
|
+
|
|
6
|
+
// Insert Tailwind import after the React plugin import.
|
|
7
|
+
viteConfigContent = viteConfigContent.replace(
|
|
8
|
+
'import react from "@vitejs/plugin-react";',
|
|
9
|
+
"import react from '@vitejs/plugin-react';\nimport tailwindcss from '@tailwindcss/vite';"
|
|
10
|
+
);
|
|
11
|
+
|
|
12
|
+
// Insert Tailwind plugin into the plugins array.
|
|
13
|
+
viteConfigContent = viteConfigContent.replace(
|
|
14
|
+
"plugins: [react(), revineLoggerPlugin()]",
|
|
15
|
+
"plugins: [\n react(),\n revineLoggerPlugin(),\n tailwindcss()\n ]"
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
await fs.writeFile(filePath, viteConfigContent);
|
|
19
|
+
}
|