create-fullstack-setup 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 (57) hide show
  1. package/README.md +391 -0
  2. package/bin/index.js +175 -0
  3. package/package.json +19 -0
  4. package/templates/backend/express-js/.env.example +6 -0
  5. package/templates/backend/express-js/Utils/ApiError.js +17 -0
  6. package/templates/backend/express-js/Utils/ApiResponse.js +12 -0
  7. package/templates/backend/express-js/Utils/AsyncHandler.js +8 -0
  8. package/templates/backend/express-js/Utils/Cloudinary.js +31 -0
  9. package/templates/backend/express-js/app.js +35 -0
  10. package/templates/backend/express-js/config/db.js +18 -0
  11. package/templates/backend/express-js/middlewares/Auth.middleware.js +21 -0
  12. package/templates/backend/express-js/middlewares/Multer.middleware.js +18 -0
  13. package/templates/backend/express-js/package.json +17 -0
  14. package/templates/backend/express-js/server.js +10 -0
  15. package/templates/backend/express-ts/.env.example +3 -0
  16. package/templates/backend/express-ts/README.md +0 -0
  17. package/templates/backend/express-ts/nodemon.json +5 -0
  18. package/templates/backend/express-ts/package.json +20 -0
  19. package/templates/backend/express-ts/src/app.ts +14 -0
  20. package/templates/backend/express-ts/src/config/db.ts +0 -0
  21. package/templates/backend/express-ts/src/middlewares/auth.middleware.ts +23 -0
  22. package/templates/backend/express-ts/src/routes/index.ts +0 -0
  23. package/templates/backend/express-ts/src/server.ts +8 -0
  24. package/templates/backend/express-ts/src/utils/ApiError.ts +21 -0
  25. package/templates/backend/express-ts/src/utils/ApiResponse.ts +13 -0
  26. package/templates/backend/express-ts/src/utils/AsyncHandler.ts +9 -0
  27. package/templates/backend/express-ts/src/utils/Cloudinary.ts +11 -0
  28. package/templates/backend/express-ts/tsconfig.json +13 -0
  29. package/templates/frontend/next-js/app/layout.js +14 -0
  30. package/templates/frontend/next-js/app/page.js +8 -0
  31. package/templates/frontend/next-js/jsconfig.json +8 -0
  32. package/templates/frontend/next-js/next.config.js +6 -0
  33. package/templates/frontend/next-js/package.json +16 -0
  34. package/templates/frontend/next-ts/app/layout.tsx +18 -0
  35. package/templates/frontend/next-ts/app/page.tsx +7 -0
  36. package/templates/frontend/next-ts/next.config.js +6 -0
  37. package/templates/frontend/next-ts/package.json +22 -0
  38. package/templates/frontend/next-ts/tsconfig.json +17 -0
  39. package/templates/frontend/react-js/index.html +12 -0
  40. package/templates/frontend/react-js/package.json +19 -0
  41. package/templates/frontend/react-js/src/App.jsx +8 -0
  42. package/templates/frontend/react-js/src/index.css +0 -0
  43. package/templates/frontend/react-js/src/main.jsx +10 -0
  44. package/templates/frontend/react-js/vite.config.js +6 -0
  45. package/templates/frontend/react-ts/index.html +12 -0
  46. package/templates/frontend/react-ts/package.json +21 -0
  47. package/templates/frontend/react-ts/src/App.tsx +9 -0
  48. package/templates/frontend/react-ts/src/index.css +0 -0
  49. package/templates/frontend/react-ts/src/main.tsx +12 -0
  50. package/templates/frontend/react-ts/tsconfig.json +10 -0
  51. package/templates/frontend/react-ts/vite.config.ts +6 -0
  52. package/utils/features.config.js +72 -0
  53. package/utils/fileOps.js +0 -0
  54. package/utils/injectFeatures.js +171 -0
  55. package/utils/installer.js +157 -0
  56. package/utils/prompts.js +59 -0
  57. package/utils/replacePlaceholders.js +54 -0
