create-rex-app 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 (53) hide show
  1. package/index.js +148 -0
  2. package/package.json +31 -0
  3. package/template/README.md +71 -0
  4. package/template/_gitignore +25 -0
  5. package/template/api/routes.js +9 -0
  6. package/template/eslint.config.js +29 -0
  7. package/template/index.html +13 -0
  8. package/template/package-lock.json +4667 -0
  9. package/template/package.json +33 -0
  10. package/template/public/rex logo.png +0 -0
  11. package/template/public/rex.png +0 -0
  12. package/template/server.js +77 -0
  13. package/template/src/App.css +42 -0
  14. package/template/src/App.jsx +326 -0
  15. package/template/src/assets/react.svg +1 -0
  16. package/template/src/hooks/useTest.js +18 -0
  17. package/template/src/index.css +1 -0
  18. package/template/src/main.jsx +14 -0
  19. package/template/vercel.json +8 -0
  20. package/template/vite.config.js +7 -0
  21. package/template-mongo/README.md +96 -0
  22. package/template-mongo/api/db.js +17 -0
  23. package/template-mongo/api/middleware/authMiddleware.js +31 -0
  24. package/template-mongo/api/models/User.js +28 -0
  25. package/template-mongo/api/routes.js +99 -0
  26. package/template-mongo/env-sample.txt +3 -0
  27. package/template-mongo/eslint.config.js +29 -0
  28. package/template-mongo/index.html +13 -0
  29. package/template-mongo/package-lock.json +5076 -0
  30. package/template-mongo/package.json +38 -0
  31. package/template-mongo/public/rex logo.png +0 -0
  32. package/template-mongo/public/rex.png +0 -0
  33. package/template-mongo/public/vite.svg +1 -0
  34. package/template-mongo/server.js +80 -0
  35. package/template-mongo/src/App.css +42 -0
  36. package/template-mongo/src/App.jsx +42 -0
  37. package/template-mongo/src/assets/react.svg +1 -0
  38. package/template-mongo/src/components/Layout.jsx +85 -0
  39. package/template-mongo/src/components/PublicOnly.jsx +17 -0
  40. package/template-mongo/src/components/RequireAuth.jsx +20 -0
  41. package/template-mongo/src/context/AuthContext.jsx +35 -0
  42. package/template-mongo/src/hooks/useAuthContext.js +11 -0
  43. package/template-mongo/src/hooks/useLogin.js +42 -0
  44. package/template-mongo/src/hooks/useSignup.js +23 -0
  45. package/template-mongo/src/hooks/useTest.js +18 -0
  46. package/template-mongo/src/index.css +1 -0
  47. package/template-mongo/src/main.jsx +18 -0
  48. package/template-mongo/src/pages/Docs.jsx +131 -0
  49. package/template-mongo/src/pages/Home.jsx +93 -0
  50. package/template-mongo/src/pages/Login.jsx +97 -0
  51. package/template-mongo/src/pages/Signup.jsx +112 -0
  52. package/template-mongo/vercel.json +13 -0
  53. package/template-mongo/vite.config.js +7 -0
