create-prisma-php-app 2.0.8 → 2.0.10
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 +345 -412
- 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"},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.dev=`npm-run-all projectName -p browserSync ${c.join(" ")}`,n.scripts=o,n.type="module",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)}n.autoload={"psr-4":{"":"src/"}},n.name=s.projectName,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")}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/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),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=`# Prisma PHP Auth Secret Key\nAUTH_SECRET="${c}"\nAUTH_COOKIE_NAME="${generateHexEncodedKey(8)}"\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"\n\n# APP CACHE ENABLED - Set to true to enable caching - Default is false\nCACHE_ENABLED="false"\n# APP CACHE TTL - Set the cache time to live in seconds - Default is 600 seconds (10 minutes)\nCACHE_TTL="600"\n\n# LOCAL STORAGE KEY - Define a custom key for local storage.\n# If not set, it defaults to "pphp_local_store_59e13".\n# Spaces in the value will be replaced with underscores, and the key will be converted to lowercase automatically.\nLOCALSTORE_KEY="${o}"`;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||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:!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}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"},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.dev=`npm-run-all projectName -p browserSync ${c.join(" ")}`,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/"}},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/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=`# Prisma PHP Auth Secret Key\nAUTH_SECRET="${c}"\nAUTH_COOKIE_NAME="${generateHexEncodedKey(8)}"\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"\n\n# APP CACHE ENABLED - Set to true to enable caching - Default is false\nCACHE_ENABLED="false"\n# APP CACHE TTL - Set the cache time to live in seconds - Default is 600 seconds (10 minutes)\nCACHE_TTL="600"\n\n# LOCAL STORAGE KEY - Define a custom key for local storage.\n# If not set, it defaults to "pphp_local_store_59e13".\n# Spaces in the value will be replaced with underscores, and the key will be converted to lowercase automatically.\nLOCALSTORE_KEY="${o}"`;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||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:!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,436 +7,369 @@ 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
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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,
|
|
16
27
|
});
|
|
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
|
-
});
|
|
34
28
|
}
|
|
35
29
|
async function installComposerDependencies(baseDir, dependencies) {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
30
|
+
console.log("Initializing new Composer project...");
|
|
31
|
+
// Initialize a composer.json if it doesn't exist
|
|
32
|
+
if (!fs.existsSync(path.join(baseDir, "composer.json"))) {
|
|
33
|
+
execSync(`composer init -n --name="vendor/package" --require="php:^8.2"`, {
|
|
34
|
+
stdio: "inherit",
|
|
35
|
+
cwd: baseDir,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
// Log the dependencies being installed
|
|
39
|
+
console.log("Installing Composer dependencies:");
|
|
40
|
+
dependencies.forEach((dep) => console.log(`- ${chalk.blue(dep)}`));
|
|
41
|
+
// Prepare the composer require command
|
|
42
|
+
const composerRequireCommand = `C:\\xampp\\php\\php.exe C:\\ProgramData\\ComposerSetup\\bin\\composer.phar require ${dependencies.join(" ")}`;
|
|
43
|
+
// Execute the composer require command
|
|
44
|
+
execSync(composerRequireCommand, {
|
|
45
|
+
stdio: "inherit",
|
|
46
|
+
cwd: baseDir,
|
|
42
47
|
});
|
|
43
|
-
}
|
|
44
|
-
// Log the dependencies being installed
|
|
45
|
-
console.log("Installing Composer dependencies:");
|
|
46
|
-
dependencies.forEach((dep) => console.log(`- ${chalk.blue(dep)}`));
|
|
47
|
-
// Prepare the composer require command
|
|
48
|
-
const composerRequireCommand = `C:\\xampp\\php\\php.exe C:\\ProgramData\\ComposerSetup\\bin\\composer.phar require ${dependencies.join(
|
|
49
|
-
" "
|
|
50
|
-
)}`;
|
|
51
|
-
// Execute the composer require command
|
|
52
|
-
execSync(composerRequireCommand, {
|
|
53
|
-
stdio: "inherit",
|
|
54
|
-
cwd: baseDir,
|
|
55
|
-
});
|
|
56
48
|
}
|
|
57
49
|
const npmPinnedVersions = {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
50
|
+
"@tailwindcss/postcss": "^4.0.15",
|
|
51
|
+
"@types/browser-sync": "^2.29.0",
|
|
52
|
+
"@types/node": "^22.13.11",
|
|
53
|
+
"@types/prompts": "^2.4.9",
|
|
54
|
+
"browser-sync": "^3.0.3",
|
|
55
|
+
chalk: "^5.4.1",
|
|
56
|
+
"chokidar-cli": "^3.0.0",
|
|
57
|
+
cssnano: "^7.0.6",
|
|
58
|
+
"http-proxy-middleware": "^3.0.3",
|
|
59
|
+
"npm-run-all": "^4.1.5",
|
|
60
|
+
"php-parser": "^3.2.2",
|
|
61
|
+
postcss: "^8.5.3",
|
|
62
|
+
"postcss-cli": "^11.0.1",
|
|
63
|
+
prompts: "^2.4.2",
|
|
64
|
+
tailwindcss: "^4.0.15",
|
|
65
|
+
tsx: "^4.19.3",
|
|
66
|
+
typescript: "^5.8.2",
|
|
75
67
|
};
|
|
76
68
|
function npmPkg(name) {
|
|
77
|
-
|
|
69
|
+
return npmPinnedVersions[name] ? `${name}@${npmPinnedVersions[name]}` : name;
|
|
78
70
|
}
|
|
79
71
|
const composerPinnedVersions = {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
72
|
+
"vlucas/phpdotenv": "^5.6.1",
|
|
73
|
+
"firebase/php-jwt": "^6.10.2",
|
|
74
|
+
"phpmailer/phpmailer": "^6.9.3",
|
|
75
|
+
"guzzlehttp/guzzle": "^7.9.2",
|
|
76
|
+
"ezyang/htmlpurifier": "^4.18.0",
|
|
77
|
+
"symfony/uid": "^7.2.0",
|
|
78
|
+
"brick/math": "^0.13.0",
|
|
79
|
+
"cboden/ratchet": "^0.4.4",
|
|
88
80
|
};
|
|
89
81
|
function composerPkg(name) {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
82
|
+
return composerPinnedVersions[name]
|
|
83
|
+
? `${name}:${composerPinnedVersions[name]}`
|
|
84
|
+
: name;
|
|
93
85
|
}
|
|
94
86
|
async function main() {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
} else {
|
|
145
|
-
answer = await getAnswer();
|
|
146
|
-
}
|
|
147
|
-
if (answer === null) {
|
|
148
|
-
console.warn(chalk.red("Installation cancelled."));
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
const latestVersionOfCreatePrismaPhpApp = await fetchPackageVersion(
|
|
152
|
-
"create-prisma-php-app"
|
|
153
|
-
);
|
|
154
|
-
const isCreatePrismaPhpAppInstalled = getInstalledPackageVersion(
|
|
155
|
-
"create-prisma-php-app"
|
|
156
|
-
);
|
|
157
|
-
if (isCreatePrismaPhpAppInstalled) {
|
|
158
|
-
if (
|
|
159
|
-
compareVersions(
|
|
160
|
-
isCreatePrismaPhpAppInstalled,
|
|
161
|
-
latestVersionOfCreatePrismaPhpApp
|
|
162
|
-
) === -1
|
|
163
|
-
) {
|
|
164
|
-
execSync("npm uninstall -g create-prisma-php-app", {
|
|
165
|
-
stdio: "inherit",
|
|
166
|
-
});
|
|
167
|
-
execSync("npm install -g create-prisma-php-app", {
|
|
168
|
-
stdio: "inherit",
|
|
169
|
-
});
|
|
170
|
-
}
|
|
171
|
-
} else {
|
|
172
|
-
execSync("npm install -g create-prisma-php-app", { stdio: "inherit" });
|
|
173
|
-
}
|
|
174
|
-
// Create the project directory
|
|
175
|
-
if (!projectName) fs.mkdirSync(answer.projectName);
|
|
176
|
-
const currentDir = process.cwd();
|
|
177
|
-
let projectPath = projectName
|
|
178
|
-
? currentDir
|
|
179
|
-
: path.join(currentDir, answer.projectName);
|
|
180
|
-
if (!projectName) process.chdir(answer.projectName);
|
|
181
|
-
let npmDependencies = [
|
|
182
|
-
npmPkg("typescript"),
|
|
183
|
-
npmPkg("@types/node"),
|
|
184
|
-
npmPkg("tsx"),
|
|
185
|
-
npmPkg("http-proxy-middleware"),
|
|
186
|
-
npmPkg("chalk"),
|
|
187
|
-
npmPkg("npm-run-all"),
|
|
188
|
-
npmPkg("browser-sync"),
|
|
189
|
-
npmPkg("@types/browser-sync"),
|
|
190
|
-
npmPkg("php-parser"),
|
|
191
|
-
];
|
|
192
|
-
let composerDependencies = [
|
|
193
|
-
composerPkg("vlucas/phpdotenv"),
|
|
194
|
-
composerPkg("firebase/php-jwt"),
|
|
195
|
-
composerPkg("phpmailer/phpmailer"),
|
|
196
|
-
composerPkg("guzzlehttp/guzzle"),
|
|
197
|
-
composerPkg("ezyang/htmlpurifier"),
|
|
198
|
-
composerPkg("symfony/uid"),
|
|
199
|
-
composerPkg("brick/math"),
|
|
200
|
-
];
|
|
201
|
-
if (answer.swaggerDocs) {
|
|
202
|
-
npmDependencies.push(
|
|
203
|
-
npmPkg("swagger-jsdoc"),
|
|
204
|
-
npmPkg("@types/swagger-jsdoc")
|
|
205
|
-
);
|
|
206
|
-
}
|
|
207
|
-
if (answer.swaggerDocs && answer.prisma) {
|
|
208
|
-
npmDependencies.push(npmPkg("prompts"), npmPkg("@types/prompts"));
|
|
209
|
-
}
|
|
210
|
-
if (answer.tailwindcss) {
|
|
211
|
-
npmDependencies.push(
|
|
212
|
-
npmPkg("tailwindcss"),
|
|
213
|
-
npmPkg("postcss"),
|
|
214
|
-
npmPkg("postcss-cli"),
|
|
215
|
-
npmPkg("@tailwindcss/postcss"),
|
|
216
|
-
npmPkg("cssnano")
|
|
217
|
-
);
|
|
218
|
-
}
|
|
219
|
-
if (answer.websocket) {
|
|
220
|
-
npmDependencies.push(npmPkg("chokidar-cli"));
|
|
221
|
-
composerDependencies.push("cboden/ratchet");
|
|
222
|
-
}
|
|
223
|
-
if (answer.prisma) {
|
|
224
|
-
execSync("npm install -g prisma-client-php", { stdio: "inherit" });
|
|
225
|
-
}
|
|
226
|
-
await installNpmDependencies(projectPath, npmDependencies, true);
|
|
227
|
-
await installComposerDependencies(projectPath, composerDependencies);
|
|
228
|
-
if (!projectName) {
|
|
229
|
-
execSync("npx tsc --init", { stdio: "inherit" });
|
|
230
|
-
}
|
|
231
|
-
await createDirectoryStructure(projectPath, answer);
|
|
232
|
-
if (answer.prisma) {
|
|
233
|
-
execSync("npx ppo init --prisma-php", { stdio: "inherit" });
|
|
234
|
-
}
|
|
235
|
-
if (answer.swaggerDocs) {
|
|
236
|
-
const swaggerDocsPath = path.join(
|
|
237
|
-
projectPath,
|
|
238
|
-
"src",
|
|
239
|
-
"app",
|
|
240
|
-
"swagger-docs"
|
|
241
|
-
);
|
|
242
|
-
// Check if the directory exists
|
|
243
|
-
if (fs.existsSync(swaggerDocsPath)) {
|
|
244
|
-
// If it exists and is not empty, remove it before cloning
|
|
245
|
-
if (fs.readdirSync(swaggerDocsPath).length > 0) {
|
|
246
|
-
console.log("Removing existing swagger-docs directory...");
|
|
247
|
-
fs.rmSync(swaggerDocsPath, { recursive: true, force: true });
|
|
87
|
+
try {
|
|
88
|
+
const args = process.argv.slice(2);
|
|
89
|
+
let projectName = args[0];
|
|
90
|
+
let answer = null;
|
|
91
|
+
if (projectName) {
|
|
92
|
+
let useBackendOnly = args.includes("--backend-only");
|
|
93
|
+
let useSwaggerDocs = args.includes("--swagger-docs");
|
|
94
|
+
let useTailwind = args.includes("--tailwindcss");
|
|
95
|
+
let useWebsocket = args.includes("--websocket");
|
|
96
|
+
let usePrisma = args.includes("--prisma");
|
|
97
|
+
let useDocker = args.includes("--docker");
|
|
98
|
+
const predefinedAnswers = {
|
|
99
|
+
projectName,
|
|
100
|
+
backendOnly: useBackendOnly,
|
|
101
|
+
swaggerDocs: useSwaggerDocs,
|
|
102
|
+
tailwindcss: useTailwind,
|
|
103
|
+
websocket: useWebsocket,
|
|
104
|
+
prisma: usePrisma,
|
|
105
|
+
docker: useDocker,
|
|
106
|
+
};
|
|
107
|
+
answer = await getAnswer(predefinedAnswers);
|
|
108
|
+
if (answer === null) {
|
|
109
|
+
console.log(chalk.red("Installation cancelled."));
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const currentDir = process.cwd();
|
|
113
|
+
const configPath = path.join(currentDir, "prisma-php.json");
|
|
114
|
+
if (fs.existsSync(configPath)) {
|
|
115
|
+
const localSettings = readJsonFile(configPath);
|
|
116
|
+
let excludeFiles = [];
|
|
117
|
+
localSettings.excludeFiles?.map((file) => {
|
|
118
|
+
const filePath = path.join(currentDir, file);
|
|
119
|
+
if (fs.existsSync(filePath))
|
|
120
|
+
excludeFiles.push(filePath.replace(/\\/g, "/"));
|
|
121
|
+
});
|
|
122
|
+
updateAnswer = {
|
|
123
|
+
projectName,
|
|
124
|
+
backendOnly: answer?.backendOnly ?? false,
|
|
125
|
+
swaggerDocs: answer?.swaggerDocs ?? false,
|
|
126
|
+
tailwindcss: answer?.tailwindcss ?? false,
|
|
127
|
+
websocket: answer?.websocket ?? false,
|
|
128
|
+
prisma: answer?.prisma ?? false,
|
|
129
|
+
docker: answer?.docker ?? false,
|
|
130
|
+
isUpdate: true,
|
|
131
|
+
excludeFiles: localSettings.excludeFiles ?? [],
|
|
132
|
+
excludeFilePath: excludeFiles ?? [],
|
|
133
|
+
filePath: currentDir,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
248
136
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
execSync(
|
|
252
|
-
`git clone https://github.com/TheSteelNinjaCode/prisma-php-swagger-docs.git ${swaggerDocsPath}`,
|
|
253
|
-
{ stdio: "inherit" }
|
|
254
|
-
);
|
|
255
|
-
// delete the folder .git
|
|
256
|
-
fs.rmSync(path.join(swaggerDocsPath, ".git"), {
|
|
257
|
-
recursive: true,
|
|
258
|
-
force: true,
|
|
259
|
-
});
|
|
260
|
-
}
|
|
261
|
-
if (updateAnswer?.isUpdate) {
|
|
262
|
-
const updateUninstallNpmDependencies = [];
|
|
263
|
-
const updateUninstallComposerDependencies = [];
|
|
264
|
-
if (updateAnswer.backendOnly) {
|
|
265
|
-
nonBackendFiles.forEach((file) => {
|
|
266
|
-
const filePath = path.join(projectPath, "src", "app", file);
|
|
267
|
-
if (fs.existsSync(filePath)) {
|
|
268
|
-
fs.unlinkSync(filePath); // Delete each file if it exists
|
|
269
|
-
console.log(`${file} was deleted successfully.`);
|
|
270
|
-
} else {
|
|
271
|
-
console.log(`${file} does not exist.`);
|
|
272
|
-
}
|
|
273
|
-
});
|
|
274
|
-
const backendOnlyFolders = ["js", "css"];
|
|
275
|
-
backendOnlyFolders.forEach((folder) => {
|
|
276
|
-
const folderPath = path.join(projectPath, "src", "app", folder);
|
|
277
|
-
if (fs.existsSync(folderPath)) {
|
|
278
|
-
fs.rmSync(folderPath, { recursive: true, force: true }); // Use fs.rmSync instead of fs.rmdirSync
|
|
279
|
-
console.log(`${folder} was deleted successfully.`);
|
|
280
|
-
} else {
|
|
281
|
-
console.log(`${folder} does not exist.`);
|
|
282
|
-
}
|
|
283
|
-
});
|
|
284
|
-
}
|
|
285
|
-
if (!updateAnswer.swaggerDocs) {
|
|
286
|
-
const swaggerDocsFolder = path.join(
|
|
287
|
-
projectPath,
|
|
288
|
-
"src",
|
|
289
|
-
"app",
|
|
290
|
-
"swagger-docs"
|
|
291
|
-
);
|
|
292
|
-
if (fs.existsSync(swaggerDocsFolder)) {
|
|
293
|
-
fs.rmSync(swaggerDocsFolder, { recursive: true, force: true }); // Use fs.rmSync instead of fs.rmdirSync
|
|
294
|
-
console.log(`swagger-docs was deleted successfully.`);
|
|
137
|
+
else {
|
|
138
|
+
answer = await getAnswer();
|
|
295
139
|
}
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
);
|
|
312
|
-
}
|
|
313
|
-
if (!updateAnswer.tailwindcss) {
|
|
314
|
-
const tailwindFiles = ["postcss.config.js"];
|
|
315
|
-
tailwindFiles.forEach((file) => {
|
|
316
|
-
const filePath = path.join(projectPath, file);
|
|
317
|
-
if (fs.existsSync(filePath)) {
|
|
318
|
-
fs.unlinkSync(filePath); // Delete each file if it exists
|
|
319
|
-
console.log(`${file} was deleted successfully.`);
|
|
320
|
-
} else {
|
|
321
|
-
console.log(`${file} does not exist.`);
|
|
322
|
-
}
|
|
323
|
-
});
|
|
324
|
-
updateUninstallNpmDependencies.push(
|
|
325
|
-
"tailwindcss",
|
|
326
|
-
"postcss",
|
|
327
|
-
"postcss-cli",
|
|
328
|
-
"@tailwindcss/postcss",
|
|
329
|
-
"cssnano"
|
|
330
|
-
);
|
|
331
|
-
}
|
|
332
|
-
if (!updateAnswer.websocket) {
|
|
333
|
-
const websocketFiles = [
|
|
334
|
-
"restart-websocket.ts",
|
|
335
|
-
"restart-websocket.bat",
|
|
336
|
-
];
|
|
337
|
-
websocketFiles.forEach((file) => {
|
|
338
|
-
const filePath = path.join(projectPath, "settings", file);
|
|
339
|
-
if (fs.existsSync(filePath)) {
|
|
340
|
-
fs.unlinkSync(filePath); // Delete each file if it exists
|
|
341
|
-
console.log(`${file} was deleted successfully.`);
|
|
342
|
-
} else {
|
|
343
|
-
console.log(`${file} does not exist.`);
|
|
344
|
-
}
|
|
345
|
-
});
|
|
346
|
-
const websocketFolder = path.join(
|
|
347
|
-
projectPath,
|
|
348
|
-
"src",
|
|
349
|
-
"Lib",
|
|
350
|
-
"Websocket"
|
|
351
|
-
);
|
|
352
|
-
if (fs.existsSync(websocketFolder)) {
|
|
353
|
-
fs.rmSync(websocketFolder, { recursive: true, force: true }); // Use fs.rmSync instead of fs.rmdirSync
|
|
354
|
-
console.log(`Websocket folder was deleted successfully.`);
|
|
140
|
+
if (answer === null) {
|
|
141
|
+
console.warn(chalk.red("Installation cancelled."));
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const latestVersionOfCreatePrismaPhpApp = await fetchPackageVersion("create-prisma-php-app");
|
|
145
|
+
const isCreatePrismaPhpAppInstalled = getInstalledPackageVersion("create-prisma-php-app");
|
|
146
|
+
if (isCreatePrismaPhpAppInstalled) {
|
|
147
|
+
if (compareVersions(isCreatePrismaPhpAppInstalled, latestVersionOfCreatePrismaPhpApp) === -1) {
|
|
148
|
+
execSync("npm uninstall -g create-prisma-php-app", {
|
|
149
|
+
stdio: "inherit",
|
|
150
|
+
});
|
|
151
|
+
execSync("npm install -g create-prisma-php-app", {
|
|
152
|
+
stdio: "inherit",
|
|
153
|
+
});
|
|
154
|
+
}
|
|
355
155
|
}
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
156
|
+
else {
|
|
157
|
+
execSync("npm install -g create-prisma-php-app", { stdio: "inherit" });
|
|
158
|
+
}
|
|
159
|
+
// Create the project directory
|
|
160
|
+
if (!projectName)
|
|
161
|
+
fs.mkdirSync(answer.projectName);
|
|
162
|
+
const currentDir = process.cwd();
|
|
163
|
+
let projectPath = projectName
|
|
164
|
+
? currentDir
|
|
165
|
+
: path.join(currentDir, answer.projectName);
|
|
166
|
+
if (!projectName)
|
|
167
|
+
process.chdir(answer.projectName);
|
|
168
|
+
console.log("🚀 ~ main ~ projectPath:", projectPath);
|
|
169
|
+
let npmDependencies = [
|
|
170
|
+
npmPkg("typescript"),
|
|
171
|
+
npmPkg("@types/node"),
|
|
172
|
+
npmPkg("tsx"),
|
|
173
|
+
npmPkg("http-proxy-middleware"),
|
|
174
|
+
npmPkg("chalk"),
|
|
175
|
+
npmPkg("npm-run-all"),
|
|
176
|
+
npmPkg("browser-sync"),
|
|
177
|
+
npmPkg("@types/browser-sync"),
|
|
178
|
+
npmPkg("php-parser"),
|
|
372
179
|
];
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
true
|
|
388
|
-
);
|
|
389
|
-
}
|
|
390
|
-
if (updateUninstallComposerDependencies.length > 0) {
|
|
391
|
-
await uninstallComposerDependencies(
|
|
392
|
-
projectPath,
|
|
393
|
-
updateUninstallComposerDependencies
|
|
394
|
-
);
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
const projectPathModified = projectPath.replace(/\\/g, "\\");
|
|
398
|
-
const bsConfig = bsConfigUrls(projectPathModified);
|
|
399
|
-
const prismaPhpConfig = {
|
|
400
|
-
projectName: answer.projectName,
|
|
401
|
-
projectRootPath: projectPathModified,
|
|
402
|
-
phpEnvironment: "XAMPP",
|
|
403
|
-
phpRootPathExe: "C:\\xampp\\php\\php.exe",
|
|
404
|
-
bsTarget: bsConfig.bsTarget,
|
|
405
|
-
bsPathRewrite: bsConfig.bsPathRewrite,
|
|
406
|
-
backendOnly: answer.backendOnly,
|
|
407
|
-
swaggerDocs: answer.swaggerDocs,
|
|
408
|
-
tailwindcss: answer.tailwindcss,
|
|
409
|
-
websocket: answer.websocket,
|
|
410
|
-
prisma: answer.prisma,
|
|
411
|
-
docker: answer.docker,
|
|
412
|
-
version: latestVersionOfCreatePrismaPhpApp,
|
|
413
|
-
excludeFiles: updateAnswer?.excludeFiles ?? [],
|
|
414
|
-
};
|
|
415
|
-
fs.writeFileSync(
|
|
416
|
-
path.join(projectPath, "prisma-php.json"),
|
|
417
|
-
JSON.stringify(prismaPhpConfig, null, 2),
|
|
418
|
-
{ flag: "w" }
|
|
419
|
-
);
|
|
420
|
-
if (updateAnswer?.isUpdate) {
|
|
421
|
-
execSync(
|
|
422
|
-
"C:\\xampp\\php\\php.exe C:\\ProgramData\\ComposerSetup\\bin\\composer.phar update",
|
|
423
|
-
{
|
|
424
|
-
stdio: "inherit",
|
|
180
|
+
let composerDependencies = [
|
|
181
|
+
composerPkg("vlucas/phpdotenv"),
|
|
182
|
+
composerPkg("firebase/php-jwt"),
|
|
183
|
+
composerPkg("phpmailer/phpmailer"),
|
|
184
|
+
composerPkg("guzzlehttp/guzzle"),
|
|
185
|
+
composerPkg("ezyang/htmlpurifier"),
|
|
186
|
+
composerPkg("symfony/uid"),
|
|
187
|
+
composerPkg("brick/math"),
|
|
188
|
+
];
|
|
189
|
+
if (answer.swaggerDocs) {
|
|
190
|
+
npmDependencies.push(npmPkg("swagger-jsdoc"), npmPkg("@types/swagger-jsdoc"));
|
|
191
|
+
}
|
|
192
|
+
if (answer.swaggerDocs && answer.prisma) {
|
|
193
|
+
npmDependencies.push(npmPkg("prompts"), npmPkg("@types/prompts"));
|
|
425
194
|
}
|
|
426
|
-
|
|
195
|
+
if (answer.tailwindcss) {
|
|
196
|
+
npmDependencies.push(npmPkg("tailwindcss"), npmPkg("postcss"), npmPkg("postcss-cli"), npmPkg("@tailwindcss/postcss"), npmPkg("cssnano"));
|
|
197
|
+
}
|
|
198
|
+
if (answer.websocket) {
|
|
199
|
+
npmDependencies.push(npmPkg("chokidar-cli"));
|
|
200
|
+
composerDependencies.push("cboden/ratchet");
|
|
201
|
+
}
|
|
202
|
+
if (answer.prisma) {
|
|
203
|
+
execSync("npm install -g prisma-client-php", { stdio: "inherit" });
|
|
204
|
+
}
|
|
205
|
+
await installNpmDependencies(projectPath, npmDependencies, true);
|
|
206
|
+
await installComposerDependencies(projectPath, composerDependencies);
|
|
207
|
+
if (!projectName) {
|
|
208
|
+
execSync("npx tsc --init", { stdio: "inherit" });
|
|
209
|
+
}
|
|
210
|
+
await createDirectoryStructure(projectPath, answer);
|
|
211
|
+
if (answer.prisma) {
|
|
212
|
+
execSync("npx ppo init --prisma-php", { stdio: "inherit" });
|
|
213
|
+
}
|
|
214
|
+
if (answer.swaggerDocs) {
|
|
215
|
+
const swaggerDocsPath = path.join(projectPath, "src", "app", "swagger-docs");
|
|
216
|
+
// Check if the directory exists
|
|
217
|
+
if (fs.existsSync(swaggerDocsPath)) {
|
|
218
|
+
// If it exists and is not empty, remove it before cloning
|
|
219
|
+
if (fs.readdirSync(swaggerDocsPath).length > 0) {
|
|
220
|
+
console.log("Removing existing swagger-docs directory...");
|
|
221
|
+
fs.rmSync(swaggerDocsPath, { recursive: true, force: true });
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
// Clone the Git repository into the swagger-docs directory
|
|
225
|
+
execSync(`git clone https://github.com/TheSteelNinjaCode/prisma-php-swagger-docs.git ${swaggerDocsPath}`, { stdio: "inherit" });
|
|
226
|
+
// delete the folder .git
|
|
227
|
+
fs.rmSync(path.join(swaggerDocsPath, ".git"), {
|
|
228
|
+
recursive: true,
|
|
229
|
+
force: true,
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
if (updateAnswer?.isUpdate) {
|
|
233
|
+
const updateUninstallNpmDependencies = [];
|
|
234
|
+
const updateUninstallComposerDependencies = [];
|
|
235
|
+
if (updateAnswer.backendOnly) {
|
|
236
|
+
nonBackendFiles.forEach((file) => {
|
|
237
|
+
const filePath = path.join(projectPath, "src", "app", file);
|
|
238
|
+
if (fs.existsSync(filePath)) {
|
|
239
|
+
fs.unlinkSync(filePath); // Delete each file if it exists
|
|
240
|
+
console.log(`${file} was deleted successfully.`);
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
console.log(`${file} does not exist.`);
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
const backendOnlyFolders = ["js", "css"];
|
|
247
|
+
backendOnlyFolders.forEach((folder) => {
|
|
248
|
+
const folderPath = path.join(projectPath, "src", "app", folder);
|
|
249
|
+
if (fs.existsSync(folderPath)) {
|
|
250
|
+
fs.rmSync(folderPath, { recursive: true, force: true }); // Use fs.rmSync instead of fs.rmdirSync
|
|
251
|
+
console.log(`${folder} was deleted successfully.`);
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
console.log(`${folder} does not exist.`);
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
if (!updateAnswer.swaggerDocs) {
|
|
259
|
+
const swaggerDocsFolder = path.join(projectPath, "src", "app", "swagger-docs");
|
|
260
|
+
if (fs.existsSync(swaggerDocsFolder)) {
|
|
261
|
+
fs.rmSync(swaggerDocsFolder, { recursive: true, force: true }); // Use fs.rmSync instead of fs.rmdirSync
|
|
262
|
+
console.log(`swagger-docs was deleted successfully.`);
|
|
263
|
+
}
|
|
264
|
+
const swaggerFiles = ["swagger-config.ts"];
|
|
265
|
+
swaggerFiles.forEach((file) => {
|
|
266
|
+
const filePath = path.join(projectPath, "settings", file);
|
|
267
|
+
if (fs.existsSync(filePath)) {
|
|
268
|
+
fs.unlinkSync(filePath); // Delete each file if it exists
|
|
269
|
+
console.log(`${file} was deleted successfully.`);
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
272
|
+
console.log(`${file} does not exist.`);
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
updateUninstallNpmDependencies.push("swagger-jsdoc", "@types/swagger-jsdoc", "prompts", "@types/prompts");
|
|
276
|
+
}
|
|
277
|
+
if (!updateAnswer.tailwindcss) {
|
|
278
|
+
const tailwindFiles = ["postcss.config.js"];
|
|
279
|
+
tailwindFiles.forEach((file) => {
|
|
280
|
+
const filePath = path.join(projectPath, file);
|
|
281
|
+
if (fs.existsSync(filePath)) {
|
|
282
|
+
fs.unlinkSync(filePath); // Delete each file if it exists
|
|
283
|
+
console.log(`${file} was deleted successfully.`);
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
console.log(`${file} does not exist.`);
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
updateUninstallNpmDependencies.push("tailwindcss", "postcss", "postcss-cli", "@tailwindcss/postcss", "cssnano");
|
|
290
|
+
}
|
|
291
|
+
if (!updateAnswer.websocket) {
|
|
292
|
+
const websocketFiles = [
|
|
293
|
+
"restart-websocket.ts",
|
|
294
|
+
"restart-websocket.bat",
|
|
295
|
+
];
|
|
296
|
+
websocketFiles.forEach((file) => {
|
|
297
|
+
const filePath = path.join(projectPath, "settings", file);
|
|
298
|
+
if (fs.existsSync(filePath)) {
|
|
299
|
+
fs.unlinkSync(filePath); // Delete each file if it exists
|
|
300
|
+
console.log(`${file} was deleted successfully.`);
|
|
301
|
+
}
|
|
302
|
+
else {
|
|
303
|
+
console.log(`${file} does not exist.`);
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
const websocketFolder = path.join(projectPath, "src", "Lib", "Websocket");
|
|
307
|
+
if (fs.existsSync(websocketFolder)) {
|
|
308
|
+
fs.rmSync(websocketFolder, { recursive: true, force: true }); // Use fs.rmSync instead of fs.rmdirSync
|
|
309
|
+
console.log(`Websocket folder was deleted successfully.`);
|
|
310
|
+
}
|
|
311
|
+
updateUninstallNpmDependencies.push("chokidar-cli");
|
|
312
|
+
updateUninstallComposerDependencies.push("cboden/ratchet");
|
|
313
|
+
}
|
|
314
|
+
if (!updateAnswer.prisma) {
|
|
315
|
+
updateUninstallNpmDependencies.push("prisma", "@prisma/client", "@prisma/internals");
|
|
316
|
+
}
|
|
317
|
+
if (!updateAnswer.docker) {
|
|
318
|
+
const dockerFiles = [
|
|
319
|
+
".dockerignore",
|
|
320
|
+
"docker-compose.yml",
|
|
321
|
+
"Dockerfile",
|
|
322
|
+
"apache.conf",
|
|
323
|
+
];
|
|
324
|
+
dockerFiles.forEach((file) => {
|
|
325
|
+
const filePath = path.join(projectPath, file);
|
|
326
|
+
if (fs.existsSync(filePath)) {
|
|
327
|
+
fs.unlinkSync(filePath); // Delete each file if it exists
|
|
328
|
+
console.log(`${file} was deleted successfully.`);
|
|
329
|
+
}
|
|
330
|
+
else {
|
|
331
|
+
console.log(`${file} does not exist.`);
|
|
332
|
+
}
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
if (updateUninstallNpmDependencies.length > 0) {
|
|
336
|
+
await uninstallNpmDependencies(projectPath, updateUninstallNpmDependencies, true);
|
|
337
|
+
}
|
|
338
|
+
if (updateUninstallComposerDependencies.length > 0) {
|
|
339
|
+
await uninstallComposerDependencies(projectPath, updateUninstallComposerDependencies);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
const projectPathModified = projectPath.replace(/\\/g, "\\");
|
|
343
|
+
const bsConfig = bsConfigUrls(projectPathModified);
|
|
344
|
+
const prismaPhpConfig = {
|
|
345
|
+
projectName: answer.projectName,
|
|
346
|
+
projectRootPath: projectPathModified,
|
|
347
|
+
phpEnvironment: "XAMPP",
|
|
348
|
+
phpRootPathExe: "C:\\xampp\\php\\php.exe",
|
|
349
|
+
bsTarget: bsConfig.bsTarget,
|
|
350
|
+
bsPathRewrite: bsConfig.bsPathRewrite,
|
|
351
|
+
backendOnly: answer.backendOnly,
|
|
352
|
+
swaggerDocs: answer.swaggerDocs,
|
|
353
|
+
tailwindcss: answer.tailwindcss,
|
|
354
|
+
websocket: answer.websocket,
|
|
355
|
+
prisma: answer.prisma,
|
|
356
|
+
docker: answer.docker,
|
|
357
|
+
version: latestVersionOfCreatePrismaPhpApp,
|
|
358
|
+
excludeFiles: updateAnswer?.excludeFiles ?? [],
|
|
359
|
+
};
|
|
360
|
+
fs.writeFileSync(path.join(projectPath, "prisma-php.json"), JSON.stringify(prismaPhpConfig, null, 2), { flag: "w" });
|
|
361
|
+
if (updateAnswer?.isUpdate) {
|
|
362
|
+
execSync("C:\\xampp\\php\\php.exe C:\\ProgramData\\ComposerSetup\\bin\\composer.phar update", {
|
|
363
|
+
stdio: "inherit",
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
console.log("\n=========================\n");
|
|
367
|
+
console.log(`${chalk.green("Success!")} Prisma PHP project successfully created in ${chalk.green(`${currentDir.replace(/\\/g, "/")}/${answer.projectName}`)}!`);
|
|
368
|
+
console.log("\n=========================");
|
|
369
|
+
}
|
|
370
|
+
catch (error) {
|
|
371
|
+
console.error("Error while creating the project:", error);
|
|
372
|
+
process.exit(1);
|
|
427
373
|
}
|
|
428
|
-
console.log("\n=========================\n");
|
|
429
|
-
console.log(
|
|
430
|
-
`${chalk.green(
|
|
431
|
-
"Success!"
|
|
432
|
-
)} Prisma PHP project successfully created in ${chalk.green(
|
|
433
|
-
`${currentDir.replace(/\\/g, "/")}/${answer.projectName}`
|
|
434
|
-
)}!`
|
|
435
|
-
);
|
|
436
|
-
console.log("\n=========================");
|
|
437
|
-
} catch (error) {
|
|
438
|
-
console.error("Error while creating the project:", error);
|
|
439
|
-
process.exit(1);
|
|
440
|
-
}
|
|
441
374
|
}
|
|
442
375
|
main();
|