@chore-dev/composer
Version:
Single command project setup! This package automates essential tools for code style, version control, releases, and Docker.
17 lines (14 loc) • 29.2 kB
JavaScript
import{DateTime}from"luxon";import inquirer from"inquirer";import chalk from"chalk";import{copyFileSync,existsSync,readFileSync,mkdirSync,renameSync,writeFileSync}from"fs";import commandLineArgs from"command-line-args";import{dirname,resolve}from"path";import{fileURLToPath}from"url";import{execSync}from"child_process";let ANSWERS={};const getAnswers=()=>ANSWERS,updateAnswers=e=>{ANSWERS={...ANSWERS,...e}};var version="1.1.0";const CONSOLE=console;let avoidDuplicateLinebreak=!1;const underline=chalk.underline,loggerBuilder=(n="",r)=>(e,...t)=>{var[e,i=!1]=e;!avoidDuplicateLinebreak&&e&&CONSOLE.log(""),r?CONSOLE.log(r(...n?[`[${n}]`]:[],...t)):CONSOLE.log(...n?[`[${n}]`]:[],...t),i&&CONSOLE.log(""),avoidDuplicateLinebreak=i},box=(t,e,i)=>{var[e,n=!1]=e;const r=Math.max(...i.map(e=>e.length));var s=`+${"-".repeat(r+2)}+`;t([e],s),i.forEach(e=>{t([!1],`| ${e}${" ".repeat(r-e.length)} |`)}),t([!1,n],s)},error=loggerBuilder("ERROR",chalk.red.bold),log=loggerBuilder(),task=loggerBuilder("TASK",chalk.cyan.bold),warn=loggerBuilder("WARNING",chalk.yellow.bold),MAX_LENGTH=85,separator=(e=MAX_LENGTH,t)=>{var i;return t?(i=(e-t.length-2)/2,"=".repeat(Math.floor(i))+` ${t} `+"=".repeat(Math.ceil(i))):"=".repeat(e)},APP_HEADER=()=>log([!0],`${separator()}
█████╗ █████╗ ███╗ ███╗ ██████╗ █████╗ ██████╗ ███████╗ ██████╗
██╔══██╗ ██╔══██╗ ████╗ ████║ ██╔══██╗ ██╔══██╗ ██╔════╝ ██╔════╝ ██╔══██╗
██║ ╚═╝ ██║ ██║ ██╔████╔██║ ██████╔╝ ██║ ██║ ╚█████╗ █████╗ ██████╔╝
██║ ██╗ ██║ ██║ ██║╚██╔╝██║ ██╔═══╝ ██║ ██║ ╚═══██╗ ██╔══╝ ██╔══██╗
╚█████╔╝ ╚█████╔╝ ██║ ╚═╝ ██║ ██║ ╚█████╔╝ ██████╔╝ ███████╗ ██║ ██║
╚════╝ ╚════╝ ╚═╝ ╚═╝ ╚═╝ ╚════╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═╝
${("v"+version).padStart(56," ")} by ${underline("Chore Team")} |
| Running under...
| Dir : ${underline(process.cwd())}
| Node: ${underline(process.version)}
`+separator()),APP_FOOTER=()=>log([!0,!0],separator(void 0,"ALL TASK(S) COMPLETED")),FLOW_HEAD=`│
└─┐`,FLOW_BODY=" ├─",FLOW_TAIL=`┌─┘
│`,PACKAGE_MANAGERS={npm:{isDefault:!1,label:"npm",scripts:{execute:"npx --no --",install:(e=!1)=>"npm i"+(e?" --save-dev":" --save"),run:"npm run"}},pnpm:{isDefault:!1,label:"PNPm",scripts:{execute:"pnpm dlx",install:(e=!1)=>"pnpm i"+(e?" -D":""),run:"pnpm run"}},yarn:{isDefault:!0,label:"Yarn",scripts:{execute:"yarn",install:(e=!1)=>"yarn add"+(e?" -D":""),run:"yarn"}}},basic=(e,t,i)=>({message:i,name:t,type:e}),massageChoices=e=>e.map(([e,t,i=e,n=!1,r=!1])=>({checked:n,disabled:r,label:e,short:i,value:t})),createList=(e,t,i)=>{var n=i.findIndex(({checked:e})=>e)||0;return{...basic("list",e,t),choices:i,default:n,loop:!0}},createListChoice=({label:e,value:t,...i})=>({name:e,value:t,...i}),createYesNo=(e,t,i=!1)=>({...basic("list",e,t),choices:massageChoices([["Yes","yes"],["No","no"]]).map(createListChoice),default:i?1:0,filter:e=>"yes"===e.toLowerCase(),loop:!0}),shouldContinue=async(e="Continue?",t=!0)=>(await inquirer.prompt([createYesNo("continue",e,t)])).continue,section=async(e,t)=>{!1!==t&&(log([!1],FLOW_HEAD),log([!1],FLOW_BODY+" ",underline(e)),log([!1],FLOW_TAIL),await t())},sectionWithConfirmation=(e,t,i)=>section(e,async()=>{await shouldContinue(`Do you want to include ${e}?`,!1)?updateAnswers(await t()):updateAnswers(await i())}),createCheckbox=(e,t,i)=>({...basic("checkbox",e,t),choices:i,filter:t=>Object.fromEntries(i.map(({value:e})=>[e,t.includes(e)])),loop:!0}),createCheckboxChoice=({label:e,value:t,...i})=>({name:e,value:t,...i}),CHOICES$c=[["Browser","isBrowser",void 0,!0],["Node","isNode"]],QUESTION$e=e=>createCheckbox(e,"Where does your code run?",massageChoices(CHOICES$c).map(createCheckboxChoice)),KEY$e="env",ENV={KEY:KEY$e,CHOICES:CHOICES$c,QUESTION:QUESTION$e(KEY$e)},CHOICES$b=[["React","react",void 0,!0],["Vue.js","vue"],["Non of these","none"]],QUESTION$d=e=>createList(e,"Which framework does your project use?",massageChoices(CHOICES$b).map(createListChoice)),KEY$d="framework",FRAMEWORK={KEY:KEY$d,CHOICES:CHOICES$b,QUESTION:QUESTION$d(KEY$d)},CHOICES$a=Object.entries(PACKAGE_MANAGERS).map(([e,{label:t,isDefault:i}])=>[t,e,t,i]),QUESTION$c=e=>createList(e,"Which package manager do you prefer?",massageChoices(CHOICES$a).map(createListChoice)),KEY$c="packageManager",PACKAGE_MANAGER={KEY:KEY$c,CHOICES:CHOICES$a,QUESTION:QUESTION$c(KEY$c)},CHOICES$9=[["CSS","css"],["SCSS","scss",void 0,!0],["No style sheet needed","none"]],QUESTION$b=e=>createList(e,"Which style sheet system do you prefer?",massageChoices(CHOICES$9).map(createListChoice)),KEY$b="styleSheet",STYLE_SHEET={KEY:KEY$b,CHOICES:CHOICES$9,QUESTION:QUESTION$b(KEY$b)},QUESTION$a=e=>createYesNo(e,"Do you use JS/TS syntax extension(JSX/TSX)?"),KEY$a="withSyntaxExtension",SYNTAX_EXTENSION={KEY:KEY$a,QUESTION:QUESTION$a(KEY$a)},onBoardingQuestions=()=>section("Onboarding Questions",async()=>{updateAnswers(await inquirer.prompt([PACKAGE_MANAGER.QUESTION,ENV.QUESTION,FRAMEWORK.QUESTION,SYNTAX_EXTENSION.QUESTION,STYLE_SHEET.QUESTION]))}),isValidCheckboxAnswer=e=>!(!e||"object"!=typeof e||!Object.values(e).some(Boolean)),CHOICES$8=[["Install dependencies","install","Install",!0],["Create commitlint.config.js","createConfig","Config",!0],["Integrate with Husky","integrate","Integrate",!0]],QUESTION$9=e=>createCheckbox(e,"Please check the item(s) you need",massageChoices(CHOICES$8).map(createCheckboxChoice)),definitions=[{name:"dry-run",alias:"D",type:Boolean},{name:"no-backup",type:Boolean},{name:"preset",alias:"P",type:String}],keyMap={[definitions[0].name]:"dryRun",[definitions[1].name]:"noBackup"},CLI=Object.fromEntries(Object.entries(commandLineArgs(definitions)).map(([e,t])=>[keyMap[e]||e,t])),getCli=()=>CLI;let APPLICATION={};const getApplication=()=>APPLICATION,updateApplication=e=>{APPLICATION={...APPLICATION,...e}},BACKUP_DIRECTORY=".composer.bak",directoryResolverBuilder=t=>(e="./")=>resolve("function"==typeof t?t():t,e),PWD=directoryResolverBuilder(process.cwd()),DIST=directoryResolverBuilder(dirname(fileURLToPath(import.meta.url))),backupDirectory=directoryResolverBuilder(PWD("./"+BACKUP_DIRECTORY)),datetimeDirectory=directoryResolverBuilder(()=>backupDirectory(getApplication().datetime)),templateDirectory=e=>DIST("./templates/"+e),backup=e=>{var t;getCli().noBackup||!isPathExist(e)||(isPathExist(backupDirectory())||mkdirSync(backupDirectory()),isPathExist(datetimeDirectory())||mkdirSync(datetimeDirectory()),t=e.split("/").pop(),isPathExist(datetimeDirectory("./"+t)))||(warn([!1],`Existing ${t} under ${e} found`),warn([!1],"Backing up..."),renameSync(e,datetimeDirectory("./"+t)),warn([!1],"Backup successful! Please find backup file(s) in "+datetimeDirectory()))},backupBeforeCopy=(e,t)=>{backup(t),task([!1],`Creating ${t}...`),copyFileSync(e,t),task([!1,!0],"Created!")},backupBeforeWrite=(e,t)=>{backup(e),task([!1],`Creating ${e}...`),writeFileSync(e,"string"==typeof t?t:JSON.stringify(t,null,2)),task([!1,!0],"Created!")},isPathExist=e=>existsSync(e),readJson=e=>JSON.parse(readFileSync(e,"utf8")),readPackageJson=()=>readJson(PWD("./package.json")),condition=(e,t)=>e?t:void 0,exportByPackageType=e=>`${"module"===readPackageJson().type?"export default":"module.exports ="} ${e};`,indent=(e,t=1)=>{e=Array.isArray(e)?lines(e):e;return e&&e.split("\n").map(e=>""+" ".repeat(2*t)+e).join("\n")},lines=e=>e.flat().filter(e=>e||!e&&""===e).join("\n"),createCommitLintConfig=()=>lines(["const config = {",indent("extends: ['@commitlint/config-conventional']"),"};","",exportByPackageType("config")]),createConfig$5=()=>{backupBeforeWrite(PWD("./commitlint.config.js"),createCommitLintConfig())},addScriptToPackageJson=e=>{if(isPathExist(PWD("./package.json"))){var t=JSON.parse(readFileSync(PWD("./package.json"),"utf8"));const i={...t.scripts};e.forEach(([e,t])=>{e in i&&(i["// composer-backup-"+e]=""+i[e]),i[e]=t}),t.scripts=i,backupBeforeWrite(PWD("./package.json"),t)}else error([!0,!0],`Failed to add script to package.json. package.json not found, run \`${managerRun("init")}\` first.`)},execInPwd=e=>execSync(`cd ${PWD()} && `+e),managerInstall=(e,t=!1)=>{var e=Array.isArray(e)?e.filter(Boolean).join(" "):e,i=PACKAGE_MANAGERS[getAnswers().packageManager].scripts.install;task([!1],`Installing ${e}...`),execInPwd(i(t)+" "+e),task([!1,!0],"Installed!")},managerRun=e=>PACKAGE_MANAGERS[getAnswers().packageManager].scripts.run+" "+e,install$6=()=>{managerInstall("@commitlint/cli @commitlint/config-conventional",!0)},createCommitMsgHook=()=>['. "$(dirname -- "$0")/common.sh"',"",PACKAGE_MANAGERS[getAnswers().packageManager].scripts.execute+" commitlint --edit $1"].join("\n"),integrate$1=()=>{var e=getAnswers()["husky"];e&&(isPathExist(PWD("./.husky"))?backupBeforeWrite(PWD("./.husky/commit-msg"),createCommitMsgHook()):error([!0,!0],`Failed to integrate with Husky. Husky is not initialized in this directory, run \`${managerRun("prepare")}\` first.`))},TASK$9=()=>{var e=getAnswers()["commitLint"];e&&(e.createConfig&&createConfig$5(),e.install&&install$6(),e.integrate)&&integrate$1()},KEY$9="commitLint",COMMIT_LINT={KEY:KEY$9,CHOICES:CHOICES$8,QUESTION:QUESTION$9(KEY$9),TASK:TASK$9},TITLE$9="commitlint",commitLintQuestions=()=>sectionWithConfirmation(TITLE$9,async()=>inquirer.prompt([COMMIT_LINT.QUESTION]),()=>({[KEY$9]:!1})),commitLintTasks=()=>section(TITLE$9,isValidCheckboxAnswer(getAnswers()[KEY$9])&&COMMIT_LINT.TASK),CHOICES$7=[["Create .dockerignore","addIgnores","Ignores",!0]],QUESTION$8=e=>createCheckbox(e,"Please check the item(s) you need",massageChoices(CHOICES$7).map(createCheckboxChoice)),addIgnores$2=()=>{backupBeforeCopy(templateDirectory(".dockerignore"),PWD("./.dockerignore"))},TASK$8=()=>{var e=getAnswers()["docker"];e&&e.addIgnores&&addIgnores$2()},KEY$8="docker",DOCKER={KEY:KEY$8,CHOICES:CHOICES$7,QUESTION:QUESTION$8(KEY$8),TASK:TASK$8},TITLE$8="Docker",dockerQuestions=()=>sectionWithConfirmation(TITLE$8,async()=>inquirer.prompt([DOCKER.QUESTION]),()=>({[KEY$8]:!1})),dockerTasks=()=>section(TITLE$8,isValidCheckboxAnswer(getAnswers()[KEY$8])&&DOCKER.TASK),QUESTION$7=e=>createYesNo(e,"Do you want to create .editorconfig?"),TASK$7=()=>{var e=getAnswers()["editorConfig"];e.createConfig&&backupBeforeCopy(templateDirectory(".editorconfig"),PWD("./.editorconfig"))},KEY$7="createConfig",EDITOR_CONFIG={KEY:KEY$7,QUESTION:QUESTION$7(KEY$7),TASK:TASK$7},TITLE$7="EditorConfig",editorConfigQuestions=()=>{return section(TITLE$7,async()=>{updateAnswers({editorConfig:await inquirer.prompt([EDITOR_CONFIG.QUESTION])})})},editorConfigTasks=()=>{return section(TITLE$7,isValidCheckboxAnswer(getAnswers().editorConfig)&&(()=>{EDITOR_CONFIG.TASK()}))},CHOICES$6=[["Install dependencies","install","Install",!0],["Insert scripts","insertScripts","Scripts",!0],["Create eslint.config.js","createConfig","Config",!0],["Add ignores in config","addIgnores","Ignores",!0]],QUESTION$6=e=>createCheckbox(e,"Please check the item(s) you need",massageChoices(CHOICES$6).map(createCheckboxChoice)),imports=()=>{var{framework:e,prettier:t}=getAnswers(),i=(t||{})["createConfig"];const n="module"===readPackageJson().type;var r="react"===e,e="vue"===e;return lines([["esLint","@eslint/js"],condition(t,["prettierRecommended","eslint-plugin-prettier/recommended"]),condition(r,["reactRecommended","eslint-plugin-react/configs/recommended"]),condition(e,["vueESLint","eslint-plugin-vue"]),["globals","globals"],["tsESLint","typescript-eslint"],condition(e,["vueParser","vue-eslint-parser"]),condition(i,["prettierConfig","./.prettier.config.js"])].filter(Boolean).map(([e,t])=>n?`import ${e} from '${t}';`:`const ${e} = require('${t}');`))},notes=()=>{var e=getAnswers()["typescript"];return condition(!e,lines(['// NOTE: You may ask why using "tsESLint.config" even you are not using TypeScript?',`// It's because "tsESLint.config" is well typed to provide autocomplete and documentation for all config properties to prevent invalid configurations`,"// In the simplest terms, this improves the developer experience.",'// To learn more about "tsESLint.config", visit https://typescript-eslint.io/packages/typescript-eslint#config']))},recommends=()=>{var{framework:e,prettier:t,typescript:i}=getAnswers();return lines(["esLint.configs.recommended,",condition(i,"tsESLint.configs.strict,"),condition(i,"tsESLint.configs.stylistic,"),condition(t,"prettierRecommended,"),condition("vue"===e,"...vueESLint.configs['flat/recommended'],")])},ignores=()=>{var{commitLint:e,eslint:t,lintStaged:i,prettier:n}=getAnswers(),e=(e||{})["createConfig"],i=(i||{})["createConfig"],n=(n||{})["createConfig"];if(t&&t.addIgnores)return lines(["{",indent(["ignores: [",indent(["// Backup files","'.composer.bak/',","// Build output directory","'coverage/',","'build/',","'bundle/',","'dist/',","'out/',","// Cache files","'.eslintcache',","// Config files",condition(n,"'.prettier.config.js',"),condition(e,"'commitlint.config.js',"),"'eslint.config.js',",condition(i,"'lint-staged.config.js'")]),"]"]),"},"])},main=()=>{var{env:e,framework:t,prettier:i,typescript:n,withSyntaxExtension:r}=getAnswers(),{isBrowser:e,isNode:s}=e,o=(i||{})["createConfig"],a="react"===t,t="vue"===t,r=["js",condition(r,"jsx"),condition(n,"ts"),condition(n&&r,"tsx"),condition(t,"vue")].filter(Boolean).join(","),e=[condition(e,".browser,"),".es2021,",".jest,",condition(s,".node,"),".serviceworker,",condition(e&&s,"['shared-node-browser'],"),".worker"].filter(Boolean).map(e=>"...globals"+e),s=[["import/no-duplicates",0],["no-console",2,JSON.stringify({allow:["error","warn"]})],...condition(i,[["prettier/prettier",2,o?"prettierConfig":void 0]])||[],...condition(a,[["react/jsx-uses-react",0],condition(!n,["react/prop-types",2]),["react/react-in-jsx-scope",0]])||[],...condition(t,[["vue/html-self-closing",0],["vue/singleline-html-element-content-newline",0]])||[],...condition(n,[["@typescript-eslint/ban-ts-comment",2,JSON.stringify({"ts-check":"allow-with-description","ts-expect-error":"allow-with-description","ts-ignore":"allow-with-description","ts-nocheck":"allow-with-description"})],["@typescript-eslint/consistent-type-definitions",0],["@typescript-eslint/explicit-module-boundary-types",0],["@typescript-eslint/no-empty-interface",0],["@typescript-eslint/no-explicit-any",2],["@typescript-eslint/no-restricted-types",2,JSON.stringify({types:{}})],["@typescript-eslint/no-unused-vars",2,JSON.stringify({argsIgnorePattern:"^_"})]])||[]].filter(Boolean).map(([e,t,i],n,r)=>{t=["off","warn","error"][t],n=n===r.length-1?"":",";return i?`'${e}': ['${t}', ${i}]`+n:`'${e}': '${t}'`+n});return lines([condition(t,lines(["{",indent(["files: ['**/*.vue'],","languageOptions: {",indent(["parser: vueParser,","parserOptions: {",indent(["parser: tsESLint.parser,","sourceType: 'module'"]),"}"]),"},"]),"},"])),"{",indent([`files: ['**/*.{${r}}'],`,condition(a,"...reactRecommended,"),"languageOptions: {",indent([condition(a,"...reactRecommended.languageOptions,"),"globals: {",indent(e),"}"]),"},","rules: {",condition(a,"...reactRecommended.rules,"),indent(s),"},"]),"},"])},createESLintConfig=()=>lines([imports(),"",notes(),'/** @type {ReturnType<typeof import("typescript-eslint").config>} */',"const config = tsESLint.config(",indent([ignores(),recommends(),main()]),");","",exportByPackageType("config")]),createConfig$4=()=>{backupBeforeWrite(PWD("./eslint.config.js"),createESLintConfig())},insertScripts$3=()=>{var e,{eslint:t,prettier:i}=getAnswers();t&&(t=t["createConfig"],i=(i||{})["insertScripts"],t=t?" --config eslint.config.js":"",i=i?managerRun("prettier:fix")+"; ":"",e=" --fix --quiet",addScriptToPackageJson([["// ESLint","---------- ---------- ---------- ---------- ----------"],["eslint",i+managerRun("eslint:no-glob .")],["eslint:no-glob","eslint --cache --color"+t],["eslint:fix",managerRun("eslint"+e)],["eslint:fix:no-glob",managerRun("eslint:no-glob"+e)]]))},FIXED_VERSION="@8",install$5=()=>{var{framework:e,prettier:t}=getAnswers(),e=[`eslint${FIXED_VERSION} globals typescript-eslint @eslint/js${FIXED_VERSION} @types/eslint__js`+FIXED_VERSION,"react"===e&&"eslint-plugin-react","vue"===e&&"eslint-plugin-vue vue-eslint-parser",t&&"eslint-config-prettier eslint-plugin-prettier"];managerInstall(e,!0)},TASK$6=()=>{var e=getAnswers()["eslint"];e&&(e.install&&install$5(),e.insertScripts&&insertScripts$3(),e.createConfig)&&createConfig$4()},KEY$6="eslint",ESLINT={KEY:KEY$6,CHOICES:CHOICES$6,QUESTION:QUESTION$6(KEY$6),TASK:TASK$6},TITLE$6="ESLint",esLintQuestions=()=>sectionWithConfirmation(TITLE$6,async()=>inquirer.prompt([ESLINT.QUESTION]),()=>({[KEY$6]:!1})),esLintTasks=()=>section(TITLE$6,isValidCheckboxAnswer(getAnswers()[KEY$6])&&ESLINT.TASK),CHOICES$5=[["Create .gitignore","addIgnores","Ignores",!0]],QUESTION$5=e=>createCheckbox(e,"Please check the item(s) you need",massageChoices(CHOICES$5).map(createCheckboxChoice)),addIgnores$1=()=>{backupBeforeCopy(templateDirectory(".gitignore-template"),PWD("./.gitignore"))},TASK$5=()=>{var e=getAnswers()["git"];e&&e.addIgnores&&addIgnores$1()},KEY$5="git",GIT={KEY:KEY$5,CHOICES:CHOICES$5,QUESTION:QUESTION$5(KEY$5),TASK:TASK$5},TITLE$5="Git",gitQuestions=()=>sectionWithConfirmation(TITLE$5,async()=>inquirer.prompt([GIT.QUESTION]),()=>({[KEY$5]:!1})),gitTasks=()=>section(TITLE$5,isValidCheckboxAnswer(getAnswers()[KEY$5])&&GIT.TASK),CHOICES$4=[["Install dependencies","install","Install",!0],["Insert scripts","insertScripts","Scripts",!0]],QUESTION$4=e=>createCheckbox(e,"Please check the item(s) you need",massageChoices(CHOICES$4).map(createCheckboxChoice)),insertScripts$2=()=>{addScriptToPackageJson([["prepare","husky"]]),isPathExist(PWD("./.git"))?(execInPwd(managerRun("prepare")),backupBeforeCopy(templateDirectory("common.sh"),PWD("./.husky/common.sh"))):error([!0,!0],"Failed to initialize husky. Git is not initialized in this directory, run `git init` first.")},install$4=()=>{managerInstall("husky",!0)},TASK$4=()=>{var e=getAnswers()["husky"];e&&(e.install&&install$4(),e.insertScripts)&&insertScripts$2()},KEY$4="husky",HUSKY={KEY:KEY$4,CHOICES:CHOICES$4,QUESTION:QUESTION$4(KEY$4),TASK:TASK$4},TITLE$4="Husky",huskyQuestions=()=>sectionWithConfirmation(TITLE$4,async()=>inquirer.prompt([HUSKY.QUESTION]),()=>({[KEY$4]:!1})),huskyTasks=()=>section(TITLE$4,isValidCheckboxAnswer(getAnswers()[KEY$4])&&HUSKY.TASK),CHOICES$3=[["Install dependencies","install","Install",!0],["Create lint-staged.config.js","createConfig","Config",!0],["Integrate with Husky","integrate","Integrate",!0]],QUESTION$3=e=>createCheckbox(e,"Please check the item(s) you need",massageChoices(CHOICES$3).map(createCheckboxChoice)),createLintStagedConfig=()=>{var{eslint:e,prettier:t}=getAnswers(),e=(e||{})["insertScripts"],t=(t||{})["insertScripts"],i="module"===readPackageJson().type,t={"*":[t&&managerRun("prettier:fix:no-glob"),e&&managerRun("eslint:fix:no-glob")].filter(Boolean)};return['/** @type {import("lint-staged").Config} */',"",`const config = ${JSON.stringify(t,null,2)};`,"",i?"export default config;":"module.exports = config;"].join("\n")},createConfig$3=()=>{backupBeforeWrite(PWD("./lint-staged.config.js"),createLintStagedConfig())},install$3=()=>{managerInstall("lint-staged @types/lint-staged",!0)},createPreCommitHook=()=>{var e=getAnswers()["lintStaged"],e=(e||{})["createConfig"],e=e?" --config lint-staged.config.js":"";return['. "$(dirname -- "$0")/common.sh"',"",PACKAGE_MANAGERS[getAnswers().packageManager].scripts.execute+" lint-staged"+e].join("\n")},integrate=()=>{var e=getAnswers()["husky"];e&&(isPathExist(PWD("./.husky"))?backupBeforeWrite(PWD("./.husky/pre-commit"),createPreCommitHook()):error([!0,!0],`Failed to integrate with Husky. Husky is not initialized in this directory, run \`${managerRun("prepare")}\` first.`))},TASK$3=()=>{var e=getAnswers()["lintStaged"];e&&(e.createConfig&&createConfig$3(),e.install&&install$3(),e.integrate)&&integrate()},KEY$3="lintStaged",LINT_STAGED={KEY:KEY$3,CHOICES:CHOICES$3,QUESTION:QUESTION$3(KEY$3),TASK:TASK$3},TITLE$3="lint-staged",lintStagedQuestions=()=>sectionWithConfirmation(TITLE$3,async()=>inquirer.prompt([LINT_STAGED.QUESTION]),()=>({[KEY$3]:!1})),lintStagedTasks=()=>section(TITLE$3,isValidCheckboxAnswer(getAnswers()[KEY$3])&&LINT_STAGED.TASK),CHOICES$2=[["Install dependencies","install","Install",!0],["Insert scripts","insertScripts","Scripts",!0],["Create .prettier.config.js","createConfig","Config",!0],["Create .prettierignore","addIgnores","Ignores",!0]],QUESTION$2=e=>createCheckbox(e,"Please check the item(s) you need",massageChoices(CHOICES$2).map(createCheckboxChoice)),addIgnores=()=>{backupBeforeCopy(templateDirectory(".prettierignore"),PWD("./.prettierignore"))},createPrettierConfig=()=>{var e="module"===readPackageJson().type;return['/** @type {import("prettier").Config} */',"",`const config = ${JSON.stringify({arrowParens:"avoid",bracketSameLine:!1,bracketSpacing:!0,embeddedLanguageFormatting:"auto",htmlWhitespaceSensitivity:"css",jsxSingleQuote:!0,proseWrap:"preserve",quoteProps:"as-needed",semi:!0,singleAttributePerLine:!0,trailingComma:"none",overrides:[{files:["*.md","*.mdx"],options:{proseWrap:"always"}}]},null,2)};`,"",e?"export default config;":"module.exports = config;"].join("\n")},createConfig$2=()=>{backupBeforeWrite(PWD("./.prettier.config.js"),createPrettierConfig())},insertScripts$1=()=>{var e,{env:t,framework:i,prettier:n,styleSheet:r,typescript:s,withSyntaxExtension:o}=getAnswers();n&&({addIgnores:n,createConfig:e}=n,e=e?" --config .prettier.config.js":"",n=n?" --ignore-path .prettierignore":"",r=["none"!==r&&("scss"===r?"?(s)css":"css"),t.isBrowser&&["html"],o?"js":"js?(x)",!!s&&(o?"ts":"ts?(x)"),"vue"===i&&"vue","json"].flat().filter(Boolean).join(","),addScriptToPackageJson([["// Prettier","---------- ---------- ---------- ---------- ----------"],["prettier",managerRun("prettier:base -c")],["prettier:base",managerRun(`prettier:base:no-glob './**/*.{${r}}'`)],["prettier:base:no-glob",`prettier --cache${e}${n} --ignore-unknown`],["prettier:fix",managerRun("prettier:base -w")],["prettier:fix:no-glob",managerRun("prettier:base:no-glob -w")]]))},install$2=()=>{managerInstall("prettier",!0)},TASK$2=()=>{var e=getAnswers()["prettier"];e&&(e.install&&install$2(),e.insertScripts&&insertScripts$1(),e.createConfig&&createConfig$2(),e.addIgnores)&&addIgnores()},KEY$2="prettier",PRETTIER={KEY:KEY$2,CHOICES:CHOICES$2,QUESTION:QUESTION$2(KEY$2),TASK:TASK$2},TITLE$2="Prettier",prettierQuestions=()=>sectionWithConfirmation(TITLE$2,async()=>inquirer.prompt([PRETTIER.QUESTION]),()=>({[KEY$2]:!1})),prettierTasks=()=>section(TITLE$2,isValidCheckboxAnswer(getAnswers()[KEY$2])&&PRETTIER.TASK),CHOICES$1=[["Install dependencies","install","Install",!0],["Insert scripts","insertScripts","Scripts",!0],["Create .release-it.json","createConfig","Config",!0]],QUESTION$1=e=>createCheckbox(e,"Please check the item(s) you need",massageChoices(CHOICES$1).map(createCheckboxChoice)),createReleaseItConfig=()=>{var e="v${version}";return{hooks:{},git:{commit:!0,commitMessage:"chore: release "+e,push:!0,pushArgs:["--follow-tags"],tag:!0,tagAnnotation:e,tagName:e,requireBranch:"develop",requireCleanWorkingDir:!0},npm:{publish:!1},github:{release:!1},gitlab:{release:!1},plugins:{"@release-it/conventional-changelog":{header:"# Changelog",ignoreRecommendedBump:!0,infile:"CHANGELOG.md",preset:{name:"conventionalcommits",types:[{type:"feat",section:"Features"},{type:"fix",section:"Bug Fixes"},{type:"refactor",section:"Restructured"},{type:"perf",section:"Performance Improved"},{type:"chore",hidden:!0},{type:"docs",hidden:!0},{type:"test",hidden:!0},{type:"style",hidden:!0}]}}}}},createConfig$1=()=>{backupBeforeWrite(PWD("./.release-it.json"),createReleaseItConfig())},insertScripts=()=>{var e=getAnswers()["releaseIt"];e&&(e=e["createConfig"],e=e?" --config .release-it.json":"",addScriptToPackageJson([["release","release-it"+e]]))},install$1=()=>{managerInstall("release-it @release-it/conventional-changelog",!0)},TASK$1=()=>{var e=getAnswers()["releaseIt"];e&&(e.install&&install$1(),e.insertScripts&&insertScripts(),e.createConfig)&&createConfig$1()},KEY$1="releaseIt",RELEASE_IT={KEY:KEY$1,CHOICES:CHOICES$1,QUESTION:QUESTION$1(KEY$1),TASK:TASK$1},TITLE$1="release-it",releaseItQuestions=()=>sectionWithConfirmation(TITLE$1,async()=>inquirer.prompt([RELEASE_IT.QUESTION]),()=>({[KEY$1]:!1})),releaseItTasks=()=>section(TITLE$1,isValidCheckboxAnswer(getAnswers()[KEY$1])&&RELEASE_IT.TASK),CHOICES=[["Install dependencies","install","Install",!0],["Create tsconfig.json","createConfig","Config",!0]],QUESTION=e=>createCheckbox(e,"Please check the item(s) you need",massageChoices(CHOICES).map(createCheckboxChoice)),createTsConfigJson=()=>{var e=getAnswers()["withSyntaxExtension"];return{exclude:[".composer.bak","bower_components","jspm_packages","node_modules","build","bundle","core","coverage","dist","storybook-static","out"],include:["**/*.d.ts","**/*.js",...e?["**/*.jsx"]:[],"**/*.ts",...e?["**/*.tsx"]:[],"@types","types"],compilerOptions:{skipLibCheck:!0,declaration:!0,"// declarationDir":"// TODO: TO BE DECIDED",declarationMap:!0,importHelpers:!0,"// noEmit":"// TODO: TO BE DECIDED","// outDir":"// TODO: TO BE DECIDED",removeComments:!0,sourceMap:!0,allowSyntheticDefaultImports:!0,esModuleInterop:!0,forceConsistentCasingInFileNames:!0,isolatedModules:!0,allowJs:!0,checkJs:!0,experimentalDecorators:!0,...e?{jsx:"react-jsx"}:{},lib:["DOM","DOM.Iterable","ESNext","WebWorker"],target:"esnext",allowArbitraryExtensions:!0,module:"esnext",moduleResolution:"node",resolveJsonModule:!0,"// rootDir":"// TODO: TO BE DECIDED",incremental:!0,allowUnusedLabels:!1,noFallthroughCasesInSwitch:!0,noImplicitOverride:!0,noImplicitReturns:!0,noUncheckedIndexedAccess:!0,noUnusedLocals:!0,noUnusedParameters:!0,strict:!0},watchOptions:{},typeAcquisition:{}}},createConfig=()=>{backupBeforeWrite(PWD("./tsconfig.json"),createTsConfigJson())},install=()=>{managerInstall("typescript",!0)},TASK=()=>{var e=getAnswers()["typescript"];e&&(e.install&&install(),e.createConfig)&&createConfig()},KEY="typescript",TYPESCRIPT={KEY:KEY,CHOICES:CHOICES,QUESTION:QUESTION(KEY),TASK:TASK},TITLE="TypeScript",typeScriptQuestions=()=>sectionWithConfirmation(TITLE,async()=>inquirer.prompt([TYPESCRIPT.QUESTION]),()=>({[KEY]:!1})),typeScriptTasks=()=>section(TITLE,isValidCheckboxAnswer(getAnswers()[KEY])&&TYPESCRIPT.TASK),isAnswered=(APP_HEADER(),()=>{var e=getCli().preset;if(!e)return!1;var t=PWD(e);if(t.endsWith(".json"))return isPathExist(t)?(updateAnswers(readJson(t)),log([!0],"You provided the following preset:"),log([!0],getAnswers()),!0):(warn([!0],"No answers found at "+e),warn([!1],"Fallback to manual input..."),!1);throw error([!0],"The preset file you provided is not a JSON file"),error([!1],"The JSON format should be same as the output of dry run,"),error([!1],"Use the --dry-run / -D to generate a preset json"),new Error("INVALID_PRESET_FILE")}),isDryRun=()=>!!getCli().dryRun&&(log([!0],separator(void 0,"DRY RUN RESULT")),log([!0],getAnswers()),log([!0],"As dry-run is enabled, no changes were made to the project"),!0),isValidEnvironment=()=>{let e=!0;return isPathExist(PWD("./package.json"))||(error([!0],"package.json not found"),error([!1],"Please be sure to run composer under the root directory."),error([!0],"or"),error([!0],"If you are already in the root directory"),error([!1],"Initialize a new project by running:"),box(error,[!1],["$ npm init ","","# or","","$ pnpm init","","# or","","$ yarn init"]),e=!1),e};(async()=>{updateApplication({datetime:DateTime.now().toFormat("yyyy-MM-dd_HH-mm-ss")});try{return isValidEnvironment()?(isAnswered()||(await onBoardingQuestions(),await editorConfigQuestions(),await typeScriptQuestions(),await esLintQuestions(),await prettierQuestions(),await huskyQuestions(),await commitLintQuestions(),await lintStagedQuestions(),await dockerQuestions(),await gitQuestions(),await releaseItQuestions()),!isDryRun()&&(log([!0],separator()),log([!0],"ℹ Before proceed to the next step, please review the answers you have given"),await shouldContinue())?(log([!0],separator(void 0,"TASK(S) STARTED")),await editorConfigTasks(),await typeScriptTasks(),await esLintTasks(),await prettierTasks(),await huskyTasks(),await commitLintTasks(),await lintStagedTasks(),await dockerTasks(),await gitTasks(),await releaseItTasks(),void APP_FOOTER()):APP_FOOTER()):APP_FOOTER()}catch(e){var t=e;t.isTtyError?error([!0],"Prompt couldn't be rendered in the current environment"):error([!0],"Something went wrong: "+t)}})();