@@ -0,0 +1,31 @@
1
+ import jwt from 'jsonwebtoken';
2
+ import User from '../models/User.js'; // Ensure this path matches your models folder
3
+
4
+ const protect = async (req, res, next) => {
5
+ let token;
6
+
7
+ // 1. Check if the "Authorization" header exists and starts with "Bearer"
8
+ if (req.headers.authorization && req.headers.authorization.startsWith('Bearer')) {
9
+ try {
10
+ // 2. Get the token from the string "Bearer <token>"
11
+ token = req.headers.authorization.split(' ')[1];
12
+
13
+ // 3. Verify the token using the Secret Key
14
+ const decoded = jwt.verify(token, process.env.JWT_SECRET);
15
+
16
+ // 4. Find the user (exclude password) and attach to 'req'
17
+ req.user = await User.findById(decoded.id).select('-password');
18
+
19
+ next(); // Pass the user to the next step
20
+ } catch (error) {
21
+ console.error(error);
22
+ res.status(401).json({ message: 'Not authorized, token failed' });
23
+ }
24
+ }
25
+
26
+ if (!token) {
27
+ res.status(401).json({ message: 'Not authorized, no token' });
28
+ }
29
+ };
30
+
31
+ export default protect;
@@ -0,0 +1,28 @@
1
+ import mongoose from 'mongoose';
2
+
3
+ const userSchema = new mongoose.Schema({
4
+ name: {
5
+ type: String,
6
+ required: true,
7
+ },
8
+ email: {
9
+ type: String,
10
+ required: true,
11
+ unique: true,
12
+ },
13
+ password: {
14
+ type: String,
15
+ required: true
16
+ }, // <--- Added this!
17
+ role: {
18
+ type: String,
19
+ default: 'developer',
20
+ },
21
+ createdAt: {
22
+ type: Date,
23
+ default: Date.now,
24
+ },
25
+ });
26
+
27
+ const User = mongoose.model('User', userSchema);
28
+ export default User;
@@ -0,0 +1,99 @@
1
+ import express from 'express';
2
+ import bcrypt from 'bcryptjs'; // <--- Import this
3
+ import User from './models/User.js';
4
+ import jwt from 'jsonwebtoken';
5
+ import protect from './middleware/authMiddleware.js';
6
+ const router = express.Router();
7
+
8
+ // 1. GET ALL USERS
9
+ router.get('/users', async (req, res) => {
10
+ try {
11
+ // Return everything BUT the password (security best practice)
12
+ const users = await User.find().select('-password');
13
+ res.json(users);
14
+ } catch (error) {
15
+ res.status(500).json({ message: error.message });
16
+ }
17
+ });
18
+
19
+ // 2. CREATE A USER (Sign Up)
20
+ router.post('/users', async (req, res) => {
21
+ try {
22
+ const { name, email, password } = req.body;
23
+
24
+ // 1. Check if user exists
25
+ const userExists = await User.findOne({ email });
26
+ if (userExists) {
27
+ return res.status(400).json({ message: 'User already exists' });
28
+ }
29
+
30
+ // 2. Hash the password
31
+ const salt = await bcrypt.genSalt(10);
32
+ const hashedPassword = await bcrypt.hash(password, salt);
33
+
34
+ // 3. Create user with hashed password
35
+ const newUser = new User({
36
+ name,
37
+ email,
38
+ password: hashedPassword
39
+ });
40
+
41
+ const savedUser = await newUser.save();
42
+
43
+ // 4. Respond (don't send back the password!)
44
+ res.status(201).json({
45
+ _id: savedUser._id,
46
+ name: savedUser.name,
47
+ email: savedUser.email,
48
+ });
49
+
50
+ } catch (error) {
51
+ res.status(400).json({ message: error.message });
52
+ }
53
+ });
54
+
55
+ // 3. LOGIN USER (Generate Token)
56
+ router.post('/login', async (req, res) => {
57
+ try {
58
+ const { email, password } = req.body;
59
+
60
+ // A. Validate User
61
+ const user = await User.findOne({ email });
62
+ if (!user) return res.status(400).json({ message: 'Invalid credentials' });
63
+
64
+ // B. Validate Password
65
+ const isMatch = await bcrypt.compare(password, user.password);
66
+ if (!isMatch) return res.status(400).json({ message: 'Invalid credentials' });
67
+
68
+ // C. Generate Token
69
+ const token = jwt.sign(
70
+ { id: user._id },
71
+ process.env.JWT_SECRET,
72
+ { expiresIn: '30d' }
73
+ );
74
+
75
+ // D. Response: STRICTLY TOKEN ONLY
76
+ res.json({
77
+ message: "Login successful",
78
+ token: token
79
+ });
80
+
81
+ } catch (error) {
82
+ res.status(500).json({ message: error.message });
83
+ }
84
+ });
85
+
86
+ // 4. Profile - Middleware
87
+ router.get('/profile', protect, (req, res) => {
88
+ // The 'protect' middleware has already run.
89
+ // It found the user and put it in 'req.user'.
90
+
91
+ res.json({
92
+ _id: req.user._id,
93
+ name: req.user.name,
94
+ email: req.user.email,
95
+ role: req.user.role,
96
+ message: `Verification Successful. Welcome, ${req.user.name}!`
97
+ });
98
+ });
99
+ export default router;
@@ -0,0 +1,3 @@
1
+ MONGO_URI=
2
+ PORT=
3
+ JWT_SECRET=
@@ -0,0 +1,29 @@
1
+ import js from '@eslint/js'
2
+ import globals from 'globals'
3
+ import reactHooks from 'eslint-plugin-react-hooks'
4
+ import reactRefresh from 'eslint-plugin-react-refresh'
5
+ import { defineConfig, globalIgnores } from 'eslint/config'
6
+
7
+ export default defineConfig([
8
+ globalIgnores(['dist']),
9
+ {
10
+ files: ['**/*.{js,jsx}'],
11
+ extends: [
12
+ js.configs.recommended,
13
+ reactHooks.configs.flat.recommended,
14
+ reactRefresh.configs.vite,
15
+ ],
16
+ languageOptions: {
17
+ ecmaVersion: 2020,
18
+ globals: globals.browser,
19
+ parserOptions: {
20
+ ecmaVersion: 'latest',
21
+ ecmaFeatures: { jsx: true },
22
+ sourceType: 'module',
23
+ },
24
+ },
25
+ rules: {
26
+ 'no-unused-vars': ['error', { varsIgnorePattern: '^[A-Z_]' }],
27
+ },
28
+ },
29
+ ])
@@ -0,0 +1,13 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/svg+xml" href="/rex.png" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>Rex - One House Partner</title>
8
+ </head>
9
+ <body>
10
+ <div id="root"></div>
11
+ <script type="module" src="/src/main.jsx"></script>
12
+ </body>
13
+ </html>