create-gramstax 0.0.12 → 0.0.14
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/src/index.cjs +2 -2
- package/dist/src/index.cjs.map +1 -1
- package/dist/src/index.js +2 -2
- package/dist/src/index.js.map +1 -1
- package/package.json +1 -1
package/dist/src/index.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
"use strict";var
|
|
2
|
+
"use strict";var x=Object.create;var u=Object.defineProperty;var M=Object.getOwnPropertyDescriptor;var D=Object.getOwnPropertyNames;var F=Object.getPrototypeOf,E=Object.prototype.hasOwnProperty;var g=(m,e)=>u(m,"name",{value:e,configurable:!0});var N=(m,e,n,t)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of D(e))!E.call(m,i)&&i!==n&&u(m,i,{get:()=>e[i],enumerable:!(t=M(e,i))||t.enumerable});return m};var f=(m,e,n)=>(n=m!=null?x(F(m)):{},N(e||!m||!m.__esModule?u(n,"default",{value:m,enumerable:!0}):n,m));var j=require("logging-pretty"),r=new j.LoggingPretty;var a=f(require("fs"),1),p=f(require("path"),1),v=require("url");var d=require("child_process"),y=f(require("enquirer"),1),T={};var R=(0,v.fileURLToPath)(T.url),L=p.dirname(R),l=class{constructor(e){this.projectDirectory=e}static{g(this,"Create")}config;printBanner(){console.log(`
|
|
3
3
|
$$$$$$\\ $$\\
|
|
4
4
|
$$ __$$\\ $$ |
|
|
5
5
|
$$ / \\__| $$$$$$\\ $$$$$$\\ $$$$$$\\$$$$\\ $$$$$$$\\ $$$$$$\\ $$$$$$\\ $$\\ $$\\
|
|
@@ -9,5 +9,5 @@ $$ | $$ |$$ | $$ __$$ |$$ | $$ | $$ | \\____$$\\ $$ |$$\\ $$ __$$ | $$
|
|
|
9
9
|
\\$$$$$$ |$$ | \\$$$$$$$ |$$ | $$ | $$ |$$$$$$$ | \\$$$$ |\\$$$$$$$ |$$ /\\$$\\
|
|
10
10
|
\\______/ \\__| \\_______|\\__| \\__| \\__|\\_______/ \\____/ \\_______|\\__/ \\__|
|
|
11
11
|
|
|
12
|
-
`)}getPackageManagerCommands(e){return{bun:{install:"bun install",dev:"bun dev",start:"bun start","pm2:start":"bun run pm2:start","pm2:stop":"bun run pm2:stop","pm2:restart":"bun run pm2:restart","pm2:delete":"bun run pm2:delete","pm2:logs":"bun run pm2:logs","pm2:monit":"bun run pm2:monit"},npm:{install:"npm install",dev:"npm run dev",start:"npm start","pm2:start":"npm run pm2:start","pm2:stop":"npm run pm2:stop","pm2:restart":"npm run pm2:restart","pm2:delete":"npm run pm2:delete","pm2:logs":"npm run pm2:logs","pm2:monit":"npm run pm2:monit"},pnpm:{install:"pnpm install",dev:"pnpm dev",start:"pnpm start","pm2:start":"pnpm pm2:start","pm2:stop":"pnpm pm2:stop","pm2:restart":"pnpm pm2:restart","pm2:delete":"pnpm pm2:delete","pm2:logs":"pnpm pm2:logs","pm2:monit":"pnpm pm2:monit"},yarn:{install:"yarn install",dev:"yarn dev",start:"yarn start","pm2:start":"yarn pm2:start","pm2:stop":"yarn pm2:stop","pm2:restart":"yarn pm2:restart","pm2:delete":"yarn pm2:delete","pm2:logs":"yarn pm2:logs","pm2:monit":"yarn pm2:monit"}}[e]}copyDirectorySync(e,n,t={}){a.existsSync(n)||a.mkdirSync(n,{recursive:!0});let
|
|
12
|
+
`)}getPackageManagerCommands(e){return{bun:{install:"bun install",dev:"bun dev",start:"bun start","pm2:start":"bun run pm2:start","pm2:stop":"bun run pm2:stop","pm2:restart":"bun run pm2:restart","pm2:delete":"bun run pm2:delete","pm2:logs":"bun run pm2:logs","pm2:monit":"bun run pm2:monit"},npm:{install:"npm install",dev:"npm run dev",start:"npm start","pm2:start":"npm run pm2:start","pm2:stop":"npm run pm2:stop","pm2:restart":"npm run pm2:restart","pm2:delete":"npm run pm2:delete","pm2:logs":"npm run pm2:logs","pm2:monit":"npm run pm2:monit"},pnpm:{install:"pnpm install",dev:"pnpm dev",start:"pnpm start","pm2:start":"pnpm pm2:start","pm2:stop":"pnpm pm2:stop","pm2:restart":"pnpm pm2:restart","pm2:delete":"pnpm pm2:delete","pm2:logs":"pnpm pm2:logs","pm2:monit":"pnpm pm2:monit"},yarn:{install:"yarn install",dev:"yarn dev",start:"yarn start","pm2:start":"yarn pm2:start","pm2:stop":"yarn pm2:stop","pm2:restart":"yarn pm2:restart","pm2:delete":"yarn pm2:delete","pm2:logs":"yarn pm2:logs","pm2:monit":"yarn pm2:monit"}}[e]}copyDirectorySync(e,n,t={}){a.existsSync(n)||a.mkdirSync(n,{recursive:!0});let i=a.readdirSync(e,{withFileTypes:!0});for(let o of i){let $=p.join(e,o.name),c=p.join(n,o.name);if(o.isDirectory())this.copyDirectorySync($,c,t);else if(o.isFile()){let s=a.readFileSync($,"utf-8");s=this.replaceTemplateVariables(s,t),a.writeFileSync(c,s)}}}replaceTemplateVariables(e,n){let t=e;for(let[i,o]of Object.entries(n))t=t.replace(new RegExp(`{{${i}}}`,"g"),o);return t}async promptForProjectName(){return(await y.default.prompt({type:"input",name:"projectName",message:"What is your project named?",initial:"",validate:g(n=>n===""||/^[a-z0-9-_]+$/i.test(n)?!0:"Project name can only contain letters, numbers, hyphens, and underscores","validate")})).projectName}async promptForConfiguration(){let e=[];e.push({type:"select",name:"packageManager",message:"Which package manager would you like to use?",choices:[{name:"bun",message:"Bun (recommended)",value:"bun"},{name:"npm",message:"npm",value:"npm"},{name:"pnpm",message:"pnpm",value:"pnpm"},{name:"yarn",message:"Yarn",value:"yarn"}],initial:0}),e.push({type:"select",name:"runtime",message:"Which runtime would you like to use?",choices:[{name:"bun",message:"Bun (recommended)",value:"bun"},{name:"node",message:"Node.js",value:"node"}],initial:0}),e.push({type:"confirm",name:"eslint",message:"Would you like to use ESLint?",initial:!0});let n=await y.default.prompt(e);return{packageManager:n.packageManager,runtime:n.runtime,eslint:n.eslint}}async installDependencies(e,n){return await new Promise((t,i)=>{let c=(0,d.spawn)(n,["install"],{cwd:e,stdio:"inherit",shell:!0});c.on("close",s=>{s===0?t(!0):(r.fail("Dependencies installation failed"),t(!1))}),c.on("error",s=>{r.fail(`Dependencies installation failed: ${s.message}`),t(!1)})})}async gatherProjectConfig(){this.printBanner();let e=this.projectDirectory,n,t=!1;e?(n=p.resolve(process.cwd(),e),t=!1):(e=await this.promptForProjectName(),e===""?(e=p.basename(process.cwd()),n=process.cwd(),t=!0):(n=p.resolve(process.cwd(),e),t=!1));let i=await this.promptForConfiguration(),o=i.packageManager,$=i.runtime,c=i.eslint;return r.info(`Project: ${e}`),r.info(`Location: ${n}`),r.info(`Package Manager: ${o}`),r.info(`Runtime: ${$}`),r.info(`ESLint: ${c?"Yes":"No"}`),t?a.readdirSync(n).length>0&&(r.error("Current directory is not empty!"),process.exit(1)):a.existsSync(n)&&(r.error(`Directory "${e}" already exists!`),process.exit(1)),{projectName:e,projectPath:n,packageManager:o,runtime:$,setupEslint:c}}async executeProjectGeneration(e){let{projectName:n,projectPath:t,packageManager:i,runtime:o,setupEslint:$}=e;r.info("Creating project directory.."),a.existsSync(t)||a.mkdirSync(t,{recursive:!0}),r.info("Copying template files..");let c=p.join(L,"templates"),s=this.getPackageManagerCommands(i),C={projectName:n,installCmd:s.install,runDevCmd:s.dev,runStartCmd:s.start,runPm2StartCmd:s["pm2:start"],runPm2StopCmd:s["pm2:stop"],runPm2RestartCmd:s["pm2:restart"],runPm2DeleteCmd:s["pm2:delete"],runPm2LogsCmd:s["pm2:logs"],runPm2MonitCmd:s["pm2:monit"]};this.copyDirectorySync(c,t,C),r.info("Creating logs directory.."),a.mkdirSync(p.join(t,"logs"),{recursive:!0}),a.writeFileSync(p.join(t,"logs/.gitkeep"),"");let S=p.join(t,".env"),_=p.join(t,".env.example");if(a.existsSync(_)&&(r.info("Creating .env file.."),a.renameSync(_,S)),o!=="bun"){r.info("Removing bunfig.toml for Node.js runtime..");let P=p.join(t,"bunfig.toml");a.existsSync(P)&&a.unlinkSync(P)}let h=p.join(t,"tsconfig.json"),k=a.readFileSync(h,{encoding:"utf8"}).replace("//{{types}}",o=="bun"?'"bun-types"':"");if(a.writeFileSync(h,k,{encoding:"utf8"}),r.info("Installing dependencies.."),!await this.installDependencies(t,i))return r.fail("Project created failed!"),process.exit();$&&(r.info("Setting up ESLint.."),await this.setupEslintConfig(t,i)),r.info("Project created successfully!"),r.info(`Next steps: ${e.projectPath!==process.cwd()?`cd ${n} && `:" "}${s.install} && ${s.dev}`),r.info(`For production: ${s["pm2:start"]}`),r.info("Done..")}async setupEslintConfig(e,n){return new Promise(t=>{let i=(0,d.spawn)("npm",["init","@eslint/config@latest"],{cwd:e,stdio:"inherit",shell:!0});i.on("close",o=>{o===0||r.fail("ESLint setup failed. You can set it up later with: npm init @eslint/config"),t()}),i.on("error",o=>{r.fail(`ESLint setup failed: ${o.message}`),r.info("You can set it up later with: npm init @eslint/config"),t()})})}async createProject(){try{this.config=await this.gatherProjectConfig(),await this.executeProjectGeneration(this.config)}catch(e){e instanceof Error?r.error(`Failed to create project: ${e.message}`):r.error(`Failed to create project: ${String(e)}`),process.exit(1)}}};var b=require("commander"),B="0.0.0",w=new b.Command;w.name("create-gramstax").description("CLI to create a new Gramstax Telegram bot project").version(B).argument("[project-directory]","Directory to create the project in").action(async m=>{try{await new l(m).createProject()}catch(e){r.error(`Failed to create project: ${String(e)}`),process.exit(1)}});w.parse();
|
|
13
13
|
//# sourceMappingURL=index.cjs.map
|
package/dist/src/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utils/logger.ts","../../src/create.ts","../../src/index.ts"],"sourcesContent":["import { LoggingPretty } from \"logging-pretty\"\r\n\r\nexport const log = new LoggingPretty()\r\n","import * as fs from \"fs\"\r\nimport * as path from \"path\"\r\nimport { log } from \"./utils/logger\"\r\nimport { spawn } from \"child_process\"\r\nimport enquirer from \"enquirer\"\r\n\r\ntype Runtime = `bun` | `node`\r\ntype PackageManager = `bun` | `npm` | `pnpm` | `yarn`\r\ntype ProjectConfig = {\r\n projectName: string\r\n projectPath: string\r\n packageManager: PackageManager\r\n runtime: Runtime\r\n setupEslint: boolean\r\n}\r\n\r\nexport class Create {\r\n private config: ProjectConfig | undefined\r\n\r\n public constructor(private projectDirectory?: string) {\r\n // Constructor hanya menerima parameter, tidak melakukan execution\r\n }\r\n\r\n public printBanner() {\r\n const banner = `\r\n $$$$$$\\\\ $$\\\\ \r\n$$ __$$\\\\ $$ | \r\n$$ / \\\\__| $$$$$$\\\\ $$$$$$\\\\ $$$$$$\\\\$$$$\\\\ $$$$$$$\\\\ $$$$$$\\\\ $$$$$$\\\\ $$\\\\ $$\\\\ \r\n$$ |$$$$\\\\ $$ __$$\\\\ \\\\____$$\\\\ $$ _$$ _$$\\\\ $$ _____|\\\\_$$ _| \\\\____$$\\\\ \\\\$$\\\\ $$ |\r\n$$ |\\\\_$$ |$$ | \\\\__|$$$$$$$ |$$ / $$ / $$ |\\\\$$$$$$\\\\ $$ | $$$$$$$ | \\\\$$$$ / \r\n$$ | $$ |$$ | $$ __$$ |$$ | $$ | $$ | \\\\____$$\\\\ $$ |$$\\\\ $$ __$$ | $$ $$< \r\n\\\\$$$$$$ |$$ | \\\\$$$$$$$ |$$ | $$ | $$ |$$$$$$$ | \\\\$$$$ |\\\\$$$$$$$ |$$ /\\\\$$\\\\ \r\n \\\\______/ \\\\__| \\\\_______|\\\\__| \\\\__| \\\\__|\\\\_______/ \\\\____/ \\\\_______|\\\\__/ \\\\__|\r\n \r\n`\r\n console.log(banner)\r\n }\r\n\r\n private getPackageManagerCommands(packageManager: PackageManager) {\r\n const commands = {\r\n bun: {\r\n install: `bun install`,\r\n dev: `bun dev`,\r\n start: `bun start`,\r\n \"pm2:start\": `bun run pm2:start`,\r\n \"pm2:stop\": `bun run pm2:stop`,\r\n \"pm2:restart\": `bun run pm2:restart`,\r\n \"pm2:delete\": `bun run pm2:delete`,\r\n \"pm2:logs\": `bun run pm2:logs`,\r\n \"pm2:monit\": `bun run pm2:monit`\r\n },\r\n npm: {\r\n install: `npm install`,\r\n dev: `npm run dev`,\r\n start: `npm start`,\r\n \"pm2:start\": `npm run pm2:start`,\r\n \"pm2:stop\": `npm run pm2:stop`,\r\n \"pm2:restart\": `npm run pm2:restart`,\r\n \"pm2:delete\": `npm run pm2:delete`,\r\n \"pm2:logs\": `npm run pm2:logs`,\r\n \"pm2:monit\": `npm run pm2:monit`\r\n },\r\n pnpm: {\r\n install: `pnpm install`,\r\n dev: `pnpm dev`,\r\n start: `pnpm start`,\r\n \"pm2:start\": `pnpm pm2:start`,\r\n \"pm2:stop\": `pnpm pm2:stop`,\r\n \"pm2:restart\": `pnpm pm2:restart`,\r\n \"pm2:delete\": `pnpm pm2:delete`,\r\n \"pm2:logs\": `pnpm pm2:logs`,\r\n \"pm2:monit\": `pnpm pm2:monit`\r\n },\r\n yarn: {\r\n install: `yarn install`,\r\n dev: `yarn dev`,\r\n start: `yarn start`,\r\n \"pm2:start\": `yarn pm2:start`,\r\n \"pm2:stop\": `yarn pm2:stop`,\r\n \"pm2:restart\": `yarn pm2:restart`,\r\n \"pm2:delete\": `yarn pm2:delete`,\r\n \"pm2:logs\": `yarn pm2:logs`,\r\n \"pm2:monit\": `yarn pm2:monit`\r\n }\r\n }\r\n return commands[packageManager]\r\n }\r\n\r\n /**\r\n * Recursively copy directory structure\r\n */\r\n private copyDirectorySync(source: string, destination: string, variables: Record<string, string> = {}) {\r\n // Create destination directory if it doesn't exist\r\n if (!fs.existsSync(destination)) {\r\n fs.mkdirSync(destination, { recursive: true })\r\n }\r\n\r\n // Read all items in source directory\r\n const items = fs.readdirSync(source, { withFileTypes: true })\r\n\r\n for (const item of items) {\r\n const sourcePath = path.join(source, item.name)\r\n const destPath = path.join(destination, item.name)\r\n\r\n if (item.isDirectory()) {\r\n // Recursively copy subdirectories\r\n this.copyDirectorySync(sourcePath, destPath, variables)\r\n } else if (item.isFile()) {\r\n // Copy file and replace variables if needed\r\n let content = fs.readFileSync(sourcePath, `utf-8`)\r\n\r\n // Replace template variables in content\r\n content = this.replaceTemplateVariables(content, variables)\r\n\r\n fs.writeFileSync(destPath, content)\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Replace template variables in content\r\n */\r\n private replaceTemplateVariables(content: string, variables: Record<string, string>): string {\r\n let result = content\r\n for (const [key, value] of Object.entries(variables)) {\r\n result = result.replace(new RegExp(`{{${key}}}`, `g`), value)\r\n }\r\n return result\r\n }\r\n\r\n private async promptForProjectName(): Promise<string> {\r\n const response = await enquirer.prompt<{ projectName: string }>({\r\n type: `input`,\r\n name: `projectName`,\r\n message: `What is your project named?`,\r\n initial: ``,\r\n validate: (value: string) => {\r\n if (value === ``) {\r\n return true\r\n }\r\n\r\n if (!/^[a-z0-9-_]+$/i.test(value)) {\r\n return `Project name can only contain letters, numbers, hyphens, and underscores`\r\n }\r\n return true\r\n }\r\n })\r\n\r\n return response.projectName\r\n }\r\n\r\n private async promptForConfiguration(): Promise<{ packageManager: PackageManager; runtime: Runtime; eslint: boolean }> {\r\n const questions: any[] = []\r\n\r\n // Package manager selection\r\n questions.push({\r\n type: `select`,\r\n name: `packageManager`,\r\n message: `Which package manager would you like to use?`,\r\n choices: [\r\n { name: `bun`, message: `Bun (recommended)`, value: `bun` },\r\n { name: `npm`, message: `npm`, value: `npm` },\r\n { name: `pnpm`, message: `pnpm`, value: `pnpm` },\r\n { name: `yarn`, message: `Yarn`, value: `yarn` }\r\n ],\r\n initial: 0\r\n })\r\n\r\n // Runtime selection\r\n questions.push({\r\n type: `select`,\r\n name: `runtime`,\r\n message: `Which runtime would you like to use?`,\r\n choices: [\r\n { name: `bun`, message: `Bun (recommended)`, value: `bun` },\r\n { name: `node`, message: `Node.js`, value: `node` }\r\n ],\r\n initial: 0\r\n })\r\n\r\n // ESLint\r\n questions.push({\r\n type: `confirm`,\r\n name: `eslint`,\r\n message: `Would you like to use ESLint?`,\r\n initial: true\r\n })\r\n\r\n const answers = await enquirer.prompt<{\r\n packageManager?: PackageManager\r\n runtime: Runtime\r\n eslint?: boolean\r\n }>(questions)\r\n\r\n return {\r\n packageManager: answers.packageManager as any,\r\n runtime: answers.runtime,\r\n eslint: answers.eslint as boolean\r\n }\r\n }\r\n\r\n private async installDependencies(projectPath: string, packageManager: PackageManager): Promise<boolean> {\r\n return await new Promise((resolve, reject) => {\r\n const installCommand = packageManager\r\n const installArgs = [`install`]\r\n const installProcess = spawn(installCommand, installArgs, {\r\n cwd: projectPath,\r\n stdio: `inherit`,\r\n shell: true\r\n })\r\n\r\n installProcess.on(`close`, (code) => {\r\n if (code === 0) {\r\n resolve(true)\r\n } else {\r\n log.fail(`Dependencies installation failed`)\r\n resolve(false)\r\n }\r\n })\r\n\r\n installProcess.on(`error`, (error) => {\r\n log.fail(`Dependencies installation failed: ${error.message}`)\r\n resolve(false)\r\n })\r\n })\r\n }\r\n\r\n /**\r\n * Step 1: Gather all project configuration through prompts\r\n * NO EXECUTION - hanya mengumpulkan data dan validasi ringan\r\n */\r\n private async gatherProjectConfig(): Promise<ProjectConfig> {\r\n // Display ASCII art banner\r\n this.printBanner()\r\n\r\n // ========== PHASE 1: GET PROJECT NAME ==========\r\n let projectName = this.projectDirectory\r\n let projectPath: string\r\n let useCurrentDir = false\r\n\r\n if (!projectName) {\r\n // PROMPT untuk project name\r\n projectName = await this.promptForProjectName()\r\n if (projectName === ``) {\r\n // Empty name means use current directory\r\n projectName = path.basename(process.cwd())\r\n projectPath = process.cwd()\r\n useCurrentDir = true\r\n } else {\r\n projectPath = path.resolve(process.cwd(), projectName)\r\n useCurrentDir = false\r\n }\r\n } else {\r\n projectPath = path.resolve(process.cwd(), projectName)\r\n useCurrentDir = false\r\n }\r\n\r\n // PROMPT untuk configuration\r\n const config = await this.promptForConfiguration()\r\n const packageManager = config.packageManager\r\n const runtime = config.runtime\r\n const setupEslint = config.eslint\r\n\r\n // ========== SEMUA PROMPT SELESAI, SEKARANG VALIDASI ==========\r\n log.info(`Project: ${projectName}`)\r\n log.info(`Location: ${projectPath}`)\r\n log.info(`Package Manager: ${packageManager}`)\r\n log.info(`Runtime: ${runtime}`)\r\n log.info(`ESLint: ${setupEslint ? `Yes` : `No`}`)\r\n\r\n // Validasi setelah semua prompt selesai\r\n if (useCurrentDir) {\r\n // Check if current directory is empty\r\n const files = fs.readdirSync(projectPath)\r\n if (files.length > 0) {\r\n log.error(`Current directory is not empty!`)\r\n process.exit(1)\r\n }\r\n } else {\r\n // Check if directory already exists\r\n if (fs.existsSync(projectPath)) {\r\n log.error(`Directory \"${projectName}\" already exists!`)\r\n process.exit(1)\r\n }\r\n }\r\n\r\n return {\r\n projectName,\r\n projectPath,\r\n packageManager,\r\n runtime,\r\n setupEslint\r\n }\r\n }\r\n\r\n /**\r\n * Step 2: Execute project generation based on gathered config\r\n */\r\n private async executeProjectGeneration(config: ProjectConfig): Promise<void> {\r\n const { projectName, projectPath, packageManager, runtime, setupEslint } = config\r\n\r\n // Task 1: Create project directory\r\n log.info(`Creating project directory..`)\r\n if (!fs.existsSync(projectPath)) {\r\n fs.mkdirSync(projectPath, { recursive: true })\r\n }\r\n\r\n // Task 2: Copy template files\r\n log.info(`Copying template files..`)\r\n const templatesPath = path.join(__dirname, `templates`)\r\n const commands = this.getPackageManagerCommands(packageManager)\r\n\r\n const variables = {\r\n projectName,\r\n installCmd: commands.install,\r\n runDevCmd: commands.dev,\r\n runStartCmd: commands.start,\r\n runPm2StartCmd: commands[`pm2:start`],\r\n runPm2StopCmd: commands[`pm2:stop`],\r\n runPm2RestartCmd: commands[`pm2:restart`],\r\n runPm2DeleteCmd: commands[`pm2:delete`],\r\n runPm2LogsCmd: commands[`pm2:logs`],\r\n runPm2MonitCmd: commands[`pm2:monit`]\r\n }\r\n\r\n this.copyDirectorySync(templatesPath, projectPath, variables)\r\n\r\n // Task 3: Create logs directory\r\n log.info(`Creating logs directory..`)\r\n fs.mkdirSync(path.join(projectPath, `logs`), { recursive: true })\r\n fs.writeFileSync(path.join(projectPath, `logs/.gitkeep`), ``)\r\n\r\n // Task 4: Create .env.example\r\n const envPath = path.join(projectPath, `.env`)\r\n const envExamplePath = path.join(projectPath, `.env.example`)\r\n if (fs.existsSync(envExamplePath)) {\r\n log.info(`Creating .env file..`)\r\n fs.renameSync(envExamplePath, envPath)\r\n }\r\n\r\n // Task 5: Remove bunfig.toml if runtime is NOT bun\r\n if (runtime !== `bun`) {\r\n log.info(`Removing bunfig.toml for Node.js runtime..`)\r\n const bunfigPath = path.join(projectPath, `bunfig.toml`)\r\n if (fs.existsSync(bunfigPath)) {\r\n fs.unlinkSync(bunfigPath)\r\n }\r\n }\r\n\r\n // Task 6: tsconfig.json\r\n const tsconfigPath = path.join(projectPath, `tsconfig.json`)\r\n const tsconfigContent = fs.readFileSync(tsconfigPath, { encoding: `utf8` }).replace(`//{{types}}`, runtime == `bun` ? `bun-types` : ``)\r\n fs.writeFileSync(tsconfigPath, tsconfigContent, { encoding: `utf8` })\r\n\r\n // Task 6: Install dependencies\r\n log.info(`Installing dependencies..`)\r\n if (!(await this.installDependencies(projectPath, packageManager))) {\r\n log.fail(`Project created failed!`)\r\n return process.exit()\r\n }\r\n\r\n // Task 7: Setup ESLint if requested\r\n if (setupEslint) {\r\n log.info(`Setting up ESLint..`)\r\n await this.setupEslintConfig(projectPath, packageManager)\r\n }\r\n\r\n // Final success message\r\n log.info(`Project created successfully!`)\r\n log.info(`Next steps: ${config.projectPath !== process.cwd() ? `cd ${projectName} && ` : ` `}${commands.install} && ${commands.dev}`)\r\n log.info(`For production: ${commands[`pm2:start`]}`)\r\n log.info(`Done..`)\r\n }\r\n\r\n private async setupEslintConfig(projectPath: string, packageManager: PackageManager): Promise<void> {\r\n return new Promise((resolve) => {\r\n const initProcess = spawn(`npm`, [`init`, `@eslint/config@latest`], {\r\n cwd: projectPath,\r\n stdio: `inherit`,\r\n shell: true\r\n })\r\n\r\n initProcess.on(`close`, (code) => {\r\n if (code === 0) {\r\n resolve()\r\n } else {\r\n log.fail(`ESLint setup failed. You can set it up later with: npm init @eslint/config`)\r\n resolve()\r\n }\r\n })\r\n\r\n initProcess.on(`error`, (error) => {\r\n log.fail(`ESLint setup failed: ${error.message}`)\r\n log.info(`You can set it up later with: npm init @eslint/config`)\r\n resolve()\r\n })\r\n })\r\n }\r\n\r\n /**\r\n * Main public method: Prompt first, then execute\r\n */\r\n public async createProject() {\r\n try {\r\n // Step 1: Gather all configuration through prompts\r\n this.config = await this.gatherProjectConfig()\r\n\r\n // Step 2: Execute project generation with the gathered config\r\n await this.executeProjectGeneration(this.config)\r\n } catch (error) {\r\n if (error instanceof Error) {\r\n log.error(`Failed to create project: ${error.message}`)\r\n } else {\r\n log.error(`Failed to create project: ${String(error)}`)\r\n }\r\n process.exit(1)\r\n }\r\n }\r\n}\r\n","#!/usr/bin/env node\r\nimport { log } from \"./utils/logger\"\r\nimport { Create } from \"./create\"\r\nimport { Command } from \"commander\"\r\n\r\n// Read version from package.json\r\nconst version = `0.0.0`\r\nconst program = new Command()\r\n\r\nprogram\r\n .name(`create-gramstax`)\r\n .description(`CLI to create a new Gramstax Telegram bot project`)\r\n .version(version)\r\n .argument(`[project-directory]`, `Directory to create the project in`)\r\n .action(async (projectDirectory?: string) => {\r\n try {\r\n await new Create(projectDirectory).createProject()\r\n } catch (error) {\r\n log.error(`Failed to create project: ${String(error)}`)\r\n process.exit(1)\r\n }\r\n })\r\n\r\nprogram.parse()\r\n"],"mappings":"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","names":["import_logging_pretty","log","fs","path","import_child_process","import_enquirer","Create","projectDirectory","__name","packageManager","source","destination","variables","items","item","sourcePath","destPath","content","result","key","value","enquirer","questions","answers","projectPath","resolve","reject","installProcess","code","log","error","projectName","useCurrentDir","config","runtime","setupEslint","templatesPath","commands","envPath","envExamplePath","bunfigPath","tsconfigPath","tsconfigContent","initProcess","import_commander","version","program","projectDirectory","Create","error","log"]}
|
|
1
|
+
{"version":3,"sources":["../../src/utils/logger.ts","../../src/create.ts","../../src/index.ts"],"sourcesContent":["import { LoggingPretty } from \"logging-pretty\"\r\n\r\nexport const log = new LoggingPretty()\r\n","import * as fs from \"fs\"\r\nimport * as path from \"path\"\r\nimport { fileURLToPath } from \"url\"\r\nimport { log } from \"./utils/logger\"\r\nimport { spawn } from \"child_process\"\r\nimport enquirer from \"enquirer\"\r\n\r\nconst __filename = fileURLToPath(import.meta.url)\r\nconst __dirname = path.dirname(__filename)\r\n\r\ntype Runtime = `bun` | `node`\r\ntype PackageManager = `bun` | `npm` | `pnpm` | `yarn`\r\ntype ProjectConfig = {\r\n projectName: string\r\n projectPath: string\r\n packageManager: PackageManager\r\n runtime: Runtime\r\n setupEslint: boolean\r\n}\r\n\r\nexport class Create {\r\n private config: ProjectConfig | undefined\r\n\r\n public constructor(private projectDirectory?: string) {\r\n // Constructor hanya menerima parameter, tidak melakukan execution\r\n }\r\n\r\n public printBanner() {\r\n const banner = `\r\n $$$$$$\\\\ $$\\\\ \r\n$$ __$$\\\\ $$ | \r\n$$ / \\\\__| $$$$$$\\\\ $$$$$$\\\\ $$$$$$\\\\$$$$\\\\ $$$$$$$\\\\ $$$$$$\\\\ $$$$$$\\\\ $$\\\\ $$\\\\ \r\n$$ |$$$$\\\\ $$ __$$\\\\ \\\\____$$\\\\ $$ _$$ _$$\\\\ $$ _____|\\\\_$$ _| \\\\____$$\\\\ \\\\$$\\\\ $$ |\r\n$$ |\\\\_$$ |$$ | \\\\__|$$$$$$$ |$$ / $$ / $$ |\\\\$$$$$$\\\\ $$ | $$$$$$$ | \\\\$$$$ / \r\n$$ | $$ |$$ | $$ __$$ |$$ | $$ | $$ | \\\\____$$\\\\ $$ |$$\\\\ $$ __$$ | $$ $$< \r\n\\\\$$$$$$ |$$ | \\\\$$$$$$$ |$$ | $$ | $$ |$$$$$$$ | \\\\$$$$ |\\\\$$$$$$$ |$$ /\\\\$$\\\\ \r\n \\\\______/ \\\\__| \\\\_______|\\\\__| \\\\__| \\\\__|\\\\_______/ \\\\____/ \\\\_______|\\\\__/ \\\\__|\r\n \r\n`\r\n console.log(banner)\r\n }\r\n\r\n private getPackageManagerCommands(packageManager: PackageManager) {\r\n const commands = {\r\n bun: {\r\n install: `bun install`,\r\n dev: `bun dev`,\r\n start: `bun start`,\r\n \"pm2:start\": `bun run pm2:start`,\r\n \"pm2:stop\": `bun run pm2:stop`,\r\n \"pm2:restart\": `bun run pm2:restart`,\r\n \"pm2:delete\": `bun run pm2:delete`,\r\n \"pm2:logs\": `bun run pm2:logs`,\r\n \"pm2:monit\": `bun run pm2:monit`\r\n },\r\n npm: {\r\n install: `npm install`,\r\n dev: `npm run dev`,\r\n start: `npm start`,\r\n \"pm2:start\": `npm run pm2:start`,\r\n \"pm2:stop\": `npm run pm2:stop`,\r\n \"pm2:restart\": `npm run pm2:restart`,\r\n \"pm2:delete\": `npm run pm2:delete`,\r\n \"pm2:logs\": `npm run pm2:logs`,\r\n \"pm2:monit\": `npm run pm2:monit`\r\n },\r\n pnpm: {\r\n install: `pnpm install`,\r\n dev: `pnpm dev`,\r\n start: `pnpm start`,\r\n \"pm2:start\": `pnpm pm2:start`,\r\n \"pm2:stop\": `pnpm pm2:stop`,\r\n \"pm2:restart\": `pnpm pm2:restart`,\r\n \"pm2:delete\": `pnpm pm2:delete`,\r\n \"pm2:logs\": `pnpm pm2:logs`,\r\n \"pm2:monit\": `pnpm pm2:monit`\r\n },\r\n yarn: {\r\n install: `yarn install`,\r\n dev: `yarn dev`,\r\n start: `yarn start`,\r\n \"pm2:start\": `yarn pm2:start`,\r\n \"pm2:stop\": `yarn pm2:stop`,\r\n \"pm2:restart\": `yarn pm2:restart`,\r\n \"pm2:delete\": `yarn pm2:delete`,\r\n \"pm2:logs\": `yarn pm2:logs`,\r\n \"pm2:monit\": `yarn pm2:monit`\r\n }\r\n }\r\n return commands[packageManager]\r\n }\r\n\r\n /**\r\n * Recursively copy directory structure\r\n */\r\n private copyDirectorySync(source: string, destination: string, variables: Record<string, string> = {}) {\r\n // Create destination directory if it doesn't exist\r\n if (!fs.existsSync(destination)) {\r\n fs.mkdirSync(destination, { recursive: true })\r\n }\r\n\r\n // Read all items in source directory\r\n const items = fs.readdirSync(source, { withFileTypes: true })\r\n\r\n for (const item of items) {\r\n const sourcePath = path.join(source, item.name)\r\n const destPath = path.join(destination, item.name)\r\n\r\n if (item.isDirectory()) {\r\n // Recursively copy subdirectories\r\n this.copyDirectorySync(sourcePath, destPath, variables)\r\n } else if (item.isFile()) {\r\n // Copy file and replace variables if needed\r\n let content = fs.readFileSync(sourcePath, `utf-8`)\r\n\r\n // Replace template variables in content\r\n content = this.replaceTemplateVariables(content, variables)\r\n\r\n fs.writeFileSync(destPath, content)\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Replace template variables in content\r\n */\r\n private replaceTemplateVariables(content: string, variables: Record<string, string>): string {\r\n let result = content\r\n for (const [key, value] of Object.entries(variables)) {\r\n result = result.replace(new RegExp(`{{${key}}}`, `g`), value)\r\n }\r\n return result\r\n }\r\n\r\n private async promptForProjectName(): Promise<string> {\r\n const response = await enquirer.prompt<{ projectName: string }>({\r\n type: `input`,\r\n name: `projectName`,\r\n message: `What is your project named?`,\r\n initial: ``,\r\n validate: (value: string) => {\r\n if (value === ``) {\r\n return true\r\n }\r\n\r\n if (!/^[a-z0-9-_]+$/i.test(value)) {\r\n return `Project name can only contain letters, numbers, hyphens, and underscores`\r\n }\r\n return true\r\n }\r\n })\r\n\r\n return response.projectName\r\n }\r\n\r\n private async promptForConfiguration(): Promise<{ packageManager: PackageManager; runtime: Runtime; eslint: boolean }> {\r\n const questions: any[] = []\r\n\r\n // Package manager selection\r\n questions.push({\r\n type: `select`,\r\n name: `packageManager`,\r\n message: `Which package manager would you like to use?`,\r\n choices: [\r\n { name: `bun`, message: `Bun (recommended)`, value: `bun` },\r\n { name: `npm`, message: `npm`, value: `npm` },\r\n { name: `pnpm`, message: `pnpm`, value: `pnpm` },\r\n { name: `yarn`, message: `Yarn`, value: `yarn` }\r\n ],\r\n initial: 0\r\n })\r\n\r\n // Runtime selection\r\n questions.push({\r\n type: `select`,\r\n name: `runtime`,\r\n message: `Which runtime would you like to use?`,\r\n choices: [\r\n { name: `bun`, message: `Bun (recommended)`, value: `bun` },\r\n { name: `node`, message: `Node.js`, value: `node` }\r\n ],\r\n initial: 0\r\n })\r\n\r\n // ESLint\r\n questions.push({\r\n type: `confirm`,\r\n name: `eslint`,\r\n message: `Would you like to use ESLint?`,\r\n initial: true\r\n })\r\n\r\n const answers = await enquirer.prompt<{\r\n packageManager?: PackageManager\r\n runtime: Runtime\r\n eslint?: boolean\r\n }>(questions)\r\n\r\n return {\r\n packageManager: answers.packageManager as any,\r\n runtime: answers.runtime,\r\n eslint: answers.eslint as boolean\r\n }\r\n }\r\n\r\n private async installDependencies(projectPath: string, packageManager: PackageManager): Promise<boolean> {\r\n return await new Promise((resolve, reject) => {\r\n const installCommand = packageManager\r\n const installArgs = [`install`]\r\n const installProcess = spawn(installCommand, installArgs, {\r\n cwd: projectPath,\r\n stdio: `inherit`,\r\n shell: true\r\n })\r\n\r\n installProcess.on(`close`, (code) => {\r\n if (code === 0) {\r\n resolve(true)\r\n } else {\r\n log.fail(`Dependencies installation failed`)\r\n resolve(false)\r\n }\r\n })\r\n\r\n installProcess.on(`error`, (error) => {\r\n log.fail(`Dependencies installation failed: ${error.message}`)\r\n resolve(false)\r\n })\r\n })\r\n }\r\n\r\n /**\r\n * Step 1: Gather all project configuration through prompts\r\n * NO EXECUTION - hanya mengumpulkan data dan validasi ringan\r\n */\r\n private async gatherProjectConfig(): Promise<ProjectConfig> {\r\n // Display ASCII art banner\r\n this.printBanner()\r\n\r\n // ========== PHASE 1: GET PROJECT NAME ==========\r\n let projectName = this.projectDirectory\r\n let projectPath: string\r\n let useCurrentDir = false\r\n\r\n if (!projectName) {\r\n // PROMPT untuk project name\r\n projectName = await this.promptForProjectName()\r\n if (projectName === ``) {\r\n // Empty name means use current directory\r\n projectName = path.basename(process.cwd())\r\n projectPath = process.cwd()\r\n useCurrentDir = true\r\n } else {\r\n projectPath = path.resolve(process.cwd(), projectName)\r\n useCurrentDir = false\r\n }\r\n } else {\r\n projectPath = path.resolve(process.cwd(), projectName)\r\n useCurrentDir = false\r\n }\r\n\r\n // PROMPT untuk configuration\r\n const config = await this.promptForConfiguration()\r\n const packageManager = config.packageManager\r\n const runtime = config.runtime\r\n const setupEslint = config.eslint\r\n\r\n // ========== SEMUA PROMPT SELESAI, SEKARANG VALIDASI ==========\r\n log.info(`Project: ${projectName}`)\r\n log.info(`Location: ${projectPath}`)\r\n log.info(`Package Manager: ${packageManager}`)\r\n log.info(`Runtime: ${runtime}`)\r\n log.info(`ESLint: ${setupEslint ? `Yes` : `No`}`)\r\n\r\n // Validasi setelah semua prompt selesai\r\n if (useCurrentDir) {\r\n // Check if current directory is empty\r\n const files = fs.readdirSync(projectPath)\r\n if (files.length > 0) {\r\n log.error(`Current directory is not empty!`)\r\n process.exit(1)\r\n }\r\n } else {\r\n // Check if directory already exists\r\n if (fs.existsSync(projectPath)) {\r\n log.error(`Directory \"${projectName}\" already exists!`)\r\n process.exit(1)\r\n }\r\n }\r\n\r\n return {\r\n projectName,\r\n projectPath,\r\n packageManager,\r\n runtime,\r\n setupEslint\r\n }\r\n }\r\n\r\n /**\r\n * Step 2: Execute project generation based on gathered config\r\n */\r\n private async executeProjectGeneration(config: ProjectConfig): Promise<void> {\r\n const { projectName, projectPath, packageManager, runtime, setupEslint } = config\r\n\r\n // Task 1: Create project directory\r\n log.info(`Creating project directory..`)\r\n if (!fs.existsSync(projectPath)) {\r\n fs.mkdirSync(projectPath, { recursive: true })\r\n }\r\n\r\n // Task 2: Copy template files\r\n log.info(`Copying template files..`)\r\n const templatesPath = path.join(__dirname, `templates`)\r\n const commands = this.getPackageManagerCommands(packageManager)\r\n\r\n const variables = {\r\n projectName,\r\n installCmd: commands.install,\r\n runDevCmd: commands.dev,\r\n runStartCmd: commands.start,\r\n runPm2StartCmd: commands[`pm2:start`],\r\n runPm2StopCmd: commands[`pm2:stop`],\r\n runPm2RestartCmd: commands[`pm2:restart`],\r\n runPm2DeleteCmd: commands[`pm2:delete`],\r\n runPm2LogsCmd: commands[`pm2:logs`],\r\n runPm2MonitCmd: commands[`pm2:monit`]\r\n }\r\n\r\n this.copyDirectorySync(templatesPath, projectPath, variables)\r\n\r\n // Task 3: Create logs directory\r\n log.info(`Creating logs directory..`)\r\n fs.mkdirSync(path.join(projectPath, `logs`), { recursive: true })\r\n fs.writeFileSync(path.join(projectPath, `logs/.gitkeep`), ``)\r\n\r\n // Task 4: Create .env.example\r\n const envPath = path.join(projectPath, `.env`)\r\n const envExamplePath = path.join(projectPath, `.env.example`)\r\n if (fs.existsSync(envExamplePath)) {\r\n log.info(`Creating .env file..`)\r\n fs.renameSync(envExamplePath, envPath)\r\n }\r\n\r\n // Task 5: Remove bunfig.toml if runtime is NOT bun\r\n if (runtime !== `bun`) {\r\n log.info(`Removing bunfig.toml for Node.js runtime..`)\r\n const bunfigPath = path.join(projectPath, `bunfig.toml`)\r\n if (fs.existsSync(bunfigPath)) {\r\n fs.unlinkSync(bunfigPath)\r\n }\r\n }\r\n\r\n // Task 6: tsconfig.json\r\n const tsconfigPath = path.join(projectPath, `tsconfig.json`)\r\n const tsconfigContent = fs.readFileSync(tsconfigPath, { encoding: `utf8` }).replace(`//{{types}}`, runtime == `bun` ? `\"bun-types\"` : ``)\r\n fs.writeFileSync(tsconfigPath, tsconfigContent, { encoding: `utf8` })\r\n\r\n // Task 6: Install dependencies\r\n log.info(`Installing dependencies..`)\r\n if (!(await this.installDependencies(projectPath, packageManager))) {\r\n log.fail(`Project created failed!`)\r\n return process.exit()\r\n }\r\n\r\n // Task 7: Setup ESLint if requested\r\n if (setupEslint) {\r\n log.info(`Setting up ESLint..`)\r\n await this.setupEslintConfig(projectPath, packageManager)\r\n }\r\n\r\n // Final success message\r\n log.info(`Project created successfully!`)\r\n log.info(`Next steps: ${config.projectPath !== process.cwd() ? `cd ${projectName} && ` : ` `}${commands.install} && ${commands.dev}`)\r\n log.info(`For production: ${commands[`pm2:start`]}`)\r\n log.info(`Done..`)\r\n }\r\n\r\n private async setupEslintConfig(projectPath: string, packageManager: PackageManager): Promise<void> {\r\n return new Promise((resolve) => {\r\n const initProcess = spawn(`npm`, [`init`, `@eslint/config@latest`], {\r\n cwd: projectPath,\r\n stdio: `inherit`,\r\n shell: true\r\n })\r\n\r\n initProcess.on(`close`, (code) => {\r\n if (code === 0) {\r\n resolve()\r\n } else {\r\n log.fail(`ESLint setup failed. You can set it up later with: npm init @eslint/config`)\r\n resolve()\r\n }\r\n })\r\n\r\n initProcess.on(`error`, (error) => {\r\n log.fail(`ESLint setup failed: ${error.message}`)\r\n log.info(`You can set it up later with: npm init @eslint/config`)\r\n resolve()\r\n })\r\n })\r\n }\r\n\r\n /**\r\n * Main public method: Prompt first, then execute\r\n */\r\n public async createProject() {\r\n try {\r\n // Step 1: Gather all configuration through prompts\r\n this.config = await this.gatherProjectConfig()\r\n\r\n // Step 2: Execute project generation with the gathered config\r\n await this.executeProjectGeneration(this.config)\r\n } catch (error) {\r\n if (error instanceof Error) {\r\n log.error(`Failed to create project: ${error.message}`)\r\n } else {\r\n log.error(`Failed to create project: ${String(error)}`)\r\n }\r\n process.exit(1)\r\n }\r\n }\r\n}\r\n","#!/usr/bin/env node\r\nimport { log } from \"./utils/logger\"\r\nimport { Create } from \"./create\"\r\nimport { Command } from \"commander\"\r\n\r\n// Read version from package.json\r\nconst version = `0.0.0`\r\nconst program = new Command()\r\n\r\nprogram\r\n .name(`create-gramstax`)\r\n .description(`CLI to create a new Gramstax Telegram bot project`)\r\n .version(version)\r\n .argument(`[project-directory]`, `Directory to create the project in`)\r\n .action(async (projectDirectory?: string) => {\r\n try {\r\n await new Create(projectDirectory).createProject()\r\n } catch (error) {\r\n log.error(`Failed to create project: ${String(error)}`)\r\n process.exit(1)\r\n }\r\n })\r\n\r\nprogram.parse()\r\n"],"mappings":"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","names":["import_logging_pretty","log","fs","path","import_url","import_child_process","import_enquirer","import_meta","__filename","import_meta","__dirname","Create","projectDirectory","__name","packageManager","source","destination","variables","items","item","sourcePath","destPath","content","result","key","value","enquirer","questions","answers","projectPath","resolve","reject","installProcess","code","log","error","projectName","useCurrentDir","config","runtime","setupEslint","templatesPath","commands","envPath","envExamplePath","bunfigPath","tsconfigPath","tsconfigContent","initProcess","import_commander","version","program","projectDirectory","Create","error","log"]}
|
package/dist/src/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var b=Object.defineProperty;var u=($,e)=>b($,"name",{value:e,configurable:!0});import{LoggingPretty as w}from"logging-pretty";var n=new w;import*as a from"fs";import*as
|
|
2
|
+
var b=Object.defineProperty;var u=($,e)=>b($,"name",{value:e,configurable:!0});import{LoggingPretty as w}from"logging-pretty";var n=new w;import*as a from"fs";import*as o from"path";import{fileURLToPath as C}from"url";import{spawn as y}from"child_process";import _ from"enquirer";var S=C(import.meta.url),k=o.dirname(S),l=class{constructor(e){this.projectDirectory=e}static{u(this,"Create")}config;printBanner(){console.log(`
|
|
3
3
|
$$$$$$\\ $$\\
|
|
4
4
|
$$ __$$\\ $$ |
|
|
5
5
|
$$ / \\__| $$$$$$\\ $$$$$$\\ $$$$$$\\$$$$\\ $$$$$$$\\ $$$$$$\\ $$$$$$\\ $$\\ $$\\
|
|
@@ -9,5 +9,5 @@ $$ | $$ |$$ | $$ __$$ |$$ | $$ | $$ | \\____$$\\ $$ |$$\\ $$ __$$ | $$
|
|
|
9
9
|
\\$$$$$$ |$$ | \\$$$$$$$ |$$ | $$ | $$ |$$$$$$$ | \\$$$$ |\\$$$$$$$ |$$ /\\$$\\
|
|
10
10
|
\\______/ \\__| \\_______|\\__| \\__| \\__|\\_______/ \\____/ \\_______|\\__/ \\__|
|
|
11
11
|
|
|
12
|
-
`)}getPackageManagerCommands(e){return{bun:{install:"bun install",dev:"bun dev",start:"bun start","pm2:start":"bun run pm2:start","pm2:stop":"bun run pm2:stop","pm2:restart":"bun run pm2:restart","pm2:delete":"bun run pm2:delete","pm2:logs":"bun run pm2:logs","pm2:monit":"bun run pm2:monit"},npm:{install:"npm install",dev:"npm run dev",start:"npm start","pm2:start":"npm run pm2:start","pm2:stop":"npm run pm2:stop","pm2:restart":"npm run pm2:restart","pm2:delete":"npm run pm2:delete","pm2:logs":"npm run pm2:logs","pm2:monit":"npm run pm2:monit"},pnpm:{install:"pnpm install",dev:"pnpm dev",start:"pnpm start","pm2:start":"pnpm pm2:start","pm2:stop":"pnpm pm2:stop","pm2:restart":"pnpm pm2:restart","pm2:delete":"pnpm pm2:delete","pm2:logs":"pnpm pm2:logs","pm2:monit":"pnpm pm2:monit"},yarn:{install:"yarn install",dev:"yarn dev",start:"yarn start","pm2:start":"yarn pm2:start","pm2:stop":"yarn pm2:stop","pm2:restart":"yarn pm2:restart","pm2:delete":"yarn pm2:delete","pm2:logs":"yarn pm2:logs","pm2:monit":"yarn pm2:monit"}}[e]}copyDirectorySync(e,r,t={}){a.existsSync(r)||a.mkdirSync(r,{recursive:!0});let
|
|
12
|
+
`)}getPackageManagerCommands(e){return{bun:{install:"bun install",dev:"bun dev",start:"bun start","pm2:start":"bun run pm2:start","pm2:stop":"bun run pm2:stop","pm2:restart":"bun run pm2:restart","pm2:delete":"bun run pm2:delete","pm2:logs":"bun run pm2:logs","pm2:monit":"bun run pm2:monit"},npm:{install:"npm install",dev:"npm run dev",start:"npm start","pm2:start":"npm run pm2:start","pm2:stop":"npm run pm2:stop","pm2:restart":"npm run pm2:restart","pm2:delete":"npm run pm2:delete","pm2:logs":"npm run pm2:logs","pm2:monit":"npm run pm2:monit"},pnpm:{install:"pnpm install",dev:"pnpm dev",start:"pnpm start","pm2:start":"pnpm pm2:start","pm2:stop":"pnpm pm2:stop","pm2:restart":"pnpm pm2:restart","pm2:delete":"pnpm pm2:delete","pm2:logs":"pnpm pm2:logs","pm2:monit":"pnpm pm2:monit"},yarn:{install:"yarn install",dev:"yarn dev",start:"yarn start","pm2:start":"yarn pm2:start","pm2:stop":"yarn pm2:stop","pm2:restart":"yarn pm2:restart","pm2:delete":"yarn pm2:delete","pm2:logs":"yarn pm2:logs","pm2:monit":"yarn pm2:monit"}}[e]}copyDirectorySync(e,r,t={}){a.existsSync(r)||a.mkdirSync(r,{recursive:!0});let p=a.readdirSync(e,{withFileTypes:!0});for(let s of p){let c=o.join(e,s.name),m=o.join(r,s.name);if(s.isDirectory())this.copyDirectorySync(c,m,t);else if(s.isFile()){let i=a.readFileSync(c,"utf-8");i=this.replaceTemplateVariables(i,t),a.writeFileSync(m,i)}}}replaceTemplateVariables(e,r){let t=e;for(let[p,s]of Object.entries(r))t=t.replace(new RegExp(`{{${p}}}`,"g"),s);return t}async promptForProjectName(){return(await _.prompt({type:"input",name:"projectName",message:"What is your project named?",initial:"",validate:u(r=>r===""||/^[a-z0-9-_]+$/i.test(r)?!0:"Project name can only contain letters, numbers, hyphens, and underscores","validate")})).projectName}async promptForConfiguration(){let e=[];e.push({type:"select",name:"packageManager",message:"Which package manager would you like to use?",choices:[{name:"bun",message:"Bun (recommended)",value:"bun"},{name:"npm",message:"npm",value:"npm"},{name:"pnpm",message:"pnpm",value:"pnpm"},{name:"yarn",message:"Yarn",value:"yarn"}],initial:0}),e.push({type:"select",name:"runtime",message:"Which runtime would you like to use?",choices:[{name:"bun",message:"Bun (recommended)",value:"bun"},{name:"node",message:"Node.js",value:"node"}],initial:0}),e.push({type:"confirm",name:"eslint",message:"Would you like to use ESLint?",initial:!0});let r=await _.prompt(e);return{packageManager:r.packageManager,runtime:r.runtime,eslint:r.eslint}}async installDependencies(e,r){return await new Promise((t,p)=>{let m=y(r,["install"],{cwd:e,stdio:"inherit",shell:!0});m.on("close",i=>{i===0?t(!0):(n.fail("Dependencies installation failed"),t(!1))}),m.on("error",i=>{n.fail(`Dependencies installation failed: ${i.message}`),t(!1)})})}async gatherProjectConfig(){this.printBanner();let e=this.projectDirectory,r,t=!1;e?(r=o.resolve(process.cwd(),e),t=!1):(e=await this.promptForProjectName(),e===""?(e=o.basename(process.cwd()),r=process.cwd(),t=!0):(r=o.resolve(process.cwd(),e),t=!1));let p=await this.promptForConfiguration(),s=p.packageManager,c=p.runtime,m=p.eslint;return n.info(`Project: ${e}`),n.info(`Location: ${r}`),n.info(`Package Manager: ${s}`),n.info(`Runtime: ${c}`),n.info(`ESLint: ${m?"Yes":"No"}`),t?a.readdirSync(r).length>0&&(n.error("Current directory is not empty!"),process.exit(1)):a.existsSync(r)&&(n.error(`Directory "${e}" already exists!`),process.exit(1)),{projectName:e,projectPath:r,packageManager:s,runtime:c,setupEslint:m}}async executeProjectGeneration(e){let{projectName:r,projectPath:t,packageManager:p,runtime:s,setupEslint:c}=e;n.info("Creating project directory.."),a.existsSync(t)||a.mkdirSync(t,{recursive:!0}),n.info("Copying template files..");let m=o.join(k,"templates"),i=this.getPackageManagerCommands(p),P={projectName:r,installCmd:i.install,runDevCmd:i.dev,runStartCmd:i.start,runPm2StartCmd:i["pm2:start"],runPm2StopCmd:i["pm2:stop"],runPm2RestartCmd:i["pm2:restart"],runPm2DeleteCmd:i["pm2:delete"],runPm2LogsCmd:i["pm2:logs"],runPm2MonitCmd:i["pm2:monit"]};this.copyDirectorySync(m,t,P),n.info("Creating logs directory.."),a.mkdirSync(o.join(t,"logs"),{recursive:!0}),a.writeFileSync(o.join(t,"logs/.gitkeep"),"");let j=o.join(t,".env"),g=o.join(t,".env.example");if(a.existsSync(g)&&(n.info("Creating .env file.."),a.renameSync(g,j)),s!=="bun"){n.info("Removing bunfig.toml for Node.js runtime..");let d=o.join(t,"bunfig.toml");a.existsSync(d)&&a.unlinkSync(d)}let f=o.join(t,"tsconfig.json"),v=a.readFileSync(f,{encoding:"utf8"}).replace("//{{types}}",s=="bun"?'"bun-types"':"");if(a.writeFileSync(f,v,{encoding:"utf8"}),n.info("Installing dependencies.."),!await this.installDependencies(t,p))return n.fail("Project created failed!"),process.exit();c&&(n.info("Setting up ESLint.."),await this.setupEslintConfig(t,p)),n.info("Project created successfully!"),n.info(`Next steps: ${e.projectPath!==process.cwd()?`cd ${r} && `:" "}${i.install} && ${i.dev}`),n.info(`For production: ${i["pm2:start"]}`),n.info("Done..")}async setupEslintConfig(e,r){return new Promise(t=>{let p=y("npm",["init","@eslint/config@latest"],{cwd:e,stdio:"inherit",shell:!0});p.on("close",s=>{s===0||n.fail("ESLint setup failed. You can set it up later with: npm init @eslint/config"),t()}),p.on("error",s=>{n.fail(`ESLint setup failed: ${s.message}`),n.info("You can set it up later with: npm init @eslint/config"),t()})})}async createProject(){try{this.config=await this.gatherProjectConfig(),await this.executeProjectGeneration(this.config)}catch(e){e instanceof Error?n.error(`Failed to create project: ${e.message}`):n.error(`Failed to create project: ${String(e)}`),process.exit(1)}}};import{Command as x}from"commander";var M="0.0.0",h=new x;h.name("create-gramstax").description("CLI to create a new Gramstax Telegram bot project").version(M).argument("[project-directory]","Directory to create the project in").action(async $=>{try{await new l($).createProject()}catch(e){n.error(`Failed to create project: ${String(e)}`),process.exit(1)}});h.parse();
|
|
13
13
|
//# sourceMappingURL=index.js.map
|
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utils/logger.ts","../../src/create.ts","../../src/index.ts"],"sourcesContent":["import { LoggingPretty } from \"logging-pretty\"\r\n\r\nexport const log = new LoggingPretty()\r\n","import * as fs from \"fs\"\r\nimport * as path from \"path\"\r\nimport { log } from \"./utils/logger\"\r\nimport { spawn } from \"child_process\"\r\nimport enquirer from \"enquirer\"\r\n\r\ntype Runtime = `bun` | `node`\r\ntype PackageManager = `bun` | `npm` | `pnpm` | `yarn`\r\ntype ProjectConfig = {\r\n projectName: string\r\n projectPath: string\r\n packageManager: PackageManager\r\n runtime: Runtime\r\n setupEslint: boolean\r\n}\r\n\r\nexport class Create {\r\n private config: ProjectConfig | undefined\r\n\r\n public constructor(private projectDirectory?: string) {\r\n // Constructor hanya menerima parameter, tidak melakukan execution\r\n }\r\n\r\n public printBanner() {\r\n const banner = `\r\n $$$$$$\\\\ $$\\\\ \r\n$$ __$$\\\\ $$ | \r\n$$ / \\\\__| $$$$$$\\\\ $$$$$$\\\\ $$$$$$\\\\$$$$\\\\ $$$$$$$\\\\ $$$$$$\\\\ $$$$$$\\\\ $$\\\\ $$\\\\ \r\n$$ |$$$$\\\\ $$ __$$\\\\ \\\\____$$\\\\ $$ _$$ _$$\\\\ $$ _____|\\\\_$$ _| \\\\____$$\\\\ \\\\$$\\\\ $$ |\r\n$$ |\\\\_$$ |$$ | \\\\__|$$$$$$$ |$$ / $$ / $$ |\\\\$$$$$$\\\\ $$ | $$$$$$$ | \\\\$$$$ / \r\n$$ | $$ |$$ | $$ __$$ |$$ | $$ | $$ | \\\\____$$\\\\ $$ |$$\\\\ $$ __$$ | $$ $$< \r\n\\\\$$$$$$ |$$ | \\\\$$$$$$$ |$$ | $$ | $$ |$$$$$$$ | \\\\$$$$ |\\\\$$$$$$$ |$$ /\\\\$$\\\\ \r\n \\\\______/ \\\\__| \\\\_______|\\\\__| \\\\__| \\\\__|\\\\_______/ \\\\____/ \\\\_______|\\\\__/ \\\\__|\r\n \r\n`\r\n console.log(banner)\r\n }\r\n\r\n private getPackageManagerCommands(packageManager: PackageManager) {\r\n const commands = {\r\n bun: {\r\n install: `bun install`,\r\n dev: `bun dev`,\r\n start: `bun start`,\r\n \"pm2:start\": `bun run pm2:start`,\r\n \"pm2:stop\": `bun run pm2:stop`,\r\n \"pm2:restart\": `bun run pm2:restart`,\r\n \"pm2:delete\": `bun run pm2:delete`,\r\n \"pm2:logs\": `bun run pm2:logs`,\r\n \"pm2:monit\": `bun run pm2:monit`\r\n },\r\n npm: {\r\n install: `npm install`,\r\n dev: `npm run dev`,\r\n start: `npm start`,\r\n \"pm2:start\": `npm run pm2:start`,\r\n \"pm2:stop\": `npm run pm2:stop`,\r\n \"pm2:restart\": `npm run pm2:restart`,\r\n \"pm2:delete\": `npm run pm2:delete`,\r\n \"pm2:logs\": `npm run pm2:logs`,\r\n \"pm2:monit\": `npm run pm2:monit`\r\n },\r\n pnpm: {\r\n install: `pnpm install`,\r\n dev: `pnpm dev`,\r\n start: `pnpm start`,\r\n \"pm2:start\": `pnpm pm2:start`,\r\n \"pm2:stop\": `pnpm pm2:stop`,\r\n \"pm2:restart\": `pnpm pm2:restart`,\r\n \"pm2:delete\": `pnpm pm2:delete`,\r\n \"pm2:logs\": `pnpm pm2:logs`,\r\n \"pm2:monit\": `pnpm pm2:monit`\r\n },\r\n yarn: {\r\n install: `yarn install`,\r\n dev: `yarn dev`,\r\n start: `yarn start`,\r\n \"pm2:start\": `yarn pm2:start`,\r\n \"pm2:stop\": `yarn pm2:stop`,\r\n \"pm2:restart\": `yarn pm2:restart`,\r\n \"pm2:delete\": `yarn pm2:delete`,\r\n \"pm2:logs\": `yarn pm2:logs`,\r\n \"pm2:monit\": `yarn pm2:monit`\r\n }\r\n }\r\n return commands[packageManager]\r\n }\r\n\r\n /**\r\n * Recursively copy directory structure\r\n */\r\n private copyDirectorySync(source: string, destination: string, variables: Record<string, string> = {}) {\r\n // Create destination directory if it doesn't exist\r\n if (!fs.existsSync(destination)) {\r\n fs.mkdirSync(destination, { recursive: true })\r\n }\r\n\r\n // Read all items in source directory\r\n const items = fs.readdirSync(source, { withFileTypes: true })\r\n\r\n for (const item of items) {\r\n const sourcePath = path.join(source, item.name)\r\n const destPath = path.join(destination, item.name)\r\n\r\n if (item.isDirectory()) {\r\n // Recursively copy subdirectories\r\n this.copyDirectorySync(sourcePath, destPath, variables)\r\n } else if (item.isFile()) {\r\n // Copy file and replace variables if needed\r\n let content = fs.readFileSync(sourcePath, `utf-8`)\r\n\r\n // Replace template variables in content\r\n content = this.replaceTemplateVariables(content, variables)\r\n\r\n fs.writeFileSync(destPath, content)\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Replace template variables in content\r\n */\r\n private replaceTemplateVariables(content: string, variables: Record<string, string>): string {\r\n let result = content\r\n for (const [key, value] of Object.entries(variables)) {\r\n result = result.replace(new RegExp(`{{${key}}}`, `g`), value)\r\n }\r\n return result\r\n }\r\n\r\n private async promptForProjectName(): Promise<string> {\r\n const response = await enquirer.prompt<{ projectName: string }>({\r\n type: `input`,\r\n name: `projectName`,\r\n message: `What is your project named?`,\r\n initial: ``,\r\n validate: (value: string) => {\r\n if (value === ``) {\r\n return true\r\n }\r\n\r\n if (!/^[a-z0-9-_]+$/i.test(value)) {\r\n return `Project name can only contain letters, numbers, hyphens, and underscores`\r\n }\r\n return true\r\n }\r\n })\r\n\r\n return response.projectName\r\n }\r\n\r\n private async promptForConfiguration(): Promise<{ packageManager: PackageManager; runtime: Runtime; eslint: boolean }> {\r\n const questions: any[] = []\r\n\r\n // Package manager selection\r\n questions.push({\r\n type: `select`,\r\n name: `packageManager`,\r\n message: `Which package manager would you like to use?`,\r\n choices: [\r\n { name: `bun`, message: `Bun (recommended)`, value: `bun` },\r\n { name: `npm`, message: `npm`, value: `npm` },\r\n { name: `pnpm`, message: `pnpm`, value: `pnpm` },\r\n { name: `yarn`, message: `Yarn`, value: `yarn` }\r\n ],\r\n initial: 0\r\n })\r\n\r\n // Runtime selection\r\n questions.push({\r\n type: `select`,\r\n name: `runtime`,\r\n message: `Which runtime would you like to use?`,\r\n choices: [\r\n { name: `bun`, message: `Bun (recommended)`, value: `bun` },\r\n { name: `node`, message: `Node.js`, value: `node` }\r\n ],\r\n initial: 0\r\n })\r\n\r\n // ESLint\r\n questions.push({\r\n type: `confirm`,\r\n name: `eslint`,\r\n message: `Would you like to use ESLint?`,\r\n initial: true\r\n })\r\n\r\n const answers = await enquirer.prompt<{\r\n packageManager?: PackageManager\r\n runtime: Runtime\r\n eslint?: boolean\r\n }>(questions)\r\n\r\n return {\r\n packageManager: answers.packageManager as any,\r\n runtime: answers.runtime,\r\n eslint: answers.eslint as boolean\r\n }\r\n }\r\n\r\n private async installDependencies(projectPath: string, packageManager: PackageManager): Promise<boolean> {\r\n return await new Promise((resolve, reject) => {\r\n const installCommand = packageManager\r\n const installArgs = [`install`]\r\n const installProcess = spawn(installCommand, installArgs, {\r\n cwd: projectPath,\r\n stdio: `inherit`,\r\n shell: true\r\n })\r\n\r\n installProcess.on(`close`, (code) => {\r\n if (code === 0) {\r\n resolve(true)\r\n } else {\r\n log.fail(`Dependencies installation failed`)\r\n resolve(false)\r\n }\r\n })\r\n\r\n installProcess.on(`error`, (error) => {\r\n log.fail(`Dependencies installation failed: ${error.message}`)\r\n resolve(false)\r\n })\r\n })\r\n }\r\n\r\n /**\r\n * Step 1: Gather all project configuration through prompts\r\n * NO EXECUTION - hanya mengumpulkan data dan validasi ringan\r\n */\r\n private async gatherProjectConfig(): Promise<ProjectConfig> {\r\n // Display ASCII art banner\r\n this.printBanner()\r\n\r\n // ========== PHASE 1: GET PROJECT NAME ==========\r\n let projectName = this.projectDirectory\r\n let projectPath: string\r\n let useCurrentDir = false\r\n\r\n if (!projectName) {\r\n // PROMPT untuk project name\r\n projectName = await this.promptForProjectName()\r\n if (projectName === ``) {\r\n // Empty name means use current directory\r\n projectName = path.basename(process.cwd())\r\n projectPath = process.cwd()\r\n useCurrentDir = true\r\n } else {\r\n projectPath = path.resolve(process.cwd(), projectName)\r\n useCurrentDir = false\r\n }\r\n } else {\r\n projectPath = path.resolve(process.cwd(), projectName)\r\n useCurrentDir = false\r\n }\r\n\r\n // PROMPT untuk configuration\r\n const config = await this.promptForConfiguration()\r\n const packageManager = config.packageManager\r\n const runtime = config.runtime\r\n const setupEslint = config.eslint\r\n\r\n // ========== SEMUA PROMPT SELESAI, SEKARANG VALIDASI ==========\r\n log.info(`Project: ${projectName}`)\r\n log.info(`Location: ${projectPath}`)\r\n log.info(`Package Manager: ${packageManager}`)\r\n log.info(`Runtime: ${runtime}`)\r\n log.info(`ESLint: ${setupEslint ? `Yes` : `No`}`)\r\n\r\n // Validasi setelah semua prompt selesai\r\n if (useCurrentDir) {\r\n // Check if current directory is empty\r\n const files = fs.readdirSync(projectPath)\r\n if (files.length > 0) {\r\n log.error(`Current directory is not empty!`)\r\n process.exit(1)\r\n }\r\n } else {\r\n // Check if directory already exists\r\n if (fs.existsSync(projectPath)) {\r\n log.error(`Directory \"${projectName}\" already exists!`)\r\n process.exit(1)\r\n }\r\n }\r\n\r\n return {\r\n projectName,\r\n projectPath,\r\n packageManager,\r\n runtime,\r\n setupEslint\r\n }\r\n }\r\n\r\n /**\r\n * Step 2: Execute project generation based on gathered config\r\n */\r\n private async executeProjectGeneration(config: ProjectConfig): Promise<void> {\r\n const { projectName, projectPath, packageManager, runtime, setupEslint } = config\r\n\r\n // Task 1: Create project directory\r\n log.info(`Creating project directory..`)\r\n if (!fs.existsSync(projectPath)) {\r\n fs.mkdirSync(projectPath, { recursive: true })\r\n }\r\n\r\n // Task 2: Copy template files\r\n log.info(`Copying template files..`)\r\n const templatesPath = path.join(__dirname, `templates`)\r\n const commands = this.getPackageManagerCommands(packageManager)\r\n\r\n const variables = {\r\n projectName,\r\n installCmd: commands.install,\r\n runDevCmd: commands.dev,\r\n runStartCmd: commands.start,\r\n runPm2StartCmd: commands[`pm2:start`],\r\n runPm2StopCmd: commands[`pm2:stop`],\r\n runPm2RestartCmd: commands[`pm2:restart`],\r\n runPm2DeleteCmd: commands[`pm2:delete`],\r\n runPm2LogsCmd: commands[`pm2:logs`],\r\n runPm2MonitCmd: commands[`pm2:monit`]\r\n }\r\n\r\n this.copyDirectorySync(templatesPath, projectPath, variables)\r\n\r\n // Task 3: Create logs directory\r\n log.info(`Creating logs directory..`)\r\n fs.mkdirSync(path.join(projectPath, `logs`), { recursive: true })\r\n fs.writeFileSync(path.join(projectPath, `logs/.gitkeep`), ``)\r\n\r\n // Task 4: Create .env.example\r\n const envPath = path.join(projectPath, `.env`)\r\n const envExamplePath = path.join(projectPath, `.env.example`)\r\n if (fs.existsSync(envExamplePath)) {\r\n log.info(`Creating .env file..`)\r\n fs.renameSync(envExamplePath, envPath)\r\n }\r\n\r\n // Task 5: Remove bunfig.toml if runtime is NOT bun\r\n if (runtime !== `bun`) {\r\n log.info(`Removing bunfig.toml for Node.js runtime..`)\r\n const bunfigPath = path.join(projectPath, `bunfig.toml`)\r\n if (fs.existsSync(bunfigPath)) {\r\n fs.unlinkSync(bunfigPath)\r\n }\r\n }\r\n\r\n // Task 6: tsconfig.json\r\n const tsconfigPath = path.join(projectPath, `tsconfig.json`)\r\n const tsconfigContent = fs.readFileSync(tsconfigPath, { encoding: `utf8` }).replace(`//{{types}}`, runtime == `bun` ? `bun-types` : ``)\r\n fs.writeFileSync(tsconfigPath, tsconfigContent, { encoding: `utf8` })\r\n\r\n // Task 6: Install dependencies\r\n log.info(`Installing dependencies..`)\r\n if (!(await this.installDependencies(projectPath, packageManager))) {\r\n log.fail(`Project created failed!`)\r\n return process.exit()\r\n }\r\n\r\n // Task 7: Setup ESLint if requested\r\n if (setupEslint) {\r\n log.info(`Setting up ESLint..`)\r\n await this.setupEslintConfig(projectPath, packageManager)\r\n }\r\n\r\n // Final success message\r\n log.info(`Project created successfully!`)\r\n log.info(`Next steps: ${config.projectPath !== process.cwd() ? `cd ${projectName} && ` : ` `}${commands.install} && ${commands.dev}`)\r\n log.info(`For production: ${commands[`pm2:start`]}`)\r\n log.info(`Done..`)\r\n }\r\n\r\n private async setupEslintConfig(projectPath: string, packageManager: PackageManager): Promise<void> {\r\n return new Promise((resolve) => {\r\n const initProcess = spawn(`npm`, [`init`, `@eslint/config@latest`], {\r\n cwd: projectPath,\r\n stdio: `inherit`,\r\n shell: true\r\n })\r\n\r\n initProcess.on(`close`, (code) => {\r\n if (code === 0) {\r\n resolve()\r\n } else {\r\n log.fail(`ESLint setup failed. You can set it up later with: npm init @eslint/config`)\r\n resolve()\r\n }\r\n })\r\n\r\n initProcess.on(`error`, (error) => {\r\n log.fail(`ESLint setup failed: ${error.message}`)\r\n log.info(`You can set it up later with: npm init @eslint/config`)\r\n resolve()\r\n })\r\n })\r\n }\r\n\r\n /**\r\n * Main public method: Prompt first, then execute\r\n */\r\n public async createProject() {\r\n try {\r\n // Step 1: Gather all configuration through prompts\r\n this.config = await this.gatherProjectConfig()\r\n\r\n // Step 2: Execute project generation with the gathered config\r\n await this.executeProjectGeneration(this.config)\r\n } catch (error) {\r\n if (error instanceof Error) {\r\n log.error(`Failed to create project: ${error.message}`)\r\n } else {\r\n log.error(`Failed to create project: ${String(error)}`)\r\n }\r\n process.exit(1)\r\n }\r\n }\r\n}\r\n","#!/usr/bin/env node\r\nimport { log } from \"./utils/logger\"\r\nimport { Create } from \"./create\"\r\nimport { Command } from \"commander\"\r\n\r\n// Read version from package.json\r\nconst version = `0.0.0`\r\nconst program = new Command()\r\n\r\nprogram\r\n .name(`create-gramstax`)\r\n .description(`CLI to create a new Gramstax Telegram bot project`)\r\n .version(version)\r\n .argument(`[project-directory]`, `Directory to create the project in`)\r\n .action(async (projectDirectory?: string) => {\r\n try {\r\n await new Create(projectDirectory).createProject()\r\n } catch (error) {\r\n log.error(`Failed to create project: ${String(error)}`)\r\n process.exit(1)\r\n }\r\n })\r\n\r\nprogram.parse()\r\n"],"mappings":"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","names":["LoggingPretty","log","fs","path","spawn","enquirer","Create","projectDirectory","__name","packageManager","source","destination","variables","items","item","sourcePath","destPath","content","result","key","value","enquirer","questions","answers","projectPath","resolve","reject","installProcess","spawn","code","log","error","projectName","useCurrentDir","config","runtime","setupEslint","templatesPath","commands","envPath","envExamplePath","bunfigPath","tsconfigPath","tsconfigContent","initProcess","Command","version","program","projectDirectory","Create","error","log"]}
|
|
1
|
+
{"version":3,"sources":["../../src/utils/logger.ts","../../src/create.ts","../../src/index.ts"],"sourcesContent":["import { LoggingPretty } from \"logging-pretty\"\r\n\r\nexport const log = new LoggingPretty()\r\n","import * as fs from \"fs\"\r\nimport * as path from \"path\"\r\nimport { fileURLToPath } from \"url\"\r\nimport { log } from \"./utils/logger\"\r\nimport { spawn } from \"child_process\"\r\nimport enquirer from \"enquirer\"\r\n\r\nconst __filename = fileURLToPath(import.meta.url)\r\nconst __dirname = path.dirname(__filename)\r\n\r\ntype Runtime = `bun` | `node`\r\ntype PackageManager = `bun` | `npm` | `pnpm` | `yarn`\r\ntype ProjectConfig = {\r\n projectName: string\r\n projectPath: string\r\n packageManager: PackageManager\r\n runtime: Runtime\r\n setupEslint: boolean\r\n}\r\n\r\nexport class Create {\r\n private config: ProjectConfig | undefined\r\n\r\n public constructor(private projectDirectory?: string) {\r\n // Constructor hanya menerima parameter, tidak melakukan execution\r\n }\r\n\r\n public printBanner() {\r\n const banner = `\r\n $$$$$$\\\\ $$\\\\ \r\n$$ __$$\\\\ $$ | \r\n$$ / \\\\__| $$$$$$\\\\ $$$$$$\\\\ $$$$$$\\\\$$$$\\\\ $$$$$$$\\\\ $$$$$$\\\\ $$$$$$\\\\ $$\\\\ $$\\\\ \r\n$$ |$$$$\\\\ $$ __$$\\\\ \\\\____$$\\\\ $$ _$$ _$$\\\\ $$ _____|\\\\_$$ _| \\\\____$$\\\\ \\\\$$\\\\ $$ |\r\n$$ |\\\\_$$ |$$ | \\\\__|$$$$$$$ |$$ / $$ / $$ |\\\\$$$$$$\\\\ $$ | $$$$$$$ | \\\\$$$$ / \r\n$$ | $$ |$$ | $$ __$$ |$$ | $$ | $$ | \\\\____$$\\\\ $$ |$$\\\\ $$ __$$ | $$ $$< \r\n\\\\$$$$$$ |$$ | \\\\$$$$$$$ |$$ | $$ | $$ |$$$$$$$ | \\\\$$$$ |\\\\$$$$$$$ |$$ /\\\\$$\\\\ \r\n \\\\______/ \\\\__| \\\\_______|\\\\__| \\\\__| \\\\__|\\\\_______/ \\\\____/ \\\\_______|\\\\__/ \\\\__|\r\n \r\n`\r\n console.log(banner)\r\n }\r\n\r\n private getPackageManagerCommands(packageManager: PackageManager) {\r\n const commands = {\r\n bun: {\r\n install: `bun install`,\r\n dev: `bun dev`,\r\n start: `bun start`,\r\n \"pm2:start\": `bun run pm2:start`,\r\n \"pm2:stop\": `bun run pm2:stop`,\r\n \"pm2:restart\": `bun run pm2:restart`,\r\n \"pm2:delete\": `bun run pm2:delete`,\r\n \"pm2:logs\": `bun run pm2:logs`,\r\n \"pm2:monit\": `bun run pm2:monit`\r\n },\r\n npm: {\r\n install: `npm install`,\r\n dev: `npm run dev`,\r\n start: `npm start`,\r\n \"pm2:start\": `npm run pm2:start`,\r\n \"pm2:stop\": `npm run pm2:stop`,\r\n \"pm2:restart\": `npm run pm2:restart`,\r\n \"pm2:delete\": `npm run pm2:delete`,\r\n \"pm2:logs\": `npm run pm2:logs`,\r\n \"pm2:monit\": `npm run pm2:monit`\r\n },\r\n pnpm: {\r\n install: `pnpm install`,\r\n dev: `pnpm dev`,\r\n start: `pnpm start`,\r\n \"pm2:start\": `pnpm pm2:start`,\r\n \"pm2:stop\": `pnpm pm2:stop`,\r\n \"pm2:restart\": `pnpm pm2:restart`,\r\n \"pm2:delete\": `pnpm pm2:delete`,\r\n \"pm2:logs\": `pnpm pm2:logs`,\r\n \"pm2:monit\": `pnpm pm2:monit`\r\n },\r\n yarn: {\r\n install: `yarn install`,\r\n dev: `yarn dev`,\r\n start: `yarn start`,\r\n \"pm2:start\": `yarn pm2:start`,\r\n \"pm2:stop\": `yarn pm2:stop`,\r\n \"pm2:restart\": `yarn pm2:restart`,\r\n \"pm2:delete\": `yarn pm2:delete`,\r\n \"pm2:logs\": `yarn pm2:logs`,\r\n \"pm2:monit\": `yarn pm2:monit`\r\n }\r\n }\r\n return commands[packageManager]\r\n }\r\n\r\n /**\r\n * Recursively copy directory structure\r\n */\r\n private copyDirectorySync(source: string, destination: string, variables: Record<string, string> = {}) {\r\n // Create destination directory if it doesn't exist\r\n if (!fs.existsSync(destination)) {\r\n fs.mkdirSync(destination, { recursive: true })\r\n }\r\n\r\n // Read all items in source directory\r\n const items = fs.readdirSync(source, { withFileTypes: true })\r\n\r\n for (const item of items) {\r\n const sourcePath = path.join(source, item.name)\r\n const destPath = path.join(destination, item.name)\r\n\r\n if (item.isDirectory()) {\r\n // Recursively copy subdirectories\r\n this.copyDirectorySync(sourcePath, destPath, variables)\r\n } else if (item.isFile()) {\r\n // Copy file and replace variables if needed\r\n let content = fs.readFileSync(sourcePath, `utf-8`)\r\n\r\n // Replace template variables in content\r\n content = this.replaceTemplateVariables(content, variables)\r\n\r\n fs.writeFileSync(destPath, content)\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Replace template variables in content\r\n */\r\n private replaceTemplateVariables(content: string, variables: Record<string, string>): string {\r\n let result = content\r\n for (const [key, value] of Object.entries(variables)) {\r\n result = result.replace(new RegExp(`{{${key}}}`, `g`), value)\r\n }\r\n return result\r\n }\r\n\r\n private async promptForProjectName(): Promise<string> {\r\n const response = await enquirer.prompt<{ projectName: string }>({\r\n type: `input`,\r\n name: `projectName`,\r\n message: `What is your project named?`,\r\n initial: ``,\r\n validate: (value: string) => {\r\n if (value === ``) {\r\n return true\r\n }\r\n\r\n if (!/^[a-z0-9-_]+$/i.test(value)) {\r\n return `Project name can only contain letters, numbers, hyphens, and underscores`\r\n }\r\n return true\r\n }\r\n })\r\n\r\n return response.projectName\r\n }\r\n\r\n private async promptForConfiguration(): Promise<{ packageManager: PackageManager; runtime: Runtime; eslint: boolean }> {\r\n const questions: any[] = []\r\n\r\n // Package manager selection\r\n questions.push({\r\n type: `select`,\r\n name: `packageManager`,\r\n message: `Which package manager would you like to use?`,\r\n choices: [\r\n { name: `bun`, message: `Bun (recommended)`, value: `bun` },\r\n { name: `npm`, message: `npm`, value: `npm` },\r\n { name: `pnpm`, message: `pnpm`, value: `pnpm` },\r\n { name: `yarn`, message: `Yarn`, value: `yarn` }\r\n ],\r\n initial: 0\r\n })\r\n\r\n // Runtime selection\r\n questions.push({\r\n type: `select`,\r\n name: `runtime`,\r\n message: `Which runtime would you like to use?`,\r\n choices: [\r\n { name: `bun`, message: `Bun (recommended)`, value: `bun` },\r\n { name: `node`, message: `Node.js`, value: `node` }\r\n ],\r\n initial: 0\r\n })\r\n\r\n // ESLint\r\n questions.push({\r\n type: `confirm`,\r\n name: `eslint`,\r\n message: `Would you like to use ESLint?`,\r\n initial: true\r\n })\r\n\r\n const answers = await enquirer.prompt<{\r\n packageManager?: PackageManager\r\n runtime: Runtime\r\n eslint?: boolean\r\n }>(questions)\r\n\r\n return {\r\n packageManager: answers.packageManager as any,\r\n runtime: answers.runtime,\r\n eslint: answers.eslint as boolean\r\n }\r\n }\r\n\r\n private async installDependencies(projectPath: string, packageManager: PackageManager): Promise<boolean> {\r\n return await new Promise((resolve, reject) => {\r\n const installCommand = packageManager\r\n const installArgs = [`install`]\r\n const installProcess = spawn(installCommand, installArgs, {\r\n cwd: projectPath,\r\n stdio: `inherit`,\r\n shell: true\r\n })\r\n\r\n installProcess.on(`close`, (code) => {\r\n if (code === 0) {\r\n resolve(true)\r\n } else {\r\n log.fail(`Dependencies installation failed`)\r\n resolve(false)\r\n }\r\n })\r\n\r\n installProcess.on(`error`, (error) => {\r\n log.fail(`Dependencies installation failed: ${error.message}`)\r\n resolve(false)\r\n })\r\n })\r\n }\r\n\r\n /**\r\n * Step 1: Gather all project configuration through prompts\r\n * NO EXECUTION - hanya mengumpulkan data dan validasi ringan\r\n */\r\n private async gatherProjectConfig(): Promise<ProjectConfig> {\r\n // Display ASCII art banner\r\n this.printBanner()\r\n\r\n // ========== PHASE 1: GET PROJECT NAME ==========\r\n let projectName = this.projectDirectory\r\n let projectPath: string\r\n let useCurrentDir = false\r\n\r\n if (!projectName) {\r\n // PROMPT untuk project name\r\n projectName = await this.promptForProjectName()\r\n if (projectName === ``) {\r\n // Empty name means use current directory\r\n projectName = path.basename(process.cwd())\r\n projectPath = process.cwd()\r\n useCurrentDir = true\r\n } else {\r\n projectPath = path.resolve(process.cwd(), projectName)\r\n useCurrentDir = false\r\n }\r\n } else {\r\n projectPath = path.resolve(process.cwd(), projectName)\r\n useCurrentDir = false\r\n }\r\n\r\n // PROMPT untuk configuration\r\n const config = await this.promptForConfiguration()\r\n const packageManager = config.packageManager\r\n const runtime = config.runtime\r\n const setupEslint = config.eslint\r\n\r\n // ========== SEMUA PROMPT SELESAI, SEKARANG VALIDASI ==========\r\n log.info(`Project: ${projectName}`)\r\n log.info(`Location: ${projectPath}`)\r\n log.info(`Package Manager: ${packageManager}`)\r\n log.info(`Runtime: ${runtime}`)\r\n log.info(`ESLint: ${setupEslint ? `Yes` : `No`}`)\r\n\r\n // Validasi setelah semua prompt selesai\r\n if (useCurrentDir) {\r\n // Check if current directory is empty\r\n const files = fs.readdirSync(projectPath)\r\n if (files.length > 0) {\r\n log.error(`Current directory is not empty!`)\r\n process.exit(1)\r\n }\r\n } else {\r\n // Check if directory already exists\r\n if (fs.existsSync(projectPath)) {\r\n log.error(`Directory \"${projectName}\" already exists!`)\r\n process.exit(1)\r\n }\r\n }\r\n\r\n return {\r\n projectName,\r\n projectPath,\r\n packageManager,\r\n runtime,\r\n setupEslint\r\n }\r\n }\r\n\r\n /**\r\n * Step 2: Execute project generation based on gathered config\r\n */\r\n private async executeProjectGeneration(config: ProjectConfig): Promise<void> {\r\n const { projectName, projectPath, packageManager, runtime, setupEslint } = config\r\n\r\n // Task 1: Create project directory\r\n log.info(`Creating project directory..`)\r\n if (!fs.existsSync(projectPath)) {\r\n fs.mkdirSync(projectPath, { recursive: true })\r\n }\r\n\r\n // Task 2: Copy template files\r\n log.info(`Copying template files..`)\r\n const templatesPath = path.join(__dirname, `templates`)\r\n const commands = this.getPackageManagerCommands(packageManager)\r\n\r\n const variables = {\r\n projectName,\r\n installCmd: commands.install,\r\n runDevCmd: commands.dev,\r\n runStartCmd: commands.start,\r\n runPm2StartCmd: commands[`pm2:start`],\r\n runPm2StopCmd: commands[`pm2:stop`],\r\n runPm2RestartCmd: commands[`pm2:restart`],\r\n runPm2DeleteCmd: commands[`pm2:delete`],\r\n runPm2LogsCmd: commands[`pm2:logs`],\r\n runPm2MonitCmd: commands[`pm2:monit`]\r\n }\r\n\r\n this.copyDirectorySync(templatesPath, projectPath, variables)\r\n\r\n // Task 3: Create logs directory\r\n log.info(`Creating logs directory..`)\r\n fs.mkdirSync(path.join(projectPath, `logs`), { recursive: true })\r\n fs.writeFileSync(path.join(projectPath, `logs/.gitkeep`), ``)\r\n\r\n // Task 4: Create .env.example\r\n const envPath = path.join(projectPath, `.env`)\r\n const envExamplePath = path.join(projectPath, `.env.example`)\r\n if (fs.existsSync(envExamplePath)) {\r\n log.info(`Creating .env file..`)\r\n fs.renameSync(envExamplePath, envPath)\r\n }\r\n\r\n // Task 5: Remove bunfig.toml if runtime is NOT bun\r\n if (runtime !== `bun`) {\r\n log.info(`Removing bunfig.toml for Node.js runtime..`)\r\n const bunfigPath = path.join(projectPath, `bunfig.toml`)\r\n if (fs.existsSync(bunfigPath)) {\r\n fs.unlinkSync(bunfigPath)\r\n }\r\n }\r\n\r\n // Task 6: tsconfig.json\r\n const tsconfigPath = path.join(projectPath, `tsconfig.json`)\r\n const tsconfigContent = fs.readFileSync(tsconfigPath, { encoding: `utf8` }).replace(`//{{types}}`, runtime == `bun` ? `\"bun-types\"` : ``)\r\n fs.writeFileSync(tsconfigPath, tsconfigContent, { encoding: `utf8` })\r\n\r\n // Task 6: Install dependencies\r\n log.info(`Installing dependencies..`)\r\n if (!(await this.installDependencies(projectPath, packageManager))) {\r\n log.fail(`Project created failed!`)\r\n return process.exit()\r\n }\r\n\r\n // Task 7: Setup ESLint if requested\r\n if (setupEslint) {\r\n log.info(`Setting up ESLint..`)\r\n await this.setupEslintConfig(projectPath, packageManager)\r\n }\r\n\r\n // Final success message\r\n log.info(`Project created successfully!`)\r\n log.info(`Next steps: ${config.projectPath !== process.cwd() ? `cd ${projectName} && ` : ` `}${commands.install} && ${commands.dev}`)\r\n log.info(`For production: ${commands[`pm2:start`]}`)\r\n log.info(`Done..`)\r\n }\r\n\r\n private async setupEslintConfig(projectPath: string, packageManager: PackageManager): Promise<void> {\r\n return new Promise((resolve) => {\r\n const initProcess = spawn(`npm`, [`init`, `@eslint/config@latest`], {\r\n cwd: projectPath,\r\n stdio: `inherit`,\r\n shell: true\r\n })\r\n\r\n initProcess.on(`close`, (code) => {\r\n if (code === 0) {\r\n resolve()\r\n } else {\r\n log.fail(`ESLint setup failed. You can set it up later with: npm init @eslint/config`)\r\n resolve()\r\n }\r\n })\r\n\r\n initProcess.on(`error`, (error) => {\r\n log.fail(`ESLint setup failed: ${error.message}`)\r\n log.info(`You can set it up later with: npm init @eslint/config`)\r\n resolve()\r\n })\r\n })\r\n }\r\n\r\n /**\r\n * Main public method: Prompt first, then execute\r\n */\r\n public async createProject() {\r\n try {\r\n // Step 1: Gather all configuration through prompts\r\n this.config = await this.gatherProjectConfig()\r\n\r\n // Step 2: Execute project generation with the gathered config\r\n await this.executeProjectGeneration(this.config)\r\n } catch (error) {\r\n if (error instanceof Error) {\r\n log.error(`Failed to create project: ${error.message}`)\r\n } else {\r\n log.error(`Failed to create project: ${String(error)}`)\r\n }\r\n process.exit(1)\r\n }\r\n }\r\n}\r\n","#!/usr/bin/env node\r\nimport { log } from \"./utils/logger\"\r\nimport { Create } from \"./create\"\r\nimport { Command } from \"commander\"\r\n\r\n// Read version from package.json\r\nconst version = `0.0.0`\r\nconst program = new Command()\r\n\r\nprogram\r\n .name(`create-gramstax`)\r\n .description(`CLI to create a new Gramstax Telegram bot project`)\r\n .version(version)\r\n .argument(`[project-directory]`, `Directory to create the project in`)\r\n .action(async (projectDirectory?: string) => {\r\n try {\r\n await new Create(projectDirectory).createProject()\r\n } catch (error) {\r\n log.error(`Failed to create project: ${String(error)}`)\r\n process.exit(1)\r\n }\r\n })\r\n\r\nprogram.parse()\r\n"],"mappings":"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","names":["LoggingPretty","log","fs","path","fileURLToPath","spawn","enquirer","__filename","fileURLToPath","__dirname","Create","projectDirectory","__name","packageManager","source","destination","variables","items","item","sourcePath","destPath","content","result","key","value","enquirer","questions","answers","projectPath","resolve","reject","installProcess","spawn","code","log","error","projectName","useCurrentDir","config","runtime","setupEslint","templatesPath","commands","envPath","envExamplePath","bunfigPath","tsconfigPath","tsconfigContent","initProcess","Command","version","program","projectDirectory","Create","error","log"]}
|