create-prisma-php-app 1.25.2 → 1.25.501

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/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{execSync}from"child_process";import fs from"fs";import{fileURLToPath}from"url";import path from"path";import chalk from"chalk";import prompts from"prompts";import https from"https";const __filename=fileURLToPath(import.meta.url),__dirname=path.dirname(__filename);let updateAnswer=null;const nonBackendFiles=["favicon.ico","\\src\\app\\index.php","metadata.php","not-found.php"],dockerFiles=[".dockerignore","docker-compose.yml","Dockerfile","apache.conf"];function bsConfigUrls(e){const s=e.indexOf("\\htdocs\\");if(-1===s)return{bsTarget:"",bsPathRewrite:{}};const t=e.substring(0,s+"\\htdocs\\".length).replace(/\\/g,"\\\\"),n=e.replace(new RegExp(`^${t}`),"").replace(/\\/g,"/");let c=`http://localhost/${n}`;c=c.endsWith("/")?c.slice(0,-1):c;const i=c.replace(/(?<!:)(\/\/+)/g,"/"),o=n.replace(/\/\/+/g,"/");return{bsTarget:`${i}/`,bsPathRewrite:{"^/":`/${o.startsWith("/")?o.substring(1):o}/`}}}async function updatePackageJson(e,s){const t=path.join(e,"package.json");if(checkExcludeFiles(t))return;const n=JSON.parse(fs.readFileSync(t,"utf8"));n.scripts={...n.scripts,projectName:"tsx settings/project-name.ts"};let c=[];s.tailwindcss&&(n.scripts={...n.scripts,tailwind:"postcss src/app/css/tailwind.css -o src/app/css/styles.css --watch"},c.push("tailwind")),s.websocket&&(n.scripts={...n.scripts,websocket:"tsx settings/restart-websocket.ts"},c.push("websocket")),s.docker&&(n.scripts={...n.scripts,docker:"docker-compose up"},c.push("docker")),s.swaggerDocs&&(n.scripts={...n.scripts,"create-swagger-docs":"tsx settings/swagger-config.ts"});let i={...n.scripts};i.browserSync="tsx settings/bs-config.ts",i.dev=`npm-run-all projectName -p browserSync ${c.join(" ")}`,n.scripts=i,n.type="module",s.prisma&&(n.prisma={seed:"tsx prisma/seed.ts"}),fs.writeFileSync(t,JSON.stringify(n,null,2))}async function updateComposerJson(e,s){const t=path.join(e,"composer.json");if(checkExcludeFiles(t))return;let n;if(fs.existsSync(t)){{const e=fs.readFileSync(t,"utf8");n=JSON.parse(e)}s.websocket&&(n.require={...n.require,"cboden/ratchet":"^0.4.4"}),s.prisma&&(n.require={...n.require,"ramsey/uuid":"5.x-dev","hidehalo/nanoid-php":"1.x-dev"}),fs.writeFileSync(t,JSON.stringify(n,null,2))}}async function updateIndexJsForWebSocket(e,s){if(!s.websocket)return;const t=path.join(e,"src","app","js","index.js");if(checkExcludeFiles(t))return;let n=fs.readFileSync(t,"utf8");n+='\n// WebSocket initialization\nvar ws = new WebSocket("ws://localhost:8080");\n',fs.writeFileSync(t,n,"utf8")}async function createUpdateGitignoreFile(e,s){const t=path.join(e,".gitignore");if(checkExcludeFiles(t))return;let n="";s.forEach((e=>{n.includes(e)||(n+=`\n${e}`)})),n=n.trimStart(),fs.writeFileSync(t,n)}function copyRecursiveSync(e,s,t){const n=fs.existsSync(e),c=n&&fs.statSync(e);if(n&&c&&c.isDirectory()){const n=s.toLowerCase();if(!t.websocket&&n.includes("src\\lib\\websocket"))return;if(!t.prisma&&n.includes("src\\lib\\prisma"))return;if(t.backendOnly&&n.includes("src\\app\\js")||t.backendOnly&&n.includes("src\\app\\css"))return;if(!t.swaggerDocs&&n.includes("src\\app\\swagger-docs"))return;const c=s.replace(/\\/g,"/");if(updateAnswer?.excludeFilePath?.includes(c))return;fs.existsSync(s)||fs.mkdirSync(s,{recursive:!0}),fs.readdirSync(e).forEach((n=>{copyRecursiveSync(path.join(e,n),path.join(s,n),t)}))}else{if(checkExcludeFiles(s))return;if(!t.tailwindcss&&(s.includes("tailwind.css")||s.includes("styles.css")))return;if(!t.websocket&&(s.includes("restart-websocket.ts")||s.includes("restart-websocket.bat")))return;if(!t.docker&&dockerFiles.some((e=>s.includes(e))))return;if(t.backendOnly&&nonBackendFiles.some((e=>s.includes(e))))return;if(!t.backendOnly&&s.includes("route.php"))return;if(!t.swaggerDocs&&s.includes("swagger-config.ts"))return;if(t.tailwindcss&&s.includes("index.css"))return;fs.copyFileSync(e,s,0)}}async function executeCopy(e,s,t){s.forEach((({src:s,dest:n})=>{copyRecursiveSync(path.join(__dirname,s),path.join(e,n),t)}))}function createOrUpdateTailwindConfig(e){const s=path.join(e,"tailwind.config.js");if(checkExcludeFiles(s))return;let t=fs.readFileSync(s,"utf8");const n=["./src/**/*.{html,js,php}"].map((e=>` "${e}"`)).join(",\n");t=t.replace(/content: \[\],/g,`content: [\n${n}\n],`),fs.writeFileSync(s,t,{flag:"w"})}function modifyPostcssConfig(e){const s=path.join(e,"postcss.config.js");if(checkExcludeFiles(s))return;fs.writeFileSync(s,"export default {\n plugins: {\n tailwindcss: {},\n autoprefixer: {},\n cssnano: {},\n },\n};",{flag:"w"})}function modifyLayoutPHP(e,s){const t=path.join(e,"src","app","layout.php");if(!checkExcludeFiles(t))try{let e=fs.readFileSync(t,"utf8"),n="";s.backendOnly||(n=s.tailwindcss?'\n <script src="https://cdn.jsdelivr.net/npm/json5@2.2.3/dist/index.min.js"><\/script>\n <script src="<?= $baseUrl; ?>/js/index.js" type="module"><\/script>':'\n <link href="<?= $baseUrl; ?>/css/index.css" rel="stylesheet">\n <script src="<?= $baseUrl; ?>/js/index.js" type="module"><\/script>');let c="";s.backendOnly||(c=s.tailwindcss?` <link href="<?= $baseUrl; ?>/css/styles.css" rel="stylesheet"> ${n}`:` <script src="https://cdn.tailwindcss.com"><\/script> ${n}`);const i=c.length>0?"\n":"";e=e.replace("</head>",`${c}${i} \x3c!-- Dynamic Head --\x3e\n <?= MainLayout::outputHeadScripts() ?>\n</head>`),fs.writeFileSync(t,e,{flag:"w"})}catch(e){}}async function createOrUpdateEnvFile(e,s){const t=path.join(e,".env");checkExcludeFiles(t)||fs.writeFileSync(t,s,{flag:"w"})}function checkExcludeFiles(e){return!!updateAnswer?.isUpdate&&(updateAnswer?.excludeFilePath?.includes(e.replace(/\\/g,"/"))??!1)}async function createDirectoryStructure(e,s){const t=[{src:"/bootstrap.php",dest:"/bootstrap.php"},{src:"/.htaccess",dest:"/.htaccess"},{src:"/../composer.json",dest:"/composer.json"},{src:"/tsconfig.json",dest:"/tsconfig.json"}];s.tailwindcss&&t.push({src:"/postcss.config.js",dest:"/postcss.config.js"},{src:"/tailwind.config.js",dest:"/tailwind.config.js"});const n=[{src:"/settings",dest:"/settings"},{src:"/src",dest:"/src"}];s.backendOnly&&s.swaggerDocs&&n.push({src:"/swagger-docs-layout.php",dest:"/src/app/layout.php"}),s.prisma&&n.push({src:"/prisma",dest:"/prisma"}),s.docker&&n.push({src:"/.dockerignore",dest:"/.dockerignore"},{src:"/docker-compose.yml",dest:"/docker-compose.yml"},{src:"/Dockerfile",dest:"/Dockerfile"},{src:"/apache.conf",dest:"/apache.conf"}),t.forEach((({src:s,dest:t})=>{const n=path.join(__dirname,s),c=path.join(e,t);if(checkExcludeFiles(c))return;const i=fs.readFileSync(n,"utf8");fs.writeFileSync(c,i,{flag:"w"})})),await executeCopy(e,n,s),await updatePackageJson(e,s),await updateComposerJson(e,s),s.backendOnly||await updateIndexJsForWebSocket(e,s),s.tailwindcss&&(createOrUpdateTailwindConfig(e),modifyPostcssConfig(e)),(s.tailwindcss||!s.backendOnly||s.swaggerDocs)&&modifyLayoutPHP(e,s);const c='# Prisma PHP Auth Secret Key For development only - Change this in production\nAUTH_SECRET=uxsjXVPHN038DEYls2Kw0QUgBcXKUyrjv416nIFWPY4= \n \n# PHPMailer\n# SMTP_HOST=smtp.gmail.com or your SMTP host\n# SMTP_USERNAME=john.doe@gmail.com or your SMTP username\n# SMTP_PASSWORD=123456\n# SMTP_PORT=587 for TLS, 465 for SSL or your SMTP port\n# SMTP_ENCRYPTION=ssl or tls\n# MAIL_FROM=john.doe@gmail.com\n# MAIL_FROM_NAME="John Doe"\n\n# SHOW ERRORS - Set to true to show errors in the browser for development only - Change this in production to false\nSHOW_ERRORS=true\n\n# APP TIMEZONE - Set your application timezone - Default is "UTC"\nAPP_TIMEZONE="UTC"\n\n# APP ENV - Set your application environment - Default is "development" - Change this in production to "production"\nAPP_ENV=development';if(s.prisma){const s=`${'# Environment variables declared in this file are automatically made available to Prisma.\n# See the documentation for more detail: https://pris.ly/d/prisma-schema#accessing-environment-variables-from-the-schema\n\n# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB.\n# See the documentation for all the connection string options: https://pris.ly/d/connection-strings\n\nDATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public"'}\n\n${c}`;await createOrUpdateEnvFile(e,s)}else await createOrUpdateEnvFile(e,c);await createUpdateGitignoreFile(e,["vendor",".env","node_modules"])}async function getAnswer(e={}){const s=[];e.projectName||s.push({type:"text",name:"projectName",message:"What is your project named?",initial:"my-app"}),e.backendOnly||s.push({type:"toggle",name:"backendOnly",message:`Would you like to create a ${chalk.blue("backend-only project")}?`,initial:!1,active:"Yes",inactive:"No"});const t=()=>{process.exit(0)},n=await prompts(s,{onCancel:t}),c=[];n.backendOnly||e.backendOnly?(e.swaggerDocs||c.push({type:"toggle",name:"swaggerDocs",message:`Would you like to use ${chalk.blue("Swagger Docs")}?`,initial:!1,active:"Yes",inactive:"No"}),e.websocket||c.push({type:"toggle",name:"websocket",message:`Would you like to use ${chalk.blue("Websocket")}?`,initial:!0,active:"Yes",inactive:"No"}),e.prisma||c.push({type:"toggle",name:"prisma",message:`Would you like to use ${chalk.blue("Prisma PHP ORM")}?`,initial:!0,active:"Yes",inactive:"No"}),e.docker||c.push({type:"toggle",name:"docker",message:`Would you like to use ${chalk.blue("Docker")}?`,initial:!1,active:"Yes",inactive:"No"})):(e.swaggerDocs||c.push({type:"toggle",name:"swaggerDocs",message:`Would you like to use ${chalk.blue("Swagger Docs")}?`,initial:!1,active:"Yes",inactive:"No"}),e.tailwindcss||c.push({type:"toggle",name:"tailwindcss",message:`Would you like to use ${chalk.blue("Tailwind CSS")}?`,initial:!0,active:"Yes",inactive:"No"}),e.websocket||c.push({type:"toggle",name:"websocket",message:`Would you like to use ${chalk.blue("Websocket")}?`,initial:!0,active:"Yes",inactive:"No"}),e.prisma||c.push({type:"toggle",name:"prisma",message:`Would you like to use ${chalk.blue("Prisma PHP ORM")}?`,initial:!0,active:"Yes",inactive:"No"}),e.docker||c.push({type:"toggle",name:"docker",message:`Would you like to use ${chalk.blue("Docker")}?`,initial:!1,active:"Yes",inactive:"No"}));const i=await prompts(c,{onCancel:t});return{projectName:n.projectName?String(n.projectName).trim().replace(/ /g,"-"):e.projectName??"my-app",backendOnly:n.backendOnly??e.backendOnly??!1,swaggerDocs:i.swaggerDocs??e.swaggerDocs??!1,tailwindcss:i.tailwindcss??e.tailwindcss??!1,websocket:i.websocket??e.websocket??!1,prisma:i.prisma??e.prisma??!1,docker:i.docker??e.docker??!1}}async function uninstallDependencies(e,s,t=!1){s.forEach((e=>{}));const n=`npm uninstall ${t?"--save-dev":"--save"} ${s.join(" ")}`;execSync(n,{stdio:"inherit",cwd:e})}function fetchPackageVersion(e){return new Promise(((s,t)=>{https.get(`https://registry.npmjs.org/${e}`,(e=>{let n="";e.on("data",(e=>n+=e)),e.on("end",(()=>{try{const e=JSON.parse(n);s(e["dist-tags"].latest)}catch(e){t(new Error("Failed to parse JSON response"))}}))})).on("error",(e=>t(e)))}))}const readJsonFile=e=>{const s=fs.readFileSync(e,"utf8");return JSON.parse(s)};function compareVersions(e,s){const t=e.split(".").map(Number),n=s.split(".").map(Number);for(let e=0;e<t.length;e++){if(t[e]>n[e])return 1;if(t[e]<n[e])return-1}return 0}function getInstalledPackageVersion(e){try{const s=execSync(`npm list -g ${e} --depth=0`).toString().match(new RegExp(`${e}@(\\d+\\.\\d+\\.\\d+)`));return s?s[1]:null}catch(e){return null}}
2
+ import{execSync}from"child_process";import fs from"fs";import{fileURLToPath}from"url";import path from"path";import chalk from"chalk";import prompts from"prompts";import https from"https";const __filename=fileURLToPath(import.meta.url),__dirname=path.dirname(__filename);let updateAnswer=null;const nonBackendFiles=["favicon.ico","\\src\\app\\index.php","metadata.php","not-found.php"],dockerFiles=[".dockerignore","docker-compose.yml","Dockerfile","apache.conf"];function bsConfigUrls(e){const s=e.indexOf("\\htdocs\\");if(-1===s)return{bsTarget:"",bsPathRewrite:{}};const t=e.substring(0,s+"\\htdocs\\".length).replace(/\\/g,"\\\\"),n=e.replace(new RegExp(`^${t}`),"").replace(/\\/g,"/");let c=`http://localhost/${n}`;c=c.endsWith("/")?c.slice(0,-1):c;const i=c.replace(/(?<!:)(\/\/+)/g,"/"),o=n.replace(/\/\/+/g,"/");return{bsTarget:`${i}/`,bsPathRewrite:{"^/":`/${o.startsWith("/")?o.substring(1):o}/`}}}async function updatePackageJson(e,s){const t=path.join(e,"package.json");if(checkExcludeFiles(t))return;const n=JSON.parse(fs.readFileSync(t,"utf8"));n.scripts={...n.scripts,projectName:"tsx settings/project-name.ts"};let c=[];s.tailwindcss&&(n.scripts={...n.scripts,tailwind:"postcss src/app/css/tailwind.css -o src/app/css/styles.css --watch"},c.push("tailwind")),s.websocket&&(n.scripts={...n.scripts,websocket:"tsx settings/restart-websocket.ts"},c.push("websocket")),s.docker&&(n.scripts={...n.scripts,docker:"docker-compose up"},c.push("docker")),s.swaggerDocs&&(n.scripts={...n.scripts,"create-swagger-docs":"tsx settings/swagger-config.ts"});let i={...n.scripts};i.browserSync="tsx settings/bs-config.ts",i.dev=`npm-run-all projectName -p browserSync ${c.join(" ")}`,n.scripts=i,n.type="module",s.prisma&&(n.prisma={seed:"tsx prisma/seed.ts"}),fs.writeFileSync(t,JSON.stringify(n,null,2))}async function updateComposerJson(e,s){const t=path.join(e,"composer.json");if(checkExcludeFiles(t))return;let n;if(fs.existsSync(t)){{const e=fs.readFileSync(t,"utf8");n=JSON.parse(e)}s.websocket&&(n.require={...n.require,"cboden/ratchet":"^0.4.4"}),s.prisma&&(n.require={...n.require,"ramsey/uuid":"5.x-dev","hidehalo/nanoid-php":"1.x-dev"}),fs.writeFileSync(t,JSON.stringify(n,null,2))}}async function updateIndexJsForWebSocket(e,s){if(!s.websocket)return;const t=path.join(e,"src","app","js","index.js");if(checkExcludeFiles(t))return;let n=fs.readFileSync(t,"utf8");n+='\n// WebSocket initialization\nvar ws = new WebSocket("ws://localhost:8080");\n',fs.writeFileSync(t,n,"utf8")}async function createUpdateGitignoreFile(e,s){const t=path.join(e,".gitignore");if(checkExcludeFiles(t))return;let n="";s.forEach((e=>{n.includes(e)||(n+=`\n${e}`)})),n=n.trimStart(),fs.writeFileSync(t,n)}function copyRecursiveSync(e,s,t){const n=fs.existsSync(e),c=n&&fs.statSync(e);if(n&&c&&c.isDirectory()){const n=s.toLowerCase();if(!t.websocket&&n.includes("src\\lib\\websocket"))return;if(!t.prisma&&n.includes("src\\lib\\prisma"))return;if(t.backendOnly&&n.includes("src\\app\\js")||t.backendOnly&&n.includes("src\\app\\css"))return;if(!t.swaggerDocs&&n.includes("src\\app\\swagger-docs"))return;const c=s.replace(/\\/g,"/");if(updateAnswer?.excludeFilePath?.includes(c))return;fs.existsSync(s)||fs.mkdirSync(s,{recursive:!0}),fs.readdirSync(e).forEach((n=>{copyRecursiveSync(path.join(e,n),path.join(s,n),t)}))}else{if(checkExcludeFiles(s))return;if(!t.tailwindcss&&(s.includes("tailwind.css")||s.includes("styles.css")))return;if(!t.websocket&&(s.includes("restart-websocket.ts")||s.includes("restart-websocket.bat")))return;if(!t.docker&&dockerFiles.some((e=>s.includes(e))))return;if(t.backendOnly&&nonBackendFiles.some((e=>s.includes(e))))return;if(!t.backendOnly&&(s.includes("route.php")||s.includes("swagger-docs-layout.php")))return;if(!t.swaggerDocs&&s.includes("swagger-config.ts"))return;if(t.tailwindcss&&s.includes("index.css"))return;fs.copyFileSync(e,s,0)}}async function executeCopy(e,s,t){s.forEach((({src:s,dest:n})=>{copyRecursiveSync(path.join(__dirname,s),path.join(e,n),t)}))}function createOrUpdateTailwindConfig(e){const s=path.join(e,"tailwind.config.js");if(checkExcludeFiles(s))return;let t=fs.readFileSync(s,"utf8");const n=["./src/**/*.{html,js,php}"].map((e=>` "${e}"`)).join(",\n");t=t.replace(/content: \[\],/g,`content: [\n${n}\n],`),fs.writeFileSync(s,t,{flag:"w"})}function modifyPostcssConfig(e){const s=path.join(e,"postcss.config.js");if(checkExcludeFiles(s))return;fs.writeFileSync(s,"export default {\n plugins: {\n tailwindcss: {},\n autoprefixer: {},\n cssnano: {},\n },\n};",{flag:"w"})}function modifyLayoutPHP(e,s){const t=path.join(e,"src","app","layout.php");if(!checkExcludeFiles(t))try{let e=fs.readFileSync(t,"utf8"),n="";s.backendOnly||(s.tailwindcss||(n='\n <link href="<?= Request::baseUrl; ?>/css/index.css" rel="stylesheet">'),n+='\n <script src="<?= Request::baseUrl; ?>/js/json5.min.js"><\/script>\n <script src="<?= Request::baseUrl; ?>/js/index.js"><\/script>');let c="";s.backendOnly||(c=s.tailwindcss?` <link href="<?= Request::baseUrl; ?>/css/styles.css" rel="stylesheet"> ${n}`:n);const i=c.length>0?"\n":"";e=e.replace("</head>",`${c}${i} \x3c!-- Dynamic Head --\x3e\n <?= MainLayout::outputHeadScripts() ?>\n</head>`),fs.writeFileSync(t,e,{flag:"w"})}catch(e){}}async function createOrUpdateEnvFile(e,s){const t=path.join(e,".env");checkExcludeFiles(t)||fs.writeFileSync(t,s,{flag:"w"})}function checkExcludeFiles(e){return!!updateAnswer?.isUpdate&&(updateAnswer?.excludeFilePath?.includes(e.replace(/\\/g,"/"))??!1)}async function createDirectoryStructure(e,s){const t=[{src:"/bootstrap.php",dest:"/bootstrap.php"},{src:"/.htaccess",dest:"/.htaccess"},{src:"/../composer.json",dest:"/composer.json"},{src:"/tsconfig.json",dest:"/tsconfig.json"}];s.tailwindcss&&t.push({src:"/postcss.config.js",dest:"/postcss.config.js"},{src:"/tailwind.config.js",dest:"/tailwind.config.js"});const n=[{src:"/settings",dest:"/settings"},{src:"/src",dest:"/src"}];s.backendOnly&&s.swaggerDocs&&n.push({src:"/src/app/swagger-docs-layout.php",dest:"/src/app/layout.php"}),s.prisma&&n.push({src:"/prisma",dest:"/prisma"}),s.docker&&n.push({src:"/.dockerignore",dest:"/.dockerignore"},{src:"/docker-compose.yml",dest:"/docker-compose.yml"},{src:"/Dockerfile",dest:"/Dockerfile"},{src:"/apache.conf",dest:"/apache.conf"}),t.forEach((({src:s,dest:t})=>{const n=path.join(__dirname,s),c=path.join(e,t);if(checkExcludeFiles(c))return;const i=fs.readFileSync(n,"utf8");fs.writeFileSync(c,i,{flag:"w"})})),await executeCopy(e,n,s),await updatePackageJson(e,s),await updateComposerJson(e,s),s.backendOnly||await updateIndexJsForWebSocket(e,s),s.tailwindcss&&(createOrUpdateTailwindConfig(e),modifyPostcssConfig(e)),(s.tailwindcss||!s.backendOnly||s.swaggerDocs)&&modifyLayoutPHP(e,s);const c='# Prisma PHP Auth Secret Key For development only - Change this in production\nAUTH_SECRET=uxsjXVPHN038DEYls2Kw0QUgBcXKUyrjv416nIFWPY4= \n \n# PHPMailer\n# SMTP_HOST=smtp.gmail.com or your SMTP host\n# SMTP_USERNAME=john.doe@gmail.com or your SMTP username\n# SMTP_PASSWORD=123456\n# SMTP_PORT=587 for TLS, 465 for SSL or your SMTP port\n# SMTP_ENCRYPTION=ssl or tls\n# MAIL_FROM=john.doe@gmail.com\n# MAIL_FROM_NAME="John Doe"\n\n# SHOW ERRORS - Set to true to show errors in the browser for development only - Change this in production to false\nSHOW_ERRORS=true\n\n# APP TIMEZONE - Set your application timezone - Default is "UTC"\nAPP_TIMEZONE="UTC"\n\n# APP ENV - Set your application environment - Default is "development" - Change this in production to "production"\nAPP_ENV=development';if(s.prisma){const s=`${'# Environment variables declared in this file are automatically made available to Prisma.\n# See the documentation for more detail: https://pris.ly/d/prisma-schema#accessing-environment-variables-from-the-schema\n\n# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB.\n# See the documentation for all the connection string options: https://pris.ly/d/connection-strings\n\nDATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public"'}\n\n${c}`;await createOrUpdateEnvFile(e,s)}else await createOrUpdateEnvFile(e,c);await createUpdateGitignoreFile(e,["vendor",".env","node_modules"])}async function getAnswer(e={}){const s=[];e.projectName||s.push({type:"text",name:"projectName",message:"What is your project named?",initial:"my-app"}),e.backendOnly||s.push({type:"toggle",name:"backendOnly",message:`Would you like to create a ${chalk.blue("backend-only project")}?`,initial:!1,active:"Yes",inactive:"No"});const t=()=>{process.exit(0)},n=await prompts(s,{onCancel:t}),c=[];n.backendOnly||e.backendOnly?(e.swaggerDocs||c.push({type:"toggle",name:"swaggerDocs",message:`Would you like to use ${chalk.blue("Swagger Docs")}?`,initial:!1,active:"Yes",inactive:"No"}),e.websocket||c.push({type:"toggle",name:"websocket",message:`Would you like to use ${chalk.blue("Websocket")}?`,initial:!0,active:"Yes",inactive:"No"}),e.prisma||c.push({type:"toggle",name:"prisma",message:`Would you like to use ${chalk.blue("Prisma PHP ORM")}?`,initial:!0,active:"Yes",inactive:"No"}),e.docker||c.push({type:"toggle",name:"docker",message:`Would you like to use ${chalk.blue("Docker")}?`,initial:!1,active:"Yes",inactive:"No"})):(e.swaggerDocs||c.push({type:"toggle",name:"swaggerDocs",message:`Would you like to use ${chalk.blue("Swagger Docs")}?`,initial:!1,active:"Yes",inactive:"No"}),e.tailwindcss||c.push({type:"toggle",name:"tailwindcss",message:`Would you like to use ${chalk.blue("Tailwind CSS")}?`,initial:!0,active:"Yes",inactive:"No"}),e.websocket||c.push({type:"toggle",name:"websocket",message:`Would you like to use ${chalk.blue("Websocket")}?`,initial:!0,active:"Yes",inactive:"No"}),e.prisma||c.push({type:"toggle",name:"prisma",message:`Would you like to use ${chalk.blue("Prisma PHP ORM")}?`,initial:!0,active:"Yes",inactive:"No"}),e.docker||c.push({type:"toggle",name:"docker",message:`Would you like to use ${chalk.blue("Docker")}?`,initial:!1,active:"Yes",inactive:"No"}));const i=await prompts(c,{onCancel:t});return{projectName:n.projectName?String(n.projectName).trim().replace(/ /g,"-"):e.projectName??"my-app",backendOnly:n.backendOnly??e.backendOnly??!1,swaggerDocs:i.swaggerDocs??e.swaggerDocs??!1,tailwindcss:i.tailwindcss??e.tailwindcss??!1,websocket:i.websocket??e.websocket??!1,prisma:i.prisma??e.prisma??!1,docker:i.docker??e.docker??!1}}async function uninstallDependencies(e,s,t=!1){s.forEach((e=>{}));const n=`npm uninstall ${t?"--save-dev":"--save"} ${s.join(" ")}`;execSync(n,{stdio:"inherit",cwd:e})}function fetchPackageVersion(e){return new Promise(((s,t)=>{https.get(`https://registry.npmjs.org/${e}`,(e=>{let n="";e.on("data",(e=>n+=e)),e.on("end",(()=>{try{const e=JSON.parse(n);s(e["dist-tags"].latest)}catch(e){t(new Error("Failed to parse JSON response"))}}))})).on("error",(e=>t(e)))}))}const readJsonFile=e=>{const s=fs.readFileSync(e,"utf8");return JSON.parse(s)};function compareVersions(e,s){const t=e.split(".").map(Number),n=s.split(".").map(Number);for(let e=0;e<t.length;e++){if(t[e]>n[e])return 1;if(t[e]<n[e])return-1}return 0}function getInstalledPackageVersion(e){try{const s=execSync(`npm list -g ${e} --depth=0`).toString().match(new RegExp(`${e}@(\\d+\\.\\d+\\.\\d+)`));return s?s[1]:null}catch(e){return null}}
3
3
  /**
4
4
  * Install dependencies in the specified directory.
5
5
  * @param {string} baseDir - The base directory where to install the dependencies.
@@ -340,7 +340,7 @@ async function main() {
340
340
  `${chalk.green(
341
341
  "Success!"
342
342
  )} Prisma PHP project successfully created in ${chalk.green(
343
- answer.projectName
343
+ `${currentDir}/${answer.projectName}`
344
344
  )}!`
345
345
  );
346
346
  console.log("\n=========================");
@@ -4,10 +4,6 @@
4
4
  * @var string SETTINGS_PATH - The absolute path to the settings directory ./settings
5
5
  */
