boilercraft 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.
- package/LICENSE +21 -0
- package/README.md +171 -0
- package/bin/boilercraft.js +110 -0
- package/cli/app.js +596 -0
- package/cli/ui.js +356 -0
- package/docs/STACK_ENGINE.md +93 -0
- package/docs/assets/cli-create.svg +52 -0
- package/docs/assets/cli-menu.svg +47 -0
- package/docs/stacks/dotnet-core.md +69 -0
- package/docs/stacks/laravel-vue.md +46 -0
- package/docs/stacks/nextjs.md +58 -0
- package/docs/stacks/node-express.md +58 -0
- package/docs/stacks/raw-php.md +130 -0
- package/main.js +82 -0
- package/package.json +86 -0
- package/public/index.html +721 -0
- package/public/logo.png +17 -0
- package/public/logo.svg +17 -0
- package/server.js +84 -0
- package/services/componentGenerator.js +195 -0
- package/services/engine/scaffoldEngine.js +517 -0
- package/services/engine/toolInstaller.js +232 -0
- package/services/engine/versionCatalog.js +115 -0
- package/services/generate.js +46 -0
- package/services/projectGenerator.js +686 -0
- package/services/readmeGenerator.js +221 -0
- package/services/themeGenerator.js +150 -0
- package/services/versionResolver.js +176 -0
- package/stacks/dotnet-core/overlays/api/Controllers/ProductsController.cs +33 -0
- package/stacks/dotnet-core/overlays/api/Program.cs +33 -0
- package/stacks/dotnet-core/overlays/api/wwwroot/index.html +38 -0
- package/stacks/dotnet-core/overlays/api-auth/Controllers/AuthController.cs +87 -0
- package/stacks/dotnet-core/overlays/common/Data/ApplicationDbContext.cs +25 -0
- package/stacks/dotnet-core/overlays/common/Models/Product.cs +19 -0
- package/stacks/dotnet-core/overlays/mvc/Controllers/ProductsController.cs +84 -0
- package/stacks/dotnet-core/overlays/mvc/Views/Home/Index.cshtml +23 -0
- package/stacks/dotnet-core/overlays/mvc/Views/Products/Create.cshtml +16 -0
- package/stacks/dotnet-core/overlays/mvc/Views/Products/Delete.cshtml +16 -0
- package/stacks/dotnet-core/overlays/mvc/Views/Products/Edit.cshtml +17 -0
- package/stacks/dotnet-core/overlays/mvc/Views/Products/Index.cshtml +46 -0
- package/stacks/dotnet-core/overlays/mvc/Views/Products/_Form.cshtml +19 -0
- package/stacks/dotnet-core/overlays/mvc-auth/Controllers/AccountController.cs +98 -0
- package/stacks/dotnet-core/overlays/mvc-auth/Models/AppUser.cs +48 -0
- package/stacks/dotnet-core/overlays/mvc-auth/Views/Account/Login.cshtml +35 -0
- package/stacks/dotnet-core/overlays/mvc-auth/Views/Account/Register.cshtml +41 -0
- package/stacks/dotnet-core/overlays/mvc-auth/Views/Shared/_AuthNav.cshtml +22 -0
- package/stacks/dotnet-core/snippets/packages-auth.xml +4 -0
- package/stacks/dotnet-core/snippets/packages-common.xml +5 -0
- package/stacks/dotnet-core/snippets/packages-ef.xml +4 -0
- package/stacks/dotnet-core/snippets/packages-mssql.xml +4 -0
- package/stacks/dotnet-core/snippets/packages-mysql.xml +4 -0
- package/stacks/dotnet-core/snippets/packages-swagger.xml +4 -0
- package/stacks/dotnet-core/stack.json +426 -0
- package/stacks/laravel/overlays/auth/app/Http/Controllers/Api/AuthController.php +67 -0
- package/stacks/laravel/overlays/common/app/Http/Controllers/BoilerCraftController.php +14 -0
- package/stacks/laravel/overlays/common/resources/views/boilercraft.blade.php +36 -0
- package/stacks/laravel/overlays/inertia-common/resources/views/app.blade.php +15 -0
- package/stacks/laravel/overlays/inertia-react/resources/js/Pages/Welcome.jsx +18 -0
- package/stacks/laravel/overlays/inertia-react/resources/js/app.jsx +13 -0
- package/stacks/laravel/overlays/inertia-vue/resources/js/Pages/Welcome.vue +23 -0
- package/stacks/laravel/overlays/inertia-vue/resources/js/app.js +13 -0
- package/stacks/laravel/snippets/api-routes.php +9 -0
- package/stacks/laravel/snippets/web-routes-inertia.php +7 -0
- package/stacks/laravel/snippets/web-routes.php +4 -0
- package/stacks/laravel/stack.json +477 -0
- package/stacks/nextjs/overlays/auth/src/lib/auth.js +36 -0
- package/stacks/nextjs/overlays/auth-app/src/app/api/auth/login/route.js +11 -0
- package/stacks/nextjs/overlays/auth-app/src/app/api/auth/register/route.js +14 -0
- package/stacks/nextjs/overlays/auth-pages/src/pages/api/auth/login.js +14 -0
- package/stacks/nextjs/overlays/auth-pages/src/pages/api/auth/register.js +17 -0
- package/stacks/nextjs/overlays/common/.env.example +3 -0
- package/stacks/nextjs/overlays/common/.env.local +3 -0
- package/stacks/nextjs/overlays/db/mongodb/src/lib/db.js +12 -0
- package/stacks/nextjs/overlays/db/mssql/src/lib/db.js +17 -0
- package/stacks/nextjs/overlays/db/mysql/src/lib/db.js +13 -0
- package/stacks/nextjs/overlays/router-app/src/app/api/health/route.js +10 -0
- package/stacks/nextjs/overlays/router-app/src/app/layout.js +16 -0
- package/stacks/nextjs/overlays/router-app/src/app/page.js +19 -0
- package/stacks/nextjs/overlays/router-pages/src/pages/_app.js +7 -0
- package/stacks/nextjs/overlays/router-pages/src/pages/_document.js +13 -0
- package/stacks/nextjs/overlays/router-pages/src/pages/api/health.js +8 -0
- package/stacks/nextjs/overlays/router-pages/src/pages/index.js +27 -0
- package/stacks/nextjs/stack.json +257 -0
- package/stacks/node-express/overlays/auth/src/controllers/authController.js +53 -0
- package/stacks/node-express/overlays/auth/src/middlewares/auth.js +36 -0
- package/stacks/node-express/overlays/auth/src/routes/authRoutes.js +16 -0
- package/stacks/node-express/overlays/common/.env.example +5 -0
- package/stacks/node-express/overlays/common/public/index.html +31 -0
- package/stacks/node-express/overlays/common/src/server.js +32 -0
- package/stacks/node-express/overlays/db/mongodb/src/db.js +13 -0
- package/stacks/node-express/overlays/db/mssql/src/db.js +22 -0
- package/stacks/node-express/overlays/db/mysql/src/db.js +22 -0
- package/stacks/node-express/stack.json +165 -0
- package/templates/dotnet-bootstrap-mssql/Controllers/AuthController.cs +74 -0
- package/templates/dotnet-bootstrap-mssql/Controllers/ProductsController.cs +33 -0
- package/templates/dotnet-bootstrap-mssql/Data/ApplicationDbContext.cs +24 -0
- package/templates/dotnet-bootstrap-mssql/Models/Product.cs +10 -0
- package/templates/dotnet-core/Controllers/AuthController.cs +74 -0
- package/templates/laravel-full/app/Http/Controllers/AuthController.php +79 -0
- package/templates/laravel-full/app/Http/Controllers/HomeController.php +22 -0
- package/templates/laravel-full/app/Models/User.php +49 -0
- package/templates/laravel-full/artisan +22 -0
- package/templates/laravel-full/bootstrap/app.php +21 -0
- package/templates/laravel-full/config/database.php +54 -0
- package/templates/laravel-full/database/migrations/2024_01_01_000001_create_users_table.php +27 -0
- package/templates/laravel-full/public/index.php +17 -0
- package/templates/laravel-full/resources/css/app.css +3 -0
- package/templates/laravel-full/resources/js/Pages/Home.vue +76 -0
- package/templates/laravel-full/resources/js/app.js +21 -0
- package/templates/laravel-full/resources/js/bootstrap.js +3 -0
- package/templates/laravel-full/resources/views/app.blade.php +15 -0
- package/templates/laravel-full/routes/api.php +8 -0
- package/templates/laravel-full/routes/console.php +7 -0
- package/templates/laravel-full/routes/web.php +24 -0
- package/templates/laravel-full/tailwind.config.js +12 -0
- package/templates/laravel-full/vite.config.js +20 -0
- package/templates/laravel-vue/app/Http/Controllers/Auth/AuthenticatedSessionController.php +43 -0
- package/templates/laravel-vue-mysql/app/Http/Controllers/HomeController.php +25 -0
- package/templates/laravel-vue-mysql/resources/js/Pages/Home.vue +70 -0
- package/templates/nextjs/src/app/api/auth/login/route.js +28 -0
- package/templates/nextjs-mongodb/src/app/api/health/route.js +17 -0
- package/templates/nextjs-mongodb/src/lib/mongodb.js +18 -0
- package/templates/nextjs-mssql/src/app/api/health/route.js +24 -0
- package/templates/nextjs-mssql/src/lib/mssql.js +38 -0
- package/templates/node-express/src/controllers/authController.js +53 -0
- package/templates/node-express/src/middlewares/auth.js +36 -0
- package/templates/node-express/src/routes/authRoutes.js +16 -0
- package/templates/node-mongodb/src/controllers/userController.js +30 -0
- package/templates/node-mongodb/src/middlewares/errorHandler.js +8 -0
- package/templates/node-mongodb/src/models/User.js +23 -0
- package/templates/node-mongodb/src/routes/api.js +9 -0
- package/templates/raw-php-mysql/app/Controllers/AuthController.php +73 -0
- package/templates/raw-php-mysql/app/Controllers/HomeController.php +65 -0
- package/templates/raw-php-mysql/app/Models/User.php +60 -0
- package/templates/raw-php-mysql/app/Views/404.php +15 -0
- package/templates/raw-php-mysql/app/Views/auth/login.php +66 -0
- package/templates/raw-php-mysql/app/Views/auth/register.php +71 -0
- package/templates/raw-php-mysql/app/Views/dashboard.php +50 -0
- package/templates/raw-php-mysql/app/Views/home.php +83 -0
- package/templates/raw-php-mysql/config/Auth.php +62 -0
- package/templates/raw-php-mysql/config/Database.php +100 -0
- package/templates/raw-php-mysql/config/Env.php +30 -0
- package/templates/raw-php-mysql/config/Middleware.php +53 -0
- package/templates/raw-php-mysql/config/QueryBuilder.php +109 -0
- package/templates/raw-php-mysql/config/Router.php +33 -0
- package/templates/raw-php-mysql/public/index.php +57 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import Head from 'next/head';
|
|
2
|
+
|
|
3
|
+
export default function Home() {
|
|
4
|
+
return (
|
|
5
|
+
<>
|
|
6
|
+
<Head>
|
|
7
|
+
<title>{{{APP_TITLE_JS}}}</title>
|
|
8
|
+
<meta name="description" content={{{APP_DESC_JS}}} />
|
|
9
|
+
</Head>
|
|
10
|
+
<div style={{ maxWidth: '900px', margin: '3rem auto', padding: '1rem', textAlign: 'center' }}>
|
|
11
|
+
<h1 style={{ fontSize: '2.5rem', fontWeight: 800 }}>{{APP_TITLE}}</h1>
|
|
12
|
+
<p style={{ color: 'var(--color-text-muted)' }}>{{APP_DESC}}</p>
|
|
13
|
+
|
|
14
|
+
<div style={{ marginTop: '2rem', padding: '1.5rem', background: 'var(--color-surface)', borderRadius: '1rem', textAlign: 'left', border: '1px solid var(--color-border)' }}>
|
|
15
|
+
<h3>Configured Architecture:</h3>
|
|
16
|
+
<ul>
|
|
17
|
+
<li><strong>Framework:</strong> Next.js {{VERSION}} (Pages Router)</li>
|
|
18
|
+
<li><strong>Database:</strong> {{DATABASE}}</li>
|
|
19
|
+
<li><strong>Styling:</strong> {{STYLING}}</li>
|
|
20
|
+
<li><strong>Theme:</strong> {{THEME}}</li>
|
|
21
|
+
</ul>
|
|
22
|
+
<p>Health API: <a href="/api/health" style={{ color: 'var(--color-primary)' }}>/api/health</a></p>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
</>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "nextjs",
|
|
3
|
+
"name": "Next.js",
|
|
4
|
+
"defaultPort": 3000,
|
|
5
|
+
"databases": [
|
|
6
|
+
"mongodb",
|
|
7
|
+
"mysql",
|
|
8
|
+
"mssql"
|
|
9
|
+
],
|
|
10
|
+
"stylings": [
|
|
11
|
+
"tailwind",
|
|
12
|
+
"bootstrap",
|
|
13
|
+
"vanilla"
|
|
14
|
+
],
|
|
15
|
+
"options": [
|
|
16
|
+
{
|
|
17
|
+
"id": "router",
|
|
18
|
+
"label": "Router",
|
|
19
|
+
"default": "app",
|
|
20
|
+
"choices": [
|
|
21
|
+
{
|
|
22
|
+
"value": "app",
|
|
23
|
+
"label": "App Router",
|
|
24
|
+
"hint": "recommended · Server Components · layouts"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"value": "pages",
|
|
28
|
+
"label": "Pages Router",
|
|
29
|
+
"hint": "classic · getServerSideProps · API routes"
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
],
|
|
34
|
+
"nextSteps": [
|
|
35
|
+
"npm run dev"
|
|
36
|
+
],
|
|
37
|
+
"versions": {
|
|
38
|
+
"source": "npm",
|
|
39
|
+
"package": "next",
|
|
40
|
+
"minMajor": 14,
|
|
41
|
+
"testedUpTo": 16,
|
|
42
|
+
"offline": [
|
|
43
|
+
16,
|
|
44
|
+
15,
|
|
45
|
+
14
|
|
46
|
+
]
|
|
47
|
+
},
|
|
48
|
+
"requires": [
|
|
49
|
+
{
|
|
50
|
+
"cmd": "node",
|
|
51
|
+
"name": "Node.js",
|
|
52
|
+
"install": "https://nodejs.org"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"cmd": "npx",
|
|
56
|
+
"name": "npx",
|
|
57
|
+
"install": "Ships with Node.js"
|
|
58
|
+
}
|
|
59
|
+
],
|
|
60
|
+
"steps": [
|
|
61
|
+
{
|
|
62
|
+
"label": "Running official create-next-app@{{VERSION}}",
|
|
63
|
+
"cwd": "parent",
|
|
64
|
+
"run": [
|
|
65
|
+
"npx",
|
|
66
|
+
"--yes",
|
|
67
|
+
"create-next-app@{{VERSION}}",
|
|
68
|
+
"{{PROJECT_NAME}}",
|
|
69
|
+
"--js",
|
|
70
|
+
"{{NEXT_ROUTER_FLAG}}",
|
|
71
|
+
"--src-dir",
|
|
72
|
+
"--eslint",
|
|
73
|
+
"--use-npm",
|
|
74
|
+
"--import-alias",
|
|
75
|
+
"@/*",
|
|
76
|
+
"{{NEXT_TAILWIND_FLAG}}"
|
|
77
|
+
]
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"when": {
|
|
81
|
+
"database": "mongodb"
|
|
82
|
+
},
|
|
83
|
+
"run": [
|
|
84
|
+
"npm",
|
|
85
|
+
"install",
|
|
86
|
+
"mongoose"
|
|
87
|
+
]
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"when": {
|
|
91
|
+
"database": "mysql"
|
|
92
|
+
},
|
|
93
|
+
"run": [
|
|
94
|
+
"npm",
|
|
95
|
+
"install",
|
|
96
|
+
"mysql2"
|
|
97
|
+
]
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"when": {
|
|
101
|
+
"database": "mssql"
|
|
102
|
+
},
|
|
103
|
+
"run": [
|
|
104
|
+
"npm",
|
|
105
|
+
"install",
|
|
106
|
+
"mssql"
|
|
107
|
+
]
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"when": {
|
|
111
|
+
"styling": "bootstrap"
|
|
112
|
+
},
|
|
113
|
+
"run": [
|
|
114
|
+
"npm",
|
|
115
|
+
"install",
|
|
116
|
+
"bootstrap"
|
|
117
|
+
]
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"when": {
|
|
121
|
+
"auth": true
|
|
122
|
+
},
|
|
123
|
+
"run": [
|
|
124
|
+
"npm",
|
|
125
|
+
"install",
|
|
126
|
+
"jsonwebtoken",
|
|
127
|
+
"bcryptjs"
|
|
128
|
+
]
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"json": "package.json",
|
|
132
|
+
"merge": {
|
|
133
|
+
"scripts": {
|
|
134
|
+
"dev": "next dev -p {{PORT}}",
|
|
135
|
+
"start": "next start -p {{PORT}}"
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
"label": "Applying BoilerCraft overlay",
|
|
141
|
+
"copy": "overlays/common"
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
"when": {
|
|
145
|
+
"router": "app"
|
|
146
|
+
},
|
|
147
|
+
"copy": "overlays/router-app"
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
"when": {
|
|
151
|
+
"router": "pages"
|
|
152
|
+
},
|
|
153
|
+
"copy": "overlays/router-pages"
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
"when": {
|
|
157
|
+
"database": "mongodb"
|
|
158
|
+
},
|
|
159
|
+
"copy": "overlays/db/mongodb"
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
"when": {
|
|
163
|
+
"database": "mysql"
|
|
164
|
+
},
|
|
165
|
+
"copy": "overlays/db/mysql"
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
"when": {
|
|
169
|
+
"database": "mssql"
|
|
170
|
+
},
|
|
171
|
+
"copy": "overlays/db/mssql"
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
"when": {
|
|
175
|
+
"auth": true
|
|
176
|
+
},
|
|
177
|
+
"copy": "overlays/auth"
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
"when": {
|
|
181
|
+
"auth": true,
|
|
182
|
+
"router": "app"
|
|
183
|
+
},
|
|
184
|
+
"copy": "overlays/auth-app"
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
"when": {
|
|
188
|
+
"auth": true,
|
|
189
|
+
"router": "pages"
|
|
190
|
+
},
|
|
191
|
+
"copy": "overlays/auth-pages"
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
"when": {
|
|
195
|
+
"styling": "bootstrap",
|
|
196
|
+
"router": "app"
|
|
197
|
+
},
|
|
198
|
+
"write": "src/styles/vendor.js",
|
|
199
|
+
"content": "import 'bootstrap/dist/css/bootstrap.min.css';\n"
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
"when": {
|
|
203
|
+
"styling": [
|
|
204
|
+
"tailwind",
|
|
205
|
+
"vanilla"
|
|
206
|
+
],
|
|
207
|
+
"router": "app"
|
|
208
|
+
},
|
|
209
|
+
"write": "src/styles/vendor.js",
|
|
210
|
+
"content": "// No vendor stylesheet for this styling option.\n"
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
"write": "src/styles/theme.css",
|
|
214
|
+
"content": "{{THEME_CSS}}"
|
|
215
|
+
}
|
|
216
|
+
],
|
|
217
|
+
"vars": [
|
|
218
|
+
{
|
|
219
|
+
"name": "NEXT_ROUTER_FLAG",
|
|
220
|
+
"when": {
|
|
221
|
+
"router": "app"
|
|
222
|
+
},
|
|
223
|
+
"value": "--app"
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
"name": "NEXT_ROUTER_FLAG",
|
|
227
|
+
"when": {
|
|
228
|
+
"router": "pages"
|
|
229
|
+
},
|
|
230
|
+
"value": "--no-app"
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
"name": "NEXT_TAILWIND_FLAG",
|
|
234
|
+
"when": {
|
|
235
|
+
"styling": "tailwind"
|
|
236
|
+
},
|
|
237
|
+
"value": "--tailwind"
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
"name": "NEXT_TAILWIND_FLAG",
|
|
241
|
+
"when": {
|
|
242
|
+
"styling": [
|
|
243
|
+
"bootstrap",
|
|
244
|
+
"vanilla"
|
|
245
|
+
]
|
|
246
|
+
},
|
|
247
|
+
"value": "--no-tailwind"
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
"name": "PAGES_VENDOR_CSS",
|
|
251
|
+
"when": {
|
|
252
|
+
"styling": "bootstrap"
|
|
253
|
+
},
|
|
254
|
+
"value": "import 'bootstrap/dist/css/bootstrap.min.css';"
|
|
255
|
+
}
|
|
256
|
+
]
|
|
257
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
const bcrypt = require('bcryptjs');
|
|
2
|
+
const jwt = require('jsonwebtoken');
|
|
3
|
+
const { JWT_SECRET } = require('../middlewares/auth');
|
|
4
|
+
|
|
5
|
+
// In-memory or dynamic model fallback
|
|
6
|
+
let usersTable = [];
|
|
7
|
+
|
|
8
|
+
exports.register = async (req, res) => {
|
|
9
|
+
const { name, email, password, role = 'user' } = req.body;
|
|
10
|
+
if (!name || !email || !password) {
|
|
11
|
+
return res.status(400).json({ success: false, error: 'Name, email, and password required.' });
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const existing = usersTable.find(u => u.email === email);
|
|
15
|
+
if (existing) {
|
|
16
|
+
return res.status(409).json({ success: false, error: 'User already exists.' });
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const hashedPassword = await bcrypt.hash(password, 10);
|
|
20
|
+
const newUser = { id: usersTable.length + 1, name, email, password: hashedPassword, role };
|
|
21
|
+
usersTable.push(newUser);
|
|
22
|
+
|
|
23
|
+
const token = jwt.sign({ id: newUser.id, name: newUser.name, email: newUser.email, role: newUser.role }, JWT_SECRET, { expiresIn: '7d' });
|
|
24
|
+
|
|
25
|
+
res.status(201).json({
|
|
26
|
+
success: true,
|
|
27
|
+
message: 'User registered successfully',
|
|
28
|
+
token,
|
|
29
|
+
user: { id: newUser.id, name: newUser.name, email: newUser.email, role: newUser.role }
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
exports.login = async (req, res) => {
|
|
34
|
+
const { email, password } = req.body;
|
|
35
|
+
const user = usersTable.find(u => u.email === email);
|
|
36
|
+
|
|
37
|
+
if (!user || !(await bcrypt.compare(password, user.password))) {
|
|
38
|
+
return res.status(401).json({ success: false, error: 'Invalid credentials.' });
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const token = jwt.sign({ id: user.id, name: user.name, email: user.email, role: user.role }, JWT_SECRET, { expiresIn: '7d' });
|
|
42
|
+
|
|
43
|
+
res.json({
|
|
44
|
+
success: true,
|
|
45
|
+
message: 'Login successful',
|
|
46
|
+
token,
|
|
47
|
+
user: { id: user.id, name: user.name, email: user.email, role: user.role }
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
exports.getProfile = (req, res) => {
|
|
52
|
+
res.json({ success: true, user: req.user });
|
|
53
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const jwt = require('jsonwebtoken');
|
|
2
|
+
|
|
3
|
+
const JWT_SECRET = process.env.JWT_SECRET || 'super_secret_jwt_key_boiler_craft_2026';
|
|
4
|
+
|
|
5
|
+
function auth(req, res, next) {
|
|
6
|
+
const authHeader = req.headers['authorization'];
|
|
7
|
+
const token = authHeader && authHeader.split(' ')[1];
|
|
8
|
+
|
|
9
|
+
if (!token) {
|
|
10
|
+
return res.status(401).json({ success: false, error: 'Access denied. No token provided.' });
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
const decoded = jwt.verify(token, JWT_SECRET);
|
|
15
|
+
req.user = decoded;
|
|
16
|
+
next();
|
|
17
|
+
} catch (err) {
|
|
18
|
+
return res.status(403).json({ success: false, error: 'Invalid or expired token.' });
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function role(allowedRoles = []) {
|
|
23
|
+
if (typeof allowedRoles === 'string') allowedRoles = [allowedRoles];
|
|
24
|
+
|
|
25
|
+
return (req, res, next) => {
|
|
26
|
+
if (!req.user) {
|
|
27
|
+
return res.status(401).json({ success: false, error: 'Unauthenticated.' });
|
|
28
|
+
}
|
|
29
|
+
if (!allowedRoles.includes(req.user.role)) {
|
|
30
|
+
return res.status(403).json({ success: false, error: 'Forbidden. Insufficient permissions.' });
|
|
31
|
+
}
|
|
32
|
+
next();
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
module.exports = { auth, role, JWT_SECRET };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const express = require('express');
|
|
2
|
+
const router = express.Router();
|
|
3
|
+
const { register, login, getProfile } = require('../controllers/authController');
|
|
4
|
+
const { auth, role } = require('../middlewares/auth');
|
|
5
|
+
|
|
6
|
+
// Public
|
|
7
|
+
router.post('/register', register);
|
|
8
|
+
router.post('/login', login);
|
|
9
|
+
|
|
10
|
+
// Protected Routes
|
|
11
|
+
router.get('/profile', auth, getProfile);
|
|
12
|
+
router.get('/admin', auth, role('admin'), (req, res) => {
|
|
13
|
+
res.json({ success: true, message: 'Welcome to Admin Authorized Area!', user: req.user });
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
module.exports = router;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en" data-theme="{{COLOR_MODE}}">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>{{APP_TITLE}}</title>
|
|
7
|
+
<link rel="stylesheet" href="/theme.css">
|
|
8
|
+
{{STYLESHEET_LINK}}
|
|
9
|
+
</head>
|
|
10
|
+
<body class="p-6">
|
|
11
|
+
<div style="max-width: 850px; margin: 2rem auto; text-align: center;">
|
|
12
|
+
{{LOGO_HTML}}
|
|
13
|
+
<h1>{{APP_TITLE}}</h1>
|
|
14
|
+
<p style="color: var(--color-text-muted);">{{APP_DESC}}</p>
|
|
15
|
+
|
|
16
|
+
<div style="text-align: left; padding: 2rem; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-base); margin-top: 2rem;">
|
|
17
|
+
<h3>Active Architecture:</h3>
|
|
18
|
+
<ul>
|
|
19
|
+
<li><strong>Backend:</strong> Node.js + Express {{VERSION}}.x</li>
|
|
20
|
+
<li><strong>Database:</strong> {{DATABASE}}</li>
|
|
21
|
+
<li><strong>Styling:</strong> {{STYLING}}</li>
|
|
22
|
+
</ul>
|
|
23
|
+
<p>Health API: <a href="/api/health">/api/health</a></p>
|
|
24
|
+
<hr style="border: none; border-top: 1px solid var(--color-border); margin: 1.5rem 0;" />
|
|
25
|
+
<h4>Components:</h4>
|
|
26
|
+
{{UI_COMPONENTS}}
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
<script src="/theme.js"></script>
|
|
30
|
+
</body>
|
|
31
|
+
</html>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const express = require('express');
|
|
2
|
+
const cors = require('cors');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
require('dotenv').config();
|
|
5
|
+
const { connectDB } = require('./db');
|
|
6
|
+
{{AUTH_REQUIRE}}
|
|
7
|
+
|
|
8
|
+
const app = express();
|
|
9
|
+
const PORT = process.env.PORT || {{PORT}};
|
|
10
|
+
|
|
11
|
+
app.use(cors());
|
|
12
|
+
app.use(express.json());
|
|
13
|
+
app.use(express.static(path.join(__dirname, '../public')));
|
|
14
|
+
|
|
15
|
+
connectDB();
|
|
16
|
+
|
|
17
|
+
// API Endpoints
|
|
18
|
+
{{AUTH_MOUNT}}
|
|
19
|
+
|
|
20
|
+
app.get('/api/health', (req, res) => {
|
|
21
|
+
res.json({
|
|
22
|
+
status: 'online',
|
|
23
|
+
app: {{APP_TITLE_JS}},
|
|
24
|
+
database: '{{DB_TYPE}}',
|
|
25
|
+
express: require('express/package.json').version,
|
|
26
|
+
auth: {{AUTH_ENABLED}}
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
app.listen(PORT, () => {
|
|
31
|
+
console.log(`⚡ Server listening at http://localhost:${PORT}`);
|
|
32
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const mongoose = require('mongoose');
|
|
2
|
+
|
|
3
|
+
async function connectDB() {
|
|
4
|
+
const uri = process.env.MONGODB_URI || 'mongodb://127.0.0.1:27017/{{DB_NAME}}';
|
|
5
|
+
try {
|
|
6
|
+
await mongoose.connect(uri);
|
|
7
|
+
console.log('⚡ Connected to MongoDB (Mongoose)');
|
|
8
|
+
} catch (err) {
|
|
9
|
+
console.error('❌ MongoDB Connection Error:', err.message);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
module.exports = { connectDB };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const sql = require('mssql');
|
|
2
|
+
|
|
3
|
+
const config = {
|
|
4
|
+
user: process.env.DB_USERNAME || 'sa',
|
|
5
|
+
password: process.env.DB_PASSWORD || '',
|
|
6
|
+
server: process.env.DB_HOST || 'localhost',
|
|
7
|
+
database: process.env.DB_DATABASE || '{{DB_NAME}}',
|
|
8
|
+
port: parseInt(process.env.DB_PORT || '1433', 10),
|
|
9
|
+
options: { encrypt: false, trustServerCertificate: true }
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
async function connectDB() {
|
|
13
|
+
try {
|
|
14
|
+
const pool = await sql.connect(config);
|
|
15
|
+
console.log('⚡ Connected to MSSQL (SQL Server)');
|
|
16
|
+
return pool;
|
|
17
|
+
} catch (err) {
|
|
18
|
+
console.error('❌ MSSQL Connection Error:', err.message);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
module.exports = { connectDB, sql };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const mysql = require('mysql2/promise');
|
|
2
|
+
|
|
3
|
+
let pool;
|
|
4
|
+
|
|
5
|
+
async function connectDB() {
|
|
6
|
+
try {
|
|
7
|
+
pool = mysql.createPool({
|
|
8
|
+
host: process.env.DB_HOST || '127.0.0.1',
|
|
9
|
+
user: process.env.DB_USERNAME || 'root',
|
|
10
|
+
password: process.env.DB_PASSWORD || '',
|
|
11
|
+
database: process.env.DB_DATABASE || '{{DB_NAME}}',
|
|
12
|
+
port: parseInt(process.env.DB_PORT || '3306', 10)
|
|
13
|
+
});
|
|
14
|
+
await pool.query('SELECT 1');
|
|
15
|
+
console.log('⚡ Connected to MySQL');
|
|
16
|
+
} catch (err) {
|
|
17
|
+
console.error('❌ MySQL Connection Error:', err.message);
|
|
18
|
+
}
|
|
19
|
+
return pool;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
module.exports = { connectDB, getPool: () => pool };
|