@leo-h/create-nodejs-app 1.0.0 → 1.0.2

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/README.md CHANGED
@@ -1,6 +1,9 @@
1
1
  # @leo-h/create-nodejs-app
2
2
 
3
- ![example](https://github.com/Leo-Henrique/create-nodejs-app/assets/72027449/c1d21542-293b-483d-a94b-3fb885a9e43e)
3
+ <div align="center">
4
+ <img src="https://github.com/Leo-Henrique/create-nodejs-app/assets/72027449/f62187c5-8667-4cf4-b121-0043aceb164e"
5
+ alt="Script usage example" />
6
+ </div>
4
7
 
5
8
  Create a Node.js application with TypeScript with just one command and without worrying about environment or framework configurations. Dedicate your energy only to the business rules of your application.
6
9
 
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- const index=require("./config/index.js"),logs=require("./utils/logs.js"),onCancel=require("./utils/on-cancel.js"),fs=require("fs"),promises=require("fs/promises"),path=require("path"),picocolors=require("picocolors"),y=require("prompts"),copyTemplate_compose=require("./compose-app/copy-template.compose.js"),replaceContentInFile_compose=require("./compose-app/replace-content-in-file.compose.js"),packageName_validation=require("./validations/package-name.validation.js"),d=e=>(a,t)=>t.template==="api"?e:null,v=[{type:"text",name:"projectName",message:"What is your project name?",validate:async e=>(await promises.readdir(index.GENERATED_APP_ROOT_PATH)).includes(e)?"Already exists a folder with same name in current directory.":packageName_validation.packageNameValidation(e)},{type:"select",name:"packageManager",message:"What is your favorite package manager?",choices:[{title:"NPM",value:"npm"},{title:"Yarn",value:"yarn"},{title:"PNPM",value:"pnpm"}],initial:2},{type:"select",name:"template",message:"Select your template:",choices:[{title:"Clean",value:"clean"},{title:"API",value:"api"}]},{type:d("select"),name:"framework",message:"What is your favorite framework:",choices:[{title:"Fastify",value:"fastify"},{title:"Nest",value:"nest",disabled:!0},{title:"tRPC",value:"trpc",disabled:!0}],initial:0}];(async()=>{process.env.NODE_ENV==="development"&&!fs.existsSync(index.GENERATED_APP_ROOT_PATH)&&await promises.mkdir(index.GENERATED_APP_ROOT_PATH,{recursive:!0});const e=await y(v,{onCancel:onCancel.onCancelPrompt}),a=path.resolve(index.GENERATED_APP_ROOT_PATH,e.projectName);await copyTemplate_compose.copyTemplateCompose(a,e.framework?e.framework:"clean");const t=path.resolve(a,"package.json"),o=path.resolve(a,".env.example"),s=path.resolve(a,".husky/pre-commit");await Promise.all([replaceContentInFile_compose.replaceContentInFileCompose(t,[["app-name",e.projectName]]),replaceContentInFile_compose.replaceContentInFileCompose(o,[["app-name",e.projectName]]),replaceContentInFile_compose.replaceContentInFileCompose(s,[["pnpm",e.packageManager]])]),logs.successLog(`Success in creating new app ${picocolors.cyan(e.projectName)}!`,`> ${a}`)})();
2
+ const index=require("./src/config/index.js"),commander=require("commander"),path=require("path"),picocolors=require("picocolors"),C=require("prompts"),_package=require("./package.json.js"),copyTemplate_compose=require("./src/compose-app/copy-template.compose.js"),replaceContentInFile_compose=require("./src/compose-app/replace-content-in-file.compose.js"),logs=require("./src/utils/logs.js"),onCancel=require("./src/utils/on-cancel.js"),framework_validation=require("./src/validations/framework.validation.js"),packageManager_validation=require("./src/validations/package-manager.validation.js"),projectNameValidation=require("./src/validations/project-name-validation.js"),template_validation=require("./src/validations/template.validation.js"),g=new commander.Command().name(_package.default.name).description(_package.default.description);g.argument("[project-directory]","Name of the project or relative path of the project considering where the script was called.").option("--package-manager <package-manager>","Package manager that will be used in the project.").option("-t, --template <template-name>","Template that will be used in the project.").option("-f, --framework <framework-name>","Framework that will be used in the project.").action(async(i,o)=>{const r={projectDirectory:{value:i,validation:projectNameValidation.ProjectNameValidation.create({path:i})},packageManager:{value:o.packageManager,validation:packageManager_validation.PackageManagerValidation.create({packageManager:o.packageManager})},template:{value:o.template,validation:template_validation.TemplateValidation.create({template:o.template})},framework:{value:o.framework,validation:framework_validation.FrameworkValidation.create({framework:o.framework})}},l=Object.keys(r);for(const a of l){const t=r[a];t.value&&await t.validation.fromCli()}const{projectDirectory:e,packageManager:s,template:p,framework:n}=r,m=await C([{type:e.value?null:"text",name:"projectDirectory",message:"What is your project name?",validate:async a=>await e.validation.fromPrompt({path:a})},{type:s.value?null:"select",name:"packageManager",message:"What is your favorite package manager?",choices:packageManager_validation.packageManagers,initial:2},{type:!p.value&&!n.value?"select":null,name:"template",message:"Select your template:",choices:template_validation.templates},{type:(a,t)=>!n.value&&(p.value==="api"||t.template==="api")?"select":null,name:"framework",message:"What is your favorite framework?",choices:framework_validation.frameworks}],{onCancel:onCancel.onCancelPrompt});for(const a of l){const t=m[a];t&&(r[a].value=t)}n.value&&(r.template.value="api");const c=path.basename(e.value);e.value=path.resolve(index.GENERATED_APP_TARGET_ROOT_PATH,e.value),await copyTemplate_compose.copyTemplateCompose(e.value,n.value??"clean");const u=path.resolve(e.value,"package.json"),v=path.resolve(e.value,".env.example"),d=path.resolve(e.value,".husky/pre-commit");await Promise.all([replaceContentInFile_compose.replaceContentInFileCompose(u,[["app-name",c]]),replaceContentInFile_compose.replaceContentInFileCompose(v,[["app-name",c]]),replaceContentInFile_compose.replaceContentInFileCompose(d,[["pnpm",s.value]])]),logs.successLog(`Success in creating new app ${picocolors.cyan(c)}!`,`> ${e.value}`)});(async()=>await g.parseAsync(process.argv))();
@@ -0,0 +1 @@
1
+ Object.defineProperty(exports,"__esModule",{value:!0});const name="@leo-h/create-nodejs-app",version="1.0.2",packageManager="pnpm@9.1.1",author="Leonardo Henrique <leonardo0507.business@gmail.com>",description="Create a modern Node.js app with TypeScript using one command.",license="MIT",keywords=["node","node.js","typescript"],bin={"create-nodejs-app":"./dist/index.js"},files=["./dist","./templates"],repository={type:"git",url:"https://github.com/Leo-Henrique/create-nodejs-app"},scripts={prepare:"husky",start:"node ./dist/index.js","start:dev":"tsx ./src/index.ts","start:dev:watch":"tsx watch ./src/index.ts",typecheck:"tsc --noEmit",lint:"eslint . --ext .ts --max-warnings 0 --cache","lint:fix":"pnpm lint --fix",format:"prettier . --write --cache","test:unit":"vitest run","test:unit:watch":"vitest","test:e2e":"vitest run --config ./vitest.config.e2e.mts","test:e2e:watch":"vitest --config ./vitest.config.e2e.mts","test:coverage":"vitest run --coverage.enabled=true --coverage.all=false",template:"tsx ./scripts/template-cli.ts",prebuild:"rimraf ./dist",build:"unbuild",prepublishOnly:"pnpm build"},dependencies={"app-root-path":"3.1.0",commander:"12.1.0",picocolors:"1.0.1",prompts:"2.4.2","validate-npm-package-name":"5.0.1",zod:"3.23.8"},devDependencies={"@faker-js/faker":"8.4.1","@types/node":"20.12.12","@types/prompts":"2.4.9","@types/validate-npm-package-name":"4.0.2","@typescript-eslint/eslint-plugin":"7.10.0","@typescript-eslint/parser":"7.10.0","conventional-changelog-conventionalcommits":"8.0.0",eslint:"8.57.0","eslint-config-prettier":"9.1.0","eslint-plugin-vitest":"0.4.0",husky:"9.0.11","lint-staged":"15.2.2","npm-run-all":"4.1.5",prettier:"3.2.5",rimraf:"5.0.7",tsx:"4.10.5",typescript:"5.4.5",unbuild:"2.0.0","vite-tsconfig-paths":"4.3.2",vitest:"1.6.0"},f={name,version,packageManager,author,description,license,keywords,bin,files,repository,scripts,dependencies,devDependencies};exports.author=author;exports.bin=bin;exports.default=f;exports.dependencies=dependencies;exports.description=description;exports.devDependencies=devDependencies;exports.files=files;exports.keywords=keywords;exports.license=license;exports.name=name;exports.packageManager=packageManager;exports.repository=repository;exports.scripts=scripts;exports.version=version;
@@ -0,0 +1 @@
1
+ const o=require("app-root-path"),fs=require("fs"),path=require("path");!process.env.NODE_ENV&&process.argv[1].endsWith(".js")?process.env.NODE_ENV="production":process.env.NODE_ENV="development";const GENERATED_APP_TARGET_ROOT_PATH=process.env.NODE_ENV==="production"?process.cwd():path.resolve(o.path,"generated-apps");process.env.NODE_ENV!=="production"&&!fs.existsSync(GENERATED_APP_TARGET_ROOT_PATH)&&fs.mkdirSync(GENERATED_APP_TARGET_ROOT_PATH);const TEMPLATES_PATH=path.resolve(o.path,"templates");path.resolve(TEMPLATES_PATH,"clean");exports.GENERATED_APP_TARGET_ROOT_PATH=GENERATED_APP_TARGET_ROOT_PATH;exports.TEMPLATES_PATH=TEMPLATES_PATH;
@@ -0,0 +1 @@
1
+ const left=require("../utils/left.js");var r=Object.defineProperty,e=(a,t,i)=>t in a?r(a,t,{enumerable:!0,configurable:!0,writable:!0,value:i}):a[t]=i,s=(a,t,i)=>(e(a,typeof t!="symbol"?t+"":t,i),i);class Validation{constructor(){s(this,"params")}createValidation(t){return t&&(this.params=t),this}async fromCli(t){t&&(this.params=t);const i=await this.validate();if(!i.isValid)return left.left(i.issue)}async fromPrompt(t){t&&(this.params=t);const i=await this.validate();return i.isValid?!0:i.issue}}exports.Validation=Validation;
@@ -0,0 +1 @@
1
+ function getValidOptionsFromSelect(t){return t.filter(e=>!e.disabled).map(({value:e})=>e)}exports.getValidOptionsFromSelect=getValidOptionsFromSelect;
@@ -0,0 +1 @@
1
+ const logs=require("./logs.js");function left(e){logs.errorLog(e),process.exit(1)}exports.left=left;
@@ -0,0 +1 @@
1
+ const validation=require("../core/validation.js"),getValidOptionsFromPrompt=require("../utils/get-valid-options-from-prompt.js"),frameworks=[{title:"Fastify",value:"fastify"},{title:"Nest",value:"nest"},{title:"tRPC",value:"trpc",disabled:!0}],validFrameworks=getValidOptionsFromPrompt.getValidOptionsFromSelect(frameworks);class FrameworkValidation extends validation.Validation{static create(t){return new this().createValidation(t)}async validate(){let{framework:t}=this.params;return t=t.toLowerCase(),validFrameworks.includes(t)?{isValid:!0}:{isValid:!1,issue:`Invalid framework, consider the options: ${validFrameworks.map(e=>`"${e}"`).join(", ")}.`}}}exports.FrameworkValidation=FrameworkValidation;exports.frameworks=frameworks;exports.validFrameworks=validFrameworks;
@@ -0,0 +1 @@
1
+ const validation=require("../core/validation.js"),getValidOptionsFromPrompt=require("../utils/get-valid-options-from-prompt.js"),packageManagers=[{title:"NPM",value:"npm"},{title:"Yarn",value:"yarn"},{title:"PNPM",value:"pnpm"}],validPackageManagers=getValidOptionsFromPrompt.getValidOptionsFromSelect(packageManagers);class PackageManagerValidation extends validation.Validation{static create(a){return new this().createValidation(a)}async validate(){let{packageManager:a}=this.params;return a=a.toLowerCase(),validPackageManagers.includes(a)?{isValid:!0}:{isValid:!1,issue:`Invalid package manager, consider the options: ${validPackageManagers.map(e=>`"${e}"`).join(", ")}.`}}}exports.PackageManagerValidation=PackageManagerValidation;exports.packageManagers=packageManagers;exports.validPackageManagers=validPackageManagers;
@@ -0,0 +1 @@
1
+ const index=require("../config/index.js"),validation=require("../core/validation.js"),toPascalCase=require("../utils/to-pascal-case.js"),fs=require("fs"),promises=require("fs/promises"),path=require("path"),c=require("validate-npm-package-name");class ProjectNameValidation extends validation.Validation{static create(e){return new this().createValidation(e)}async validate(){const{path:e}=this.params,a=path.basename(e),s=path.resolve(index.GENERATED_APP_TARGET_ROOT_PATH,e);if(fs.existsSync(s)&&(await promises.readdir(s)).includes(a))return{isValid:!1,issue:`Folder with name "${a}" already exists in project directory.`};const i=c(a);return i.validForNewPackages?{isValid:!0}:{isValid:!1,issue:toPascalCase.toPascalCase(i.errors[0])}}}exports.ProjectNameValidation=ProjectNameValidation;
@@ -0,0 +1 @@
1
+ const validation=require("../core/validation.js"),getValidOptionsFromPrompt=require("../utils/get-valid-options-from-prompt.js"),templates=[{title:"Clean",value:"clean"},{title:"API",value:"api"}],validTemplates=getValidOptionsFromPrompt.getValidOptionsFromSelect(templates);class TemplateValidation extends validation.Validation{static create(e){return new this().createValidation(e)}async validate(){let{template:e}=this.params;return e=e.toLowerCase(),validTemplates.includes(e)?{isValid:!0}:{isValid:!1,issue:`Invalid template, consider the options: ${validTemplates.map(t=>`"${t}"`).join(", ")}.`}}}exports.TemplateValidation=TemplateValidation;exports.templates=templates;exports.validTemplates=validTemplates;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leo-h/create-nodejs-app",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "packageManager": "pnpm@9.1.1",
5
5
  "author": "Leonardo Henrique <leonardo0507.business@gmail.com>",
6
6
  "description": "Create a modern Node.js app with TypeScript using one command.",
@@ -32,14 +32,16 @@
32
32
  "format": "prettier . --write --cache",
33
33
  "test:unit": "vitest run",
34
34
  "test:unit:watch": "vitest",
35
+ "test:e2e": "vitest run --config ./vitest.config.e2e.mts",
36
+ "test:e2e:watch": "vitest --config ./vitest.config.e2e.mts",
35
37
  "test:coverage": "vitest run --coverage.enabled=true --coverage.all=false",
36
- "template:create": "tsx ./scripts/create-template.script.ts",
37
- "template:open": "tsx ./scripts/open-template.script.ts",
38
+ "template": "tsx ./scripts/template-cli.ts",
38
39
  "prebuild": "rimraf ./dist",
39
40
  "build": "unbuild",
40
41
  "prepublishOnly": "pnpm build"
41
42
  },
42
43
  "dependencies": {
44
+ "app-root-path": "3.1.0",
43
45
  "commander": "12.1.0",
44
46
  "picocolors": "1.0.1",
45
47
  "prompts": "2.4.2",