6
6
  define("SETTINGS_PATH", dirname(__FILE__));
7
- /**
8
- * @var string PUBLIC_PATH - The absolute path to the public directory ./public
9
- */
10
- define("PUBLIC_PATH", dirname(SETTINGS_PATH) . "/public");
11
7
  /**
12
8
  * @var string PRISMA_LIB_PATH - The absolute path to the Prisma library directory ./src/Lib/Prisma
13
9
  */
@@ -11,10 +11,10 @@ use Lib\Validator;
11
11
  */
12
12
  class ChatGPTClient
13
13
  {
14
- private $client;
15
- private $apiUrl;
16
- private $apiKey;
17
- private $cache = [];
14
+ private Client $client;
15
+ private string $apiUrl = '';
16
+ private string $apiKey = '';
17
+ private array $cache = [];
18
18
 
19
19
  /**
20
20
  * Constructor initializes the Guzzle HTTP client and sets up API configuration.
@@ -9,18 +9,19 @@ use DateTime;
9
9
  use Lib\Validator;
10
10
  use GuzzleHttp\Client;
11
11
  use GuzzleHttp\Exception\RequestException;
12
+ use Lib\Request;
12
13
 
13
14
  class Auth
14
15
  {
15
16
  public const PAYLOAD_NAME = 'role';
16
17
  public const ROLE_NAME = '';
17
- public const PAYLOAD = 'payload_2183A';
18
+ public const PAYLOAD_SESSION_KEY = 'payload_2183A';
18
19
  public const COOKIE_NAME = 'pphp_aut_token_D36E5';
19
20
 
20
21
  private static ?Auth $instance = null;
21
22
  private const PPHPAUTH = 'pphpauth';
22
- private $secretKey;
23
- private $defaultTokenValidity = '1h'; // Default to 1 hour
23
+ private string $secretKey;
24
+ private string $defaultTokenValidity = '1h'; // Default to 1 hour
24
25
 
25
26
  /**
26
27
  * Private constructor to prevent direct instantiation.
@@ -62,16 +63,16 @@ class Auth
62
63
  * @throws InvalidArgumentException Thrown if the secret key is not set or if the duration format is invalid.
63
64
  *
64
65
  * Example:
65
- * $auth = new Authentication();
66
+ * $auth = Auth::getInstance();
66
67
  * $auth->setSecretKey('your_secret_key');
67
68
  * try {
68
- * $jwt = $auth->authenticate('Admin', '1h');
69
+ * $jwt = $auth->signIn('Admin', '1h');
69
70
  * echo "JWT: " . $jwt;
70
71
  * } catch (\InvalidArgumentException $e) {
71
72
  * echo "Error: " . $e->getMessage();
72
73
  * }
73
74
  */
74
- public function authenticate($data, string $tokenValidity = null): string
75
+ public function signIn($data, string $tokenValidity = null): string
75
76
  {
76
77
  if (!$this->secretKey) {
77
78
  throw new \InvalidArgumentException("Secret key is required for authentication.");
@@ -89,7 +90,7 @@ class Auth
89
90
  ];
90
91
 
91
92
  // Set the payload in the session
92
- $_SESSION[self::PAYLOAD] = $payload;
93
+ $_SESSION[self::PAYLOAD_SESSION_KEY] = $payload;
93
94
 
94
95
  // Encode the JWT
95
96
  $jwt = JWT::encode($payload, $this->secretKey, 'HS256');
@@ -109,15 +110,13 @@ class Auth
109
110
  */
110
111
  public function isAuthenticated(): bool
111
112
  {
112
- global $_fileToInclude;
113
-
114
113
  if (!isset($_COOKIE[self::COOKIE_NAME])) {
115
- unset($_SESSION[self::PAYLOAD]);
114
+ unset($_SESSION[self::PAYLOAD_SESSION_KEY]);
116
115
  return false;
117
116
  }
118
117
 
119
- if ($_fileToInclude === 'route.php') {
120
- $bearerToken = getBearerToken();
118
+ if (Request::$fileToInclude === 'route.php') {
119
+ $bearerToken = Request::getBearerToken();
121
120
  $verifyBearerToken = $this->verifyToken($bearerToken);
122
121
  if (!$verifyBearerToken) {
123
122
  return false;
@@ -250,24 +249,24 @@ class Auth
250
249
  * @param string|null $redirect Optional parameter specifying the URL to redirect to after logging out.
251
250
  *
252
251
  * Example:
253
- * $auth = new Authentication();
254
- * $auth->logout('/login');
252
+ * $auth = Auth::getInstance();
253
+ * $auth->signOut('/login');
255
254
  *
256
255
  * @return void
257
256
  */
258
- public function logout(string $redirect = null)
257
+ public function signOut(string $redirect = null)
259
258
  {
260
259
  if (isset($_COOKIE[self::COOKIE_NAME])) {
261
260
  unset($_COOKIE[self::COOKIE_NAME]);
262
261
  setcookie(self::COOKIE_NAME, '', time() - 3600, '/');
263
262
  }
264
263
 
265
- if (isset($_SESSION[self::PAYLOAD])) {
266
- unset($_SESSION[self::PAYLOAD]);
264
+ if (isset($_SESSION[self::PAYLOAD_SESSION_KEY])) {
265
+ unset($_SESSION[self::PAYLOAD_SESSION_KEY]);
267
266
  }
268
267
 
269
268
  if ($redirect) {
270
- redirect($redirect);
269
+ Request::redirect($redirect);
271
270
  }
272
271
  }
273
272
 
@@ -279,8 +278,8 @@ class Auth
279
278
  */
280
279
  public function getPayload()
281
280
  {
282
- if (isset($_SESSION[self::PAYLOAD])) {
283
- $value = $_SESSION[self::PAYLOAD][self::PAYLOAD_NAME];
281
+ if (isset($_SESSION[self::PAYLOAD_SESSION_KEY])) {
282
+ $value = $_SESSION[self::PAYLOAD_SESSION_KEY][self::PAYLOAD_NAME];
284
283
  return is_array($value) ? new \ArrayObject($value, \ArrayObject::ARRAY_AS_PROPS) : $value;
285
284
  }
286
285
 
@@ -337,27 +336,27 @@ class Auth
337
336
  */
338
337
  public function authProviders(...$providers)
339
338
  {
340
- global $isGet, $dynamicRouteParams;
339
+ $dynamicRouteParams = Request::$dynamicParams;
341
340
 
342
- if ($isGet && in_array('signin', $dynamicRouteParams[self::PPHPAUTH])) {
341
+ if (Request::$isGet && in_array('signin', $dynamicRouteParams[self::PPHPAUTH])) {
343
342
  foreach ($providers as $provider) {
344
343
  if ($provider instanceof GithubProvider && in_array('github', $dynamicRouteParams[self::PPHPAUTH])) {
345
344
  $githubAuthUrl = "https://github.com/login/oauth/authorize?scope=user:email%20read:user&client_id={$provider->clientId}";
346
- redirect($githubAuthUrl);
345
+ Request::redirect($githubAuthUrl);
347
346
  } elseif ($provider instanceof GoogleProvider && in_array('google', $dynamicRouteParams[self::PPHPAUTH])) {
348
347
  $googleAuthUrl = "https://accounts.google.com/o/oauth2/v2/auth?"
349
348
  . "scope=" . urlencode('email profile') . "&"
350
349
  . "response_type=code&"
351
350
  . "client_id=" . urlencode($provider->clientId) . "&"
352
351
  . "redirect_uri=" . urlencode($provider->redirectUri);
353
- redirect($googleAuthUrl);
352
+ Request::redirect($googleAuthUrl);
354
353
  }
355
354
  }
356
355
  }
357
356
 
358
357
  $authCode = Validator::string($_GET['code'] ?? '');
359
358
 
360
- if ($isGet && in_array('callback', $dynamicRouteParams[self::PPHPAUTH]) && isset($authCode)) {
359
+ if (Request::$isGet && in_array('callback', $dynamicRouteParams[self::PPHPAUTH]) && isset($authCode)) {
361
360
  if (in_array('github', $dynamicRouteParams[self::PPHPAUTH])) {
362
361
  $provider = $this->findProvider($providers, GithubProvider::class);
363
362
 
@@ -444,7 +443,7 @@ class Auth
444
443
  ];
445
444
  $userToAuthenticate = (object)$userToAuthenticate;
446
445
 
447
- $this->authenticate($userToAuthenticate, $githubProvider->maxAge);
446
+ $this->signIn($userToAuthenticate, $githubProvider->maxAge);
448
447
  }
449
448
  }
450
449
  }
@@ -502,7 +501,7 @@ class Auth
502
501
  ];
503
502
  $userToAuthenticate = (object)$userToAuthenticate;
504
503
 
505
- $this->authenticate($userToAuthenticate, $googleProvider->maxAge);
504
+ $this->signIn($userToAuthenticate, $googleProvider->maxAge);
506
505
  }
507
506
  }
508
507
  }
@@ -4,7 +4,7 @@ namespace Lib\FileManager;
4
4
 
5
5
  class UploadFile
6
6
  {
7
- protected string $destination;
7
+ protected string $destination = '';
8
8
  protected array $messages = [];
9
9
  protected array $errorCode = [];
10
10
  protected int $maxSize = 51200; // 50KB default
@@ -19,7 +19,7 @@ class UploadFile
19
19
  protected bool $typeCheckingOn = true;
20
20
  protected array $notTrusted = ['bin', 'cgi', 'exe', 'js', 'pl', 'php', 'py', 'sh'];
21
21
  protected string $suffix = '.upload';
22
- protected bool $renameDuplicates;
22
+ protected bool $renameDuplicates = true;
23
23
 
24
24
  /**
25
25
  * Constructor for the UploadFile class.
@@ -16,21 +16,21 @@ class Boom
16
16
  *
17
17
  * @var int
18
18
  */
19
- protected int $statusCode;
19
+ protected int $statusCode = 500;
20
20
 
21
21
  /**
22
22
  * Error message.
23
23
  *
24
24
  * @var string
25
25
  */
26
- protected string $errorMessage;
26
+ protected string $errorMessage = 'Internal Server Error';
27
27
 
28
28
  /**
29
29
  * Additional error details.
30
30
  *
31
31
  * @var array
32
32
  */
33
- protected array $errorDetails;
33
+ protected array $errorDetails = [];
34
34
 
35
35
  /**
36
36
  * Boom constructor.
@@ -4,22 +4,22 @@ namespace Lib;
4
4
 
5
5
  class MainLayout
6
6
  {
7
- private static $headScripts = [];
8
- private static $footerScripts = [];
9
-
10
- // Default metadata properties
11
7
  public static string $title = '';
12
8
  public static string $description = '';
9
+ public static string $children = '';
10
+ public static string $childLayoutChildren = '';
13
11
 
14
- // Custom metadata storage
12
+ private static $headScripts = [];
13
+ private static $footerScripts = [];
15
14
  private static array $customMetadata = [];
16
15
 
17
16
  /**
18
17
  * Adds one or more scripts to the head section if they are not already present.
19
18
  *
20
19
  * @param string ...$scripts The scripts to be added to the head section.
20
+ * @return void
21
21
  */
22
- public static function addHeadScript(string ...$scripts)
22
+ public static function addHeadScript(string ...$scripts): void
23
23
  {
24
24
  foreach ($scripts as $script) {
25
25
  if (!in_array($script, self::$headScripts)) {
@@ -36,8 +36,9 @@ class MainLayout
36
36
  * it will be appended.
37
37
  *
38
38
  * @param string ...$scripts One or more scripts to be added to the footer.
39
+ * @return void
39
40
  */
40
- public static function addFooterScript(string ...$scripts)
41
+ public static function addFooterScript(string ...$scripts): void
41
42
  {
42
43
  foreach ($scripts as $script) {
43
44
  if (!in_array($script, self::$footerScripts)) {
@@ -51,9 +52,19 @@ class MainLayout
51
52
  *
52
53
  * @return void
53
54
  */
54
- public static function outputHeadScripts()
55
+ public static function outputHeadScripts(): void
55
56
  {
56
- echo implode("\n", self::$headScripts);
57
+ $headScriptsWithAttributes = array_map(function ($tag) {
58
+ // Check if the tag is a <link> or <script> and add the dynamic attribute
59
+ if (strpos($tag, '<script') !== false) {
60
+ return str_replace('<script', '<script pp-dynamic-script="81D7D"', $tag);
61
+ } elseif (strpos($tag, '<link') !== false) {
62
+ return str_replace('<link', '<link pp-dynamic-link="81D7D"', $tag);
63
+ }
64
+ return $tag; // Return the tag unchanged if it's neither <script> nor <link>
65
+ }, self::$headScripts);
66
+
67
+ echo implode("\n", $headScriptsWithAttributes);
57
68
  }
58
69
 
59
70
  /**
@@ -61,7 +72,7 @@ class MainLayout
61
72
  *
62
73
  * @return void
63
74
  */
64
- public static function outputFooterScripts()
75
+ public static function outputFooterScripts(): void
65
76
  {
66
77
  echo implode("\n", self::$footerScripts);
67
78
  }
@@ -71,7 +82,7 @@ class MainLayout
71
82
  *
72
83
  * @return void
73
84
  */
74
- public static function clearHeadScripts()
85
+ public static function clearHeadScripts(): void
75
86
  {
76
87
  self::$headScripts = [];
77
88
  }
@@ -81,7 +92,7 @@ class MainLayout
81
92
  *
82
93
  * @return void
83
94
  */
84
- public static function clearFooterScripts()
95
+ public static function clearFooterScripts(): void
85
96
  {
86
97
  self::$footerScripts = [];
87
98
  }
@@ -93,7 +104,7 @@ class MainLayout
93
104
  * @param string $value
94
105
  * @return void
95
106
  */
96
- public static function addCustomMetadata(string $key, string $value)
107
+ public static function addCustomMetadata(string $key, string $value): void
97
108
  {
98
109
  self::$customMetadata[$key] = $value;
99
110
  }
@@ -114,15 +125,24 @@ class MainLayout
114
125
  *
115
126
  * @return void
116
127
  */
117
- public static function outputMetadata()
128
+ public static function outputMetadata(): void
118
129
  {
119
130
  // Output standard metadata
120
131
  echo '<title>' . htmlspecialchars(self::$title) . '</title>' . "\n";
121
- echo '<meta name="description" content="' . htmlspecialchars(self::$description) . '">' . "\n";
122
132
 
123
- // Output custom metadata
133
+ // Ensure the description is included in custom metadata if not already present
134
+ if (!isset(self::$customMetadata['description'])) {
135
+ self::$customMetadata['description'] = self::$description;
136
+ }
137
+
138
+ $customMetadataContent = [];
124
139
  foreach (self::$customMetadata as $key => $value) {
125
- echo '<meta name="' . htmlspecialchars($key) . '" content="' . htmlspecialchars($value) . '">' . "\n";
140
+ // Add the dynamic meta ID attribute to each <meta> tag
141
+ $customMetadataContent[] = '<meta name="' . htmlspecialchars($key) . '" content="' . htmlspecialchars($value) . '" pp-dynamic-meta="81D7D">';
142
+ }
143
+
144
+ if (!empty($customMetadataContent)) {
145
+ echo implode("\n", $customMetadataContent) . "\n";
126
146
  }
127
147
  }
128
148
 
@@ -131,7 +151,7 @@ class MainLayout
131
151
  *
132
152
  * @return void
133
153
  */
134
- public static function clearCustomMetadata()
154
+ public static function clearCustomMetadata(): void
135
155
  {
136
156
  self::$customMetadata = [];
137
157
  }
@@ -4,31 +4,32 @@ namespace Lib\Middleware;
4
4
 
5
5
  use Lib\Auth\Auth;
6
6
  use Lib\Auth\AuthConfig;
7
+ use Lib\Request;
7
8
 
8
9
  final class AuthMiddleware
9
10
  {
10
- public static function handle($requestUri)
11
+ public static function handle($requestPathname)
11
12
  {
12
- $requestUri = trim($requestUri);
13
- if (!self::matches($requestUri)) {
13
+ $requestPathname = trim($requestPathname);
14
+ if (!self::matches($requestPathname)) {
14
15
  return;
15
16
  }
16
17
 
17
18
  // Check if the user is authorized to access the route or redirect to login
18
19
  if (!self::isAuthorized()) {
19
- redirect('/auth/login');
20
+ Request::redirect('/auth/login');
20
21
  }
21
22
 
22
23
  // Check if the user has the required role to access the route or redirect to denied
23
- if (AuthConfig::IS_ROLE_BASE && !self::hasRequiredRole($requestUri)) {
24
- redirect('/denied');
24
+ if (AuthConfig::IS_ROLE_BASE && !self::hasRequiredRole($requestPathname)) {
25
+ Request::redirect('/denied');
25
26
  }
26
27
  }
27
28
 
28
- protected static function matches($requestUri)
29
+ protected static function matches($requestPathname)
29
30
  {
30
31
  foreach (AuthConfig::$privateRoutes ?? [] as $pattern) {
31
- if (self::getUriRegex($pattern, $requestUri)) {
32
+ if (self::getUriRegex($pattern, $requestPathname)) {
32
33
  return true;
33
34
  }
34
35
  }
@@ -40,7 +41,7 @@ final class AuthMiddleware
40
41
  $auth = Auth::getInstance();
41
42
  $cookieName = Auth::COOKIE_NAME;
42
43
  if (!isset($_COOKIE[$cookieName])) {
43
- unset($_SESSION[Auth::PAYLOAD]);
44
+ unset($_SESSION[Auth::PAYLOAD_SESSION_KEY]);
44
45
  return false;
45
46
  }
46
47
 
@@ -64,12 +65,12 @@ final class AuthMiddleware
64
65
  return false;
65
66
  }
66
67
 
67
- protected static function hasRequiredRole($requestUri): bool
68
+ protected static function hasRequiredRole($requestPathname): bool
68
69
  {
69
70
  $auth = Auth::getInstance();
70
71
  $roleBasedRoutes = AuthConfig::$roleBasedRoutes ?? [];
71
72
  foreach ($roleBasedRoutes as $pattern => $data) {
72
- if (self::getUriRegex($pattern, $requestUri)) {
73
+ if (self::getUriRegex($pattern, $requestPathname)) {
73
74
  $userRole = Auth::ROLE_NAME ? $auth->getPayload()[Auth::ROLE_NAME] : $auth->getPayload();
74
75
  if ($userRole !== null && AuthConfig::checkAuthRole($userRole, $data[AuthConfig::ROLE_IDENTIFIER])) {
75
76
  return true;
@@ -79,19 +80,19 @@ final class AuthMiddleware
79
80
  return false;
80
81
  }
81
82
 
82
- private static function getUriRegex($pattern, $requestUri)
83
+ private static function getUriRegex($pattern, $requestPathname)
83
84
  {
84
85
  $pattern = strtolower($pattern);
85
- $requestUri = strtolower(trim($requestUri));
86
+ $requestPathname = strtolower(trim($requestPathname));
86
87
 
87
- // Handle the case where the requestUri is empty, which means home or "/"
88
- if (empty($requestUri) || $requestUri === '/') {
89
- $requestUri = '/';
88
+ // Handle the case where the requestPathname is empty, which means home or "/"
89
+ if (empty($requestPathname) || $requestPathname === '/') {
90
+ $requestPathname = '/';
90
91
  } else {
91
- $requestUri = "/" . $requestUri;
92
+ $requestPathname = "/" . $requestPathname;
92
93
  }
93
94
 
94
95
  $regex = "#^/?" . preg_quote($pattern, '#') . "(/.*)?$#";
95
- return preg_match($regex, $requestUri);
96
+ return preg_match($regex, $requestPathname);
96
97
  }
97
98
  }
@@ -0,0 +1,43 @@
1
+ <?php
2
+
3
+ namespace Lib;
4
+
5
+ class PrismaPHPSettings
6
+ {
7
+ /**
8
+ *
9
+ */
10
+ public static \ArrayObject $option;
11
+
12
+ public static array $routeFiles = [];
13
+
14
+ public static function init(): void
15
+ {
16
+ self::$option = self::getPrismaSettings();
17
+ self::$routeFiles = self::getRoutesFileList();
18
+ }
19
+
20
+ private static function getPrismaSettings(): \ArrayObject
21
+ {
22
+ $prismaPHPSettingsJson = DOCUMENT_PATH . '/prisma-php.json';
23
+
24
+ if (file_exists($prismaPHPSettingsJson)) {
25
+ $jsonContent = file_get_contents($prismaPHPSettingsJson);
26
+ $decodedJson = json_decode($jsonContent, true);
27
+
28
+ if (json_last_error() === JSON_ERROR_NONE) {
29
+ return new \ArrayObject($decodedJson, \ArrayObject::ARRAY_AS_PROPS);
30
+ } else {
31
+ return new \ArrayObject([]);
32
+ }
33
+ }
34
+ }
35
+
36
+ private static function getRoutesFileList(): array
37
+ {
38
+ $jsonFileName = SETTINGS_PATH . '/files-list.json';
39
+ $routeFiles = file_exists($jsonFileName) ? json_decode(file_get_contents($jsonFileName), true) : [];
40
+
41
+ return $routeFiles;
42
+ }
43
+ }