create-prisma-php-app 4.0.0-alpha.11 → 4.0.0-alpha.13

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 (2) hide show
  1. package/dist/index.js +495 -351
  2. package/package.json +1 -1
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";import{randomBytes}from"crypto";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","error.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 o=c.replace(/(?<!:)(\/\/+)/g,"/"),i=n.replace(/\/\/+/g,"/");return{bsTarget:`${o}/`,bsPathRewrite:{"^/":`/${i.startsWith("/")?i.substring(1):i}/`}}}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=[];if(s.tailwindcss&&(n.scripts={...n.scripts,tailwind:"postcss src/app/css/tailwind.css -o src/app/css/styles.css --watch","tailwind:build":"postcss src/app/css/tailwind.css -o src/app/css/styles.css"},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){const e=s.prisma?"tsx settings/auto-swagger-docs.ts":"tsx settings/swagger-config.ts";n.scripts={...n.scripts,"create-swagger-docs":e}}let o={...n.scripts};o.browserSync="tsx settings/bs-config.ts",o["browserSync:build"]="tsx settings/build.ts",o.dev=`npm-run-all projectName -p browserSync ${c.join(" ")}`,o.build=`npm-run-all${s.tailwindcss?" tailwind:build":""} browserSync:build`,n.scripts=o,n.type="module",fs.writeFileSync(t,JSON.stringify(n,null,2))}async function updateComposerJson(e){const s=path.join(e,"composer.json");if(checkExcludeFiles(s))return;let t;if(fs.existsSync(s)){{const e=fs.readFileSync(s,"utf8");t=JSON.parse(e)}t.autoload={"psr-4":{"":"src/"}},t.version="1.0.0",fs.writeFileSync(s,JSON.stringify(t,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")}function generateAuthSecret(){return randomBytes(33).toString("base64")}function generateHexEncodedKey(e=16){return randomBytes(e).toString("hex")}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.backendOnly&&n.includes("src\\app\\js")||t.backendOnly&&n.includes("src\\app\\css")||t.backendOnly&&n.includes("src\\app\\assets"))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.backendOnly&&!t.swaggerDocs&&s.includes("layout.php"))return;if(!t.swaggerDocs&&s.includes("swagger-config.ts"))return;if(t.tailwindcss&&s.includes("index.css"))return;if((!t.swaggerDocs||!t.prisma)&&(s.includes("auto-swagger-docs.ts")||s.includes("prisma-schema-config.json")))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 modifyPostcssConfig(e){const s=path.join(e,"postcss.config.js");if(checkExcludeFiles(s))return;fs.writeFileSync(s,'export default {\n plugins: {\n "@tailwindcss/postcss": {},\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/morphdom-umd.min.js"><\/script>\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),e=e.replace("</head>",`${c}\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:"/tsconfig.json",dest:"/tsconfig.json"},{src:"/app-gitignore",dest:"/.gitignore"}];s.tailwindcss&&t.push({src:"/postcss.config.js",dest:"/postcss.config.js"});const n=[{src:"/settings",dest:"/settings"},{src:"/src",dest:"/src"}];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 o=fs.readFileSync(n,"utf8");fs.writeFileSync(c,o,{flag:"w"})})),await executeCopy(e,n,s),await updatePackageJson(e,s),await updateComposerJson(e),s.backendOnly||await updateIndexJsForWebSocket(e,s),s.tailwindcss&&modifyPostcssConfig(e),(s.tailwindcss||!s.backendOnly||s.swaggerDocs)&&modifyLayoutPHP(e,s);const c=generateAuthSecret(),o=generateHexEncodedKey(),i=`# Authentication secret key for JWT or session encryption.\nAUTH_SECRET="${c}"\n# Name of the authentication cookie.\nAUTH_COOKIE_NAME="${generateHexEncodedKey(8)}"\n\n# PHPMailer SMTP configuration (uncomment and set as needed)\n# SMTP_HOST="smtp.gmail.com" # Your SMTP host\n# SMTP_USERNAME="john.doe@gmail.com" # Your SMTP username\n# SMTP_PASSWORD="123456" # Your SMTP password\n# SMTP_PORT="587" # 587 for TLS, 465 for SSL, or your SMTP port\n# SMTP_ENCRYPTION="ssl" # ssl or tls\n# MAIL_FROM="john.doe@gmail.com" # Sender email address\n# MAIL_FROM_NAME="John Doe" # Sender name\n\n# Show errors in the browser (development only). Set to false in production.\nSHOW_ERRORS="true"\n\n# Application timezone (default: UTC)\nAPP_TIMEZONE="UTC"\n\n# Application environment (development or production)\nAPP_ENV="development"\n\n# Enable or disable application cache (default: false)\nCACHE_ENABLED="false"\n# Cache time-to-live in seconds (default: 600)\nCACHE_TTL="600"\n\n# Local storage key for browser storage (auto-generated if not set).\n# Spaces will be replaced with underscores and converted to lowercase.\nLOCALSTORE_KEY="${o}"\n\n# Secret key for encrypting function calls.\nFUNCTION_CALL_SECRET="${generateHexEncodedKey(32)}"`;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${i}`;await createOrUpdateEnvFile(e,s)}else await createOrUpdateEnvFile(e,i)}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||updateAnswer?.isUpdate||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??!1?(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:!1,active:"Yes",inactive:"No"}),e.websocket||c.push({type:"toggle",name:"websocket",message:`Would you like to use ${chalk.blue("Websocket")}?`,initial:!1,active:"Yes",inactive:"No"}),e.prisma||c.push({type:"toggle",name:"prisma",message:`Would you like to use ${chalk.blue("Prisma PHP ORM")}?`,initial:!1,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 o=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:o.swaggerDocs??e.swaggerDocs??!1,tailwindcss:o.tailwindcss??e.tailwindcss??!1,websocket:o.websocket??e.websocket??!1,prisma:o.prisma??e.prisma??!1,docker:o.docker??e.docker??!1}}async function uninstallNpmDependencies(e,s,t=!1){s.forEach((e=>{}));const n=`npm uninstall ${t?"--save-dev":"--save"} ${s.join(" ")}`;execSync(n,{stdio:"inherit",cwd:e})}async function uninstallComposerDependencies(e,s){s.forEach((e=>{}));const t=`C:\\xampp\\php\\php.exe C:\\ProgramData\\ComposerSetup\\bin\\composer.phar remove ${s.join(" ")}`;execSync(t,{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,spawnSync}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";import{randomBytes}from"crypto";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","error.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 o=c.replace(/(?<!:)(\/\/+)/g,"/"),i=n.replace(/\/\/+/g,"/");return{bsTarget:`${o}/`,bsPathRewrite:{"^/":`/${i.startsWith("/")?i.substring(1):i}/`}}}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=[];if(s.tailwindcss&&(n.scripts={...n.scripts,tailwind:"postcss src/app/css/tailwind.css -o src/app/css/styles.css --watch","tailwind:build":"postcss src/app/css/tailwind.css -o src/app/css/styles.css"},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){const e=s.prisma?"tsx settings/auto-swagger-docs.ts":"tsx settings/swagger-config.ts";n.scripts={...n.scripts,"create-swagger-docs":e}}let o={...n.scripts};o.browserSync="tsx settings/bs-config.ts",o["browserSync:build"]="tsx settings/build.ts",o.dev=`npm-run-all projectName -p browserSync ${c.join(" ")}`,o.build=`npm-run-all${s.tailwindcss?" tailwind:build":""} browserSync:build`,n.scripts=o,n.type="module",fs.writeFileSync(t,JSON.stringify(n,null,2))}async function updateComposerJson(e){checkExcludeFiles(path.join(e,"composer.json"))}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")}function generateAuthSecret(){return randomBytes(33).toString("base64")}function generateHexEncodedKey(e=16){return randomBytes(e).toString("hex")}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.backendOnly&&n.includes("src\\app\\js")||t.backendOnly&&n.includes("src\\app\\css")||t.backendOnly&&n.includes("src\\app\\assets"))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.backendOnly&&!t.swaggerDocs&&s.includes("layout.php"))return;if(!t.swaggerDocs&&s.includes("swagger-config.ts"))return;if(t.tailwindcss&&s.includes("index.css"))return;if((!t.swaggerDocs||!t.prisma)&&(s.includes("auto-swagger-docs.ts")||s.includes("prisma-schema-config.json")))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 modifyPostcssConfig(e){const s=path.join(e,"postcss.config.js");if(checkExcludeFiles(s))return;fs.writeFileSync(s,'export default {\n plugins: {\n "@tailwindcss/postcss": {},\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/morphdom-umd.min.js"><\/script>\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),e=e.replace("</head>",`${c}\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:"/tsconfig.json",dest:"/tsconfig.json"},{src:"/app-gitignore",dest:"/.gitignore"}];s.tailwindcss&&t.push({src:"/postcss.config.js",dest:"/postcss.config.js"});const n=[{src:"/settings",dest:"/settings"},{src:"/src",dest:"/src"}];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 o=fs.readFileSync(n,"utf8");fs.writeFileSync(c,o,{flag:"w"})})),await executeCopy(e,n,s),await updatePackageJson(e,s),await updateComposerJson(e),s.backendOnly||await updateIndexJsForWebSocket(e,s),s.tailwindcss&&modifyPostcssConfig(e),(s.tailwindcss||!s.backendOnly||s.swaggerDocs)&&modifyLayoutPHP(e,s);const c=generateAuthSecret(),o=generateHexEncodedKey(),i=`# Authentication secret key for JWT or session encryption.\nAUTH_SECRET="${c}"\n# Name of the authentication cookie.\nAUTH_COOKIE_NAME="${generateHexEncodedKey(8)}"\n\n# PHPMailer SMTP configuration (uncomment and set as needed)\n# SMTP_HOST="smtp.gmail.com" # Your SMTP host\n# SMTP_USERNAME="john.doe@gmail.com" # Your SMTP username\n# SMTP_PASSWORD="123456" # Your SMTP password\n# SMTP_PORT="587" # 587 for TLS, 465 for SSL, or your SMTP port\n# SMTP_ENCRYPTION="ssl" # ssl or tls\n# MAIL_FROM="john.doe@gmail.com" # Sender email address\n# MAIL_FROM_NAME="John Doe" # Sender name\n\n# Show errors in the browser (development only). Set to false in production.\nSHOW_ERRORS="true"\n\n# Application timezone (default: UTC)\nAPP_TIMEZONE="UTC"\n\n# Application environment (development or production)\nAPP_ENV="development"\n\n# Enable or disable application cache (default: false)\nCACHE_ENABLED="false"\n# Cache time-to-live in seconds (default: 600)\nCACHE_TTL="600"\n\n# Local storage key for browser storage (auto-generated if not set).\n# Spaces will be replaced with underscores and converted to lowercase.\nLOCALSTORE_KEY="${o}"\n\n# Secret key for encrypting function calls.\nFUNCTION_CALL_SECRET="${generateHexEncodedKey(32)}"`;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${i}`;await createOrUpdateEnvFile(e,s)}else await createOrUpdateEnvFile(e,i)}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||updateAnswer?.isUpdate||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??!1?(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:!1,active:"Yes",inactive:"No"}),e.websocket||c.push({type:"toggle",name:"websocket",message:`Would you like to use ${chalk.blue("Websocket")}?`,initial:!1,active:"Yes",inactive:"No"}),e.prisma||c.push({type:"toggle",name:"prisma",message:`Would you like to use ${chalk.blue("Prisma PHP ORM")}?`,initial:!1,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 o=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:o.swaggerDocs??e.swaggerDocs??!1,tailwindcss:o.tailwindcss??e.tailwindcss??!1,websocket:o.websocket??e.websocket??!1,prisma:o.prisma??e.prisma??!1,docker:o.docker??e.docker??!1}}async function uninstallNpmDependencies(e,s,t=!1){s.forEach((e=>{}));const n=`npm uninstall ${t?"--save-dev":"--save"} ${s.join(" ")}`;execSync(n,{stdio:"inherit",cwd:e})}async function uninstallComposerDependencies(e,s){s.forEach((e=>{}));const t=`C:\\xampp\\php\\php.exe C:\\ProgramData\\ComposerSetup\\bin\\composer.phar remove ${s.join(" ")}`;execSync(t,{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.
@@ -7,378 +7,522 @@ import{execSync}from"child_process";import fs from"fs";import{fileURLToPath}from
7
7
  * @param {boolean} [isDev=false] - Whether to install the dependencies as devDependencies.
8
8
  */
9
9
  async function installNpmDependencies(baseDir, dependencies, isDev = false) {
10
- console.log("Initializing new Node.js project...");
11
- // Initialize a package.json if it doesn't exist
12
- if (!fs.existsSync(path.join(baseDir, "package.json"))) {
13
- execSync("npm init -y", {
14
- stdio: "inherit",
15
- cwd: baseDir,
16
- });
17
- }
18
- // Log the dependencies being installed
19
- console.log(`${isDev ? "Installing development dependencies" : "Installing dependencies"}:`);
20
- dependencies.forEach((dep) => console.log(`- ${chalk.blue(dep)}`));
21
- // Prepare the npm install command with the appropriate flag for dev dependencies
22
- const npmInstallCommand = `npm install ${isDev ? "--save-dev" : ""} ${dependencies.join(" ")}`;
23
- // Execute the npm install command
24
- execSync(npmInstallCommand, {
25
- stdio: "inherit",
26
- cwd: baseDir,
10
+ console.log("Initializing new Node.js project...");
11
+ // Initialize a package.json if it doesn't exist
12
+ if (!fs.existsSync(path.join(baseDir, "package.json"))) {
13
+ execSync("npm init -y", {
14
+ stdio: "inherit",
15
+ cwd: baseDir,
27
16
  });
17
+ }
18
+ // Log the dependencies being installed
19
+ console.log(
20
+ `${
21
+ isDev ? "Installing development dependencies" : "Installing dependencies"
22
+ }:`
23
+ );
24
+ dependencies.forEach((dep) => console.log(`- ${chalk.blue(dep)}`));
25
+ // Prepare the npm install command with the appropriate flag for dev dependencies
26
+ const npmInstallCommand = `npm install ${
27
+ isDev ? "--save-dev" : ""
28
+ } ${dependencies.join(" ")}`;
29
+ // Execute the npm install command
30
+ execSync(npmInstallCommand, {
31
+ stdio: "inherit",
32
+ cwd: baseDir,
33
+ });
28
34
  }
29
- async function installComposerDependencies(baseDir, dependencies) {
30
- console.log(chalk.green(`Composer project initialization: ${updateAnswer?.isUpdate
31
- ? "Updating existing project..."
32
- : "Setting up new project..."}`));
33
- // Initialize a composer.json if it doesn't exist
34
- if (!fs.existsSync(path.join(baseDir, "composer.json"))) {
35
- execSync(`composer init -n \
36
- --name="tsnc/prisma-php-app" \
37
- --require="php:^8.2" \
38
- --version="1.0.0"`, { stdio: "inherit", cwd: baseDir });
35
+ async function composerBin() {
36
+ const windowsPhar =
37
+ '"C:\\xampp\\php\\php.exe" "C:\\ProgramData\\ComposerSetup\\bin\\composer.phar"';
38
+ try {
39
+ execSync("composer --version", { stdio: "ignore" });
40
+ return "composer";
41
+ } catch {
42
+ return windowsPhar;
43
+ }
44
+ }
45
+ export async function installComposerDependencies(baseDir, dependencies) {
46
+ const composer = await composerBin();
47
+ const composerJsonPath = path.join(baseDir, "composer.json");
48
+ const existsAlready = fs.existsSync(composerJsonPath);
49
+ console.log(
50
+ chalk.green(
51
+ `Composer project initialization: ${
52
+ existsAlready ? "Updating existing project…" : "Setting up new project…"
53
+ }`
54
+ )
55
+ );
56
+ /* ------------------------------------------------------------------ */
57
+ /* 1. Crear composer.json (solo si no existe) */
58
+ /* ------------------------------------------------------------------ */
59
+ if (!existsAlready) {
60
+ const init = spawnSync(
61
+ composer,
62
+ [
63
+ "init",
64
+ "--no-interaction",
65
+ "--name",
66
+ "tsnc/prisma-php-app",
67
+ "--require",
68
+ "php:^8.2",
69
+ "--type",
70
+ "project",
71
+ "--version",
72
+ "1.0.0",
73
+ ],
74
+ { stdio: "inherit", cwd: baseDir }
75
+ );
76
+ if (init.status !== 0) {
77
+ throw new Error("Composer init failed");
78
+ }
79
+ /* -- Última defensa: si composer.json no apareció, lo creamos mínimo */
80
+ if (!fs.existsSync(composerJsonPath)) {
81
+ fs.writeFileSync(
82
+ composerJsonPath,
83
+ JSON.stringify(
84
+ {
85
+ name: "tsnc/prisma-php-app",
86
+ require: { php: "^8.2" },
87
+ autoload: { "psr-4": { "": "src/" } },
88
+ type: "project",
89
+ version: "1.0.0",
90
+ },
91
+ null,
92
+ 2
93
+ )
94
+ );
39
95
  }
40
- // Log the dependencies being installed
96
+ }
97
+ /* ------------------------------------------------------------------ */
98
+ /* 2. Garantizar autoload PSR-4 sin borrar mapeos previos */
99
+ /* ------------------------------------------------------------------ */
100
+ const json = JSON.parse(fs.readFileSync(composerJsonPath, "utf8"));
101
+ json.autoload ??= {};
102
+ json.autoload["psr-4"] ??= {};
103
+ json.autoload["psr-4"][""] ??= "src/";
104
+ fs.writeFileSync(composerJsonPath, JSON.stringify(json, null, 2));
105
+ /* ------------------------------------------------------------------ */
106
+ /* 3. Instalar dependencias */
107
+ /* ------------------------------------------------------------------ */
108
+ if (dependencies.length) {
41
109
  console.log("Installing Composer dependencies:");
42
110
  dependencies.forEach((dep) => console.log(`- ${chalk.blue(dep)}`));
43
- // Prepare the composer require command
44
- const composerRequireCommand = `C:\\xampp\\php\\php.exe C:\\ProgramData\\ComposerSetup\\bin\\composer.phar require ${dependencies.join(" ")}`;
45
- // Execute the composer require command
46
- execSync(composerRequireCommand, {
47
- stdio: "inherit",
48
- cwd: baseDir,
111
+ execSync(`${composer} require --no-interaction ${dependencies.join(" ")}`, {
112
+ stdio: "inherit",
113
+ cwd: baseDir,
114
+ });
115
+ }
116
+ /* ------------------------------------------------------------------ */
117
+ /* 4. Refrescar lock (solo modo update) */
118
+ /* ------------------------------------------------------------------ */
119
+ if (existsAlready) {
120
+ execSync(`${composer} update --lock --no-install --no-interaction`, {
121
+ stdio: "inherit",
122
+ cwd: baseDir,
49
123
  });
124
+ }
125
+ /* ------------------------------------------------------------------ */
126
+ /* 5. Regenerar autoloader */
127
+ /* ------------------------------------------------------------------ */
128
+ execSync(`${composer} dump-autoload --quiet`, {
129
+ stdio: "inherit",
130
+ cwd: baseDir,
131
+ });
50
132
  }
51
133
  const npmPinnedVersions = {
52
- "@tailwindcss/postcss": "^4.1.11",
53
- "@types/browser-sync": "^2.29.0",
54
- "@types/node": "^24.0.13",
55
- "@types/prompts": "^2.4.9",
56
- "browser-sync": "^3.0.4",
57
- chalk: "^5.4.1",
58
- "chokidar-cli": "^3.0.0",
59
- cssnano: "^7.0.7",
60
- "http-proxy-middleware": "^3.0.5",
61
- "npm-run-all": "^4.1.5",
62
- "php-parser": "^3.2.5",
63
- postcss: "^8.5.6",
64
- "postcss-cli": "^11.0.1",
65
- prompts: "^2.4.2",
66
- tailwindcss: "^4.1.11",
67
- tsx: "^4.20.3",
68
- typescript: "^5.8.3",
134
+ "@tailwindcss/postcss": "^4.1.11",
135
+ "@types/browser-sync": "^2.29.0",
136
+ "@types/node": "^24.0.13",
137
+ "@types/prompts": "^2.4.9",
138
+ "browser-sync": "^3.0.4",
139
+ chalk: "^5.4.1",
140
+ "chokidar-cli": "^3.0.0",
141
+ cssnano: "^7.0.7",
142
+ "http-proxy-middleware": "^3.0.5",
143
+ "npm-run-all": "^4.1.5",
144
+ "php-parser": "^3.2.5",
145
+ postcss: "^8.5.6",
146
+ "postcss-cli": "^11.0.1",
147
+ prompts: "^2.4.2",
148
+ tailwindcss: "^4.1.11",
149
+ tsx: "^4.20.3",
150
+ typescript: "^5.8.3",
69
151
  };
70
152
  function npmPkg(name) {
71
- return npmPinnedVersions[name] ? `${name}@${npmPinnedVersions[name]}` : name;
153
+ return npmPinnedVersions[name] ? `${name}@${npmPinnedVersions[name]}` : name;
72
154
  }
73
155
  const composerPinnedVersions = {
74
- "vlucas/phpdotenv": "^5.6.2",
75
- "firebase/php-jwt": "^6.11.1",
76
- "phpmailer/phpmailer": "^6.10.0",
77
- "guzzlehttp/guzzle": "^7.9.3",
78
- "ezyang/htmlpurifier": "^4.18.0",
79
- "symfony/uid": "^7.2.0",
80
- "brick/math": "^0.13.1",
81
- "cboden/ratchet": "^0.4.4",
82
- "tsnc/prisma-php": "^1.0.0",
156
+ "vlucas/phpdotenv": "^5.6.2",
157
+ "firebase/php-jwt": "^6.11.1",
158
+ "phpmailer/phpmailer": "^6.10.0",
159
+ "guzzlehttp/guzzle": "^7.9.3",
160
+ "ezyang/htmlpurifier": "^4.18.0",
161
+ "symfony/uid": "^7.2.0",
162
+ "brick/math": "^0.13.1",
163
+ "cboden/ratchet": "^0.4.4",
164
+ "tsnc/prisma-php": "^1.0.0",
83
165
  };
84
166
  function composerPkg(name) {
85
- return composerPinnedVersions[name]
86
- ? `${name}:${composerPinnedVersions[name]}`
87
- : name;
167
+ return composerPinnedVersions[name]
168
+ ? `${name}:${composerPinnedVersions[name]}`
169
+ : name;
88
170
  }
89
171
  async function main() {
90
- try {
91
- const args = process.argv.slice(2);
92
- let projectName = args[0];
93
- let answer = null;
94
- if (projectName) {
95
- let useBackendOnly = args.includes("--backend-only");
96
- let useSwaggerDocs = args.includes("--swagger-docs");
97
- let useTailwind = args.includes("--tailwindcss");
98
- let useWebsocket = args.includes("--websocket");
99
- let usePrisma = args.includes("--prisma");
100
- let useDocker = args.includes("--docker");
101
- const predefinedAnswers = {
102
- projectName,
103
- backendOnly: useBackendOnly,
104
- swaggerDocs: useSwaggerDocs,
105
- tailwindcss: useTailwind,
106
- websocket: useWebsocket,
107
- prisma: usePrisma,
108
- docker: useDocker,
109
- };
110
- answer = await getAnswer(predefinedAnswers);
111
- if (answer === null) {
112
- console.log(chalk.red("Installation cancelled."));
113
- return;
114
- }
115
- const currentDir = process.cwd();
116
- const configPath = path.join(currentDir, "prisma-php.json");
117
- if (fs.existsSync(configPath)) {
118
- const localSettings = readJsonFile(configPath);
119
- let excludeFiles = [];
120
- localSettings.excludeFiles?.map((file) => {
121
- const filePath = path.join(currentDir, file);
122
- if (fs.existsSync(filePath))
123
- excludeFiles.push(filePath.replace(/\\/g, "/"));
124
- });
125
- updateAnswer = {
126
- projectName,
127
- backendOnly: answer?.backendOnly ?? false,
128
- swaggerDocs: answer?.swaggerDocs ?? false,
129
- tailwindcss: answer?.tailwindcss ?? false,
130
- websocket: answer?.websocket ?? false,
131
- prisma: answer?.prisma ?? false,
132
- docker: answer?.docker ?? false,
133
- isUpdate: true,
134
- excludeFiles: localSettings.excludeFiles ?? [],
135
- excludeFilePath: excludeFiles ?? [],
136
- filePath: currentDir,
137
- };
138
- }
139
- }
140
- else {
141
- answer = await getAnswer();
142
- }
143
- if (answer === null) {
144
- console.warn(chalk.red("Installation cancelled."));
145
- return;
146
- }
147
- const latestVersionOfCreatePrismaPhpApp = await fetchPackageVersion("create-prisma-php-app");
148
- const isCreatePrismaPhpAppInstalled = getInstalledPackageVersion("create-prisma-php-app");
149
- if (isCreatePrismaPhpAppInstalled) {
150
- if (compareVersions(isCreatePrismaPhpAppInstalled, latestVersionOfCreatePrismaPhpApp) === -1) {
151
- execSync("npm uninstall -g create-prisma-php-app", {
152
- stdio: "inherit",
153
- });
154
- execSync("npm install -g create-prisma-php-app", {
155
- stdio: "inherit",
156
- });
157
- }
172
+ try {
173
+ const args = process.argv.slice(2);
174
+ let projectName = args[0];
175
+ let answer = null;
176
+ if (projectName) {
177
+ let useBackendOnly = args.includes("--backend-only");
178
+ let useSwaggerDocs = args.includes("--swagger-docs");
179
+ let useTailwind = args.includes("--tailwindcss");
180
+ let useWebsocket = args.includes("--websocket");
181
+ let usePrisma = args.includes("--prisma");
182
+ let useDocker = args.includes("--docker");
183
+ const predefinedAnswers = {
184
+ projectName,
185
+ backendOnly: useBackendOnly,
186
+ swaggerDocs: useSwaggerDocs,
187
+ tailwindcss: useTailwind,
188
+ websocket: useWebsocket,
189
+ prisma: usePrisma,
190
+ docker: useDocker,
191
+ };
192
+ answer = await getAnswer(predefinedAnswers);
193
+ if (answer === null) {
194
+ console.log(chalk.red("Installation cancelled."));
195
+ return;
196
+ }
197
+ const currentDir = process.cwd();
198
+ const configPath = path.join(currentDir, "prisma-php.json");
199
+ if (fs.existsSync(configPath)) {
200
+ const localSettings = readJsonFile(configPath);
201
+ let excludeFiles = [];
202
+ localSettings.excludeFiles?.map((file) => {
203
+ const filePath = path.join(currentDir, file);
204
+ if (fs.existsSync(filePath))
205
+ excludeFiles.push(filePath.replace(/\\/g, "/"));
206
+ });
207
+ updateAnswer = {
208
+ projectName,
209
+ backendOnly: answer?.backendOnly ?? false,
210
+ swaggerDocs: answer?.swaggerDocs ?? false,
211
+ tailwindcss: answer?.tailwindcss ?? false,
212
+ websocket: answer?.websocket ?? false,
213
+ prisma: answer?.prisma ?? false,
214
+ docker: answer?.docker ?? false,
215
+ isUpdate: true,
216
+ excludeFiles: localSettings.excludeFiles ?? [],
217
+ excludeFilePath: excludeFiles ?? [],
218
+ filePath: currentDir,
219
+ };
220
+ }
221
+ } else {
222
+ answer = await getAnswer();
223
+ }
224
+ if (answer === null) {
225
+ console.warn(chalk.red("Installation cancelled."));
226
+ return;
227
+ }
228
+ const latestVersionOfCreatePrismaPhpApp = await fetchPackageVersion(
229
+ "create-prisma-php-app"
230
+ );
231
+ const isCreatePrismaPhpAppInstalled = getInstalledPackageVersion(
232
+ "create-prisma-php-app"
233
+ );
234
+ if (isCreatePrismaPhpAppInstalled) {
235
+ if (
236
+ compareVersions(
237
+ isCreatePrismaPhpAppInstalled,
238
+ latestVersionOfCreatePrismaPhpApp
239
+ ) === -1
240
+ ) {
241
+ execSync("npm uninstall -g create-prisma-php-app", {
242
+ stdio: "inherit",
243
+ });
244
+ execSync("npm install -g create-prisma-php-app", {
245
+ stdio: "inherit",
246
+ });
247
+ }
248
+ } else {
249
+ execSync("npm install -g create-prisma-php-app", { stdio: "inherit" });
250
+ }
251
+ // Create the project directory
252
+ if (!projectName) fs.mkdirSync(answer.projectName);
253
+ const currentDir = process.cwd();
254
+ let projectPath = projectName
255
+ ? currentDir
256
+ : path.join(currentDir, answer.projectName);
257
+ if (!projectName) process.chdir(answer.projectName);
258
+ let npmDependencies = [
259
+ npmPkg("typescript"),
260
+ npmPkg("@types/node"),
261
+ npmPkg("tsx"),
262
+ npmPkg("http-proxy-middleware"),
263
+ npmPkg("chalk"),
264
+ npmPkg("npm-run-all"),
265
+ npmPkg("browser-sync"),
266
+ npmPkg("@types/browser-sync"),
267
+ npmPkg("php-parser"),
268
+ ];
269
+ let composerDependencies = [
270
+ composerPkg("vlucas/phpdotenv"),
271
+ composerPkg("firebase/php-jwt"),
272
+ composerPkg("phpmailer/phpmailer"),
273
+ composerPkg("guzzlehttp/guzzle"),
274
+ composerPkg("ezyang/htmlpurifier"),
275
+ composerPkg("symfony/uid"),
276
+ composerPkg("brick/math"),
277
+ composerPkg("tsnc/prisma-php"),
278
+ ];
279
+ if (answer.swaggerDocs) {
280
+ npmDependencies.push(
281
+ npmPkg("swagger-jsdoc"),
282
+ npmPkg("@types/swagger-jsdoc")
283
+ );
284
+ }
285
+ if (answer.swaggerDocs && answer.prisma) {
286
+ npmDependencies.push(npmPkg("prompts"), npmPkg("@types/prompts"));
287
+ }
288
+ if (answer.tailwindcss) {
289
+ npmDependencies.push(
290
+ npmPkg("tailwindcss"),
291
+ npmPkg("postcss"),
292
+ npmPkg("postcss-cli"),
293
+ npmPkg("@tailwindcss/postcss"),
294
+ npmPkg("cssnano")
295
+ );
296
+ }
297
+ if (answer.websocket) {
298
+ npmDependencies.push(npmPkg("chokidar-cli"));
299
+ composerDependencies.push("cboden/ratchet");
300
+ }
301
+ if (answer.prisma) {
302
+ execSync("npm install -g prisma-client-php", { stdio: "inherit" });
303
+ }
304
+ await installNpmDependencies(projectPath, npmDependencies, true);
305
+ await installComposerDependencies(projectPath, composerDependencies);
306
+ if (!projectName) {
307
+ execSync("npx tsc --init", { stdio: "inherit" });
308
+ }
309
+ await createDirectoryStructure(projectPath, answer);
310
+ if (answer.prisma) {
311
+ execSync("npx ppo init --prisma-php", { stdio: "inherit" });
312
+ }
313
+ if (answer.swaggerDocs) {
314
+ const swaggerDocsPath = path.join(
315
+ projectPath,
316
+ "src",
317
+ "app",
318
+ "swagger-docs"
319
+ );
320
+ // Check if the directory exists
321
+ if (fs.existsSync(swaggerDocsPath)) {
322
+ // If it exists and is not empty, remove it before cloning
323
+ if (fs.readdirSync(swaggerDocsPath).length > 0) {
324
+ console.log("Removing existing swagger-docs directory...");
325
+ fs.rmSync(swaggerDocsPath, { recursive: true, force: true });
158
326
  }
159
- else {
160
- execSync("npm install -g create-prisma-php-app", { stdio: "inherit" });
327
+ }
328
+ // Clone the Git repository into the swagger-docs directory
329
+ execSync(
330
+ `git clone https://github.com/TheSteelNinjaCode/prisma-php-swagger-docs.git ${swaggerDocsPath}`,
331
+ { stdio: "inherit" }
332
+ );
333
+ // delete the folder .git
334
+ fs.rmSync(path.join(swaggerDocsPath, ".git"), {
335
+ recursive: true,
336
+ force: true,
337
+ });
338
+ }
339
+ if (updateAnswer?.isUpdate) {
340
+ const updateUninstallNpmDependencies = [];
341
+ const updateUninstallComposerDependencies = [];
342
+ if (updateAnswer.backendOnly) {
343
+ nonBackendFiles.forEach((file) => {
344
+ const filePath = path.join(projectPath, "src", "app", file);
345
+ if (fs.existsSync(filePath)) {
346
+ fs.unlinkSync(filePath); // Delete each file if it exists
347
+ console.log(`${file} was deleted successfully.`);
348
+ } else {
349
+ console.log(`${file} does not exist.`);
350
+ }
351
+ });
352
+ const backendOnlyFolders = ["js", "css"];
353
+ backendOnlyFolders.forEach((folder) => {
354
+ const folderPath = path.join(projectPath, "src", "app", folder);
355
+ if (fs.existsSync(folderPath)) {
356
+ fs.rmSync(folderPath, { recursive: true, force: true }); // Use fs.rmSync instead of fs.rmdirSync
357
+ console.log(`${folder} was deleted successfully.`);
358
+ } else {
359
+ console.log(`${folder} does not exist.`);
360
+ }
361
+ });
362
+ }
363
+ if (!updateAnswer.swaggerDocs) {
364
+ const swaggerDocsFolder = path.join(
365
+ projectPath,
366
+ "src",
367
+ "app",
368
+ "swagger-docs"
369
+ );
370
+ if (fs.existsSync(swaggerDocsFolder)) {
371
+ fs.rmSync(swaggerDocsFolder, { recursive: true, force: true }); // Use fs.rmSync instead of fs.rmdirSync
372
+ console.log(`swagger-docs was deleted successfully.`);
161
373
  }
162
- // Create the project directory
163
- if (!projectName)
164
- fs.mkdirSync(answer.projectName);
165
- const currentDir = process.cwd();
166
- let projectPath = projectName
167
- ? currentDir
168
- : path.join(currentDir, answer.projectName);
169
- if (!projectName)
170
- process.chdir(answer.projectName);
171
- let npmDependencies = [
172
- npmPkg("typescript"),
173
- npmPkg("@types/node"),
174
- npmPkg("tsx"),
175
- npmPkg("http-proxy-middleware"),
176
- npmPkg("chalk"),
177
- npmPkg("npm-run-all"),
178
- npmPkg("browser-sync"),
179
- npmPkg("@types/browser-sync"),
180
- npmPkg("php-parser"),
181
- ];
182
- let composerDependencies = [
183
- composerPkg("vlucas/phpdotenv"),
184
- composerPkg("firebase/php-jwt"),
185
- composerPkg("phpmailer/phpmailer"),
186
- composerPkg("guzzlehttp/guzzle"),
187
- composerPkg("ezyang/htmlpurifier"),
188
- composerPkg("symfony/uid"),
189
- composerPkg("brick/math"),
190
- composerPkg("tsnc/prisma-php"),
374
+ const swaggerFiles = ["swagger-config.ts"];
375
+ swaggerFiles.forEach((file) => {
376
+ const filePath = path.join(projectPath, "settings", file);
377
+ if (fs.existsSync(filePath)) {
378
+ fs.unlinkSync(filePath); // Delete each file if it exists
379
+ console.log(`${file} was deleted successfully.`);
380
+ } else {
381
+ console.log(`${file} does not exist.`);
382
+ }
383
+ });
384
+ updateUninstallNpmDependencies.push(
385
+ "swagger-jsdoc",
386
+ "@types/swagger-jsdoc",
387
+ "prompts",
388
+ "@types/prompts"
389
+ );
390
+ }
391
+ if (!updateAnswer.tailwindcss) {
392
+ const tailwindFiles = ["postcss.config.js"];
393
+ tailwindFiles.forEach((file) => {
394
+ const filePath = path.join(projectPath, file);
395
+ if (fs.existsSync(filePath)) {
396
+ fs.unlinkSync(filePath); // Delete each file if it exists
397
+ console.log(`${file} was deleted successfully.`);
398
+ } else {
399
+ console.log(`${file} does not exist.`);
400
+ }
401
+ });
402
+ updateUninstallNpmDependencies.push(
403
+ "tailwindcss",
404
+ "postcss",
405
+ "postcss-cli",
406
+ "@tailwindcss/postcss",
407
+ "cssnano"
408
+ );
409
+ }
410
+ if (!updateAnswer.websocket) {
411
+ const websocketFiles = [
412
+ "restart-websocket.ts",
413
+ "restart-websocket.bat",
191
414
  ];
192
- if (answer.swaggerDocs) {
193
- npmDependencies.push(npmPkg("swagger-jsdoc"), npmPkg("@types/swagger-jsdoc"));
194
- }
195
- if (answer.swaggerDocs && answer.prisma) {
196
- npmDependencies.push(npmPkg("prompts"), npmPkg("@types/prompts"));
197
- }
198
- if (answer.tailwindcss) {
199
- npmDependencies.push(npmPkg("tailwindcss"), npmPkg("postcss"), npmPkg("postcss-cli"), npmPkg("@tailwindcss/postcss"), npmPkg("cssnano"));
200
- }
201
- if (answer.websocket) {
202
- npmDependencies.push(npmPkg("chokidar-cli"));
203
- composerDependencies.push("cboden/ratchet");
204
- }
205
- if (answer.prisma) {
206
- execSync("npm install -g prisma-client-php", { stdio: "inherit" });
207
- }
208
- await installNpmDependencies(projectPath, npmDependencies, true);
209
- await installComposerDependencies(projectPath, composerDependencies);
210
- if (!projectName) {
211
- execSync("npx tsc --init", { stdio: "inherit" });
212
- }
213
- await createDirectoryStructure(projectPath, answer);
214
- if (answer.prisma) {
215
- execSync("npx ppo init --prisma-php", { stdio: "inherit" });
216
- }
217
- if (answer.swaggerDocs) {
218
- const swaggerDocsPath = path.join(projectPath, "src", "app", "swagger-docs");
219
- // Check if the directory exists
220
- if (fs.existsSync(swaggerDocsPath)) {
221
- // If it exists and is not empty, remove it before cloning
222
- if (fs.readdirSync(swaggerDocsPath).length > 0) {
223
- console.log("Removing existing swagger-docs directory...");
224
- fs.rmSync(swaggerDocsPath, { recursive: true, force: true });
225
- }
226
- }
227
- // Clone the Git repository into the swagger-docs directory
228
- execSync(`git clone https://github.com/TheSteelNinjaCode/prisma-php-swagger-docs.git ${swaggerDocsPath}`, { stdio: "inherit" });
229
- // delete the folder .git
230
- fs.rmSync(path.join(swaggerDocsPath, ".git"), {
231
- recursive: true,
232
- force: true,
233
- });
234
- }
235
- if (updateAnswer?.isUpdate) {
236
- const updateUninstallNpmDependencies = [];
237
- const updateUninstallComposerDependencies = [];
238
- if (updateAnswer.backendOnly) {
239
- nonBackendFiles.forEach((file) => {
240
- const filePath = path.join(projectPath, "src", "app", file);
241
- if (fs.existsSync(filePath)) {
242
- fs.unlinkSync(filePath); // Delete each file if it exists
243
- console.log(`${file} was deleted successfully.`);
244
- }
245
- else {
246
- console.log(`${file} does not exist.`);
247
- }
248
- });
249
- const backendOnlyFolders = ["js", "css"];
250
- backendOnlyFolders.forEach((folder) => {
251
- const folderPath = path.join(projectPath, "src", "app", folder);
252
- if (fs.existsSync(folderPath)) {
253
- fs.rmSync(folderPath, { recursive: true, force: true }); // Use fs.rmSync instead of fs.rmdirSync
254
- console.log(`${folder} was deleted successfully.`);
255
- }
256
- else {
257
- console.log(`${folder} does not exist.`);
258
- }
259
- });
260
- }
261
- if (!updateAnswer.swaggerDocs) {
262
- const swaggerDocsFolder = path.join(projectPath, "src", "app", "swagger-docs");
263
- if (fs.existsSync(swaggerDocsFolder)) {
264
- fs.rmSync(swaggerDocsFolder, { recursive: true, force: true }); // Use fs.rmSync instead of fs.rmdirSync
265
- console.log(`swagger-docs was deleted successfully.`);
266
- }
267
- const swaggerFiles = ["swagger-config.ts"];
268
- swaggerFiles.forEach((file) => {
269
- const filePath = path.join(projectPath, "settings", file);
270
- if (fs.existsSync(filePath)) {
271
- fs.unlinkSync(filePath); // Delete each file if it exists
272
- console.log(`${file} was deleted successfully.`);
273
- }
274
- else {
275
- console.log(`${file} does not exist.`);
276
- }
277
- });
278
- updateUninstallNpmDependencies.push("swagger-jsdoc", "@types/swagger-jsdoc", "prompts", "@types/prompts");
279
- }
280
- if (!updateAnswer.tailwindcss) {
281
- const tailwindFiles = ["postcss.config.js"];
282
- tailwindFiles.forEach((file) => {
283
- const filePath = path.join(projectPath, file);
284
- if (fs.existsSync(filePath)) {
285
- fs.unlinkSync(filePath); // Delete each file if it exists
286
- console.log(`${file} was deleted successfully.`);
287
- }
288
- else {
289
- console.log(`${file} does not exist.`);
290
- }
291
- });
292
- updateUninstallNpmDependencies.push("tailwindcss", "postcss", "postcss-cli", "@tailwindcss/postcss", "cssnano");
293
- }
294
- if (!updateAnswer.websocket) {
295
- const websocketFiles = [
296
- "restart-websocket.ts",
297
- "restart-websocket.bat",
298
- ];
299
- websocketFiles.forEach((file) => {
300
- const filePath = path.join(projectPath, "settings", file);
301
- if (fs.existsSync(filePath)) {
302
- fs.unlinkSync(filePath); // Delete each file if it exists
303
- console.log(`${file} was deleted successfully.`);
304
- }
305
- else {
306
- console.log(`${file} does not exist.`);
307
- }
308
- });
309
- const websocketFolder = path.join(projectPath, "src", "Lib", "Websocket");
310
- if (fs.existsSync(websocketFolder)) {
311
- fs.rmSync(websocketFolder, { recursive: true, force: true }); // Use fs.rmSync instead of fs.rmdirSync
312
- console.log(`Websocket folder was deleted successfully.`);
313
- }
314
- updateUninstallNpmDependencies.push("chokidar-cli");
315
- updateUninstallComposerDependencies.push("cboden/ratchet");
316
- }
317
- if (!updateAnswer.prisma) {
318
- updateUninstallNpmDependencies.push("prisma", "@prisma/client", "@prisma/internals");
319
- }
320
- if (!updateAnswer.docker) {
321
- const dockerFiles = [
322
- ".dockerignore",
323
- "docker-compose.yml",
324
- "Dockerfile",
325
- "apache.conf",
326
- ];
327
- dockerFiles.forEach((file) => {
328
- const filePath = path.join(projectPath, file);
329
- if (fs.existsSync(filePath)) {
330
- fs.unlinkSync(filePath); // Delete each file if it exists
331
- console.log(`${file} was deleted successfully.`);
332
- }
333
- else {
334
- console.log(`${file} does not exist.`);
335
- }
336
- });
337
- }
338
- if (updateUninstallNpmDependencies.length > 0) {
339
- await uninstallNpmDependencies(projectPath, updateUninstallNpmDependencies, true);
340
- }
341
- if (updateUninstallComposerDependencies.length > 0) {
342
- await uninstallComposerDependencies(projectPath, updateUninstallComposerDependencies);
343
- }
415
+ websocketFiles.forEach((file) => {
416
+ const filePath = path.join(projectPath, "settings", file);
417
+ if (fs.existsSync(filePath)) {
418
+ fs.unlinkSync(filePath); // Delete each file if it exists
419
+ console.log(`${file} was deleted successfully.`);
420
+ } else {
421
+ console.log(`${file} does not exist.`);
422
+ }
423
+ });
424
+ const websocketFolder = path.join(
425
+ projectPath,
426
+ "src",
427
+ "Lib",
428
+ "Websocket"
429
+ );
430
+ if (fs.existsSync(websocketFolder)) {
431
+ fs.rmSync(websocketFolder, { recursive: true, force: true }); // Use fs.rmSync instead of fs.rmdirSync
432
+ console.log(`Websocket folder was deleted successfully.`);
344
433
  }
345
- const projectPathModified = projectPath.replace(/\\/g, "\\");
346
- const bsConfig = bsConfigUrls(projectPathModified);
347
- const prismaPhpConfig = {
348
- projectName: answer.projectName,
349
- projectRootPath: projectPathModified,
350
- phpEnvironment: "XAMPP",
351
- phpRootPathExe: "C:\\xampp\\php\\php.exe",
352
- phpGenerateClassPath: "src/Lib/Prisma/Classes",
353
- bsTarget: bsConfig.bsTarget,
354
- bsPathRewrite: bsConfig.bsPathRewrite,
355
- backendOnly: answer.backendOnly,
356
- swaggerDocs: answer.swaggerDocs,
357
- tailwindcss: answer.tailwindcss,
358
- websocket: answer.websocket,
359
- prisma: answer.prisma,
360
- docker: answer.docker,
361
- version: latestVersionOfCreatePrismaPhpApp,
362
- excludeFiles: updateAnswer?.excludeFiles ?? [],
363
- };
364
- fs.writeFileSync(path.join(projectPath, "prisma-php.json"), JSON.stringify(prismaPhpConfig, null, 2), { flag: "w" });
365
- if (updateAnswer?.isUpdate) {
366
- execSync("C:\\xampp\\php\\php.exe C:\\ProgramData\\ComposerSetup\\bin\\composer.phar update", {
367
- stdio: "inherit",
368
- });
434
+ updateUninstallNpmDependencies.push("chokidar-cli");
435
+ updateUninstallComposerDependencies.push("cboden/ratchet");
436
+ }
437
+ if (!updateAnswer.prisma) {
438
+ updateUninstallNpmDependencies.push(
439
+ "prisma",
440
+ "@prisma/client",
441
+ "@prisma/internals"
442
+ );
443
+ }
444
+ if (!updateAnswer.docker) {
445
+ const dockerFiles = [
446
+ ".dockerignore",
447
+ "docker-compose.yml",
448
+ "Dockerfile",
449
+ "apache.conf",
450
+ ];
451
+ dockerFiles.forEach((file) => {
452
+ const filePath = path.join(projectPath, file);
453
+ if (fs.existsSync(filePath)) {
454
+ fs.unlinkSync(filePath); // Delete each file if it exists
455
+ console.log(`${file} was deleted successfully.`);
456
+ } else {
457
+ console.log(`${file} does not exist.`);
458
+ }
459
+ });
460
+ }
461
+ if (updateUninstallNpmDependencies.length > 0) {
462
+ await uninstallNpmDependencies(
463
+ projectPath,
464
+ updateUninstallNpmDependencies,
465
+ true
466
+ );
467
+ }
468
+ if (updateUninstallComposerDependencies.length > 0) {
469
+ await uninstallComposerDependencies(
470
+ projectPath,
471
+ updateUninstallComposerDependencies
472
+ );
473
+ }
474
+ }
475
+ const projectPathModified = projectPath.replace(/\\/g, "\\");
476
+ const bsConfig = bsConfigUrls(projectPathModified);
477
+ const prismaPhpConfig = {
478
+ projectName: answer.projectName,
479
+ projectRootPath: projectPathModified,
480
+ phpEnvironment: "XAMPP",
481
+ phpRootPathExe: "C:\\xampp\\php\\php.exe",
482
+ phpGenerateClassPath: "src/Lib/Prisma/Classes",
483
+ bsTarget: bsConfig.bsTarget,
484
+ bsPathRewrite: bsConfig.bsPathRewrite,
485
+ backendOnly: answer.backendOnly,
486
+ swaggerDocs: answer.swaggerDocs,
487
+ tailwindcss: answer.tailwindcss,
488
+ websocket: answer.websocket,
489
+ prisma: answer.prisma,
490
+ docker: answer.docker,
491
+ version: latestVersionOfCreatePrismaPhpApp,
492
+ excludeFiles: updateAnswer?.excludeFiles ?? [],
493
+ };
494
+ fs.writeFileSync(
495
+ path.join(projectPath, "prisma-php.json"),
496
+ JSON.stringify(prismaPhpConfig, null, 2),
497
+ { flag: "w" }
498
+ );
499
+ if (updateAnswer?.isUpdate) {
500
+ execSync(
501
+ "C:\\xampp\\php\\php.exe C:\\ProgramData\\ComposerSetup\\bin\\composer.phar update",
502
+ {
503
+ stdio: "inherit",
369
504
  }
370
- else {
371
- execSync("C:\\xampp\\php\\php.exe C:\\ProgramData\\ComposerSetup\\bin\\composer.phar install", {
372
- stdio: "inherit",
373
- });
505
+ );
506
+ } else {
507
+ execSync(
508
+ "C:\\xampp\\php\\php.exe C:\\ProgramData\\ComposerSetup\\bin\\composer.phar install",
509
+ {
510
+ stdio: "inherit",
374
511
  }
375
- console.log("\n=========================\n");
376
- console.log(`${chalk.green("Success!")} Prisma PHP project successfully created in ${chalk.green(`${currentDir.replace(/\\/g, "/")}/${answer.projectName}`)}!`);
377
- console.log("\n=========================");
378
- }
379
- catch (error) {
380
- console.error("Error while creating the project:", error);
381
- process.exit(1);
512
+ );
382
513
  }
514
+ console.log("\n=========================\n");
515
+ console.log(
516
+ `${chalk.green(
517
+ "Success!"
518
+ )} Prisma PHP project successfully created in ${chalk.green(
519
+ `${currentDir.replace(/\\/g, "/")}/${answer.projectName}`
520
+ )}!`
521
+ );
522
+ console.log("\n=========================");
523
+ } catch (error) {
524
+ console.error("Error while creating the project:", error);
525
+ process.exit(1);
526
+ }
383
527
  }
384
528
  main();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-prisma-php-app",
3
- "version": "4.0.0-alpha.11",
3
+ "version": "4.0.0-alpha.13",
4
4
  "description": "Prisma-PHP: A Revolutionary Library Bridging PHP with Prisma ORM",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",