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,30 @@
1
+ <?php
2
+ namespace App\Config;
3
+
4
+ class Env {
5
+ public static function load(string $path): void {
6
+ if (!file_exists($path)) {
7
+ return;
8
+ }
9
+
10
+ $lines = file($path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
11
+ foreach ($lines as $line) {
12
+ $line = trim($line);
13
+ if (empty($line) || str_starts_with($line, '#')) {
14
+ continue;
15
+ }
16
+
17
+ if (str_contains($line, '=')) {
18
+ [$key, $value] = explode('=', $line, 2);
19
+ $key = trim($key);
20
+ $value = trim($value, " \t\n\r\0\x0B\"'");
21
+
22
+ if (!array_key_exists($key, $_SERVER) && !array_key_exists($key, $_ENV)) {
23
+ putenv("{$key}={$value}");
24
+ $_ENV[$key] = $value;
25
+ $_SERVER[$key] = $value;
26
+ }
27
+ }
28
+ }
29
+ }
30
+ }
@@ -0,0 +1,53 @@
1
+ <?php
2
+ namespace App\Config;
3
+
4
+ class Middleware {
5
+ /**
6
+ * Authentication Guard (Blocks guest users)
7
+ */
8
+ public static function auth(): void {
9
+ if (!Auth::check()) {
10
+ if (self::isAjax()) {
11
+ http_response_code(401);
12
+ header('Content-Type: application/json');
13
+ echo json_encode(['success' => false, 'error' => 'Unauthorized. Please login.']);
14
+ exit;
15
+ }
16
+ header('Location: /login');
17
+ exit;
18
+ }
19
+ }
20
+
21
+ /**
22
+ * Guest Guard (Redirects logged-in users away from login/register)
23
+ */
24
+ public static function guest(): void {
25
+ if (Auth::check()) {
26
+ header('Location: /dashboard');
27
+ exit;
28
+ }
29
+ }
30
+
31
+ /**
32
+ * Role-based Authorization Guard (e.g. 'admin', 'moderator')
33
+ */
34
+ public static function role(string|array $roles): void {
35
+ self::auth(); // Must be logged in first
36
+
37
+ if (!Auth::hasRole($roles)) {
38
+ if (self::isAjax()) {
39
+ http_response_code(403);
40
+ header('Content-Type: application/json');
41
+ echo json_encode(['success' => false, 'error' => 'Forbidden. You lack sufficient permissions.']);
42
+ exit;
43
+ }
44
+ http_response_code(403);
45
+ die("<h1>403 Forbidden</h1><p>You do not have permission to access this area.</p>");
46
+ }
47
+ }
48
+
49
+ private static function isAjax(): bool {
50
+ return (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest')
51
+ || (isset($_SERVER['HTTP_ACCEPT']) && str_contains($_SERVER['HTTP_ACCEPT'], 'application/json'));
52
+ }
53
+ }
@@ -0,0 +1,109 @@
1
+ <?php
2
+ namespace App\Config;
3
+
4
+ class QueryBuilder {
5
+ protected string $table = '';
6
+ protected array $fields = ['*'];
7
+ protected array $wheres = [];
8
+ protected array $bindings = [];
9
+ protected string $orderBy = '';
10
+ protected ?int $limitNum = null;
11
+
12
+ public static function table(string $table): self {
13
+ $qb = new self();
14
+ $qb->table = $table;
15
+ return $qb;
16
+ }
17
+
18
+ public function select(array|string $fields = ['*']): self {
19
+ $this->fields = is_array($fields) ? $fields : func_get_args();
20
+ return $this;
21
+ }
22
+
23
+ public function where(string $column, mixed $operatorOrValue, mixed $value = null): self {
24
+ if ($value === null) {
25
+ $value = $operatorOrValue;
26
+ $operator = '=';
27
+ } else {
28
+ $operator = $operatorOrValue;
29
+ }
30
+
31
+ $paramKey = ":p_" . count($this->bindings);
32
+ $this->wheres[] = "{$column} {$operator} {$paramKey}";
33
+ $this->bindings[$paramKey] = $value;
34
+ return $this;
35
+ }
36
+
37
+ public function orderBy(string $column, string $direction = 'ASC'): self {
38
+ $this->orderBy = "ORDER BY {$column} " . strtoupper($direction);
39
+ return $this;
40
+ }
41
+
42
+ public function limit(int $limit): self {
43
+ $this->limitNum = $limit;
44
+ return $this;
45
+ }
46
+
47
+ public function get(): array {
48
+ $sql = "SELECT " . implode(', ', $this->fields) . " FROM {$this->table}";
49
+ if (!empty($this->wheres)) {
50
+ $sql .= " WHERE " . implode(' AND ', $this->wheres);
51
+ }
52
+ if (!empty($this->orderBy)) {
53
+ $sql .= " {$this->orderBy}";
54
+ }
55
+ if ($this->limitNum !== null) {
56
+ $sql .= " LIMIT {$this->limitNum}";
57
+ }
58
+
59
+ return Database::query($sql, $this->bindings);
60
+ }
61
+
62
+ public function first(): ?array {
63
+ $this->limit(1);
64
+ $results = $this->get();
65
+ return $results[0] ?? null;
66
+ }
67
+
68
+ public function insert(array $data): bool {
69
+ $columns = implode(', ', array_keys($data));
70
+ $placeholders = [];
71
+ $params = [];
72
+
73
+ foreach ($data as $k => $v) {
74
+ $param = ":ins_{$k}";
75
+ $placeholders[] = $param;
76
+ $params[$param] = $v;
77
+ }
78
+
79
+ $sql = "INSERT INTO {$this->table} ({$columns}) VALUES (" . implode(', ', $placeholders) . ")";
80
+ return Database::execute($sql, $params);
81
+ }
82
+
83
+ public function update(array $data): bool {
84
+ $sets = [];
85
+ $params = [];
86
+
87
+ foreach ($data as $k => $v) {
88
+ $param = ":upd_{$k}";
89
+ $sets[] = "{$k} = {$param}";
90
+ $params[$param] = $v;
91
+ }
92
+
93
+ $sql = "UPDATE {$this->table} SET " . implode(', ', $sets);
94
+ if (!empty($this->wheres)) {
95
+ $sql .= " WHERE " . implode(' AND ', $this->wheres);
96
+ $params = array_merge($params, $this->bindings);
97
+ }
98
+
99
+ return Database::execute($sql, $params);
100
+ }
101
+
102
+ public function delete(): bool {
103
+ $sql = "DELETE FROM {$this->table}";
104
+ if (!empty($this->wheres)) {
105
+ $sql .= " WHERE " . implode(' AND ', $this->wheres);
106
+ }
107
+ return Database::execute($sql, $this->bindings);
108
+ }
109
+ }
@@ -0,0 +1,33 @@
1
+ <?php
2
+ namespace App\Config;
3
+
4
+ class Router {
5
+ private array $routes = [];
6
+
7
+ public function get(string $path, callable|array $handler): void {
8
+ $this->routes['GET'][$path] = $handler;
9
+ }
10
+
11
+ public function post(string $path, callable|array $handler): void {
12
+ $this->routes['POST'][$path] = $handler;
13
+ }
14
+
15
+ public function dispatch(): void {
16
+ $method = $_SERVER['REQUEST_METHOD'];
17
+ $uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
18
+
19
+ if (isset($this->routes[$method][$uri])) {
20
+ $handler = $this->routes[$method][$uri];
21
+ if (is_callable($handler)) {
22
+ call_user_func($handler);
23
+ } elseif (is_array($handler)) {
24
+ [$class, $action] = $handler;
25
+ $controller = new $class();
26
+ $controller->$action();
27
+ }
28
+ } else {
29
+ http_response_code(404);
30
+ require __DIR__ . '/../app/Views/404.php';
31
+ }
32
+ }
33
+ }
@@ -0,0 +1,57 @@
1
+ <?php
2
+ // Autoloader
3
+ spl_autoload_register(function ($class) {
4
+ $prefix = 'App\\';
5
+ $base_dir = __DIR__ . '/../app/';
6
+
7
+ $len = strlen($prefix);
8
+ if (strncmp($prefix, $class, $len) !== 0) {
9
+ return;
10
+ }
11
+
12
+ $relative_class = substr($class, $len);
13
+ if (strpos($relative_class, 'Config\\') === 0) {
14
+ $file = __DIR__ . '/../' . str_replace('\\', '/', $relative_class) . '.php';
15
+ } else {
16
+ $file = $base_dir . str_replace('\\', '/', $relative_class) . '.php';
17
+ }
18
+
19
+ if (file_exists($file)) {
20
+ require $file;
21
+ }
22
+ });
23
+
24
+ use App\Config\Env;
25
+ use App\Config\Router;
26
+ use App\Config\Middleware;
27
+ use App\Controllers\HomeController;
28
+ use App\Controllers\AuthController;
29
+
30
+ Env::load(__DIR__ . '/../.env');
31
+
32
+ $router = new Router();
33
+
34
+ // Public Routes
35
+ $router->get('/', [HomeController::class, 'index']);
36
+ $router->get('/login', [AuthController::class, 'showLogin']);
37
+ $router->get('/register', [AuthController::class, 'showRegister']);
38
+ $router->get('/logout', [AuthController::class, 'logout']);
39
+
40
+ // AJAX Auth Endpoints
41
+ $router->post('/api/login', [AuthController::class, 'login']);
42
+ $router->post('/api/register', [AuthController::class, 'register']);
43
+ $router->get('/api/health', [HomeController::class, 'apiHealth']);
44
+
45
+ // Protected Routes (Guarded by Middleware)
46
+ $router->get('/dashboard', function() {
47
+ Middleware::auth(); // Protect route: must be logged in
48
+ require __DIR__ . '/../app/Views/dashboard.php';
49
+ });
50
+
51
+ $router->get('/admin', function() {
52
+ Middleware::role('admin'); // Protect route: only admin role allowed
53
+ require __DIR__ . '/../app/Views/dashboard.php';
54
+ });
55
+
56
+ // Dispatch request
57
+ $router->dispatch();