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.
Files changed (146) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +171 -0
  3. package/bin/boilercraft.js +110 -0
  4. package/cli/app.js +596 -0
  5. package/cli/ui.js +356 -0
  6. package/docs/STACK_ENGINE.md +93 -0
  7. package/docs/assets/cli-create.svg +52 -0
  8. package/docs/assets/cli-menu.svg +47 -0
  9. package/docs/stacks/dotnet-core.md +69 -0
  10. package/docs/stacks/laravel-vue.md +46 -0
  11. package/docs/stacks/nextjs.md +58 -0
  12. package/docs/stacks/node-express.md +58 -0
  13. package/docs/stacks/raw-php.md +130 -0
  14. package/main.js +82 -0
  15. package/package.json +86 -0
  16. package/public/index.html +721 -0
  17. package/public/logo.png +17 -0
  18. package/public/logo.svg +17 -0
  19. package/server.js +84 -0
  20. package/services/componentGenerator.js +195 -0
  21. package/services/engine/scaffoldEngine.js +517 -0
  22. package/services/engine/toolInstaller.js +232 -0
  23. package/services/engine/versionCatalog.js +115 -0
  24. package/services/generate.js +46 -0
  25. package/services/projectGenerator.js +686 -0
  26. package/services/readmeGenerator.js +221 -0
  27. package/services/themeGenerator.js +150 -0
  28. package/services/versionResolver.js +176 -0
  29. package/stacks/dotnet-core/overlays/api/Controllers/ProductsController.cs +33 -0
  30. package/stacks/dotnet-core/overlays/api/Program.cs +33 -0
  31. package/stacks/dotnet-core/overlays/api/wwwroot/index.html +38 -0
  32. package/stacks/dotnet-core/overlays/api-auth/Controllers/AuthController.cs +87 -0
  33. package/stacks/dotnet-core/overlays/common/Data/ApplicationDbContext.cs +25 -0
  34. package/stacks/dotnet-core/overlays/common/Models/Product.cs +19 -0
  35. package/stacks/dotnet-core/overlays/mvc/Controllers/ProductsController.cs +84 -0
  36. package/stacks/dotnet-core/overlays/mvc/Views/Home/Index.cshtml +23 -0
  37. package/stacks/dotnet-core/overlays/mvc/Views/Products/Create.cshtml +16 -0
  38. package/stacks/dotnet-core/overlays/mvc/Views/Products/Delete.cshtml +16 -0
  39. package/stacks/dotnet-core/overlays/mvc/Views/Products/Edit.cshtml +17 -0
  40. package/stacks/dotnet-core/overlays/mvc/Views/Products/Index.cshtml +46 -0
  41. package/stacks/dotnet-core/overlays/mvc/Views/Products/_Form.cshtml +19 -0
  42. package/stacks/dotnet-core/overlays/mvc-auth/Controllers/AccountController.cs +98 -0
  43. package/stacks/dotnet-core/overlays/mvc-auth/Models/AppUser.cs +48 -0
  44. package/stacks/dotnet-core/overlays/mvc-auth/Views/Account/Login.cshtml +35 -0
  45. package/stacks/dotnet-core/overlays/mvc-auth/Views/Account/Register.cshtml +41 -0
  46. package/stacks/dotnet-core/overlays/mvc-auth/Views/Shared/_AuthNav.cshtml +22 -0
  47. package/stacks/dotnet-core/snippets/packages-auth.xml +4 -0
  48. package/stacks/dotnet-core/snippets/packages-common.xml +5 -0
  49. package/stacks/dotnet-core/snippets/packages-ef.xml +4 -0
  50. package/stacks/dotnet-core/snippets/packages-mssql.xml +4 -0
  51. package/stacks/dotnet-core/snippets/packages-mysql.xml +4 -0
  52. package/stacks/dotnet-core/snippets/packages-swagger.xml +4 -0
  53. package/stacks/dotnet-core/stack.json +426 -0
  54. package/stacks/laravel/overlays/auth/app/Http/Controllers/Api/AuthController.php +67 -0
  55. package/stacks/laravel/overlays/common/app/Http/Controllers/BoilerCraftController.php +14 -0
  56. package/stacks/laravel/overlays/common/resources/views/boilercraft.blade.php +36 -0
  57. package/stacks/laravel/overlays/inertia-common/resources/views/app.blade.php +15 -0
  58. package/stacks/laravel/overlays/inertia-react/resources/js/Pages/Welcome.jsx +18 -0
  59. package/stacks/laravel/overlays/inertia-react/resources/js/app.jsx +13 -0
  60. package/stacks/laravel/overlays/inertia-vue/resources/js/Pages/Welcome.vue +23 -0
  61. package/stacks/laravel/overlays/inertia-vue/resources/js/app.js +13 -0
  62. package/stacks/laravel/snippets/api-routes.php +9 -0
  63. package/stacks/laravel/snippets/web-routes-inertia.php +7 -0
  64. package/stacks/laravel/snippets/web-routes.php +4 -0
  65. package/stacks/laravel/stack.json +477 -0
  66. package/stacks/nextjs/overlays/auth/src/lib/auth.js +36 -0
  67. package/stacks/nextjs/overlays/auth-app/src/app/api/auth/login/route.js +11 -0
  68. package/stacks/nextjs/overlays/auth-app/src/app/api/auth/register/route.js +14 -0
  69. package/stacks/nextjs/overlays/auth-pages/src/pages/api/auth/login.js +14 -0
  70. package/stacks/nextjs/overlays/auth-pages/src/pages/api/auth/register.js +17 -0
  71. package/stacks/nextjs/overlays/common/.env.example +3 -0
  72. package/stacks/nextjs/overlays/common/.env.local +3 -0
  73. package/stacks/nextjs/overlays/db/mongodb/src/lib/db.js +12 -0
  74. package/stacks/nextjs/overlays/db/mssql/src/lib/db.js +17 -0
  75. package/stacks/nextjs/overlays/db/mysql/src/lib/db.js +13 -0
  76. package/stacks/nextjs/overlays/router-app/src/app/api/health/route.js +10 -0
  77. package/stacks/nextjs/overlays/router-app/src/app/layout.js +16 -0
  78. package/stacks/nextjs/overlays/router-app/src/app/page.js +19 -0
  79. package/stacks/nextjs/overlays/router-pages/src/pages/_app.js +7 -0
  80. package/stacks/nextjs/overlays/router-pages/src/pages/_document.js +13 -0
  81. package/stacks/nextjs/overlays/router-pages/src/pages/api/health.js +8 -0
  82. package/stacks/nextjs/overlays/router-pages/src/pages/index.js +27 -0
  83. package/stacks/nextjs/stack.json +257 -0
  84. package/stacks/node-express/overlays/auth/src/controllers/authController.js +53 -0
  85. package/stacks/node-express/overlays/auth/src/middlewares/auth.js +36 -0
  86. package/stacks/node-express/overlays/auth/src/routes/authRoutes.js +16 -0
  87. package/stacks/node-express/overlays/common/.env.example +5 -0
  88. package/stacks/node-express/overlays/common/public/index.html +31 -0
  89. package/stacks/node-express/overlays/common/src/server.js +32 -0
  90. package/stacks/node-express/overlays/db/mongodb/src/db.js +13 -0
  91. package/stacks/node-express/overlays/db/mssql/src/db.js +22 -0
  92. package/stacks/node-express/overlays/db/mysql/src/db.js +22 -0
  93. package/stacks/node-express/stack.json +165 -0
  94. package/templates/dotnet-bootstrap-mssql/Controllers/AuthController.cs +74 -0
  95. package/templates/dotnet-bootstrap-mssql/Controllers/ProductsController.cs +33 -0
  96. package/templates/dotnet-bootstrap-mssql/Data/ApplicationDbContext.cs +24 -0
  97. package/templates/dotnet-bootstrap-mssql/Models/Product.cs +10 -0
  98. package/templates/dotnet-core/Controllers/AuthController.cs +74 -0
  99. package/templates/laravel-full/app/Http/Controllers/AuthController.php +79 -0
  100. package/templates/laravel-full/app/Http/Controllers/HomeController.php +22 -0
  101. package/templates/laravel-full/app/Models/User.php +49 -0
  102. package/templates/laravel-full/artisan +22 -0
  103. package/templates/laravel-full/bootstrap/app.php +21 -0
  104. package/templates/laravel-full/config/database.php +54 -0
  105. package/templates/laravel-full/database/migrations/2024_01_01_000001_create_users_table.php +27 -0
  106. package/templates/laravel-full/public/index.php +17 -0
  107. package/templates/laravel-full/resources/css/app.css +3 -0
  108. package/templates/laravel-full/resources/js/Pages/Home.vue +76 -0
  109. package/templates/laravel-full/resources/js/app.js +21 -0
  110. package/templates/laravel-full/resources/js/bootstrap.js +3 -0
  111. package/templates/laravel-full/resources/views/app.blade.php +15 -0
  112. package/templates/laravel-full/routes/api.php +8 -0
  113. package/templates/laravel-full/routes/console.php +7 -0
  114. package/templates/laravel-full/routes/web.php +24 -0
  115. package/templates/laravel-full/tailwind.config.js +12 -0
  116. package/templates/laravel-full/vite.config.js +20 -0
  117. package/templates/laravel-vue/app/Http/Controllers/Auth/AuthenticatedSessionController.php +43 -0
  118. package/templates/laravel-vue-mysql/app/Http/Controllers/HomeController.php +25 -0
  119. package/templates/laravel-vue-mysql/resources/js/Pages/Home.vue +70 -0
  120. package/templates/nextjs/src/app/api/auth/login/route.js +28 -0
  121. package/templates/nextjs-mongodb/src/app/api/health/route.js +17 -0
  122. package/templates/nextjs-mongodb/src/lib/mongodb.js +18 -0
  123. package/templates/nextjs-mssql/src/app/api/health/route.js +24 -0
  124. package/templates/nextjs-mssql/src/lib/mssql.js +38 -0
  125. package/templates/node-express/src/controllers/authController.js +53 -0
  126. package/templates/node-express/src/middlewares/auth.js +36 -0
  127. package/templates/node-express/src/routes/authRoutes.js +16 -0
  128. package/templates/node-mongodb/src/controllers/userController.js +30 -0
  129. package/templates/node-mongodb/src/middlewares/errorHandler.js +8 -0
  130. package/templates/node-mongodb/src/models/User.js +23 -0
  131. package/templates/node-mongodb/src/routes/api.js +9 -0
  132. package/templates/raw-php-mysql/app/Controllers/AuthController.php +73 -0
  133. package/templates/raw-php-mysql/app/Controllers/HomeController.php +65 -0
  134. package/templates/raw-php-mysql/app/Models/User.php +60 -0
  135. package/templates/raw-php-mysql/app/Views/404.php +15 -0
  136. package/templates/raw-php-mysql/app/Views/auth/login.php +66 -0
  137. package/templates/raw-php-mysql/app/Views/auth/register.php +71 -0
  138. package/templates/raw-php-mysql/app/Views/dashboard.php +50 -0
  139. package/templates/raw-php-mysql/app/Views/home.php +83 -0
  140. package/templates/raw-php-mysql/config/Auth.php +62 -0
  141. package/templates/raw-php-mysql/config/Database.php +100 -0
  142. package/templates/raw-php-mysql/config/Env.php +30 -0
  143. package/templates/raw-php-mysql/config/Middleware.php +53 -0
  144. package/templates/raw-php-mysql/config/QueryBuilder.php +109 -0
  145. package/templates/raw-php-mysql/config/Router.php +33 -0
  146. package/templates/raw-php-mysql/public/index.php +57 -0