@@ -0,0 +1,18 @@
1
+ import dotenv from "dotenv";
2
+ dotenv.config();
3
+ import mongoose from "mongoose"
4
+ import { ApiError } from "../Utils/ApiError.js";
5
+
6
+ const connectDB=async()=>{
7
+ try{
8
+ const connectionInstance=await mongoose.connect(process.env.MONGODB_URI);
9
+ console.log("database connected at",connectionInstance.connection.host)
10
+ }
11
+ catch(error){
12
+ throw new ApiError(500,"somthing went wrong while database is connect",error);
13
+ }
14
+
15
+
16
+ }
17
+
18
+ export default connectDB;
@@ -0,0 +1,21 @@
1
+ import jwt from "jsonwebtoken";
2
+ import { AsyncHandler } from "../utils/AsyncHandler.js";
3
+ import { ApiError } from "../utils/ApiError.js";
4
+
5
+ export const verifyJWT = AsyncHandler(async (req, res, next) => {
6
+ const token =
7
+ req.cookies?.accessToken ||
8
+ req.header("Authorization")?.split(" ")[1];
9
+
10
+ if (!token) {
11
+ throw new ApiError(401, "Unauthorized request");
12
+ }
13
+
14
+ const decoded = jwt.verify(
15
+ token,
16
+ process.env.ACCESS_TOKEN_SECRET
17
+ );
18
+
19
+ req.user = decoded;
20
+ next();
21
+ });
@@ -0,0 +1,18 @@
1
+ import multer from "multer";
2
+ import path from "path";
3
+ import { fileURLToPath } from "url";
4
+
5
+ const __filename = fileURLToPath(import.meta.url);
6
+ const __dirname = path.dirname(__filename);
7
+
8
+ const storage = multer.diskStorage({
9
+ destination: function (req, file, cb) {
10
+ cb(null, path.join(__dirname, "../../File/temp"));
11
+ },
12
+ filename: function (req, file, cb) {
13
+ const uniqueSuffix = Date.now() + "-" + Math.round(Math.random() * 1e9);
14
+ cb(null, `${file.fieldname}-${uniqueSuffix}`);
15
+ },
16
+ });
17
+
18
+ export const upload = multer({ storage });
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "__PROJECT_NAME__-server",
3
+ "version": "1.0.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "nodemon server.js",
8
+ "start": "node server.js"
9
+ },
10
+ "dependencies": {
11
+ "express": "^4.19.0",
12
+ "dotenv": "^16.4.0"
13
+ },
14
+ "devDependencies": {
15
+ "nodemon": "^3.0.3"
16
+ }
17
+ }
@@ -0,0 +1,10 @@
1
+ import app from "./app.js";
2
+ import dotenv from "dotenv";
3
+
4
+ dotenv.config();
5
+
6
+ const PORT = process.env.PORT || 5000;
7
+
8
+ app.listen(PORT, () => {
9
+ console.log(`🚀 Server running on port ${PORT}`);
10
+ });
@@ -0,0 +1,3 @@
1
+ PORT=5000
2
+ MONGO_URI=
3
+ JWT_SECRET=
File without changes
@@ -0,0 +1,5 @@
1
+ {
2
+ "watch": ["src"],
3
+ "ext": "ts",
4
+ "exec": "ts-node src/server.ts"
5
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "__PROJECT_NAME__-server",
3
+ "version": "1.0.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "nodemon",
8
+ "build": "tsc",
9
+ "start": "node dist/server.js"
10
+ },
11
+ "dependencies": {
12
+ "express": "^4.19.0"
13
+ },
14
+ "devDependencies": {
15
+ "@types/express": "^4.17.21",
16
+ "typescript": "^5.4.0",
17
+ "ts-node": "^10.9.2",
18
+ "nodemon": "^3.0.3"
19
+ }
20
+ }
@@ -0,0 +1,14 @@
1
+ import express, { Application } from "express";
2
+
3
+ const app: Application = express();
4
+
5
+ app.use(express.json());
6
+
7
+ app.get("/", (_req, res) => {
8
+ res.json({
9
+ success: true,
10
+ message: "Express + TypeScript server running 🚀"
11
+ });
12
+ });
13
+
14
+ export default app;
File without changes
@@ -0,0 +1,23 @@
1
+ import { Request, Response, NextFunction } from "express";
2
+ import jwt from "jsonwebtoken";
3
+
4
+ export function authMiddleware(
5
+ req: Request,
6
+ res: Response,
7
+ next: NextFunction
8
+ ) {
9
+ const token =
10
+ req.headers.authorization?.split(" ")[1] ||
11
+ req.cookies?.token;
12
+
13
+ if (!token) {
14
+ return res.status(401).json({ message: "Unauthorized" });
15
+ }
16
+
17
+ try {
18
+ jwt.verify(token, process.env.ACCESS_TOKEN_SECRET as string);
19
+ next();
20
+ } catch {
21
+ return res.status(401).json({ message: "Invalid token" });
22
+ }
23
+ }
@@ -0,0 +1,8 @@
1
+ import app from "./app";
2
+ import "dotenv/config";
3
+
4
+ const PORT = process.env.PORT || 5000;
5
+
6
+ app.listen(PORT, () => {
7
+ console.log(`🚀 Server running on http://localhost:${PORT}`);
8
+ });
@@ -0,0 +1,21 @@
1
+ export class ApiError extends Error {
2
+ public statusCode: number;
3
+ public errors: unknown[];
4
+ public override stack?: string;
5
+
6
+ constructor(statusCode: number, message = 'failed', errors: unknown[] = [], stack?: string) {
7
+ super(message);
8
+ this.name = 'ApiError';
9
+ this.statusCode = statusCode;
10
+ this.errors = errors;
11
+
12
+ // restore prototype chain (necessary when targeting ES5)
13
+ Object.setPrototypeOf(this, ApiError.prototype);
14
+
15
+ if (stack) {
16
+ this.stack = stack;
17
+ } else if (typeof Error.captureStackTrace === 'function') {
18
+ Error.captureStackTrace(this, this.constructor);
19
+ }
20
+ }
21
+ }
@@ -0,0 +1,13 @@
1
+ export class ApiResponse<T = any> {
2
+ statusCode: number;
3
+ data: T | null;
4
+ message: string;
5
+ success: boolean;
6
+
7
+ constructor(statusCode: number, data: T | null = null, message = "success", success = true) {
8
+ this.statusCode = statusCode;
9
+ this.data = data;
10
+ this.message = message;
11
+ this.success = success;
12
+ }
13
+ }
@@ -0,0 +1,9 @@
1
+ import { Request, Response, NextFunction, RequestHandler } from "express";
2
+
3
+ const AsyncHandler = (reqHandler: RequestHandler): RequestHandler => {
4
+ return (req: Request, res: Response, next: NextFunction): void => {
5
+ Promise.resolve(reqHandler(req, res, next)).catch(next);
6
+ };
7
+ };
8
+
9
+ export { AsyncHandler };
@@ -0,0 +1,11 @@
1
+ import { v2 as cloudinary } from "cloudinary";
2
+
3
+ export function connectCloudinary() {
4
+ cloudinary.config({
5
+ cloud_name: process.env.CLOUDINARY_NAME,
6
+ api_key: process.env.CLOUDINARY_API_KEY,
7
+ api_secret: process.env.CLOUDINARY_API_SECRET
8
+ });
9
+
10
+ console.log("☁️ Cloudinary connected");
11
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "Node",
6
+ "outDir": "dist",
7
+ "rootDir": "src",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true
11
+ },
12
+ "include": ["src"]
13
+ }
@@ -0,0 +1,14 @@
1
+ export const metadata = {
2
+ title: "Next App",
3
+ description: "Generated by create-fullstack-app"
4
+ };
5
+
6
+ export default function RootLayout({ children }) {
7
+ return (
8
+ <html lang="en">
9
+ <body style={{ margin: 0, fontFamily: "sans-serif" }}>
10
+ {children}
11
+ </body>
12
+ </html>
13
+ );
14
+ }
@@ -0,0 +1,8 @@
1
+ export default function Home() {
2
+ return (
3
+ <main style={{ padding: "2rem" }}>
4
+ <h1>🚀 Next.js (JavaScript) Ready</h1>
5
+ <p>Edit <code>app/page.js</code> and start building.</p>
6
+ </main>
7
+ );
8
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "compilerOptions": {
3
+ "baseUrl": ".",
4
+ "paths": {
5
+ "@/*": ["./*"]
6
+ }
7
+ }
8
+ }
@@ -0,0 +1,6 @@
1
+ /** @type {import('next').NextConfig} */
2
+ const nextConfig = {
3
+ reactStrictMode: true
4
+ };
5
+
6
+ module.exports = nextConfig;
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "__PROJECT_NAME__",
3
+ "private": true,
4
+ "version": "0.1.0",
5
+ "scripts": {
6
+ "dev": "next dev",
7
+ "build": "next build",
8
+ "start": "next start",
9
+ "lint": "next lint"
10
+ },
11
+ "dependencies": {
12
+ "next": "^14.1.0",
13
+ "react": "^18.2.0",
14
+ "react-dom": "^18.2.0"
15
+ }
16
+ }
@@ -0,0 +1,18 @@
1
+ export const metadata = {
2
+ title: "Next App",
3
+ description: "Generated by create-fullstack-app"
4
+ };
5
+
6
+ export default function RootLayout({
7
+ children
8
+ }: {
9
+ children: React.ReactNode;
10
+ }) {
11
+ return (
12
+ <html lang="en">
13
+ <body style={{ margin: 0, fontFamily: "sans-serif" }}>
14
+ {children}
15
+ </body>
16
+ </html>
17
+ );
18
+ }
@@ -0,0 +1,7 @@
1
+ export default function Home(): JSX.Element {
2
+ return (
3
+ <main style={{ padding: "2rem" }}>
4
+ <h1>🚀 Next.js + TypeScript Ready</h1>
5
+ </main>
6
+ );
7
+ }
@@ -0,0 +1,6 @@
1
+ /** @type {import('next').NextConfig} */
2
+ const nextConfig = {
3
+ reactStrictMode: true
4
+ };
5
+
6
+ module.exports = nextConfig;
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "__PROJECT_NAME__",
3
+ "private": true,
4
+ "version": "0.1.0",
5
+ "scripts": {
6
+ "dev": "next dev",
7
+ "build": "next build",
8
+ "start": "next start",
9
+ "lint": "next lint"
10
+ },
11
+ "dependencies": {
12
+ "next": "^14.1.0",
13
+ "react": "^18.2.0",
14
+ "react-dom": "^18.2.0"
15
+ },
16
+ "devDependencies": {
17
+ "typescript": "^5.3.0",
18
+ "@types/react": "^18.2.0",
19
+ "@types/react-dom": "^18.2.0",
20
+ "@types/node": "^20.10.0"
21
+ }
22
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "lib": ["DOM", "DOM.Iterable", "ESNext"],
5
+ "allowJs": false,
6
+ "skipLibCheck": true,
7
+ "strict": true,
8
+ "noEmit": true,
9
+ "module": "ESNext",
10
+ "moduleResolution": "Bundler",
11
+ "resolveJsonModule": true,
12
+ "isolatedModules": true,
13
+ "jsx": "preserve"
14
+ },
15
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
16
+ "exclude": ["node_modules"]
17
+ }
@@ -0,0 +1,12 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>React App</title>
7
+ </head>
8
+ <body>
9
+ <div id="root"></div>
10
+ <script type="module" src="/src/main.jsx"></script>
11
+ </body>
12
+ </html>
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "__PROJECT_NAME__",
3
+ "private": true,
4
+ "version": "0.0.0",
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "build": "vite build",
9
+ "preview": "vite preview"
10
+ },
11
+ "dependencies": {
12
+ "react": "^18.2.0",
13
+ "react-dom": "^18.2.0"
14
+ },
15
+ "devDependencies": {
16
+ "@vitejs/plugin-react": "^4.2.0",
17
+ "vite": "^5.0.0"
18
+ }
19
+ }
@@ -0,0 +1,8 @@
1
+ export default function App() {
2
+ return (
3
+ <div style={{ padding: "2rem" }}>
4
+ <h1>🚀 React App Ready</h1>
5
+ <p>Edit <code>App.jsx</code> and start building.</p>
6
+ </div>
7
+ );
8
+ }
File without changes
@@ -0,0 +1,10 @@
1
+ import React from "react";
2
+ import ReactDOM from "react-dom/client";
3
+ import App from "./App";
4
+ import "./index.css";
5
+
6
+ ReactDOM.createRoot(document.getElementById("root")).render(
7
+ <React.StrictMode>
8
+ <App />
9
+ </React.StrictMode>
10
+ );
@@ -0,0 +1,6 @@
1
+ import { defineConfig } from "vite";
2
+ import react from "@vitejs/plugin-react";
3
+
4
+ export default defineConfig({
5
+ plugins: [react()]
6
+ });
@@ -0,0 +1,12 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>React TS App</title>
7
+ </head>
8
+ <body>
9
+ <div id="root"></div>
10
+ <script type="module" src="/src/main.tsx"></script>
11
+ </body>
12
+ </html>
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "__PROJECT_NAME__",
3
+ "private": true,
4
+ "version": "0.0.0",
5
+ "scripts": {
6
+ "dev": "vite",
7
+ "build": "vite build",
8
+ "preview": "vite preview"
9
+ },
10
+ "dependencies": {
11
+ "react": "^18.2.0",
12
+ "react-dom": "^18.2.0"
13
+ },
14
+ "devDependencies": {
15
+ "@types/react": "^18.2.0",
16
+ "@types/react-dom": "^18.2.0",
17
+ "@vitejs/plugin-react": "^4.2.0",
18
+ "typescript": "^5.3.0",
19
+ "vite": "^5.0.0"
20
+ }
21
+ }
@@ -0,0 +1,9 @@
1
+ function App(): JSX.Element {
2
+ return (
3
+ <div style={{ padding: "2rem" }}>
4
+ <h1>🚀 React + TypeScript Ready</h1>
5
+ </div>
6
+ );
7
+ }
8
+
9
+ export default App;
File without changes
@@ -0,0 +1,12 @@
1
+ import React from "react";
2
+ import ReactDOM from "react-dom/client";
3
+ import App from "./App";
4
+ import "./index.css";
5
+
6
+ ReactDOM.createRoot(
7
+ document.getElementById("root") as HTMLElement
8
+ ).render(
9
+ <React.StrictMode>
10
+ <App />
11
+ </React.StrictMode>
12
+ );
@@ -0,0 +1,10 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "lib": ["ES2020", "DOM"],
5
+ "module": "ESNext",
6
+ "jsx": "react-jsx",
7
+ "moduleResolution": "Bundler",
8
+ "strict": true
9
+ }
10
+ }
@@ -0,0 +1,6 @@
1
+ import { defineConfig } from "vite";
2
+ import react from "@vitejs/plugin-react";
3
+
4
+ export default defineConfig({
5
+ plugins: [react()]
6
+ });
@@ -0,0 +1,72 @@
1
+ /* -------------------------------------------------------------------------- */
2
+ /* Backend Feature Configuration */
3
+ /* -------------------------------------------------------------------------- */
4
+
5
+ export const FEATURES = {
6
+ /* =============================== CORS ================================= */
7
+
8
+ CORS: {
9
+ middleware: `
10
+ import cors from "cors";
11
+ app.use(cors());
12
+ `.trim(),
13
+ env: []
14
+ },
15
+
16
+ /* =========================== COOKIE PARSER ============================= */
17
+
18
+ "Cookie-Parser": {
19
+ middleware: `
20
+ import cookieParser from "cookie-parser";
21
+ app.use(cookieParser());
22
+ `.trim(),
23
+ env: []
24
+ },
25
+
26
+ /* ================================ JWT ================================= */
27
+
28
+ JWT: {
29
+ middleware: "",
30
+ files: {
31
+ js: [
32
+ {
33
+ path: "middlewares/Auth.middleware.js",
34
+ fromTemplate:true,
35
+ }
36
+ ],
37
+ ts: [
38
+ {
39
+ path: "src/middlewares/auth.middleware.ts",
40
+ fromTemplate:true,
41
+ }
42
+ ]
43
+ },
44
+ },
45
+
46
+ /* ============================ CLOUDINARY ============================== */
47
+
48
+ Cloudinary: {
49
+ middleware: "",
50
+ files: {
51
+ js: [
52
+ {
53
+ path: "Utils/Cloudinary.js",
54
+ fromTemplate:true
55
+ }
56
+ ],
57
+ ts: [
58
+ {
59
+ path: "src/utils/Cloudinary.ts",
60
+ fromTemplate:true,
61
+ }
62
+ ]
63
+ }
64
+ },
65
+
66
+ /* ============================== DOTENV ================================ */
67
+
68
+ Dotenv: {
69
+ middleware: `import "dotenv/config";`,
70
+ env: ["PORT=5000"]
71
+ }
72
+ };
File without changes