create-prisma-php-app 1.20.3 → 1.20.500

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 (31) hide show
  1. package/dist/bootstrap.php +38 -1
  2. package/dist/index.js +1109 -1
  3. package/dist/prisma-php.js +63 -1
  4. package/dist/settings/public-functions.php +26 -0
  5. package/dist/settings/request-methods.php +1 -0
  6. package/dist/settings/start-dev.js +132 -0
  7. package/dist/settings/swagger-setup.js +54 -0
  8. package/dist/src/Lib/FileManager/UploadFile.php +23 -19
  9. package/dist/src/app/swagger-docs/apis/pphp-swagger.json +259 -0
  10. package/dist/src/app/swagger-docs/apis/users.js +180 -0
  11. package/dist/src/app/swagger-docs/dist/favicon-16x16.png +0 -0
  12. package/dist/src/app/swagger-docs/dist/favicon-32x32.png +0 -0
  13. package/dist/src/app/swagger-docs/dist/index.css +16 -0
  14. package/dist/src/app/swagger-docs/dist/index.html +19 -0
  15. package/dist/src/app/swagger-docs/dist/oauth2-redirect.html +79 -0
  16. package/dist/src/app/swagger-docs/dist/swagger-initializer.js +36 -0
  17. package/dist/src/app/swagger-docs/dist/swagger-ui-bundle.js +2 -0
  18. package/dist/src/app/swagger-docs/dist/swagger-ui-bundle.js.map +1 -0
  19. package/dist/src/app/swagger-docs/dist/swagger-ui-es-bundle-core.js +3 -0
  20. package/dist/src/app/swagger-docs/dist/swagger-ui-es-bundle-core.js.map +1 -0
  21. package/dist/src/app/swagger-docs/dist/swagger-ui-es-bundle.js +2 -0
  22. package/dist/src/app/swagger-docs/dist/swagger-ui-es-bundle.js.map +1 -0
  23. package/dist/src/app/swagger-docs/dist/swagger-ui-standalone-preset.js +2 -0
  24. package/dist/src/app/swagger-docs/dist/swagger-ui-standalone-preset.js.map +1 -0
  25. package/dist/src/app/swagger-docs/dist/swagger-ui.css +3 -0
  26. package/dist/src/app/swagger-docs/dist/swagger-ui.css.map +1 -0
  27. package/dist/src/app/swagger-docs/dist/swagger-ui.js +2 -0
  28. package/dist/src/app/swagger-docs/dist/swagger-ui.js.map +1 -0
  29. package/dist/src/app/swagger-docs/index.php +16 -0
  30. package/dist/src/app/swagger-docs-layout.php +17 -0
  31. package/package.json +1 -1
@@ -1,5 +1,66 @@
1
1
  #!/usr/bin/env node
