jmdev-stack-cli 1.0.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.
Files changed (2) hide show
  1. package/index.js +155 -0
  2. package/package.json +31 -0
package/index.js ADDED
@@ -0,0 +1,155 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { Command } = require("commander");
4
+ const inquirer = require("inquirer");
5
+ const chalk = require("chalk");
6
+ const ora = require("ora");
7
+ const { execa } = require("execa"); // destructure the function
8
+ const fs = require("fs-extra");
9
+ require("dotenv").config();
10
+
11
+ const program = new Command();
12
+
13
+ program
14
+ .name("jmdev-stack-cli")
15
+ .description("Fullstack CLI generator for Next.js + Drizzle + Neon + Chakra UI")
16
+ .version("1.0.0");
17
+
18
+ program
19
+ .command("create [projectName]")
20
+ .option("-t, --typescript", "Use TypeScript")
21
+ .action(async (projectName, options) => {
22
+ try {
23
+ // šŸ”„ STEP 1: Ask missing inputs
24
+ if (!projectName) {
25
+ const answer = await inquirer.prompt([
26
+ {
27
+ type: "input",
28
+ name: "name",
29
+ message: "Project name:",
30
+ default: "my-app",
31
+ },
32
+ ]);
33
+ projectName = answer.name;
34
+ }
35
+
36
+ let useTS = options.typescript;
37
+
38
+ if (!useTS) {
39
+ const answer = await inquirer.prompt([
40
+ {
41
+ type: "confirm",
42
+ name: "typescript",
43
+ message: "Use TypeScript?",
44
+ default: true,
45
+ },
46
+ ]);
47
+ useTS = answer.typescript;
48
+ }
49
+
50
+ console.log(chalk.cyan(`\nCreating ${projectName}...\n`));
51
+
52
+ // šŸ”„ STEP 2: Create Next.js app
53
+ const spinner = ora("Creating Next.js app...").start();
54
+
55
+ const args = ["create-next-app@latest", projectName, "--yes"];
56
+ if (useTS) args.push("--ts");
57
+
58
+ await execa("npx", args, { stdio: "inherit" });
59
+
60
+ spinner.succeed("Next.js created!");
61
+
62
+ process.chdir(projectName);
63
+
64
+ // šŸ”„ STEP 3: Install dependencies
65
+ spinner.start("Installing dependencies...");
66
+
67
+ await execa("npm", [
68
+ "install",
69
+ "drizzle-orm",
70
+ "@neondatabase/serverless",
71
+ "dotenv",
72
+ "@chakra-ui/react",
73
+ "@emotion/react",
74
+ "@emotion/styled",
75
+ "framer-motion"
76
+ ]);
77
+
78
+ await execa("npm", [
79
+ "install",
80
+ "-D",
81
+ "drizzle-kit",
82
+ "tsx"
83
+ ]);
84
+
85
+ spinner.succeed("Dependencies installed!");
86
+
87
+ // šŸ”„ STEP 4: Create project structure
88
+ spinner.start("Setting up project files...");
89
+
90
+ await fs.ensureDir("config");
91
+
92
+ // .env
93
+ await fs.writeFile(".env", "DATABASE_URL=\n");
94
+
95
+ // db.ts
96
+ await fs.writeFile(
97
+ "config/db.ts",
98
+ `import { neon } from '@neondatabase/serverless';
99
+ import { drizzle } from 'drizzle-orm/neon-http';
100
+
101
+ const sql = neon(process.env.DATABASE_URL!);
102
+ export const db = drizzle({ client: sql });
103
+ `
104
+ );
105
+
106
+ // schema.ts
107
+ await fs.writeFile(
108
+ "config/schema.ts",
109
+ `import { pgTable, serial, text } from "drizzle-orm/pg-core";
110
+
111
+ export const users = pgTable("users", {
112
+ id: serial("id").primaryKey(),
113
+ name: text("name"),
114
+ });
115
+ `
116
+ );
117
+
118
+ // drizzle.config.ts
119
+ await fs.writeFile(
120
+ "drizzle.config.ts",
121
+ `import 'dotenv/config';
122
+ import { defineConfig } from 'drizzle-kit';
123
+
124
+ export default defineConfig({
125
+ schema: './config/schema.ts',
126
+ dialect: 'postgresql',
127
+ dbCredentials: {
128
+ url: process.env.DATABASE_URL!,
129
+ },
130
+ });
131
+ `
132
+ );
133
+
134
+ spinner.succeed("Project setup complete!");
135
+
136
+ // šŸ”„ STEP 5: Validate .env
137
+ const envContent = await fs.readFile(".env", "utf-8");
138
+
139
+ if (!envContent.includes("DATABASE_URL=")) {
140
+ console.log(chalk.red("Missing DATABASE_URL in .env"));
141
+ } else {
142
+ console.log(chalk.yellow("\nāš ļø Add your Neon DATABASE_URL in .env\n"));
143
+ }
144
+
145
+ // šŸŽ‰ DONE
146
+ console.log(chalk.green("\nāœ… All set!\n"));
147
+ console.log(`cd ${projectName}`);
148
+ console.log("npm run dev\n");
149
+
150
+ } catch (error) {
151
+ console.error(chalk.red("Error:"), error.message);
152
+ }
153
+ });
154
+
155
+ program.parse();
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "jmdev-stack-cli",
3
+ "version": "1.0.0",
4
+ "description": "Fullstack CLI generator (Next.js + Drizzle + Neon + Chakra UI)",
5
+ "main": "index.js",
6
+ "bin": {
7
+ "jmdev-stack-cli": "./index.js"
8
+ },
9
+ "scripts": {
10
+ "test": "echo \"Error: no test specified\" && exit 1"
11
+ },
12
+ "keywords": [
13
+ "cli",
14
+ "nextjs",
15
+ "drizzle",
16
+ "neon",
17
+ "chakra"
18
+ ],
19
+ "author": "",
20
+ "license": "ISC",
21
+ "type": "commonjs",
22
+ "dependencies": {
23
+ "chalk": "^4.1.2",
24
+ "commander": "^14.0.3",
25
+ "dotenv": "^17.4.0",
26
+ "execa": "^8.0.1",
27
+ "fs-extra": "^11.3.4",
28
+ "inquirer": "^8.2.7",
29
+ "ora": "^5.4.1"
30
+ }
31
+ }