@teispace/next-maker 0.4.0 → 1.0.1
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/CHANGELOG.md +18 -0
- package/README.md +185 -12
- package/dist/index.js +59 -52
- package/dist/index.js.map +4 -4
- package/dist/src/commands/index.d.ts.map +1 -1
- package/dist/src/commands/setup.d.ts +3 -0
- package/dist/src/commands/setup.d.ts.map +1 -0
- package/dist/src/core/git.d.ts +1 -1
- package/dist/src/core/git.d.ts.map +1 -1
- package/dist/src/core/package-manager.d.ts +2 -0
- package/dist/src/core/package-manager.d.ts.map +1 -1
- package/dist/src/services/init/config.service.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{Command as Yt}from"commander";import ie from"node:path";import L from"picocolors";import Me from"ora";function D(t="",e){let i=Me({text:t,...e});return i.start(),i}import Ue from"enquirer";var{prompt:He}=Ue,se=async t=>{let e=await He([{type:"input",name:"projectName",message:"What is the project name?",initial:t||"my-app",skip:!!t,validate:i=>/^[a-z0-9-_]+$/.test(i)?!0:"Project name must be lowercase and contain only alphanumeric characters, hyphens, and underscores."},{type:"input",name:"description",message:"Project description:",initial:"A Next.js application"},{type:"input",name:"author",message:"Author:",initial:"Teispace"},{type:"input",name:"version",message:"Version:",initial:"0.1.0",validate:i=>/^\d+\.\d+\.\d+$/.test(i)?!0:"Version must be a valid semantic version (x.y.z)."},{type:"input",name:"email",message:"Support email:",initial:"support@example.com",validate:i=>/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(i)?!0:"Please enter a valid email address."},{type:"select",name:"packageManager",message:"Which package manager would you like to use?",choices:["npm","yarn","pnpm","bun"],initial:1},{type:"input",name:"gitRemote",message:"GitHub repository URL (optional):",validate:i=>{if(!i)return!0;let n=/^https:\/\/github\.com\/[\w-]+\/[\w.-]+$/,s=/^git@github\.com:[\w-]+\/[\w.-]+\.git$/;return!n.test(i)&&!s.test(i)?"Please enter a valid GitHub repository URL (e.g., https://github.com/user/repo)":!0}},{type:"confirm",name:"keepTemplates",message:"Do you want to keep GitHub issue and pull request templates?",initial:!1},{type:"select",name:"httpClient",message:"Which HTTP client do you want to use?",choices:["axios","fetch","both","none"],initial:1},{type:"confirm",name:"reactSecureStorage",message:"Do you want to include react-secure-storage?",initial:!0,skip:function(){let i=this.state?.answers??this.enquirer?.answers??{};return!!(i.httpClient&&i.httpClient!=="none")}},{type:"confirm",name:"darkMode",message:"Do you want to include Dark Mode (Tailwind + next-themes)?",initial:!0},{type:"confirm",name:"redux",message:"Do you want to include Redux Toolkit?",initial:!0},{type:"confirm",name:"i18n",message:"Do you want to include Internationalization (next-intl)?",initial:!0},{type:"multiselect",name:"communityFiles",message:"Select community files to include:",choices:[{name:"CODE_OF_CONDUCT.md",value:"CODE_OF_CONDUCT.md"},{name:"CONTRIBUTING.md",value:"CONTRIBUTING.md"},{name:"SECURITY.md",value:"SECURITY.md"}],initial:[]},{type:"confirm",name:"readme",message:"Do you want to create a README.md?",initial:!0},{type:"confirm",name:"docker",message:"Do you want to include Docker configuration?",initial:!1},{type:"input",name:"containerName",message:"Docker Container Name:",initial:"next-app",skip:function(){return!(this.state?.answers??this.enquirer?.answers??{}).docker},validate:i=>/^[a-zA-Z0-9][a-zA-Z0-9_.-]*$/.test(i)?!0:"Invalid Docker container name."},{type:"input",name:"imageName",message:"Docker Image Name:",initial:"nextjs-starter",skip:function(){return!(this.state?.answers??this.enquirer?.answers??{}).docker},validate:i=>/^[a-z0-9]+(?:[._-][a-z0-9]+)*$/.test(i)?!0:"Invalid Docker image name (must be lowercase)."},{type:"input",name:"imageTag",message:"Docker Image Tag:",initial:"latest",skip:function(){return!(this.state?.answers??this.enquirer?.answers??{}).docker},validate:i=>/^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,127}$/.test(i)?!0:"Invalid Docker image tag."},{type:"confirm",name:"ci",message:"Do you want to include GitHub Actions (CI/CD)?",initial:!1},{type:"confirm",name:"preCommitHooks",message:"Do you want to setup pre-commit hooks (Husky, Commitlint, Lint-staged)?",initial:!0},{type:"confirm",name:"commitizen",message:"Do you want to setup Commitizen?",initial:!0},{type:"confirm",name:"copyEnv",message:"Want to copy .env.example to .env?",initial:!0}]);if(e.company=e.author,e.gitRemote&&!e.gitHomepage){let i=e.gitRemote.replace("git@github.com:","https://github.com/").replace(/\.git$/,"");e.gitHomepage=`${i}#readme`,e.gitIssues=`${i}/issues`}return e};import X from"node:fs/promises";import Xe from"node:path";import{existsSync as Q}from"node:fs";var g=async t=>X.readFile(t,"utf-8"),u=async(t,e)=>{await X.mkdir(Xe.dirname(t),{recursive:!0}),await X.writeFile(t,e,"utf-8")},h=async t=>{Q(t)&&await X.unlink(t)},y=async t=>{Q(t)&&await X.rm(t,{recursive:!0,force:!0})},z=async(t,e)=>{let i=await g(t),n=JSON.parse(i),s=e(n);await u(t,JSON.stringify(s,null,2))},x=t=>Q(t);import{exec as ze}from"node:child_process";import{promisify as Ye}from"node:util";var B=Ye(ze),ae=async t=>{try{await B("git init",{cwd:t}),await B("git add .",{cwd:t}),await B('git commit -m "Initial commit from @teispace/next-maker"',{cwd:t})}catch(e){console.warn("Failed to initialize git repository",e)}},ce=async(t,e)=>{try{await B(`git remote add origin ${e}`,{cwd:t})}catch(i){console.warn("Failed to add remote origin",i)}};import{exec as We}from"node:child_process";import{promisify as Ke}from"node:util";var pe=Ke(We),le=async(t,e)=>{let i=`${e} install`;try{await pe(i,{cwd:t})}catch(n){throw new Error(`Failed to install dependencies with ${e}: ${n}`)}},ee=async(t,e,i)=>{let n=e==="npm"?`${e} run ${i}`:`${e} ${i}`;try{await pe(n,{cwd:t})}catch(s){console.warn(`Warning: Failed to run script '${i}': ${s}`)}};import A from"picocolors";var Ve={reset:t=>t,red:A.red,green:A.green,yellow:A.yellow,blue:A.blue,cyan:A.cyan,magenta:A.magenta,white:A.white,gray:A.gray,bright:A.bold,dim:A.dim};function M(t,e="reset"){let i=Ve[e]??(n=>n);console.log(i(t))}function J(t){M(`\u2716 ${t}`,"red")}var E=J;function p(t){M(t)}function me(){console.log(""),M("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557","cyan"),M("\u2551 \u2551","cyan"),M("\u2551 \u{1F680} Create Teispace Next.js App \u{1F680} \u2551","cyan"),M("\u2551 \u2551","cyan"),M("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D","cyan"),console.log("")}function de(t){let{logger:e=o=>console.error(o),exitOnCancel:i=process.env.NODE_ENV!=="test"}=t??{},n=()=>{console.log(""),console.log(""),e("Setup cancelled by user"),console.log(""),i&&process.exit(0)},s=o=>{if(o!==null&&typeof o=="object"&&"code"in o&&o.code==="ERR_USE_AFTER_CLOSE"){n();return}if(o instanceof Error){e(`Uncaught exception: ${o.message}`);return}e(`Uncaught exception: ${String(o)}`)},r=o=>{if(o instanceof Error){e(`Unhandled promise rejection: ${o.message}`);return}e(`Unhandled promise rejection: ${String(o)}`)};return process.on("SIGINT",n),process.on("SIGTERM",n),process.on("uncaughtException",s),process.on("unhandledRejection",r),()=>{process.off("SIGINT",n),process.off("SIGTERM",n),process.off("uncaughtException",s),process.off("unhandledRejection",r)}}var Be=t=>t.charAt(0).toUpperCase()+t.slice(1),O=t=>t.replace(/-([a-z])/g,(e,i)=>i.toUpperCase()),G=t=>Be(O(t));import Je from"ora";var f=Je();import qe from"degit";var ue=async t=>{let e=D("Downloading template...");try{await qe("teispace/nextjs-starter",{cache:!1,force:!0,verbose:!0}).clone(t),e.succeed("Template downloaded successfully.")}catch(i){throw e.fail("Failed to download template."),i}};import Ze from"node:path";var a={NEXT_CONFIG:"next.config.ts",TAILWIND_CONFIG:"tailwind.config.ts",POSTCSS_CONFIG:"postcss.config.mjs",ESLINT_CONFIG:"eslint.config.mjs",TS_CONFIG:"tsconfig.json",PACKAGE_JSON:"package.json",ENV_EXAMPLE:".env.example",GITIGNORE:".gitignore",README:"README.md",LICENSE:"LICENSE",CHANGELOG:"CHANGELOG.md",NVM_RC:".nvmrc",NPM_RC:".npmrc",SRC:"src",APP:"src/app",COMPONENTS:"src/components",LIB:"src/lib",PROVIDERS:"src/providers",STYLES:"src/styles",TYPES:"src/types",UTILS:"src/lib/utils",HOOKS:"src/hooks",SERVICES:"src/services",STORE:"src/store",I18N:"src/i18n",GLOBALS_CSS:"src/styles/globals.css",ROOT_LAYOUT:"src/app/layout.tsx",ROOT_PAGE:"src/app/page.tsx",ROOT_PROVIDER:"src/providers/RootProvider.tsx",PROVIDERS_INDEX:"src/providers/index.ts",COMPONENTS_INDEX:"src/components/index.ts",TYPES_INDEX:"src/types/index.ts",UTILS_INDEX:"src/lib/utils/index.ts",CONFIG_INDEX:"src/lib/config/index.ts",CONSTANTS:"src/lib/config/constants.ts",APP_LOCALES:"src/lib/config/app-locales.ts",MIDDLEWARE:"src/middleware.ts",PROXY:"src/proxy.ts",I18N_TYPES:"src/types/i18n.ts",HTTP_UTILS:"src/lib/utils/http",AXIOS_CLIENT:"src/lib/utils/http/axios-client",FETCH_CLIENT:"src/lib/utils/http/fetch-client",CLIENT_UTILS:"src/lib/utils/http/client-utils.ts",APP_APIS:"src/lib/config/app-apis.ts",STORAGE_SERVICE:"src/services/storage",COUNTER_FEATURE:"src/features/counter",I18N_DIR:"src/i18n",LOCALE_DIR:"src/app/[locale]",ERRORS_DIR:"src/lib/errors",UTILITY_TYPES_DIR:"src/types/utility",COMMON_TYPES_DIR:"src/types/common",HTTP_TYPES:"src/types/common/http.types.ts",GITHUB_DIR:".github",HUSKY_DIR:".husky",STORE_PROVIDER:"src/providers/StoreProvider.tsx",THEME_PROVIDER:"src/providers/CustomThemeProvider.tsx",COUNTER_COMPONENT:"src/features/counter/components/Counter.tsx",LOCALE_PAGE:"src/app/[locale]/page.tsx",COMMITLINT_CONFIG:"commitlint.config.mjs",LINTSTAGED_RC:".lintstagedrc.mjs",CZRC:".czrc",DOCKERIGNORE:".dockerignore",DOCKERFILE:"Dockerfile",DOCKER_COMPOSE:"docker-compose.yml",GITHUB_WORKFLOWS:".github/workflows",GITHUB_ISSUE_TEMPLATE:"ISSUE_TEMPLATE",GITHUB_PR_TEMPLATE:"PULL_REQUEST_TEMPLATE.md",CODE_OF_CONDUCT:"CODE_OF_CONDUCT.md",CONTRIBUTING:"CONTRIBUTING.md",SECURITY:"SECURITY.md"};var w={REDUX_TOOLKIT:"@reduxjs/toolkit",REACT_REDUX:"react-redux",REDUX_PERSIST:"redux-persist",REACT_SECURE_STORAGE:"react-secure-storage",NEXT_INTL:"next-intl",NEXT_THEMES:"next-themes",AXIOS:"axios",HUSKY:"husky",COMMITLINT_CLI:"@commitlint/cli",COMMITLINT_CONFIG:"@commitlint/config-conventional",LINT_STAGED:"lint-staged",COMMITIZEN:"commitizen",CZ_CONVENTIONAL_CHANGELOG:"cz-conventional-changelog"};var fe=async(t,e)=>{let i=D("Configuring package.json...");try{let n=e.gitRemote,s=e.gitHomepage,r=e.gitIssues;e.gitRemote&&(e.gitRemote.startsWith("git@github.com:")&&(n=e.gitRemote.replace("git@github.com:","https://github.com/").replace(/\.git$/,"")),s||(s=`${n.replace(/\.git$/,"")}#readme`),r||(r=`${n.replace(/\.git$/,"")}/issues`),n.endsWith(".git")||(n=`${n}.git`)),await z(Ze.join(t,a.PACKAGE_JSON),o=>(o.name=e.projectName,o.version=e.version,o.description=e.description,o.author=e.author,delete o.packageManager,s&&(o.homepage=s),r&&(o.bugs={url:r}),n&&(o.repository={type:"git",url:n}),e.redux||(delete o.dependencies[w.REDUX_TOOLKIT],delete o.dependencies[w.REACT_REDUX],delete o.dependencies[w.REDUX_PERSIST]),e.httpClient!=="none"||e.reactSecureStorage||delete o.dependencies[w.REACT_SECURE_STORAGE],e.i18n||delete o.dependencies[w.NEXT_INTL],e.darkMode||delete o.dependencies[w.NEXT_THEMES],e.httpClient==="none"?delete o.dependencies[w.AXIOS]:e.httpClient==="fetch"&&delete o.dependencies[w.AXIOS],o)),i.succeed("package.json configured.")}catch(n){throw i.fail("Failed to configure package.json."),n}};import l from"node:path";var ge=async(t,e)=>{let i=D("Customizing features...");try{await Qe(t,e),await et(t,e),await tt(t,e),await it(t,e),await rt(t,e),await ot(t),await nt(t),await st(t),i.succeed("Features customized.")}catch(n){throw i.fail("Failed to customize features."),n}},Qe=async(t,e)=>{let i=l.join(t,a.HTTP_UTILS),n=e.httpClient!=="none"||e.reactSecureStorage;if(e.httpClient==="none"){if(await y(l.join(t,a.AXIOS_CLIENT)),await y(l.join(t,a.FETCH_CLIENT)),n)await u(l.join(i,"index.ts"),`export * from './token-store';
|
|
3
|
-
`),await h(l.join(t,a.CLIENT_UTILS));else{await y(i);let r=l.join(t,a.UTILS_INDEX);if(x(r)){let
|
|
2
|
+
import{Command as Vt}from"commander";import re from"node:path";import L from"picocolors";import Ue from"ora";function k(t="",e){let i=Ue({text:t,...e});return i.start(),i}import He from"enquirer";var{prompt:ze}=He,ae=async t=>{let e=await ze([{type:"input",name:"projectName",message:"What is the project name?",initial:t||"my-app",skip:!!t,validate:i=>/^[a-z0-9-_]+$/.test(i)?!0:"Project name must be lowercase and contain only alphanumeric characters, hyphens, and underscores."},{type:"input",name:"description",message:"Project description:",initial:"A Next.js application"},{type:"input",name:"author",message:"Author:",initial:"Teispace"},{type:"input",name:"version",message:"Version:",initial:"0.1.0",validate:i=>/^\d+\.\d+\.\d+$/.test(i)?!0:"Version must be a valid semantic version (x.y.z)."},{type:"input",name:"email",message:"Support email:",initial:"support@example.com",validate:i=>/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(i)?!0:"Please enter a valid email address."},{type:"select",name:"packageManager",message:"Which package manager would you like to use?",choices:["npm","yarn","pnpm","bun"],initial:1},{type:"input",name:"gitRemote",message:"GitHub repository URL (optional):",validate:i=>{if(!i)return!0;let n=/^https:\/\/github\.com\/[\w-]+\/[\w.-]+$/,s=/^git@github\.com:[\w-]+\/[\w.-]+\.git$/;return!n.test(i)&&!s.test(i)?"Please enter a valid GitHub repository URL (e.g., https://github.com/user/repo)":!0}},{type:"confirm",name:"keepTemplates",message:"Do you want to keep GitHub issue and pull request templates?",initial:!1},{type:"select",name:"httpClient",message:"Which HTTP client do you want to use?",choices:["axios","fetch","both","none"],initial:1},{type:"confirm",name:"reactSecureStorage",message:"Do you want to include react-secure-storage?",initial:!0,skip:function(){let i=this.state?.answers??this.enquirer?.answers??{};return!!(i.httpClient&&i.httpClient!=="none")}},{type:"confirm",name:"darkMode",message:"Do you want to include Dark Mode (Tailwind + next-themes)?",initial:!0},{type:"confirm",name:"redux",message:"Do you want to include Redux Toolkit?",initial:!0},{type:"confirm",name:"i18n",message:"Do you want to include Internationalization (next-intl)?",initial:!0},{type:"multiselect",name:"communityFiles",message:"Select community files to include:",choices:[{name:"CODE_OF_CONDUCT.md",value:"CODE_OF_CONDUCT.md"},{name:"CONTRIBUTING.md",value:"CONTRIBUTING.md"},{name:"SECURITY.md",value:"SECURITY.md"}],initial:[]},{type:"confirm",name:"readme",message:"Do you want to create a README.md?",initial:!0},{type:"confirm",name:"docker",message:"Do you want to include Docker configuration?",initial:!1},{type:"input",name:"containerName",message:"Docker Container Name:",initial:"next-app",skip:function(){return!(this.state?.answers??this.enquirer?.answers??{}).docker},validate:i=>/^[a-zA-Z0-9][a-zA-Z0-9_.-]*$/.test(i)?!0:"Invalid Docker container name."},{type:"input",name:"imageName",message:"Docker Image Name:",initial:"nextjs-starter",skip:function(){return!(this.state?.answers??this.enquirer?.answers??{}).docker},validate:i=>/^[a-z0-9]+(?:[._-][a-z0-9]+)*$/.test(i)?!0:"Invalid Docker image name (must be lowercase)."},{type:"input",name:"imageTag",message:"Docker Image Tag:",initial:"latest",skip:function(){return!(this.state?.answers??this.enquirer?.answers??{}).docker},validate:i=>/^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,127}$/.test(i)?!0:"Invalid Docker image tag."},{type:"confirm",name:"ci",message:"Do you want to include GitHub Actions (CI/CD)?",initial:!1},{type:"confirm",name:"preCommitHooks",message:"Do you want to setup pre-commit hooks (Husky, Commitlint, Lint-staged)?",initial:!0},{type:"confirm",name:"commitizen",message:"Do you want to setup Commitizen?",initial:!0},{type:"confirm",name:"copyEnv",message:"Want to copy .env.example to .env?",initial:!0}]);if(e.company=e.author,e.gitRemote&&!e.gitHomepage){let i=e.gitRemote.replace("git@github.com:","https://github.com/").replace(/\.git$/,"");e.gitHomepage=`${i}#readme`,e.gitIssues=`${i}/issues`}return e};import X from"node:fs/promises";import Xe from"node:path";import{existsSync as ee}from"node:fs";var g=async t=>X.readFile(t,"utf-8"),u=async(t,e)=>{await X.mkdir(Xe.dirname(t),{recursive:!0}),await X.writeFile(t,e,"utf-8")},h=async t=>{ee(t)&&await X.unlink(t)},y=async t=>{ee(t)&&await X.rm(t,{recursive:!0,force:!0})},Y=async(t,e)=>{let i=await g(t),n=JSON.parse(i),s=e(n);await u(t,JSON.stringify(s,null,2))},x=t=>ee(t);import{exec as Ye}from"node:child_process";import{promisify as We}from"node:util";var J=We(Ye),ce=async(t,e)=>{try{await J("git init",{cwd:t}),await J("git add .",{cwd:t}),await J('git commit -m "Initial commit from @teispace/next-maker"',{cwd:t}),e&&await J(`git remote add origin ${e}`,{cwd:t})}catch(i){console.warn("Failed to initialize git repository",i)}};import{exec as Ke}from"node:child_process";import{promisify as Ve}from"node:util";var pe=Ve(Ke),le=async(t,e)=>{let i=`${e} install`;try{await pe(i,{cwd:t})}catch(n){throw new Error(`Failed to install dependencies with ${e}: ${n}`)}},te=async(t,e,i)=>{let n=e==="npm"?`${e} run ${i}`:`${e} ${i}`;try{await pe(n,{cwd:t})}catch(s){console.warn(`Warning: Failed to run script '${i}': ${s}`)}};import A from"picocolors";var Be={reset:t=>t,red:A.red,green:A.green,yellow:A.yellow,blue:A.blue,cyan:A.cyan,magenta:A.magenta,white:A.white,gray:A.gray,bright:A.bold,dim:A.dim};function U(t,e="reset"){let i=Be[e]??(n=>n);console.log(i(t))}function q(t){U(`\u2716 ${t}`,"red")}var C=q;function c(t){U(t)}function me(){console.log(""),U("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557","cyan"),U("\u2551 \u2551","cyan"),U("\u2551 \u{1F680} Create Teispace Next.js App \u{1F680} \u2551","cyan"),U("\u2551 \u2551","cyan"),U("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D","cyan"),console.log("")}function de(t){let{logger:e=o=>console.error(o),exitOnCancel:i=process.env.NODE_ENV!=="test"}=t??{},n=()=>{console.log(""),console.log(""),e("Setup cancelled by user"),console.log(""),i&&process.exit(0)},s=o=>{if(o!==null&&typeof o=="object"&&"code"in o&&o.code==="ERR_USE_AFTER_CLOSE"){n();return}if(o instanceof Error){e(`Uncaught exception: ${o.message}`);return}e(`Uncaught exception: ${String(o)}`)},r=o=>{if(o instanceof Error){e(`Unhandled promise rejection: ${o.message}`);return}e(`Unhandled promise rejection: ${String(o)}`)};return process.on("SIGINT",n),process.on("SIGTERM",n),process.on("uncaughtException",s),process.on("unhandledRejection",r),()=>{process.off("SIGINT",n),process.off("SIGTERM",n),process.off("uncaughtException",s),process.off("unhandledRejection",r)}}var Je=t=>t.charAt(0).toUpperCase()+t.slice(1),b=t=>t.replace(/-([a-z])/g,(e,i)=>i.toUpperCase()),G=t=>Je(b(t));import qe from"ora";var f=qe();import Ze from"degit";var ue=async t=>{let e=k("Downloading template...");try{await Ze("teispace/nextjs-starter",{cache:!1,force:!0,verbose:!0}).clone(t),e.succeed("Template downloaded successfully.")}catch(i){throw e.fail("Failed to download template."),i}};import Qe from"node:path";var a={NEXT_CONFIG:"next.config.ts",TAILWIND_CONFIG:"tailwind.config.ts",POSTCSS_CONFIG:"postcss.config.mjs",ESLINT_CONFIG:"eslint.config.mjs",TS_CONFIG:"tsconfig.json",PACKAGE_JSON:"package.json",ENV_EXAMPLE:".env.example",GITIGNORE:".gitignore",README:"README.md",LICENSE:"LICENSE",CHANGELOG:"CHANGELOG.md",NVM_RC:".nvmrc",NPM_RC:".npmrc",SRC:"src",APP:"src/app",COMPONENTS:"src/components",LIB:"src/lib",PROVIDERS:"src/providers",STYLES:"src/styles",TYPES:"src/types",UTILS:"src/lib/utils",HOOKS:"src/hooks",SERVICES:"src/services",STORE:"src/store",I18N:"src/i18n",GLOBALS_CSS:"src/styles/globals.css",ROOT_LAYOUT:"src/app/layout.tsx",ROOT_PAGE:"src/app/page.tsx",ROOT_PROVIDER:"src/providers/RootProvider.tsx",PROVIDERS_INDEX:"src/providers/index.ts",COMPONENTS_INDEX:"src/components/index.ts",TYPES_INDEX:"src/types/index.ts",UTILS_INDEX:"src/lib/utils/index.ts",CONFIG_INDEX:"src/lib/config/index.ts",CONSTANTS:"src/lib/config/constants.ts",APP_LOCALES:"src/lib/config/app-locales.ts",MIDDLEWARE:"src/middleware.ts",PROXY:"src/proxy.ts",I18N_TYPES:"src/types/i18n.ts",HTTP_UTILS:"src/lib/utils/http",AXIOS_CLIENT:"src/lib/utils/http/axios-client",FETCH_CLIENT:"src/lib/utils/http/fetch-client",CLIENT_UTILS:"src/lib/utils/http/client-utils.ts",APP_APIS:"src/lib/config/app-apis.ts",STORAGE_SERVICE:"src/services/storage",COUNTER_FEATURE:"src/features/counter",I18N_DIR:"src/i18n",LOCALE_DIR:"src/app/[locale]",ERRORS_DIR:"src/lib/errors",UTILITY_TYPES_DIR:"src/types/utility",COMMON_TYPES_DIR:"src/types/common",HTTP_TYPES:"src/types/common/http.types.ts",GITHUB_DIR:".github",HUSKY_DIR:".husky",STORE_PROVIDER:"src/providers/StoreProvider.tsx",THEME_PROVIDER:"src/providers/CustomThemeProvider.tsx",COUNTER_COMPONENT:"src/features/counter/components/Counter.tsx",LOCALE_PAGE:"src/app/[locale]/page.tsx",COMMITLINT_CONFIG:"commitlint.config.mjs",LINTSTAGED_RC:".lintstagedrc.mjs",CZRC:".czrc",DOCKERIGNORE:".dockerignore",DOCKERFILE:"Dockerfile",DOCKER_COMPOSE:"docker-compose.yml",GITHUB_WORKFLOWS:".github/workflows",GITHUB_ISSUE_TEMPLATE:"ISSUE_TEMPLATE",GITHUB_PR_TEMPLATE:"PULL_REQUEST_TEMPLATE.md",CODE_OF_CONDUCT:"CODE_OF_CONDUCT.md",CONTRIBUTING:"CONTRIBUTING.md",SECURITY:"SECURITY.md"};var w={REDUX_TOOLKIT:"@reduxjs/toolkit",REACT_REDUX:"react-redux",REDUX_PERSIST:"redux-persist",REACT_SECURE_STORAGE:"react-secure-storage",NEXT_INTL:"next-intl",NEXT_THEMES:"next-themes",AXIOS:"axios",HUSKY:"husky",COMMITLINT_CLI:"@commitlint/cli",COMMITLINT_CONFIG:"@commitlint/config-conventional",LINT_STAGED:"lint-staged",COMMITIZEN:"commitizen",CZ_CONVENTIONAL_CHANGELOG:"cz-conventional-changelog"};var fe=async(t,e)=>{let i=k("Configuring package.json...");try{let n=e.gitRemote,s=e.gitHomepage,r=e.gitIssues;e.gitRemote&&(e.gitRemote.startsWith("git@github.com:")&&(n=e.gitRemote.replace("git@github.com:","https://github.com/").replace(/\.git$/,"")),s||(s=`${n.replace(/\.git$/,"")}#readme`),r||(r=`${n.replace(/\.git$/,"")}/issues`),n.endsWith(".git")||(n=`${n}.git`)),await Y(Qe.join(t,a.PACKAGE_JSON),o=>(o.name=e.projectName,o.version=e.version,o.description=e.description,o.author=e.author,delete o.packageManager,e.gitRemote?(s&&(o.homepage=s),r&&(o.bugs={url:r}),n&&(o.repository={type:"git",url:n})):(delete o.homepage,delete o.bugs,delete o.repository),e.redux||(delete o.dependencies[w.REDUX_TOOLKIT],delete o.dependencies[w.REACT_REDUX],delete o.dependencies[w.REDUX_PERSIST]),e.httpClient!=="none"||e.reactSecureStorage||delete o.dependencies[w.REACT_SECURE_STORAGE],e.i18n||delete o.dependencies[w.NEXT_INTL],e.darkMode||delete o.dependencies[w.NEXT_THEMES],e.httpClient==="none"?delete o.dependencies[w.AXIOS]:e.httpClient==="fetch"&&delete o.dependencies[w.AXIOS],o)),i.succeed("package.json configured.")}catch(n){throw i.fail("Failed to configure package.json."),n}};import l from"node:path";var ge=async(t,e)=>{let i=k("Customizing features...");try{await et(t,e),await tt(t,e),await it(t,e),await rt(t,e),await ot(t,e),await nt(t),await st(t),await at(t),i.succeed("Features customized.")}catch(n){throw i.fail("Failed to customize features."),n}},et=async(t,e)=>{let i=l.join(t,a.HTTP_UTILS),n=e.httpClient!=="none"||e.reactSecureStorage;if(e.httpClient==="none"){if(await y(l.join(t,a.AXIOS_CLIENT)),await y(l.join(t,a.FETCH_CLIENT)),n)await u(l.join(i,"index.ts"),`export * from './token-store';
|
|
3
|
+
`),await h(l.join(t,a.CLIENT_UTILS));else{await y(i);let r=l.join(t,a.UTILS_INDEX);if(x(r)){let p=await g(r);p=p.replace(/export \* from '\.\/http';\n/,""),await u(r,p)}await h(l.join(t,a.APP_APIS));let o=l.join(t,a.CONFIG_INDEX);if(x(o)){let p=await g(o);p=p.replace(/export \* from '\.\/app-apis';\n/,""),await u(o,p)}}let s=l.join(t,a.CONSTANTS);if(x(s)){let r=await g(s);r=r.replace(/export const API_RESPONSE_DATA_KEY = 'data';\n/,""),r=r.replace(/export const SAVE_AUTH_TOKENS = false;\n/,""),await u(s,r)}if(await y(l.join(t,a.ERRORS_DIR)),!n){await y(l.join(t,a.COMMON_TYPES_DIR)),await y(l.join(t,a.UTILITY_TYPES_DIR));let r=l.join(t,a.TYPES_INDEX);if(x(r)){let o=await g(r);o=o.replace(/export \* from '\.\/utility';\n/,""),o=o.replace(/export \* from '\.\/common';\n/,""),await u(r,o)}}}else if(e.httpClient==="axios"){await y(l.join(t,a.FETCH_CLIENT));let s=await g(l.join(i,"index.ts"));s=s.replace(/export .* from '\.\/fetch-client';\n/g,""),await u(l.join(i,"index.ts"),s);let r=l.join(t,a.HTTP_TYPES);if(x(r)){let o=await g(r);o=o.replace(/export interface FetchClientOptions \{[\s\S]*?\}\n\n/,""),o=o.replace(/export interface ExtendedRequestInit extends RequestInit \{[\s\S]*?\}\n\n/,""),await u(r,o)}}else if(e.httpClient==="fetch"){await y(l.join(t,a.AXIOS_CLIENT));let s=await g(l.join(i,"index.ts"));s=s.replace(/export .* from '\.\/axios-client';\n/g,""),await u(l.join(i,"index.ts"),s);let r=l.join(t,a.HTTP_TYPES);if(x(r)){let o=await g(r);o=o.replace(/declare module 'axios' \{[\s\S]*?\}\n\n/,""),o=o.replace(/export interface AxiosClientOptions \{[\s\S]*?\}\n\n/,""),await u(r,o)}}},tt=async(t,e)=>{e.httpClient!=="none"||e.reactSecureStorage||await y(l.join(t,a.STORAGE_SERVICE))},it=async(t,e)=>{if(!e.redux){await y(l.join(t,a.STORE)),await y(l.join(t,a.COUNTER_FEATURE)),await h(l.join(t,a.STORE_PROVIDER));let i=l.join(t,a.PROVIDERS_INDEX),n=await g(i);n=n.replace(/export \* from '\.\/StoreProvider';\n/,""),await u(i,n);let s=[l.join(t,a.ROOT_PAGE),l.join(t,a.LOCALE_PAGE)];for(let r of s)if(x(r)){let o=await g(r);o=o.replace(/import\s+\{\s*Counter\s*\}\s+from\s+['"]@\/features\/counter['"];\n?/,""),o=o.replace(/<Counter\s*\/>\n?/g,""),await u(r,o)}}},rt=async(t,e)=>{if(!e.darkMode){await h(l.join(t,a.THEME_PROVIDER));let i=l.join(t,a.PROVIDERS_INDEX),n=await g(i);n=n.replace(/export \* from '\.\/CustomThemeProvider';\n/,""),await u(i,n);let s=l.join(t,a.GLOBALS_CSS);if(x(s)){let r=await g(s);r=r.replace(/@custom-variant dark \(.*?\);\n\n/,""),r=r.replace(/@theme \{[\s\S]*?\}\n/,""),await u(s,r)}if(!e.i18n){let r=l.join(t,a.ROOT_LAYOUT);if(x(r)){let o=await g(r);o=o.replace(/bg-light dark:bg-dark /g,""),await u(r,o)}}}},ot=async(t,e)=>{if(!e.i18n){await y(l.join(t,a.I18N_DIR)),await y(l.join(t,a.LOCALE_DIR)),await h(l.join(t,a.PROXY)),await h(l.join(t,a.MIDDLEWARE)),await h(l.join(t,a.I18N_TYPES)),await h(l.join(t,a.APP_LOCALES));let i=l.join(t,a.TYPES_INDEX);if(x(i)){let o=await g(i);o=o.replace(/export \* from '\.\/i18n';\n/,""),await u(i,o)}let n=l.join(t,a.CONFIG_INDEX);if(x(n)){let o=await g(n);o=o.replace(/export \* from '\.\/app-locales';\n/,""),await u(n,o)}let s=l.join(t,a.NEXT_CONFIG);if(x(s)){let o=await g(s);o=o.replace(/import createNextIntlPlugin from 'next-intl\/plugin';\n/,""),o=o.replace(/const withNextIntl = createNextIntlPlugin\(\);\n/,""),o=o.replace(/export default withNextIntl\(nextConfig\);/,"export default nextConfig;"),await u(s,o)}let r=l.join(t,a.COUNTER_COMPONENT);if(x(r)){let o=await g(r);o=o.replace(/import\s+\{\s*useTranslations\s*\}\s+from\s+['"]next-intl['"];\n/,""),o=o.replace(/\s*const\s+t\s*=\s*useTranslations\(['"]Count['"]\);\n/,""),o=o.replace(/\{t\('currentCount',\s*\{\s*count:\s*value\s*\}\)\}/g,"{value}"),o=o.replace(/\{t\(['"]increment['"]\)\}/g,"Increment"),o=o.replace(/\{t\(['"]decrement['"]\)\}/g,"Decrement"),o=o.replace(/\{t\(['"]reset['"]\)\}/g,"Reset"),await u(r,o)}}},nt=async t=>{await h(l.join(t,a.LICENSE))},st=async t=>{await h(l.join(t,a.CHANGELOG))},at=async t=>{await h(l.join(t,a.NVM_RC)),await h(l.join(t,a.NPM_RC))};import ie from"node:path";var he=async(t,e)=>{let i=[],n=[];e.redux&&(i.push("import { StoreProvider } from '@/providers';"),n.push("StoreProvider")),e.darkMode&&(i.push("import { CustomThemeProvider } from '@/providers';"),n.push("CustomThemeProvider")),e.i18n&&(i.push("import { NextIntlClientProvider, AbstractIntlMessages } from 'next-intl';"),i.push("import { SupportedLocale } from '@/types/i18n';"));let s=`'use client';
|
|
4
4
|
${i.join(`
|
|
5
5
|
`)}
|
|
6
6
|
|
|
@@ -23,7 +23,7 @@ export const RootProvider = ({
|
|
|
23
23
|
</StoreProvider>`),r==="{children}"&&(r="<>{children}</>"),s+=` ${r}
|
|
24
24
|
);
|
|
25
25
|
};
|
|
26
|
-
`,await u(
|
|
26
|
+
`,await u(ie.join(t,a.ROOT_PROVIDER),s)},xe=async(t,e)=>{if(!e.i18n){let i=`import type { Metadata } from 'next';
|
|
27
27
|
import '@/styles/globals.css';
|
|
28
28
|
import { Livvic } from 'next/font/google';
|
|
29
29
|
import { RootProvider } from '@/providers';
|
|
@@ -55,7 +55,7 @@ export default function RootLayout({
|
|
|
55
55
|
</html>
|
|
56
56
|
);
|
|
57
57
|
}
|
|
58
|
-
`;await u(
|
|
58
|
+
`;await u(ie.join(t,a.ROOT_LAYOUT),i);let n=e.redux?`import { Counter } from '@/features/counter';
|
|
59
59
|
|
|
60
60
|
`:"",s=e.redux?`
|
|
61
61
|
<Counter />`:"",r=`${n}export default function Home() {
|
|
@@ -66,8 +66,8 @@ export default function RootLayout({
|
|
|
66
66
|
</div>
|
|
67
67
|
);
|
|
68
68
|
}
|
|
69
|
-
`;await u(
|
|
70
|
-
`};s("CONTAINER_NAME",e.containerName||"next-app"),s("IMAGE_NAME",e.imageName||"nextjs-starter"),s("IMAGE_TAG",e.imageTag||"latest"),await u(i,n)}}else{await h(S.join(t,a.DOCKERFILE)),await h(S.join(t,a.DOCKER_COMPOSE)),await h(S.join(t,a.DOCKERIGNORE));let i=S.join(t,a.ENV_EXAMPLE);if(x(i)){let n=await g(i);n=n.replace(/# Docker Compose Configuration\n/,""),n=n.replace(/CONTAINER_NAME=.*\n/,""),n=n.replace(/IMAGE_NAME=.*\n/,""),n=n.replace(/IMAGE_TAG=.*\n/,""),await u(i,n)}}},
|
|
69
|
+
`;await u(ie.join(t,a.ROOT_PAGE),r)}};import S from"node:path";import{readdir as Se}from"node:fs/promises";var ye=async(t,e)=>{await ct(t,e),await pt(t,e),await lt(t,e),await mt(t,e),await dt(t,e),await ut(t,e),await ft(t,e)},ct=async(t,e)=>{e.preCommitHooks||(await y(S.join(t,a.HUSKY_DIR)),await h(S.join(t,a.COMMITLINT_CONFIG)),await h(S.join(t,a.LINTSTAGED_RC)),await Y(S.join(t,a.PACKAGE_JSON),i=>(delete i.devDependencies[w.HUSKY],delete i.devDependencies[w.COMMITLINT_CLI],delete i.devDependencies[w.COMMITLINT_CONFIG],delete i.devDependencies[w.LINT_STAGED],delete i.scripts.prepare,delete i.scripts.postinstall,delete i.commitlint,delete i["lint-staged"],i)))},pt=async(t,e)=>{e.commitizen||(await h(S.join(t,a.CZRC)),await Y(S.join(t,a.PACKAGE_JSON),i=>(delete i.devDependencies[w.COMMITIZEN],delete i.devDependencies[w.CZ_CONVENTIONAL_CHANGELOG],delete i.config?.commitizen,i.config&&Object.keys(i.config).length===0&&delete i.config,delete i.scripts.commit,i)))},lt=async(t,e)=>{e.ci||await y(S.join(t,a.GITHUB_WORKFLOWS))},mt=async(t,e)=>{let i=S.join(t,a.GITHUB_DIR);if(!e.keepTemplates)await y(S.join(i,a.GITHUB_ISSUE_TEMPLATE)),await h(S.join(i,a.GITHUB_PR_TEMPLATE));else{let n=S.join(i,a.GITHUB_ISSUE_TEMPLATE),s=S.join(i,a.GITHUB_PR_TEMPLATE),r=o=>o.replace(/Teispace/g,e.company).replace(/support@teispace\.com/g,e.email).replace(/Next\.js Starter/g,e.projectName).replace(/\[AUTHOR\]/g,e.author).replace(/\[COMPANY\]/g,e.company).replace(/\[EMAIL\]/g,e.email);if(x(s)){let o=await g(s);o=r(o),await u(s,o)}try{if(x(n)){let o=await Se(n);for(let p of o){let m=S.join(n,p),d=await g(m);d=r(d),await u(m,d)}}}catch{}}},dt=async(t,e)=>{let i=[a.CODE_OF_CONDUCT,a.CONTRIBUTING,a.SECURITY];for(let n of i)e.communityFiles.includes(n)||await h(S.join(t,n))},ut=async(t,e)=>{if(e.docker){let i=S.join(t,a.ENV_EXAMPLE);if(x(i)){let n=await g(i),s=(r,o)=>{let p=new RegExp(`${r}=.*`);p.test(n)?n=n.replace(p,`${r}=${o}`):n+=`${r}=${o}
|
|
70
|
+
`};s("CONTAINER_NAME",e.containerName||"next-app"),s("IMAGE_NAME",e.imageName||"nextjs-starter"),s("IMAGE_TAG",e.imageTag||"latest"),await u(i,n)}}else{await h(S.join(t,a.DOCKERFILE)),await h(S.join(t,a.DOCKER_COMPOSE)),await h(S.join(t,a.DOCKERIGNORE));let i=S.join(t,a.ENV_EXAMPLE);if(x(i)){let n=await g(i);n=n.replace(/# Docker Compose Configuration\n/,""),n=n.replace(/CONTAINER_NAME=.*\n/,""),n=n.replace(/IMAGE_NAME=.*\n/,""),n=n.replace(/IMAGE_TAG=.*\n/,""),await u(i,n)}}},ft=async(t,e)=>{let i=async r=>{let o=await Se(r,{withFileTypes:!0}),p=[];for(let m of o){let d=S.join(r,m.name);m.isDirectory()&&m.name!=="node_modules"&&m.name!==".git"?p.push(...await i(d)):m.isFile()&&m.name.toLowerCase()==="readme.md"&&p.push(d)}return p},n=await i(t),s=S.join(t,a.README);for(let r of n)r!==s&&await h(r);if(e.readme){let r=`# ${e.projectName}
|
|
71
71
|
|
|
72
72
|
${e.description}
|
|
73
73
|
|
|
@@ -80,9 +80,9 @@ ${e.packageManager==="npm"?"npm run dev":e.packageManager+" dev"}
|
|
|
80
80
|
\`\`\`
|
|
81
81
|
|
|
82
82
|
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
|
83
|
-
`;await u(s,r)}else await h(s)};var Ce=t=>{t.command("init").description("Initialize a new Next.js project").argument("[name]","Project name").action(async e=>{await
|
|
83
|
+
`;await u(s,r)}else await h(s)};var Ce=t=>{t.command("init").description("Initialize a new Next.js project").argument("[name]","Project name").action(async e=>{await gt(e)})},gt=async t=>{me(),c("Welcome to the Teispace Next.js App Creator!"),c("");let e=await ae(t),i=re.resolve(process.cwd(),e.projectName);x(i)&&(console.error(L.red(`Error: Directory ${e.projectName} already exists.`)),process.exit(1));let n=k("Initializing project..."),s=async()=>{if(x(i)){n.stop(),console.log(L.yellow(`
|
|
84
84
|
Cleaning up: Deleting directory ${e.projectName}...`));try{await y(i),console.log(L.green("Cleanup successful."))}catch(o){console.error(L.red(`Failed to clean up directory ${e.projectName}:`),o)}}},r=async()=>{console.log(L.red(`
|
|
85
|
-
Process interrupted. Cleaning up...`)),await s(),process.exit(1)};process.on("SIGINT",r),process.on("SIGTERM",r);try{if(await ue(i),await fe(i,e),await ge(i,e),n.text="Generating code...",await he(i,e),await xe(i,e),n.text="Setting up developer tools...",await ye(i,e),n.text="Initializing Git...",await
|
|
85
|
+
Process interrupted. Cleaning up...`)),await s(),process.exit(1)};process.on("SIGINT",r),process.on("SIGTERM",r);try{if(await ue(i),await fe(i,e),await ge(i,e),n.text="Generating code...",await he(i,e),await xe(i,e),n.text="Setting up developer tools...",await ye(i,e),n.text="Initializing Git...",await ce(i,e.gitRemote),n.text="Installing dependencies...",await le(i,e.packageManager),n.text="Formatting and Linting...",await te(i,e.packageManager,"format"),await te(i,e.packageManager,"lint:fix"),e.copyEnv){n.text="Creating .env file...";let o=re.join(i,".env.example"),p=re.join(i,".env");x(o)&&await(await import("node:fs/promises")).copyFile(o,p)}process.off("SIGINT",r),process.off("SIGTERM",r),n.succeed(L.green(`Project ${e.projectName} created successfully!`)),c(""),c("To get started:"),c(L.cyan(` cd ${e.projectName}`)),c(L.cyan(` ${e.packageManager==="npm"?"npm run dev":e.packageManager+" dev"}`)),c("")}catch(o){n.fail("Failed to create project."),console.error(o),await s(),process.exit(1)}};import v from"picocolors";import se from"node:path";import ht from"enquirer";var{prompt:xt}=ht,Pe=async(t,e,i,n,s,r,o)=>{let p=[];t||p.push({type:"input",name:"featureName",message:"What is the feature name?",initial:"my-feature",validate:d=>/^[a-z0-9-]+$/.test(d)?!0:"Feature name must be lowercase and contain only alphanumeric characters and hyphens."}),e&&n===void 0&&s===void 0&&(p.push({type:"confirm",name:"createStore",message:"Generate Redux store for this feature?",initial:!0}),p.push({type:"confirm",name:"persistStore",message:"Enable persistence for this store?",initial:!1,skip(){return!this.state.answers.createStore}})),i&&i!=="none"&&r===void 0&&o===void 0&&(p.push({type:"confirm",name:"createService",message:"Generate API service for this feature?",initial:!0}),i==="both"&&p.push({type:"select",name:"selectedHttpClient",message:"Which HTTP client to use for the service?",choices:["fetch","axios"],initial:0,skip(){return!this.state.answers.createService}}));let m=p.length>0?await xt(p):{};return{featureName:t||m.featureName,hasRedux:e||!1,createStore:n===!0?!1:s!==void 0?!0:m.createStore||!1,persistStore:s==="persist"?!0:s==="no-persist"?!1:m.persistStore||!1,httpClient:i||"none",createService:r===!0?!1:o!==void 0?!0:m.createService||!1,selectedHttpClient:o||m.selectedHttpClient||(i==="both"?"fetch":i!=="none"?i:void 0)}};import{readFile as St,access as oe}from"node:fs/promises";import W from"node:path";var z=async t=>{let e=!1,i=!1,n=!1,s=!1;try{let r=W.join(t,"package.json"),o=await St(r,"utf-8"),p=JSON.parse(o),m={...p.dependencies,...p.devDependencies};e=!!(m["@reduxjs/toolkit"]&&m["react-redux"]),i=!!m.axios,s=!!m["next-intl"];let d=W.join(t,"src","lib","utils","http","axios-client");try{await oe(d),i=i&&!0}catch{i=!1}let R=W.join(t,"src","lib","utils","http","fetch-client");try{await oe(R),n=!0}catch{n=!1}let P;return i&&n?P="both":i?P="axios":n?P="fetch":P="none",{hasRedux:e,httpClient:P,hasI18n:s}}catch(r){throw new Error(`Failed to detect project setup: ${r}`)}},Ee=async(t,e,i=W.join("src","features"))=>{let n=W.join(t,i,e);try{return await oe(n),!0}catch{return!1}};import{writeFile as F,mkdir as K}from"node:fs/promises";import N from"node:path";var ve=async t=>{let{featurePath:e}=t;await K(N.join(e,"components"),{recursive:!0}),await K(N.join(e,"hooks"),{recursive:!0}),await K(N.join(e,"types"),{recursive:!0}),t.createStore&&await K(N.join(e,"store"),{recursive:!0}),t.createService&&await K(N.join(e,"services"),{recursive:!0}),await yt(t),await Ct(t),await Pt(t),await Tt(t),t.createStore&&await Et(t),t.createService&&t.httpClient&&await vt(t)};var yt=async t=>{let{featureName:e,featurePath:i}=t,n=G(e),s=`use${n}`,r=`'use client';
|
|
86
86
|
import { ${s} } from '../hooks/${s}';
|
|
87
87
|
|
|
88
88
|
export function ${n}() {
|
|
@@ -97,7 +97,7 @@ export function ${n}() {
|
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
export default ${n};
|
|
100
|
-
`;await
|
|
100
|
+
`;await F(N.join(i,"components",`${n}.tsx`),r)},Ct=async t=>{let{featureName:e,featurePath:i,createStore:n}=t,s=G(e),r=`use${s}`,o;n?o=`'use client';
|
|
101
101
|
import { useAppDispatch, useAppSelector } from '@/store/hooks';
|
|
102
102
|
import { select${s}State, setLoading, setError } from '../store/${e}.selectors';
|
|
103
103
|
|
|
@@ -133,12 +133,12 @@ export const ${r} = () => {
|
|
|
133
133
|
// Add your methods here
|
|
134
134
|
} as const;
|
|
135
135
|
};
|
|
136
|
-
`,await
|
|
136
|
+
`,await F(N.join(i,"hooks",`${r}.ts`),o)},Pt=async t=>{let{featureName:e,featurePath:i,createStore:n}=t,o=`export interface ${`${G(e)}State`} {
|
|
137
137
|
// Add your state properties here
|
|
138
138
|
${n?`loading: boolean;
|
|
139
139
|
error: string | null;`:"// example: value: string;"}
|
|
140
140
|
}
|
|
141
|
-
`;await
|
|
141
|
+
`;await F(N.join(i,"types",`${e}.types.ts`),o)},Et=async t=>{let{featureName:e,featurePath:i,persistStore:n}=t,s=G(e),r=b(e),o=`import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
|
142
142
|
import { ${s}State } from '../types/${e}.types';
|
|
143
143
|
|
|
144
144
|
const initialState: ${s}State = {
|
|
@@ -167,11 +167,11 @@ export const ${r}Slice = createSlice({
|
|
|
167
167
|
export const { setLoading, setError, resetState } = ${r}Slice.actions;
|
|
168
168
|
|
|
169
169
|
export const ${r}Reducer = ${r}Slice.reducer;
|
|
170
|
-
`;await
|
|
170
|
+
`;await F(N.join(i,"store",`${e}.slice.ts`),o);let p=`import { RootState } from '@/store/rootReducer';
|
|
171
171
|
|
|
172
172
|
export const select${s}State = (state: RootState) => state.${r};
|
|
173
173
|
export { setLoading, setError, resetState } from './${e}.slice';
|
|
174
|
-
`;if(await
|
|
174
|
+
`;if(await F(N.join(i,"store",`${e}.selectors.ts`),p),n){let d=`import { PersistConfig } from 'redux-persist';
|
|
175
175
|
import storage from 'redux-persist/lib/storage';
|
|
176
176
|
import { ${s}State } from '../types/${e}.types';
|
|
177
177
|
|
|
@@ -180,10 +180,10 @@ export const ${r}PersistConfig: PersistConfig<${s}State> = {
|
|
|
180
180
|
storage,
|
|
181
181
|
// whitelist: ['someField'], // Specify which fields to persist
|
|
182
182
|
};
|
|
183
|
-
`;await
|
|
183
|
+
`;await F(N.join(i,"store","persist.ts"),d)}let m=`export * from './${e}.slice';
|
|
184
184
|
export * from './${e}.selectors';${n?`
|
|
185
185
|
export * from './persist';`:""}
|
|
186
|
-
`;await
|
|
186
|
+
`;await F(N.join(i,"store","index.ts"),m)},vt=async t=>{let{featureName:e,featurePath:i,httpClient:n}=t,s=b(e),r;n==="axios"?r=`import { AppApis } from '@/lib/config';
|
|
187
187
|
import { axiosClient } from '@/lib/utils/http';
|
|
188
188
|
import { ResultAsync } from '@/types';
|
|
189
189
|
|
|
@@ -201,40 +201,40 @@ export const ${s}Service = {
|
|
|
201
201
|
return fetchClient.get<string>(AppApis.${s}.getAll);
|
|
202
202
|
},
|
|
203
203
|
};
|
|
204
|
-
`,await
|
|
204
|
+
`,await F(N.join(i,"services",`${e}.service.ts`),r)},Tt=async t=>{let{featureName:e,featurePath:i,createStore:n,createService:s}=t,r=G(e),o=`export { default as ${r} } from './components/${r}';
|
|
205
205
|
export { use${r} } from './hooks/use${r}';
|
|
206
206
|
export * from './types/${e}.types';${n?`
|
|
207
207
|
export * from './store';`:""}${s?`
|
|
208
208
|
export * from './services/${e}.service';`:""}
|
|
209
|
-
`;await
|
|
210
|
-
`+r.slice(
|
|
211
|
-
`+r;let
|
|
212
|
-
${o}: persistReducer(${m}, ${
|
|
213
|
-
${o}: ${
|
|
214
|
-
})`)}else throw new Error("Could not find combineReducers in rootReducer.ts");await we(s,r)}catch(r){throw new Error(`Failed to register feature in rootReducer: ${r}`)}},
|
|
215
|
-
`+r.slice(
|
|
216
|
-
`+r;let
|
|
217
|
-
${o}: persistReducer(${m}, ${
|
|
218
|
-
${o}: ${
|
|
219
|
-
})`)}else throw new Error("Could not find combineReducers in rootReducer.ts");await we(s,r)}catch(r){throw new Error(`Failed to register slice in rootReducer: ${r}`)}};import{readFile as
|
|
209
|
+
`;await F(N.join(i,"index.ts"),o)};import{readFile as Te,writeFile as we}from"node:fs/promises";import ne from"node:path";var Ie=async(t,e,i,n=ne.join("src","features"))=>{let s=ne.join(t,"src","store","rootReducer.ts");try{let r=await Te(s,"utf-8"),o=b(e),p=`${o}Reducer`,m=i?`${o}PersistConfig`:"",d=n.replace(/^src\//,"@/"),R=i?`import { ${p}, ${m} } from '${d}/${e}/store';`:`import { ${p} } from '${d}/${e}/store';`,P=/import\s+.*\s+from\s+['"].*['"];?\n/g,T=r.match(P);if(T&&T.length>0){let I=T[T.length-1],_=r.lastIndexOf(I);r=r.slice(0,_+I.length)+R+`
|
|
210
|
+
`+r.slice(_+I.length)}else r=R+`
|
|
211
|
+
`+r;let E=/combineReducers\(\{([^}]*)\}\)/s,j=r.match(E);if(j){let I=j[1],_=i?`
|
|
212
|
+
${o}: persistReducer(${m}, ${p}),`:`
|
|
213
|
+
${o}: ${p},`,Q=I.trimEnd()+_;r=r.replace(E,`combineReducers({${Q}
|
|
214
|
+
})`)}else throw new Error("Could not find combineReducers in rootReducer.ts");await we(s,r)}catch(r){throw new Error(`Failed to register feature in rootReducer: ${r}`)}},Re=async(t,e,i,n)=>{let s=ne.join(t,"src","store","rootReducer.ts");try{let r=await Te(s,"utf-8"),o=b(e),p=`${o}Reducer`,m=i?`${o}PersistConfig`:"",d=n.replace(/^src\//,"@/"),R=i?`import { ${p}, ${m} } from '${d}/${e}';`:`import { ${p} } from '${d}/${e}';`,P=/import\s+.*\s+from\s+['"].*['"];?\n/g,T=r.match(P);if(T&&T.length>0){let I=T[T.length-1],_=r.lastIndexOf(I);r=r.slice(0,_+I.length)+R+`
|
|
215
|
+
`+r.slice(_+I.length)}else r=R+`
|
|
216
|
+
`+r;let E=/combineReducers\(\{([^}]*)\}\)/s,j=r.match(E);if(j){let I=j[1],_=i?`
|
|
217
|
+
${o}: persistReducer(${m}, ${p}),`:`
|
|
218
|
+
${o}: ${p},`,Q=I.trimEnd()+_;r=r.replace(E,`combineReducers({${Q}
|
|
219
|
+
})`)}else throw new Error("Could not find combineReducers in rootReducer.ts");await we(s,r)}catch(r){throw new Error(`Failed to register slice in rootReducer: ${r}`)}};import{readFile as wt,writeFile as It}from"node:fs/promises";import Rt from"node:path";var Z=async t=>{let{serviceName:e,projectPath:i}=t,n=b(e),s=Rt.join(i,"src","lib","config","app-apis.ts");try{let r=await wt(s,"utf-8");if(r.includes(`${n}:`))return;if(!r.match(/export const AppApis = \{[\s\S]*?\} as const;/))throw new Error("Could not find AppApis object in app-apis.ts");let p=` ${n}: {
|
|
220
220
|
base: \`\${API_PREFIX}/${e}\`,
|
|
221
221
|
getAll: \`\${API_PREFIX}/${e}\`,
|
|
222
|
-
},`,m=/(\s*)\} as const;/;if(!r.match(m))throw new Error("Could not find closing brace of AppApis object");let
|
|
223
|
-
${
|
|
224
|
-
${T}`:
|
|
225
|
-
`+
|
|
226
|
-
`+T,await
|
|
222
|
+
},`,m=/(\s*)\} as const;/;if(!r.match(m))throw new Error("Could not find closing brace of AppApis object");let R=r.lastIndexOf("} as const;"),P=r.substring(0,R),T=r.substring(R),E=P.trim().endsWith(","),j=P.match(/:\s*\{[^}]*\},\s*$/),I;j||E?I=`${P}
|
|
223
|
+
${p}
|
|
224
|
+
${T}`:I=P.trimEnd()+`
|
|
225
|
+
`+p+`
|
|
226
|
+
`+T,await It(s,I)}catch(r){throw new Error(`Failed to register API endpoints: ${r}`)}};var Ne=t=>{t.command("feature [name]").description("Generate a new feature module").option("--skip-store","Skip Redux store generation").option("--store <type>","Generate Redux store with persistence option (persist|no-persist)").option("--skip-service","Skip API service generation").option("--service <client>","Generate API service with specific HTTP client (axios|fetch)").option("--path <path>","Custom path for feature generation (default: src/features)").action(async(e,i)=>{try{let n=process.cwd();i.store&&!["persist","no-persist"].includes(i.store)&&(C("Invalid --store option. Use: persist or no-persist"),process.exit(1)),i.service&&!["axios","fetch"].includes(i.service)&&(C("Invalid --service option. Use: axios or fetch"),process.exit(1)),i.skipStore&&i.store&&(C("Cannot use --skip-store and --store together"),process.exit(1)),i.skipService&&i.service&&(C("Cannot use --skip-service and --service together"),process.exit(1)),c(v.cyan(`
|
|
227
227
|
\u{1F3AF} Feature Generator
|
|
228
|
-
`)),f.start("Detecting project setup...");let s=await
|
|
229
|
-
`));let r=await Pe(e,s.hasRedux,s.httpClient,i.skipStore,i.store,i.skipService,i.service),o=i.path||
|
|
228
|
+
`)),f.start("Detecting project setup...");let s=await z(n);f.succeed("Project setup detected"),c(v.dim(` Redux: ${s.hasRedux?"\u2713":"\u2717"}`)),c(v.dim(` HTTP Client: ${s.httpClient}`)),c(v.dim(` i18n: ${s.hasI18n?"\u2713":"\u2717"}
|
|
229
|
+
`));let r=await Pe(e,s.hasRedux,s.httpClient,i.skipStore,i.store,i.skipService,i.service),o=i.path||se.join("src","features"),p=se.join(n,o,r.featureName);await Ee(n,r.featureName,o)&&(C(`Feature '${r.featureName}' already exists at ${o}!`),process.exit(1)),f.start("Generating feature files..."),await ve({featureName:r.featureName,featurePath:p,createStore:r.createStore,persistStore:r.persistStore,createService:r.createService,httpClient:r.selectedHttpClient}),f.succeed("Feature files generated"),r.createService&&(f.start("Registering API endpoints..."),await Z({serviceName:r.featureName,projectPath:n}),f.succeed("API endpoints registered")),r.createStore&&s.hasRedux&&(f.start("Registering feature in rootReducer..."),await Ie(n,r.featureName,r.persistStore,o),f.succeed("Feature registered in rootReducer"));let d=se.join(o,r.featureName);c(v.green(`
|
|
230
230
|
\u2728 Feature '${r.featureName}' created successfully!
|
|
231
|
-
`)),
|
|
232
|
-
`)),
|
|
231
|
+
`)),c(v.dim("Generated files:")),c(v.dim(` \u{1F4C2} ${d}/`)),c(v.dim(" \u251C\u2500\u2500 components/")),c(v.dim(" \u251C\u2500\u2500 hooks/")),c(v.dim(" \u251C\u2500\u2500 types/")),r.createStore&&c(v.dim(" \u251C\u2500\u2500 store/")),r.createService&&c(v.dim(" \u251C\u2500\u2500 services/")),c(v.dim(` \u2514\u2500\u2500 index.ts
|
|
232
|
+
`)),c(v.cyan("Next steps:"));let R=o.replace(/^src\//,"@/");c(v.dim(` 1. Import and use the feature: import { ${r.featureName} } from '${R}/${r.featureName}'`)),r.createStore&&c(v.dim(` 2. Customize your Redux slice in: ${d}/store/`)),r.createService&&c(v.dim(` 3. Add API methods in: ${d}/services/${r.featureName}.service.ts`)),c("")}catch(n){f.fail("Feature generation failed"),C(`${n}`),process.exit(1)}})};import $ from"picocolors";import M from"node:path";import{existsSync as kt}from"node:fs";import{mkdir as Gt}from"node:fs/promises";import Nt from"enquirer";var{prompt:$t}=Nt,$e=async(t,e,i)=>{let n=[];t||n.push({type:"input",name:"sliceName",message:"What is the slice name?",initial:"my-slice",validate:r=>/^[a-z0-9-]+$/.test(r)?!0:"Slice name must be lowercase and contain only alphanumeric characters and hyphens."}),e===void 0&&i===void 0&&n.push({type:"confirm",name:"persistSlice",message:"Enable persistence for this slice?",initial:!1});let s=n.length>0?await $t(n):{};return{sliceName:t||s.sliceName,persistSlice:e===!0?!0:i===!1?!1:s.persistSlice||!1}};import{writeFile as V,mkdir as bt}from"node:fs/promises";import B from"node:path";var be=async t=>{let{sliceName:e,slicePath:i,persistSlice:n}=t;await bt(i,{recursive:!0});let s=G(e),r=b(e);await Ot(e,i,s),await At(e,i,s,r),await jt(e,i,s,r),n&&await _t(e,i,s,r),await Ft(e,i,n)},Ot=async(t,e,i)=>{let n=`export interface ${i}State {
|
|
233
233
|
loading: boolean;
|
|
234
234
|
error: string | null;
|
|
235
235
|
// Add your state properties here
|
|
236
236
|
}
|
|
237
|
-
`;await
|
|
237
|
+
`;await V(B.join(e,`${t}.types.ts`),n)},At=async(t,e,i,n)=>{let s=`import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
|
238
238
|
import { ${i}State } from './${t}.types';
|
|
239
239
|
|
|
240
240
|
const initialState: ${i}State = {
|
|
@@ -263,11 +263,11 @@ export const ${n}Slice = createSlice({
|
|
|
263
263
|
export const { setLoading, setError, resetState } = ${n}Slice.actions;
|
|
264
264
|
|
|
265
265
|
export const ${n}Reducer = ${n}Slice.reducer;
|
|
266
|
-
`;await
|
|
266
|
+
`;await V(B.join(e,`${t}.slice.ts`),s)},jt=async(t,e,i,n)=>{let s=`import { RootState } from '@/store/rootReducer';
|
|
267
267
|
|
|
268
268
|
export const select${i}State = (state: RootState) => state.${n};
|
|
269
269
|
export { setLoading, setError, resetState } from './${t}.slice';
|
|
270
|
-
`;await
|
|
270
|
+
`;await V(B.join(e,`${t}.selectors.ts`),s)},_t=async(t,e,i,n)=>{let s=`import { PersistConfig } from 'redux-persist';
|
|
271
271
|
import storage from 'redux-persist/lib/storage';
|
|
272
272
|
import { ${i}State } from './${t}.types';
|
|
273
273
|
|
|
@@ -276,19 +276,19 @@ export const ${n}PersistConfig: PersistConfig<${i}State> = {
|
|
|
276
276
|
storage,
|
|
277
277
|
// whitelist: ['someField'], // Specify which fields to persist
|
|
278
278
|
};
|
|
279
|
-
`;await
|
|
279
|
+
`;await V(B.join(e,"persist.ts"),s)},Ft=async(t,e,i)=>{let n=`export * from './${t}.slice';
|
|
280
280
|
export * from './${t}.selectors';
|
|
281
281
|
export * from './${t}.types';${i?`
|
|
282
282
|
export * from './persist';`:""}
|
|
283
|
-
`;await
|
|
283
|
+
`;await V(B.join(e,"index.ts"),n)};import{access as Dt}from"node:fs/promises";import Oe from"node:path";var Ae=async(t,e,i=Oe.join("src","store","slices"))=>{let n=Oe.join(t,i,e);try{return await Dt(n),!0}catch{return!1}};var je=t=>{t.command("slice [name]").description("Generate a Redux slice").option("--path <path>","Custom path for slice generation (default: create new feature)").option("--persist","Enable persistence for this slice").option("--no-persist","Disable persistence for this slice").action(async(e,i)=>{try{let n=process.cwd();i.persist&&i.noPersist===!0&&(C("Cannot use --persist and --no-persist together"),process.exit(1)),c($.cyan(`
|
|
284
284
|
\u{1F527} Slice Generator
|
|
285
|
-
`)),f.start("Detecting project setup...");let s=await
|
|
285
|
+
`)),f.start("Detecting project setup...");let s=await z(n);f.succeed("Project setup detected"),s.hasRedux||(f.fail("Redux is not setup in this project"),C("Please install @reduxjs/toolkit and react-redux first"),c($.dim(`
|
|
286
286
|
Run: npm install @reduxjs/toolkit react-redux
|
|
287
|
-
`)),process.exit(1)),
|
|
288
|
-
`));let r=await $e(e,i.persist,i.noPersist===!0?!1:void 0),o,
|
|
287
|
+
`)),process.exit(1)),c($.dim(` Redux: \u2713
|
|
288
|
+
`));let r=await $e(e,i.persist,i.noPersist===!0?!1:void 0),o,p,m;if(i.path){let E=i.path.replace(/^src\//,"");E.startsWith("features/")?(p=E.split("/")[1],o=M.join("src","features",p,"store"),m=M.join(n,o,r.sliceName)):(o=M.join("src",E),p=E.split("/")[0],m=M.join(n,o,r.sliceName))}else p=r.sliceName,o=M.join("src","features",p,"store"),m=M.join(n,o,r.sliceName);let d=M.join(n,o);kt(d)||await Gt(d,{recursive:!0}),await Ae(n,r.sliceName,o)&&(C(`Slice '${r.sliceName}' already exists at ${o}!`),process.exit(1)),f.start("Generating slice files..."),await be({sliceName:r.sliceName,slicePath:m,persistSlice:r.persistSlice}),f.succeed("Slice files generated"),f.start("Registering slice in rootReducer..."),await Re(n,r.sliceName,r.persistSlice,o),f.succeed("Slice registered in rootReducer");let P=M.join(o,r.sliceName);c($.green(`
|
|
289
289
|
\u2728 Slice '${r.sliceName}' created successfully!
|
|
290
|
-
`)),
|
|
291
|
-
`)),
|
|
290
|
+
`)),c($.dim("Generated files:")),c($.dim(` \u{1F4C2} ${P}/`)),c($.dim(` \u251C\u2500\u2500 ${r.sliceName}.slice.ts`)),c($.dim(` \u251C\u2500\u2500 ${r.sliceName}.selectors.ts`)),r.persistSlice&&c($.dim(" \u251C\u2500\u2500 persist.ts")),c($.dim(` \u251C\u2500\u2500 ${r.sliceName}.types.ts`)),c($.dim(` \u2514\u2500\u2500 index.ts
|
|
291
|
+
`)),c($.cyan("Next steps:"));let T=o.replace(/^src\//,"@/");c($.dim(` 1. Import actions: import { setLoading, setError } from '${T}/${r.sliceName}'`)),c($.dim(" 2. Use in component: dispatch(setLoading(true))")),c("")}catch(n){f.fail("Slice generation failed"),C(`${n}`),process.exit(1)}})};import D from"picocolors";import H from"node:path";import{existsSync as Xt}from"node:fs";import{mkdir as Yt}from"node:fs/promises";import _e from"enquirer";var Fe=async(t,e,i,n)=>{let s=t||(await _e.prompt({type:"input",name:"serviceName",message:"Service name (kebab-case):",validate:o=>o?/^[a-z0-9-]+$/.test(o)?!0:"Service name must be lowercase with hyphens only":"Service name is required"})).serviceName,r;return e!==void 0?r="axios":i!==void 0?r="fetch":n==="axios"?r="axios":n==="fetch"?r="fetch":n==="both"?r=(await _e.prompt({type:"select",name:"httpClient",message:"Choose HTTP client:",choices:["axios","fetch"]})).httpClient:r="axios",{serviceName:s,httpClient:r}};import{writeFile as Lt}from"node:fs/promises";import Mt from"node:path";var De=async t=>{await Ut(t)},Ut=async t=>{let{serviceName:e,servicePath:i,httpClient:n}=t,s=b(e),r;n==="axios"?r=`import { AppApis } from '@/lib/config';
|
|
292
292
|
import { axiosClient } from '@/lib/utils/http';
|
|
293
293
|
import { ResultAsync } from '@/types';
|
|
294
294
|
|
|
@@ -306,13 +306,20 @@ export const ${s}Service = {
|
|
|
306
306
|
return fetchClient.get<string>(AppApis.${s}.getAll);
|
|
307
307
|
},
|
|
308
308
|
};
|
|
309
|
-
`;let o=`${e}.service.ts`;await Lt(
|
|
309
|
+
`;let o=`${e}.service.ts`;await Lt(Mt.join(i,o),r)};import{existsSync as Ht}from"node:fs";import zt from"node:path";var ke=async(t,e,i)=>{let n=zt.join(t,i,`${e}.service.ts`);return Ht(n)};var Ge=t=>{t.command("service [name]").description("Generate an API service").option("--path <path>","Custom path for service generation (default: create new feature)").option("--axios","Use Axios HTTP client").option("--fetch","Use Fetch HTTP client").action(async(e,i)=>{try{let n=process.cwd();i.axios&&i.fetch&&(C("Cannot use --axios and --fetch together"),process.exit(1)),c(D.cyan(`
|
|
310
310
|
\u{1F527} Service Generator
|
|
311
|
-
`)),f.start("Detecting project setup...");let s=await
|
|
311
|
+
`)),f.start("Detecting project setup...");let s=await z(n);f.succeed("Project setup detected"),s.httpClient==="none"&&(f.fail("No HTTP client is setup in this project"),C("Please setup either AxiosClient or FetchClient first"),c(D.dim(`
|
|
312
312
|
Check: lib/utils/http/axios-client or lib/utils/http/fetch-client
|
|
313
|
-
`)),process.exit(1));let r=[];(s.httpClient==="axios"||s.httpClient==="both")&&r.push("Axios \u2713"),(s.httpClient==="fetch"||s.httpClient==="both")&&r.push("Fetch \u2713"),
|
|
314
|
-
`));let o=await Fe(e,i.axios,i.fetch,s.httpClient),
|
|
313
|
+
`)),process.exit(1));let r=[];(s.httpClient==="axios"||s.httpClient==="both")&&r.push("Axios \u2713"),(s.httpClient==="fetch"||s.httpClient==="both")&&r.push("Fetch \u2713"),c(D.dim(` HTTP Clients: ${r.join(", ")}
|
|
314
|
+
`));let o=await Fe(e,i.axios,i.fetch,s.httpClient),p,m,d;if(i.path){let E=i.path.replace(/^src\//,"");E.startsWith("features/")?(m=E.split("/")[1],p=H.join("src","features",m,"services"),d=H.join(n,p)):(p=H.join("src",E),m=E.split("/")[0],d=H.join(n,p))}else m=o.serviceName,p=H.join("src","features",m,"services"),d=H.join(n,p);Xt(d)||await Yt(d,{recursive:!0}),await ke(n,o.serviceName,p)&&(C(`Service '${o.serviceName}' already exists at ${p}!`),process.exit(1)),f.start("Generating service files..."),await De({serviceName:o.serviceName,servicePath:d,httpClient:o.httpClient}),f.succeed("Service files generated"),f.start("Registering API endpoints..."),await Z({serviceName:o.serviceName,projectPath:n}),f.succeed("API endpoints registered");let P=H.join(p,`${o.serviceName}.service.ts`);c(D.green(`
|
|
315
315
|
\u2728 Service '${o.serviceName}' created successfully!
|
|
316
|
-
`)),
|
|
317
|
-
`)),
|
|
316
|
+
`)),c(D.dim("Generated files:")),c(D.dim(` \u{1F4C4} ${P}
|
|
317
|
+
`)),c(D.cyan("Next steps:"));let T=p.replace(/^src\//,"@/");c(D.dim(` 1. Import service: import { ${o.serviceName}Service } from '${T}/${o.serviceName}.service'`)),c(D.dim(` 2. Use in component: const data = await ${o.serviceName}Service.getAll()`)),c("")}catch(n){f.fail("Service generation failed"),C(`${n}`),process.exit(1)}})};import O from"picocolors";import Wt from"enquirer";var{prompt:Kt}=Wt,Le=t=>{t.command("setup").description("Setup additional features for your Next.js project").option("--http-client <type>","Setup HTTP client (axios|fetch|both)").option("--dark-theme","Setup dark theme support").option("--redux","Setup Redux Toolkit with persistence").option("--i18n","Setup next-intl for internationalization").action(async e=>{try{if(c(O.cyan(`
|
|
318
|
+
\u{1F527} Setup Wizard
|
|
319
|
+
`)),!e.httpClient&&!e.darkTheme&&!e.redux&&!e.i18n){let i=await Kt([{type:"select",name:"feature",message:"What would you like to setup?",choices:["HTTP Client (Axios/Fetch)","Dark Theme","Redux Toolkit","Internationalization (next-intl)","Cancel"]}]);if(i.feature==="Cancel"){c(O.yellow("Setup cancelled."));return}c(O.yellow(`
|
|
320
|
+
\u26A0\uFE0F ${i.feature} setup is not implemented yet.`)),c(O.dim("This feature will be available in a future update."))}else e.httpClient&&(c(O.yellow(`
|
|
321
|
+
\u26A0\uFE0F HTTP Client setup is not implemented yet.`)),c(O.dim("This feature will be available in a future update."))),e.darkTheme&&(c(O.yellow(`
|
|
322
|
+
\u26A0\uFE0F Dark Theme setup is not implemented yet.`)),c(O.dim("This feature will be available in a future update."))),e.redux&&(c(O.yellow(`
|
|
323
|
+
\u26A0\uFE0F Redux Toolkit setup is not implemented yet.`)),c(O.dim("This feature will be available in a future update."))),e.i18n&&(c(O.yellow(`
|
|
324
|
+
\u26A0\uFE0F Internationalization setup is not implemented yet.`)),c(O.dim("This feature will be available in a future update.")))}catch(i){f.fail("Setup failed"),C(`${i}`),process.exit(1)}})};var Me=t=>{Ce(t),Le(t),Ne(t),je(t),Ge(t)};async function Bt(){de({logger:e=>q(e)});let t=new Vt;t.name("next-maker").description("Teispace Next.js Project Generator").version("1.0.0"),Me(t),t.parse()}Bt().catch(t=>{let e=t&&typeof t=="object"&&"message"in t?t.message:String(t);q(`Unexpected error: ${e}`)});
|
|
318
325
|
//# sourceMappingURL=index.js.map
|