@@ -0,0 +1,477 @@
1
+ {
2
+ "id": "laravel",
3
+ "name": "Laravel",
4
+ "aliases": [
5
+ "laravel-vue-mysql"
6
+ ],
7
+ "defaultPort": 8000,
8
+ "databases": [
9
+ "mysql",
10
+ "mssql"
11
+ ],
12
+ "stylings": [
13
+ "tailwind",
14
+ "bootstrap",
15
+ "vanilla"
16
+ ],
17
+ "options": [
18
+ {
19
+ "id": "frontend",
20
+ "label": "Frontend",
21
+ "default": "blade",
22
+ "choices": [
23
+ {
24
+ "value": "blade",
25
+ "label": "Blade",
26
+ "hint": "server-rendered · classic Laravel"
27
+ },
28
+ {
29
+ "value": "vue",
30
+ "label": "Vue 3 (Inertia)",
31
+ "hint": "SPA feel, Laravel routing"
32
+ },
33
+ {
34
+ "value": "react",
35
+ "label": "React (Inertia)",
36
+ "hint": "SPA feel, Laravel routing"
37
+ }
38
+ ]
39
+ }
40
+ ],
41
+ "nextSteps": [
42
+ "php artisan migrate",
43
+ "php artisan serve --port={{PORT}}"
44
+ ],
45
+ "versions": {
46
+ "source": "packagist",
47
+ "package": "laravel/laravel",
48
+ "minMajor": 10,
49
+ "testedUpTo": 13,
50
+ "offline": [
51
+ 13,
52
+ 12,
53
+ 11,
54
+ 10
55
+ ]
56
+ },
57
+ "requires": [
58
+ {
59
+ "cmd": "php",
60
+ "args": [
61
+ "-v"
62
+ ],
63
+ "name": "PHP",
64
+ "install": "https://www.php.net/downloads (or XAMPP / WAMP / Laragon / Herd)"
65
+ },
66
+ {
67
+ "cmd": "composer",
68
+ "name": "Composer",
69
+ "install": "https://getcomposer.org/download/"
70
+ }
71
+ ],
72
+ "steps": [
73
+ {
74
+ "label": "Running official composer create-project laravel/laravel:^{{VERSION}}.0",
75
+ "cwd": "parent",
76
+ "run": [
77
+ "composer",
78
+ "create-project",
79
+ "laravel/laravel:^{{VERSION}}.0",
80
+ "{{PROJECT_NAME}}",
81
+ "--prefer-dist",
82
+ "--no-interaction"
83
+ ]
84
+ },
85
+ {
86
+ "env": {
87
+ "APP_NAME": "{{APP_TITLE_JS}}"
88
+ }
89
+ },
90
+ {
91
+ "when": {
92
+ "database": "mysql"
93
+ },
94
+ "env": {
95
+ "DB_CONNECTION": "mysql",
96
+ "DB_HOST": "127.0.0.1",
97
+ "DB_PORT": "3306",
98
+ "DB_DATABASE": "{{DB_NAME}}",
99
+ "DB_USERNAME": "root",
100
+ "DB_PASSWORD": ""
101
+ }
102
+ },
103
+ {
104
+ "when": {
105
+ "database": "mssql"
106
+ },
107
+ "env": {
108
+ "DB_CONNECTION": "sqlsrv",
109
+ "DB_HOST": "127.0.0.1",
110
+ "DB_PORT": "1433",
111
+ "DB_DATABASE": "{{DB_NAME}}",
112
+ "DB_USERNAME": "sa"
113
+ }
114
+ },
115
+ {
116
+ "when": {
117
+ "database": "mssql"
118
+ },
119
+ "env": {
120
+ "DB_PASSWORD": "{{RANDOM_PASSWORD}}"
121
+ },
122
+ "files": [
123
+ ".env"
124
+ ]
125
+ },
126
+ {
127
+ "when": {
128
+ "database": "mssql"
129
+ },
130
+ "env": {
131
+ "DB_PASSWORD": "change-me"
132
+ },
133
+ "files": [
134
+ ".env.example"
135
+ ]
136
+ },
137
+ {
138
+ "label": "Applying BoilerCraft overlay",
139
+ "copy": "overlays/common",
140
+ "when": {
141
+ "frontend": "blade"
142
+ }
143
+ },
144
+ {
145
+ "write": "public/css/boilercraft-theme.css",
146
+ "content": "{{THEME_CSS}}"
147
+ },
148
+ {
149
+ "write": "public/js/boilercraft-theme.js",
150
+ "content": "{{THEME_JS}}"
151
+ },
152
+ {
153
+ "append": "routes/web.php",
154
+ "from": "snippets/web-routes.php",
155
+ "when": {
156
+ "frontend": "blade"
157
+ }
158
+ },
159
+ {
160
+ "label": "Installing API scaffolding (Sanctum) via php artisan install:api",
161
+ "when": {
162
+ "auth": true,
163
+ "version": ">=11",
164
+ "frontend": "blade"
165
+ },
166
+ "run": [
167
+ "php",
168
+ "artisan",
169
+ "install:api",
170
+ "--no-interaction",
171
+ "--without-migration-prompt"
172
+ ]
173
+ },
174
+ {
175
+ "when": {
176
+ "auth": true,
177
+ "version": ">=11",
178
+ "frontend": "blade"
179
+ },
180
+ "replace": "app/Models/User.php",
181
+ "skipIfContains": "HasApiTokens",
182
+ "find": "use HasFactory, Notifiable;",
183
+ "with": "use \\Laravel\\Sanctum\\HasApiTokens, HasFactory, Notifiable;"
184
+ },
185
+ {
186
+ "when": {
187
+ "auth": true,
188
+ "frontend": "blade"
189
+ },
190
+ "copy": "overlays/auth"
191
+ },
192
+ {
193
+ "when": {
194
+ "auth": true,
195
+ "frontend": "blade"
196
+ },
197
+ "append": "routes/api.php",
198
+ "from": "snippets/api-routes.php"
199
+ },
200
+ {
201
+ "label": "Installing Laravel Breeze ({{OPTION_FRONTEND}}) with authentication",
202
+ "when": {
203
+ "auth": true,
204
+ "frontend": [
205
+ "vue",
206
+ "react"
207
+ ]
208
+ },
209
+ "run": [
210
+ "composer",
211
+ "require",
212
+ "laravel/breeze",
213
+ "--dev",
214
+ "--no-interaction"
215
+ ]
216
+ },
217
+ {
218
+ "label": "Running php artisan breeze:install {{OPTION_FRONTEND}}",
219
+ "when": {
220
+ "auth": true,
221
+ "frontend": [
222
+ "vue",
223
+ "react"
224
+ ]
225
+ },
226
+ "run": [
227
+ "php",
228
+ "artisan",
229
+ "breeze:install",
230
+ "{{OPTION_FRONTEND}}",
231
+ "--no-interaction"
232
+ ]
233
+ },
234
+ {
235
+ "label": "Installing Inertia (server side)",
236
+ "when": {
237
+ "auth": false,
238
+ "frontend": [
239
+ "vue",
240
+ "react"
241
+ ]
242
+ },
243
+ "run": [
244
+ "composer",
245
+ "require",
246
+ "inertiajs/inertia-laravel",
247
+ "--no-interaction"
248
+ ]
249
+ },
250
+ {
251
+ "when": {
252
+ "auth": false,
253
+ "frontend": [
254
+ "vue",
255
+ "react"
256
+ ]
257
+ },
258
+ "run": [
259
+ "php",
260
+ "artisan",
261
+ "inertia:middleware",
262
+ "--no-interaction"
263
+ ]
264
+ },
265
+ {
266
+ "when": {
267
+ "auth": false,
268
+ "frontend": [
269
+ "vue",
270
+ "react"
271
+ ],
272
+ "version": ">=11"
273
+ },
274
+ "replace": "bootstrap/app.php",
275
+ "skipIfContains": "HandleInertiaRequests",
276
+ "findRegex": "->withMiddleware\\(function \\(Middleware \\$middleware\\)(: void)? \\{",
277
+ "with": "$&\n $middleware->web(append: [\\App\\Http\\Middleware\\HandleInertiaRequests::class]);"
278
+ },
279
+ {
280
+ "when": {
281
+ "auth": false,
282
+ "frontend": [
283
+ "vue",
284
+ "react"
285
+ ],
286
+ "version": "<11"
287
+ },
288
+ "replace": "app/Http/Kernel.php",
289
+ "skipIfContains": "HandleInertiaRequests",
290
+ "find": "'web' => [",
291
+ "with": "$&\n \\App\\Http\\Middleware\\HandleInertiaRequests::class,"
292
+ },
293
+ {
294
+ "label": "Installing Vue 3 + Inertia (client side)",
295
+ "when": {
296
+ "auth": false,
297
+ "frontend": "vue"
298
+ },
299
+ "run": [
300
+ "npm",
301
+ "install",
302
+ "-D",
303
+ "{{VITE_PLUGIN_VUE}}",
304
+ "vue",
305
+ "@inertiajs/vue3"
306
+ ]
307
+ },
308
+ {
309
+ "label": "Installing React + Inertia (client side)",
310
+ "when": {
311
+ "auth": false,
312
+ "frontend": "react"
313
+ },
314
+ "run": [
315
+ "npm",
316
+ "install",
317
+ "-D",
318
+ "{{VITE_PLUGIN_REACT}}",
319
+ "react",
320
+ "react-dom",
321
+ "@inertiajs/react"
322
+ ]
323
+ },
324
+ {
325
+ "when": {
326
+ "auth": false,
327
+ "frontend": "vue"
328
+ },
329
+ "replace": "vite.config.js",
330
+ "skipIfContains": "@vitejs/plugin-vue",
331
+ "find": "import laravel from 'laravel-vite-plugin';",
332
+ "with": "import laravel from 'laravel-vite-plugin';\nimport vue from '@vitejs/plugin-vue';"
333
+ },
334
+ {
335
+ "when": {
336
+ "auth": false,
337
+ "frontend": "vue"
338
+ },
339
+ "replace": "vite.config.js",
340
+ "skipIfContains": "vue({",
341
+ "find": "plugins: [",
342
+ "with": "$&\n vue({ template: { transformAssetUrls: { base: null, includeAbsolute: false } } }),"
343
+ },
344
+ {
345
+ "when": {
346
+ "auth": false,
347
+ "frontend": "react"
348
+ },
349
+ "replace": "vite.config.js",
350
+ "skipIfContains": "@vitejs/plugin-react",
351
+ "find": "import laravel from 'laravel-vite-plugin';",
352
+ "with": "import laravel from 'laravel-vite-plugin';\nimport react from '@vitejs/plugin-react';"
353
+ },
354
+ {
355
+ "when": {
356
+ "auth": false,
357
+ "frontend": "react"
358
+ },
359
+ "replace": "vite.config.js",
360
+ "skipIfContains": "react(),",
361
+ "find": "plugins: [",
362
+ "with": "$&\n react(),"
363
+ },
364
+ {
365
+ "when": {
366
+ "auth": false,
367
+ "frontend": "react"
368
+ },
369
+ "replace": "vite.config.js",
370
+ "find": "resources/js/app.js'",
371
+ "with": "resources/js/app.jsx'"
372
+ },
373
+ {
374
+ "when": {
375
+ "auth": false,
376
+ "frontend": "react"
377
+ },
378
+ "remove": "resources/js/app.js"
379
+ },
380
+ {
381
+ "label": "Applying BoilerCraft Inertia pages",
382
+ "when": {
383
+ "auth": false,
384
+ "frontend": [
385
+ "vue",
386
+ "react"
387
+ ]
388
+ },
389
+ "copy": "overlays/inertia-common"
390
+ },
391
+ {
392
+ "when": {
393
+ "auth": false,
394
+ "frontend": "vue"
395
+ },
396
+ "copy": "overlays/inertia-vue"
397
+ },
398
+ {
399
+ "when": {
400
+ "auth": false,
401
+ "frontend": "react"
402
+ },
403
+ "copy": "overlays/inertia-react"
404
+ },
405
+ {
406
+ "when": {
407
+ "auth": false,
408
+ "frontend": [
409
+ "vue",
410
+ "react"
411
+ ]
412
+ },
413
+ "append": "routes/web.php",
414
+ "from": "snippets/web-routes-inertia.php"
415
+ },
416
+ {
417
+ "label": "Building frontend assets",
418
+ "when": {
419
+ "auth": false,
420
+ "frontend": [
421
+ "vue",
422
+ "react"
423
+ ]
424
+ },
425
+ "optional": true,
426
+ "run": [
427
+ "npm",
428
+ "run",
429
+ "build"
430
+ ]
431
+ }
432
+ ],
433
+ "vars": [
434
+ {
435
+ "name": "VITE_TAGS",
436
+ "when": {
437
+ "frontend": "vue"
438
+ },
439
+ "value": "@vite(['resources/css/app.css', 'resources/js/app.js'])"
440
+ },
441
+ {
442
+ "name": "VITE_TAGS",
443
+ "when": {
444
+ "frontend": "react"
445
+ },
446
+ "value": "@viteReactRefresh\n @vite(['resources/css/app.css', 'resources/js/app.jsx'])"
447
+ },
448
+ {
449
+ "name": "VITE_PLUGIN_VUE",
450
+ "when": {
451
+ "version": "<11"
452
+ },
453
+ "value": "@vitejs/plugin-vue@^4"
454
+ },
455
+ {
456
+ "name": "VITE_PLUGIN_VUE",
457
+ "when": {
458
+ "version": ">=11"
459
+ },
460
+ "value": "@vitejs/plugin-vue"
461
+ },
462
+ {
463
+ "name": "VITE_PLUGIN_REACT",
464
+ "when": {
465
+ "version": "<11"
466
+ },
467
+ "value": "@vitejs/plugin-react@^4"
468
+ },
469
+ {
470
+ "name": "VITE_PLUGIN_REACT",
471
+ "when": {
472
+ "version": ">=11"
473
+ },
474
+ "value": "@vitejs/plugin-react"
475
+ }
476
+ ]
477
+ }
@@ -0,0 +1,36 @@
1
+ import jwt from 'jsonwebtoken';
2
+ import bcrypt from 'bcryptjs';
3
+
4
+ // In-memory user store so the auth flow works out of the box.
5
+ // Replace with your database model (see src/lib/db.js).
6
+ const users = globalThis.__bcUsers || (globalThis.__bcUsers = []);
7
+
8
+ function secret() {
9
+ if (!process.env.JWT_SECRET) throw new Error('JWT_SECRET is not set (.env.local)');
10
+ return process.env.JWT_SECRET;
11
+ }
12
+
13
+ export function signToken(user) {
14
+ return jwt.sign({ id: user.id, name: user.name, email: user.email, role: user.role }, secret(), { expiresIn: '7d' });
15
+ }
16
+
17
+ export function verifyToken(token) {
18
+ return jwt.verify(token, secret());
19
+ }
20
+
21
+ export async function createUser({ name, email, password, role = 'user' }) {
22
+ if (users.some(u => u.email === email)) return null;
23
+ const user = { id: users.length + 1, name, email, role, password: await bcrypt.hash(password, 10) };
24
+ users.push(user);
25
+ return user;
26
+ }
27
+
28
+ export async function findUserByCredentials(email, password) {
29
+ const user = users.find(u => u.email === email);
30
+ if (!user || !(await bcrypt.compare(password, user.password))) return null;
31
+ return user;
32
+ }
33
+
34
+ export function publicUser({ password, ...rest }) {
35
+ return rest;
36
+ }
@@ -0,0 +1,11 @@
1
+ import { NextResponse } from 'next/server';
2
+ import { findUserByCredentials, signToken, publicUser } from '@/lib/auth';
3
+
4
+ export async function POST(request) {
5
+ const { email, password } = await request.json();
6
+ const user = await findUserByCredentials(email, password);
7
+ if (!user) {
8
+ return NextResponse.json({ success: false, error: 'Invalid credentials.' }, { status: 401 });
9
+ }
10
+ return NextResponse.json({ success: true, token: signToken(user), user: publicUser(user) });
11
+ }
@@ -0,0 +1,14 @@
1
+ import { NextResponse } from 'next/server';
2
+ import { createUser, signToken, publicUser } from '@/lib/auth';
3
+
4
+ export async function POST(request) {
5
+ const { name, email, password } = await request.json();
6
+ if (!name || !email || !password) {
7
+ return NextResponse.json({ success: false, error: 'Name, email and password are required.' }, { status: 400 });
8
+ }
9
+ const user = await createUser({ name, email, password });
10
+ if (!user) {
11
+ return NextResponse.json({ success: false, error: 'User already exists.' }, { status: 409 });
12
+ }
13
+ return NextResponse.json({ success: true, token: signToken(user), user: publicUser(user) }, { status: 201 });
14
+ }
@@ -0,0 +1,14 @@
1
+ import { findUserByCredentials, signToken, publicUser } from '@/lib/auth';
2
+
3
+ export default async function handler(req, res) {
4
+ if (req.method !== 'POST') {
5
+ res.setHeader('Allow', 'POST');
6
+ return res.status(405).json({ success: false, error: 'Method not allowed' });
7
+ }
8
+ const { email, password } = req.body || {};
9
+ const user = await findUserByCredentials(email, password);
10
+ if (!user) {
11
+ return res.status(401).json({ success: false, error: 'Invalid credentials.' });
12
+ }
13
+ return res.status(200).json({ success: true, token: signToken(user), user: publicUser(user) });
14
+ }
@@ -0,0 +1,17 @@
1
+ import { createUser, signToken, publicUser } from '@/lib/auth';
2
+
3
+ export default async function handler(req, res) {
4
+ if (req.method !== 'POST') {
5
+ res.setHeader('Allow', 'POST');
6
+ return res.status(405).json({ success: false, error: 'Method not allowed' });
7
+ }
8
+ const { name, email, password } = req.body || {};
9
+ if (!name || !email || !password) {
10
+ return res.status(400).json({ success: false, error: 'Name, email and password are required.' });
11
+ }
12
+ const user = await createUser({ name, email, password });
13
+ if (!user) {
14
+ return res.status(409).json({ success: false, error: 'User already exists.' });
15
+ }
16
+ return res.status(201).json({ success: true, token: signToken(user), user: publicUser(user) });
17
+ }
@@ -0,0 +1,3 @@
1
+ APP_NAME={{APP_TITLE_JS}}
2
+ JWT_SECRET=change-me
3
+ {{DB_ENV_EXAMPLE}}
@@ -0,0 +1,3 @@
1
+ APP_NAME={{APP_TITLE_JS}}
2
+ JWT_SECRET={{RANDOM_SECRET}}
3
+ {{DB_ENV}}
@@ -0,0 +1,12 @@
1
+ import mongoose from 'mongoose';
2
+
3
+ // Cached across hot reloads in development.
4
+ const cached = globalThis.__bcMongoose || (globalThis.__bcMongoose = { conn: null, promise: null });
5
+
6
+ export async function connectDB() {
7
+ if (cached.conn) return cached.conn;
8
+ const uri = process.env.MONGODB_URI || 'mongodb://127.0.0.1:27017/{{DB_NAME}}';
9
+ cached.promise ||= mongoose.connect(uri);
10
+ cached.conn = await cached.promise;
11
+ return cached.conn;
12
+ }
@@ -0,0 +1,17 @@
1
+ import sql from '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
+ export function connectDB() {
13
+ globalThis.__bcMssql ||= sql.connect(config);
14
+ return globalThis.__bcMssql;
15
+ }
16
+
17
+ export { sql };
@@ -0,0 +1,13 @@
1
+ import mysql from 'mysql2/promise';
2
+
3
+ const pool = globalThis.__bcMysql || (globalThis.__bcMysql = mysql.createPool({
4
+ host: process.env.DB_HOST || '127.0.0.1',
5
+ user: process.env.DB_USERNAME || 'root',
6
+ password: process.env.DB_PASSWORD || '',
7
+ database: process.env.DB_DATABASE || '{{DB_NAME}}',
8
+ port: parseInt(process.env.DB_PORT || '3306', 10)
9
+ }));
10
+
11
+ export function connectDB() {
12
+ return pool;
13
+ }
@@ -0,0 +1,10 @@
1
+ import { NextResponse } from 'next/server';
2
+
3
+ export async function GET() {
4
+ return NextResponse.json({
5
+ status: 'online',
6
+ stack: 'Next.js {{VERSION}} App Router',
7
+ database: '{{DB_TYPE}}',
8
+ appName: {{APP_TITLE_JS}}
9
+ });
10
+ }
@@ -0,0 +1,16 @@
1
+ import './globals.css';
2
+ import '../styles/theme.css';
3
+ import '../styles/vendor.js';
4
+
5
+ export const metadata = {
6
+ title: {{APP_TITLE_JS}},
7
+ description: {{APP_DESC_JS}}
8
+ };
9
+
10
+ export default function RootLayout({ children }) {
11
+ return (
12
+ <html lang="en" data-theme="{{COLOR_MODE}}">
13
+ <body>{children}</body>
14
+ </html>
15
+ );
16
+ }
@@ -0,0 +1,19 @@
1
+ export default function Home() {
2
+ return (
3
+ <div style={{ maxWidth: '900px', margin: '3rem auto', padding: '1rem', textAlign: 'center' }}>
4
+ <h1 style={{ fontSize: '2.5rem', fontWeight: 800 }}>{{APP_TITLE}}</h1>
5
+ <p style={{ color: 'var(--color-text-muted)' }}>{{APP_DESC}}</p>
6
+
7
+ <div style={{ marginTop: '2rem', padding: '1.5rem', background: 'var(--color-surface)', borderRadius: '1rem', textAlign: 'left', border: '1px solid var(--color-border)' }}>
8
+ <h3>Configured Architecture:</h3>
9
+ <ul>
10
+ <li><strong>Framework:</strong> Next.js {{VERSION}} (App Router)</li>
11
+ <li><strong>Database:</strong> {{DATABASE}}</li>
12
+ <li><strong>Styling:</strong> {{STYLING}}</li>
13
+ <li><strong>Theme:</strong> {{THEME}}</li>
14
+ </ul>
15
+ <p>Health API: <a href="/api/health" style={{ color: 'var(--color-primary)' }}>/api/health</a></p>
16
+ </div>
17
+ </div>
18
+ );
19
+ }
@@ -0,0 +1,7 @@
1
+ import '@/styles/globals.css';
2
+ import '@/styles/theme.css';
3
+ {{PAGES_VENDOR_CSS}}
4
+
5
+ export default function App({ Component, pageProps }) {
6
+ return <Component {...pageProps} />;
7
+ }