revine 0.1.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/createProject.js +49 -0
- package/dist/config/package.js +14 -0
- package/dist/config/readme.js +6 -0
- package/dist/config/vite.js +9 -0
- package/dist/index.js +2 -91
- package/dist/installers/dependencies.js +15 -0
- package/dist/prompts/tailwind.js +12 -0
- package/dist/setup/tailwind.js +20 -0
- package/dist/utils/file.js +4 -0
- package/dist/utils/logger.js +7 -0
- package/package.json +1 -1
- package/src/commands/createProject.ts +59 -0
- package/src/config/package.ts +23 -0
- package/src/config/readme.ts +7 -0
- package/src/config/vite.ts +19 -0
- package/src/index.ts +2 -130
- package/src/installers/dependencies.ts +16 -0
- package/src/prompts/tailwind.ts +13 -0
- package/src/setup/tailwind.ts +34 -0
- package/src/utils/file.ts +9 -0
- package/src/utils/logger.ts +9 -0
- package/template/.revine/bundler/defaults/vite.ts +14 -0
- package/template/.revine/bundler/generateConfig.ts +18 -0
- package/template/.revine/bundler/utils/loadUserConfig.ts +13 -0
- package/template/.revine/bundler/vite.config.ts +8 -0
- package/template/index.html +1 -1
- package/template/package.json +22 -20
- package/template/revine.config.ts +13 -0
- package/template/tsconfig.json +1 -1
- package/template/vite.config.ts +0 -15
- /package/template/{src → .revine/bundler/types}/vite-env.d.ts +0 -0
- /package/template/src/{main.tsx → root.tsx} +0 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import { fileURLToPath } from "url";
|
|
3
|
+
import { updatePackageJson } from "../config/package.js";
|
|
4
|
+
import { updateReadme } from "../config/readme.js";
|
|
5
|
+
import { installDependencies } from "../installers/dependencies.js";
|
|
6
|
+
import { askForTailwindSetup } from "../prompts/tailwind.js";
|
|
7
|
+
import { setupTailwind } from "../setup/tailwind.js";
|
|
8
|
+
import { copyTemplate } from "../utils/file.js";
|
|
9
|
+
import { logError, logInfo } from "../utils/logger.js";
|
|
10
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
11
|
+
const __dirname = path.dirname(__filename);
|
|
12
|
+
export async function createProject(projectName, options) {
|
|
13
|
+
// Calculate directories. This uses "../../template" for your template folder.
|
|
14
|
+
const templateDir = path.join(__dirname, "../../template");
|
|
15
|
+
const projectDir = path.resolve(projectName);
|
|
16
|
+
const isCurrentDir = [".", "./"].includes(projectName);
|
|
17
|
+
try {
|
|
18
|
+
logInfo(`Creating project in ${projectDir}...`);
|
|
19
|
+
// This copies everything, including hidden directories like .revine
|
|
20
|
+
await copyTemplate(templateDir, projectDir, options.force);
|
|
21
|
+
// Derive final project name
|
|
22
|
+
const finalProjectName = isCurrentDir
|
|
23
|
+
? path.basename(projectDir)
|
|
24
|
+
: projectName;
|
|
25
|
+
// Update package.json (e.g., set name, set "type": "module", add Tailwind deps if chosen)
|
|
26
|
+
const packageJsonPath = path.join(projectDir, "package.json");
|
|
27
|
+
const useTailwind = await askForTailwindSetup();
|
|
28
|
+
await updatePackageJson(packageJsonPath, finalProjectName, { useTailwind });
|
|
29
|
+
// Update README with the project name
|
|
30
|
+
const readmePath = path.join(projectDir, "README.md");
|
|
31
|
+
await updateReadme(readmePath, finalProjectName);
|
|
32
|
+
// Install dependencies
|
|
33
|
+
logInfo("\nInstalling dependencies...");
|
|
34
|
+
await installDependencies(projectDir);
|
|
35
|
+
// If Tailwind is selected, set it up
|
|
36
|
+
if (useTailwind) {
|
|
37
|
+
await setupTailwind(projectDir);
|
|
38
|
+
}
|
|
39
|
+
logInfo(`\nSuccess! Created project at ${projectDir}`);
|
|
40
|
+
logInfo("\nStart developing with:");
|
|
41
|
+
if (!isCurrentDir)
|
|
42
|
+
console.log(` cd ${projectName}`);
|
|
43
|
+
console.log(" npm run dev\n");
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
logError("Error during project creation:", error);
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import fs from "fs-extra";
|
|
2
|
+
export async function updatePackageJson(filePath, projectName, options = {}) {
|
|
3
|
+
const packageJson = await fs.readJson(filePath);
|
|
4
|
+
packageJson.name = projectName;
|
|
5
|
+
packageJson.type = "module";
|
|
6
|
+
if (options.useTailwind) {
|
|
7
|
+
packageJson.devDependencies = {
|
|
8
|
+
...packageJson.devDependencies,
|
|
9
|
+
tailwindcss: "^4.0.0",
|
|
10
|
+
"@tailwindcss/vite": "^4.0.0",
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
await fs.writeJson(filePath, packageJson, { spaces: 2 });
|
|
14
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import fs from "fs-extra";
|
|
2
|
+
export async function updateReadme(filePath, projectName) {
|
|
3
|
+
let readmeContent = await fs.readFile(filePath, "utf-8");
|
|
4
|
+
readmeContent = readmeContent.replace(/%PROJECT_NAME%/g, projectName);
|
|
5
|
+
await fs.writeFile(filePath, readmeContent);
|
|
6
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import fs from "fs-extra";
|
|
2
|
+
export async function updateViteConfig(filePath) {
|
|
3
|
+
let viteConfigContent = await fs.readFile(filePath, "utf-8");
|
|
4
|
+
// Insert Tailwind import after the React plugin import.
|
|
5
|
+
viteConfigContent = viteConfigContent.replace("import react from '@vitejs/plugin-react';", "import react from '@vitejs/plugin-react';\nimport tailwindcss from '@tailwindcss/vite';");
|
|
6
|
+
// Insert Tailwind plugin into the plugins array.
|
|
7
|
+
viteConfigContent = viteConfigContent.replace("plugins: [react()]", "plugins: [\n react(),\n tailwindcss()\n ]");
|
|
8
|
+
await fs.writeFile(filePath, viteConfigContent);
|
|
9
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -1,101 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import chalk from "chalk";
|
|
3
|
-
import { spawnSync } from "child_process";
|
|
4
2
|
import { Command } from "commander";
|
|
5
|
-
import
|
|
6
|
-
import inquirer from "inquirer";
|
|
7
|
-
import path from "path";
|
|
8
|
-
import { fileURLToPath } from "url";
|
|
9
|
-
// Get directory paths in ESM
|
|
10
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
11
|
-
const __dirname = path.dirname(__filename);
|
|
3
|
+
import { createProject } from "./commands/createProject.js";
|
|
12
4
|
const program = new Command();
|
|
13
5
|
program
|
|
14
6
|
.version("0.1.0")
|
|
15
7
|
.argument("<project-name>")
|
|
16
8
|
.option("-f, --force", "Force creation in non-empty directory")
|
|
17
9
|
.action(async (projectName, options) => {
|
|
18
|
-
|
|
19
|
-
const projectDir = path.resolve(projectName);
|
|
20
|
-
const isCurrentDir = [".", "./"].includes(projectName);
|
|
21
|
-
// ... [keep existing directory checks the same] ...
|
|
22
|
-
try {
|
|
23
|
-
console.log(chalk.cyan(`Creating project in ${projectDir}...`));
|
|
24
|
-
fs.copySync(templateDir, projectDir, { overwrite: options.force });
|
|
25
|
-
// Update package.json with ESM configuration
|
|
26
|
-
const packageJsonPath = path.join(projectDir, "package.json");
|
|
27
|
-
const packageJson = await fs.readJson(packageJsonPath);
|
|
28
|
-
const finalProjectName = isCurrentDir
|
|
29
|
-
? path.basename(projectDir)
|
|
30
|
-
: projectName;
|
|
31
|
-
packageJson.name = finalProjectName;
|
|
32
|
-
packageJson.type = "module"; // Add ESM type declaration
|
|
33
|
-
const npmCmd = process.platform === "win32" ? "npm.cmd" : "npm";
|
|
34
|
-
// Add Tailwind prompt
|
|
35
|
-
const { useTailwind } = await inquirer.prompt([
|
|
36
|
-
{
|
|
37
|
-
type: "confirm",
|
|
38
|
-
name: "useTailwind",
|
|
39
|
-
message: "Would you like to set up Tailwind CSS?",
|
|
40
|
-
default: true,
|
|
41
|
-
},
|
|
42
|
-
]);
|
|
43
|
-
// Add Tailwind v4 dependencies if selected
|
|
44
|
-
if (useTailwind) {
|
|
45
|
-
packageJson.devDependencies = {
|
|
46
|
-
...packageJson.devDependencies,
|
|
47
|
-
tailwindcss: "^4.0.0",
|
|
48
|
-
"@tailwindcss/vite": "^4.0.0",
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
|
|
52
|
-
// Update README
|
|
53
|
-
const readmePath = path.join(projectDir, "README.md");
|
|
54
|
-
let readmeContent = fs.readFileSync(readmePath, "utf-8");
|
|
55
|
-
readmeContent = readmeContent.replace(/%PROJECT_NAME%/g, finalProjectName);
|
|
56
|
-
fs.writeFileSync(readmePath, readmeContent);
|
|
57
|
-
// Install dependencies with error handling
|
|
58
|
-
console.log(chalk.cyan("\nInstalling dependencies..."));
|
|
59
|
-
const installResult = spawnSync(npmCmd, ["install"], {
|
|
60
|
-
stdio: "inherit",
|
|
61
|
-
cwd: projectDir,
|
|
62
|
-
shell: true,
|
|
63
|
-
});
|
|
64
|
-
if (installResult.error || installResult.status !== 0) {
|
|
65
|
-
console.log(chalk.red("\nError installing dependencies!", installResult.error));
|
|
66
|
-
console.log(chalk.yellow("Try running manually: npm install"));
|
|
67
|
-
process.exit(1);
|
|
68
|
-
}
|
|
69
|
-
// Setup Tailwind after dependencies are installed
|
|
70
|
-
if (useTailwind) {
|
|
71
|
-
console.log(chalk.cyan("\nSetting up Tailwind CSS v4..."));
|
|
72
|
-
// Update Vite config to add Tailwind plugin
|
|
73
|
-
const viteConfigPath = path.join(projectDir, "vite.config.ts");
|
|
74
|
-
let viteConfigContent = fs.readFileSync(viteConfigPath, "utf-8");
|
|
75
|
-
// Add Tailwind import
|
|
76
|
-
viteConfigContent = viteConfigContent.replace("import react from '@vitejs/plugin-react';", "import react from '@vitejs/plugin-react';\nimport tailwindcss from '@tailwindcss/vite';");
|
|
77
|
-
// Add Tailwind plugin to existing config
|
|
78
|
-
viteConfigContent = viteConfigContent.replace("plugins: [react()]", "plugins: [\n react(),\n tailwindcss()\n ]");
|
|
79
|
-
fs.writeFileSync(viteConfigPath, viteConfigContent);
|
|
80
|
-
fs.writeFileSync(viteConfigPath, viteConfigContent);
|
|
81
|
-
// Create CSS file with import
|
|
82
|
-
const cssDir = path.join(projectDir, "src", "styles");
|
|
83
|
-
fs.ensureDirSync(cssDir);
|
|
84
|
-
fs.writeFileSync(path.join(cssDir, "global.css"), "@import 'tailwindcss';\n");
|
|
85
|
-
// Add CSS import to main.tsx
|
|
86
|
-
const mainTsxPath = path.join(projectDir, "src", "main.tsx");
|
|
87
|
-
const mainContent = `import './styles/global.css';\n${fs.readFileSync(mainTsxPath, "utf-8")}`;
|
|
88
|
-
fs.writeFileSync(mainTsxPath, mainContent);
|
|
89
|
-
}
|
|
90
|
-
console.log(chalk.green("\nSuccess! Created project at"), chalk.yellow(projectDir));
|
|
91
|
-
console.log(chalk.cyan("\nStart developing with:"));
|
|
92
|
-
if (!isCurrentDir)
|
|
93
|
-
console.log(` cd ${projectName}`);
|
|
94
|
-
console.log(" npm run dev\n");
|
|
95
|
-
}
|
|
96
|
-
catch (error) {
|
|
97
|
-
console.log(chalk.red("Error:"), error);
|
|
98
|
-
process.exit(1);
|
|
99
|
-
}
|
|
10
|
+
await createProject(projectName, options);
|
|
100
11
|
});
|
|
101
12
|
program.parse(process.argv);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { spawnSync } from "child_process";
|
|
2
|
+
import { logError, logInfo } from "../utils/logger.js";
|
|
3
|
+
export async function installDependencies(projectDir) {
|
|
4
|
+
const npmCmd = process.platform === "win32" ? "npm.cmd" : "npm";
|
|
5
|
+
const installResult = spawnSync(npmCmd, ["install"], {
|
|
6
|
+
stdio: "inherit",
|
|
7
|
+
cwd: projectDir,
|
|
8
|
+
shell: true,
|
|
9
|
+
});
|
|
10
|
+
if (installResult.error || installResult.status !== 0) {
|
|
11
|
+
logError("Error installing dependencies:", installResult.error);
|
|
12
|
+
logInfo("Try running manually: npm install");
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import inquirer from "inquirer";
|
|
2
|
+
export async function askForTailwindSetup() {
|
|
3
|
+
const { useTailwind } = await inquirer.prompt([
|
|
4
|
+
{
|
|
5
|
+
type: "confirm",
|
|
6
|
+
name: "useTailwind",
|
|
7
|
+
message: "Would you like to set up Tailwind CSS?",
|
|
8
|
+
default: true,
|
|
9
|
+
},
|
|
10
|
+
]);
|
|
11
|
+
return useTailwind;
|
|
12
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import fs from "fs-extra";
|
|
3
|
+
import { updateViteConfig } from "../config/vite.js";
|
|
4
|
+
import { logInfo } from "../utils/logger.js";
|
|
5
|
+
export async function setupTailwind(projectDir) {
|
|
6
|
+
logInfo("\nSetting up Tailwind CSS v4...");
|
|
7
|
+
// Point to the hidden Vite config
|
|
8
|
+
const viteConfigPath = path.join(projectDir, ".revine", "bundler", "vite.config.ts");
|
|
9
|
+
// Now use existing updateViteConfig logic on this new path
|
|
10
|
+
await updateViteConfig(viteConfigPath);
|
|
11
|
+
// Creating the CSS directory and file that imports Tailwind
|
|
12
|
+
const cssDir = path.join(projectDir, "src", "styles");
|
|
13
|
+
await fs.ensureDir(cssDir);
|
|
14
|
+
await fs.writeFile(path.join(cssDir, "global.css"), "@import 'tailwindcss';\n");
|
|
15
|
+
// Prepend the CSS import to src/main.tsx
|
|
16
|
+
const rootTsxPath = path.join(projectDir, "src", "root.tsx");
|
|
17
|
+
const mainContent = `import './styles/global.css';\n` +
|
|
18
|
+
(await fs.readFile(rootTsxPath, "utf-8"));
|
|
19
|
+
await fs.writeFile(rootTsxPath, mainContent);
|
|
20
|
+
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import { fileURLToPath } from "url";
|
|
3
|
+
import { updatePackageJson } from "../config/package.js";
|
|
4
|
+
import { updateReadme } from "../config/readme.js";
|
|
5
|
+
import { installDependencies } from "../installers/dependencies.js";
|
|
6
|
+
import { askForTailwindSetup } from "../prompts/tailwind.js";
|
|
7
|
+
import { setupTailwind } from "../setup/tailwind.js";
|
|
8
|
+
import { copyTemplate } from "../utils/file.js";
|
|
9
|
+
import { logError, logInfo } from "../utils/logger.js";
|
|
10
|
+
|
|
11
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
12
|
+
const __dirname = path.dirname(__filename);
|
|
13
|
+
|
|
14
|
+
export async function createProject(
|
|
15
|
+
projectName: string,
|
|
16
|
+
options: { force?: boolean }
|
|
17
|
+
) {
|
|
18
|
+
// Calculate directories. This uses "../../template" for your template folder.
|
|
19
|
+
const templateDir = path.join(__dirname, "../../template");
|
|
20
|
+
const projectDir = path.resolve(projectName);
|
|
21
|
+
const isCurrentDir = [".", "./"].includes(projectName);
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
logInfo(`Creating project in ${projectDir}...`);
|
|
25
|
+
// This copies everything, including hidden directories like .revine
|
|
26
|
+
await copyTemplate(templateDir, projectDir, options.force);
|
|
27
|
+
|
|
28
|
+
// Derive final project name
|
|
29
|
+
const finalProjectName = isCurrentDir
|
|
30
|
+
? path.basename(projectDir)
|
|
31
|
+
: projectName;
|
|
32
|
+
|
|
33
|
+
// Update package.json (e.g., set name, set "type": "module", add Tailwind deps if chosen)
|
|
34
|
+
const packageJsonPath = path.join(projectDir, "package.json");
|
|
35
|
+
const useTailwind = await askForTailwindSetup();
|
|
36
|
+
await updatePackageJson(packageJsonPath, finalProjectName, { useTailwind });
|
|
37
|
+
|
|
38
|
+
// Update README with the project name
|
|
39
|
+
const readmePath = path.join(projectDir, "README.md");
|
|
40
|
+
await updateReadme(readmePath, finalProjectName);
|
|
41
|
+
|
|
42
|
+
// Install dependencies
|
|
43
|
+
logInfo("\nInstalling dependencies...");
|
|
44
|
+
await installDependencies(projectDir);
|
|
45
|
+
|
|
46
|
+
// If Tailwind is selected, set it up
|
|
47
|
+
if (useTailwind) {
|
|
48
|
+
await setupTailwind(projectDir);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
logInfo(`\nSuccess! Created project at ${projectDir}`);
|
|
52
|
+
logInfo("\nStart developing with:");
|
|
53
|
+
if (!isCurrentDir) console.log(` cd ${projectName}`);
|
|
54
|
+
console.log(" npm run dev\n");
|
|
55
|
+
} catch (error) {
|
|
56
|
+
logError("Error during project creation:", error);
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,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
|
+
if (options.useTailwind) {
|
|
16
|
+
packageJson.devDependencies = {
|
|
17
|
+
...packageJson.devDependencies,
|
|
18
|
+
tailwindcss: "^4.0.0",
|
|
19
|
+
"@tailwindcss/vite": "^4.0.0",
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
await fs.writeJson(filePath, packageJson, { spaces: 2 });
|
|
23
|
+
}
|
|
@@ -0,0 +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
|
+
}
|
|
@@ -0,0 +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()]",
|
|
15
|
+
"plugins: [\n react(),\n tailwindcss()\n ]"
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
await fs.writeFile(filePath, viteConfigContent);
|
|
19
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,16 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import chalk from "chalk";
|
|
4
|
-
import { spawnSync } from "child_process";
|
|
5
2
|
import { Command } from "commander";
|
|
6
|
-
import
|
|
7
|
-
import inquirer from "inquirer";
|
|
8
|
-
import path from "path";
|
|
9
|
-
import { fileURLToPath } from "url";
|
|
10
|
-
|
|
11
|
-
// Get directory paths in ESM
|
|
12
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
13
|
-
const __dirname = path.dirname(__filename);
|
|
3
|
+
import { createProject } from "./commands/createProject.js";
|
|
14
4
|
|
|
15
5
|
const program = new Command();
|
|
16
6
|
|
|
@@ -19,125 +9,7 @@ program
|
|
|
19
9
|
.argument("<project-name>")
|
|
20
10
|
.option("-f, --force", "Force creation in non-empty directory")
|
|
21
11
|
.action(async (projectName: string, options: { force?: boolean }) => {
|
|
22
|
-
|
|
23
|
-
const projectDir = path.resolve(projectName);
|
|
24
|
-
const isCurrentDir = [".", "./"].includes(projectName);
|
|
25
|
-
|
|
26
|
-
// ... [keep existing directory checks the same] ...
|
|
27
|
-
|
|
28
|
-
try {
|
|
29
|
-
console.log(chalk.cyan(`Creating project in ${projectDir}...`));
|
|
30
|
-
fs.copySync(templateDir, projectDir, { overwrite: options.force });
|
|
31
|
-
|
|
32
|
-
// Update package.json with ESM configuration
|
|
33
|
-
const packageJsonPath = path.join(projectDir, "package.json");
|
|
34
|
-
const packageJson = await fs.readJson(packageJsonPath);
|
|
35
|
-
const finalProjectName = isCurrentDir
|
|
36
|
-
? path.basename(projectDir)
|
|
37
|
-
: projectName;
|
|
38
|
-
|
|
39
|
-
packageJson.name = finalProjectName;
|
|
40
|
-
packageJson.type = "module"; // Add ESM type declaration
|
|
41
|
-
|
|
42
|
-
const npmCmd = process.platform === "win32" ? "npm.cmd" : "npm";
|
|
43
|
-
|
|
44
|
-
// Add Tailwind prompt
|
|
45
|
-
const { useTailwind } = await inquirer.prompt([
|
|
46
|
-
{
|
|
47
|
-
type: "confirm",
|
|
48
|
-
name: "useTailwind",
|
|
49
|
-
message: "Would you like to set up Tailwind CSS?",
|
|
50
|
-
default: true,
|
|
51
|
-
},
|
|
52
|
-
]);
|
|
53
|
-
|
|
54
|
-
// Add Tailwind v4 dependencies if selected
|
|
55
|
-
if (useTailwind) {
|
|
56
|
-
packageJson.devDependencies = {
|
|
57
|
-
...packageJson.devDependencies,
|
|
58
|
-
tailwindcss: "^4.0.0",
|
|
59
|
-
"@tailwindcss/vite": "^4.0.0",
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
|
|
64
|
-
|
|
65
|
-
// Update README
|
|
66
|
-
const readmePath = path.join(projectDir, "README.md");
|
|
67
|
-
let readmeContent = fs.readFileSync(readmePath, "utf-8");
|
|
68
|
-
readmeContent = readmeContent.replace(
|
|
69
|
-
/%PROJECT_NAME%/g,
|
|
70
|
-
finalProjectName
|
|
71
|
-
);
|
|
72
|
-
fs.writeFileSync(readmePath, readmeContent);
|
|
73
|
-
|
|
74
|
-
// Install dependencies with error handling
|
|
75
|
-
console.log(chalk.cyan("\nInstalling dependencies..."));
|
|
76
|
-
const installResult = spawnSync(npmCmd, ["install"], {
|
|
77
|
-
stdio: "inherit",
|
|
78
|
-
cwd: projectDir,
|
|
79
|
-
shell: true,
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
if (installResult.error || installResult.status !== 0) {
|
|
83
|
-
console.log(
|
|
84
|
-
chalk.red("\nError installing dependencies!", installResult.error)
|
|
85
|
-
);
|
|
86
|
-
console.log(chalk.yellow("Try running manually: npm install"));
|
|
87
|
-
process.exit(1);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Setup Tailwind after dependencies are installed
|
|
91
|
-
if (useTailwind) {
|
|
92
|
-
console.log(chalk.cyan("\nSetting up Tailwind CSS v4..."));
|
|
93
|
-
|
|
94
|
-
// Update Vite config to add Tailwind plugin
|
|
95
|
-
const viteConfigPath = path.join(projectDir, "vite.config.ts");
|
|
96
|
-
let viteConfigContent = fs.readFileSync(viteConfigPath, "utf-8");
|
|
97
|
-
|
|
98
|
-
// Add Tailwind import
|
|
99
|
-
viteConfigContent = viteConfigContent.replace(
|
|
100
|
-
"import react from '@vitejs/plugin-react';",
|
|
101
|
-
"import react from '@vitejs/plugin-react';\nimport tailwindcss from '@tailwindcss/vite';"
|
|
102
|
-
);
|
|
103
|
-
|
|
104
|
-
// Add Tailwind plugin to existing config
|
|
105
|
-
viteConfigContent = viteConfigContent.replace(
|
|
106
|
-
"plugins: [react()]",
|
|
107
|
-
"plugins: [\n react(),\n tailwindcss()\n ]"
|
|
108
|
-
);
|
|
109
|
-
|
|
110
|
-
fs.writeFileSync(viteConfigPath, viteConfigContent);
|
|
111
|
-
fs.writeFileSync(viteConfigPath, viteConfigContent);
|
|
112
|
-
|
|
113
|
-
// Create CSS file with import
|
|
114
|
-
const cssDir = path.join(projectDir, "src", "styles");
|
|
115
|
-
fs.ensureDirSync(cssDir);
|
|
116
|
-
fs.writeFileSync(
|
|
117
|
-
path.join(cssDir, "global.css"),
|
|
118
|
-
"@import 'tailwindcss';\n"
|
|
119
|
-
);
|
|
120
|
-
|
|
121
|
-
// Add CSS import to main.tsx
|
|
122
|
-
const mainTsxPath = path.join(projectDir, "src", "main.tsx");
|
|
123
|
-
const mainContent = `import './styles/global.css';\n${fs.readFileSync(
|
|
124
|
-
mainTsxPath,
|
|
125
|
-
"utf-8"
|
|
126
|
-
)}`;
|
|
127
|
-
fs.writeFileSync(mainTsxPath, mainContent);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
console.log(
|
|
131
|
-
chalk.green("\nSuccess! Created project at"),
|
|
132
|
-
chalk.yellow(projectDir)
|
|
133
|
-
);
|
|
134
|
-
console.log(chalk.cyan("\nStart developing with:"));
|
|
135
|
-
if (!isCurrentDir) console.log(` cd ${projectName}`);
|
|
136
|
-
console.log(" npm run dev\n");
|
|
137
|
-
} catch (error) {
|
|
138
|
-
console.log(chalk.red("Error:"), error);
|
|
139
|
-
process.exit(1);
|
|
140
|
-
}
|
|
12
|
+
await createProject(projectName, options);
|
|
141
13
|
});
|
|
142
14
|
|
|
143
15
|
program.parse(process.argv);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { spawnSync } from "child_process";
|
|
2
|
+
import { logError, logInfo } from "../utils/logger.js";
|
|
3
|
+
|
|
4
|
+
export async function installDependencies(projectDir: string): Promise<void> {
|
|
5
|
+
const npmCmd = process.platform === "win32" ? "npm.cmd" : "npm";
|
|
6
|
+
const installResult = spawnSync(npmCmd, ["install"], {
|
|
7
|
+
stdio: "inherit",
|
|
8
|
+
cwd: projectDir,
|
|
9
|
+
shell: true,
|
|
10
|
+
});
|
|
11
|
+
if (installResult.error || installResult.status !== 0) {
|
|
12
|
+
logError("Error installing dependencies:", installResult.error);
|
|
13
|
+
logInfo("Try running manually: npm install");
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import inquirer from "inquirer";
|
|
2
|
+
|
|
3
|
+
export async function askForTailwindSetup(): Promise<boolean> {
|
|
4
|
+
const { useTailwind } = await inquirer.prompt([
|
|
5
|
+
{
|
|
6
|
+
type: "confirm",
|
|
7
|
+
name: "useTailwind",
|
|
8
|
+
message: "Would you like to set up Tailwind CSS?",
|
|
9
|
+
default: true,
|
|
10
|
+
},
|
|
11
|
+
]);
|
|
12
|
+
return useTailwind;
|
|
13
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import fs from "fs-extra";
|
|
3
|
+
import { updateViteConfig } from "../config/vite.js";
|
|
4
|
+
import { logInfo } from "../utils/logger.js";
|
|
5
|
+
|
|
6
|
+
export async function setupTailwind(projectDir: string) {
|
|
7
|
+
logInfo("\nSetting up Tailwind CSS v4...");
|
|
8
|
+
|
|
9
|
+
// Point to the hidden Vite config
|
|
10
|
+
const viteConfigPath = path.join(
|
|
11
|
+
projectDir,
|
|
12
|
+
".revine",
|
|
13
|
+
"bundler",
|
|
14
|
+
"vite.config.ts"
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
// Now use existing updateViteConfig logic on this new path
|
|
18
|
+
await updateViteConfig(viteConfigPath);
|
|
19
|
+
|
|
20
|
+
// Creating the CSS directory and file that imports Tailwind
|
|
21
|
+
const cssDir = path.join(projectDir, "src", "styles");
|
|
22
|
+
await fs.ensureDir(cssDir);
|
|
23
|
+
await fs.writeFile(
|
|
24
|
+
path.join(cssDir, "global.css"),
|
|
25
|
+
"@import 'tailwindcss';\n"
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
// Prepend the CSS import to src/main.tsx
|
|
29
|
+
const rootTsxPath = path.join(projectDir, "src", "root.tsx");
|
|
30
|
+
const mainContent =
|
|
31
|
+
`import './styles/global.css';\n` +
|
|
32
|
+
(await fs.readFile(rootTsxPath, "utf-8"));
|
|
33
|
+
await fs.writeFile(rootTsxPath, mainContent);
|
|
34
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// .revine/bundler/generateConfig.ts
|
|
2
|
+
import { merge } from 'lodash-es';
|
|
3
|
+
import { defaultViteConfig } from './defaults/vite.js';
|
|
4
|
+
import { loadUserConfig } from './utils/loadUserConfig.js';
|
|
5
|
+
import tailwindcss from '@tailwindcss/vite'; // For direct plugin usage
|
|
6
|
+
|
|
7
|
+
export async function generateRevineViteConfig() {
|
|
8
|
+
// Load the user's revine.config.ts
|
|
9
|
+
const userConfig = await loadUserConfig();
|
|
10
|
+
|
|
11
|
+
// Merge user "vite" overrides with your default config
|
|
12
|
+
const finalConfig = merge({}, defaultViteConfig, userConfig.vite || {});
|
|
13
|
+
|
|
14
|
+
// Insert the Tailwind plugin, if desired, automatically or conditionally:
|
|
15
|
+
// finalConfig.plugins.push(tailwindcss());
|
|
16
|
+
|
|
17
|
+
return finalConfig;
|
|
18
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export async function loadUserConfig() {
|
|
2
|
+
try {
|
|
3
|
+
// relative path to the user's revine.config.ts
|
|
4
|
+
const configModule = await import("../../../revine.config.ts");
|
|
5
|
+
return configModule.default || {};
|
|
6
|
+
} catch (error) {
|
|
7
|
+
console.error(
|
|
8
|
+
"[Revine] Could not load revine.config.ts, using defaults.",
|
|
9
|
+
error
|
|
10
|
+
);
|
|
11
|
+
return {};
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { defineConfig } from "vite";
|
|
2
|
+
import { generateRevineViteConfig } from "./generateConfig.js";
|
|
3
|
+
|
|
4
|
+
// Vite supports async config. We can do:
|
|
5
|
+
export default defineConfig(async () => {
|
|
6
|
+
// Merge defaults + user overrides
|
|
7
|
+
return await generateRevineViteConfig();
|
|
8
|
+
});
|
package/template/index.html
CHANGED
package/template/package.json
CHANGED
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
2
|
+
"name": "{{project-name}}",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"scripts": {
|
|
5
|
+
"dev": "vite --config .revine/bundler/vite.config.ts",
|
|
6
|
+
"build": "vite build --config .revine/bundler/vite.config.ts",
|
|
7
|
+
"preview": "vite preview --config .revine/bundler/vite.config.ts"
|
|
8
|
+
},
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"react": "^18.2.0",
|
|
11
|
+
"react-dom": "^18.2.0",
|
|
12
|
+
"react-router-dom": "^6.22.3"
|
|
13
|
+
},
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@types/react": "^18.2.45",
|
|
16
|
+
"@types/react-dom": "^18.2.18",
|
|
17
|
+
"typescript": "^5.3.3",
|
|
18
|
+
"vite": "^5.0.12",
|
|
19
|
+
"@vitejs/plugin-react": "^4.2.1",
|
|
20
|
+
"lodash-es": "^4.17.21",
|
|
21
|
+
"@tailwindcss/vite": "^4.0.0"
|
|
22
|
+
}
|
|
23
|
+
}
|
package/template/tsconfig.json
CHANGED
package/template/vite.config.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from 'vite';
|
|
2
|
-
import react from '@vitejs/plugin-react';
|
|
3
|
-
|
|
4
|
-
export default defineConfig({
|
|
5
|
-
plugins: [react()],
|
|
6
|
-
server: {
|
|
7
|
-
open: true,
|
|
8
|
-
port: 3000,
|
|
9
|
-
host: true
|
|
10
|
-
},
|
|
11
|
-
build: {
|
|
12
|
-
outDir: 'dist',
|
|
13
|
-
emptyOutDir: true,
|
|
14
|
-
}
|
|
15
|
-
});
|
|
File without changes
|
|
File without changes
|