create-prisma-php-app 3.1.11 → 4.0.0-alpha.2

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 (34) hide show
  1. package/dist/bootstrap.php +10 -10
  2. package/dist/index.js +12 -8
  3. package/dist/settings/restart-websocket.bat +1 -1
  4. package/dist/settings/restart-websocket.ts +2 -9
  5. package/dist/src/{Lib/Websocket → Websocket}/ConnectionManager.php +1 -1
  6. package/dist/src/app/error.php +1 -1
  7. package/dist/src/app/index.php +1 -1
  8. package/dist/src/app/js/index.js +1 -1
  9. package/dist/src/app/layout.php +2 -2
  10. package/dist/{src/Lib/Websocket/websocket-server.php → websocket-server.php} +2 -7
  11. package/package.json +1 -1
  12. package/dist/src/Lib/AI/ChatGPTClient.php +0 -147
  13. package/dist/src/Lib/Auth/Auth.php +0 -544
  14. package/dist/src/Lib/Auth/AuthConfig.php +0 -89
  15. package/dist/src/Lib/CacheHandler.php +0 -121
  16. package/dist/src/Lib/ErrorHandler.php +0 -322
  17. package/dist/src/Lib/FileManager/UploadFile.php +0 -383
  18. package/dist/src/Lib/Headers/Boom.php +0 -208
  19. package/dist/src/Lib/IncludeTracker.php +0 -59
  20. package/dist/src/Lib/MainLayout.php +0 -215
  21. package/dist/src/Lib/Middleware/AuthMiddleware.php +0 -154
  22. package/dist/src/Lib/PHPMailer/Mailer.php +0 -169
  23. package/dist/src/Lib/PHPX/Exceptions/ComponentValidationException.php +0 -49
  24. package/dist/src/Lib/PHPX/IPHPX.php +0 -22
  25. package/dist/src/Lib/PHPX/PHPX.php +0 -173
  26. package/dist/src/Lib/PHPX/TemplateCompiler.php +0 -571
  27. package/dist/src/Lib/PHPX/TwMerge.php +0 -195
  28. package/dist/src/Lib/PHPX/TypeCoercer.php +0 -490
  29. package/dist/src/Lib/PartialRenderer.php +0 -40
  30. package/dist/src/Lib/PrismaPHPSettings.php +0 -181
  31. package/dist/src/Lib/Request.php +0 -476
  32. package/dist/src/Lib/Set.php +0 -102
  33. package/dist/src/Lib/StateManager.php +0 -127
  34. package/dist/src/Lib/Validator.php +0 -738
