create-gramstax 0.8.2 → 0.8.4

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.
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- "use strict";var G=Object.create;var h=Object.defineProperty;var B=Object.getOwnPropertyDescriptor;var O=Object.getOwnPropertyNames;var V=Object.getPrototypeOf,q=Object.prototype.hasOwnProperty;var p=(o,e)=>h(o,"name",{value:e,configurable:!0});var J=(o,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of O(e))!q.call(o,s)&&s!==t&&h(o,s,{get:()=>e[s],enumerable:!(n=B(e,s))||n.enumerable});return o};var v=(o,e,t)=>(t=o!=null?G(V(o)):{},J(e||!o||!o.__esModule?h(t,"default",{value:o,enumerable:!0}):t,o));var Y=p(()=>typeof document>"u"?new URL(`file:${__filename}`).href:document.currentScript&&document.currentScript.tagName.toUpperCase()==="SCRIPT"?document.currentScript.src:new URL("main.js",document.baseURI).href,"getImportMetaUrl"),f=Y();var D=require("logging-pretty"),i=new D.LoggingPretty;var r=v(require("fs"),1),a=v(require("path"),1),x=require("url");var E=require("fs");var g=class o{static{p(this,"FsUt")}static DEFAULT_IGNORED_ENTRIES=new Set([".git",".gitignore",".gitkeep",".DS_Store","Thumbs.db"]);static isDirectoryEffectivelyEmpty(e,t=o.DEFAULT_IGNORED_ENTRIES){return(0,E.readdirSync)(e).filter(c=>!t.has(c)).length===0}static resolvePackageManagerCommand(e,t=process.platform){return t!=="win32"||e==="bun"?e:`${e}.cmd`}static resolveInitialWorkingDirectory(e=process.cwd(),t=process.env.INIT_CWD){return t??e}};var j=require("child_process"),P=v(require("enquirer"),1);var z=(0,x.fileURLToPath)(f),H=a.dirname(z),_=class{constructor(e,t){this.projectDirectory=e;this.version=t?.version}static{p(this,"Create")}config;version;printBanner(){let e=`
2
+ "use strict";var W=Object.create;var h=Object.defineProperty;var A=Object.getOwnPropertyDescriptor;var G=Object.getOwnPropertyNames;var B=Object.getPrototypeOf,O=Object.prototype.hasOwnProperty;var p=(o,e)=>h(o,"name",{value:e,configurable:!0});var V=(o,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let a of G(e))!O.call(o,a)&&a!==t&&h(o,a,{get:()=>e[a],enumerable:!(n=A(e,a))||n.enumerable});return o};var v=(o,e,t)=>(t=o!=null?W(B(o)):{},V(e||!o||!o.__esModule?h(t,"default",{value:o,enumerable:!0}):t,o));var q=p(()=>typeof document>"u"?new URL(`file:${__filename}`).href:document.currentScript&&document.currentScript.tagName.toUpperCase()==="SCRIPT"?document.currentScript.src:new URL("main.js",document.baseURI).href,"getImportMetaUrl"),f=q();var C=require("logging-pretty"),r=new C.LoggingPretty;var i=v(require("fs"),1),s=v(require("path"),1),E=require("url");var D=require("fs");var g=class o{static{p(this,"FsUt")}static DEFAULT_IGNORED_ENTRIES=new Set([".git",".gitignore",".gitkeep",".DS_Store","Thumbs.db"]);static isDirectoryEffectivelyEmpty(e,t=o.DEFAULT_IGNORED_ENTRIES){return(0,D.readdirSync)(e).filter(c=>!t.has(c)).length===0}static resolvePackageManagerCommand(e,t=process.platform){return t!=="win32"||e==="bun"?e:`${e}.cmd`}static resolveInitialWorkingDirectory(e=process.cwd(),t=process.env.INIT_CWD){return t??e}};var j=require("child_process"),P=v(require("enquirer"),1);var J=(0,E.fileURLToPath)(f),Y=s.dirname(J),_=class{constructor(e,t){this.projectDirectory=e;this.version=t?.version}static{p(this,"Create")}config;version;printBanner(){let e=`
3
3
  $$$$$$\\ $$\\
4
4
  $$ __$$\\ $$ |
5
5
  $$ / \\__| $$$$$$\\ $$$$$$\\ $$$$$$\\$$$$\\ $$$$$$$\\ $$$$$$\\ $$$$$$\\ $$\\ $$\\
@@ -10,4 +10,4 @@ $$ | $$ |$$ | $$ __$$ |$$ | $$ | $$ | \\____$$\\ $$ |$$\\ $$ __$$ | $$
10
10
  \\______/ \\__| \\_______|\\__| \\__| \\__|\\_______/ \\____/ \\_______|\\__/ \\__|
11
11
 
12
12
  `,t=this.version?`v${this.version}`:"v0.0.0";console.log(`${e}${t}
13
- `)}getPackageManagerCommands(e){return{bun:{install:"bun install",dev:"bun dev",start:"bun start"},npm:{install:"npm install",dev:"npm run dev",start:"npm start"},pnpm:{install:"pnpm install",dev:"pnpm dev",start:"pnpm start"},yarn:{install:"yarn install",dev:"yarn dev",start:"yarn start"}}[e]}copyDirectorySync(e,t,n={}){r.existsSync(t)||r.mkdirSync(t,{recursive:!0});let s=r.readdirSync(e,{withFileTypes:!0});for(let c of s){let m=a.join(e,c.name),l=a.join(t,c.name);if(c.isDirectory())this.copyDirectorySync(m,l,n);else if(c.isFile()){let $=r.readFileSync(m,"utf-8");$=this.replaceTemplateVariables($,n),r.writeFileSync(l,$)}}}replaceTemplateVariables(e,t){let n=e;for(let[s,c]of Object.entries(t))n=n.replace(new RegExp(`{{${s}}}`,"g"),c);return n}async promptForProjectName(){return(await P.default.prompt({type:"input",name:"projectName",message:"What is your project named?",initial:"",validate:p(t=>t===""||/^[a-z0-9-_]+$/i.test(t)?!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 t=await P.default.prompt(e);return{packageManager:t.packageManager,runtime:t.runtime,eslint:t.eslint}}async installDependencies(e,t){return await new Promise(n=>{let s=g.resolvePackageManagerCommand(t),m=(0,j.spawn)(s,["install"],{cwd:e,stdio:"inherit",shell:!1});m.on("close",l=>{l===0?n(!0):(i.fail("Dependencies installation failed"),n(!1))}),m.on("error",l=>{i.fail(`Dependencies installation failed: ${l.message}`),n(!1)})})}async gatherProjectConfig(){this.printBanner();let e=this.projectDirectory,t,n=!1,s=g.resolveInitialWorkingDirectory();e?(t=a.resolve(s,e),n=!1):(e=await this.promptForProjectName(),e===""?(e=a.basename(s),t=s,n=!0):(t=a.resolve(s,e),n=!1));let c=await this.promptForConfiguration(),m=c.packageManager,l=c.runtime,$=c.eslint;return i.info(`Project: ${e}`),i.info(`Location: ${t}`),i.info(`Package Manager: ${m}`),i.info(`Runtime: ${l}`),i.info(`ESLint: ${$?"Yes":"No"}`),n?g.isDirectoryEffectivelyEmpty(t)||(i.error("Current directory is not empty!"),process.exit(1)):r.existsSync(t)&&(i.error(`Directory "${e}" already exists!`),process.exit(1)),{projectName:e,projectPath:t,packageManager:m,runtime:l,setupEslint:$}}async executeProjectGeneration(e){let{projectName:t,projectPath:n,packageManager:s,runtime:c,setupEslint:m}=e;i.info("Creating project directory.."),r.existsSync(n)||r.mkdirSync(n,{recursive:!0}),i.info("Copying template files..");let l=a.join(H,"templates"),$=this.getPackageManagerCommands(s),L={projectName:t,installCmd:$.install,runDevCmd:$.dev,runStartCmd:$.start};this.copyDirectorySync(l,n,L),i.info("Creating logs directory.."),r.mkdirSync(a.join(n,"logs"),{recursive:!0}),r.writeFileSync(a.join(n,"logs/.gitkeep"),"");let T=a.join(n,".env"),S=a.join(n,".env.example");if(r.existsSync(S)&&(i.info("Creating .env file.."),r.renameSync(S,T)),c!=="bun"){i.info("Removing bunfig.toml for Node.js runtime..");let d=a.join(n,"bunfig.toml");r.existsSync(d)&&r.unlinkSync(d)}let b=a.join(n,"tsconfig.json"),U=r.readFileSync(b,{encoding:"utf8"}).replace("//{{types}}",c=="bun"?'"bun-types"':"");if(r.writeFileSync(b,U,{encoding:"utf8"}),i.info("Installing dependencies.."),!await this.installDependencies(n,s))return i.fail("Project created failed!"),process.exit();let u=a.join(n,"eslint.config.ts.template"),W=a.join(n,"eslint.config.ts");if(m){i.info("Installing ESLint dependencies..");let d=g.resolvePackageManagerCommand(s),k=s==="yarn"?["add","-D"]:["install","-D"];k.push("eslint","@eslint/js","globals","typescript-eslint"),await new Promise(w=>{let C=(0,j.spawn)(d,k,{cwd:n,stdio:"inherit",shell:!1});C.on("close",()=>w()),C.on("error",A=>{i.fail(`Failed to install ESLint dependencies: ${A.message}`),w()})}),r.existsSync(u)&&r.renameSync(u,W)}else r.existsSync(u)&&r.unlinkSync(u);i.info("Project created successfully!"),i.info(`Next steps: ${e.projectPath!==process.cwd()?`cd ${t} && `:" "}${$.install} && ${$.dev}`),i.info("Done..")}async createProject(){try{this.config=await this.gatherProjectConfig(),await this.executeProjectGeneration(this.config)}catch(e){e instanceof Error?i.error(`Failed to create project: ${e.message}`):i.error(`Failed to create project: ${String(e)}`),process.exit(1)}}};var R=require("commander"),F=require("fs"),y=require("path"),M=require("url"),K=(0,M.fileURLToPath)(f),Q=(0,y.dirname)(K),X=(0,y.join)(Q,"../../package.json"),N=JSON.parse((0,F.readFileSync)(X,"utf-8")).version,I=new R.Command;I.name("create-gramstax").description("CLI to create a new Gramstax Telegram bot project").version(N).argument("[project-directory]","Directory to create the project in").action(async o=>{try{await new _(o,{version:N}).createProject()}catch(e){i.error(`Failed to create project: ${String(e)}`),process.exit(1)}});I.parse();
13
+ `)}getPackageManagerCommands(e){return{bun:{install:"bun install",dev:"bun dev",start:"bun start"},npm:{install:"npm install",dev:"npm run dev",start:"npm start"},pnpm:{install:"pnpm install",dev:"pnpm dev",start:"pnpm start"},yarn:{install:"yarn install",dev:"yarn dev",start:"yarn start"}}[e]}copyDirectorySync(e,t,n={}){i.existsSync(t)||i.mkdirSync(t,{recursive:!0});let a=i.readdirSync(e,{withFileTypes:!0});for(let c of a){let m=s.join(e,c.name),l=s.join(t,c.name);if(c.isDirectory())this.copyDirectorySync(m,l,n);else if(c.isFile()){let $=i.readFileSync(m,"utf-8");$=this.replaceTemplateVariables($,n),i.writeFileSync(l,$)}}}replaceTemplateVariables(e,t){let n=e;for(let[a,c]of Object.entries(t))n=n.replace(new RegExp(`{{${a}}}`,"g"),c);return n}async promptForProjectName(){return(await P.default.prompt({type:"input",name:"projectName",message:"What is your project named?",initial:"",validate:p(t=>t===""||/^[a-z0-9-_]+$/i.test(t)?!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 t=await P.default.prompt(e);return{packageManager:t.packageManager,runtime:t.runtime,eslint:t.eslint}}async installDependencies(e,t){return await new Promise(n=>{let a=g.resolvePackageManagerCommand(t),m=(0,j.spawn)(a,["install"],{cwd:e,stdio:"inherit",shell:!1});m.on("close",l=>{l===0?n(!0):(r.fail("Dependencies installation failed"),n(!1))}),m.on("error",l=>{r.fail(`Dependencies installation failed: ${l.message}`),n(!1)})})}async gatherProjectConfig(){this.printBanner();let e=this.projectDirectory,t,n=!1,a=g.resolveInitialWorkingDirectory();e?(t=s.resolve(a,e),n=!1):(e=await this.promptForProjectName(),e===""?(e=s.basename(a),t=a,n=!0):(t=s.resolve(a,e),n=!1));let c=await this.promptForConfiguration(),m=c.packageManager,l=c.runtime,$=c.eslint;return r.info(`Project: ${e}`),r.info(`Location: ${t}`),r.info(`Package Manager: ${m}`),r.info(`Runtime: ${l}`),r.info(`ESLint: ${$?"Yes":"No"}`),n?g.isDirectoryEffectivelyEmpty(t)||(r.error("Current directory is not empty!"),process.exit(1)):i.existsSync(t)&&(r.error(`Directory "${e}" already exists!`),process.exit(1)),{projectName:e,projectPath:t,packageManager:m,runtime:l,setupEslint:$}}async executeProjectGeneration(e){let{projectName:t,projectPath:n,packageManager:a,runtime:c,setupEslint:m}=e;r.info("Creating project directory.."),i.existsSync(n)||i.mkdirSync(n,{recursive:!0}),r.info("Copying template files..");let l=s.join(Y,"templates"),$=this.getPackageManagerCommands(a),I={projectName:t,installCmd:$.install,runDevCmd:$.dev,runStartCmd:$.start};this.copyDirectorySync(l,n,I),r.info("Creating logs directory.."),i.mkdirSync(s.join(n,"logs"),{recursive:!0}),i.writeFileSync(s.join(n,"logs/.gitkeep"),"");let L=s.join(n,".env"),S=s.join(n,".env.example");if(i.existsSync(S)&&(r.info("Creating .env file.."),i.renameSync(S,L)),c!=="bun"){r.info("Removing bunfig.toml for Node.js runtime..");let d=s.join(n,"bunfig.toml");i.existsSync(d)&&i.unlinkSync(d)}if(r.info("Installing dependencies.."),!await this.installDependencies(n,a))return r.fail("Project created failed!"),process.exit();let u=s.join(n,"eslint.config.ts.template"),T=s.join(n,"eslint.config.ts");if(m){r.info("Installing ESLint dependencies..");let d=g.resolvePackageManagerCommand(a),b=a==="yarn"?["add","-D"]:["install","-D"];b.push("eslint","@eslint/js","globals","typescript-eslint"),await new Promise(k=>{let w=(0,j.spawn)(d,b,{cwd:n,stdio:"inherit",shell:!1});w.on("close",()=>k()),w.on("error",U=>{r.fail(`Failed to install ESLint dependencies: ${U.message}`),k()})}),i.existsSync(u)&&i.renameSync(u,T)}else i.existsSync(u)&&i.unlinkSync(u);r.info("Project created successfully!"),r.info(`Next steps: ${e.projectPath!==process.cwd()?`cd ${t} && `:" "}${$.install} && ${$.dev}`),r.info("Done..")}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 N=require("commander"),R=require("fs"),y=require("path"),M=require("url"),z=(0,M.fileURLToPath)(f),H=(0,y.dirname)(z),K=(0,y.join)(H,"../../package.json"),x=JSON.parse((0,R.readFileSync)(K,"utf-8")).version,F=new N.Command;F.name("create-gramstax").description("CLI to create a new Gramstax Telegram bot project").version(x).argument("[project-directory]","Directory to create the project in").action(async o=>{try{await new _(o,{version:x}).createProject()}catch(e){r.error(`Failed to create project: ${String(e)}`),process.exit(1)}});F.parse();
package/dist/src/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- var F=Object.defineProperty;var g=(p,e)=>F(p,"name",{value:e,configurable:!0});import{LoggingPretty as R}from"logging-pretty";var i=new R;import*as r from"fs";import*as s from"path";import{fileURLToPath as T}from"url";import{readdirSync as L}from"fs";var m=class p{static{g(this,"FsUt")}static DEFAULT_IGNORED_ENTRIES=new Set([".git",".gitignore",".gitkeep",".DS_Store","Thumbs.db"]);static isDirectoryEffectivelyEmpty(e,t=p.DEFAULT_IGNORED_ENTRIES){return L(e).filter(o=>!t.has(o)).length===0}static resolvePackageManagerCommand(e,t=process.platform){return t!=="win32"||e==="bun"?e:`${e}.cmd`}static resolveInitialWorkingDirectory(e=process.cwd(),t=process.env.INIT_CWD){return t??e}};import{spawn as P}from"child_process";import S from"enquirer";var I=T(import.meta.url),W=s.dirname(I),d=class{constructor(e,t){this.projectDirectory=e;this.version=t?.version}static{g(this,"Create")}config;version;printBanner(){let e=`
2
+ var E=Object.defineProperty;var g=(p,e)=>E(p,"name",{value:e,configurable:!0});import{LoggingPretty as N}from"logging-pretty";var r=new N;import*as i from"fs";import*as a from"path";import{fileURLToPath as R}from"url";import{readdirSync as F}from"fs";var m=class p{static{g(this,"FsUt")}static DEFAULT_IGNORED_ENTRIES=new Set([".git",".gitignore",".gitkeep",".DS_Store","Thumbs.db"]);static isDirectoryEffectivelyEmpty(e,t=p.DEFAULT_IGNORED_ENTRIES){return F(e).filter(o=>!t.has(o)).length===0}static resolvePackageManagerCommand(e,t=process.platform){return t!=="win32"||e==="bun"?e:`${e}.cmd`}static resolveInitialWorkingDirectory(e=process.cwd(),t=process.env.INIT_CWD){return t??e}};import{spawn as j}from"child_process";import P from"enquirer";var L=R(import.meta.url),T=a.dirname(L),d=class{constructor(e,t){this.projectDirectory=e;this.version=t?.version}static{g(this,"Create")}config;version;printBanner(){let e=`
3
3
  $$$$$$\\ $$\\
4
4
  $$ __$$\\ $$ |
5
5
  $$ / \\__| $$$$$$\\ $$$$$$\\ $$$$$$\\$$$$\\ $$$$$$$\\ $$$$$$\\ $$$$$$\\ $$\\ $$\\
@@ -10,4 +10,4 @@ $$ | $$ |$$ | $$ __$$ |$$ | $$ | $$ | \\____$$\\ $$ |$$\\ $$ __$$ | $$
10
10
  \\______/ \\__| \\_______|\\__| \\__| \\__|\\_______/ \\____/ \\_______|\\__/ \\__|
11
11
 
12
12
  `,t=this.version?`v${this.version}`:"v0.0.0";console.log(`${e}${t}
13
- `)}getPackageManagerCommands(e){return{bun:{install:"bun install",dev:"bun dev",start:"bun start"},npm:{install:"npm install",dev:"npm run dev",start:"npm start"},pnpm:{install:"pnpm install",dev:"pnpm dev",start:"pnpm start"},yarn:{install:"yarn install",dev:"yarn dev",start:"yarn start"}}[e]}copyDirectorySync(e,t,n={}){r.existsSync(t)||r.mkdirSync(t,{recursive:!0});let a=r.readdirSync(e,{withFileTypes:!0});for(let o of a){let l=s.join(e,o.name),$=s.join(t,o.name);if(o.isDirectory())this.copyDirectorySync(l,$,n);else if(o.isFile()){let c=r.readFileSync(l,"utf-8");c=this.replaceTemplateVariables(c,n),r.writeFileSync($,c)}}}replaceTemplateVariables(e,t){let n=e;for(let[a,o]of Object.entries(t))n=n.replace(new RegExp(`{{${a}}}`,"g"),o);return n}async promptForProjectName(){return(await S.prompt({type:"input",name:"projectName",message:"What is your project named?",initial:"",validate:g(t=>t===""||/^[a-z0-9-_]+$/i.test(t)?!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 t=await S.prompt(e);return{packageManager:t.packageManager,runtime:t.runtime,eslint:t.eslint}}async installDependencies(e,t){return await new Promise(n=>{let a=m.resolvePackageManagerCommand(t),l=P(a,["install"],{cwd:e,stdio:"inherit",shell:!1});l.on("close",$=>{$===0?n(!0):(i.fail("Dependencies installation failed"),n(!1))}),l.on("error",$=>{i.fail(`Dependencies installation failed: ${$.message}`),n(!1)})})}async gatherProjectConfig(){this.printBanner();let e=this.projectDirectory,t,n=!1,a=m.resolveInitialWorkingDirectory();e?(t=s.resolve(a,e),n=!1):(e=await this.promptForProjectName(),e===""?(e=s.basename(a),t=a,n=!0):(t=s.resolve(a,e),n=!1));let o=await this.promptForConfiguration(),l=o.packageManager,$=o.runtime,c=o.eslint;return i.info(`Project: ${e}`),i.info(`Location: ${t}`),i.info(`Package Manager: ${l}`),i.info(`Runtime: ${$}`),i.info(`ESLint: ${c?"Yes":"No"}`),n?m.isDirectoryEffectivelyEmpty(t)||(i.error("Current directory is not empty!"),process.exit(1)):r.existsSync(t)&&(i.error(`Directory "${e}" already exists!`),process.exit(1)),{projectName:e,projectPath:t,packageManager:l,runtime:$,setupEslint:c}}async executeProjectGeneration(e){let{projectName:t,projectPath:n,packageManager:a,runtime:o,setupEslint:l}=e;i.info("Creating project directory.."),r.existsSync(n)||r.mkdirSync(n,{recursive:!0}),i.info("Copying template files..");let $=s.join(W,"templates"),c=this.getPackageManagerCommands(a),w={projectName:t,installCmd:c.install,runDevCmd:c.dev,runStartCmd:c.start};this.copyDirectorySync($,n,w),i.info("Creating logs directory.."),r.mkdirSync(s.join(n,"logs"),{recursive:!0}),r.writeFileSync(s.join(n,"logs/.gitkeep"),"");let C=s.join(n,".env"),y=s.join(n,".env.example");if(r.existsSync(y)&&(i.info("Creating .env file.."),r.renameSync(y,C)),o!=="bun"){i.info("Removing bunfig.toml for Node.js runtime..");let u=s.join(n,"bunfig.toml");r.existsSync(u)&&r.unlinkSync(u)}let _=s.join(n,"tsconfig.json"),D=r.readFileSync(_,{encoding:"utf8"}).replace("//{{types}}",o=="bun"?'"bun-types"':"");if(r.writeFileSync(_,D,{encoding:"utf8"}),i.info("Installing dependencies.."),!await this.installDependencies(n,a))return i.fail("Project created failed!"),process.exit();let f=s.join(n,"eslint.config.ts.template"),E=s.join(n,"eslint.config.ts");if(l){i.info("Installing ESLint dependencies..");let u=m.resolvePackageManagerCommand(a),h=a==="yarn"?["add","-D"]:["install","-D"];h.push("eslint","@eslint/js","globals","typescript-eslint"),await new Promise(v=>{let j=P(u,h,{cwd:n,stdio:"inherit",shell:!1});j.on("close",()=>v()),j.on("error",x=>{i.fail(`Failed to install ESLint dependencies: ${x.message}`),v()})}),r.existsSync(f)&&r.renameSync(f,E)}else r.existsSync(f)&&r.unlinkSync(f);i.info("Project created successfully!"),i.info(`Next steps: ${e.projectPath!==process.cwd()?`cd ${t} && `:" "}${c.install} && ${c.dev}`),i.info("Done..")}async createProject(){try{this.config=await this.gatherProjectConfig(),await this.executeProjectGeneration(this.config)}catch(e){e instanceof Error?i.error(`Failed to create project: ${e.message}`):i.error(`Failed to create project: ${String(e)}`),process.exit(1)}}};import{Command as A}from"commander";import{readFileSync as G}from"fs";import{dirname as B,join as O}from"path";import{fileURLToPath as U}from"url";var V=U(import.meta.url),q=B(V),J=O(q,"../../package.json"),b=JSON.parse(G(J,"utf-8")).version,k=new A;k.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 p=>{try{await new d(p,{version:b}).createProject()}catch(e){i.error(`Failed to create project: ${String(e)}`),process.exit(1)}});k.parse();
13
+ `)}getPackageManagerCommands(e){return{bun:{install:"bun install",dev:"bun dev",start:"bun start"},npm:{install:"npm install",dev:"npm run dev",start:"npm start"},pnpm:{install:"pnpm install",dev:"pnpm dev",start:"pnpm start"},yarn:{install:"yarn install",dev:"yarn dev",start:"yarn start"}}[e]}copyDirectorySync(e,t,n={}){i.existsSync(t)||i.mkdirSync(t,{recursive:!0});let s=i.readdirSync(e,{withFileTypes:!0});for(let o of s){let l=a.join(e,o.name),$=a.join(t,o.name);if(o.isDirectory())this.copyDirectorySync(l,$,n);else if(o.isFile()){let c=i.readFileSync(l,"utf-8");c=this.replaceTemplateVariables(c,n),i.writeFileSync($,c)}}}replaceTemplateVariables(e,t){let n=e;for(let[s,o]of Object.entries(t))n=n.replace(new RegExp(`{{${s}}}`,"g"),o);return n}async promptForProjectName(){return(await P.prompt({type:"input",name:"projectName",message:"What is your project named?",initial:"",validate:g(t=>t===""||/^[a-z0-9-_]+$/i.test(t)?!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 t=await P.prompt(e);return{packageManager:t.packageManager,runtime:t.runtime,eslint:t.eslint}}async installDependencies(e,t){return await new Promise(n=>{let s=m.resolvePackageManagerCommand(t),l=j(s,["install"],{cwd:e,stdio:"inherit",shell:!1});l.on("close",$=>{$===0?n(!0):(r.fail("Dependencies installation failed"),n(!1))}),l.on("error",$=>{r.fail(`Dependencies installation failed: ${$.message}`),n(!1)})})}async gatherProjectConfig(){this.printBanner();let e=this.projectDirectory,t,n=!1,s=m.resolveInitialWorkingDirectory();e?(t=a.resolve(s,e),n=!1):(e=await this.promptForProjectName(),e===""?(e=a.basename(s),t=s,n=!0):(t=a.resolve(s,e),n=!1));let o=await this.promptForConfiguration(),l=o.packageManager,$=o.runtime,c=o.eslint;return r.info(`Project: ${e}`),r.info(`Location: ${t}`),r.info(`Package Manager: ${l}`),r.info(`Runtime: ${$}`),r.info(`ESLint: ${c?"Yes":"No"}`),n?m.isDirectoryEffectivelyEmpty(t)||(r.error("Current directory is not empty!"),process.exit(1)):i.existsSync(t)&&(r.error(`Directory "${e}" already exists!`),process.exit(1)),{projectName:e,projectPath:t,packageManager:l,runtime:$,setupEslint:c}}async executeProjectGeneration(e){let{projectName:t,projectPath:n,packageManager:s,runtime:o,setupEslint:l}=e;r.info("Creating project directory.."),i.existsSync(n)||i.mkdirSync(n,{recursive:!0}),r.info("Copying template files..");let $=a.join(T,"templates"),c=this.getPackageManagerCommands(s),b={projectName:t,installCmd:c.install,runDevCmd:c.dev,runStartCmd:c.start};this.copyDirectorySync($,n,b),r.info("Creating logs directory.."),i.mkdirSync(a.join(n,"logs"),{recursive:!0}),i.writeFileSync(a.join(n,"logs/.gitkeep"),"");let w=a.join(n,".env"),_=a.join(n,".env.example");if(i.existsSync(_)&&(r.info("Creating .env file.."),i.renameSync(_,w)),o!=="bun"){r.info("Removing bunfig.toml for Node.js runtime..");let u=a.join(n,"bunfig.toml");i.existsSync(u)&&i.unlinkSync(u)}if(r.info("Installing dependencies.."),!await this.installDependencies(n,s))return r.fail("Project created failed!"),process.exit();let f=a.join(n,"eslint.config.ts.template"),D=a.join(n,"eslint.config.ts");if(l){r.info("Installing ESLint dependencies..");let u=m.resolvePackageManagerCommand(s),y=s==="yarn"?["add","-D"]:["install","-D"];y.push("eslint","@eslint/js","globals","typescript-eslint"),await new Promise(h=>{let v=j(u,y,{cwd:n,stdio:"inherit",shell:!1});v.on("close",()=>h()),v.on("error",C=>{r.fail(`Failed to install ESLint dependencies: ${C.message}`),h()})}),i.existsSync(f)&&i.renameSync(f,D)}else i.existsSync(f)&&i.unlinkSync(f);r.info("Project created successfully!"),r.info(`Next steps: ${e.projectPath!==process.cwd()?`cd ${t} && `:" "}${c.install} && ${c.dev}`),r.info("Done..")}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)}}};import{Command as I}from"commander";import{readFileSync as W}from"fs";import{dirname as A,join as G}from"path";import{fileURLToPath as B}from"url";var O=B(import.meta.url),U=A(O),V=G(U,"../../package.json"),k=JSON.parse(W(V,"utf-8")).version,S=new I;S.name("create-gramstax").description("CLI to create a new Gramstax Telegram bot project").version(k).argument("[project-directory]","Directory to create the project in").action(async p=>{try{await new d(p,{version:k}).createProject()}catch(e){r.error(`Failed to create project: ${String(e)}`),process.exit(1)}});S.parse();
@@ -35,11 +35,11 @@
35
35
  "lint:fix": "eslint . --fix"
36
36
  },
37
37
  "dependencies": {
38
- "gramstax": "^0.8.1",
38
+ "gramstax": "^0.8.3",
39
39
  "dayjs": "^1.11.13"
40
40
  },
41
41
  "peerDependencies": {
42
- "typescript": "5.9.3"
42
+ "typescript": "6.0.3"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@types/bun": "latest"
@@ -11,7 +11,7 @@ export class UserGuard extends GuardBase {
11
11
  async ensureUsername(edit: boolean) {
12
12
  try {
13
13
  if (!this.userName || this.userName.length == 0) {
14
- await new UserNameNotFoundPage(this).entryPoint(edit)
14
+ await new UserNameNotFoundPage(this).showEntryPoint(edit)
15
15
  return null
16
16
  }
17
17
  return {status: true}
@@ -37,8 +37,8 @@ export class GeneralStatusPage extends PageBase {
37
37
  this.constructorName = p?.constructor?.name
38
38
  }
39
39
 
40
- async error(funcName: string, error: any, edit = true) {
41
- await Alert.error(this, funcName, error, edit)
40
+ async error(...args: Parameters<typeof Alert.error> extends [any, ...infer R] ? R : []) {
41
+ await Alert.error(this, ...args)
42
42
  }
43
43
 
44
44
  async errorInputNotFound() {
@@ -1,8 +1,8 @@
1
1
  import {PageBase} from "~/base/page"
2
2
  import {StartPage} from "./start"
3
3
 
4
- class Perform {
5
- static async entryPoint(ctx: HelpPage, edit = true) {
4
+ class Main {
5
+ static async showEntryPoint(ctx: HelpPage, edit = true) {
6
6
  const kb = ctx.inlineKeyboardT([StartPage])
7
7
  if (edit) {
8
8
  await ctx.edit(kb)
@@ -14,11 +14,11 @@ class Perform {
14
14
 
15
15
  export class HelpPage extends PageBase {
16
16
  async handleCallbackData() {
17
- await Perform.entryPoint(this, true)
17
+ await Main.showEntryPoint(this, true)
18
18
  }
19
19
 
20
20
  async handleCommandText() {
21
- await Perform.entryPoint(this, false)
21
+ await Main.showEntryPoint(this, false)
22
22
  }
23
23
 
24
24
  static template = `
@@ -1,8 +1,8 @@
1
1
  import {PageBase} from "~/base/page"
2
2
  import {StartPage} from "./start"
3
3
 
4
- class Perform {
5
- static async entryPoint(ctx: RandomNumberPage, edit = true) {
4
+ class Main {
5
+ static async showEntryPoint(ctx: RandomNumberPage, edit = true) {
6
6
  const kb = ctx.inlineKeyboardT([this, StartPage])
7
7
  const da = {result: Math.random() * 10 ** 18}
8
8
  if (edit) {
@@ -15,15 +15,15 @@ class Perform {
15
15
 
16
16
  export class RandomNumberPage extends PageBase {
17
17
  async handleCallbackData() {
18
- await Perform.entryPoint(this, true)
18
+ await Main.showEntryPoint(this, true)
19
19
  }
20
20
 
21
21
  async handleCommandText() {
22
- await Perform.entryPoint(this, false)
22
+ await Main.showEntryPoint(this, false)
23
23
  }
24
24
 
25
25
  async entryPoint(edit = true) {
26
- await Perform.entryPoint(this, edit)
26
+ await Main.showEntryPoint(this, edit)
27
27
  }
28
28
 
29
29
  static template = `
@@ -3,8 +3,8 @@ import {PageBase} from "~/base/page"
3
3
  import {RandomNumberPage} from "./random-number"
4
4
  import {SumNumberPage} from "./sum-number"
5
5
 
6
- class Perform {
7
- static async entryPoint(ctx: StartPage, edit = true) {
6
+ class Main {
7
+ static async showEntryPoint(ctx: StartPage, edit = true) {
8
8
  await ctx.clearSession()
9
9
  const kb = ctx.inlineKeyboardT([RandomNumberPage, SumNumberPage, HelpPage], `2`)
10
10
  const da = {userName: ctx.userName}
@@ -18,15 +18,15 @@ class Perform {
18
18
 
19
19
  export class StartPage extends PageBase {
20
20
  async handleCallbackData() {
21
- await Perform.entryPoint(this, true)
21
+ await Main.showEntryPoint(this, true)
22
22
  }
23
23
 
24
24
  async handleCommandText() {
25
- await Perform.entryPoint(this, false)
25
+ await Main.showEntryPoint(this, false)
26
26
  }
27
27
 
28
28
  async entryPoint(edit = true) {
29
- await Perform.entryPoint(this, edit)
29
+ await Main.showEntryPoint(this, edit)
30
30
  }
31
31
 
32
32
  static template = `
@@ -4,7 +4,7 @@ import {StartPage} from "./start"
4
4
  class Base {
5
5
  static pleft: `pleft`
6
6
  static pright: `pright`
7
- static result: `result`
7
+ static success: `success`
8
8
  }
9
9
 
10
10
  class Helper {
@@ -17,8 +17,8 @@ class Helper {
17
17
  }
18
18
  }
19
19
 
20
- class Flow {
21
- static async step1Form(ctx: SumNumberPage, edit: boolean) {
20
+ class Main {
21
+ static async showStep1Form(ctx: SumNumberPage, edit: boolean) {
22
22
  await ctx.sessionFreeText({step: `left`})
23
23
  const bi = Base.pleft
24
24
  const kb = Helper.kb(ctx, bi)
@@ -30,15 +30,15 @@ class Flow {
30
30
  }
31
31
  }
32
32
 
33
- static async step1Answer(ctx: SumNumberPage, left: number) {
33
+ static async processStep1Answer(ctx: SumNumberPage, left: number) {
34
34
  if (!Number.isFinite(left)) {
35
- await Flow.step1Form(ctx, false)
35
+ await Main.showStep1Form(ctx, false)
36
36
  } else {
37
- await this.step2Form(ctx, left)
37
+ await this.showStep2Form(ctx, left)
38
38
  }
39
39
  }
40
40
 
41
- static async step2Form(ctx: SumNumberPage, left: number) {
41
+ static async showStep2Form(ctx: SumNumberPage, left: number) {
42
42
  await ctx.sessionFreeText({step: `right`, left})
43
43
  const bi = Base.pright
44
44
  const kb = Helper.kb(ctx, bi)
@@ -46,12 +46,12 @@ class Flow {
46
46
  await ctx.reply(kb, da, bi)
47
47
  }
48
48
 
49
- static async step2Answer(ctx: SumNumberPage, left: number, right: number) {
49
+ static async processStep2Answer(ctx: SumNumberPage, left: number, right: number) {
50
50
  if (!Number.isFinite(right)) {
51
- await Flow.step2Form(ctx, right)
51
+ await Main.showStep2Form(ctx, right)
52
52
  } else if (!Number.isFinite(right ?? NaN)) {
53
53
  await ctx.clearSession()
54
- await Flow.step1Form(ctx, false)
54
+ await Main.showStep1Form(ctx, false)
55
55
  } else {
56
56
  await Alert.success(ctx, left, right)
57
57
  }
@@ -61,7 +61,7 @@ class Flow {
61
61
  class Alert {
62
62
  static async success(ctx: SumNumberPage, left: number, right: number) {
63
63
  await ctx.clearSession()
64
- const bi = Base.result
64
+ const bi = Base.success
65
65
  const kb = Helper.kb(ctx, bi)
66
66
  const da = {result: left! + right}
67
67
  await ctx.reply(kb, da, bi)
@@ -70,11 +70,11 @@ class Alert {
70
70
 
71
71
  export class SumNumberPage extends PageBase {
72
72
  async handleCallbackData() {
73
- await Flow.step1Form(this, true)
73
+ await Main.showStep1Form(this, true)
74
74
  }
75
75
 
76
76
  async handleCommandText() {
77
- await Flow.step1Form(this, false)
77
+ await Main.showStep1Form(this, false)
78
78
  }
79
79
 
80
80
  async handleFreeText() {
@@ -85,9 +85,9 @@ export class SumNumberPage extends PageBase {
85
85
  const input = this.msgText?.trim()
86
86
  const value = input ? Number(input) : NaN
87
87
  if (step === `left`) {
88
- await Flow.step1Answer(this, value)
88
+ await Main.processStep1Answer(this, value)
89
89
  } else if (step === `right`) {
90
- await Flow.step2Answer(this, left!, value)
90
+ await Main.processStep2Answer(this, left!, value)
91
91
  }
92
92
  }
93
93
 
@@ -120,7 +120,7 @@ export class SumNumberPage extends PageBase {
120
120
  </message>
121
121
  </base>
122
122
 
123
- <base id="${Base.result}">
123
+ <base id="${Base.success}">
124
124
  ${this.kbk.home()}
125
125
  <message>
126
126
  <b>📚 Result Sum</b>
@@ -1,8 +1,8 @@
1
1
  import {HelpPage} from "./help"
2
2
  import {PageBase} from "~/base/page"
3
3
 
4
- class Perform {
5
- static async entryPoint(ctx: UserNameNotFoundPage, edit = true) {
4
+ class Main {
5
+ static async showEntryPoint(ctx: UserNameNotFoundPage, edit = true) {
6
6
  const kb = ctx.inlineKeyboardT([HelpPage])
7
7
  if (edit) {
8
8
  await ctx.edit(kb)
@@ -13,8 +13,8 @@ class Perform {
13
13
  }
14
14
 
15
15
  export class UserNameNotFoundPage extends PageBase {
16
- async entryPoint(edit = true) {
17
- await Perform.entryPoint(this, edit)
16
+ async showEntryPoint(edit = true) {
17
+ await Main.showEntryPoint(this, edit)
18
18
  }
19
19
 
20
20
  static template = `
@@ -13,7 +13,8 @@
13
13
  "module": "Preserve",
14
14
  "moduleDetection": "force",
15
15
  "types": [
16
- //{{types}}
16
+ "node",
17
+ "bun"
17
18
  ],
18
19
  "jsx": "react-jsx",
19
20
  "allowJs": true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-gramstax",
3
- "version": "0.8.2",
3
+ "version": "0.8.4",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -45,7 +45,7 @@
45
45
  "tsup": "^8.5.1"
46
46
  },
47
47
  "peerDependencies": {
48
- "typescript": "^5.9.3"
48
+ "typescript": "^6.0.3"
49
49
  },
50
50
  "dependencies": {
51
51
  "commander": "^14.0.2",