2
- import chalk from"chalk";import{spawn}from"child_process";import fs from"fs";import path from"path";import prompts from"prompts";import{fileURLToPath}from"url";const __filename=fileURLToPath(import.meta.url),__dirname=path.dirname(__filename),args=process.argv.slice(2),readJsonFile=e=>{const t=fs.readFileSync(e,"utf8");return JSON.parse(t)},executeCommand=(e,t=[],o={})=>new Promise(((r,a)=>{const s=spawn(e,t,Object.assign({stdio:"inherit",shell:!0},o));s.on("error",(e=>{a(e)})),s.on("close",(e=>{0===e?r():a(new Error(`Process exited with code ${e}`))}))}));async function getAnswer(){const e=[{type:"toggle",name:"shouldProceed",message:`This command will update the ${chalk.blue("create-prisma-php-app")} package and overwrite all default files. ${chalk.blue("Do you want to proceed")}?`,initial:!1,active:"Yes",inactive:"No"}],t=await prompts(e,{onCancel:()=>{process.exit(0)}});return 0===Object.keys(t).length?null:t}const commandsToExecute={generateClass:"npx php generate class",update:"npx php update project"};
2
+ import chalk from "chalk";
3
+ import { spawn } from "child_process";
4
+ import fs from "fs";
5
+ import path from "path";
6
+ import prompts from "prompts";
7
+ import { fileURLToPath } from "url";
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = path.dirname(__filename);
10
+ const args = process.argv.slice(2);
11
+ const readJsonFile = (filePath) => {
12
+ const jsonData = fs.readFileSync(filePath, "utf8");
13
+ return JSON.parse(jsonData);
14
+ };
15
+ const executeCommand = (command, args = [], options = {}) => {
16
+ return new Promise((resolve, reject) => {
17
+ const process = spawn(
18
+ command,
19
+ args,
20
+ Object.assign({ stdio: "inherit", shell: true }, options)
21
+ );
22
+ process.on("error", (error) => {
23
+ console.error(`Execution error: ${error.message}`);
24
+ reject(error);
25
+ });
26
+ process.on("close", (code) => {
27
+ if (code === 0) {
28
+ resolve();
29
+ } else {
30
+ reject(new Error(`Process exited with code ${code}`));
31
+ }
32
+ });
33
+ });
34
+ };
35
+ async function getAnswer() {
36
+ const questions = [
37
+ {
38
+ type: "toggle",
39
+ name: "shouldProceed",
40
+ message: `This command will update the ${chalk.blue(
41
+ "create-prisma-php-app"
42
+ )} package and overwrite all default files. ${chalk.blue(
43
+ "Do you want to proceed"
44
+ )}?`,
45
+ initial: false,
46
+ active: "Yes",
47
+ inactive: "No",
48
+ },
49
+ ];
50
+ const onCancel = () => {
51
+ console.log(chalk.red("Operation cancelled by the user."));
52
+ process.exit(0);
53
+ };
54
+ const response = await prompts(questions, { onCancel });
55
+ if (Object.keys(response).length === 0) {
56
+ return null;
57
+ }
58
+ return response;
59
+ }
60
+ const commandsToExecute = {
61
+ generateClass: "npx php generate class",
62
+ update: "npx php update project",
63
+ };
3
64
  const main = async () => {
4
65
  if (args.length === 0) {
5
66
  console.log("No command provided.");
@@ -33,6 +94,7 @@ const main = async () => {
33
94
  const localSettings = readJsonFile(configPath);
34
95
  const commandArgs = [localSettings.projectName];
35
96
  if (localSettings.backendOnly) commandArgs.push("--backend-only");
97
+ if (localSettings.swaggerDocs) commandArgs.push("--swagger-docs");
36
98
  if (localSettings.tailwindcss) commandArgs.push("--tailwindcss");
37
99
  if (localSettings.websocket) commandArgs.push("--websocket");
38
100
  if (localSettings.prisma) commandArgs.push("--prisma");
@@ -18,6 +18,11 @@ function redirect(string $url, bool $replace = true, int $responseCode = 0)
18
18
  exit;
19
19
  }
20
20
 
21
+ /**
22
+ * Checks if the request is an AJAX request.
23
+ *
24
+ * @return bool True if the request is an AJAX request, false otherwise.
25
+ */
21
26
  function isAjaxRequest()
22
27
  {
23
28
  $isAjax = false;
@@ -52,6 +57,11 @@ function isAjaxRequest()
52
57
  return $isAjax;
53
58
  }
54
59
 
60
+ /**
61
+ * Checks if the request is a wire request.
62
+ *
63
+ * @return bool True if the request is a wire request, false otherwise.
64
+ */
55
65
  function isWireRequest(): bool
56
66
  {
57
67
  $serverFetchSite = $_SERVER['HTTP_SEC_FETCH_SITE'] ?? '';
@@ -62,3 +72,19 @@ function isWireRequest(): bool
62
72
 
63
73
  return false;
64
74
  }
75
+
76
+ /**
77
+ * Checks if the request is an X-File request.
78
+ *
79
+ * @return bool True if the request is an X-File request, false otherwise.
80
+ */
81
+ function isXFilRequest(): bool
82
+ {
83
+ $serverFetchSite = $_SERVER['HTTP_SEC_FETCH_SITE'] ?? '';
84
+ if (isset($serverFetchSite) && $serverFetchSite === 'same-origin') {
85
+ $headers = getallheaders();
86
+ return isset($headers['http_pphp_x_file_request']) && strtolower($headers['http_pphp_x_file_request']) === 'true';
87
+ }
88
+
89
+ return false;
90
+ }
@@ -24,6 +24,7 @@ $isHead = $requestMethod === 'HEAD';
24
24
  $isOptions = $requestMethod === 'OPTIONS';
25
25
  $isAjax = isAjaxRequest();
26
26
  $isWire = isWireRequest();
27
+ $isXFilRequest = isXFilRequest();
27
28
  $contentType = $_SERVER['CONTENT_TYPE'] ?? '';
28
29
  $requestedWith = $_SERVER['HTTP_X_REQUESTED_WITH'] ?? '';
29
30
  $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ||
@@ -0,0 +1,132 @@
1
+ import { exec, execSync } from "child_process";
2
+ import chalk from "chalk";
3
+ import { writeFileSync } from "fs";
4
+
5
+ // Function to check if a command exists in the system
6
+ function commandExists(command) {
7
+ try {
8
+ execSync(`command -v ${command}`, { stdio: "ignore" }); // Works for Linux/macOS
9
+ return true;
10
+ } catch {
11
+ return false;
12
+ }
13
+ }
14
+
15
+ function startDev() {
16
+ // Start projectName first, since it's always required
17
+ console.log("Starting projectName...");
18
+ const projectName = exec("npm run projectName");
19
+
20
+ projectName.stdout.on("data", (data) => {
21
+ console.log(`projectName: ${data}`);
22
+ });
23
+
24
+ projectName.stderr.on("data", (data) => {
25
+ console.error(`projectName error: ${data}`);
26
+ });
27
+
28
+ projectName.on("close", (code) => {
29
+ // console.log(`projectName process exited with code ${code}`);
30
+
31
+ // Start browser-sync after projectName completes
32
+ console.log("Starting browser-sync...");
33
+ const browserSync = exec("npm run browser-sync");
34
+ let formattedLog = {
35
+ local: "",
36
+ external: "",
37
+ ui: "",
38
+ uiExternal: "",
39
+ };
40
+
41
+ browserSync.stdout.on("data", (data) => {
42
+ const lines = data.split("\n");
43
+
44
+ lines.forEach((line) => {
45
+ if (/Proxying/.test(line)) {
46
+ console.log(chalk.blue("[Browsersync]") + ` ${line.trim()}`);
47
+ } else if (/Access URLs:/.test(line)) {
48
+ console.log(chalk.green("[Browsersync] Access URLs:"));
49
+ } else if (/Local:/.test(line)) {
50
+ const localUrl = line.match(/Local:\s*(http:\/\/.+)/)[1];
51
+ formattedLog.local = localUrl;
52
+ console.log(chalk.white("Local: ") + chalk.cyanBright(localUrl));
53
+ } else if (/^ {4}External:/.test(line)) {
54
+ const externalUrl = line.match(/External:\s*(http:\/\/\S+)/)[1];
55
+ formattedLog.external = externalUrl;
56
+ console.log(
57
+ chalk.white("External: ") + chalk.magentaBright(externalUrl)
58
+ );
59
+ } else if (/UI:/.test(line)) {
60
+ const uiUrl = line.match(/UI:\s*(http:\/\/.+)/)[1];
61
+ formattedLog.ui = uiUrl;
62
+ console.log(chalk.yellow("UI: ") + chalk.cyanBright(uiUrl));
63
+ } else if (/UI External:/.test(line)) {
64
+ const uiExternalUrl = line.match(/UI External:\s*(http:\/\/.+)/)[1];
65
+ formattedLog.uiExternal = uiExternalUrl;
66
+ console.log(
67
+ chalk.yellow("UI External: ") + chalk.magentaBright(uiExternalUrl)
68
+ );
69
+ } else if (/Watching files/.test(line)) {
70
+ console.log(chalk.blue("[Browsersync] Watching files..."));
71
+ const outputPath = "./settings/bs-output.json";
72
+ writeFileSync(
73
+ outputPath,
74
+ JSON.stringify(formattedLog, null, 2),
75
+ "utf-8"
76
+ );
77
+ console.log(`Browser-sync output saved to ${outputPath}`);
78
+ }
79
+ });
80
+ });
81
+
82
+ browserSync.stderr.on("data", (data) => {
83
+ console.error(`browser-sync error: ${data}`);
84
+ });
85
+
86
+ // Check if tailwind exists, and if so, execute it
87
+ if (commandExists("tailwindcss")) {
88
+ console.log("Starting tailwind...");
89
+ const tailwind = exec("npm run tailwind");
90
+
91
+ tailwind.stdout.on("data", (data) => {
92
+ console.log(chalk.magenta("tailwind: ") + data);
93
+ });
94
+
95
+ tailwind.stderr.on("data", (data) => {
96
+ console.error(chalk.red("tailwind error: ") + data);
97
+ });
98
+
99
+ tailwind.on("close", (code) => {
100
+ console.log(`tailwind process exited with code ${code}`);
101
+ });
102
+ } else {
103
+ // console.log(
104
+ // chalk.red("tailwindcss is not installed, skipping tailwind task.")
105
+ // );
106
+ }
107
+
108
+ // Check if websocket exists, and if so, execute it
109
+ if (commandExists("node")) {
110
+ console.log("Starting websocket...");
111
+ const websocket = exec("npm run websocket");
112
+
113
+ websocket.stdout.on("data", (data) => {
114
+ console.log(chalk.blue("websocket: ") + data);
115
+ });
116
+
117
+ websocket.stderr.on("data", (data) => {
118
+ console.error(chalk.red("websocket error: ") + data);
119
+ });
120
+
121
+ websocket.on("close", (code) => {
122
+ console.log(`websocket process exited with code ${code}`);
123
+ });
124
+ } else {
125
+ // console.log(
126
+ // chalk.red("Websocket is not installed, skipping websocket task.")
127
+ // );
128
+ }
129
+ });
130
+ }
131
+
132
+ startDev();
@@ -0,0 +1,54 @@
1
+ import swaggerJsdoc from "swagger-jsdoc";
2
+ import { writeFileSync } from "fs";
3
+ import { fileURLToPath } from "url";
4
+ import { join, dirname } from "path";
5
+ import { readFileSync } from "fs";
6
+
7
+ // Define __dirname equivalent in ES modules
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = dirname(__filename);
10
+
11
+ // Define the output path for the swagger.json file
12
+ const outputPath = join(
13
+ __dirname,
14
+ "../src/app/swagger-docs/apis/pphp-swagger.json"
15
+ );
16
+
17
+ const bsConnectionInfo = join(__dirname, "bs-output.json");
18
+ const jsonData = JSON.parse(readFileSync(bsConnectionInfo, "utf8"));
19
+
20
+ // Swagger options
21
+ const options = {
22
+ definition: {
23
+ openapi: "3.0.0",
24
+ info: {
25
+ title: "Prisma PHP API Documentation",
26
+ version: "1.0.0",
27
+ description: "API documentation for the Prisma PHP project",
28
+ },
29
+ servers: [
30
+ {
31
+ url: jsonData.local, // For Development
32
+ description: "Server",
33
+ },
34
+ {
35
+ url: "your-domain", // For Production
36
+ description: "Server",
37
+ },
38
+ ],
39
+ },
40
+ apis: [join(__dirname, "../src/app/swagger-docs/apis/**/*.js")], // Path to your API routes
41
+ };
42
+
43
+ // Generate the Swagger specification
44
+ const swaggerSpec = JSON.stringify(swaggerJsdoc(options), null, 2);
45
+
46
+ // Always generate the swagger.json file
47
+ try {
48
+ writeFileSync(outputPath, swaggerSpec, "utf-8");
49
+ console.log(
50
+ `Swagger JSON has been generated and saved to /src/app/swagger-docs/pphp-swagger.json`
51
+ );
52
+ } catch (error) {
53
+ console.error("Error saving Swagger JSON:", error);
54
+ }
@@ -296,29 +296,33 @@ class UploadFile
296
296
 
297
297
  protected function checkName(array $file): void
298
298
  {
299
- $name = str_replace(' ', '_', $file['name']);
300
- $nameParts = pathinfo($name);
299
+ $this->newName = '';
300
+ $noSpaces = str_replace(' ', '_', $file['name']);
301
+ if ($noSpaces != $file['name']) {
302
+ $this->newName = $noSpaces;
303
+ }
304
+ $nameParts = pathinfo($noSpaces);
301
305
  $extension = $nameParts['extension'] ?? '';
302
-
303
- // Handle trusted vs untrusted extensions
304
- if (!$this->typeCheckingOn && (in_array($extension, $this->notTrusted) || empty($extension))) {
305
- $this->newName = $name . $this->suffix;
306
+ if (!$this->typeCheckingOn && !empty($this->suffix)) {
307
+ if (in_array($extension, $this->notTrusted) || empty($extension)) {
308
+ $this->newName = $noSpaces . $this->suffix;
309
+ }
306
310
  }
307
-
308
- // Rename duplicates if necessary
309
311
  if ($this->renameDuplicates) {
310
- $existingFiles = scandir($this->destination);
311
- $originalName = $name;
312
- $i = 1;
313
-
314
- while (in_array($name, $existingFiles)) {
315
- $name = "{$nameParts['filename']}_$i." . ($extension ?: ''); // Maintain the extension if available
316
- $i++;
312
+ $name = isset($this->newName) ? $this->newName : $file['name'];
313
+ $existing = scandir($this->destination);
314
+ if (in_array($name, $existing)) {
315
+ $i = 1;
316
+ do {
317
+ $this->newName = $nameParts['filename'] . '_' . $i++;
318
+ if (!empty($extension)) {
319
+ $this->newName .= ".$extension";
320
+ }
321
+ if (in_array($extension, $this->notTrusted)) {
322
+ $this->newName .= $this->suffix;
323
+ }
324
+ } while (in_array($this->newName, $existing));
317
325
  }
318
-
319
- $this->newName = $name;
320
- } else {
321
- $this->newName = $name;
322
326
  }
323
327
  }
324
328
 
@@ -0,0 +1,259 @@
1
+ {
2
+ "openapi": "3.0.0",
3
+ "info": {
4
+ "title": "Prisma PHP API Documentation",
5
+ "version": "1.0.0",
6
+ "description": "API documentation for the Prisma PHP project"
7
+ },
8
+ "servers": [
9
+ {
10
+ "url": "http://localhost:3000",
11
+ "description": "Server"
12
+ },
13
+ {
14
+ "url": "your-domain",
15
+ "description": "Server"
16
+ }
17
+ ],
18
+ "paths": {
19
+ "/users": {
20
+ "get": {
21
+ "summary": "Retrieve a list of users",
22
+ "tags": [
23
+ "Users"
24
+ ],
25
+ "responses": {
26
+ "200": {
27
+ "description": "A list of users",
28
+ "content": {
29
+ "application/json": {
30
+ "schema": {
31
+ "type": "array",
32
+ "items": {
33
+ "type": "object",
34
+ "properties": {
35
+ "id": {
36
+ "type": "integer",
37
+ "example": 1
38
+ },
39
+ "name": {
40
+ "type": "string",
41
+ "example": "John Doe"
42
+ },
43
+ "email": {
44
+ "type": "string",
45
+ "example": "johndoe@example.com"
46
+ }
47
+ }
48
+ }
49
+ }
50
+ }
51
+ }
52
+ }
53
+ }
54
+ },
55
+ "post": {
56
+ "summary": "Create a new user",
57
+ "tags": [
58
+ "Users"
59
+ ],
60
+ "requestBody": {
61
+ "required": true,
62
+ "content": {
63
+ "application/json": {
64
+ "schema": {
65
+ "type": "object",
66
+ "required": [
67
+ "name",
68
+ "email"
69
+ ],
70
+ "properties": {
71
+ "name": {
72
+ "type": "string",
73
+ "example": "Jane Doe"
74
+ },
75
+ "email": {
76
+ "type": "string",
77
+ "example": "janedoe@example.com"
78
+ }
79
+ }
80
+ }
81
+ }
82
+ }
83
+ },
84
+ "responses": {
85
+ "201": {
86
+ "description": "The created user",
87
+ "content": {
88
+ "application/json": {
89
+ "schema": {
90
+ "type": "object",
91
+ "properties": {
92
+ "id": {
93
+ "type": "integer",
94
+ "example": 2
95
+ },
96
+ "name": {
97
+ "type": "string",
98
+ "example": "Jane Doe"
99
+ },
100
+ "email": {
101
+ "type": "string",
102
+ "example": "janedoe@example.com"
103
+ }
104
+ }
105
+ }
106
+ }
107
+ }
108
+ }
109
+ }
110
+ }
111
+ },
112
+ "/users/{id}": {
113
+ "get": {
114
+ "summary": "Retrieve a single user by ID",
115
+ "tags": [
116
+ "Users"
117
+ ],
118
+ "parameters": [
119
+ {
120
+ "in": "path",
121
+ "name": "id",
122
+ "required": true,
123
+ "description": "The user ID",
124
+ "schema": {
125
+ "type": "integer"
126
+ }
127
+ }
128
+ ],
129
+ "responses": {
130
+ "200": {
131
+ "description": "A single user object",
132
+ "content": {
133
+ "application/json": {
134
+ "schema": {
135
+ "type": "object",
136
+ "properties": {
137
+ "id": {
138
+ "type": "integer",
139
+ "example": 1
140
+ },
141
+ "name": {
142
+ "type": "string",
143
+ "example": "John Doe"
144
+ },
145
+ "email": {
146
+ "type": "string",
147
+ "example": "johndoe@example.com"
148
+ }
149
+ }
150
+ }
151
+ }
152
+ }
153
+ },
154
+ "404": {
155
+ "description": "User not found"
156
+ }
157
+ }
158
+ },
159
+ "put": {
160
+ "summary": "Update a user by ID",
161
+ "tags": [
162
+ "Users"
163
+ ],
164
+ "parameters": [
165
+ {
166
+ "in": "path",
167
+ "name": "id",
168
+ "required": true,
169
+ "description": "The user ID",
170
+ "schema": {
171
+ "type": "integer"
172
+ }
173
+ }
174
+ ],
175
+ "requestBody": {
176
+ "required": true,
177
+ "content": {
178
+ "application/json": {
179
+ "schema": {
180
+ "type": "object",
181
+ "properties": {
182
+ "name": {
183
+ "type": "string",
184
+ "example": "Updated Name"
185
+ },
186
+ "email": {
187
+ "type": "string",
188
+ "example": "updatedemail@example.com"
189
+ }
190
+ }
191
+ }
192
+ }
193
+ }
194
+ },
195
+ "responses": {
196
+ "200": {
197
+ "description": "The updated user",
198
+ "content": {
199
+ "application/json": {
200
+ "schema": {
201
+ "type": "object",
202
+ "properties": {
203
+ "id": {
204
+ "type": "integer",
205
+ "example": 1
206
+ },
207
+ "name": {
208
+ "type": "string",
209
+ "example": "Updated Name"
210
+ },
211
+ "email": {
212
+ "type": "string",
213
+ "example": "updatedemail@example.com"
214
+ }
215
+ }
216
+ }
217
+ }
218
+ }
219
+ },
220
+ "404": {
221
+ "description": "User not found"
222
+ }
223
+ }
224
+ },
225
+ "delete": {
226
+ "summary": "Delete a user by ID",
227
+ "tags": [
228
+ "Users"
229
+ ],
230
+ "parameters": [
231
+ {
232
+ "in": "path",
233
+ "name": "id",
234
+ "required": true,
235
+ "description": "The user ID",
236
+ "schema": {
237
+ "type": "integer"
238
+ }
239
+ }
240
+ ],
241
+ "responses": {
242
+ "204": {
243
+ "description": "User successfully deleted"
244
+ },
245
+ "404": {
246
+ "description": "User not found"
247
+ }
248
+ }
249
+ }
250
+ }
251
+ },
252
+ "components": {},
253
+ "tags": [
254
+ {
255
+ "name": "Users",
256
+ "description": "User management API"
257
+ }
258
+ ]
259
+ }