@@ -1,215 +0,0 @@
1
- <?php
2
-
3
- declare(strict_types=1);
4
-
5
- namespace Lib;
6
-
7
- use Lib\Set;
8
-
9
- class MainLayout
10
- {
11
- public static string $title = '';
12
- public static string $description = '';
13
- public static string $children = '';
14
- public static string $childLayoutChildren = '';
15
- public static string $html = '';
16
-
17
- /** @var Set<string>|null */
18
- private static ?Set $headScripts = null;
19
- /** @var Set<string>|null */
20
- private static ?Set $footerScripts = null;
21
- private static array $customMetadata = [];
22
-
23
- public static function init(): void
24
- {
25
- if (self::$headScripts === null) {
26
- self::$headScripts = new Set();
27
- }
28
- if (self::$footerScripts === null) {
29
- self::$footerScripts = new Set();
30
- }
31
- }
32
-
33
- /**
34
- * Adds one or more scripts to the head section if they are not already present.
35
- *
36
- * @param string ...$scripts The scripts to be added to the head section.
37
- * @return void
38
- */
39
- public static function addHeadScript(string ...$scripts): void
40
- {
41
- foreach ($scripts as $script) {
42
- self::$headScripts->add($script);
43
- }
44
- }
45
-
46
- /**
47
- * Adds one or more scripts to the footer section if they are not already present.
48
- *
49
- * @param string ...$scripts One or more scripts to be added to the footer.
50
- * @return void
51
- */
52
- public static function addFooterScript(string ...$scripts): void
53
- {
54
- $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
55
- $callerClass = $trace[1]['class'] ?? 'Unknown';
56
-
57
- foreach ($scripts as $script) {
58
- if (strpos($script, '<script') !== false) {
59
- $taggedScript = "<!-- class:" . $callerClass . " -->\n" . $script;
60
- self::$footerScripts->add($taggedScript);
61
- } else {
62
- self::$footerScripts->add($script);
63
- }
64
- }
65
- }
66
-
67
- /**
68
- * Generates all the head scripts with dynamic attributes.
69
- *
70
- * This method iterates over all registered head scripts and adds a custom dynamic attribute
71
- * based on the tag type (script, link, or style).
72
- *
73
- * @return string The concatenated head scripts with dynamic attributes.
74
- */
75
- public static function outputHeadScripts(): string
76
- {
77
- $headScriptsArray = self::$headScripts->values();
78
- $headScriptsWithAttributes = array_map(function ($tag) {
79
- if (strpos($tag, '<script') !== false) {
80
- return str_replace('<script', '<script pp-dynamic-script="81D7D"', $tag);
81
- } elseif (strpos($tag, '<link') !== false) {
82
- return str_replace('<link', '<link pp-dynamic-link="81D7D"', $tag);
83
- } elseif (strpos($tag, '<style') !== false) {
84
- return str_replace('<style', '<style pp-dynamic-style="81D7D"', $tag);
85
- }
86
- return $tag;
87
- }, $headScriptsArray);
88
-
89
- return implode("\n", $headScriptsWithAttributes);
90
- }
91
-
92
- /**
93
- * Generates all the footer scripts.
94
- *
95
- * @return string The concatenated footer scripts.
96
- */
97
- public static function outputFooterScripts(): string
98
- {
99
- $processed = [];
100
-
101
- foreach (self::$footerScripts->values() as $script) {
102
- if (preg_match('/<!-- class:([^\s]+) -->/', $script, $matches)) {
103
- $rawClassName = $matches[1];
104
- $script = preg_replace('/<!-- class:[^\s]+ -->\s*/', '', $script, 1);
105
-
106
- if (str_starts_with(trim($script), '<script')) {
107
- $script = preg_replace_callback(
108
- '/<script\b([^>]*)>/i',
109
- function ($m) use ($rawClassName) {
110
- $attrs = $m[1];
111
- $encodedClass = 's' . base_convert(sprintf('%u', crc32($rawClassName)), 10, 36);
112
-
113
- if (!str_contains($attrs, 'pp-sync-script=')) {
114
- $attrs .= " pp-sync-script=\"{$encodedClass}\"";
115
- }
116
-
117
- if (!preg_match('/\btype\s*=\s*(["\'])[^\1]*\1|\btype\s*=\s*\S+/i', $attrs)) {
118
- $attrs .= ' type="text/php"';
119
- }
120
-
121
- return "<script{$attrs}>";
122
- },
123
- $script,
124
- 1
125
- );
126
- }
127
- }
128
-
129
- $processed[] = $script;
130
- }
131
-
132
- return implode("\n", $processed);
133
- }
134
-
135
- /**
136
- * Clears all head scripts.
137
- *
138
- * @return void
139
- */
140
- public static function clearHeadScripts(): void
141
- {
142
- self::$headScripts->clear();
143
- }
144
-
145
- /**
146
- * Clears all footer scripts.
147
- *
148
- * @return void
149
- */
150
- public static function clearFooterScripts(): void
151
- {
152
- self::$footerScripts->clear();
153
- }
154
-
155
- /**
156
- * Adds custom metadata.
157
- *
158
- * @param string $key The metadata key.
159
- * @param string $value The metadata value.
160
- * @return void
161
- */
162
- public static function addCustomMetadata(string $key, string $value): void
163
- {
164
- self::$customMetadata[$key] = $value;
165
- }
166
-
167
- /**
168
- * Retrieves custom metadata by key.
169
- *
170
- * @param string $key The metadata key.
171
- * @return string|null The metadata value or null if the key does not exist.
172
- */
173
- public static function getCustomMetadata(string $key): ?string
174
- {
175
- return self::$customMetadata[$key] ?? null;
176
- }
177
-
178
- /**
179
- * Generates the metadata as meta tags for the head section.
180
- *
181
- * This method includes default tags for charset and viewport, a title tag,
182
- * and additional metadata. If a description is not already set in the custom metadata,
183
- * it will use the class's description property.
184
- *
185
- * @return string The concatenated meta tags.
186
- */
187
- public static function outputMetadata(): string
188
- {
189
- $metadataContent = [
190
- '<meta charset="UTF-8">',
191
- '<meta name="viewport" content="width=device-width, initial-scale=1.0">',
192
- ];
193
- $metadataContent[] = '<title>' . htmlspecialchars(self::$title) . '</title>';
194
-
195
- if (!isset(self::$customMetadata['description'])) {
196
- self::$customMetadata['description'] = self::$description;
197
- }
198
-
199
- foreach (self::$customMetadata as $key => $value) {
200
- $metadataContent[] = '<meta name="' . htmlspecialchars($key) . '" content="' . htmlspecialchars($value) . '" pp-dynamic-meta="81D7D">';
201
- }
202
-
203
- return implode("\n", $metadataContent);
204
- }
205
-
206
- /**
207
- * Clears all custom metadata.
208
- *
209
- * @return void
210
- */
211
- public static function clearCustomMetadata(): void
212
- {
213
- self::$customMetadata = [];
214
- }
215
- }
@@ -1,154 +0,0 @@
1
- <?php
2
-
3
- declare(strict_types=1);
4
-
5
- namespace Lib\Middleware;
6
-
7
- use Lib\Auth\Auth;
8
- use Lib\Auth\AuthConfig;
9
- use Lib\Request;
10
-
11
- final class AuthMiddleware
12
- {
13
- public static function handle($requestPathname)
14
- {
15
- if (AuthConfig::IS_ALL_ROUTES_PRIVATE) {
16
- $isLogin = Auth::getInstance()->isAuthenticated();
17
- $isApiAuthRoute = stripos($requestPathname, AuthConfig::API_AUTH_PREFIX) === 0;
18
- $isPublicRoute = self::matches($requestPathname, AuthConfig::$publicRoutes);
19
- $isAuthRoute = self::matches($requestPathname, AuthConfig::$authRoutes);
20
-
21
- // Check if the user is authenticated and refresh the token if necessary
22
- if (AuthConfig::IS_TOKEN_AUTO_REFRESH) {
23
- $auth = Auth::getInstance();
24
- if (isset($_COOKIE[Auth::$cookieName])) {
25
- $jwt = $_COOKIE[Auth::$cookieName];
26
- $jwt = $auth->refreshToken($jwt);
27
- }
28
- }
29
-
30
- // Skip the middleware if the route is api auth route
31
- if ($isApiAuthRoute) {
32
- return;
33
- }
34
-
35
- // Redirect to the default sign in route if the user is already authenticated
36
- if ($isAuthRoute) {
37
- if ($isLogin) {
38
- Request::redirect(AuthConfig::DEFAULT_SIGNIN_REDIRECT);
39
- }
40
- return;
41
- }
42
-
43
- // Redirect to the default home route if the user is already authenticated
44
- if (!$isLogin && !$isPublicRoute) {
45
- Request::redirect("/signin");
46
- }
47
- } else {
48
- // Skip the middleware if the route is public
49
- if (!self::matches($requestPathname, AuthConfig::$privateRoutes)) {
50
- return;
51
- }
52
-
53
- // Check if the user is authorized to access the route or redirect to login
54
- if (!self::isAuthorized()) {
55
- Request::redirect('/signin');
56
- }
57
- }
58
-
59
- // Check if the user has the required role to access the route or redirect to denied
60
- if (AuthConfig::IS_ROLE_BASE) {
61
- $matchValue = self::hasRequiredRole($requestPathname);
62
- if ($matchValue === "Route not in array") {
63
- // echo "No validation needed for this route.";
64
- } elseif ($matchValue === "Match") {
65
- // echo "You are authorized to access this route";
66
- } elseif ($matchValue === "Role mismatch") {
67
- // echo "You are not authorized to access this route";
68
- Request::redirect('/denied');
69
- } else {
70
- // echo "Unexpected error encountered";
71
- }
72
- }
73
- }
74
-
75
- protected static function matches(string $requestPathname, array $routes): bool
76
- {
77
- foreach ($routes ?? [] as $pattern) {
78
- $getUriRegexValue = self::getUriRegex($pattern, $requestPathname);
79
- if ($getUriRegexValue) {
80
- return true;
81
- }
82
- }
83
- return false;
84
- }
85
-
86
- protected static function isAuthorized(): bool
87
- {
88
- $auth = Auth::getInstance();
89
- if (!isset($_COOKIE[Auth::$cookieName])) {
90
- unset($_SESSION[Auth::PAYLOAD_SESSION_KEY]);
91
- return false;
92
- }
93
-
94
- $jwt = $_COOKIE[Auth::$cookieName];
95
-
96
- if (AuthConfig::IS_TOKEN_AUTO_REFRESH) {
97
- $jwt = $auth->refreshToken($jwt);
98
- $verifyToken = $auth->verifyToken($jwt);
99
- }
100
-
101
- $verifyToken = $auth->verifyToken($jwt);
102
- if ($verifyToken === false) {
103
- return false;
104
- }
105
-
106
- // Access the PAYLOAD_NAME property using the -> operator instead of array syntax
107
- if (isset($verifyToken->{Auth::PAYLOAD_NAME})) {
108
- return true;
109
- }
110
-
111
- return false;
112
- }
113
-
114
- protected static function hasRequiredRole(string $requestPathname): string
115
- {
116
- $auth = Auth::getInstance();
117
- $roleBasedRoutes = AuthConfig::$roleBasedRoutes ?? [];
118
-
119
- // Normalize the request path for matching
120
- $requestPathnameValue = trim($requestPathname, '/');
121
-
122
- foreach ($roleBasedRoutes as $pattern => $data) {
123
- $patternValue = trim($pattern, '/');
124
- if ($patternValue === $requestPathnameValue) {
125
- // Route is found in array, check permissions
126
- $userRole = Auth::ROLE_NAME ? $auth->getPayload()[Auth::ROLE_NAME] : $auth->getPayload();
127
- return ($userRole !== null && AuthConfig::checkAuthRole($userRole, $data[AuthConfig::ROLE_IDENTIFIER]))
128
- ? "Match"
129
- : "Role mismatch";
130
- }
131
- }
132
-
133
- // Route not found in role-based routes array
134
- return "Route not in array";
135
- }
136
-
137
- private static function getUriRegex(string $pattern, string $requestPathname): int|bool
138
- {
139
- // Normalize both the pattern and the request path
140
- $pattern = strtolower(trim($pattern, '/'));
141
- $requestPathname = strtolower(trim($requestPathname, '/'));
142
-
143
- // Handle the case where the requestPathname is empty, which means home or "/"
144
- if (empty($requestPathname)) {
145
- $requestPathname = '/';
146
- } else {
147
- $requestPathname = "/$requestPathname";
148
- }
149
-
150
- // Construct the regex pattern
151
- $regex = "#^/?" . preg_quote("/$pattern", '#') . "(/.*)?$#";
152
- return preg_match($regex, $requestPathname);
153
- }
154
- }
@@ -1,169 +0,0 @@
1
- <?php
2
-
3
- declare(strict_types=1);
4
-
5
- namespace Lib\PHPMailer;
6
-
7
- use PHPMailer\PHPMailer\PHPMailer;
8
- use PHPMailer\PHPMailer\Exception;
9
- use Lib\Validator;
10
-
11
- class Mailer
12
- {
13
- private PHPMailer $mail;
14
-
15
- public function __construct()
16
- {
17
- $this->mail = new PHPMailer(true);
18
- $this->mail->CharSet = 'UTF-8';
19
- $this->setup();
20
- }
21
-
22
- private function setup(): void
23
- {
24
- $this->mail->isSMTP();
25
- $this->mail->SMTPDebug = 0;
26
- $this->mail->Host = $_ENV['SMTP_HOST'];
27
- $this->mail->SMTPAuth = true;
28
- $this->mail->Username = $_ENV['SMTP_USERNAME'];
29
- $this->mail->Password = $_ENV['SMTP_PASSWORD'];
30
- $this->mail->SMTPSecure = $_ENV['SMTP_ENCRYPTION'];
31
- $this->mail->Port = (int) $_ENV['SMTP_PORT'];
32
- $this->mail->setFrom($_ENV['MAIL_FROM'], $_ENV['MAIL_FROM_NAME']);
33
- }
34
-
35
- /**
36
- * Send an email.
37
- *
38
- * @param string $to The recipient's email address.
39
- * @param string $subject The subject of the email.
40
- * @param string $body The HTML body of the email.
41
- * @param array $options (optional) Additional email options like name, altBody, CC, BCC, and attachments.
42
- * - attachments: A string or an array of file paths, or an array of associative arrays with keys 'path' and 'name'.
43
- *
44
- * @return bool Returns true if the email is sent successfully, false otherwise.
45
- *
46
- * @throws Exception Throws an exception if the email could not be sent.
47
- */
48
- public function send(string $to, string $subject, string $body, array $options = []): bool
49
- {
50
- try {
51
- // Validate and sanitize inputs
52
- $to = Validator::email($to);
53
- if (!$to) {
54
- throw new Exception('Invalid email address for the main recipient');
55
- }
56
-
57
- $subject = Validator::string($subject);
58
- $body = Validator::html($body);
59
- $altBody = $this->convertToPlainText($body);
60
-
61
- $name = $options['name'] ?? '';
62
- $addCC = $options['addCC'] ?? [];
63
- $addBCC = $options['addBCC'] ?? [];
64
- $attachments = $options['attachments'] ?? [];
65
-
66
- $name = Validator::string($name);
67
-
68
- // Handle CC recipients
69
- $this->handleRecipients($addCC, 'CC');
70
- // Handle BCC recipients
71
- $this->handleRecipients($addBCC, 'BCC');
72
- // Handle file attachments if provided
73
- if (!empty($attachments)) {
74
- $this->handleAttachments($attachments);
75
- }
76
-
77
- // Set the main recipient and other email properties
78
- $this->mail->addAddress($to, $name);
79
- $this->mail->isHTML(true);
80
- $this->mail->Subject = $subject;
81
- $this->mail->Body = $body;
82
- $this->mail->AltBody = $altBody;
83
-
84
- // Send the email
85
- return $this->mail->send();
86
- } catch (Exception $e) {
87
- throw new Exception($e->getMessage());
88
- }
89
- }
90
-
91
- /**
92
- * Handle adding CC or BCC recipients.
93
- *
94
- * @param string|array $recipients Email addresses to add.
95
- * @param string $type Type of recipient ('CC' or 'BCC').
96
- *
97
- * @throws Exception Throws an exception if any email address is invalid.
98
- */
99
- private function handleRecipients(string|array $recipients, string $type): void
100
- {
101
- if (!empty($recipients)) {
102
- $method = $type === 'CC' ? 'addCC' : 'addBCC';
103
-
104
- if (is_array($recipients)) {
105
- foreach ($recipients as $recipient) {
106
- $recipient = Validator::email($recipient);
107
- if ($recipient) {
108
- $this->mail->{$method}($recipient);
109
- } else {
110
- throw new Exception("Invalid email address in $type");
111
- }
112
- }
113
- } else {
114
- $recipient = Validator::email($recipients);
115
- if ($recipient) {
116
- $this->mail->{$method}($recipient);
117
- } else {
118
- throw new Exception("Invalid email address in $type");
119
- }
120
- }
121
- }
122
- }
123
-
124
- /**
125
- * Handle adding file attachments.
126
- *
127
- * @param string|array $attachments File path(s) to attach.
128
- * You can pass a string for a single file or an array of file paths.
129
- * Alternatively, each attachment can be an array with keys 'path' and 'name' for custom naming.
130
- *
131
- * @throws Exception Throws an exception if any attachment file is not found.
132
- */
133
- private function handleAttachments(string|array $attachments): void
134
- {
135
- if (is_array($attachments)) {
136
- foreach ($attachments as $attachment) {
137
- if (is_array($attachment)) {
138
- $file = $attachment['path'] ?? null;
139
- $name = $attachment['name'] ?? '';
140
- if (!$file || !file_exists($file)) {
141
- throw new Exception("Attachment file does not exist: " . ($file ?? 'unknown'));
142
- }
143
- $this->mail->addAttachment($file, $name);
144
- } else {
145
- if (!file_exists($attachment)) {
146
- throw new Exception("Attachment file does not exist: $attachment");
147
- }
148
- $this->mail->addAttachment($attachment);
149
- }
150
- }
151
- } else {
152
- if (!file_exists($attachments)) {
153
- throw new Exception("Attachment file does not exist: $attachments");
154
- }
155
- $this->mail->addAttachment($attachments);
156
- }
157
- }
158
-
159
- /**
160
- * Convert HTML content to plain text.
161
- *
162
- * @param string $html The HTML content to convert.
163
- * @return string The plain text content.
164
- */
165
- private function convertToPlainText(string $html): string
166
- {
167
- return strip_tags(str_replace(['<br>', '<br/>', '<br />', '</p>'], "\n", $html));
168
- }
169
- }
@@ -1,49 +0,0 @@
1
- <?php
2
-
3
- namespace Lib\PHPX\Exceptions;
4
-
5
- use RuntimeException;
6
-
7
- class ComponentValidationException extends RuntimeException
8
- {
9
- private string $propName;
10
- private string $componentName;
11
- private array $availableProps;
12
-
13
- public function __construct(
14
- string $propName,
15
- string $componentName,
16
- array $availableProps,
17
- string $context = ''
18
- ) {
19
- $this->propName = $propName;
20
- $this->componentName = $componentName;
21
- $this->availableProps = $availableProps;
22
-
23
- $availableList = implode(', ', $availableProps);
24
-
25
- $message = "Invalid prop '{$propName}' for component '{$componentName}'.\n";
26
- $message .= "Available props: {$availableList}";
27
-
28
- if ($context) {
29
- $message .= "\n{$context}";
30
- }
31
-
32
- parent::__construct($message);
33
- }
34
-
35
- public function getPropName(): string
36
- {
37
- return $this->propName;
38
- }
39
-
40
- public function getComponentName(): string
41
- {
42
- return $this->componentName;
43
- }
44
-
45
- public function getAvailableProps(): array
46
- {
47
- return $this->availableProps;
48
- }
49
- }
@@ -1,22 +0,0 @@
1
- <?php
2
-
3
- declare(strict_types=1);
4
-
5
- namespace Lib\PHPX;
6
-
7
- interface IPHPX
8
- {
9
- /**
10
- * Constructor to initialize the component with the given properties.
11
- *
12
- * @param array<string, mixed> $props Optional properties to customize the component.
13
- */
14
- public function __construct(array $props = []);
15
-
16
- /**
17
- * Renders the component with the given properties and children.
18
- *
19
- * @return string The rendered HTML content.
20
- */
21
- public function render(): string;
22
- }