@teispace/next-maker 1.13.1 → 1.15.0

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.
Files changed (101) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/LICENSE +21 -0
  3. package/README.md +149 -40
  4. package/dist/index.js +574 -339
  5. package/dist/index.js.map +4 -4
  6. package/dist/src/commands/app.d.ts +1 -1
  7. package/dist/src/commands/app.d.ts.map +1 -1
  8. package/dist/src/commands/component.d.ts +1 -1
  9. package/dist/src/commands/component.d.ts.map +1 -1
  10. package/dist/src/commands/feature.d.ts +1 -1
  11. package/dist/src/commands/feature.d.ts.map +1 -1
  12. package/dist/src/commands/hook.d.ts +1 -1
  13. package/dist/src/commands/hook.d.ts.map +1 -1
  14. package/dist/src/commands/index.d.ts +1 -1
  15. package/dist/src/commands/index.d.ts.map +1 -1
  16. package/dist/src/commands/locale.d.ts +1 -1
  17. package/dist/src/commands/locale.d.ts.map +1 -1
  18. package/dist/src/commands/page.d.ts +1 -1
  19. package/dist/src/commands/page.d.ts.map +1 -1
  20. package/dist/src/commands/service.d.ts +1 -1
  21. package/dist/src/commands/service.d.ts.map +1 -1
  22. package/dist/src/commands/setup.d.ts +1 -1
  23. package/dist/src/commands/setup.d.ts.map +1 -1
  24. package/dist/src/commands/slice.d.ts +1 -1
  25. package/dist/src/commands/slice.d.ts.map +1 -1
  26. package/dist/src/commands/test.d.ts +3 -0
  27. package/dist/src/commands/test.d.ts.map +1 -0
  28. package/dist/src/config/index.d.ts +1 -1
  29. package/dist/src/config/index.d.ts.map +1 -1
  30. package/dist/src/config/packages.d.ts +11 -1
  31. package/dist/src/config/packages.d.ts.map +1 -1
  32. package/dist/src/config/paths.d.ts +5 -2
  33. package/dist/src/config/paths.d.ts.map +1 -1
  34. package/dist/src/config/spinner.d.ts +1 -1
  35. package/dist/src/config/spinner.d.ts.map +1 -1
  36. package/dist/src/core/package-manager.d.ts +2 -0
  37. package/dist/src/core/package-manager.d.ts.map +1 -1
  38. package/dist/src/detection/index.d.ts +2 -2
  39. package/dist/src/detection/index.d.ts.map +1 -1
  40. package/dist/src/detection/project.detector.d.ts +1 -0
  41. package/dist/src/detection/project.detector.d.ts.map +1 -1
  42. package/dist/src/generators/index.d.ts +12 -10
  43. package/dist/src/generators/index.d.ts.map +1 -1
  44. package/dist/src/generators/templates/test.template.d.ts +27 -0
  45. package/dist/src/generators/templates/test.template.d.ts.map +1 -0
  46. package/dist/src/generators/test.generator.d.ts +19 -0
  47. package/dist/src/generators/test.generator.d.ts.map +1 -0
  48. package/dist/src/modifiers/index.d.ts +3 -3
  49. package/dist/src/modifiers/index.d.ts.map +1 -1
  50. package/dist/src/pipelines/feature.pipeline.d.ts.map +1 -1
  51. package/dist/src/pipelines/index.d.ts +5 -5
  52. package/dist/src/pipelines/index.d.ts.map +1 -1
  53. package/dist/src/prompts/component.prompt.d.ts.map +1 -1
  54. package/dist/src/prompts/create-app.prompt.d.ts +4 -1
  55. package/dist/src/prompts/create-app.prompt.d.ts.map +1 -1
  56. package/dist/src/prompts/feature.prompt.d.ts.map +1 -1
  57. package/dist/src/prompts/hook.prompt.d.ts.map +1 -1
  58. package/dist/src/prompts/locale.prompt.d.ts.map +1 -1
  59. package/dist/src/prompts/page.prompt.d.ts.map +1 -1
  60. package/dist/src/prompts/slice.prompt.d.ts.map +1 -1
  61. package/dist/src/services/common/test-utils.d.ts +12 -0
  62. package/dist/src/services/common/test-utils.d.ts.map +1 -0
  63. package/dist/src/services/init/cleanup/bundle-analyzer.cleanup.d.ts +3 -0
  64. package/dist/src/services/init/cleanup/bundle-analyzer.cleanup.d.ts.map +1 -0
  65. package/dist/src/services/init/cleanup/http.cleanup.d.ts.map +1 -1
  66. package/dist/src/services/init/cleanup/i18n.cleanup.d.ts.map +1 -1
  67. package/dist/src/services/init/cleanup/index.d.ts.map +1 -1
  68. package/dist/src/services/init/cleanup/react-compiler.cleanup.d.ts +3 -0
  69. package/dist/src/services/init/cleanup/react-compiler.cleanup.d.ts.map +1 -0
  70. package/dist/src/services/init/cleanup/redux.cleanup.d.ts.map +1 -1
  71. package/dist/src/services/init/cleanup/tests.cleanup.d.ts +3 -0
  72. package/dist/src/services/init/cleanup/tests.cleanup.d.ts.map +1 -0
  73. package/dist/src/services/init/config.service.d.ts +1 -1
  74. package/dist/src/services/init/config.service.d.ts.map +1 -1
  75. package/dist/src/services/init/devtools.service.d.ts +1 -1
  76. package/dist/src/services/init/devtools.service.d.ts.map +1 -1
  77. package/dist/src/services/init/providers.service.d.ts +1 -1
  78. package/dist/src/services/init/providers.service.d.ts.map +1 -1
  79. package/dist/src/services/setup/bundle-analyzer/index.d.ts +2 -0
  80. package/dist/src/services/setup/bundle-analyzer/index.d.ts.map +1 -0
  81. package/dist/src/services/setup/dark-theme/assets.d.ts +1 -1
  82. package/dist/src/services/setup/dark-theme/assets.d.ts.map +1 -1
  83. package/dist/src/services/setup/dark-theme/checks.d.ts.map +1 -1
  84. package/dist/src/services/setup/dark-theme/injectors.d.ts.map +1 -1
  85. package/dist/src/services/setup/http-client/assets.d.ts +1 -1
  86. package/dist/src/services/setup/http-client/assets.d.ts.map +1 -1
  87. package/dist/src/services/setup/i18n/assets.d.ts +1 -1
  88. package/dist/src/services/setup/i18n/assets.d.ts.map +1 -1
  89. package/dist/src/services/setup/i18n/checks.d.ts.map +1 -1
  90. package/dist/src/services/setup/i18n/index.d.ts.map +1 -1
  91. package/dist/src/services/setup/i18n/injectors.d.ts.map +1 -1
  92. package/dist/src/services/setup/react-compiler/index.d.ts +2 -0
  93. package/dist/src/services/setup/react-compiler/index.d.ts.map +1 -0
  94. package/dist/src/services/setup/redux/assets.d.ts +1 -1
  95. package/dist/src/services/setup/redux/assets.d.ts.map +1 -1
  96. package/dist/src/services/setup/redux/index.d.ts.map +1 -1
  97. package/dist/src/services/setup/redux/injectors.d.ts +1 -1
  98. package/dist/src/services/setup/redux/injectors.d.ts.map +1 -1
  99. package/dist/src/services/setup/tests/index.d.ts +2 -0
  100. package/dist/src/services/setup/tests/index.d.ts.map +1 -0
  101. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -1,41 +1,214 @@
1
1
  #!/usr/bin/env node
2
- var wr=Object.defineProperty;var se=(t,o)=>()=>(t&&(o=t(t=0)),o);var Me=(t,o)=>{for(var e in o)wr(t,e,{get:o[e],enumerable:!0})};import te from"node:fs/promises";import It from"node:path";import{existsSync as Ue}from"node:fs";var d,u,O,w,h,me,l,P=se(()=>{"use strict";d=async t=>te.readFile(t,"utf-8"),u=async(t,o)=>{await te.mkdir(It.dirname(t),{recursive:!0}),await te.writeFile(t,o,"utf-8")},O=async(t,o)=>{await te.mkdir(It.dirname(o),{recursive:!0}),await te.copyFile(t,o)},w=async t=>{Ue(t)&&await te.unlink(t)},h=async t=>{Ue(t)&&await te.rm(t,{recursive:!0,force:!0})},me=async(t,o)=>{let e=await d(t),r=JSON.parse(e),n=o(r);await u(t,JSON.stringify(n,null,2))},l=t=>Ue(t)});var Ot={};Me(Ot,{PROJECT_PATHS:()=>a});var a,T=se(()=>{"use strict";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",AXIOS_CLIENT_FILE:"src/lib/utils/http/axios-client/index.ts",FETCH_CLIENT_FILE:"src/lib/utils/http/fetch-client/index.ts",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",SCRIPTS_DIR:"scripts",DOCS_DIR:"docs",CLAUDE_DIR:".claude",VSCODE_DIR:".vscode"}});var _t={};Me(_t,{cleanupHttpTypes:()=>ae,isFileUsed:()=>Gr,isStringUsed:()=>Mr,migrateClientUsages:()=>Ve,removeHttpExports:()=>qe,updateConfigIndex:()=>Be,updateHttpIndex:()=>Ye,updateTypesIndex:()=>We,updateUtilsIndex:()=>ze});import R from"node:path";import{exec as Lr}from"node:child_process";import{promisify as Hr}from"node:util";var Je,Ye,ze,We,Be,ae,Ve,qe,Gr,Mr,Re=se(()=>{"use strict";P();T();Je=Hr(Lr),Ye=async(t,o)=>{let e=R.join(t,a.HTTP_UTILS,"index.ts");if(l(e)){let r=await d(e);r=r.replace(/export .* from '\.\/axios-client';?\n?/g,""),r=r.replace(/export .* from '\.\/fetch-client';?\n?/g,""),o.includes("fetch")&&!r.includes("fetch-client")&&(r+=`export * from './fetch-client';
3
- `),o.includes("axios")&&!r.includes("axios-client")&&(r+=`export * from './axios-client';
4
- `),await u(e,r)}},ze=async t=>{let o=R.join(t,a.UTILS_INDEX);if(l(o)){let e=await d(o);e.includes("./http")||(e+=`export * from './http';
5
- `,await u(o,e))}},We=async t=>{let o=R.join(t,a.TYPES_INDEX);if(l(o)){let e=await d(o);e.includes("./common")||(e+=`export * from './common';
6
- `),e.includes("./utility")||(e+=`export * from './utility';
7
- `),await u(o,e)}},Be=async t=>{let o=R.join(t,a.CONFIG_INDEX);if(l(o)){let e=await d(o);e.includes("./app-apis")||(e+=`export * from './app-apis';
8
- `,await u(o,e))}},ae=async(t,o)=>{let e=R.join(t,a.HTTP_TYPES);if(l(e)){let r=await d(e);o.includes("axios")||(r=r.replace(/declare module 'axios'\s*\{\s*export interface AxiosRequestConfig\s*\{[\s\S]*?\}\s*\}/g,""),r=r.replace(/\n\s*\n/g,`
9
-
10
- `).trim()+`
11
- `,await u(e,r))}},Ve=async(t,o,e)=>{if(o===e)return;let r=o==="fetch"?"fetchClient":"axiosClient",n=e==="fetch"?"fetchClient":"axiosClient",i=o==="fetch"?"fetch-client":"axios-client",s=e==="fetch"?"fetch-client":"axios-client",c=R.join(t,"src");try{let m=`grep -rl "${r}" "${c}" --include="*.ts" --include="*.tsx" || true`,{stdout:f}=await Je(m);if(!f.trim())return;let x=f.trim().split(`
12
- `).filter(S=>S);for(let S of x){if(!l(S))continue;let v=await d(S),M=!1,Ge=new RegExp(`(import\\s*\\{[^}]*?)\\b${r}\\b([^}]*?\\}\\s*from\\s*['"][^'"]*?/http['"])`,"g");Ge.test(v)&&(v=v.replace(Ge,`$1${n}$2`),M=!0);let Te=new RegExp(`import\\s+${r}\\s+from\\s+['"]([^'"]*?)/${i}['"]`,"g");Te.test(v)&&(v=v.replace(Te,`import ${n} from '$1/${s}'`),M=!0);let Ee=new RegExp(`\\b${r}\\b(?=\\.)`,"g");Ee.test(v)&&(v=v.replace(Ee,n),M=!0);let Tt=new RegExp(`\\b${r}\\b(?![.\\w])`,"g");Tt.test(v)&&(v=v.replace(Tt,n),M=!0),M&&await u(S,v)}}catch(m){console.warn("Warning: Could not scan for HTTP client usages:",m)}},qe=async t=>{let o=R.join(t,a.UTILS_INDEX);if(l(o)){let r=await d(o);r=r.replace(/^\s*export\s+\*\s+from\s+['"]\.\/http['"];?.*$/gm,""),await u(o,r)}let e=R.join(t,a.TYPES_INDEX);if(l(e)){let r=await d(e),n=R.join(t,a.COMMON_TYPES_DIR);if(!l(n))r=r.replace(/^\s*export\s+\*\s+from\s+['"]\.\/common['"];?.*$/gm,"");else{let i=R.join(n,"index.ts");if(l(i)){let s=await d(i);s=s.replace(/^\s*export\s+\*\s+from\s+['"]\.\/http\.types['"];?.*$/gm,""),await u(i,s)}}l(R.join(t,a.UTILITY_TYPES_DIR))||(r=r.replace(/^\s*export\s+\*\s+from\s+['"]\.\/utility['"];?.*$/gm,"")),await u(e,r)}},Gr=async(t,o,e=[])=>{let r=R.join(t,"src"),i=`grep -r "from ['\\"].*${o.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}.*['\\"]" "${r}" --include="*.ts" --include="*.tsx" || true`;try{let{stdout:s}=await Je(i);return s.trim()?s.trim().split(`
13
- `).filter(f=>{let[x]=f.split(":"),S=R.resolve(t,x);return!e.some(v=>!!(S===v||S.startsWith(v+R.sep)))}).length>0:!1}catch(s){return console.warn(`Warning: Failed to check usage for ${o}:`,s),!0}},Mr=async(t,o,e=[])=>{let r=R.join(t,"src"),i=`grep -r "${o.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}" "${r}" --include="*.ts" --include="*.tsx" || true`;try{let{stdout:s}=await Je(i);return s.trim()?s.trim().split(`
14
- `).filter(f=>{let[x]=f.split(":"),S=R.resolve(t,x);return!e.some(v=>!!(S===v||S.startsWith(v+R.sep)))}).length>0:!1}catch(s){return console.warn(`Warning: Failed to check usage for string ${o}:`,s),!0}}});import{readFile as fi,access as Kt}from"node:fs/promises";import Qe from"node:path";var _,Zt=se(()=>{"use strict";_=async t=>{try{let o=Qe.join(t,"package.json"),e=await fi(o,"utf-8"),r=JSON.parse(e),n={...r.dependencies,...r.devDependencies},i=!!(n["@reduxjs/toolkit"]&&n["react-redux"]),s=!!n["next-intl"],c=!!n.axios,m=!1,f=Qe.join(t,"src","lib","utils","http","axios-client");try{await Kt(f)}catch{c=!1}let x=Qe.join(t,"src","lib","utils","http","fetch-client");try{await Kt(x),m=!0}catch{m=!1}let S;return c&&m?S="both":c?S="axios":m?S="fetch":S="none",{hasRedux:i,httpClient:S,hasI18n:s}}catch(o){throw new Error(`Failed to detect project setup: ${o}`,{cause:o})}}});import{access as gi}from"node:fs/promises";import{existsSync as hi}from"node:fs";import Qt from"node:path";var Q,Ae,eo=se(()=>{"use strict";Q=async(t,o,e)=>{try{return await gi(Qt.join(t,e,o)),!0}catch{return!1}},Ae=(t,o,e)=>hi(Qt.join(t,o,e))});var to={};Me(to,{detectProjectSetup:()=>_,directoryExists:()=>Q,fileExistsAt:()=>Ae});var W=se(()=>{"use strict";Zt();eo()});import{Command as Ln}from"commander";import Ze from"node:path";import Z from"picocolors";import Sr from"ora";function A(t="",o){let e=Sr({text:t,...o});return e.start(),e}import Cr from"enquirer";var{prompt:vr}=Cr,Et=async t=>{let o=await vr([{type:"input",name:"projectName",message:"What is the project name?",initial:t||"my-app",skip:!!t,validate:e=>/^[a-z0-9-_]+$/.test(e)?!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:e=>/^\d+\.\d+\.\d+$/.test(e)?!0:"Version must be a valid semantic version (x.y.z)."},{type:"input",name:"email",message:"Support email:",initial:"support@example.com",validate:e=>/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e)?!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):",initial:""},{type:"confirm",name:"pushToRemote",message:"Would you like to push the changes to the remote repository?",initial:!0,skip:function(){return!this.state?.answers?.gitRemote}},{type:"input",name:"gitIssues",message:"GitHub issues URL (optional):",initial:"",skip:function(){return!this.state?.answers?.gitRemote},validate:e=>e?/^https:\/\/github\.com\/[\w-]+\/[\w.-]+\/issues$/.test(e)?!0:"Please enter a valid GitHub issues URL (e.g., https://github.com/user/repo/issues)":!0},{type:"input",name:"gitHomepage",message:"GitHub homepage URL (optional):",initial:"",skip:function(){return!this.state?.answers?.gitRemote},validate:e=>e?/^https:\/\/github\.com\/[\w-]+\/[\w.-]+#readme$/.test(e)?!0:"Please enter a valid GitHub homepage URL (e.g., https://github.com/user/repo#readme)":!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 e=this.state?.answers??this.enquirer?.answers??{};return!!(e.httpClient&&e.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:e=>/^[a-zA-Z0-9][a-zA-Z0-9_.-]*$/.test(e)?!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:e=>/^[a-z0-9]+(?:[._-][a-z0-9]+)*$/.test(e)?!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:e=>/^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,127}$/.test(e)?!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(o.company=o.author,o.gitRemote&&!o.gitHomepage){let e=o.gitRemote.replace("git@github.com:","https://github.com/").replace(/\.git$/,"");o.gitHomepage=`${e}#readme`,o.gitIssues=`${e}/issues`}return o};P();import{exec as Tr}from"node:child_process";import{promisify as Er}from"node:util";var z=Er(Tr),Nt=async(t,o,e)=>{try{if(await z("git init",{cwd:t}),await z("git add .",{cwd:t}),await z('git commit -m "Initial commit from @teispace/next-maker"',{cwd:t}),o&&(await z(`git remote add origin ${o}`,{cwd:t}),e)){await z("git fetch origin",{cwd:t});let r="main";try{await z("git show-branch origin/main",{cwd:t})}catch{try{await z("git show-branch origin/master",{cwd:t}),r="master"}catch{r="main"}}await z(`git merge origin/${r} --allow-unrelated-histories -X ours`,{cwd:t}),await z(`git push origin HEAD:${r}`,{cwd:t})}}catch(r){console.warn("Failed to initialize git repository",r)}};import{exec as Ir}from"node:child_process";import{promisify as Nr}from"node:util";var Ie=Nr(Ir),Rt=async(t,o)=>{let e=`${o} install`;try{await Ie(e,{cwd:t})}catch(r){throw new Error(`Failed to install dependencies with ${o}: ${r}`,{cause:r})}},D=async(t,o,e)=>{let r=o==="npm"?`${o} run ${e}`:`${o} ${e}`;try{await Ie(r,{cwd:t})}catch(n){console.warn(`Warning: Failed to run script '${e}': ${n}`)}},Rr=()=>{let t=process.env.npm_config_user_agent;if(t){if(t.startsWith("yarn"))return"yarn";if(t.startsWith("pnpm"))return"pnpm";if(t.startsWith("bun"))return"bun"}return"npm"},U=async t=>{let{existsSync:o}=await import("node:fs"),e=await import("node:path");return o(e.join(t,"pnpm-lock.yaml"))?"pnpm":o(e.join(t,"yarn.lock"))?"yarn":o(e.join(t,"bun.lockb"))?"bun":o(e.join(t,"package-lock.json"))?"npm":Rr()},$r=async(t,o,e)=>{if(e.length===0)return;let n=`${Ar(o)} ${e.join(" ")}`;try{await Ie(n,{cwd:t})}catch(i){throw new Error(`Failed to install packages with ${o}: ${i}`,{cause:i})}},Ar=t=>{switch(t){case"npm":return"npm install";case"yarn":return"yarn add";case"pnpm":return"pnpm add";case"bun":return"bun add";default:return"npm install"}},F=async(t,o)=>{let e=await U(t);await $r(t,e,[o])},br=async(t,o,e)=>{if(e.length===0)return;let n=`${Or(o)} ${e.join(" ")}`;try{await Ie(n,{cwd:t})}catch(i){throw new Error(`Failed to uninstall packages with ${o}: ${i}`,{cause:i})}},Or=t=>{switch(t){case"npm":return"npm uninstall";case"yarn":return"yarn remove";case"pnpm":return"pnpm remove";case"bun":return"bun remove";default:return"npm uninstall"}},Xe=async(t,o)=>{let e=await U(t);await br(t,e,[o])};import X from"picocolors";var kr={reset:t=>t,red:X.red,green:X.green,yellow:X.yellow,blue:X.blue,cyan:X.cyan,magenta:X.magenta,white:X.white,gray:X.gray,bright:X.bold,dim:X.dim};function oe(t,o="reset"){let e=kr[o]??(r=>r);console.log(e(t))}function Ne(t){oe(`\u2716 ${t}`,"red")}var C=Ne;function p(t){oe(t)}function $t(){console.log(""),oe("\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"),oe("\u2551 \u2551","cyan"),oe("\u2551 \u{1F680} Create Teispace Next.js App \u{1F680} \u2551","cyan"),oe("\u2551 \u2551","cyan"),oe("\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 At(t){let{logger:o=s=>console.error(s),exitOnCancel:e=process.env.NODE_ENV!=="test"}=t??{},r=()=>{console.log(""),console.log(""),o("Setup cancelled by user"),console.log(""),e&&process.exit(0)},n=s=>{if(s!==null&&typeof s=="object"&&"code"in s&&s.code==="ERR_USE_AFTER_CLOSE"){r();return}if(s instanceof Error){o(`Uncaught exception: ${s.message}`);return}o(`Uncaught exception: ${String(s)}`)},i=s=>{if(s instanceof Error){o(`Unhandled promise rejection: ${s.message}`);return}o(`Unhandled promise rejection: ${String(s)}`)};return process.on("SIGINT",r),process.on("SIGTERM",r),process.on("uncaughtException",n),process.on("unhandledRejection",i),()=>{process.off("SIGINT",r),process.off("SIGTERM",r),process.off("uncaughtException",n),process.off("unhandledRejection",i)}}var _r=t=>t.charAt(0).toUpperCase()+t.slice(1),k=t=>t.replace(/-([a-z])/g,(o,e)=>e.toUpperCase()),N=t=>_r(k(t));import jr from"ora";var g=jr();import Fr from"degit";var bt=async t=>{let o=A("Downloading template...");try{await Fr("teispace/nextjs-starter",{cache:!1,force:!0,verbose:!0}).clone(t),o.succeed("Template downloaded successfully.")}catch(e){throw o.fail("Failed to download template."),e}};P();import Dr from"node:path";T();var b={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 kt=async(t,o)=>{let e=A("Configuring package.json...");try{let r=o.gitRemote,n=o.gitHomepage,i=o.gitIssues;o.gitRemote&&(o.gitRemote.startsWith("git@github.com:")&&(r=o.gitRemote.replace("git@github.com:","https://github.com/").replace(/\.git$/,"")),n||(n=`${r.replace(/\.git$/,"")}#readme`),i||(i=`${r.replace(/\.git$/,"")}/issues`),r.endsWith(".git")||(r=`${r}.git`)),await me(Dr.join(t,a.PACKAGE_JSON),s=>(s.name=o.projectName,s.version=o.version,s.description=o.description,s.author=o.author,delete s.packageManager,o.gitRemote?(n&&(s.homepage=n),i&&(s.bugs={url:i}),r&&(s.repository={type:"git",url:r})):(delete s.homepage,delete s.bugs,delete s.repository),o.redux||(delete s.dependencies[b.REDUX_TOOLKIT],delete s.dependencies[b.REACT_REDUX],delete s.dependencies[b.REDUX_PERSIST]),o.httpClient!=="none"||o.reactSecureStorage||delete s.dependencies[b.REACT_SECURE_STORAGE],o.i18n||delete s.dependencies[b.NEXT_INTL],o.darkMode||delete s.dependencies[b.NEXT_THEMES],o.httpClient==="none"?delete s.dependencies[b.AXIOS]:o.httpClient==="fetch"&&delete s.dependencies[b.AXIOS],s)),e.succeed("package.json configured.")}catch(r){throw e.fail("Failed to configure package.json."),r}};P();T();Re();import E from"node:path";var jt=async(t,o)=>{let e=E.join(t,a.HTTP_UTILS),r=o.httpClient!=="none"||!!o.reactSecureStorage;o.httpClient==="none"?await Ur(t,e,r):o.httpClient==="axios"?await Xr(t,e):o.httpClient==="fetch"&&await Jr(t,e)},Ur=async(t,o,e)=>{await h(E.join(t,a.AXIOS_CLIENT)),await h(E.join(t,a.FETCH_CLIENT)),e?(await u(E.join(o,"index.ts"),`export * from './token-store';
15
- `),await w(E.join(t,a.CLIENT_UTILS)),await ae(t,[])):(await h(o),await Yr(t),await w(E.join(t,a.APP_APIS)),await zr(t)),await Wr(t),await h(E.join(t,a.ERRORS_DIR)),e||(await h(E.join(t,a.COMMON_TYPES_DIR)),await h(E.join(t,a.UTILITY_TYPES_DIR)),await Br(t))},Xr=async(t,o)=>{await h(E.join(t,a.FETCH_CLIENT));let e=await d(E.join(o,"index.ts"));e=e.replace(/export .* from '\.\/fetch-client';\n/g,""),await u(E.join(o,"index.ts"),e);let r=E.join(t,a.HTTP_TYPES);if(l(r)){let n=await d(r);n=n.replace(/export interface FetchClientOptions \{[\s\S]*?\}\n\n/,""),n=n.replace(/export interface ExtendedRequestInit extends RequestInit \{[\s\S]*?\}\n\n/,""),await u(r,n)}},Jr=async(t,o)=>{await h(E.join(t,a.AXIOS_CLIENT));let e=await d(E.join(o,"index.ts"));e=e.replace(/export .* from '\.\/axios-client';\n/g,""),await u(E.join(o,"index.ts"),e),await ae(t,["fetch"]);let r=E.join(t,a.HTTP_TYPES);if(l(r)){let n=await d(r);n=n.replace(/export interface AxiosClientOptions \{[\s\S]*?\}\n\n/,""),await u(r,n)}},Yr=async t=>{let o=E.join(t,a.UTILS_INDEX);if(l(o)){let e=await d(o);e=e.replace(/export \* from '\.\/http';\n/,""),await u(o,e)}},zr=async t=>{let o=E.join(t,a.CONFIG_INDEX);if(l(o)){let e=await d(o);e=e.replace(/export \* from '\.\/app-apis';\n/,""),await u(o,e)}},Wr=async t=>{let o=E.join(t,a.CONSTANTS);if(l(o)){let e=await d(o);e=e.replace(/export const API_RESPONSE_DATA_KEY = 'data';\n/,""),e=e.replace(/export const SAVE_AUTH_TOKENS = false;\n/,""),await u(o,e)}},Br=async t=>{let o=E.join(t,a.TYPES_INDEX);if(l(o)){let e=await d(o);e=e.replace(/export \* from '\.\/utility';\n/,""),e=e.replace(/export \* from '\.\/common';\n/,""),await u(o,e)}};P();T();import ce from"node:path";var Ft=async(t,o)=>{o.redux||(await h(ce.join(t,a.STORE)),await h(ce.join(t,a.COUNTER_FEATURE)),await w(ce.join(t,a.STORE_PROVIDER)),await Vr(t),await qr(t))},Vr=async t=>{let o=ce.join(t,a.PROVIDERS_INDEX),e=await d(o);e=e.replace(/export \* from '\.\/StoreProvider';\n/,""),await u(o,e)},qr=async t=>{let o=[ce.join(t,a.ROOT_PAGE),ce.join(t,a.LOCALE_PAGE)];for(let e of o)if(l(e)){let r=await d(e);r=r.replace(/import\s+\{\s*Counter\s*\}\s+from\s+['"]@\/features\/counter['"];\n?/,""),r=r.replace(/<Counter\s*\/>\n?/g,""),await u(e,r)}};P();T();import $e from"node:path";var Dt=async(t,o)=>{o.darkMode||(await w($e.join(t,a.THEME_PROVIDER)),await Kr(t),await Zr(t),o.i18n||await Qr(t))},Kr=async t=>{let o=$e.join(t,a.PROVIDERS_INDEX),e=await d(o);e=e.replace(/export \* from '\.\/CustomThemeProvider';\n/,""),await u(o,e)},Zr=async t=>{let o=$e.join(t,a.GLOBALS_CSS);if(l(o)){let e=await d(o);e=e.replace(/@custom-variant dark \(.*?\);\n\n/,""),e=e.replace(/@theme \{[\s\S]*?\}\n/,""),await u(o,e)}},Qr=async t=>{let o=$e.join(t,a.ROOT_LAYOUT);if(l(o)){let e=await d(o);e=e.replace(/bg-light dark:bg-dark /g,""),await u(o,e)}};P();T();import J from"node:path";var Lt=async(t,o)=>{o.i18n||(await ei(t),await ti(t),await oi(t),await ri(t))},ei=async t=>{await h(J.join(t,a.I18N_DIR)),await h(J.join(t,a.LOCALE_DIR)),await w(J.join(t,a.PROXY)),await w(J.join(t,a.MIDDLEWARE)),await w(J.join(t,a.I18N_TYPES)),await w(J.join(t,a.APP_LOCALES))},ti=async t=>{let o=J.join(t,a.TYPES_INDEX);if(l(o)){let r=await d(o);r=r.replace(/export \* from '\.\/i18n';\n/,""),await u(o,r)}let e=J.join(t,a.CONFIG_INDEX);if(l(e)){let r=await d(e);r=r.replace(/export \* from '\.\/app-locales';\n/,""),await u(e,r)}},oi=async t=>{let o=J.join(t,a.NEXT_CONFIG);if(l(o)){let e=await d(o);e=e.replace(/import createNextIntlPlugin from 'next-intl\/plugin';\n/,""),e=e.replace(/const withNextIntl = createNextIntlPlugin\(\);\n/,""),e=e.replace(/export default withNextIntl\(nextConfig\);/,"export default nextConfig;"),await u(o,e)}},ri=async t=>{let o=J.join(t,a.COUNTER_COMPONENT);if(l(o)){let e=await d(o);e=e.replace(/import\s+\{\s*useTranslations\s*\}\s+from\s+['"]next-intl['"];\n/,""),e=e.replace(/\s*const\s+t\s*=\s*useTranslations\(['"]Count['"]\);\n/,""),e=e.replace(/\{t\('currentCount',\s*\{\s*count:\s*value\s*\}\)\}/g,"{value}"),e=e.replace(/\{t\(['"]increment['"]\)\}/g,"Increment"),e=e.replace(/\{t\(['"]decrement['"]\)\}/g,"Decrement"),e=e.replace(/\{t\(['"]reset['"]\)\}/g,"Reset"),await u(o,e)}};P();T();import K from"node:path";var Ht=async(t,o)=>{o.httpClient!=="none"||o.reactSecureStorage||await h(K.join(t,a.STORAGE_SERVICE))},Gt=async t=>{await w(K.join(t,a.LICENSE))},Mt=async t=>{await w(K.join(t,a.CHANGELOG))},Ut=async t=>{await w(K.join(t,a.NVM_RC)),await w(K.join(t,a.NPM_RC))},Xt=async t=>{await h(K.join(t,a.CLAUDE_DIR)),await h(K.join(t,a.DOCS_DIR)),await h(K.join(t,a.VSCODE_DIR))};var Jt=async(t,o)=>{let e=A("Customizing features...");try{await jt(t,o),await Ht(t,o),await Ft(t,o),await Dt(t,o),await Lt(t,o),await Gt(t),await Mt(t),await Ut(t),await Xt(t),e.succeed("Features customized.")}catch(r){throw e.fail("Failed to customize features."),r}};P();T();import Ke from"node:path";var Yt=async(t,o)=>{let e=[],r=[];o.redux&&(e.push("import { StoreProvider } from '@/providers';"),r.push("StoreProvider")),o.darkMode&&(e.push("import { CustomThemeProvider } from '@/providers';"),r.push("CustomThemeProvider")),o.i18n&&(e.push("import { NextIntlClientProvider, AbstractIntlMessages } from 'next-intl';"),e.push("import { SupportedLocale } from '@/types/i18n';"));let n=`'use client';
16
- ${e.join(`
17
- `)}
2
+ var Yo=Object.defineProperty;var ue=(e,r)=>()=>(e&&(r=e(e=0)),r);var Ye=(e,r)=>{for(var t in r)Yo(e,t,{get:r[t],enumerable:!0})};import{existsSync as Ve}from"node:fs";import ce from"node:fs/promises";import zt from"node:path";var d,u,A,S,P,j,l,T=ue(()=>{"use strict";d=async e=>ce.readFile(e,"utf-8"),u=async(e,r)=>{await ce.mkdir(zt.dirname(e),{recursive:!0}),await ce.writeFile(e,r,"utf-8")},A=async(e,r)=>{await ce.mkdir(zt.dirname(r),{recursive:!0}),await ce.copyFile(e,r)},S=async e=>{Ve(e)&&await ce.unlink(e)},P=async e=>{Ve(e)&&await ce.rm(e,{recursive:!0,force:!0})},j=async(e,r)=>{let t=await d(e),o=JSON.parse(t),n=r(o);await u(e,JSON.stringify(n,null,2))},l=e=>Ve(e)});var Kt={};Ye(Kt,{PROJECT_PATHS:()=>a});var a,C=ue(()=>{"use strict";a={NEXT_CONFIG:"next.config.ts",POSTCSS_CONFIG:"postcss.config.mjs",BIOME_CONFIG:"biome.json",VITEST_CONFIG:"vitest.config.ts",TEST_DIR:"test",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",AGENTS_MD:"AGENTS.md",CLAUDE_MD:"CLAUDE.md",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",AXIOS_CLIENT_FILE:"src/lib/utils/http/axios-client/index.ts",FETCH_CLIENT_FILE:"src/lib/utils/http/fetch-client/index.ts",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",SCRIPTS_DIR:"scripts",DOCS_DIR:"docs",CLAUDE_DIR:".claude",VSCODE_DIR:".vscode"}});var Qt={};Ye(Qt,{cleanupHttpTypes:()=>fe,isFileUsed:()=>Si,isStringUsed:()=>wi,migrateClientUsages:()=>rt,removeHttpExports:()=>ot,updateConfigIndex:()=>tt,updateHttpIndex:()=>Ze,updateTypesIndex:()=>et,updateUtilsIndex:()=>Qe});import{exec as Pi}from"node:child_process";import _ from"node:path";import{promisify as Ti}from"node:util";var qe,Ze,Qe,et,tt,fe,rt,ot,Si,wi,je=ue(()=>{"use strict";C();T();qe=Ti(Pi),Ze=async(e,r)=>{let t=_.join(e,a.HTTP_UTILS,"index.ts");if(l(t)){let o=await d(t);o=o.replace(/export .* from '\.\/axios-client';?\n?/g,""),o=o.replace(/export .* from '\.\/fetch-client';?\n?/g,""),r.includes("fetch")&&!o.includes("fetch-client")&&(o+=`export * from './fetch-client';
3
+ `),r.includes("axios")&&!o.includes("axios-client")&&(o+=`export * from './axios-client';
4
+ `),await u(t,o)}},Qe=async e=>{let r=_.join(e,a.UTILS_INDEX);if(l(r)){let t=await d(r);t.includes("./http")||(t+=`export * from './http';
5
+ `,await u(r,t))}},et=async e=>{let r=_.join(e,a.TYPES_INDEX);if(l(r)){let t=await d(r);t.includes("./common")||(t+=`export * from './common';
6
+ `),t.includes("./utility")||(t+=`export * from './utility';
7
+ `),await u(r,t)}},tt=async e=>{let r=_.join(e,a.CONFIG_INDEX);if(l(r)){let t=await d(r);t.includes("./app-apis")||(t+=`export * from './app-apis';
8
+ `,await u(r,t))}},fe=async(e,r)=>{let t=_.join(e,a.HTTP_TYPES);if(l(t)){let o=await d(t);r.includes("axios")||(o=o.replace(/declare module 'axios'\s*\{\s*export interface AxiosRequestConfig\s*\{[\s\S]*?\}\s*\}/g,""),o=`${o.replace(/\n\s*\n/g,`
9
+
10
+ `).trim()}
11
+ `,await u(t,o))}},rt=async(e,r,t)=>{if(r===t)return;let o=r==="fetch"?"fetchClient":"axiosClient",n=t==="fetch"?"fetchClient":"axiosClient",i=r==="fetch"?"fetch-client":"axios-client",s=t==="fetch"?"fetch-client":"axios-client",c=_.join(e,"src");try{let p=`grep -rl "${o}" "${c}" --include="*.ts" --include="*.tsx" || true`,{stdout:f}=await qe(p);if(!f.trim())return;let g=f.trim().split(`
12
+ `).filter(y=>y);for(let y of g){if(!l(y))continue;let x=await d(y),X=!1,Xe=new RegExp(`(import\\s*\\{[^}]*?)\\b${o}\\b([^}]*?\\}\\s*from\\s*['"][^'"]*?/http['"])`,"g");Xe.test(x)&&(x=x.replace(Xe,`$1${n}$2`),X=!0);let Ae=new RegExp(`import\\s+${o}\\s+from\\s+['"]([^'"]*?)/${i}['"]`,"g");Ae.test(x)&&(x=x.replace(Ae,`import ${n} from '$1/${s}'`),X=!0);let Oe=new RegExp(`\\b${o}\\b(?=\\.)`,"g");Oe.test(x)&&(x=x.replace(Oe,n),X=!0);let Ut=new RegExp(`\\b${o}\\b(?![.\\w])`,"g");Ut.test(x)&&(x=x.replace(Ut,n),X=!0),X&&await u(y,x)}}catch(p){console.warn("Warning: Could not scan for HTTP client usages:",p)}},ot=async e=>{let r=_.join(e,a.UTILS_INDEX);if(l(r)){let o=await d(r);o=o.replace(/^\s*export\s+\*\s+from\s+['"]\.\/http['"];?.*$/gm,""),await u(r,o)}let t=_.join(e,a.TYPES_INDEX);if(l(t)){let o=await d(t),n=_.join(e,a.COMMON_TYPES_DIR);if(!l(n))o=o.replace(/^\s*export\s+\*\s+from\s+['"]\.\/common['"];?.*$/gm,"");else{let i=_.join(n,"index.ts");if(l(i)){let s=await d(i);s=s.replace(/^\s*export\s+\*\s+from\s+['"]\.\/http\.types['"];?.*$/gm,""),await u(i,s)}}l(_.join(e,a.UTILITY_TYPES_DIR))||(o=o.replace(/^\s*export\s+\*\s+from\s+['"]\.\/utility['"];?.*$/gm,"")),await u(t,o)}},Si=async(e,r,t=[])=>{let o=_.join(e,"src"),i=`grep -r "from ['\\"].*${r.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}.*['\\"]" "${o}" --include="*.ts" --include="*.tsx" || true`;try{let{stdout:s}=await qe(i);return s.trim()?s.trim().split(`
13
+ `).filter(f=>{let[g]=f.split(":"),y=_.resolve(e,g);return!t.some(x=>!!(y===x||y.startsWith(x+_.sep)))}).length>0:!1}catch(s){return console.warn(`Warning: Failed to check usage for ${r}:`,s),!0}},wi=async(e,r,t=[])=>{let o=_.join(e,"src"),i=`grep -r "${r.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}" "${o}" --include="*.ts" --include="*.tsx" || true`;try{let{stdout:s}=await qe(i);return s.trim()?s.trim().split(`
14
+ `).filter(f=>{let[g]=f.split(":"),y=_.resolve(e,g);return!t.some(x=>!!(y===x||y.startsWith(x+_.sep)))}).length>0:!1}catch(s){return console.warn(`Warning: Failed to check usage for string ${r}:`,s),!0}}});import{existsSync as Vi}from"node:fs";import{access as Ki}from"node:fs/promises";import Pr from"node:path";var oe,De,Tr=ue(()=>{"use strict";oe=async(e,r,t)=>{try{return await Ki(Pr.join(e,t,r)),!0}catch{return!1}},De=(e,r,t)=>Vi(Pr.join(e,r,t))});import{access as st,readFile as Wi}from"node:fs/promises";import Le from"node:path";var O,Sr=ue(()=>{"use strict";O=async e=>{try{let r=Le.join(e,"package.json"),t=await Wi(r,"utf-8"),o=JSON.parse(t),n={...o.dependencies,...o.devDependencies},i=!!(n["@reduxjs/toolkit"]&&n["react-redux"]),s=!!n["next-intl"],c=!!n.axios,p=!1,f=Le.join(e,"src","lib","utils","http","axios-client");try{await st(f)}catch{c=!1}let g=Le.join(e,"src","lib","utils","http","fetch-client");try{await st(g),p=!0}catch{p=!1}let y;c&&p?y="both":c?y="axios":p?y="fetch":y="none";let x=!!n.vitest;if(!x)try{await st(Le.join(e,"vitest.config.ts")),x=!0}catch{}return{hasRedux:i,httpClient:y,hasI18n:s,hasTests:x}}catch(r){throw new Error(`Failed to detect project setup: ${r}`,{cause:r})}}});var wr={};Ye(wr,{detectProjectSetup:()=>O,directoryExists:()=>oe,fileExistsAt:()=>De});var U=ue(()=>{"use strict";Tr();Sr()});import{Command as _s}from"commander";import nt from"node:path";import re from"picocolors";function Mt(e){let{logger:r=s=>console.error(s),exitOnCancel:t=process.env.NODE_ENV!=="test"}=e??{},o=()=>{console.log(""),console.log(""),r("Setup cancelled by user"),console.log(""),t&&process.exit(0)},n=s=>{if(s!==null&&typeof s=="object"&&"code"in s&&s.code==="ERR_USE_AFTER_CLOSE"){o();return}if(s instanceof Error){r(`Uncaught exception: ${s.message}`);return}r(`Uncaught exception: ${String(s)}`)},i=s=>{if(s instanceof Error){r(`Unhandled promise rejection: ${s.message}`);return}r(`Unhandled promise rejection: ${String(s)}`)};return process.on("SIGINT",o),process.on("SIGTERM",o),process.on("uncaughtException",n),process.on("unhandledRejection",i),()=>{process.off("SIGINT",o),process.off("SIGTERM",o),process.off("uncaughtException",n),process.off("unhandledRejection",i)}}import Y from"picocolors";var Vo={reset:e=>e,red:Y.red,green:Y.green,yellow:Y.yellow,blue:Y.blue,cyan:Y.cyan,magenta:Y.magenta,white:Y.white,gray:Y.gray,bright:Y.bold,dim:Y.dim};function ae(e,r="reset"){let t=Vo[r]??(o=>o);console.log(t(e))}function _e(e){ae(`\u2716 ${e}`,"red")}var w=_e;function m(e){ae(e)}function Jt(){console.log(""),ae("\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"),ae("\u2551 \u2551","cyan"),ae("\u2551 \u{1F680} Create Teispace Next.js App \u{1F680} \u2551","cyan"),ae("\u2551 \u2551","cyan"),ae("\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("")}import Ko from"ora";function I(e="",r){let t=Ko({text:e,...r});return t.start(),t}var Wo=e=>e.charAt(0).toUpperCase()+e.slice(1),$=e=>e.replace(/-([a-z])/g,(r,t)=>t.toUpperCase()),R=e=>Wo($(e));import qo from"ora";var h=qo();T();import{exec as Zo}from"node:child_process";import{promisify as Qo}from"node:util";var W=Qo(Zo),Bt=async(e,r,t)=>{try{if(await W("git init",{cwd:e}),await W("git add .",{cwd:e}),await W('git commit -m "Initial commit from @teispace/next-maker"',{cwd:e}),r&&(await W(`git remote add origin ${r}`,{cwd:e}),t)){await W("git fetch origin",{cwd:e});let o="main";try{await W("git show-branch origin/main",{cwd:e})}catch{try{await W("git show-branch origin/master",{cwd:e}),o="master"}catch{o="main"}}await W(`git merge origin/${o} --allow-unrelated-histories -X ours`,{cwd:e}),await W(`git push origin HEAD:${o}`,{cwd:e})}}catch(o){console.warn("Failed to initialize git repository",o)}};import{exec as ei}from"node:child_process";import{promisify as ti}from"node:util";var he=ti(ei),Xt=async(e,r)=>{let t=`${r} install`;try{await he(t,{cwd:e})}catch(o){throw new Error(`Failed to install dependencies with ${r}: ${o}`,{cause:o})}},G=async(e,r,t)=>{let o=r==="npm"?`${r} run ${t}`:`${r} ${t}`;try{await he(o,{cwd:e})}catch(n){console.warn(`Warning: Failed to run script '${t}': ${n}`)}},ri=()=>{let e=process.env.npm_config_user_agent;if(e){if(e.startsWith("yarn"))return"yarn";if(e.startsWith("pnpm"))return"pnpm";if(e.startsWith("bun"))return"bun"}return"npm"},D=async e=>{let{existsSync:r}=await import("node:fs"),t=await import("node:path");return r(t.join(e,"pnpm-lock.yaml"))?"pnpm":r(t.join(e,"yarn.lock"))?"yarn":r(t.join(e,"bun.lockb"))?"bun":r(t.join(e,"package-lock.json"))?"npm":ri()},oi=async(e,r,t)=>{if(t.length===0)return;let n=`${Yt(r)} ${t.join(" ")}`;try{await he(n,{cwd:e})}catch(i){throw new Error(`Failed to install packages with ${r}: ${i}`,{cause:i})}},Yt=e=>{switch(e){case"npm":return"npm install";case"yarn":return"yarn add";case"pnpm":return"pnpm add";case"bun":return"bun add";default:return"npm install"}},H=async(e,r)=>{let t=await D(e);await oi(e,t,[r])},ii=e=>{switch(e){case"npm":return"--save-dev";case"yarn":case"pnpm":case"bun":return"-D";default:return"--save-dev"}},Ke=async(e,r,t)=>{if(t.length===0)return;let o=Yt(r),n=ii(r),i=`${o} ${n} ${t.join(" ")}`;try{await he(i,{cwd:e})}catch(s){throw new Error(`Failed to install dev packages with ${r}: ${s}`,{cause:s})}},ke=async(e,r)=>{let t=await D(e);await Ke(e,t,[r])},ni=async(e,r,t)=>{if(t.length===0)return;let n=`${si(r)} ${t.join(" ")}`;try{await he(n,{cwd:e})}catch(i){throw new Error(`Failed to uninstall packages with ${r}: ${i}`,{cause:i})}},si=e=>{switch(e){case"npm":return"npm uninstall";case"yarn":return"yarn remove";case"pnpm":return"pnpm remove";case"bun":return"bun remove";default:return"npm uninstall"}},We=async(e,r)=>{let t=await D(e);await ni(e,t,[r])};import ai from"enquirer";var{prompt:ci}=ai,Vt=async e=>{let r=await ci([{type:"input",name:"projectName",message:"What is the project name?",initial:e||"my-app",skip:!!e,validate:t=>/^[a-z0-9-_]+$/.test(t)?!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:t=>/^\d+\.\d+\.\d+$/.test(t)?!0:"Version must be a valid semantic version (x.y.z)."},{type:"input",name:"email",message:"Support email:",initial:"support@example.com",validate:t=>/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t)?!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):",initial:""},{type:"confirm",name:"pushToRemote",message:"Would you like to push the changes to the remote repository?",initial:!0,skip:function(){return!this.state?.answers?.gitRemote}},{type:"input",name:"gitIssues",message:"GitHub issues URL (optional):",initial:"",skip:function(){return!this.state?.answers?.gitRemote},validate:t=>t?/^https:\/\/github\.com\/[\w-]+\/[\w.-]+\/issues$/.test(t)?!0:"Please enter a valid GitHub issues URL (e.g., https://github.com/user/repo/issues)":!0},{type:"input",name:"gitHomepage",message:"GitHub homepage URL (optional):",initial:"",skip:function(){return!this.state?.answers?.gitRemote},validate:t=>t?/^https:\/\/github\.com\/[\w-]+\/[\w.-]+#readme$/.test(t)?!0:"Please enter a valid GitHub homepage URL (e.g., https://github.com/user/repo#readme)":!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 t=this.state?.answers??this.enquirer?.answers??{};return!!(t.httpClient&&t.httpClient!=="none")}},{type:"confirm",name:"darkMode",message:"Do you want to include Dark Mode (Tailwind + @teispace/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:"confirm",name:"tests",message:"Do you want to include testing setup (Vitest + React Testing Library)?",initial:!0},{type:"confirm",name:"reactCompiler",message:"Do you want to enable the React Compiler?",initial:!0},{type:"confirm",name:"bundleAnalyzer",message:"Do you want to include @next/bundle-analyzer?",initial:!1},{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:t=>/^[a-zA-Z0-9][a-zA-Z0-9_.-]*$/.test(t)?!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:t=>/^[a-z0-9]+(?:[._-][a-z0-9]+)*$/.test(t)?!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:t=>/^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,127}$/.test(t)?!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(r.company=r.author,r.gitRemote&&!r.gitHomepage){let t=r.gitRemote.replace("git@github.com:","https://github.com/").replace(/\.git$/,"");r.gitHomepage=`${t}#readme`,r.gitIssues=`${t}/issues`}return r};T();import pi from"node:path";var ee=async(e,r)=>{let t=li(r);await u(pi.join(e,"test/test-utils.tsx"),t)},li=({redux:e,i18n:r})=>e&&r?mi:e?di:r?ui:fi,mi=`import { type RenderOptions, render } from '@testing-library/react';
15
+ import { NextIntlClientProvider } from 'next-intl';
16
+ import type { ReactElement, ReactNode } from 'react';
17
+ import { Provider } from 'react-redux';
18
+ import { type AppState, type AppStore, makeStore } from '@/store';
19
+ import type { SupportedLocale } from '@/types/i18n';
20
+
21
+ type TestProvidersProps = {
22
+ children: ReactNode;
23
+ store?: AppStore;
24
+ preloadedState?: Partial<AppState>;
25
+ messages?: Record<string, unknown>;
26
+ locale?: SupportedLocale;
27
+ };
18
28
 
19
- export const RootProvider = ({
29
+ export function TestProviders({
20
30
  children,
21
- ${o.i18n?`locale,
22
- messages,`:""}
23
- }: {
24
- children: React.ReactNode;
25
- ${o.i18n?`locale: SupportedLocale;
26
- messages: AbstractIntlMessages;`:""}
27
- }) => {
31
+ store,
32
+ preloadedState,
33
+ messages = {},
34
+ locale = 'en',
35
+ }: TestProvidersProps) {
36
+ const testStore = store ?? makeStore(preloadedState);
37
+
28
38
  return (
29
- `,i="{children}";o.i18n&&(i=`<NextIntlClientProvider locale={locale} messages={messages}>
39
+ <Provider store={testStore}>
40
+ <NextIntlClientProvider locale={locale} messages={messages} timeZone="UTC">
41
+ {children}
42
+ </NextIntlClientProvider>
43
+ </Provider>
44
+ );
45
+ }
46
+
47
+ type ExtendedRenderOptions = Omit<RenderOptions, 'wrapper'> & {
48
+ store?: AppStore;
49
+ preloadedState?: Partial<AppState>;
50
+ messages?: Record<string, unknown>;
51
+ locale?: SupportedLocale;
52
+ };
53
+
54
+ export function renderWithProviders(
55
+ ui: ReactElement,
56
+ { store, preloadedState, messages, locale, ...renderOptions }: ExtendedRenderOptions = {},
57
+ ) {
58
+ const testStore = store ?? makeStore(preloadedState);
59
+
60
+ return {
61
+ store: testStore,
62
+ ...render(ui, {
63
+ wrapper: ({ children }) => (
64
+ <TestProviders store={testStore} messages={messages} locale={locale}>
65
+ {children}
66
+ </TestProviders>
67
+ ),
68
+ ...renderOptions,
69
+ }),
70
+ };
71
+ }
72
+
73
+ export * from '@testing-library/react';
74
+ export { default as userEvent } from '@testing-library/user-event';
75
+ `,di=`import { type RenderOptions, render } from '@testing-library/react';
76
+ import type { ReactElement, ReactNode } from 'react';
77
+ import { Provider } from 'react-redux';
78
+ import { type AppState, type AppStore, makeStore } from '@/store';
79
+
80
+ type TestProvidersProps = {
81
+ children: ReactNode;
82
+ store?: AppStore;
83
+ preloadedState?: Partial<AppState>;
84
+ };
85
+
86
+ export function TestProviders({ children, store, preloadedState }: TestProvidersProps) {
87
+ const testStore = store ?? makeStore(preloadedState);
88
+
89
+ return <Provider store={testStore}>{children}</Provider>;
90
+ }
91
+
92
+ type ExtendedRenderOptions = Omit<RenderOptions, 'wrapper'> & {
93
+ store?: AppStore;
94
+ preloadedState?: Partial<AppState>;
95
+ };
96
+
97
+ export function renderWithProviders(
98
+ ui: ReactElement,
99
+ { store, preloadedState, ...renderOptions }: ExtendedRenderOptions = {},
100
+ ) {
101
+ const testStore = store ?? makeStore(preloadedState);
102
+
103
+ return {
104
+ store: testStore,
105
+ ...render(ui, {
106
+ wrapper: ({ children }) => <TestProviders store={testStore}>{children}</TestProviders>,
107
+ ...renderOptions,
108
+ }),
109
+ };
110
+ }
111
+
112
+ export * from '@testing-library/react';
113
+ export { default as userEvent } from '@testing-library/user-event';
114
+ `,ui=`import { type RenderOptions, render } from '@testing-library/react';
115
+ import { NextIntlClientProvider } from 'next-intl';
116
+ import type { ReactElement, ReactNode } from 'react';
117
+ import type { SupportedLocale } from '@/types/i18n';
118
+
119
+ type TestProvidersProps = {
120
+ children: ReactNode;
121
+ messages?: Record<string, unknown>;
122
+ locale?: SupportedLocale;
123
+ };
124
+
125
+ export function TestProviders({ children, messages = {}, locale = 'en' }: TestProvidersProps) {
126
+ return (
127
+ <NextIntlClientProvider locale={locale} messages={messages} timeZone="UTC">
128
+ {children}
129
+ </NextIntlClientProvider>
130
+ );
131
+ }
132
+
133
+ type ExtendedRenderOptions = Omit<RenderOptions, 'wrapper'> & {
134
+ messages?: Record<string, unknown>;
135
+ locale?: SupportedLocale;
136
+ };
137
+
138
+ export function renderWithProviders(
139
+ ui: ReactElement,
140
+ { messages, locale, ...renderOptions }: ExtendedRenderOptions = {},
141
+ ) {
142
+ return render(ui, {
143
+ wrapper: ({ children }) => (
144
+ <TestProviders messages={messages} locale={locale}>
145
+ {children}
146
+ </TestProviders>
147
+ ),
148
+ ...renderOptions,
149
+ });
150
+ }
151
+
152
+ export * from '@testing-library/react';
153
+ export { default as userEvent } from '@testing-library/user-event';
154
+ `,fi=`import { type RenderOptions, render } from '@testing-library/react';
155
+ import type { ReactElement, ReactNode } from 'react';
156
+
157
+ type TestProvidersProps = {
158
+ children: ReactNode;
159
+ };
160
+
161
+ export function TestProviders({ children }: TestProvidersProps) {
162
+ return <>{children}</>;
163
+ }
164
+
165
+ type ExtendedRenderOptions = Omit<RenderOptions, 'wrapper'>;
166
+
167
+ export function renderWithProviders(ui: ReactElement, options: ExtendedRenderOptions = {}) {
168
+ return render(ui, {
169
+ wrapper: ({ children }) => <TestProviders>{children}</TestProviders>,
170
+ ...options,
171
+ });
172
+ }
173
+
174
+ export * from '@testing-library/react';
175
+ export { default as userEvent } from '@testing-library/user-event';
176
+ `;import Wt from"node:path";var E={REDUX_TOOLKIT:"@reduxjs/toolkit",REACT_REDUX:"react-redux",REDUX:"redux",REDUX_PERSIST:"redux-persist",REACT_SECURE_STORAGE:"react-secure-storage",NEXT_INTL:"next-intl",NEXT_THEMES:"@teispace/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",VITEST:"vitest",JSDOM:"jsdom",VITE_PLUGIN_REACT:"@vitejs/plugin-react",TESTING_LIBRARY_DOM:"@testing-library/dom",TESTING_LIBRARY_JEST_DOM:"@testing-library/jest-dom",TESTING_LIBRARY_REACT:"@testing-library/react",TESTING_LIBRARY_USER_EVENT:"@testing-library/user-event",REACT_COMPILER_BABEL:"babel-plugin-react-compiler",NEXT_BUNDLE_ANALYZER:"@next/bundle-analyzer"};C();T();var qt=async(e,r)=>{if(r.bundleAnalyzer)return;let t=Wt.join(e,a.NEXT_CONFIG);if(l(t)){let o=await d(t);o=o.replace(/import\s+withBundleAnalyzer\s+from\s+'@next\/bundle-analyzer';\n/,""),o=o.replace(/const\s+bundleAnalyzer\s*=\s*withBundleAnalyzer\(\{[\s\S]*?\}\);\n+/,""),o=o.replace(/bundleAnalyzer\(([^)]*)\)/,"$1"),await u(t,o)}await j(Wt.join(e,a.PACKAGE_JSON),o=>(o.devDependencies&&delete o.devDependencies[E.NEXT_BUNDLE_ANALYZER],o.scripts&&delete o.scripts.analyze,o))};C();T();import xe from"node:path";var Zt=async(e,r)=>{r.darkMode||(await S(xe.join(e,a.THEME_PROVIDER)),await gi(e),await hi(e),await yi(e))},gi=async e=>{let r=xe.join(e,a.PROVIDERS_INDEX),t=await d(r);t=t.replace(/export \* from '\.\/CustomThemeProvider';\n/,""),await u(r,t)},hi=async e=>{let r=xe.join(e,a.GLOBALS_CSS);if(l(r)){let t=await d(r);t=t.replace(/@custom-variant dark \(.*?\);\n\n/,""),t=t.replace(/@theme \{[\s\S]*?\}\n/,""),await u(r,t)}},xi=e=>e.replace(/\bbg-light\b\s?/g,"").replace(/\bdark:bg-dark\b\s?/g,"").replace(/\s{2,}/g," ").replace(/suppressHydrationWarning=\{true\}/g,""),yi=async e=>{let r=[xe.join(e,a.ROOT_LAYOUT),xe.join(e,"src/app/[locale]/layout.tsx")];for(let t of r)if(l(t)){let o=await d(t),n=xi(o);n!==o&&await u(t,n)}};C();T();je();import N from"node:path";var er=async(e,r)=>{let t=N.join(e,a.HTTP_UTILS),o=r.httpClient!=="none"||!!r.reactSecureStorage;r.httpClient==="none"?await vi(e,t,o):r.httpClient==="axios"?await Ci(e,t):r.httpClient==="fetch"&&await Ei(e,t)},vi=async(e,r,t)=>{await P(N.join(e,a.AXIOS_CLIENT)),await P(N.join(e,a.FETCH_CLIENT)),t?(await u(N.join(r,"index.ts"),`export * from './token-store';
177
+ `),await S(N.join(e,a.CLIENT_UTILS)),await fe(e,[])):(await P(r),await Ii(e),await S(N.join(e,a.APP_APIS)),await Ri(e)),await Ni(e),await P(N.join(e,a.ERRORS_DIR)),t||(await P(N.join(e,a.COMMON_TYPES_DIR)),await P(N.join(e,a.UTILITY_TYPES_DIR)),await bi(e))},Ci=async(e,r)=>{await P(N.join(e,a.FETCH_CLIENT));let t=await d(N.join(r,"index.ts"));t=t.replace(/export .* from '\.\/fetch-client';\n/g,""),await u(N.join(r,"index.ts"),t);let o=N.join(e,a.HTTP_TYPES);if(l(o)){let n=await d(o);n=n.replace(/export interface FetchClientOptions \{[\s\S]*?\}\n\n/,""),n=n.replace(/export interface ExtendedRequestInit extends RequestInit \{[\s\S]*?\}\n\n/,""),await u(o,n)}},Ei=async(e,r)=>{await P(N.join(e,a.AXIOS_CLIENT));let t=await d(N.join(r,"index.ts"));t=t.replace(/export .* from '\.\/axios-client';\n/g,""),await u(N.join(r,"index.ts"),t),await fe(e,["fetch"]);let o=N.join(e,a.HTTP_TYPES);if(l(o)){let n=await d(o);n=n.replace(/export interface AxiosClientOptions \{[\s\S]*?\}\n\n/,""),await u(o,n)}},Ii=async e=>{let r=N.join(e,a.UTILS_INDEX);if(l(r)){let t=await d(r);t=t.replace(/export \* from '\.\/http';\n/,""),await u(r,t)}},Ri=async e=>{let r=N.join(e,a.CONFIG_INDEX);if(l(r)){let t=await d(r);t=t.replace(/export \* from '\.\/app-apis';\n/,""),await u(r,t)}},Ni=async e=>{let r=N.join(e,a.CONSTANTS);if(l(r)){let t=await d(r);t=t.replace(/export const API_RESPONSE_DATA_KEY = 'data';\n/,""),t=t.replace(/export const SAVE_AUTH_TOKENS = false;\n/,""),await u(r,t)}},bi=async e=>{let r=N.join(e,a.TYPES_INDEX);if(l(r)){let t=await d(r);t=t.replace(/export \* from '\.\/utility';\n/,""),t=t.replace(/export \* from '\.\/common';\n/,""),await u(r,t)}};C();T();import L from"node:path";var tr=async(e,r)=>{r.i18n||(await Ai(e),await Oi(e),await _i(e),await ki(e),await $i(e))},$i=async e=>{let r=L.join(e,a.ENV_EXAMPLE);if(!l(r))return;let t=await d(r);t=t.replace(/#[^\n]*IANA time zone[\s\S]*?DEFAULT_TIMEZONE=[^\n]*\n?/,""),t=t.replace(/#[^\n]*Fallback locale[\s\S]*?DEFAULT_LOCALE=[^\n]*\n?/,""),t=t.replace(/^DEFAULT_TIMEZONE=.*\n?/m,""),t=t.replace(/^DEFAULT_LOCALE=.*\n?/m,""),await u(r,t)},Ai=async e=>{await P(L.join(e,a.I18N_DIR)),await P(L.join(e,a.LOCALE_DIR)),await S(L.join(e,a.PROXY)),await S(L.join(e,a.MIDDLEWARE)),await S(L.join(e,a.I18N_TYPES)),await S(L.join(e,a.APP_LOCALES))},Oi=async e=>{let r=L.join(e,a.TYPES_INDEX);if(l(r)){let o=await d(r);o=o.replace(/export \* from '\.\/i18n';\n/,""),await u(r,o)}let t=L.join(e,a.CONFIG_INDEX);if(l(t)){let o=await d(t);o=o.replace(/export \* from '\.\/app-locales';\n/,""),await u(t,o)}},_i=async e=>{let r=L.join(e,a.NEXT_CONFIG);if(l(r)){let t=await d(r);t=t.replace(/import createNextIntlPlugin from 'next-intl\/plugin';\n/,""),t=t.replace(/const withNextIntl = createNextIntlPlugin\(\);\n+/,""),t=t.replace(/withNextIntl\(([^)]+)\)/,"$1"),await u(r,t)}},ki=async e=>{let r=L.join(e,a.COUNTER_COMPONENT);if(l(r)){let n=await d(r);n=n.replace(/import\s+\{\s*useTranslations\s*\}\s+from\s+['"]next-intl['"];\n/,""),n=n.replace(/\s*const\s+t\s*=\s*useTranslations\(['"]Count['"]\);\n/,""),n=n.replace(/\{t\('currentCount',\s*\{\s*count:\s*value\s*\}\)\}/g,"Current Count: {value}"),n=n.replace(/\{t\(['"]increment['"]\)\}/g,"Increment"),n=n.replace(/\{t\(['"]decrement['"]\)\}/g,"Decrement"),n=n.replace(/\{t\(['"]reset['"]\)\}/g,"Reset"),await u(r,n)}let t=L.join(e,"src/features/counter/components/Counter.test.tsx"),o=L.join(e,"test/test-utils.tsx");await S(t),await S(o)};C();T();import te from"node:path";var rr=async(e,r)=>{r.httpClient!=="none"||r.reactSecureStorage||await P(te.join(e,a.STORAGE_SERVICE))},or=async e=>{await S(te.join(e,a.LICENSE))},ir=async e=>{await S(te.join(e,a.CHANGELOG))},nr=async e=>{await S(te.join(e,a.NVM_RC)),await S(te.join(e,a.NPM_RC))},sr=async e=>{await P(te.join(e,a.CLAUDE_DIR)),await P(te.join(e,a.DOCS_DIR)),await P(te.join(e,a.VSCODE_DIR))};import ar from"node:path";C();T();var cr=async(e,r)=>{if(r.reactCompiler)return;let t=ar.join(e,a.NEXT_CONFIG);if(l(t)){let o=await d(t);o=o.replace(/^\s*reactCompiler:\s*true,?\n/m,""),await u(t,o)}await j(ar.join(e,a.PACKAGE_JSON),o=>(o.devDependencies&&delete o.devDependencies[E.REACT_COMPILER_BABEL],o))};C();T();import pe from"node:path";var pr=async(e,r)=>{r.redux||(await P(pe.join(e,a.STORE)),await P(pe.join(e,a.COUNTER_FEATURE)),await S(pe.join(e,a.STORE_PROVIDER)),await S(pe.join(e,"test/test-utils.tsx")),await ji(e),await Fi(e))},ji=async e=>{let r=pe.join(e,a.PROVIDERS_INDEX),t=await d(r);t=t.replace(/export \* from '\.\/StoreProvider';\n/,""),await u(r,t)},Fi=async e=>{let r=[pe.join(e,a.ROOT_PAGE),pe.join(e,a.LOCALE_PAGE)];for(let t of r)if(l(t)){let o=await d(t);o=o.replace(/import\s+\{\s*Counter\s*\}\s+from\s+['"]@\/features\/counter['"];\n?/,""),o=o.replace(/<Counter\s*\/>\n?/g,""),await u(t,o)}};import Fe from"node:path";C();T();var Di=[E.VITEST,E.JSDOM,E.VITE_PLUGIN_REACT,E.TESTING_LIBRARY_DOM,E.TESTING_LIBRARY_JEST_DOM,E.TESTING_LIBRARY_REACT,E.TESTING_LIBRARY_USER_EVENT],lr=async(e,r)=>{r.tests||(await S(Fe.join(e,a.VITEST_CONFIG)),await P(Fe.join(e,a.TEST_DIR)),await S(Fe.join(e,"src/features/counter/components/Counter.test.tsx")),await j(Fe.join(e,a.PACKAGE_JSON),t=>{if(t.devDependencies)for(let o of Di)delete t.devDependencies[o];return t.scripts&&(delete t.scripts.test,delete t.scripts["test:watch"],delete t.scripts["test:coverage"],typeof t.scripts.validate=="string"&&(t.scripts.validate=t.scripts.validate.replace(/\s*&&\s*yarn\s+test(?![:\w])/,"").replace(/\byarn\s+test(?![:\w])\s*&&\s*/,""))),t}))};var mr=async(e,r)=>{let t=I("Customizing features...");try{await er(e,r),await rr(e,r),await pr(e,r),await Zt(e,r),await qt(e,r),await tr(e,r),await cr(e,r),await lr(e,r),await or(e),await ir(e),await nr(e),await sr(e),r.tests&&await ee(e,{redux:r.redux,i18n:r.i18n}),t.succeed("Features customized.")}catch(o){throw t.fail("Failed to customize features."),o}};import Li from"node:path";C();T();var dr=async(e,r)=>{let t=I("Configuring package.json...");try{let o=r.gitRemote,n=r.gitHomepage,i=r.gitIssues;r.gitRemote&&(r.gitRemote.startsWith("git@github.com:")&&(o=r.gitRemote.replace("git@github.com:","https://github.com/").replace(/\.git$/,"")),n||(n=`${o.replace(/\.git$/,"")}#readme`),i||(i=`${o.replace(/\.git$/,"")}/issues`),o.endsWith(".git")||(o=`${o}.git`)),await j(Li.join(e,a.PACKAGE_JSON),s=>(s.name=r.projectName,s.version=r.version,s.description=r.description,s.author=r.author,delete s.packageManager,r.gitRemote?(n&&(s.homepage=n),i&&(s.bugs={url:i}),o&&(s.repository={type:"git",url:o})):(delete s.homepage,delete s.bugs,delete s.repository),r.redux||(delete s.dependencies[E.REDUX_TOOLKIT],delete s.dependencies[E.REACT_REDUX],delete s.dependencies[E.REDUX],delete s.dependencies[E.REDUX_PERSIST]),r.httpClient!=="none"||r.reactSecureStorage||delete s.dependencies[E.REACT_SECURE_STORAGE],r.i18n||delete s.dependencies[E.NEXT_INTL],r.darkMode||delete s.dependencies[E.NEXT_THEMES],r.httpClient==="none"?delete s.dependencies[E.AXIOS]:r.httpClient==="fetch"&&delete s.dependencies[E.AXIOS],s)),t.succeed("package.json configured.")}catch(o){throw t.fail("Failed to configure package.json."),o}};import{readdir as ur}from"node:fs/promises";import b from"node:path";C();T();var fr=async(e,r)=>{await Gi(e,r),await Hi(e,r),await Ui(e,r),await Mi(e,r),await Ji(e,r),await zi(e,r),await Bi(e,r)},Gi=async(e,r)=>{r.preCommitHooks||(await P(b.join(e,a.HUSKY_DIR)),await S(b.join(e,a.COMMITLINT_CONFIG)),await S(b.join(e,a.LINTSTAGED_RC)),await j(b.join(e,a.PACKAGE_JSON),t=>(delete t.devDependencies[E.HUSKY],delete t.devDependencies[E.COMMITLINT_CLI],delete t.devDependencies[E.COMMITLINT_CONFIG],delete t.devDependencies[E.LINT_STAGED],delete t.scripts.prepare,delete t.scripts.postinstall,delete t.commitlint,delete t["lint-staged"],t)))},Hi=async(e,r)=>{r.commitizen||(await S(b.join(e,a.CZRC)),await j(b.join(e,a.PACKAGE_JSON),t=>(delete t.devDependencies[E.COMMITIZEN],delete t.devDependencies[E.CZ_CONVENTIONAL_CHANGELOG],delete t.config?.commitizen,t.config&&Object.keys(t.config).length===0&&delete t.config,delete t.scripts.commit,t)))},Ui=async(e,r)=>{r.ci||await P(b.join(e,a.GITHUB_WORKFLOWS))},Mi=async(e,r)=>{let t=b.join(e,a.GITHUB_DIR);if(!r.keepTemplates)await P(b.join(t,a.GITHUB_ISSUE_TEMPLATE)),await S(b.join(t,a.GITHUB_PR_TEMPLATE));else{let o=b.join(t,a.GITHUB_ISSUE_TEMPLATE),n=b.join(t,a.GITHUB_PR_TEMPLATE),i=s=>s.replace(/Teispace/g,r.company).replace(/support@teispace\.com/g,r.email).replace(/Next\.js Starter/g,r.projectName).replace(/\[AUTHOR\]/g,r.author).replace(/\[COMPANY\]/g,r.company).replace(/\[EMAIL\]/g,r.email);if(l(n)){let s=await d(n);s=i(s),await u(n,s)}try{if(l(o)){let s=await ur(o);for(let c of s){let p=b.join(o,c),f=await d(p);f=i(f),await u(p,f)}}}catch{}}},Ji=async(e,r)=>{let t=[a.CODE_OF_CONDUCT,a.CONTRIBUTING,a.SECURITY];for(let o of t)r.communityFiles.includes(o)||await S(b.join(e,o))},zi=async(e,r)=>{if(r.docker){let t=b.join(e,a.ENV_EXAMPLE);if(l(t)){let o=await d(t),n=(i,s)=>{let c=new RegExp(`${i}=.*`);c.test(o)?o=o.replace(c,`${i}=${s}`):o+=`${i}=${s}
178
+ `};n("CONTAINER_NAME",r.containerName||"next-app"),n("IMAGE_NAME",r.imageName||"nextjs-starter"),n("IMAGE_TAG",r.imageTag||"latest"),await u(t,o)}}else{await S(b.join(e,a.DOCKERFILE)),await S(b.join(e,a.DOCKER_COMPOSE)),await S(b.join(e,a.DOCKERIGNORE));let t=b.join(e,a.ENV_EXAMPLE);if(l(t)){let o=await d(t);o=o.replace(/# Docker Compose Configuration\n/,""),o=o.replace(/CONTAINER_NAME=.*\n/,""),o=o.replace(/IMAGE_NAME=.*\n/,""),o=o.replace(/IMAGE_TAG=.*\n/,""),await u(t,o)}}},Bi=async(e,r)=>{let t=async i=>{let s=await ur(i,{withFileTypes:!0}),c=[];for(let p of s){let f=b.join(i,p.name);p.isDirectory()&&p.name!=="node_modules"&&p.name!==".git"?c.push(...await t(f)):p.isFile()&&p.name.toLowerCase()==="readme.md"&&c.push(f)}return c},o=await t(e),n=b.join(e,a.README);for(let i of o)i!==n&&await S(i);if(r.readme){let i=`# ${r.projectName}
179
+
180
+ ${r.description}
181
+
182
+ ## Getting Started
183
+
184
+ First, run the development server:
185
+
186
+ \`\`\`bash
187
+ ${r.packageManager==="npm"?"npm run dev":`${r.packageManager} dev`}
188
+ \`\`\`
189
+
190
+ Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
191
+ `;await u(n,i)}else await S(n)};C();T();import it from"node:path";var gr=async(e,r)=>{let t=[];r.i18n&&t.push("import { type AbstractIntlMessages, NextIntlClientProvider } from 'next-intl';"),r.darkMode&&t.push("import { CustomThemeProvider } from '@/providers';"),r.redux&&t.push("import type { AppState } from '@/store';"),r.i18n&&t.push("import type { SupportedLocale } from '@/types/i18n';"),r.redux&&t.push("import { StoreProvider } from './StoreProvider';");let o=["children: React.ReactNode;"],n=["children"];r.i18n&&(o.push("locale: SupportedLocale;"),o.push("messages: AbstractIntlMessages;"),o.push("timeZone: string;"),n.push("locale","messages","timeZone")),r.redux&&(o.push("preloadedState?: Partial<AppState>;"),n.push("preloadedState"));let i="{children}";r.i18n&&(i=`<NextIntlClientProvider locale={locale} messages={messages} timeZone={timeZone}>
30
192
  ${i}
31
- </NextIntlClientProvider>`),o.darkMode&&(i=`<CustomThemeProvider>
193
+ </NextIntlClientProvider>`),r.darkMode&&(i=`<CustomThemeProvider>
32
194
  ${i}
33
- </CustomThemeProvider>`),o.redux&&(i=`<StoreProvider>
195
+ </CustomThemeProvider>`),r.redux&&(i=`<StoreProvider preloadedState={preloadedState}>
34
196
  ${i}
35
- </StoreProvider>`),i==="{children}"&&(i="<>{children}</>"),n+=` ${i}
197
+ </StoreProvider>`),i==="{children}"&&(i="<>{children}</>");let s=`type RootProviderProps = {
198
+ ${o.join(`
199
+ `)}
200
+ };`,c=`'use client';
201
+ ${t.join(`
202
+ `)}
203
+
204
+ ${s}
205
+
206
+ export const RootProvider = ({ ${n.join(", ")} }: RootProviderProps) => {
207
+ return (
208
+ ${i}
36
209
  );
37
210
  };
38
- `,await u(Ke.join(t,a.ROOT_PROVIDER),n)},zt=async(t,o)=>{if(!o.i18n){let e=`import type { Metadata } from 'next';
211
+ `;await u(it.join(e,a.ROOT_PROVIDER),c)},hr=async(e,r)=>{if(r.i18n)return;let t=`\`\${livvic.variable} ${r.darkMode?"bg-light antialiased dark:bg-dark":"antialiased"}\``,o=(r.redux,""),n=`import type { Metadata } from 'next';
39
212
  import '@/styles/globals.css';
40
213
  import { Livvic } from 'next/font/google';
41
214
  import { RootProvider } from '@/providers';
@@ -48,8 +221,8 @@ const livvic = Livvic({
48
221
  });
49
222
 
50
223
  export const metadata: Metadata = {
51
- title: '${o.projectName}',
52
- description: '${o.description}',
224
+ title: '${r.projectName}',
225
+ description: '${r.description}',
53
226
  };
54
227
 
55
228
  export default function RootLayout({
@@ -58,119 +231,129 @@ export default function RootLayout({
58
231
  children: React.ReactNode;
59
232
  }>) {
60
233
  return (
61
- <html lang="en" suppressHydrationWarning={${o.darkMode?"true":"false"}}>
62
- <body className={\`\${livvic.variable} ${o.darkMode?"bg-light dark:bg-dark ":""}antialiased\`}>
63
- <RootProvider>
234
+ <html lang="en"${r.darkMode?" suppressHydrationWarning={true}":""}>
235
+ <body className={${t}}>
236
+ <RootProvider${o}>
64
237
  {children}
65
238
  </RootProvider>
66
239
  </body>
67
240
  </html>
68
241
  );
69
242
  }
70
- `;await u(Ke.join(t,a.ROOT_LAYOUT),e);let r=o.redux?`import { Counter } from '@/features/counter';
243
+ `;await u(it.join(e,a.ROOT_LAYOUT),n);let i=r.redux?`import { Counter } from '@/features/counter';
71
244
 
72
- `:"",n=o.redux?`
73
- <Counter />`:"",i=`${r}export default function Home() {
245
+ `:"",s=r.redux?`
246
+ <Counter />`:"",c=`${i}export default function Home() {
74
247
  return (
75
248
  <div className="flex min-h-screen flex-col items-center justify-center p-24">
76
- <h1 className="text-4xl font-bold">Welcome to ${o.projectName}</h1>
77
- <p className="mt-4 text-xl">Get started by editing src/app/page.tsx</p>${n}
249
+ <h1 className="text-4xl font-bold">Welcome to ${r.projectName}</h1>
250
+ <p className="mt-4 text-xl">Get started by editing src/app/page.tsx</p>${s}
78
251
  </div>
79
252
  );
80
253
  }
81
- `;await u(Ke.join(t,a.ROOT_PAGE),i)}};P();T();import I from"node:path";import{readdir as Wt}from"node:fs/promises";var Bt=async(t,o)=>{await ii(t,o),await ni(t,o),await si(t,o),await ai(t,o),await ci(t,o),await pi(t,o),await mi(t,o)},ii=async(t,o)=>{o.preCommitHooks||(await h(I.join(t,a.HUSKY_DIR)),await w(I.join(t,a.COMMITLINT_CONFIG)),await w(I.join(t,a.LINTSTAGED_RC)),await me(I.join(t,a.PACKAGE_JSON),e=>(delete e.devDependencies[b.HUSKY],delete e.devDependencies[b.COMMITLINT_CLI],delete e.devDependencies[b.COMMITLINT_CONFIG],delete e.devDependencies[b.LINT_STAGED],delete e.scripts.prepare,delete e.scripts.postinstall,delete e.commitlint,delete e["lint-staged"],e)))},ni=async(t,o)=>{o.commitizen||(await w(I.join(t,a.CZRC)),await me(I.join(t,a.PACKAGE_JSON),e=>(delete e.devDependencies[b.COMMITIZEN],delete e.devDependencies[b.CZ_CONVENTIONAL_CHANGELOG],delete e.config?.commitizen,e.config&&Object.keys(e.config).length===0&&delete e.config,delete e.scripts.commit,e)))},si=async(t,o)=>{o.ci||await h(I.join(t,a.GITHUB_WORKFLOWS))},ai=async(t,o)=>{let e=I.join(t,a.GITHUB_DIR);if(!o.keepTemplates)await h(I.join(e,a.GITHUB_ISSUE_TEMPLATE)),await w(I.join(e,a.GITHUB_PR_TEMPLATE));else{let r=I.join(e,a.GITHUB_ISSUE_TEMPLATE),n=I.join(e,a.GITHUB_PR_TEMPLATE),i=s=>s.replace(/Teispace/g,o.company).replace(/support@teispace\.com/g,o.email).replace(/Next\.js Starter/g,o.projectName).replace(/\[AUTHOR\]/g,o.author).replace(/\[COMPANY\]/g,o.company).replace(/\[EMAIL\]/g,o.email);if(l(n)){let s=await d(n);s=i(s),await u(n,s)}try{if(l(r)){let s=await Wt(r);for(let c of s){let m=I.join(r,c),f=await d(m);f=i(f),await u(m,f)}}}catch{}}},ci=async(t,o)=>{let e=[a.CODE_OF_CONDUCT,a.CONTRIBUTING,a.SECURITY];for(let r of e)o.communityFiles.includes(r)||await w(I.join(t,r))},pi=async(t,o)=>{if(o.docker){let e=I.join(t,a.ENV_EXAMPLE);if(l(e)){let r=await d(e),n=(i,s)=>{let c=new RegExp(`${i}=.*`);c.test(r)?r=r.replace(c,`${i}=${s}`):r+=`${i}=${s}
82
- `};n("CONTAINER_NAME",o.containerName||"next-app"),n("IMAGE_NAME",o.imageName||"nextjs-starter"),n("IMAGE_TAG",o.imageTag||"latest"),await u(e,r)}}else{await w(I.join(t,a.DOCKERFILE)),await w(I.join(t,a.DOCKER_COMPOSE)),await w(I.join(t,a.DOCKERIGNORE));let e=I.join(t,a.ENV_EXAMPLE);if(l(e)){let r=await d(e);r=r.replace(/# Docker Compose Configuration\n/,""),r=r.replace(/CONTAINER_NAME=.*\n/,""),r=r.replace(/IMAGE_NAME=.*\n/,""),r=r.replace(/IMAGE_TAG=.*\n/,""),await u(e,r)}}},mi=async(t,o)=>{let e=async i=>{let s=await Wt(i,{withFileTypes:!0}),c=[];for(let m of s){let f=I.join(i,m.name);m.isDirectory()&&m.name!=="node_modules"&&m.name!==".git"?c.push(...await e(f)):m.isFile()&&m.name.toLowerCase()==="readme.md"&&c.push(f)}return c},r=await e(t),n=I.join(t,a.README);for(let i of r)i!==n&&await w(i);if(o.readme){let i=`# ${o.projectName}
83
-
84
- ${o.description}
85
-
86
- ## Getting Started
87
-
88
- First, run the development server:
254
+ `;await u(it.join(e,a.ROOT_PAGE),c)};import Xi from"degit";var xr=async e=>{let r=I("Downloading template...");try{await Xi("teispace/nextjs-starter",{cache:!1,force:!0,verbose:!0}).clone(e),r.succeed("Template downloaded successfully.")}catch(t){throw r.fail("Failed to download template."),t}};var yr=e=>{e.command("init").description("Initialize a new Next.js project").argument("[name]","Project name").action(async r=>{await Yi(r)})},Yi=async e=>{Jt(),m("Welcome to the Teispace Next.js App Creator!"),m("");let r=await Vt(e),t=nt.resolve(process.cwd(),r.projectName);l(t)&&(console.error(re.red(`Error: Directory ${r.projectName} already exists.`)),process.exit(1));let o=I("Initializing project..."),n=async()=>{if(l(t)){o.stop(),console.log(re.yellow(`
255
+ Cleaning up: Deleting directory ${r.projectName}...`));try{await P(t),console.log(re.green("Cleanup successful."))}catch(s){console.error(re.red(`Failed to clean up directory ${r.projectName}:`),s)}}},i=async()=>{console.log(re.red(`
256
+ Process interrupted. Cleaning up...`)),await n(),process.exit(1)};process.on("SIGINT",i),process.on("SIGTERM",i);try{if(await xr(t),await dr(t,r),await mr(t,r),o.text="Generating code...",await gr(t,r),await hr(t,r),o.text="Setting up developer tools...",await fr(t,r),o.text="Initializing Git...",await Bt(t,r.gitRemote,r.pushToRemote),o.text="Installing dependencies...",await Xt(t,r.packageManager),o.text="Formatting and Linting...",await G(t,r.packageManager,"lint:fix"),r.copyEnv){o.text="Creating .env file...";let s=nt.join(t,".env.example"),c=nt.join(t,".env");l(s)&&await(await import("node:fs/promises")).copyFile(s,c)}process.off("SIGINT",i),process.off("SIGTERM",i),o.succeed(re.green(`Project ${r.projectName} created successfully!`)),m(""),m("To get started:"),m(re.cyan(` cd ${r.projectName}`)),m(re.cyan(` ${r.packageManager==="npm"?"npm run dev":`${r.packageManager} dev`}`)),m("")}catch(s){o.fail("Failed to create project."),console.error(s),await n(),process.exit(1)}};import xt from"node:path";import V from"picocolors";U();import{mkdir as Cr,writeFile as ct}from"node:fs/promises";import le from"node:path";T();var at=e=>{let{componentName:r,isClient:t,hasI18n:o}=e,n=e.translationNamespace||r,i=[];return(t||o)&&i.push("'use client';"),o&&i.push("import { useTranslations } from 'next-intl';"),i.push(""),i.push(`export function ${r}() {`),o?(i.push(` const t = useTranslations('${n}');`),i.push(""),i.push(" return ("),i.push(" <div>"),i.push(" <h2>{t('title')}</h2>"),i.push(" </div>"),i.push(" );")):(i.push(" return ("),i.push(" <div>"),i.push(` <h2>${r}</h2>`),i.push(" </div>"),i.push(" );")),i.push("}"),i.push(""),i.join(`
257
+ `)},vr=e=>`export { ${e.componentName} } from './${e.componentName}';
258
+ `;var pt=async e=>{let{name:r,projectPath:t,isClient:o,hasI18n:n,featurePath:i}=e,s=R(r);i?await qi(s,t,i,o,n):await Zi(s,r,t,o,n)},qi=async(e,r,t,o,n)=>{let i=le.join(r,t,"components");await Cr(i,{recursive:!0}),await ct(le.join(i,`${e}.tsx`),at({componentName:e,isClient:o,hasI18n:n}))},Zi=async(e,r,t,o,n)=>{let i=le.join(t,"src","components","common",e);await Cr(i,{recursive:!0}),await ct(le.join(i,`${e}.tsx`),at({componentName:e,isClient:o,hasI18n:n})),await ct(le.join(i,"index.ts"),vr({componentName:e}));let s=le.join(t,"src","components","common","index.ts");await Qi(s,`export { ${e} } from './${e}';
259
+ `);let c=le.join(t,"src","components","index.ts");await en(c)},Qi=async(e,r)=>{let t="";l(e)&&(t=await d(e)),t.includes(r.trim())||(t+=r,await u(e,t))},en=async e=>{let r="";l(e)&&(r=await d(e));let t=`export * from './common';
260
+ `;r.includes(t.trim())||(r+=t,await u(e,r))};import{writeFile as tn}from"node:fs/promises";import rn from"node:path";var Er=e=>{let{camelName:r,pascalName:t,httpClient:o}=e,n=o==="axios"?"import { axiosClient } from '@/lib/utils/http';":"import { fetchClient } from '@/lib/utils/http';",i=o==="axios"?"axiosClient":"fetchClient";return`import { AppApis } from '@/lib/config';
261
+ ${n}
262
+ import type { ResultAsync } from '@/types';
89
263
 
90
- \`\`\`bash
91
- ${o.packageManager==="npm"?"npm run dev":o.packageManager+" dev"}
92
- \`\`\`
264
+ /**
265
+ * Summary type used in list responses (e.g., cards, tables).
266
+ */
267
+ export interface ${t}Summary {
268
+ id: string;
269
+ // Add list/card fields here (title, thumbnail, status, etc.)
270
+ }
93
271
 
94
- Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
95
- `;await u(n,i)}else await w(n)};var Vt=t=>{t.command("init").description("Initialize a new Next.js project").argument("[name]","Project name").action(async o=>{await li(o)})},li=async t=>{$t(),p("Welcome to the Teispace Next.js App Creator!"),p("");let o=await Et(t),e=Ze.resolve(process.cwd(),o.projectName);l(e)&&(console.error(Z.red(`Error: Directory ${o.projectName} already exists.`)),process.exit(1));let r=A("Initializing project..."),n=async()=>{if(l(e)){r.stop(),console.log(Z.yellow(`
96
- Cleaning up: Deleting directory ${o.projectName}...`));try{await h(e),console.log(Z.green("Cleanup successful."))}catch(s){console.error(Z.red(`Failed to clean up directory ${o.projectName}:`),s)}}},i=async()=>{console.log(Z.red(`
97
- Process interrupted. Cleaning up...`)),await n(),process.exit(1)};process.on("SIGINT",i),process.on("SIGTERM",i);try{if(await bt(e),await kt(e,o),await Jt(e,o),r.text="Generating code...",await Yt(e,o),await zt(e,o),r.text="Setting up developer tools...",await Bt(e,o),r.text="Initializing Git...",await Nt(e,o.gitRemote,o.pushToRemote),r.text="Installing dependencies...",await Rt(e,o.packageManager),r.text="Formatting and Linting...",await D(e,o.packageManager,"format"),await D(e,o.packageManager,"lint:fix"),o.copyEnv){r.text="Creating .env file...";let s=Ze.join(e,".env.example"),c=Ze.join(e,".env");l(s)&&await(await import("node:fs/promises")).copyFile(s,c)}process.off("SIGINT",i),process.off("SIGTERM",i),r.succeed(Z.green(`Project ${o.projectName} created successfully!`)),p(""),p("To get started:"),p(Z.cyan(` cd ${o.projectName}`)),p(Z.cyan(` ${o.packageManager==="npm"?"npm run dev":o.packageManager+" dev"}`)),p("")}catch(s){r.fail("Failed to create project."),console.error(s),await n(),process.exit(1)}};import $ from"picocolors";import xt from"node:path";import di from"enquirer";var{prompt:ui}=di,qt=async(t,o,e,r,n,i,s)=>{let c=[];t||c.push({type:"input",name:"featureName",message:"What is the feature name?",initial:"my-feature",validate:f=>/^[a-z0-9-]+$/.test(f)?!0:"Feature name must be lowercase and contain only alphanumeric characters and hyphens."}),o&&r===void 0&&n===void 0&&(c.push({type:"confirm",name:"createStore",message:"Generate Redux store for this feature?",initial:!0}),c.push({type:"confirm",name:"persistStore",message:"Enable persistence for this store?",initial:!1,skip(){return!this.state.answers.createStore}})),e&&e!=="none"&&i===void 0&&s===void 0&&(c.push({type:"confirm",name:"createService",message:"Generate API service for this feature?",initial:!0}),e==="both"&&c.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=c.length>0?await ui(c):{};return{featureName:t||m.featureName,hasRedux:o||!1,createStore:r===!0?!1:n!==void 0?!0:m.createStore||!1,persistStore:n==="persist"?!0:n==="no-persist"?!1:m.persistStore||!1,httpClient:e||"none",createService:i===!0?!1:s!==void 0?!0:m.createService||!1,selectedHttpClient:s||m.selectedHttpClient||(e==="both"?"fetch":e!=="none"?e:void 0)}};W();var re=async(t,o)=>{for(let e of t)if(!e.shouldSkip?.(o)){o.spinner.start(e.spinnerText);try{await e.execute(o),o.spinner.succeed(e.name)}catch(r){throw o.spinner.fail(e.name),r}}};import Bi from"node:path";import{writeFile as Oe,mkdir as wi}from"node:fs/promises";import L from"node:path";var oo=t=>{let{componentName:o,hookName:e}=t;return`'use client';
98
- import { ${e} } from '../hooks/${e}';
272
+ /**
273
+ * Detail type used in single-item responses (e.g., detail page).
274
+ */
275
+ export interface ${t}Detail extends ${t}Summary {
276
+ // Add detailed fields here (content, metadata, relations, etc.)
277
+ }
99
278
 
100
- export function ${o}() {
101
- const {} = ${e}();
279
+ export interface Create${t}Dto {
280
+ // Add create fields here
281
+ }
102
282
 
103
- return (
104
- <div>
105
- <h2>${o} Component</h2>
106
- {/* Add your component UI here */}
107
- </div>
108
- );
283
+ export interface Update${t}Dto {
284
+ // Add update fields here
109
285
  }
110
286
 
111
- export default ${o};
112
- `};var ro=t=>{let{hookName:o,componentName:e,featureName:r}=t;return`'use client';
113
- import { useAppDispatch, useAppSelector } from '@/store/hooks';
114
- import { select${e}State, setLoading, setError } from '../store/${r}.selectors';
287
+ export const ${r}Service = {
288
+ getAll: (): ResultAsync<${t}Summary[]> => {
289
+ return ${i}.get<${t}Summary[]>(AppApis.${r}.getAll);
290
+ },
115
291
 
116
- export const ${o} = () => {
117
- const dispatch = useAppDispatch();
118
- const state = useAppSelector(select${e}State);
292
+ getById: (id: string): ResultAsync<${t}Detail> => {
293
+ return ${i}.get<${t}Detail>(AppApis.${r}.getById(id));
294
+ },
119
295
 
120
- const handleSetLoading = (loading: boolean) => {
121
- dispatch(setLoading(loading));
122
- console.log('Loading state updated:', loading);
123
- };
296
+ create: (data: Create${t}Dto): ResultAsync<${t}Detail> => {
297
+ return ${i}.post<${t}Detail>(AppApis.${r}.create, data);
298
+ },
124
299
 
125
- const handleSetError = (error: string | null) => {
126
- dispatch(setError(error));
127
- console.log('Error state updated:', error);
128
- };
300
+ update: (id: string, data: Update${t}Dto): ResultAsync<${t}Detail> => {
301
+ return ${i}.patch<${t}Detail>(AppApis.${r}.update(id), data);
302
+ },
129
303
 
130
- return {
131
- state,
132
- setLoading: handleSetLoading,
133
- setError: handleSetError,
134
- } as const;
304
+ delete: (id: string): ResultAsync<void> => {
305
+ return ${i}.delete<void>(AppApis.${r}.delete(id));
306
+ },
135
307
  };
136
- `},io=t=>{let{hookName:o}=t;return`'use client';
137
- import { useState } from 'react';
138
-
139
- export const ${o} = () => {
140
- // Add your state and logic here
141
- const [state, setState] = useState({});
142
-
143
- return {
144
- state,
145
- // Add your methods here
146
- } as const;
308
+ `},Ir=e=>{let{camelName:r,kebabName:t}=e;return` ${r}: {
309
+ base: \`\${API_PREFIX}/${t}\`,
310
+ getAll: \`\${API_PREFIX}/${t}\`,
311
+ getById: (id: string) => \`\${API_PREFIX}/${t}/\${id}\`,
312
+ create: \`\${API_PREFIX}/${t}\`,
313
+ update: (id: string) => \`\${API_PREFIX}/${t}/\${id}\`,
314
+ delete: (id: string) => \`\${API_PREFIX}/${t}/\${id}\`,
315
+ },`};var lt=async e=>{let{name:r,outputPath:t,httpClient:o}=e,n=$(r),i=R(r);await tn(rn.join(t,`${r}.service.ts`),Er({camelName:n,pascalName:i,httpClient:o}))};import{mkdir as an,writeFile as He}from"node:fs/promises";import M from"node:path";import{writeFile as on}from"node:fs/promises";import nn from"node:path";var Rr=e=>{let{camelName:r,httpClient:t}=e;return`import { AppApis } from '@/lib/config';
316
+ ${t==="axios"?"import { axiosClient } from '@/lib/utils/http';":"import { fetchClient } from '@/lib/utils/http';"}
317
+ import type { ResultAsync } from '@/types';
318
+
319
+ export const ${r}Service = {
320
+ getAll: (): ResultAsync<string> => {
321
+ return ${t==="axios"?"axiosClient":"fetchClient"}.get<string>(AppApis.${r}.getAll);
322
+ },
147
323
  };
148
- `};var be=t=>{let{componentName:o,withStore:e}=t;return`export interface ${o}State {
149
- ${e?`loading: boolean;
150
- error: string | null;
151
- // Add your state properties here`:`// Add your state properties here
152
- // example: value: string;`}
153
- }
154
- `};var no=t=>{let{sliceName:o,withPersist:e}=t;return`export * from './${o}.slice';
155
- export * from './${o}.selectors';
156
- export * from './${o}.types';${e?`
324
+ `};var ye=async e=>{let{name:r,outputPath:t,httpClient:o}=e,n=$(r);await on(nn.join(t,`${r}.service.ts`),Rr({camelName:n,httpClient:o}))};import{mkdir as sn,writeFile as Pe}from"node:fs/promises";import Te from"node:path";var Nr=e=>{let{sliceName:r,withPersist:t}=e;return`export * from './${r}.slice';
325
+ export * from './${r}.selectors';
326
+ export * from './${r}.types';${t?`
157
327
  export * from './persist';`:""}
158
- `},so=t=>{let{featureName:o,componentName:e,hookName:r,withStore:n,withService:i}=t;return`export { default as ${e} } from './components/${e}';
159
- export { ${r} } from './hooks/${r}';
160
- export * from './types/${o}.types';${n?`
328
+ `},br=e=>{let{featureName:r,componentName:t,hookName:o,withStore:n,withService:i}=e;return`export { default as ${t} } from './components/${t}';
329
+ export { ${o} } from './hooks/${o}';
330
+ export * from './types/${r}.types';${n?`
161
331
  export * from './store';`:""}${i?`
162
- export * from './services/${o}.service';`:""}
163
- `};import{writeFile as le,mkdir as xi}from"node:fs/promises";import de from"node:path";var ao=t=>{let{componentName:o,camelName:e,typesImportPath:r}=t;return`import { createSlice, PayloadAction } from '@reduxjs/toolkit';
164
- import { ${o}State } from '${r}';
332
+ export * from './services/${r}.service';`:""}
333
+ `};var $r=e=>{let{componentName:r,camelName:t,typesImportPath:o}=e;return`import type { PersistConfig } from 'redux-persist';
334
+ import storage from 'redux-persist/lib/storage';
335
+ import type { ${r}State } from '${o}';
165
336
 
166
- const initialState: ${o}State = {
337
+ export const ${t}PersistConfig: PersistConfig<${r}State> = {
338
+ key: '${t}',
339
+ storage,
340
+ // whitelist: ['someField'], // Specify which fields to persist
341
+ };
342
+ `};var Ar=e=>{let{componentName:r,camelName:t,sliceName:o}=e;return`import { RootState } from '@/store/rootReducer';
343
+
344
+ export const select${r}State = (state: RootState) => state.${t};
345
+ export { setLoading, setError, resetState } from './${o}.slice';
346
+ `};var Or=e=>{let{componentName:r,camelName:t,typesImportPath:o}=e;return`import { createSlice, type PayloadAction } from '@reduxjs/toolkit';
347
+ import type { ${r}State } from '${o}';
348
+
349
+ const initialState: ${r}State = {
167
350
  loading: false,
168
351
  error: null,
169
352
  // Add your initial state here
170
353
  };
171
354
 
172
- export const ${e}Slice = createSlice({
173
- name: '${e}',
355
+ export const ${t}Slice = createSlice({
356
+ name: '${t}',
174
357
  initialState,
175
358
  reducers: {
176
359
  setLoading: (state, action: PayloadAction<boolean>) => {
@@ -186,90 +369,78 @@ export const ${e}Slice = createSlice({
186
369
  },
187
370
  });
188
371
 
189
- export const { setLoading, setError, resetState } = ${e}Slice.actions;
190
-
191
- export const ${e}Reducer = ${e}Slice.reducer;
192
- `};var co=t=>{let{componentName:o,camelName:e,sliceName:r}=t;return`import { RootState } from '@/store/rootReducer';
193
-
194
- export const select${o}State = (state: RootState) => state.${e};
195
- export { setLoading, setError, resetState } from './${r}.slice';
196
- `};var po=t=>{let{componentName:o,camelName:e,typesImportPath:r}=t;return`import { PersistConfig } from 'redux-persist';
197
- import storage from 'redux-persist/lib/storage';
198
- import { ${o}State } from '${r}';
199
-
200
- export const ${e}PersistConfig: PersistConfig<${o}State> = {
201
- key: '${e}',
202
- storage,
203
- // whitelist: ['someField'], // Specify which fields to persist
204
- };
205
- `};var ue=async t=>{let{name:o,outputPath:e,persist:r,typesImportPath:n=`./${o}.types`}=t;await xi(e,{recursive:!0});let i=N(o),s=k(o);await Promise.all([le(de.join(e,`${o}.types.ts`),be({componentName:i,withStore:!0})),le(de.join(e,`${o}.slice.ts`),ao({componentName:i,camelName:s,typesImportPath:n})),le(de.join(e,`${o}.selectors.ts`),co({componentName:i,camelName:s,sliceName:o})),...r?[le(de.join(e,"persist.ts"),po({componentName:i,camelName:s,typesImportPath:n}))]:[],le(de.join(e,"index.ts"),no({sliceName:o,withPersist:r}))])};import{writeFile as yi}from"node:fs/promises";import Pi from"node:path";var mo=t=>{let{camelName:o,httpClient:e}=t;return`import { AppApis } from '@/lib/config';
206
- ${e==="axios"?"import { axiosClient } from '@/lib/utils/http';":"import { fetchClient } from '@/lib/utils/http';"}
207
- import { ResultAsync } from '@/types';
208
-
209
- export const ${o}Service = {
210
- getAll: (): ResultAsync<string> => {
211
- return ${e==="axios"?"axiosClient":"fetchClient"}.get<string>(AppApis.${o}.getAll);
212
- },
213
- };
214
- `};var fe=async t=>{let{name:o,outputPath:e,httpClient:r}=t,n=k(o);await yi(Pi.join(e,`${o}.service.ts`),mo({camelName:n,httpClient:r}))};var et=async t=>{let{name:o,outputPath:e,createStore:r,persistStore:n,createService:i,httpClient:s}=t,c=N(o),m=`use${c}`,f=[L.join(e,"components"),L.join(e,"hooks"),L.join(e,"types"),...r?[L.join(e,"store")]:[],...i?[L.join(e,"services")]:[]];await Promise.all(f.map(x=>wi(x,{recursive:!0}))),await Promise.all([Oe(L.join(e,"components",`${c}.tsx`),oo({componentName:c,hookName:m})),Oe(L.join(e,"hooks",`${m}.ts`),r?ro({hookName:m,componentName:c,featureName:o}):io({hookName:m})),Oe(L.join(e,"types",`${o}.types.ts`),be({componentName:c,withStore:r})),Oe(L.join(e,"index.ts"),so({featureName:o,componentName:c,hookName:m,withStore:r,withService:i}))]),r&&await ue({name:o,outputPath:L.join(e,"store"),persist:n,typesImportPath:`../types/${o}.types`}),i&&s&&await fe({name:o,outputPath:L.join(e,"services"),httpClient:s})};import{writeFile as Si}from"node:fs/promises";import Ci from"node:path";var lo=t=>{let{camelName:o,pascalName:e,httpClient:r}=t,n=r==="axios"?"import { axiosClient } from '@/lib/utils/http';":"import { fetchClient } from '@/lib/utils/http';",i=r==="axios"?"axiosClient":"fetchClient";return`import { AppApis } from '@/lib/config';
215
- ${n}
216
- import { ResultAsync } from '@/types';
372
+ export const { setLoading, setError, resetState } = ${t}Slice.actions;
217
373
 
218
- /**
219
- * Summary type used in list responses (e.g., cards, tables).
220
- */
221
- export interface ${e}Summary {
222
- id: string;
223
- // Add list/card fields here (title, thumbnail, status, etc.)
374
+ export const ${t}Reducer = ${t}Slice.reducer;
375
+ `};var Ge=e=>{let{componentName:r,withStore:t}=e;return`export interface ${r}State {
376
+ ${t?`loading: boolean;
377
+ error: string | null;
378
+ // Add your state properties here`:`// Add your state properties here
379
+ // example: value: string;`}
224
380
  }
381
+ `};var Se=async e=>{let{name:r,outputPath:t,persist:o,typesImportPath:n=`./${r}.types`}=e;await sn(t,{recursive:!0});let i=R(r),s=$(r);await Promise.all([Pe(Te.join(t,`${r}.types.ts`),Ge({componentName:i,withStore:!0})),Pe(Te.join(t,`${r}.slice.ts`),Or({componentName:i,camelName:s,typesImportPath:n})),Pe(Te.join(t,`${r}.selectors.ts`),Ar({componentName:i,camelName:s,sliceName:r})),...o?[Pe(Te.join(t,"persist.ts"),$r({componentName:i,camelName:s,typesImportPath:n}))]:[],Pe(Te.join(t,"index.ts"),Nr({sliceName:r,withPersist:o}))])};var _r=e=>{let{componentName:r,hookName:t}=e;return`'use client';
382
+ import { ${t} } from '../hooks/${t}';
225
383
 
226
- /**
227
- * Detail type used in single-item responses (e.g., detail page).
228
- */
229
- export interface ${e}Detail extends ${e}Summary {
230
- // Add detailed fields here (content, metadata, relations, etc.)
231
- }
384
+ export function ${r}() {
385
+ const {} = ${t}();
232
386
 
233
- export interface Create${e}Dto {
234
- // Add create fields here
387
+ return (
388
+ <div>
389
+ <h2>${r} Component</h2>
390
+ {/* Add your component UI here */}
391
+ </div>
392
+ );
235
393
  }
236
394
 
237
- export interface Update${e}Dto {
238
- // Add update fields here
239
- }
395
+ export default ${r};
396
+ `};var kr=e=>{let{hookName:r,componentName:t,featureName:o}=e;return`'use client';
397
+ import { useAppDispatch, useAppSelector } from '@/store/hooks';
398
+ import { select${t}State, setLoading, setError } from '../store/${o}.selectors';
240
399
 
241
- export const ${o}Service = {
242
- getAll: (): ResultAsync<${e}Summary[]> => {
243
- return ${i}.get<${e}Summary[]>(AppApis.${o}.getAll);
244
- },
400
+ export const ${r} = () => {
401
+ const dispatch = useAppDispatch();
402
+ const state = useAppSelector(select${t}State);
245
403
 
246
- getById: (id: string): ResultAsync<${e}Detail> => {
247
- return ${i}.get<${e}Detail>(AppApis.${o}.getById(id));
248
- },
404
+ const handleSetLoading = (loading: boolean) => {
405
+ dispatch(setLoading(loading));
406
+ console.log('Loading state updated:', loading);
407
+ };
249
408
 
250
- create: (data: Create${e}Dto): ResultAsync<${e}Detail> => {
251
- return ${i}.post<${e}Detail>(AppApis.${o}.create, data);
252
- },
409
+ const handleSetError = (error: string | null) => {
410
+ dispatch(setError(error));
411
+ console.log('Error state updated:', error);
412
+ };
253
413
 
254
- update: (id: string, data: Update${e}Dto): ResultAsync<${e}Detail> => {
255
- return ${i}.patch<${e}Detail>(AppApis.${o}.update(id), data);
256
- },
414
+ return {
415
+ state,
416
+ setLoading: handleSetLoading,
417
+ setError: handleSetError,
418
+ } as const;
419
+ };
420
+ `},jr=e=>{let{hookName:r}=e;return`'use client';
421
+ import { useState } from 'react';
257
422
 
258
- delete: (id: string): ResultAsync<void> => {
259
- return ${i}.delete<void>(AppApis.${o}.delete(id));
260
- },
423
+ export const ${r} = () => {
424
+ // Add your state and logic here
425
+ const [state, setState] = useState({});
426
+
427
+ return {
428
+ state,
429
+ // Add your methods here
430
+ } as const;
261
431
  };
262
- `},uo=t=>{let{camelName:o,kebabName:e}=t;return` ${o}: {
263
- base: \`\${API_PREFIX}/${e}\`,
264
- getAll: \`\${API_PREFIX}/${e}\`,
265
- getById: (id: string) => \`\${API_PREFIX}/${e}/\${id}\`,
266
- create: \`\${API_PREFIX}/${e}\`,
267
- update: (id: string) => \`\${API_PREFIX}/${e}/\${id}\`,
268
- delete: (id: string) => \`\${API_PREFIX}/${e}/\${id}\`,
269
- },`};var tt=async t=>{let{name:o,outputPath:e,httpClient:r}=t,n=k(o),i=N(o);await Si(Ci.join(e,`${o}.service.ts`),lo({camelName:n,pascalName:i,httpClient:r}))};import{writeFile as ot,mkdir as vi}from"node:fs/promises";import ge from"node:path";var fo=t=>{let{componentName:o,routePath:e,hasI18n:r}=t;return r?`import { generateSEOMetadata } from '@/lib/config/seo';
270
- import { SupportedLocale } from '@/types/i18n';
271
- import { Metadata } from 'next';
432
+ `};var mt=async e=>{let{name:r,outputPath:t,createStore:o,persistStore:n,createService:i,httpClient:s}=e,c=R(r),p=`use${c}`,f=[M.join(t,"components"),M.join(t,"hooks"),M.join(t,"types"),...o?[M.join(t,"store")]:[],...i?[M.join(t,"services")]:[]];await Promise.all(f.map(g=>an(g,{recursive:!0}))),await Promise.all([He(M.join(t,"components",`${c}.tsx`),_r({componentName:c,hookName:p})),He(M.join(t,"hooks",`${p}.ts`),o?kr({hookName:p,componentName:c,featureName:r}):jr({hookName:p})),He(M.join(t,"types",`${r}.types.ts`),Ge({componentName:c,withStore:o})),He(M.join(t,"index.ts"),br({featureName:r,componentName:c,hookName:p,withStore:o,withService:i}))]),o&&await Se({name:r,outputPath:M.join(t,"store"),persist:n,typesImportPath:`../types/${r}.types`}),i&&s&&await ye({name:r,outputPath:M.join(t,"services"),httpClient:s})};import{mkdir as cn,writeFile as pn}from"node:fs/promises";import dt from"node:path";var Fr=e=>{let{hookName:r,isClient:t}=e,o=[];return t&&o.push("'use client';"),o.push("import { useState, useCallback } from 'react';"),o.push(""),o.push(`export const ${r} = () => {`),o.push(" const [loading, setLoading] = useState(false);"),o.push(" const [error, setError] = useState<string | null>(null);"),o.push(""),o.push(" const execute = useCallback(async () => {"),o.push(" setLoading(true);"),o.push(" setError(null);"),o.push(" try {"),o.push(" // Add your logic here"),o.push(" } catch (err) {"),o.push(" setError(err instanceof Error ? err.message : 'An error occurred');"),o.push(" } finally {"),o.push(" setLoading(false);"),o.push(" }"),o.push(" }, []);"),o.push(""),o.push(" return {"),o.push(" loading,"),o.push(" error,"),o.push(" execute,"),o.push(" } as const;"),o.push("};"),o.push(""),o.join(`
433
+ `)};var ut=async e=>{let{name:r,projectPath:t,isClient:o,featurePath:n}=e,s=`use${R(r)}`,c;n?c=dt.join(t,n,"hooks"):c=dt.join(t,"src","hooks"),await cn(c,{recursive:!0}),await pn(dt.join(c,`${s}.ts`),Fr({hookName:s,isClient:o}))};T();import{copyFile as ln,readFile as mn,writeFile as dn}from"node:fs/promises";import we from"node:path";var ft=async e=>{let{code:r,name:t,country:o,flag:n,projectPath:i,copyTranslations:s}=e;await un(i,r,s),await fn(i,r),await gn(i,r,t,o,n)},un=async(e,r,t)=>{let o=we.join(e,"src","i18n","translations"),n=we.join(o,"en.json"),i=we.join(o,`${r}.json`);if(t)await ln(n,i);else{let s=await mn(n,"utf-8"),c=JSON.parse(s),p=Dr(c);await dn(i,`${JSON.stringify(p,null,2)}
434
+ `)}},Dr=e=>{let r={};for(let[t,o]of Object.entries(e))typeof o=="object"&&o!==null?r[t]=Dr(o):r[t]="";return r},fn=async(e,r)=>{let t=we.join(e,"src","types","i18n.ts");if(!l(t))return;let o=await d(t),n=/export type SupportedLocale = (.*);/,i=o.match(n);if(i&&!i[1].includes(`'${r}'`)){let s=`${i[1]} | '${r}'`;o=o.replace(n,`export type SupportedLocale = ${s};`),await u(t,o)}},gn=async(e,r,t,o,n)=>{let i=we.join(e,"src","lib","config","app-locales.ts");if(!l(i))return;let s=await d(i);if(s.includes(`locale: '${r}'`))return;let c=s.lastIndexOf("];");if(c===-1)return;let p=` {
435
+ name: '${t}',
436
+ locale: '${r}',
437
+ flag: '${n}',
438
+ country: '${o}',
439
+ },
440
+ `;s=s.slice(0,c)+p+s.slice(c),await u(i,s)};import{mkdir as hn,writeFile as gt}from"node:fs/promises";import ve from"node:path";var Lr=e=>{let{componentName:r,routePath:t,hasI18n:o}=e;return o?`import { generateSEOMetadata } from '@/lib/config/seo';
441
+ import type { Metadata } from 'next';
272
442
  import { getTranslations, setRequestLocale } from 'next-intl/server';
443
+ import type { SupportedLocale } from '@/types/i18n';
273
444
 
274
445
  type Props = {
275
446
  params: Promise<{ locale: string }>;
@@ -277,20 +448,20 @@ type Props = {
277
448
 
278
449
  export async function generateMetadata(props: Props): Promise<Metadata> {
279
450
  const locale = (await props.params).locale as SupportedLocale;
280
- const t = await getTranslations({ locale, namespace: '${o}' });
451
+ const t = await getTranslations({ locale, namespace: '${r}' });
281
452
 
282
453
  return generateSEOMetadata({
283
454
  title: t('title'),
284
455
  description: t('description'),
285
- path: '${e}',
456
+ path: '${t}',
286
457
  });
287
458
  }
288
459
 
289
- export default async function ${o}Page(props: Props) {
460
+ export default async function ${r}Page(props: Props) {
290
461
  const locale = (await props.params).locale as SupportedLocale;
291
462
  setRequestLocale(locale);
292
463
 
293
- const t = await getTranslations('${o}');
464
+ const t = await getTranslations('${r}');
294
465
 
295
466
  return (
296
467
  <div>
@@ -298,84 +469,84 @@ export default async function ${o}Page(props: Props) {
298
469
  </div>
299
470
  );
300
471
  }
301
- `:`import { Metadata } from 'next';
472
+ `:`import type { Metadata } from 'next';
302
473
 
303
474
  export const metadata: Metadata = {
304
- title: '${o}',
305
- description: '${o} page',
475
+ title: '${r}',
476
+ description: '${r} page',
306
477
  };
307
478
 
308
- export default function ${o}Page() {
479
+ export default function ${r}Page() {
309
480
  return (
310
481
  <div>
311
- <h1>${o}</h1>
482
+ <h1>${r}</h1>
312
483
  </div>
313
484
  );
314
485
  }
315
- `},go=t=>{let{componentName:o,paramName:e,routePath:r,hasI18n:n}=t;return n?`import { generateSEOMetadata } from '@/lib/config/seo';
316
- import { SupportedLocale } from '@/types/i18n';
317
- import { Metadata } from 'next';
486
+ `},Gr=e=>{let{componentName:r,paramName:t,routePath:o,hasI18n:n}=e;return n?`import { generateSEOMetadata } from '@/lib/config/seo';
487
+ import type { Metadata } from 'next';
318
488
  import { getTranslations, setRequestLocale } from 'next-intl/server';
489
+ import type { SupportedLocale } from '@/types/i18n';
319
490
 
320
491
  type Props = {
321
- params: Promise<{ locale: string; ${e}: string }>;
492
+ params: Promise<{ locale: string; ${t}: string }>;
322
493
  };
323
494
 
324
495
  export async function generateMetadata(props: Props): Promise<Metadata> {
325
- const { locale, ${e} } = await props.params;
326
- const t = await getTranslations({ locale: locale as SupportedLocale, namespace: '${o}' });
496
+ const { locale, ${t} } = await props.params;
497
+ const t = await getTranslations({ locale: locale as SupportedLocale, namespace: '${r}' });
327
498
 
328
499
  return generateSEOMetadata({
329
500
  title: t('title'),
330
501
  description: t('description'),
331
- path: '${r}',
502
+ path: '${o}',
332
503
  });
333
504
  }
334
505
 
335
- export default async function ${o}Page(props: Props) {
336
- const { locale, ${e} } = await props.params;
506
+ export default async function ${r}Page(props: Props) {
507
+ const { locale, ${t} } = await props.params;
337
508
  setRequestLocale(locale);
338
509
 
339
- const t = await getTranslations('${o}');
510
+ const t = await getTranslations('${r}');
340
511
 
341
512
  return (
342
513
  <div>
343
514
  <h1>{t('title')}</h1>
344
- <p>${o}: {${e}}</p>
515
+ <p>${r}: {${t}}</p>
345
516
  </div>
346
517
  );
347
518
  }
348
- `:`import { Metadata } from 'next';
519
+ `:`import type { Metadata } from 'next';
349
520
 
350
521
  export const metadata: Metadata = {
351
- title: '${o}',
352
- description: '${o} page',
522
+ title: '${r}',
523
+ description: '${r} page',
353
524
  };
354
525
 
355
526
  type Props = {
356
- params: Promise<{ ${e}: string }>;
527
+ params: Promise<{ ${t}: string }>;
357
528
  };
358
529
 
359
- export default async function ${o}Page(props: Props) {
360
- const { ${e} } = await props.params;
530
+ export default async function ${r}Page(props: Props) {
531
+ const { ${t} } = await props.params;
361
532
 
362
533
  return (
363
534
  <div>
364
- <h1>${o}</h1>
365
- <p>${o}: {${e}}</p>
535
+ <h1>${r}</h1>
536
+ <p>${r}: {${t}}</p>
366
537
  </div>
367
538
  );
368
539
  }
369
- `},ho=t=>`export default function ${t.componentName}Loading() {
540
+ `},Hr=e=>`export default function ${e.componentName}Loading() {
370
541
  return (
371
542
  <div className="flex h-full items-center justify-center">
372
543
  <p>Loading...</p>
373
544
  </div>
374
545
  );
375
546
  }
376
- `,xo=t=>`'use client';
547
+ `,Ur=e=>`'use client';
377
548
 
378
- export default function ${t.componentName}Error({
549
+ export default function ${e.componentName}Error({
379
550
  error,
380
551
  reset,
381
552
  }: {
@@ -390,65 +561,126 @@ export default function ${t.componentName}Error({
390
561
  </div>
391
562
  );
392
563
  }
393
- `;var rt=async t=>{let{name:o,projectPath:e,hasI18n:r,dynamic:n,withLoading:i=!1,withError:s=!1}=t,c=N(o),m=`/${o}`,f=r?"src/app/[locale]":"src/app",x;n?x=ge.join(e,f,o,`[${n}]`):x=ge.join(e,f,o),await vi(x,{recursive:!0});let S=n?go({componentName:c,routePath:n?`${m}/[${n}]`:m,paramName:n,hasI18n:r}):fo({componentName:c,routePath:m,hasI18n:r});await ot(ge.join(x,"page.tsx"),S),i&&await ot(ge.join(x,"loading.tsx"),ho({componentName:c})),s&&await ot(ge.join(x,"error.tsx"),xo({componentName:c}))};import{writeFile as nt,mkdir as Po}from"node:fs/promises";import ie from"node:path";var it=t=>{let{componentName:o,isClient:e,hasI18n:r}=t,n=t.translationNamespace||o,i=[];return(e||r)&&i.push("'use client';"),r&&i.push("import { useTranslations } from 'next-intl';"),i.push(""),i.push(`export function ${o}() {`),r?(i.push(` const t = useTranslations('${n}');`),i.push(""),i.push(" return ("),i.push(" <div>"),i.push(" <h2>{t('title')}</h2>"),i.push(" </div>"),i.push(" );")):(i.push(" return ("),i.push(" <div>"),i.push(` <h2>${o}</h2>`),i.push(" </div>"),i.push(" );")),i.push("}"),i.push(""),i.join(`
394
- `)},yo=t=>`export { ${t.componentName} } from './${t.componentName}';
395
- `;P();var st=async t=>{let{name:o,projectPath:e,isClient:r,hasI18n:n,featurePath:i}=t,s=N(o);i?await Ti(s,e,i,r,n):await Ei(s,o,e,r,n)},Ti=async(t,o,e,r,n)=>{let i=ie.join(o,e,"components");await Po(i,{recursive:!0}),await nt(ie.join(i,`${t}.tsx`),it({componentName:t,isClient:r,hasI18n:n}))},Ei=async(t,o,e,r,n)=>{let i=ie.join(e,"src","components","common",t);await Po(i,{recursive:!0}),await nt(ie.join(i,`${t}.tsx`),it({componentName:t,isClient:r,hasI18n:n})),await nt(ie.join(i,"index.ts"),yo({componentName:t}));let s=ie.join(e,"src","components","common","index.ts");await Ii(s,`export { ${t} } from './${t}';
396
- `);let c=ie.join(e,"src","components","index.ts");await Ni(c)},Ii=async(t,o)=>{let e="";l(t)&&(e=await d(t)),e.includes(o.trim())||(e+=o,await u(t,e))},Ni=async t=>{let o="";l(t)&&(o=await d(t));let e=`export * from './common';
397
- `;o.includes(e.trim())||(o+=e,await u(t,o))};P();import{readFile as Ri,writeFile as $i,copyFile as Ai}from"node:fs/promises";import he from"node:path";var at=async t=>{let{code:o,name:e,country:r,flag:n,projectPath:i,copyTranslations:s}=t;await bi(i,o,s),await Oi(i,o),await ki(i,o,e,r,n)},bi=async(t,o,e)=>{let r=he.join(t,"src","i18n","translations"),n=he.join(r,"en.json"),i=he.join(r,`${o}.json`);if(e)await Ai(n,i);else{let s=await Ri(n,"utf-8"),c=JSON.parse(s),m=wo(c);await $i(i,JSON.stringify(m,null,2)+`
398
- `)}},wo=t=>{let o={};for(let[e,r]of Object.entries(t))typeof r=="object"&&r!==null?o[e]=wo(r):o[e]="";return o},Oi=async(t,o)=>{let e=he.join(t,"src","types","i18n.ts");if(!l(e))return;let r=await d(e),n=/export type SupportedLocale = (.*);/,i=r.match(n);if(i&&!i[1].includes(`'${o}'`)){let s=`${i[1]} | '${o}'`;r=r.replace(n,`export type SupportedLocale = ${s};`),await u(e,r)}},ki=async(t,o,e,r,n)=>{let i=he.join(t,"src","lib","config","app-locales.ts");if(!l(i))return;let s=await d(i);if(s.includes(`locale: '${o}'`))return;let c=s.lastIndexOf("];");if(c===-1)return;let m=` {
399
- name: '${e}',
400
- locale: '${o}',
401
- flag: '${n}',
402
- country: '${r}',
403
- },
404
- `;s=s.slice(0,c)+m+s.slice(c),await u(i,s)};import{writeFile as _i,mkdir as ji}from"node:fs/promises";import ct from"node:path";var So=t=>{let{hookName:o,isClient:e}=t,r=[];return e&&r.push("'use client';"),r.push("import { useState, useCallback } from 'react';"),r.push(""),r.push(`export const ${o} = () => {`),r.push(" const [loading, setLoading] = useState(false);"),r.push(" const [error, setError] = useState<string | null>(null);"),r.push(""),r.push(" const execute = useCallback(async () => {"),r.push(" setLoading(true);"),r.push(" setError(null);"),r.push(" try {"),r.push(" // Add your logic here"),r.push(" } catch (err) {"),r.push(" setError(err instanceof Error ? err.message : 'An error occurred');"),r.push(" } finally {"),r.push(" setLoading(false);"),r.push(" }"),r.push(" }, []);"),r.push(""),r.push(" return {"),r.push(" loading,"),r.push(" error,"),r.push(" execute,"),r.push(" } as const;"),r.push("};"),r.push(""),r.join(`
405
- `)};var pt=async t=>{let{name:o,projectPath:e,isClient:r,featurePath:n}=t,s=`use${N(o)}`,c;n?c=ct.join(e,n,"hooks"):c=ct.join(e,"src","hooks"),await ji(c,{recursive:!0}),await _i(ct.join(c,`${s}.ts`),So({hookName:s,isClient:r}))};import{readFile as Fi,writeFile as Di}from"node:fs/promises";import Li from"node:path";var mt=(t,o)=>{let e=/import\s+.*\s+from\s+['"].*['"];?\n/g,r=t.match(e);if(r&&r.length>0){let n=r[r.length-1],i=t.lastIndexOf(n);return t.slice(0,i+n.length)+o+`
406
- `+t.slice(i+n.length)}return o+`
407
- `+t},lt=(t,o,e)=>{let r=/combineReducers\(\{([^}]*)\}\)/s,n=t.match(r);if(!n)throw new Error("Could not find combineReducers in rootReducer.ts");let i=n[1],s=`
408
- ${o}: ${e},`,c=i.trimEnd()+s;return t.replace(r,`combineReducers({${c}
409
- })`)},xe=(t,o)=>{let e=t.lastIndexOf("} as const;");if(e===-1)throw new Error("Could not find closing brace of AppApis object");let r=t.substring(0,e),n=t.substring(e);return r.trimEnd()+`
410
- `+o+`
411
- `+n};var ye=async t=>{let{projectPath:o,name:e,persist:r,importPath:n}=t,i=Li.join(o,"src","store","rootReducer.ts");try{let s=await Fi(i,"utf-8"),c=k(e),m=`${c}Reducer`,f=`${c}PersistConfig`,x=n.replace(/^src\//,"@/"),S=r?`import { ${m}, ${f} } from '${x}';`:`import { ${m} } from '${x}';`;s=mt(s,S);let v=r?`persistReducer(${f}, ${m})`:m;s=lt(s,c,v),await Di(i,s)}catch(s){throw new Error(`Failed to register reducer '${e}' in rootReducer: ${s}`,{cause:s})}};import{readFile as Hi,writeFile as Gi}from"node:fs/promises";import Mi from"node:path";var Pe=async t=>{let{serviceName:o,projectPath:e}=t,r=k(o),n=Mi.join(e,"src","lib","config","app-apis.ts");try{let i=await Hi(n,"utf-8");if(i.includes(`${r}:`))return;if(!i.match(/export const AppApis = \{[\s\S]*?\} as const;/))throw new Error("Could not find AppApis object in app-apis.ts");let s=` ${r}: {
412
- base: \`\${API_PREFIX}/${o}\`,
413
- getAll: \`\${API_PREFIX}/${o}\`,
414
- },`;i=xe(i,s),await Gi(n,i)}catch(i){throw new Error(`Failed to register API endpoints: ${i}`,{cause:i})}};import{readFile as Ui,writeFile as Xi}from"node:fs/promises";import Ji from"node:path";P();var dt=async(t,o,e)=>{let r=Ji.join(t,"src","lib","config","app-paths.ts");if(!l(r))return;let n=await Ui(r,"utf-8"),i=k(o);if(n.includes(`${i}:`))return;let s=n.lastIndexOf("} as const;");if(s===-1)return;let c=` ${i}: '${e}',
415
- `;n=n.slice(0,s)+c+n.slice(s),await Xi(r,n)};P();import{readFile as Yi,writeFile as zi}from"node:fs/promises";import Wi from"node:path";var ut=async(t,o)=>{let e=Wi.join(t,"src","i18n","translations","en.json");if(!l(e))return;let r=await Yi(e,"utf-8"),n=JSON.parse(r);n[o]||(n[o]={title:o,description:`${o} page description`},await zi(e,JSON.stringify(n,null,2)+`
416
- `))};W();var ft=()=>[{name:"Project setup detected",spinnerText:"Detecting project setup...",execute:async t=>{t.detection=await _(t.projectPath)}},{name:"Feature files generated",spinnerText:"Generating feature files...",execute:async t=>{await et({name:t.featureName,outputPath:t.featurePath,createStore:t.createStore,persistStore:t.persistStore,createService:t.createService,httpClient:t.httpClient})}},{name:"API endpoints registered",spinnerText:"Registering API endpoints...",shouldSkip:t=>!t.createService,execute:async t=>{await Pe({serviceName:t.featureName,projectPath:t.projectPath})}},{name:"Feature registered in rootReducer",spinnerText:"Registering feature in rootReducer...",shouldSkip:t=>!t.createStore||!t.detection.hasRedux,execute:async t=>{await ye({projectPath:t.projectPath,name:t.featureName,persist:t.persistStore,importPath:Bi.join(t.basePath,t.featureName,"store")})}}];import Vi from"node:path";var gt=()=>[{name:"Slice files generated",spinnerText:"Generating slice files...",execute:async t=>{await ue({name:t.sliceName,outputPath:t.slicePath,persist:t.persistSlice})}},{name:"Slice registered in rootReducer",spinnerText:"Registering slice in rootReducer...",execute:async t=>{await ye({projectPath:t.projectPath,name:t.sliceName,persist:t.persistSlice,importPath:Vi.join(t.basePath,t.sliceName)})}}];var ht=()=>[{name:"Service files generated",spinnerText:"Generating service files...",execute:async t=>{await fe({name:t.serviceName,outputPath:t.servicePath,httpClient:t.httpClient})}},{name:"API endpoints registered",spinnerText:"Registering API endpoints...",execute:async t=>{await Pe({serviceName:t.serviceName,projectPath:t.projectPath})}}];var Co=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(o,e)=>{try{let r=process.cwd();qi(e),p($.cyan(`
564
+ `;var ht=async e=>{let{name:r,projectPath:t,hasI18n:o,dynamic:n,withLoading:i=!1,withError:s=!1}=e,c=R(r),p=`/${r}`,f=o?"src/app/[locale]":"src/app",g;n?g=ve.join(t,f,r,`[${n}]`):g=ve.join(t,f,r),await hn(g,{recursive:!0});let y=n?Gr({componentName:c,routePath:n?`${p}/[${n}]`:p,paramName:n,hasI18n:o}):Lr({componentName:c,routePath:p,hasI18n:o});await gt(ve.join(g,"page.tsx"),y),i&&await gt(ve.join(g,"loading.tsx"),Hr({componentName:c})),s&&await gt(ve.join(g,"error.tsx"),Ur({componentName:c}))};T();import Ce from"node:path";var Mr=e=>{let{componentName:r,sourceImportPath:t,testUtilsImportPath:o,hasRedux:n,hasI18n:i}=e,s=[];i&&s.push("messages: {}"),n&&s.push("preloadedState: {}");let c=s.length?`, {
565
+ ${s.join(`,
566
+ `)},
567
+ }`:"";return`import { describe, expect, it } from 'vitest';
568
+ import { renderWithProviders, screen } from '${o}';
569
+ import { ${r} } from '${t}';
570
+
571
+ describe('${r}', () => {
572
+ it('renders without crashing', () => {
573
+ renderWithProviders(<${r} />${c});
574
+ // TODO: assert something meaningful about the rendered output.
575
+ expect(screen).toBeDefined();
576
+ });
577
+ });
578
+ `},Jr=e=>{let{hookName:r,sourceImportPath:t,withStore:o,testUtilsImportPath:n}=e;return o?`import { renderHook } from '@testing-library/react';
579
+ import { describe, expect, it } from 'vitest';
580
+ import { TestProviders } from '${n}';
581
+ import { ${r} } from '${t}';
582
+
583
+ describe('${r}', () => {
584
+ it('returns a defined value', () => {
585
+ const { result } = renderHook(() => ${r}(), { wrapper: TestProviders });
586
+ expect(result.current).toBeDefined();
587
+ });
588
+ });
589
+ `:`import { renderHook } from '@testing-library/react';
590
+ import { describe, expect, it } from 'vitest';
591
+ import { ${r} } from '${t}';
592
+
593
+ describe('${r}', () => {
594
+ it('returns a defined value', () => {
595
+ const { result } = renderHook(() => ${r}());
596
+ expect(result.current).toBeDefined();
597
+ });
598
+ });
599
+ `},zr=e=>{let{camelName:r,sourceImportPath:t}=e,o=`${r}Slice`;return`import { describe, expect, it } from 'vitest';
600
+ import { ${o}, resetState, setError, setLoading } from '${t}';
601
+
602
+ describe('${o}', () => {
603
+ const initialState = { loading: false, error: null } as const;
604
+
605
+ it('returns the initial state', () => {
606
+ expect(${o}.reducer(undefined, { type: '@@INIT' })).toEqual(initialState);
607
+ });
608
+
609
+ it('handles setLoading', () => {
610
+ const next = ${o}.reducer(initialState, setLoading(true));
611
+ expect(next.loading).toBe(true);
612
+ });
613
+
614
+ it('handles setError', () => {
615
+ const next = ${o}.reducer(initialState, setError('boom'));
616
+ expect(next.error).toBe('boom');
617
+ });
618
+
619
+ it('handles resetState', () => {
620
+ const next = ${o}.reducer({ loading: true, error: 'boom' }, resetState());
621
+ expect(next).toEqual(initialState);
622
+ });
623
+ });
624
+ `};var q=async e=>{let{projectPath:r,sourceFile:t,kind:o,symbolName:n}=e,i=Ce.dirname(t),s=Ce.basename(t).replace(/\.(tsx?|jsx?)$/i,""),c=o==="component"?".tsx":".ts",p=Ce.join(i,`${s}.test${c}`),f=`./${s}`,g=xn(i,Ce.join(r,"test","test-utils")),y;return o==="component"?y=Mr({componentName:n,sourceImportPath:f,testUtilsImportPath:g,hasRedux:!!e.hasRedux,hasI18n:!!e.hasI18n}):o==="hook"?y=Jr({hookName:n,sourceImportPath:f,withStore:!!e.hookUsesStore,testUtilsImportPath:e.hookUsesStore?g:void 0}):y=zr({camelName:n,sourceImportPath:f}),await u(p,y),p},xn=(e,r)=>{let t=Ce.relative(e,r).replace(/\\/g,"/");return t.startsWith(".")?t:`./${t}`};import yn from"enquirer";var{prompt:Pn}=yn,Br=async e=>{let r=[];e||r.push({type:"input",name:"componentName",message:"Component name (kebab-case):",validate:o=>o?/^[a-z][a-z0-9-]*$/.test(o)?!0:"Use lowercase letters, numbers, and hyphens only":"Component name is required"}),r.push({type:"confirm",name:"isClient",message:"Add 'use client' directive?",initial:!1});let t=await Pn(r);return{componentName:e||t.componentName,isClient:t.isClient}};var Xr=e=>{e.command("component [name]").description("Generate a shared component").option("--client","Add 'use client' directive").option("--i18n","Add useTranslations hook").option("--feature <path>","Generate in feature directory (e.g., src/features/auth)").option("--test","Also generate a sibling test file").option("--no-test","Skip test file generation").action(async(r,t)=>{try{let o=process.cwd();m(V.cyan(`
625
+ \u{1F9E9} Component Generator
626
+ `)),h.start("Detecting project setup...");let n=await O(o);h.succeed("Project setup detected");let i=await Br(r),s=R(i.componentName),c=t.client??i.isClient,p=t.i18n??!1,f=Tn(t,n.hasTests);h.start("Generating component..."),await pt({name:i.componentName,projectPath:o,isClient:c||p,hasI18n:p,featurePath:t.feature}),h.succeed("Component generated");let g=null;if(f){let x=t.feature?xt.join(o,t.feature,"components",`${s}.tsx`):xt.join(o,"src/components/common",s,`${s}.tsx`);h.start("Generating test..."),g=await q({projectPath:o,sourceFile:x,kind:"component",symbolName:s,hasRedux:n.hasRedux,hasI18n:n.hasI18n}),h.succeed("Test generated")}let y=t.feature?`${t.feature}/components/${s}.tsx`:`src/components/common/${s}/${s}.tsx`;m(V.green(`
627
+ \u2728 Component '${s}' created successfully!
628
+ `)),m(V.dim(` \u{1F4C4} ${y}`)),t.feature||(m(V.dim(` \u{1F4C4} src/components/common/${s}/index.ts`)),m(V.dim(" \u{1F4DD} Updated src/components/common/index.ts")),m(V.dim(" \u{1F4DD} Updated src/components/index.ts"))),g&&m(V.dim(` \u{1F9EA} ${xt.relative(o,g)}`)),m(""),m(V.cyan("Usage:")),t.feature?m(V.dim(` import { ${s} } from '${t.feature.replace(/^src\//,"@/")}/components/${s}';`)):m(V.dim(` import { ${s} } from '@/components';`)),m("")}catch(o){h.fail("Component generation failed"),w(`${o}`),process.exit(1)}})},Tn=(e,r)=>e.noTest?!1:e.test?!0:r;import Et from"node:path";import k from"picocolors";U();U();import _n from"node:path";import{readFile as Sn,writeFile as wn}from"node:fs/promises";import vn from"node:path";var yt=(e,r)=>{let t=/import\s+.*\s+from\s+['"].*['"];?\n/g,o=e.match(t);if(o&&o.length>0){let n=o[o.length-1],i=e.lastIndexOf(n);return e.slice(0,i+n.length)+r+`
629
+ `+e.slice(i+n.length)}return`${r}
630
+ ${e}`},Pt=(e,r,t)=>{let o=/combineReducers\(\{([^}]*)\}\)/s,n=e.match(o);if(!n)throw new Error("Could not find combineReducers in rootReducer.ts");let i=n[1],s=`
631
+ ${r}: ${t},`,c=i.trimEnd()+s;return e.replace(o,`combineReducers({${c}
632
+ })`)},Ee=(e,r)=>{let t=e.lastIndexOf("} as const;");if(t===-1)throw new Error("Could not find closing brace of AppApis object");let o=e.substring(0,t),n=e.substring(t);return`${o.trimEnd()}
633
+ ${r}
634
+ ${n}`};var Ie=async e=>{let{serviceName:r,projectPath:t}=e,o=$(r),n=vn.join(t,"src","lib","config","app-apis.ts");try{let i=await Sn(n,"utf-8");if(i.includes(`${o}:`))return;if(!i.match(/export const AppApis = \{[\s\S]*?\} as const;/))throw new Error("Could not find AppApis object in app-apis.ts");let s=` ${o}: {
635
+ base: \`\${API_PREFIX}/${r}\`,
636
+ getAll: \`\${API_PREFIX}/${r}\`,
637
+ },`;i=Ee(i,s),await wn(n,i)}catch(i){throw new Error(`Failed to register API endpoints: ${i}`,{cause:i})}};import{readFile as Cn,writeFile as En}from"node:fs/promises";import In from"node:path";T();var Tt=async(e,r,t)=>{let o=In.join(e,"src","lib","config","app-paths.ts");if(!l(o))return;let n=await Cn(o,"utf-8"),i=$(r);if(n.includes(`${i}:`))return;let s=n.lastIndexOf("} as const;");if(s===-1)return;let c=` ${i}: '${t}',
638
+ `;n=n.slice(0,s)+c+n.slice(s),await En(o,n)};import{readFile as Rn,writeFile as Nn}from"node:fs/promises";import bn from"node:path";var Re=async e=>{let{projectPath:r,name:t,persist:o,importPath:n}=e,i=bn.join(r,"src","store","rootReducer.ts");try{let s=await Rn(i,"utf-8"),c=$(t),p=`${c}Reducer`,f=`${c}PersistConfig`,g=n.replace(/^src\//,"@/"),y=o?`import { ${p}, ${f} } from '${g}';`:`import { ${p} } from '${g}';`;s=yt(s,y);let x=o?`persistReducer(${f}, ${p})`:p;s=Pt(s,c,x),await Nn(i,s)}catch(s){throw new Error(`Failed to register reducer '${t}' in rootReducer: ${s}`,{cause:s})}};T();import{readFile as $n,writeFile as An}from"node:fs/promises";import On from"node:path";var St=async(e,r)=>{let t=On.join(e,"src","i18n","translations","en.json");if(!l(t))return;let o=await $n(t,"utf-8"),n=JSON.parse(o);n[r]||(n[r]={title:r,description:`${r} page description`},await An(t,`${JSON.stringify(n,null,2)}
639
+ `))};var wt=()=>[{name:"Project setup detected",spinnerText:"Detecting project setup...",execute:async e=>{e.detection=await O(e.projectPath)}},{name:"Feature files generated",spinnerText:"Generating feature files...",execute:async e=>{await mt({name:e.featureName,outputPath:e.featurePath,createStore:e.createStore,persistStore:e.persistStore,createService:e.createService,httpClient:e.httpClient})}},{name:"API endpoints registered",spinnerText:"Registering API endpoints...",shouldSkip:e=>!e.createService,execute:async e=>{await Ie({serviceName:e.featureName,projectPath:e.projectPath})}},{name:"Feature registered in rootReducer",spinnerText:"Registering feature in rootReducer...",shouldSkip:e=>!e.createStore||!e.detection.hasRedux,execute:async e=>{await Re({projectPath:e.projectPath,name:e.featureName,persist:e.persistStore,importPath:_n.join(e.basePath,e.featureName,"store")})}}];var me=async(e,r)=>{for(let t of e)if(!t.shouldSkip?.(r)){r.spinner.start(t.spinnerText);try{await t.execute(r),r.spinner.succeed(t.name)}catch(o){throw r.spinner.fail(t.name),o}}};var vt=()=>[{name:"Service files generated",spinnerText:"Generating service files...",execute:async e=>{await ye({name:e.serviceName,outputPath:e.servicePath,httpClient:e.httpClient})}},{name:"API endpoints registered",spinnerText:"Registering API endpoints...",execute:async e=>{await Ie({serviceName:e.serviceName,projectPath:e.projectPath})}}];import kn from"node:path";var Ct=()=>[{name:"Slice files generated",spinnerText:"Generating slice files...",execute:async e=>{await Se({name:e.sliceName,outputPath:e.slicePath,persist:e.persistSlice})}},{name:"Slice registered in rootReducer",spinnerText:"Registering slice in rootReducer...",execute:async e=>{await Re({projectPath:e.projectPath,name:e.sliceName,persist:e.persistSlice,importPath:kn.join(e.basePath,e.sliceName)})}}];import jn from"enquirer";var{prompt:Fn}=jn,Yr=async(e,r,t,o,n,i,s)=>{let c=[];e||c.push({type:"input",name:"featureName",message:"What is the feature name?",initial:"my-feature",validate:f=>/^[a-z0-9-]+$/.test(f)?!0:"Feature name must be lowercase and contain only alphanumeric characters and hyphens."}),r&&o===void 0&&n===void 0&&(c.push({type:"confirm",name:"createStore",message:"Generate Redux store for this feature?",initial:!0}),c.push({type:"confirm",name:"persistStore",message:"Enable persistence for this store?",initial:!1,skip(){return!this.state.answers.createStore}})),t&&t!=="none"&&i===void 0&&s===void 0&&(c.push({type:"confirm",name:"createService",message:"Generate API service for this feature?",initial:!0}),t==="both"&&c.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 p=c.length>0?await Fn(c):{};return{featureName:e||p.featureName,hasRedux:r||!1,createStore:o===!0?!1:n!==void 0?!0:p.createStore||!1,persistStore:n==="persist"?!0:n==="no-persist"?!1:p.persistStore||!1,httpClient:t||"none",createService:i===!0?!1:s!==void 0?!0:p.createService||!1,selectedHttpClient:s||p.selectedHttpClient||(t==="both"?"fetch":t!=="none"?t:void 0)}};var Vr=e=>{e.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(r,t)=>{try{let o=process.cwd();Dn(t),m(k.cyan(`
417
640
  \u{1F3AF} Feature Generator
418
- `));let n=ft();g.start("Detecting project setup...");let{detectProjectSetup:i}=await Promise.resolve().then(()=>(W(),to)),s=await i(r);g.succeed("Project setup detected"),p($.dim(` Redux: ${s.hasRedux?"\u2713":"\u2717"}`)),p($.dim(` HTTP Client: ${s.httpClient}`)),p($.dim(` i18n: ${s.hasI18n?"\u2713":"\u2717"}
419
- `));let c=await qt(o,s.hasRedux,s.httpClient,e.skipStore,e.store,e.skipService,e.service),m=e.path||xt.join("src","features"),f=xt.join(r,m,c.featureName);await Q(r,c.featureName,m)&&(C(`Feature '${c.featureName}' already exists at ${m}!`),process.exit(1)),await re(n.slice(1),{projectPath:r,spinner:g,featureName:c.featureName,basePath:m,featurePath:f,createStore:c.createStore,persistStore:c.persistStore,createService:c.createService,httpClient:c.selectedHttpClient,detection:s}),Ki(c,m)}catch(r){g.fail("Feature generation failed"),C(`${r}`),process.exit(1)}})},qi=t=>{t.store&&!["persist","no-persist"].includes(t.store)&&(C("Invalid --store option. Use: persist or no-persist"),process.exit(1)),t.service&&!["axios","fetch"].includes(t.service)&&(C("Invalid --service option. Use: axios or fetch"),process.exit(1)),t.skipStore&&t.store&&(C("Cannot use --skip-store and --store together"),process.exit(1)),t.skipService&&t.service&&(C("Cannot use --skip-service and --service together"),process.exit(1))},Ki=(t,o)=>{let e=xt.join(o,t.featureName);p($.green(`
420
- \u2728 Feature '${t.featureName}' created successfully!
421
- `)),p($.dim("Generated files:")),p($.dim(` \u{1F4C2} ${e}/`)),p($.dim(" \u251C\u2500\u2500 components/")),p($.dim(" \u251C\u2500\u2500 hooks/")),p($.dim(" \u251C\u2500\u2500 types/")),t.createStore&&p($.dim(" \u251C\u2500\u2500 store/")),t.createService&&p($.dim(" \u251C\u2500\u2500 services/")),p($.dim(` \u2514\u2500\u2500 index.ts
422
- `)),p($.cyan("Next steps:"));let r=o.replace(/^src\//,"@/");p($.dim(` 1. Import and use the feature: import { ${t.featureName} } from '${r}/${t.featureName}'`)),t.createStore&&p($.dim(` 2. Customize your Redux slice in: ${e}/store/`)),t.createService&&p($.dim(` 3. Add API methods in: ${e}/services/${t.featureName}.service.ts`)),p("")};import j from"picocolors";import pe from"node:path";import{existsSync as en}from"node:fs";import{mkdir as tn}from"node:fs/promises";import Zi from"enquirer";var{prompt:Qi}=Zi,vo=async(t,o,e)=>{let r=[];t||r.push({type:"input",name:"sliceName",message:"What is the slice name?",initial:"my-slice",validate:i=>/^[a-z0-9-]+$/.test(i)?!0:"Slice name must be lowercase and contain only alphanumeric characters and hyphens."}),o===void 0&&e===void 0&&r.push({type:"confirm",name:"persistSlice",message:"Enable persistence for this slice?",initial:!1});let n=r.length>0?await Qi(r):{};return{sliceName:t||n.sliceName,persistSlice:o===!0?!0:e===!1?!1:n.persistSlice||!1}};W();var To=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(o,e)=>{try{let r=process.cwd();e.persist&&e.noPersist===!0&&(C("Cannot use --persist and --no-persist together"),process.exit(1)),p(j.cyan(`
423
- \u{1F527} Slice Generator
424
- `)),g.start("Detecting project setup...");let n=await _(r);g.succeed("Project setup detected"),n.hasRedux||(g.fail("Redux is not setup in this project"),C("Please install @reduxjs/toolkit and react-redux first"),p(j.dim(`
425
- Run: npm install @reduxjs/toolkit react-redux
426
- `)),process.exit(1)),p(j.dim(` Redux: \u2713
427
- `));let i=await vo(o,e.persist,e.noPersist===!0?!1:void 0),{basePath:s,slicePath:c}=on(r,i.sliceName,e.path),m=pe.join(r,s);en(m)||await tn(m,{recursive:!0}),await Q(r,i.sliceName,s)&&(C(`Slice '${i.sliceName}' already exists at ${s}!`),process.exit(1)),await re(gt(),{projectPath:r,spinner:g,sliceName:i.sliceName,basePath:s,slicePath:c,persistSlice:i.persistSlice}),rn(i,s)}catch(r){g.fail("Slice generation failed"),C(`${r}`),process.exit(1)}})},on=(t,o,e)=>{let r;if(e){let n=e.replace(/^src\//,"");if(n.startsWith("features/")){let i=n.split("/")[1];r=pe.join("src","features",i,"store")}else r=pe.join("src",n)}else r=pe.join("src","features",o,"store");return{basePath:r,slicePath:pe.join(t,r,o)}},rn=(t,o)=>{let e=pe.join(o,t.sliceName);p(j.green(`
428
- \u2728 Slice '${t.sliceName}' created successfully!
429
- `)),p(j.dim("Generated files:")),p(j.dim(` \u{1F4C2} ${e}/`)),p(j.dim(` \u251C\u2500\u2500 ${t.sliceName}.slice.ts`)),p(j.dim(` \u251C\u2500\u2500 ${t.sliceName}.selectors.ts`)),t.persistSlice&&p(j.dim(" \u251C\u2500\u2500 persist.ts")),p(j.dim(` \u251C\u2500\u2500 ${t.sliceName}.types.ts`)),p(j.dim(` \u2514\u2500\u2500 index.ts
430
- `)),p(j.cyan("Next steps:"));let r=o.replace(/^src\//,"@/");p(j.dim(` 1. Import actions: import { setLoading, setError } from '${r}/${t.sliceName}'`)),p(j.dim(" 2. Use in component: dispatch(setLoading(true))")),p("")};import H from"picocolors";import we from"node:path";import{existsSync as cn}from"node:fs";import{mkdir as pn}from"node:fs/promises";import Eo from"enquirer";var Io=async(t,o,e,r)=>{let n=t||(await Eo.prompt({type:"input",name:"serviceName",message:"Service name (kebab-case):",validate:s=>s?/^[a-z0-9-]+$/.test(s)?!0:"Service name must be lowercase with hyphens only":"Service name is required"})).serviceName,i;return o!==void 0?i="axios":e!==void 0?i="fetch":r==="axios"?i="axios":r==="fetch"?i="fetch":r==="both"?i=(await Eo.prompt({type:"select",name:"httpClient",message:"Choose HTTP client:",choices:["axios","fetch"]})).httpClient:i="axios",{serviceName:n,httpClient:i}};W();import{readFile as nn,writeFile as sn}from"node:fs/promises";import an from"node:path";var No=async(t,o)=>{let e=k(o),r=an.join(t,"src","lib","config","app-apis.ts");try{let n=await nn(r,"utf-8");if(n.includes(`${e}:`))return;if(!n.match(/export const AppApis = \{[\s\S]*?\} as const;/))throw new Error("Could not find AppApis object in app-apis.ts");let i=uo({camelName:e,kebabName:o});n=xe(n,i),await sn(r,n)}catch(n){throw new Error(`Failed to register CRUD API endpoints: ${n}`,{cause:n})}};var Ro=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").option("--crud","Generate full CRUD service (getAll, getById, create, update, delete)").action(async(o,e)=>{try{let r=process.cwd();e.axios&&e.fetch&&(C("Cannot use --axios and --fetch together"),process.exit(1)),p(H.cyan(`
641
+ `));let n=wt();h.start("Detecting project setup...");let{detectProjectSetup:i}=await Promise.resolve().then(()=>(U(),wr)),s=await i(o);h.succeed("Project setup detected"),m(k.dim(` Redux: ${s.hasRedux?"\u2713":"\u2717"}`)),m(k.dim(` HTTP Client: ${s.httpClient}`)),m(k.dim(` i18n: ${s.hasI18n?"\u2713":"\u2717"}
642
+ `));let c=await Yr(r,s.hasRedux,s.httpClient,t.skipStore,t.store,t.skipService,t.service),p=t.path||Et.join("src","features"),f=Et.join(o,p,c.featureName);await oe(o,c.featureName,p)&&(w(`Feature '${c.featureName}' already exists at ${p}!`),process.exit(1)),await me(n.slice(1),{projectPath:o,spinner:h,featureName:c.featureName,basePath:p,featurePath:f,createStore:c.createStore,persistStore:c.persistStore,createService:c.createService,httpClient:c.selectedHttpClient,detection:s}),Ln(c,p)}catch(o){h.fail("Feature generation failed"),w(`${o}`),process.exit(1)}})},Dn=e=>{e.store&&!["persist","no-persist"].includes(e.store)&&(w("Invalid --store option. Use: persist or no-persist"),process.exit(1)),e.service&&!["axios","fetch"].includes(e.service)&&(w("Invalid --service option. Use: axios or fetch"),process.exit(1)),e.skipStore&&e.store&&(w("Cannot use --skip-store and --store together"),process.exit(1)),e.skipService&&e.service&&(w("Cannot use --skip-service and --service together"),process.exit(1))},Ln=(e,r)=>{let t=Et.join(r,e.featureName);m(k.green(`
643
+ \u2728 Feature '${e.featureName}' created successfully!
644
+ `)),m(k.dim("Generated files:")),m(k.dim(` \u{1F4C2} ${t}/`)),m(k.dim(" \u251C\u2500\u2500 components/")),m(k.dim(" \u251C\u2500\u2500 hooks/")),m(k.dim(" \u251C\u2500\u2500 types/")),e.createStore&&m(k.dim(" \u251C\u2500\u2500 store/")),e.createService&&m(k.dim(" \u251C\u2500\u2500 services/")),m(k.dim(` \u2514\u2500\u2500 index.ts
645
+ `)),m(k.cyan("Next steps:"));let o=r.replace(/^src\//,"@/");m(k.dim(` 1. Import and use the feature: import { ${e.featureName} } from '${o}/${e.featureName}'`)),e.createStore&&m(k.dim(` 2. Customize your Redux slice in: ${t}/store/`)),e.createService&&m(k.dim(` 3. Add API methods in: ${t}/services/${e.featureName}.service.ts`)),m("")};import It from"node:path";import ge from"picocolors";U();import Gn from"enquirer";var{prompt:Hn}=Gn,Kr=async e=>e?{hookName:e}:await Hn({type:"input",name:"hookName",message:'Hook name (kebab-case, without "use" prefix):',validate:t=>t?/^[a-z][a-z0-9-]*$/.test(t)?!0:"Use lowercase letters, numbers, and hyphens only":"Hook name is required"});var Wr=e=>{e.command("hook [name]").description("Generate a custom React hook").option("--client","Add 'use client' directive (default: true)",!0).option("--feature <path>","Generate in feature directory (e.g., src/features/auth)").option("--test","Also generate a sibling test file").option("--no-test","Skip test file generation").action(async(r,t)=>{try{let o=process.cwd();m(ge.cyan(`
646
+ \u{1FA9D} Hook Generator
647
+ `));let n=await O(o),i=await Kr(r),c=`use${R(i.hookName)}`,p=Un(t,n.hasTests);h.start("Generating hook..."),await ut({name:i.hookName,projectPath:o,isClient:t.client??!0,featurePath:t.feature}),h.succeed("Hook generated");let f=t.feature?It.join(o,t.feature,"hooks",`${c}.ts`):It.join(o,"src/hooks",`${c}.ts`),g=null;p&&(h.start("Generating test..."),g=await q({projectPath:o,sourceFile:f,kind:"hook",symbolName:c,hookUsesStore:n.hasRedux&&!!t.feature}),h.succeed("Test generated"));let y=t.feature?`${t.feature}/hooks/${c}.ts`:`src/hooks/${c}.ts`;m(ge.green(`
648
+ \u2728 Hook '${c}' created successfully!
649
+ `)),m(ge.dim(` \u{1F4C4} ${y}`)),g&&m(ge.dim(` \u{1F9EA} ${It.relative(o,g)}`)),m(""),m(ge.cyan("Usage:"));let x=t.feature?`${t.feature.replace(/^src\//,"@/")}/hooks/${c}`:`@/hooks/${c}`;m(ge.dim(` import { ${c} } from '${x}';`)),m("")}catch(o){h.fail("Hook generation failed"),w(`${o}`),process.exit(1)}})},Un=(e,r)=>e.noTest?!1:e.test?!0:r;import zn from"node:path";import K from"picocolors";T();U();import Mn from"enquirer";var{prompt:Jn}=Mn,qr=async e=>{let r=[];e||r.push({type:"input",name:"code",message:"Locale code (e.g., es, fr, de):",validate:o=>o?/^[a-z]{2}(-[A-Z]{2})?$/.test(o)?!0:"Use format: xx or xx-XX (e.g., es, pt-BR)":"Locale code is required"}),r.push({type:"input",name:"name",message:"Language name (e.g., Spanish, French):",validate:o=>o?!0:"Language name is required"},{type:"input",name:"country",message:"Country (e.g., Spain, France):",validate:o=>o?!0:"Country is required"},{type:"input",name:"flag",message:"Flag emoji (e.g., \u{1F1EA}\u{1F1F8}, \u{1F1EB}\u{1F1F7}):",validate:o=>o?!0:"Flag emoji is required"},{type:"confirm",name:"copyTranslations",message:"Copy translations from English? (No = empty values)",initial:!1});let t=await Jn(r);return{code:e||t.code,name:t.name,country:t.country,flag:t.flag,copyTranslations:t.copyTranslations}};var Zr=e=>{e.command("locale [code]").description("Add a new locale/language").option("--copy-translations","Copy translations from English instead of empty values").action(async(r,t)=>{try{let o=process.cwd();m(K.cyan(`
650
+ \u{1F30D} Locale Generator
651
+ `)),h.start("Detecting project setup...");let n=await O(o);h.succeed("Project setup detected"),n.hasI18n||(h.fail("i18n is not set up in this project"),w("Please set up internationalization first"),m(K.dim(`
652
+ Run: npx @teispace/next-maker setup --i18n
653
+ `)),process.exit(1));let i=await qr(r),s=zn.join(o,"src","i18n","translations",`${i.code}.json`);l(s)&&(w(`Locale '${i.code}' already exists!`),process.exit(1)),h.start("Adding locale..."),await ft({...i,projectPath:o,copyTranslations:t.copyTranslations??i.copyTranslations}),h.succeed("Locale added"),m(K.green(`
654
+ \u2728 Locale '${i.code}' (${i.name}) added successfully!
655
+ `)),m(K.dim("Updated files:")),m(K.dim(` \u{1F4C4} src/i18n/translations/${i.code}.json`)),m(K.dim(" \u{1F4DD} src/types/i18n.ts (SupportedLocale type)")),m(K.dim(" \u{1F4DD} src/lib/config/app-locales.ts")),m(""),m(K.cyan("Next steps:")),m(K.dim(` 1. Translate: src/i18n/translations/${i.code}.json`)),m(K.dim(` 2. Visit: http://localhost:3000/${i.code}`)),m("")}catch(o){h.fail("Locale generation failed"),w(`${o}`),process.exit(1)}})};import eo from"node:path";import J from"picocolors";U();import Bn from"enquirer";var{prompt:Xn}=Bn,Qr=async e=>{let r=[];e||r.push({type:"input",name:"pageName",message:"Page name (kebab-case):",validate:o=>o?/^[a-z][a-z0-9-]*$/.test(o)?!0:"Use lowercase letters, numbers, and hyphens only":"Page name is required"}),r.push({type:"confirm",name:"withLoading",message:"Generate loading.tsx?",initial:!0},{type:"confirm",name:"withError",message:"Generate error.tsx?",initial:!0});let t=await Xn(r);return{pageName:e||t.pageName,withLoading:t.withLoading,withError:t.withError}};var to=e=>{e.command("page [name]").description("Generate a new page/route").option("--dynamic <param>","Create dynamic route with parameter (e.g., id)").option("--loading","Generate loading.tsx").option("--error","Generate error.tsx").action(async(r,t)=>{try{let o=process.cwd();m(J.cyan(`
656
+ \u{1F4C4} Page Generator
657
+ `)),h.start("Detecting project setup...");let n=await O(o);h.succeed("Project setup detected"),m(J.dim(` i18n: ${n.hasI18n?"\u2713":"\u2717"}
658
+ `));let i=await Qr(r),s=i.pageName,c=R(s),p=n.hasI18n?"src/app/[locale]":"src/app";await oe(o,s,p)&&(w(`Page '${s}' already exists at ${p}/${s}!`),process.exit(1)),h.start("Generating page files..."),await ht({name:s,projectPath:o,hasI18n:n.hasI18n,dynamic:t.dynamic,withLoading:t.loading??i.withLoading,withError:t.error??i.withError}),h.succeed("Page files generated"),h.start("Registering route...");let g=t.dynamic?`/${s}/[${t.dynamic}]`:`/${s}`;await Tt(o,s,g),h.succeed("Route registered"),n.hasI18n&&(h.start("Adding translation namespace..."),await St(o,c),h.succeed("Translation namespace added"));let y=t.dynamic?eo.join(p,s,`[${t.dynamic}]`):eo.join(p,s);m(J.green(`
659
+ \u2728 Page '${s}' created successfully!
660
+ `)),m(J.dim("Generated files:")),m(J.dim(` \u{1F4C2} ${y}/`)),m(J.dim(" \u251C\u2500\u2500 page.tsx")),(t.loading??i.withLoading)&&m(J.dim(" \u251C\u2500\u2500 loading.tsx")),(t.error??i.withError)&&m(J.dim(" \u2514\u2500\u2500 error.tsx")),m(""),n.hasI18n&&(m(J.cyan("Next steps:")),m(J.dim(` 1. Add translations in: src/i18n/translations/en.json \u2192 "${c}"`)),m(J.dim(` 2. Visit: http://localhost:3000/${s}`)),m(""))}catch(o){h.fail("Page generation failed"),w(`${o}`),process.exit(1)}})};import{existsSync as Wn}from"node:fs";import{mkdir as qn}from"node:fs/promises";import Ne from"node:path";import z from"picocolors";U();import{readFile as Yn,writeFile as Vn}from"node:fs/promises";import Kn from"node:path";var ro=async(e,r)=>{let t=$(r),o=Kn.join(e,"src","lib","config","app-apis.ts");try{let n=await Yn(o,"utf-8");if(n.includes(`${t}:`))return;if(!n.match(/export const AppApis = \{[\s\S]*?\} as const;/))throw new Error("Could not find AppApis object in app-apis.ts");let i=Ir({camelName:t,kebabName:r});n=Ee(n,i),await Vn(o,n)}catch(n){throw new Error(`Failed to register CRUD API endpoints: ${n}`,{cause:n})}};import oo from"enquirer";var io=async(e,r,t,o)=>{let n=e||(await oo.prompt({type:"input",name:"serviceName",message:"Service name (kebab-case):",validate:s=>s?/^[a-z0-9-]+$/.test(s)?!0:"Service name must be lowercase with hyphens only":"Service name is required"})).serviceName,i;return r!==void 0?i="axios":t!==void 0?i="fetch":o==="axios"?i="axios":o==="fetch"?i="fetch":o==="both"?i=(await oo.prompt({type:"select",name:"httpClient",message:"Choose HTTP client:",choices:["axios","fetch"]})).httpClient:i="axios",{serviceName:n,httpClient:i}};var no=e=>{e.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").option("--crud","Generate full CRUD service (getAll, getById, create, update, delete)").action(async(r,t)=>{try{let o=process.cwd();t.axios&&t.fetch&&(w("Cannot use --axios and --fetch together"),process.exit(1)),m(z.cyan(`
431
661
  \u{1F527} Service Generator
432
- `)),g.start("Detecting project setup...");let n=await _(r);g.succeed("Project setup detected"),n.httpClient==="none"&&(g.fail("No HTTP client is setup in this project"),C("Please setup either AxiosClient or FetchClient first"),p(H.dim(`
662
+ `)),h.start("Detecting project setup...");let n=await O(o);h.succeed("Project setup detected"),n.httpClient==="none"&&(h.fail("No HTTP client is setup in this project"),w("Please setup either AxiosClient or FetchClient first"),m(z.dim(`
433
663
  Check: lib/utils/http/axios-client or lib/utils/http/fetch-client
434
- `)),process.exit(1));let i=[];(n.httpClient==="axios"||n.httpClient==="both")&&i.push("Axios \u2713"),(n.httpClient==="fetch"||n.httpClient==="both")&&i.push("Fetch \u2713"),p(H.dim(` HTTP Clients: ${i.join(", ")}
435
- `));let s=await Io(o,e.axios,e.fetch,n.httpClient),{basePath:c,servicePath:m}=mn(r,s.serviceName,e.path);cn(m)||await pn(m,{recursive:!0}),Ae(r,c,`${s.serviceName}.service.ts`)&&(C(`Service '${s.serviceName}' already exists at ${c}!`),process.exit(1)),e.crud?(g.start("Generating CRUD service files..."),await tt({name:s.serviceName,outputPath:m,httpClient:s.httpClient}),g.succeed("CRUD service files generated"),g.start("Registering CRUD API endpoints..."),await No(r,s.serviceName),g.succeed("CRUD API endpoints registered")):await re(ht(),{projectPath:r,spinner:g,serviceName:s.serviceName,servicePath:m,httpClient:s.httpClient}),ln(s,c,!!e.crud)}catch(r){g.fail("Service generation failed"),C(`${r}`),process.exit(1)}})},mn=(t,o,e)=>{let r;if(e){let n=e.replace(/^src\//,"");if(n.startsWith("features/")){let i=n.split("/")[1];r=we.join("src","features",i,"services")}else r=we.join("src",n)}else r=we.join("src","features",o,"services");return{basePath:r,servicePath:we.join(t,r)}},ln=(t,o,e=!1)=>{let r=we.join(o,`${t.serviceName}.service.ts`);p(H.green(`
436
- \u2728 ${e?"CRUD ":""}Service '${t.serviceName}' created successfully!
437
- `)),p(H.dim("Generated files:")),p(H.dim(` \u{1F4C4} ${r}
438
- `)),p(H.cyan("Next steps:"));let n=o.replace(/^src\//,"@/");p(H.dim(` 1. Import service: import { ${t.serviceName}Service } from '${n}/${t.serviceName}.service'`)),e?(p(H.dim(" 2. Available methods: getAll, getById, create, update, delete")),p(H.dim(" 3. Update DTO types in the service file"))):p(H.dim(` 2. Use in component: const data = await ${t.serviceName}Service.getAll()`)),p("")};import He from"picocolors";import Nn from"enquirer";P();import un from"node:path";import fn from"picocolors";P();T();import Se from"node:path";P();T();import $o from"node:path";var ke=async t=>{let o=[$o.join(t,a.ROOT_LAYOUT),$o.join(t,"src/app/[locale]/layout.tsx")];for(let e of o)if(l(e)&&(await d(e)).includes("<body"))return e;for(let e of o)if(l(e))return e;return""};var Ao=async t=>{let o=Se.join(t,a.THEME_PROVIDER),e=Se.join(t,a.GLOBALS_CSS),r=Se.join(t,"package.json");if(l(o))return{isSetup:!0,reason:"CustomThemeProvider.tsx exists"};if(l(r)){let n=JSON.parse(await d(r));if(n.dependencies&&n.dependencies["next-themes"]||n.devDependencies&&n.devDependencies["next-themes"])return{isSetup:!0,reason:"next-themes is installed"}}return l(e)&&(await d(e)).includes("@custom-variant dark")?{isSetup:!0,reason:"Dark theme CSS found in globals.css"}:{isSetup:!1,reason:""}},bo=async t=>{let o=Se.join(t,a.GLOBALS_CSS),e=Se.join(t,a.PROVIDERS_INDEX),r=await ke(t);if(!l(o)||!r||!l(e))throw new Error("Project structure mismatch. Ensure src/styles/globals.css, src/app/layout.tsx (or src/app/[locale]/layout.tsx), and src/providers/index.ts exist.");return r};P();T();import Oo from"node:path";import dn from"degit";var ko=async(t,o)=>{o.text="Fetching assets from starter repo...",await dn("teispace/nextjs-starter",{cache:!1,force:!0,verbose:!1}).clone(t)},_o=async(t,o)=>{let e=Oo.join(t,a.THEME_PROVIDER),r=Oo.join(o,"src/providers/CustomThemeProvider.tsx");await O(r,e)};P();T();import _e from"node:path";var jo=async t=>{let o=_e.join(t,a.PROVIDERS_INDEX),e=await d(o);e.includes("CustomThemeProvider")||(e+=`export * from './CustomThemeProvider';
439
- `,await u(o,e))},Fo=async t=>{let o=_e.join(t,"src/providers/RootProvider.tsx");if(l(o)){let e=await d(o),r="'use client';",n=e.includes(r);if(n&&(e=e.replace(r,"").trim()),e.includes("CustomThemeProvider")||(e=e.replace(/import \{ StoreProvider \} from '@\/providers';\n/,`import { StoreProvider, CustomThemeProvider } from '@/providers';
440
- `),e.includes("CustomThemeProvider")||(e.includes("from '@/providers'")?e=e.replace(/\} from '@\/providers'/,", CustomThemeProvider } from '@/providers'"):e=`import { CustomThemeProvider } from '@/providers';
441
- `+e)),n&&(e=r+`
442
- `+e),!e.includes("<CustomThemeProvider>")){if(e.includes("<StoreProvider>"))e=e.replace(/<StoreProvider>/,`<StoreProvider>
443
- <CustomThemeProvider>`),e=e.replace(/<\/StoreProvider>/,`</CustomThemeProvider>
444
- </StoreProvider>`);else{let i=e.match(/return\s*(?:\(\s*)?([\s\S]*?)(?:\s*\))?;/);if(i){let s=i[1];e=e.replace(i[0],`return (
664
+ `)),process.exit(1));let i=[];(n.httpClient==="axios"||n.httpClient==="both")&&i.push("Axios \u2713"),(n.httpClient==="fetch"||n.httpClient==="both")&&i.push("Fetch \u2713"),m(z.dim(` HTTP Clients: ${i.join(", ")}
665
+ `));let s=await io(r,t.axios,t.fetch,n.httpClient),{basePath:c,servicePath:p}=Zn(o,s.serviceName,t.path);Wn(p)||await qn(p,{recursive:!0}),De(o,c,`${s.serviceName}.service.ts`)&&(w(`Service '${s.serviceName}' already exists at ${c}!`),process.exit(1)),t.crud?(h.start("Generating CRUD service files..."),await lt({name:s.serviceName,outputPath:p,httpClient:s.httpClient}),h.succeed("CRUD service files generated"),h.start("Registering CRUD API endpoints..."),await ro(o,s.serviceName),h.succeed("CRUD API endpoints registered")):await me(vt(),{projectPath:o,spinner:h,serviceName:s.serviceName,servicePath:p,httpClient:s.httpClient}),Qn(s,c,!!t.crud)}catch(o){h.fail("Service generation failed"),w(`${o}`),process.exit(1)}})},Zn=(e,r,t)=>{let o;if(t){let n=t.replace(/^src\//,"");if(n.startsWith("features/")){let i=n.split("/")[1];o=Ne.join("src","features",i,"services")}else o=Ne.join("src",n)}else o=Ne.join("src","features",r,"services");return{basePath:o,servicePath:Ne.join(e,o)}},Qn=(e,r,t=!1)=>{let o=Ne.join(r,`${e.serviceName}.service.ts`);m(z.green(`
666
+ \u2728 ${t?"CRUD ":""}Service '${e.serviceName}' created successfully!
667
+ `)),m(z.dim("Generated files:")),m(z.dim(` \u{1F4C4} ${o}
668
+ `)),m(z.cyan("Next steps:"));let n=r.replace(/^src\//,"@/");m(z.dim(` 1. Import service: import { ${e.serviceName}Service } from '${n}/${e.serviceName}.service'`)),t?(m(z.dim(" 2. Available methods: getAll, getById, create, update, delete")),m(z.dim(" 3. Update DTO types in the service file"))):m(z.dim(` 2. Use in component: const data = await ${e.serviceName}Service.getAll()`)),m("")};import Ts from"enquirer";import Gt from"picocolors";C();import so from"node:path";import es from"picocolors";T();var Rt=async e=>{let r=I("Adding @next/bundle-analyzer...");try{let t=so.join(e,a.NEXT_CONFIG);if(!l(t))throw new Error(`${a.NEXT_CONFIG} not found.`);let o=await d(t);if(o.includes("@next/bundle-analyzer")){r.fail("@next/bundle-analyzer is already configured.");return}o=`import withBundleAnalyzer from '@next/bundle-analyzer';
669
+ ${o}`;let n=/export default (.*?);/,i=o.match(n);if(!i)throw new Error("Could not locate `export default` in next.config.ts.");let c=`const bundleAnalyzer = withBundleAnalyzer({
670
+ enabled: process.env.ANALYZE === 'true',
671
+ });
672
+
673
+ export default bundleAnalyzer(${i[1]});`;o=o.replace(n,c),await u(t,o),await j(so.join(e,a.PACKAGE_JSON),p=>(p.scripts=p.scripts??{},p.scripts.analyze||(p.scripts.analyze="ANALYZE=true next build"),p)),r.text="Installing @next/bundle-analyzer...",await ke(e,"@next/bundle-analyzer"),r.succeed(es.green("@next/bundle-analyzer configured."))}catch(t){throw r.fail("Failed to add @next/bundle-analyzer."),t}};import rs from"node:path";import os from"picocolors";T();C();T();import ao from"node:path";import ts from"degit";var co=async(e,r)=>{r.text="Fetching assets from starter repo...",await ts("teispace/nextjs-starter",{cache:!1,force:!0,verbose:!1}).clone(e)},po=async(e,r)=>{let t=ao.join(e,a.THEME_PROVIDER),o=ao.join(r,"src/providers/CustomThemeProvider.tsx");await A(o,t)};C();T();import be from"node:path";C();T();import lo from"node:path";var Ue=async e=>{let r=[lo.join(e,a.ROOT_LAYOUT),lo.join(e,"src/app/[locale]/layout.tsx")];for(let t of r)if(l(t)&&(await d(t)).includes("<body"))return t;for(let t of r)if(l(t))return t;return""};var mo=async e=>{let r=be.join(e,a.THEME_PROVIDER),t=be.join(e,a.GLOBALS_CSS),o=be.join(e,"package.json");if(l(r))return{isSetup:!0,reason:"CustomThemeProvider.tsx exists"};if(l(o)){let n=JSON.parse(await d(o)),i="@teispace/next-themes";if(n.dependencies?.[i]||n.devDependencies?.[i])return{isSetup:!0,reason:`${i} is installed`}}return l(t)&&(await d(t)).includes("@custom-variant dark")?{isSetup:!0,reason:"Dark theme CSS found in globals.css"}:{isSetup:!1,reason:""}},uo=async e=>{let r=be.join(e,a.GLOBALS_CSS),t=be.join(e,a.PROVIDERS_INDEX),o=await Ue(e);if(!l(r)||!o||!l(t))throw new Error("Project structure mismatch. Ensure src/styles/globals.css, src/app/layout.tsx (or src/app/[locale]/layout.tsx), and src/providers/index.ts exist.");return o};C();T();import Me from"node:path";var fo=async e=>{let r=Me.join(e,a.PROVIDERS_INDEX),t=await d(r);t.includes("CustomThemeProvider")||(t+=`export * from './CustomThemeProvider';
674
+ `,await u(r,t))},go=async e=>{let r=Me.join(e,"src/providers/RootProvider.tsx");if(!l(r))return;let t=await d(r),o="'use client';",n=t.includes(o);if(n&&(t=t.replace(o,"").trim()),t.includes("CustomThemeProvider")||(/import\s*\{[^}]*\}\s*from\s*'@\/providers'/.test(t)?t=t.replace(/(import\s*\{)([^}]*)(\}\s*from\s*'@\/providers')/,(i,s,c,p)=>`${s}${c.trim()?`${c.trim()}, CustomThemeProvider `:" CustomThemeProvider "}${p}`):t=`import { CustomThemeProvider } from '@/providers';
675
+ ${t}`),n&&(t=`${o}
676
+ ${t}`),!t.includes("<CustomThemeProvider"))if(t.includes("{children}"))t=t.replace(/\{children\}/,"<CustomThemeProvider>{children}</CustomThemeProvider>");else{let i=t.match(/return\s*\(\s*([\s\S]*?)\s*\);/);i&&(t=t.replace(i[0],`return (
445
677
  <CustomThemeProvider>
446
- ${s}
678
+ ${i[1]}
447
679
  </CustomThemeProvider>
448
- );`)}}await u(o,e)}}},Do=async(t,o)=>{let e=_e.join(t,a.GLOBALS_CSS),r=_e.join(o,"src/styles/globals.css"),n="";if(l(r)){let s=await d(r),c=s.match(/@custom-variant dark \(.*?\);/),m=s.match(/@theme \{[\s\S]*?\}/);c&&(n+=`
680
+ );`))}await u(r,t)},ho=async(e,r)=>{let t=Me.join(e,a.GLOBALS_CSS),o=Me.join(r,"src/styles/globals.css"),n="";if(l(o)){let s=await d(o),c=s.match(/@custom-variant dark \(.*?\);/),p=s.match(/@theme \{[\s\S]*?\}/);c&&(n+=`
449
681
  ${c[0]}
450
- `),m&&(n+=`
451
- ${m[0]}
682
+ `),p&&(n+=`
683
+ ${p[0]}
452
684
  `)}n||(n=`
453
685
  @custom-variant dark (&:where(.dark, .dark *));
454
686
 
@@ -456,59 +688,61 @@ ${m[0]}
456
688
  --color-dark: #202938;
457
689
  --color-light: #f5f5f5;
458
690
  }
459
- `);let i=await d(e);if(!i.includes("@custom-variant dark")){if(i.includes("@import")){let s=i.lastIndexOf("@import"),c=i.indexOf(`
460
- `,s);i=i.slice(0,c+1)+n+i.slice(c+1)}else i=n+i;await u(e,i)}},Lo=async t=>{let o=await d(t);o.includes("dark:bg-dark")||(o=o.replace(/className="([^"]*)"/,'className="$1 bg-light dark:bg-dark"'),await u(t,o))};var yt=async t=>{let o=A("Setting up Dark Theme..."),e=un.join(t,".next-maker-temp");try{let{isSetup:r,reason:n}=await Ao(t);if(r){o.fail(`Dark Theme is already set up (${n}).`);return}let i=await bo(t);await ko(e,o),await _o(t,e),await jo(t),await Fo(t),await Do(t,e),await Lo(i),o.text="Installing next-themes...",await F(t,"next-themes"),o.text="Formatting code...";let s=await U(t);await D(t,s,"format"),o.succeed(fn.green("Dark Theme setup successfully!"))}catch(r){throw o.fail("Failed to setup Dark Theme."),r}finally{await h(e)}};P();import hn from"node:path";import xn from"picocolors";P();T();import Pt from"node:path";var Ho=async t=>{let o=Pt.join(t,a.STORE),e=Pt.join(t,"package.json");if(l(o))return{isSetup:!0,reason:"src/store directory exists"};if(l(e)){let r=JSON.parse(await d(e));if(r.dependencies&&r.dependencies["@reduxjs/toolkit"]||r.devDependencies&&r.devDependencies["@reduxjs/toolkit"])return{isSetup:!0,reason:"@reduxjs/toolkit is installed"}}return{isSetup:!1,reason:""}},Go=async t=>{let o=Pt.join(t,a.PROVIDERS_INDEX);if(!await ke(t)||!l(o))throw new Error("Project structure mismatch. Ensure src/app/layout.tsx (or src/app/[locale]/layout.tsx) and src/providers/index.ts exist.")};P();T();import ne from"node:path";import gn from"degit";import Mo from"node:fs/promises";var Uo=async(t,o)=>{o.text="Fetching assets from starter repo...",await gn("teispace/nextjs-starter",{cache:!1,force:!0,verbose:!1}).clone(t)},Xo=async(t,o)=>{let e=ne.join(o,"src/providers/StoreProvider.tsx"),r=ne.join(t,a.STORE_PROVIDER);await O(e,r);let n=ne.join(o,"src/store"),i=ne.join(t,a.STORE);await Mo.cp(n,i,{recursive:!0})},Jo=async(t,o)=>{let e=ne.join(o,"src/features/counter"),r=ne.join(t,a.COUNTER_FEATURE);await Mo.cp(e,r,{recursive:!0});let n=ne.join(r,"components/Counter.tsx");if(await l(n)){let i=await d(n);i=i.replace(/import \{ useTranslations \} from 'next-intl';\n?/,""),i=i.replace(/const t = useTranslations\('Count'\);\n?/,""),i=i.replace(/\{t\('currentCount', \{ count: value \}\)\}/g,"Current Count: {value}"),i=i.replace(/\{t\('increment'\)\}/g,"Increment"),i=i.replace(/\{t\('decrement'\)\}/g,"Decrement"),i=i.replace(/\{t\('reset'\)\}/g,"Reset"),await u(n,i)}};P();T();import je from"node:path";var Yo=async t=>{let o=je.join(t,a.PROVIDERS_INDEX),e=await d(o);e.includes("StoreProvider")||(e+=`export * from './StoreProvider';
461
- `,await u(o,e))},zo=async t=>{let o=je.join(t,"src/providers/RootProvider.tsx");if(l(o)){let e=await d(o),r="'use client';",n=e.includes(r);if(n&&(e=e.replace(r,"").trim()),e.includes("StoreProvider")||(e=e.replace(/import \{ (.*?) \} from '@\/providers';/,"import { $1, StoreProvider } from '@/providers';"),e.includes("StoreProvider")||(e.includes("from '@/providers'")?e=e.replace(/\} from '@\/providers'/,", StoreProvider } from '@/providers'"):e=`import { StoreProvider } from '@/providers';
462
- `+e)),n&&(e=r+`
463
- `+e),!e.includes("<StoreProvider>")){let i=e.match(/return\s*(?:\(\s*)?([\s\S]*?)(?:\s*\))?;/);if(i){let s=i[1];e=e.replace(i[0],`return (
464
- <StoreProvider>
465
- ${s}
466
- </StoreProvider>
467
- );`),await u(o,e)}}}},Wo=async t=>{let o=[je.join(t,a.ROOT_PAGE),je.join(t,"src/app/[locale]/page.tsx")],e="";for(let r of o)if(l(r)){e=r;break}if(e){let r=await d(e);if(r.includes("Counter")||(r=`import { Counter } from '@/features/counter/components/Counter';
468
- `+r),!r.includes("<Counter />")){let n=r.lastIndexOf("</div>"),i=r.lastIndexOf("</main>"),s=i!==-1?i:n;s!==-1&&(r=r.slice(0,s)+`
469
- <div className="mt-8">
470
- <h2 className="text-2xl font-bold mb-4">Redux Counter</h2>
471
- <Counter />
472
- </div>
473
- `+r.slice(s),await u(e,r))}}};var wt=async t=>{let o=A("Setting up Redux Toolkit..."),e=hn.join(t,".next-maker-temp-redux");try{let{isSetup:r,reason:n}=await Ho(t);if(r){o.fail(`Redux is already set up (${n}).`);return}await Go(t),await Uo(e,o),o.text="Copying Redux files...",await Xo(t,e),o.text="Creating Counter feature...",await Jo(t,e),o.text="Updating providers and pages...",await Yo(t),await zo(t),await Wo(t),o.text="Installing dependencies...",await F(t,"@reduxjs/toolkit"),await F(t,"react-redux"),await F(t,"redux-persist"),await F(t,"react-secure-storage"),o.text="Formatting code...";let i=await U(t);await D(t,i,"format"),o.succeed(xn.green("Redux Toolkit setup successfully!"))}catch(r){throw o.fail("Failed to setup Redux Toolkit."),r}finally{await h(e)}};P();import Sn from"node:path";import Cn from"picocolors";P();T();import Fe from"node:path";var Bo=async t=>{let o=Fe.join(t,a.I18N_DIR),e=Fe.join(t,"package.json");if(l(o))return{isSetup:!0,reason:"src/i18n directory exists"};if(l(e)){let r=JSON.parse(await d(e));if(r.dependencies&&r.dependencies["next-intl"]||r.devDependencies&&r.devDependencies["next-intl"])return{isSetup:!0,reason:"next-intl is installed"}}return{isSetup:!1,reason:""}},Vo=async t=>{let o=Fe.join(t,a.ROOT_LAYOUT),e=Fe.join(t,"src/app/[locale]/layout.tsx");if(!l(o)&&!l(e))throw new Error("Project structure mismatch. Ensure src/app/layout.tsx exists.")};P();T();import ee from"node:path";import yn from"degit";import Pn from"node:fs/promises";var qo=async(t,o)=>{o.text="Fetching assets from starter repo...",await yn("teispace/nextjs-starter",{cache:!1,force:!0,verbose:!1}).clone(t)},Ko=async(t,o)=>{let e=ee.join(o,"src/i18n"),r=ee.join(t,a.I18N_DIR);await Pn.cp(e,r,{recursive:!0});let n=ee.join(o,"src/proxy.ts"),i=ee.join(t,a.PROXY);await O(n,i);let s=ee.join(o,"src/types/i18n.ts"),c=ee.join(t,a.I18N_TYPES);await O(s,c);let m=ee.join(o,"src/lib/config/app-locales.ts"),f=ee.join(t,a.APP_LOCALES);await O(m,f)};P();T();import B from"node:path";import wn from"node:fs/promises";var Zo=async t=>{let o=B.join(t,a.NEXT_CONFIG);if(l(o)){let e=await d(o);if(!e.includes("createNextIntlPlugin")){e=`import createNextIntlPlugin from 'next-intl/plugin';
474
- `+e;let r=/export default (.*?);/;r.test(e)?e=e.replace(r,`
691
+ `);let i=await d(t);if(!i.includes("@custom-variant dark")){if(i.includes("@import")){let s=i.lastIndexOf("@import"),c=i.indexOf(`
692
+ `,s);i=i.slice(0,c+1)+n+i.slice(c+1)}else i=n+i;await u(t,i)}},xo=async e=>{let r=await d(e);r.includes("dark:bg-dark")||(r=r.replace(/className="([^"]*)"/,'className="$1 bg-light dark:bg-dark"'),await u(e,r))};var Nt=async e=>{let r=I("Setting up Dark Theme..."),t=rs.join(e,".next-maker-temp");try{let{isSetup:o,reason:n}=await mo(e);if(o){r.fail(`Dark Theme is already set up (${n}).`);return}let i=await uo(e);await co(t,r),await po(e,t),await fo(e),await go(e),await ho(e,t),await xo(i),r.text="Installing @teispace/next-themes...",await H(e,"@teispace/next-themes"),r.text="Formatting code...";let s=await D(e);await G(e,s,"lint:fix"),r.succeed(os.green("Dark Theme setup successfully!"))}catch(o){throw r.fail("Failed to setup Dark Theme."),o}finally{await P(t)}};import ns from"node:fs/promises";import Je from"node:path";import ze from"enquirer";import bt from"picocolors";T();C();T();import Z from"node:fs/promises";import v from"node:path";import is from"degit";var yo=async(e,r)=>{r.text="Downloading assets from starter repository...",await is("teispace/nextjs-starter",{cache:!1,force:!0,verbose:!1}).clone(e)},Po=async(e,r,t,o)=>{let n=v.join(e,a.HTTP_UTILS),i=v.join(r,a.HTTP_UTILS);await Z.cp(v.join(r,a.ERRORS_DIR),v.join(e,a.ERRORS_DIR),{recursive:!0});let s=v.join(e,a.APP_APIS);l(s)||await A(v.join(r,a.APP_APIS),s);let c=v.join(e,a.CONSTANTS);if(!l(c))await A(v.join(r,a.CONSTANTS),c);else{let f=await d(c),g=!1;f.includes("API_RESPONSE_DATA_KEY")||(f+=`
693
+ export const API_RESPONSE_DATA_KEY = 'data';
694
+ `,g=!0),f.includes("SAVE_AUTH_TOKENS")||(f+=`
695
+ export const SAVE_AUTH_TOKENS = false;
696
+ `,g=!0),g&&await u(c,f)}let p=v.join(e,a.STORAGE_SERVICE);if(l(p)||await Z.cp(v.join(r,a.STORAGE_SERVICE),p,{recursive:!0}),await Z.cp(v.join(r,a.COMMON_TYPES_DIR),v.join(e,a.COMMON_TYPES_DIR),{recursive:!0}),await Z.cp(v.join(r,a.UTILITY_TYPES_DIR),v.join(e,a.UTILITY_TYPES_DIR),{recursive:!0}),await A(v.join(i,"token-store.ts"),v.join(n,"token-store.ts")),await A(v.join(i,"client-utils.ts"),v.join(n,"client-utils.ts")),o&&o.length>0)for(let f of o){let g=v.join(e,f==="fetch"?a.FETCH_CLIENT:a.AXIOS_CLIENT);await P(g)}for(let f of t)f==="fetch"?await Z.cp(v.join(r,a.FETCH_CLIENT),v.join(e,a.FETCH_CLIENT),{recursive:!0}):await Z.cp(v.join(r,a.AXIOS_CLIENT),v.join(e,a.AXIOS_CLIENT),{recursive:!0});await A(v.join(i,"index.ts"),v.join(n,"index.ts")),await A(v.join(r,a.HTTP_TYPES),v.join(e,a.HTTP_TYPES))},To=async e=>{let{isFileUsed:r,isStringUsed:t}=await Promise.resolve().then(()=>(je(),Qt));await P(v.join(e,a.HTTP_UTILS));let o=v.join(e,a.STORAGE_SERVICE);l(o)&&(await t(e,"SecureStorageService",[o])||await P(o));let n=v.join(e,a.CONSTANTS);if(l(n)){let p=await d(n),f=!1;await t(e,"API_RESPONSE_DATA_KEY",[n])||(p=p.replace(/export const API_RESPONSE_DATA_KEY = .*;\n?/g,""),f=!0),await t(e,"SAVE_AUTH_TOKENS",[n])||(p=p.replace(/export const SAVE_AUTH_TOKENS = .*;\n?/g,""),f=!0),f&&(p=`${p.replace(/\n\s*\n/g,`
697
+
698
+ `).trim()}
699
+ `,await u(n,p))}let i=v.join(e,a.ERRORS_DIR);if(l(i)){let p=await Z.readdir(i),f=!1;for(let g of p){let y=v.parse(g).name;if(await r(e,y,[v.join(i,g)])){f=!0;break}}f||await P(i)}let s=v.join(e,a.COMMON_TYPES_DIR);l(s)&&(await Z.readdir(s)).length===0&&await P(s);let c=v.join(e,a.UTILITY_TYPES_DIR);l(c)&&(await Z.readdir(c)).length===0&&await P(c)};C();T();import $e from"node:path";var So=async e=>{let r=$e.join(e,a.FETCH_CLIENT_FILE),t=$e.join(e,a.AXIOS_CLIENT_FILE),o=l(r),n=l(t);return o&&n?{status:"both",reason:"Both Fetch and Axios clients are detected"}:o?{status:"fetch",reason:"Fetch client is already setup"}:n?{status:"axios",reason:"Axios client is already setup"}:{status:"none"}},wo=async e=>{let t=[$e.join(e,"src/lib"),$e.join(e,"src/types"),$e.join(e,"src/lib/config")].filter(o=>!l(o));if(t.length>0)throw new Error(`Invalid project structure. Missing directories:
700
+ ${t.map(o=>`- ${o}`).join(`
701
+ `)}`)};je();var $t=async e=>{let r=I("Checking HTTP Client setup..."),t=Je.join(e,".next-maker-temp-http");try{let{status:o,reason:n}=await So(e);r.stop();let i=await ss(o,n);if(i.type==="cancel"){console.log(bt.yellow("Setup cancelled."));return}if(r.start("Setting up HTTP client(s)..."),await wo(e),await yo(t,r),i.type==="replace"&&i.fromClient&&(r.text="Migrating client usages...",await rt(e,i.fromClient,i.clients[0])),i.type!=="remove-both"&&i.type!=="remove-one"){r.text="Copying client files...";let X=i.type==="replace"&&i.fromClient?[i.fromClient]:void 0;await Po(e,t,i.clients,X)}if(i.type==="remove-one"||i.type==="remove-both"){r.text="Removing client files...";let{PROJECT_PATHS:X}=await Promise.resolve().then(()=>(C(),Kt));for(let Ae of i.clients){let Oe=Je.join(e,Ae==="fetch"?X.FETCH_CLIENT:X.AXIOS_CLIENT);await P(Oe)}vo(o,i).length===0&&(r.text="Performing full cleanup...",await To(e),await ot(e))}let s=vo(o,i);s.length>0&&(r.text="Configuring client...",await Ze(e,s),await Qe(e),await et(e),await tt(e)),await fe(e,s),r.text="Managing dependencies...";let c=Je.join(e,"package.json"),p=JSON.parse(await ns.readFile(c,"utf-8")),f={...p.dependencies,...p.devDependencies};s.includes("axios")?f.axios||(r.text="Installing Axios...",await H(e,"axios")):f.axios&&(r.text="Uninstalling Axios...",await We(e,"axios"));let g=Je.join(e,"src/services/storage");s.length>0||l(g)?f["react-secure-storage"]||(r.text="Installing react-secure-storage...",await H(e,"react-secure-storage")):f["react-secure-storage"]&&(r.text="Uninstalling react-secure-storage...",await We(e,"react-secure-storage")),r.text="Formatting code...";let x=await D(e);await G(e,x,"lint:fix"),r.succeed(bt.green(as(i)))}catch(o){throw r.fail("Failed to setup HTTP Client."),o}finally{await P(t)}};async function ss(e,r){if(e==="none"){let{choice:o}=await ze.prompt({type:"select",name:"choice",message:"Which HTTP client(s) do you want to setup?",choices:[{name:"fetch",message:"Fetch (Native)"},{name:"axios",message:"Axios"},{name:"both",message:"Both (Fetch + Axios)"}]});return o==="both"?{type:"install",clients:["fetch","axios"]}:{type:"install",clients:[o]}}if(e==="fetch"){let{action:o}=await ze.prompt({type:"select",name:"action",message:`${r}. What would you like to do?`,choices:[{name:"cancel",message:"Keep Fetch only (cancel)"},{name:"add",message:"Add Axios (have both)"},{name:"replace",message:"Replace with Axios only"},{name:"remove",message:"Remove Fetch"}]});if(o==="cancel")return{type:"cancel",clients:[]};if(o==="add")return{type:"add",clients:["axios"]};if(o==="replace")return{type:"replace",clients:["axios"],fromClient:"fetch"};if(o==="remove")return{type:"remove-one",clients:["fetch"]}}if(e==="axios"){let{action:o}=await ze.prompt({type:"select",name:"action",message:`${r}. What would you like to do?`,choices:[{name:"cancel",message:"Keep Axios only (cancel)"},{name:"add",message:"Add Fetch (have both)"},{name:"replace",message:"Replace with Fetch only"},{name:"remove",message:"Remove Axios"}]});if(o==="cancel")return{type:"cancel",clients:[]};if(o==="add")return{type:"add",clients:["fetch"]};if(o==="replace")return{type:"replace",clients:["fetch"],fromClient:"axios"};if(o==="remove")return{type:"remove-one",clients:["axios"]}}console.log(bt.yellow(`\u2716 ${r}`));let{action:t}=await ze.prompt({type:"select",name:"action",message:"What would you like to do?",choices:[{name:"cancel",message:"Keep both (cancel)"},{name:"remove-fetch",message:"Remove Fetch (keep Axios)"},{name:"remove-axios",message:"Remove Axios (keep Fetch)"},{name:"remove-both",message:"Remove both"}]});return t==="cancel"?{type:"cancel",clients:[]}:t==="remove-fetch"?{type:"remove-one",clients:["fetch"]}:t==="remove-axios"?{type:"remove-one",clients:["axios"]}:t==="remove-both"?{type:"remove-both",clients:["fetch","axios"]}:{type:"cancel",clients:[]}}function vo(e,r){return r.type==="install"?r.clients:r.type==="add"?[...e==="fetch"?["fetch"]:["axios"],...r.clients]:r.type==="replace"?r.clients:r.type==="remove-one"?e==="both"?r.clients[0]==="fetch"?["axios"]:["fetch"]:[]:[]}function as(e){if(e.type==="install")return`HTTP Client (${e.clients.map(t=>t==="fetch"?"Fetch":"Axios").join(" + ")}) setup successfully!`;if(e.type==="add")return`${e.clients[0]==="fetch"?"Fetch":"Axios"} client added successfully! Both clients are now available.`;if(e.type==="replace"){let r=e.fromClient==="fetch"?"Fetch":"Axios",t=e.clients[0]==="fetch"?"Fetch":"Axios";return`Replaced ${r} with ${t} successfully! Imports automatically migrated.`}return e.type==="remove-one"?`${e.clients[0]==="fetch"?"Fetch":"Axios"} client removed successfully!`:e.type==="remove-both"?"Both HTTP clients removed successfully!":"HTTP Client setup completed!"}C();import At from"node:path";import ms from"picocolors";T();C();T();import cs from"node:fs/promises";import ie from"node:path";import ps from"degit";var Co=async(e,r)=>{r.text="Fetching assets from starter repo...",await ps("teispace/nextjs-starter",{cache:!1,force:!0,verbose:!1}).clone(e)},Eo=async(e,r)=>{let t=ie.join(r,"src/i18n"),o=ie.join(e,a.I18N_DIR);await cs.cp(t,o,{recursive:!0});let n=ie.join(r,"src/proxy.ts"),i=ie.join(e,a.PROXY);await A(n,i);let s=ie.join(r,"src/types/i18n.ts"),c=ie.join(e,a.I18N_TYPES);await A(s,c);let p=ie.join(r,"src/lib/config/app-locales.ts"),f=ie.join(e,a.APP_LOCALES);await A(p,f)};C();T();import Be from"node:path";var Io=async e=>{let r=Be.join(e,a.I18N_DIR),t=Be.join(e,"package.json");if(l(r))return{isSetup:!0,reason:"src/i18n directory exists"};if(l(t)){let o=JSON.parse(await d(t));if(o.dependencies?.["next-intl"]||o.devDependencies?.["next-intl"])return{isSetup:!0,reason:"next-intl is installed"}}return{isSetup:!1,reason:""}},Ro=async e=>{let r=Be.join(e,a.ROOT_LAYOUT),t=Be.join(e,"src/app/[locale]/layout.tsx");if(!l(r)&&!l(t))throw new Error("Project structure mismatch. Ensure src/app/layout.tsx exists.")};C();T();import ls from"node:fs/promises";import Q from"node:path";var No=async e=>{let r=Q.join(e,a.NEXT_CONFIG);if(l(r)){let t=await d(r);if(!t.includes("createNextIntlPlugin")){t=`import createNextIntlPlugin from 'next-intl/plugin';
702
+ ${t}`;let o=/export default (.*?);/;o.test(t)?t=t.replace(o,`
475
703
  const withNextIntl = createNextIntlPlugin();
476
- export default withNextIntl($1);`):(e+=`
704
+ export default withNextIntl($1);`):(t+=`
477
705
  const withNextIntl = createNextIntlPlugin();
478
- `,e+=`export default withNextIntl(nextConfig);
479
- `),await u(o,e)}}},Qo=async t=>{let o=B.join(t,a.TYPES_INDEX);if(l(o)){let e=await d(o);e.includes("./i18n")||(e+=`export * from './i18n';
480
- `,await u(o,e))}},er=async t=>{let o=B.join(t,a.CONFIG_INDEX);if(l(o)){let e=await d(o);e.includes("./app-locales")||(e+=`export * from './app-locales';
481
- `,await u(o,e))}},tr=async t=>{let o=B.join(t,"src/providers/RootProvider.tsx");if(l(o)){let e=await d(o),r="'use client';",n=e.includes(r);if(n&&(e=e.replace(r,"").trim()),e.includes("next-intl")||(e=`import { SupportedLocale } from '@/types/i18n';
482
- import { NextIntlClientProvider, AbstractIntlMessages } from 'next-intl';
483
- `+e),n&&(e=r+`
484
- `+e),!e.includes("locale: SupportedLocale")){let i=/export const RootProvider = \(\{([\s\S]*?)\}: \{([\s\S]*?)\}\) => \{/,s=e.match(i);s&&(e=e.replace(s[0],`export const RootProvider = ({
485
- children,
486
- locale,
706
+ `,t+=`export default withNextIntl(nextConfig);
707
+ `),await u(r,t)}}},bo=async e=>{let r=Q.join(e,a.TYPES_INDEX);if(l(r)){let t=await d(r);t.includes("./i18n")||(t+=`export * from './i18n';
708
+ `,await u(r,t))}},$o=async e=>{let r=Q.join(e,a.CONFIG_INDEX);if(l(r)){let t=await d(r);t.includes("./app-locales")||(t+=`export * from './app-locales';
709
+ `,await u(r,t))}},Ao=async e=>{let r=Q.join(e,"src/providers/RootProvider.tsx");if(l(r)){let t=await d(r),o="'use client';",n=t.includes(o);if(n&&(t=t.replace(o,"").trim()),t.includes("next-intl")||(t=`import { type AbstractIntlMessages, NextIntlClientProvider } from 'next-intl';
710
+ import type { SupportedLocale } from '@/types/i18n';
711
+ `+t),n&&(t=`${o}
712
+ ${t}`),!t.includes("locale: SupportedLocale")){let i=` locale: SupportedLocale;
713
+ messages: AbstractIntlMessages;
714
+ timeZone: string;`,s=/(type\s+RootProviderProps\s*=\s*\{)([\s\S]*?)(\};?)/,c=/export const RootProvider = \(\{([\s\S]*?)\}: \{([\s\S]*?)\}\) => \{/;if(s.test(t))t=t.replace(s,(p,f,g,y)=>{let x=g.replace(/\s+$/,"");return`${f}${x}
715
+ ${i}
716
+ ${y}`}),t=t.replace(/export const RootProvider = \(\{([\s\S]*?)\}:\s*RootProviderProps\)/,(p,f)=>{let g=f.trim().replace(/,$/,"");return`export const RootProvider = ({ ${g?`${g}, `:""}locale, messages, timeZone }: RootProviderProps)`});else{let p=t.match(c);if(p){let f=p[1].trim().replace(/,$/,""),g=p[2].trim().replace(/;$/,""),y=`
717
+ ${f?`${f},
718
+ `:""}locale,
487
719
  messages,
488
- }: {
489
- children: React.ReactNode;
490
- locale: SupportedLocale;
720
+ timeZone,`,x=`
721
+ ${g?`${g};
722
+ `:""}locale: SupportedLocale;
491
723
  messages: AbstractIntlMessages;
492
- }) => {`))}if(!e.includes("<NextIntlClientProvider")){let i=e.match(/return\s*(?:\(\s*)?([\s\S]*?)(?:\s*\))?;/);if(i){let s=i[1];if(s.includes("{children}")){let c=s.replace("{children}",`<NextIntlClientProvider locale={locale} messages={messages}>
724
+ timeZone: string;`;t=t.replace(p[0],`export const RootProvider = ({${y}
725
+ }: {${x}
726
+ }) => {`)}}}if(!t.includes("<NextIntlClientProvider")){let i=t.match(/return\s*(?:\(\s*)?([\s\S]*?)(?:\s*\))?;/);if(i){let s=i[1],c=`<NextIntlClientProvider locale={locale} messages={messages} timeZone={timeZone}>
493
727
  {children}
494
- </NextIntlClientProvider>`);e=e.replace(i[0],`return (
495
- ${c}
496
- );`)}else e=e.replace(i[0],`return (
497
- <NextIntlClientProvider locale={locale} messages={messages}>
728
+ </NextIntlClientProvider>`;if(s.includes("{children}")){let p=s.replace("{children}",c);t=t.replace(i[0],`return (
729
+ ${p}
730
+ );`)}else t=t.replace(i[0],`return (
731
+ <NextIntlClientProvider locale={locale} messages={messages} timeZone={timeZone}>
498
732
  ${s}
499
733
  </NextIntlClientProvider>
500
- );`)}}await u(o,e)}},or=async t=>{let o=B.join(t,a.ROOT_LAYOUT),e=B.join(t,a.ROOT_PAGE),r=B.join(t,"src/app/[locale]");if(await wn.mkdir(r,{recursive:!0}),l(o)){let n=B.join(r,"layout.tsx"),i=await d(o);if(i.includes("next-intl")||(i=`import { routing } from '@/i18n/routing';
734
+ );`)}}await u(r,t)}},Oo=async e=>{let r=Q.join(e,a.ROOT_LAYOUT),t=Q.join(e,a.ROOT_PAGE),o=Q.join(e,"src/app/[locale]");if(await ls.mkdir(o,{recursive:!0}),l(r)){let n=Q.join(o,"layout.tsx"),i=await d(r);if(i.includes("next-intl")||(i=`import { routing } from '@/i18n/routing';
501
735
  import { hasLocale } from 'next-intl';
502
736
  import { notFound } from 'next/navigation';
503
- import { setRequestLocale, getMessages } from 'next-intl/server';
504
- `+i),!i.includes("generateStaticParams")){let m=i.indexOf("};",i.indexOf("export const metadata"));if(m!==-1){let f=m+2;i=i.slice(0,f)+`
737
+ import { getMessages, getTimeZone, setRequestLocale } from 'next-intl/server';
738
+ ${i}`),!i.includes("generateStaticParams")){let p=i.indexOf("};",i.indexOf("export const metadata"));if(p!==-1){let f=p+2;i=i.slice(0,f)+`
505
739
 
506
740
  export function generateStaticParams() {
507
741
  return routing.locales.map((locale) => ({ locale }));
508
742
  }`+i.slice(f)}}i=i.replace(/Readonly<\{\s*children:\s*React\.ReactNode;\s*}>/,`Readonly<{
509
743
  children: React.ReactNode;
510
744
  params: Promise<{ locale: string }>;
511
- }>`);let s=/export default (async )?function RootLayout\(\{\s*children,?\s*\}\s*:/,c=i.match(s);if(c){c[1]||(i=i.replace("export default function","export default async function")),i=i.replace(/export default (async )?function RootLayout\(\{\s*children,?\s*\}\s*:/,"export default async function RootLayout({ children, params }:");let f=/export default async function RootLayout[\s\S]*?\)\s*\{/,x=i.match(f);if(x&&x.index!==void 0){let S=x.index+x[0].length-1;i=i.slice(0,S+1)+`
745
+ }>`);let s=/export default (async )?function RootLayout\(\{\s*children,?\s*\}\s*:/,c=i.match(s);if(c){c[1]||(i=i.replace("export default function","export default async function")),i=i.replace(/export default (async )?function RootLayout\(\{\s*children,?\s*\}\s*:/,"export default async function RootLayout({ children, params }:");let f=/export default async function RootLayout[\s\S]*?\)\s*\{/,g=i.match(f);if(g&&g.index!==void 0){let y=g.index+g[0].length-1;i=i.slice(0,y+1)+`
512
746
  const { locale } = await params;
513
747
 
514
748
  if (!hasLocale(routing.locales, locale)) {
@@ -517,46 +751,47 @@ export function generateStaticParams() {
517
751
 
518
752
  setRequestLocale(locale);
519
753
 
520
- const messages = await getMessages();
521
- `+i.slice(S+1)}i=i.replace(/<RootProvider>/,"<RootProvider locale={locale} messages={messages}>"),i=i.replace(/<html lang="en"/,"<html lang={locale}")}await u(n,i),await w(o)}if(l(e)){let n=B.join(r,"page.tsx"),i=await d(e);i.includes("next-intl")||(i=`import { SupportedLocale } from '@/types/i18n';
754
+ const [messages, timeZone] = await Promise.all([getMessages(), getTimeZone()]);
755
+ `+i.slice(y+1)}i=i.replace(/<RootProvider>/,"<RootProvider locale={locale} messages={messages} timeZone={timeZone}>"),i=i.replace(/<html lang="en"/,"<html lang={locale}")}await u(n,i),await S(r)}if(l(t)){let n=Q.join(o,"page.tsx"),i=await d(t);i.includes("next-intl")||(i=`import { SupportedLocale } from '@/types/i18n';
522
756
  import { setRequestLocale } from 'next-intl/server';
523
- `+i),i=i.replace(/export default function Home\(\)/,`type Props = {
757
+ ${i}`),i=i.replace(/export default function Home\(\)/,`type Props = {
524
758
  params: Promise<{ locale: string }>;
525
759
  };
526
760
 
527
761
  export default async function Home(props: Props)`);let s=i.indexOf("export default async function Home(props: Props) {");if(s!==-1){let c=`
528
762
  const locale = (await props.params).locale as SupportedLocale;
529
763
  setRequestLocale(locale);
530
- `,m=i.indexOf("{",s);i=i.slice(0,m+1)+c+i.slice(m+1)}await u(n,i),await w(e)}};var St=async t=>{let o=A("Setting up Internationalization (next-intl)..."),e=Sn.join(t,".next-maker-temp-i18n");try{let{isSetup:r,reason:n}=await Bo(t);if(r){o.fail(`i18n is already set up (${n}).`);return}await Vo(t),await qo(e,o),o.text="Copying i18n files...",await Ko(t,e),o.text="Configuring project structure...",await Zo(t),await Qo(t),await er(t),await tr(t),o.text="Migrating to [locale] structure...",await or(t),o.text="Installing dependencies...",await F(t,"next-intl"),o.text="Formatting code...";let i=await U(t);await D(t,i,"format"),o.succeed(Cn.green("Internationalization setup successfully!"))}catch(r){throw o.fail("Failed to setup Internationalization."),r}finally{await h(e)}};P();import De from"node:path";import Tn from"node:fs/promises";import Ct from"picocolors";import Le from"enquirer";P();T();import Ce from"node:path";var rr=async t=>{let o=Ce.join(t,a.FETCH_CLIENT_FILE),e=Ce.join(t,a.AXIOS_CLIENT_FILE),r=l(o),n=l(e);return r&&n?{status:"both",reason:"Both Fetch and Axios clients are detected"}:r?{status:"fetch",reason:"Fetch client is already setup"}:n?{status:"axios",reason:"Axios client is already setup"}:{status:"none"}},ir=async t=>{let e=[Ce.join(t,"src/lib"),Ce.join(t,"src/types"),Ce.join(t,"src/lib/config")].filter(r=>!l(r));if(e.length>0)throw new Error(`Invalid project structure. Missing directories:
531
- ${e.map(r=>`- ${r}`).join(`
532
- `)}`)};P();T();import y from"node:path";import vn from"degit";import V from"node:fs/promises";var nr=async(t,o)=>{o.text="Downloading assets from starter repository...",await vn("teispace/nextjs-starter",{cache:!1,force:!0,verbose:!1}).clone(t)},sr=async(t,o,e,r)=>{let n=y.join(t,a.HTTP_UTILS),i=y.join(o,a.HTTP_UTILS);await V.cp(y.join(o,a.ERRORS_DIR),y.join(t,a.ERRORS_DIR),{recursive:!0});let s=y.join(t,a.APP_APIS);l(s)||await O(y.join(o,a.APP_APIS),s);let c=y.join(t,a.CONSTANTS);if(!l(c))await O(y.join(o,a.CONSTANTS),c);else{let f=await d(c),x=!1;f.includes("API_RESPONSE_DATA_KEY")||(f+=`
533
- export const API_RESPONSE_DATA_KEY = 'data';
534
- `,x=!0),f.includes("SAVE_AUTH_TOKENS")||(f+=`
535
- export const SAVE_AUTH_TOKENS = false;
536
- `,x=!0),x&&await u(c,f)}let m=y.join(t,a.STORAGE_SERVICE);if(l(m)||await V.cp(y.join(o,a.STORAGE_SERVICE),m,{recursive:!0}),await V.cp(y.join(o,a.COMMON_TYPES_DIR),y.join(t,a.COMMON_TYPES_DIR),{recursive:!0}),await V.cp(y.join(o,a.UTILITY_TYPES_DIR),y.join(t,a.UTILITY_TYPES_DIR),{recursive:!0}),await O(y.join(i,"token-store.ts"),y.join(n,"token-store.ts")),await O(y.join(i,"client-utils.ts"),y.join(n,"client-utils.ts")),r&&r.length>0)for(let f of r){let x=y.join(t,f==="fetch"?a.FETCH_CLIENT:a.AXIOS_CLIENT);await h(x)}for(let f of e)f==="fetch"?await V.cp(y.join(o,a.FETCH_CLIENT),y.join(t,a.FETCH_CLIENT),{recursive:!0}):await V.cp(y.join(o,a.AXIOS_CLIENT),y.join(t,a.AXIOS_CLIENT),{recursive:!0});await O(y.join(i,"index.ts"),y.join(n,"index.ts")),await O(y.join(o,a.HTTP_TYPES),y.join(t,a.HTTP_TYPES))},ar=async t=>{let{isFileUsed:o,isStringUsed:e}=await Promise.resolve().then(()=>(Re(),_t));await h(y.join(t,a.HTTP_UTILS));let r=y.join(t,a.STORAGE_SERVICE);l(r)&&(await e(t,"SecureStorageService",[r])||await h(r));let n=y.join(t,a.CONSTANTS);if(l(n)){let m=await d(n),f=!1;await e(t,"API_RESPONSE_DATA_KEY",[n])||(m=m.replace(/export const API_RESPONSE_DATA_KEY = .*;\n?/g,""),f=!0),await e(t,"SAVE_AUTH_TOKENS",[n])||(m=m.replace(/export const SAVE_AUTH_TOKENS = .*;\n?/g,""),f=!0),f&&(m=m.replace(/\n\s*\n/g,`
537
-
538
- `).trim()+`
539
- `,await u(n,m))}let i=y.join(t,a.ERRORS_DIR);if(l(i)){let m=await V.readdir(i),f=!1;for(let x of m){let S=y.parse(x).name;if(await o(t,S,[y.join(i,x)])){f=!0;break}}f||await h(i)}let s=y.join(t,a.COMMON_TYPES_DIR);l(s)&&(await V.readdir(s)).length===0&&await h(s);let c=y.join(t,a.UTILITY_TYPES_DIR);l(c)&&(await V.readdir(c)).length===0&&await h(c)};Re();var vt=async t=>{let o=A("Checking HTTP Client setup..."),e=De.join(t,".next-maker-temp-http");try{let{status:r,reason:n}=await rr(t);o.stop();let i=await En(r,n);if(i.type==="cancel"){console.log(Ct.yellow("Setup cancelled."));return}if(o.start("Setting up HTTP client(s)..."),await ir(t),await nr(e,o),i.type==="replace"&&i.fromClient&&(o.text="Migrating client usages...",await Ve(t,i.fromClient,i.clients[0])),i.type!=="remove-both"&&i.type!=="remove-one"){o.text="Copying client files...";let M=i.type==="replace"&&i.fromClient?[i.fromClient]:void 0;await sr(t,e,i.clients,M)}if(i.type==="remove-one"||i.type==="remove-both"){o.text="Removing client files...";let{PROJECT_PATHS:M}=await Promise.resolve().then(()=>(T(),Ot));for(let Te of i.clients){let Ee=De.join(t,Te==="fetch"?M.FETCH_CLIENT:M.AXIOS_CLIENT);await h(Ee)}cr(r,i).length===0&&(o.text="Performing full cleanup...",await ar(t),await qe(t))}let s=cr(r,i);s.length>0&&(o.text="Configuring client...",await Ye(t,s),await ze(t),await We(t),await Be(t)),await ae(t,s),o.text="Managing dependencies...";let c=De.join(t,"package.json"),m=JSON.parse(await Tn.readFile(c,"utf-8")),f={...m.dependencies,...m.devDependencies};s.includes("axios")?f.axios||(o.text="Installing Axios...",await F(t,"axios")):f.axios&&(o.text="Uninstalling Axios...",await Xe(t,"axios"));let x=De.join(t,"src/services/storage");s.length>0||l(x)?f["react-secure-storage"]||(o.text="Installing react-secure-storage...",await F(t,"react-secure-storage")):f["react-secure-storage"]&&(o.text="Uninstalling react-secure-storage...",await Xe(t,"react-secure-storage")),o.text="Formatting code...";let v=await U(t);await D(t,v,"format"),o.succeed(Ct.green(In(i)))}catch(r){throw o.fail("Failed to setup HTTP Client."),r}finally{await h(e)}};async function En(t,o){if(t==="none"){let{choice:r}=await Le.prompt({type:"select",name:"choice",message:"Which HTTP client(s) do you want to setup?",choices:[{name:"fetch",message:"Fetch (Native)"},{name:"axios",message:"Axios"},{name:"both",message:"Both (Fetch + Axios)"}]});return r==="both"?{type:"install",clients:["fetch","axios"]}:{type:"install",clients:[r]}}if(t==="fetch"){let{action:r}=await Le.prompt({type:"select",name:"action",message:`${o}. What would you like to do?`,choices:[{name:"cancel",message:"Keep Fetch only (cancel)"},{name:"add",message:"Add Axios (have both)"},{name:"replace",message:"Replace with Axios only"},{name:"remove",message:"Remove Fetch"}]});if(r==="cancel")return{type:"cancel",clients:[]};if(r==="add")return{type:"add",clients:["axios"]};if(r==="replace")return{type:"replace",clients:["axios"],fromClient:"fetch"};if(r==="remove")return{type:"remove-one",clients:["fetch"]}}if(t==="axios"){let{action:r}=await Le.prompt({type:"select",name:"action",message:`${o}. What would you like to do?`,choices:[{name:"cancel",message:"Keep Axios only (cancel)"},{name:"add",message:"Add Fetch (have both)"},{name:"replace",message:"Replace with Fetch only"},{name:"remove",message:"Remove Axios"}]});if(r==="cancel")return{type:"cancel",clients:[]};if(r==="add")return{type:"add",clients:["fetch"]};if(r==="replace")return{type:"replace",clients:["fetch"],fromClient:"axios"};if(r==="remove")return{type:"remove-one",clients:["axios"]}}console.log(Ct.yellow(`\u2716 ${o}`));let{action:e}=await Le.prompt({type:"select",name:"action",message:"What would you like to do?",choices:[{name:"cancel",message:"Keep both (cancel)"},{name:"remove-fetch",message:"Remove Fetch (keep Axios)"},{name:"remove-axios",message:"Remove Axios (keep Fetch)"},{name:"remove-both",message:"Remove both"}]});return e==="cancel"?{type:"cancel",clients:[]}:e==="remove-fetch"?{type:"remove-one",clients:["fetch"]}:e==="remove-axios"?{type:"remove-one",clients:["axios"]}:e==="remove-both"?{type:"remove-both",clients:["fetch","axios"]}:{type:"cancel",clients:[]}}function cr(t,o){return o.type==="install"?o.clients:o.type==="add"?[...t==="fetch"?["fetch"]:["axios"],...o.clients]:o.type==="replace"?o.clients:o.type==="remove-one"?t==="both"?o.clients[0]==="fetch"?["axios"]:["fetch"]:[]:[]}function In(t){if(t.type==="install")return`HTTP Client (${t.clients.map(e=>e==="fetch"?"Fetch":"Axios").join(" + ")}) setup successfully!`;if(t.type==="add")return`${t.clients[0]==="fetch"?"Fetch":"Axios"} client added successfully! Both clients are now available.`;if(t.type==="replace"){let o=t.fromClient==="fetch"?"Fetch":"Axios",e=t.clients[0]==="fetch"?"Fetch":"Axios";return`Replaced ${o} with ${e} successfully! Imports automatically migrated.`}return t.type==="remove-one"?`${t.clients[0]==="fetch"?"Fetch":"Axios"} client removed successfully!`:t.type==="remove-both"?"Both HTTP clients removed successfully!":"HTTP Client setup completed!"}var{prompt:Rn}=Nn,pr=t=>{t.command("setup").description("Setup features in an existing Next.js project").option("--http-client","Setup HTTP client (axios|fetch)").option("--dark-theme","Setup Dark Theme (Tailwind + next-themes)").option("--redux","Setup Redux Toolkit").option("--i18n","Setup next-intl for internationalization").action(async o=>{try{if(p(He.cyan(`
764
+ `,p=i.indexOf("{",s);i=i.slice(0,p+1)+c+i.slice(p+1)}await u(n,i),await S(t)}};var Ot=async e=>{let r=I("Setting up Internationalization (next-intl)..."),t=At.join(e,".next-maker-temp-i18n");try{let{isSetup:o,reason:n}=await Io(e);if(o){r.fail(`i18n is already set up (${n}).`);return}await Ro(e),await Co(t,r),r.text="Copying i18n files...",await Eo(e,t),r.text="Configuring project structure...",await No(e),await bo(e),await $o(e),await Ao(e),r.text="Migrating to [locale] structure...",await Oo(e),r.text="Installing dependencies...",await H(e,"next-intl");let i=At.join(e,a.VITEST_CONFIG);if(l(i)){let c=JSON.parse(await d(At.join(e,a.PACKAGE_JSON))),p={...c.dependencies,...c.devDependencies},f=!!(p["@reduxjs/toolkit"]&&p["react-redux"]);await ee(e,{redux:f,i18n:!0})}r.text="Formatting code...";let s=await D(e);await G(e,s,"lint:fix"),r.succeed(ms.green("Internationalization setup successfully!"))}catch(o){throw r.fail("Failed to setup Internationalization."),o}finally{await P(t)}};C();import ds from"node:path";import us from"picocolors";T();var _t=async e=>{let r=I("Enabling React Compiler...");try{let t=ds.join(e,a.NEXT_CONFIG);if(!l(t))throw new Error(`${a.NEXT_CONFIG} not found.`);let o=await d(t);if(o.includes("reactCompiler:")){r.fail("React Compiler is already configured in next.config.ts.");return}let n=/(const\s+nextConfig\s*:\s*NextConfig\s*=\s*\{)/;if(!n.test(o))throw new Error("Could not locate `const nextConfig: NextConfig = {` in next.config.ts.");o=o.replace(n,`$1
765
+ reactCompiler: true,`),await u(t,o),r.text="Installing babel-plugin-react-compiler...",await ke(e,"babel-plugin-react-compiler"),r.succeed(us.green("React Compiler enabled."))}catch(t){throw r.fail("Failed to enable React Compiler."),t}};C();import Ft from"node:path";import gs from"picocolors";T();C();T();import _o from"node:fs/promises";import de from"node:path";import fs from"degit";var ko=async(e,r)=>{r.text="Fetching assets from starter repo...",await fs("teispace/nextjs-starter",{cache:!1,force:!0,verbose:!1}).clone(e)},jo=async(e,r)=>{let t=de.join(r,"src/providers/StoreProvider.tsx"),o=de.join(e,a.STORE_PROVIDER);await A(t,o);let n=de.join(r,"src/store"),i=de.join(e,a.STORE);await _o.cp(n,i,{recursive:!0})},Fo=async(e,r)=>{let t=de.join(r,"src/features/counter"),o=de.join(e,a.COUNTER_FEATURE);await _o.cp(t,o,{recursive:!0});let n=de.join(o,"components/Counter.tsx");if(await l(n)){let i=await d(n);i=i.replace(/import \{ useTranslations \} from 'next-intl';\n?/,""),i=i.replace(/const t = useTranslations\('Count'\);\n?/,""),i=i.replace(/\{t\('currentCount', \{ count: value \}\)\}/g,"Current Count: {value}"),i=i.replace(/\{t\('increment'\)\}/g,"Increment"),i=i.replace(/\{t\('decrement'\)\}/g,"Decrement"),i=i.replace(/\{t\('reset'\)\}/g,"Reset"),await u(n,i)}};C();T();import kt from"node:path";var Do=async e=>{let r=kt.join(e,a.STORE),t=kt.join(e,"package.json");if(l(r))return{isSetup:!0,reason:"src/store directory exists"};if(l(t)){let o=JSON.parse(await d(t));if(o.dependencies?.["@reduxjs/toolkit"]||o.devDependencies?.["@reduxjs/toolkit"])return{isSetup:!0,reason:"@reduxjs/toolkit is installed"}}return{isSetup:!1,reason:""}},Lo=async e=>{let r=kt.join(e,a.PROVIDERS_INDEX);if(!await Ue(e)||!l(r))throw new Error("Project structure mismatch. Ensure src/app/layout.tsx (or src/app/[locale]/layout.tsx) and src/providers/index.ts exist.")};C();T();import jt from"node:path";var Go=async e=>{},Ho=async e=>{let r=jt.join(e,"src/providers/RootProvider.tsx");if(!l(r))return;let t=await d(r),o="'use client';",n=t.includes(o);if(n&&(t=t.replace(o,"").trim()),t.includes("from '@/store'")||(t=`import type { AppState } from '@/store';
766
+ ${t}`),t.includes("from './StoreProvider'")||(t=`${t.includes("from '@/store'"),""}import { StoreProvider } from './StoreProvider';
767
+ ${t}`),n&&(t=`${o}
768
+ ${t}`),t.includes("preloadedState")||(t=t.replace(/children:\s*React\.ReactNode;/,`children: React.ReactNode;
769
+ preloadedState?: Partial<AppState>;`),t=t.replace(/export const RootProvider = \(\{([\s\S]*?)\}:/,(i,s)=>`export const RootProvider = ({${s}, preloadedState }:`),t=t.replace(/,\s*,/g,",").replace(/\{\s*,/g,"{ ").replace(/,\s*\}/g," }")),!t.includes("<StoreProvider")){let i=t.match(/return\s*\(\s*([\s\S]*?)\s*\);/);if(i){let s=i[1];t=t.replace(i[0],`return (
770
+ <StoreProvider preloadedState={preloadedState}>
771
+ ${s}
772
+ </StoreProvider>
773
+ );`)}}await u(r,t)},Uo=async e=>{let r=[jt.join(e,a.ROOT_PAGE),jt.join(e,"src/app/[locale]/page.tsx")],t="";for(let n of r)if(l(n)){t=n;break}if(!t)return;let o=await d(t);if(o.includes("Counter")||(o=`import { Counter } from '@/features/counter';
774
+ ${o}`),!o.includes("<Counter />")){let n=o.lastIndexOf("</div>"),i=o.lastIndexOf("</main>"),s=i!==-1?i:n;s!==-1&&(o=o.slice(0,s)+`
775
+ <div className="mt-8">
776
+ <h2 className="mb-4 text-2xl font-bold">Redux Counter</h2>
777
+ <Counter />
778
+ </div>
779
+ `+o.slice(s),await u(t,o))}};var Dt=async e=>{let r=I("Setting up Redux Toolkit..."),t=Ft.join(e,".next-maker-temp-redux");try{let{isSetup:o,reason:n}=await Do(e);if(o){r.fail(`Redux is already set up (${n}).`);return}await Lo(e),await ko(t,r),r.text="Copying Redux files...",await jo(e,t),r.text="Creating Counter feature...",await Fo(e,t),r.text="Updating providers and pages...",await Go(e),await Ho(e),await Uo(e),r.text="Installing dependencies...",await H(e,"@reduxjs/toolkit"),await H(e,"react-redux"),await H(e,"redux-persist"),await H(e,"react-secure-storage");let i=Ft.join(e,a.VITEST_CONFIG);if(l(i)){let c=JSON.parse(await d(Ft.join(e,a.PACKAGE_JSON))),p={...c.dependencies,...c.devDependencies};await ee(e,{redux:!0,i18n:!!p["next-intl"]})}r.text="Formatting code...";let s=await D(e);await G(e,s,"lint:fix"),r.succeed(gs.green("Redux Toolkit setup successfully!"))}catch(o){throw r.fail("Failed to setup Redux Toolkit."),o}finally{await P(t)}};C();import hs from"node:fs/promises";import ne from"node:path";import xs from"degit";import ys from"picocolors";T();var Ps=["vitest","jsdom","@vitejs/plugin-react","@testing-library/dom","@testing-library/jest-dom","@testing-library/react","@testing-library/user-event"],Lt=async e=>{let r=I("Setting up testing (Vitest + RTL)..."),t=ne.join(e,".next-maker-temp-tests");try{let o=ne.join(e,a.VITEST_CONFIG);if(l(o)){r.fail("Testing is already set up (vitest.config.ts exists).");return}r.text="Fetching assets from starter repo...",await xs("teispace/nextjs-starter",{cache:!1,force:!0,verbose:!1}).clone(t),await A(ne.join(t,a.VITEST_CONFIG),ne.join(e,a.VITEST_CONFIG));let i=ne.join(e,a.TEST_DIR);await hs.mkdir(i,{recursive:!0}),await A(ne.join(t,a.TEST_DIR,"setup.ts"),ne.join(i,"setup.ts"));let s=ne.join(e,a.PACKAGE_JSON),c=JSON.parse(await d(s)),p={...c.dependencies,...c.devDependencies},f=!!(p["@reduxjs/toolkit"]&&p["react-redux"]),g=!!p["next-intl"];await ee(e,{redux:f,i18n:g}),await j(s,x=>(x.scripts=x.scripts??{},x.scripts.test=x.scripts.test??"vitest run",x.scripts["test:watch"]=x.scripts["test:watch"]??"vitest",x.scripts["test:coverage"]=x.scripts["test:coverage"]??"vitest run --coverage",typeof x.scripts.validate=="string"&&!/\byarn\s+test(?![:\w])/.test(x.scripts.validate)&&(x.scripts.validate=x.scripts.validate.replace(/(\byarn\s+check:deprecated\s*)(&&)/,"$1&& yarn test $2")),x)),r.text="Installing testing devDependencies...";let y=await D(e);await Ke(e,y,Ps),r.text="Formatting code...",await G(e,y,"lint:fix"),r.succeed(ys.green("Testing setup complete."))}catch(o){throw r.fail("Failed to set up testing."),o}finally{await P(t)}};var{prompt:Ss}=Ts,Mo=e=>{e.command("setup").description("Setup features in an existing Next.js project").option("--http-client","Setup HTTP client (axios|fetch)").option("--dark-theme","Setup Dark Theme (Tailwind + @teispace/next-themes)").option("--redux","Setup Redux Toolkit").option("--i18n","Setup next-intl for internationalization").option("--tests","Setup testing (Vitest + React Testing Library)").option("--react-compiler","Enable the React Compiler").option("--bundle-analyzer","Add @next/bundle-analyzer").action(async r=>{try{if(m(Gt.cyan(`
540
780
  \u{1F527} Setup Wizard
541
- `)),o.httpClient||o.darkTheme||o.redux||o.i18n){o.httpClient&&await vt(process.cwd()),o.darkTheme&&await yt(process.cwd()),o.redux&&await wt(process.cwd()),o.i18n&&await St(process.cwd());return}let r=(await Rn([{type:"select",name:"feature",message:"What would you like to setup?",choices:[{name:"Dark Theme",value:"dark-theme"},{name:"Redux Toolkit",value:"redux"},{name:"HTTP Client (Axios/Fetch)",value:"http-client"},{name:"Internationalization (next-intl)",value:"i18n"},"Cancel"]}])).feature;if(r==="Cancel"){p(He.yellow("Setup cancelled."));return}r==="dark-theme"?await yt(process.cwd()):r==="redux"?await wt(process.cwd()):r==="http-client"?await vt(process.cwd()):r==="i18n"?await St(process.cwd()):(p(He.yellow(`
542
- \u26A0\uFE0F ${r} setup is not implemented yet.`)),p(He.dim("This feature will be available in a future update.")))}catch(e){g.fail("Setup failed"),C(`${e}`),process.exit(1)}})};import G from"picocolors";import lr from"node:path";import $n from"enquirer";var{prompt:An}=$n,mr=async t=>{let o=[];t||o.push({type:"input",name:"pageName",message:"Page name (kebab-case):",validate:r=>r?/^[a-z][a-z0-9-]*$/.test(r)?!0:"Use lowercase letters, numbers, and hyphens only":"Page name is required"}),o.push({type:"confirm",name:"withLoading",message:"Generate loading.tsx?",initial:!0},{type:"confirm",name:"withError",message:"Generate error.tsx?",initial:!0});let e=await An(o);return{pageName:t||e.pageName,withLoading:e.withLoading,withError:e.withError}};W();var dr=t=>{t.command("page [name]").description("Generate a new page/route").option("--dynamic <param>","Create dynamic route with parameter (e.g., id)").option("--loading","Generate loading.tsx").option("--error","Generate error.tsx").action(async(o,e)=>{try{let r=process.cwd();p(G.cyan(`
543
- \u{1F4C4} Page Generator
544
- `)),g.start("Detecting project setup...");let n=await _(r);g.succeed("Project setup detected"),p(G.dim(` i18n: ${n.hasI18n?"\u2713":"\u2717"}
545
- `));let i=await mr(o),s=i.pageName,c=N(s),m=n.hasI18n?"src/app/[locale]":"src/app";await Q(r,s,m)&&(C(`Page '${s}' already exists at ${m}/${s}!`),process.exit(1)),g.start("Generating page files..."),await rt({name:s,projectPath:r,hasI18n:n.hasI18n,dynamic:e.dynamic,withLoading:e.loading??i.withLoading,withError:e.error??i.withError}),g.succeed("Page files generated"),g.start("Registering route...");let x=e.dynamic?`/${s}/[${e.dynamic}]`:`/${s}`;await dt(r,s,x),g.succeed("Route registered"),n.hasI18n&&(g.start("Adding translation namespace..."),await ut(r,c),g.succeed("Translation namespace added"));let S=e.dynamic?lr.join(m,s,`[${e.dynamic}]`):lr.join(m,s);p(G.green(`
546
- \u2728 Page '${s}' created successfully!
547
- `)),p(G.dim("Generated files:")),p(G.dim(` \u{1F4C2} ${S}/`)),p(G.dim(" \u251C\u2500\u2500 page.tsx")),(e.loading??i.withLoading)&&p(G.dim(" \u251C\u2500\u2500 loading.tsx")),(e.error??i.withError)&&p(G.dim(" \u2514\u2500\u2500 error.tsx")),p(""),n.hasI18n&&(p(G.cyan("Next steps:")),p(G.dim(` 1. Add translations in: src/i18n/translations/en.json \u2192 "${c}"`)),p(G.dim(` 2. Visit: http://localhost:3000/${s}`)),p(""))}catch(r){g.fail("Page generation failed"),C(`${r}`),process.exit(1)}})};import q from"picocolors";import bn from"enquirer";var{prompt:On}=bn,ur=async t=>{let o=[];t||o.push({type:"input",name:"componentName",message:"Component name (kebab-case):",validate:r=>r?/^[a-z][a-z0-9-]*$/.test(r)?!0:"Use lowercase letters, numbers, and hyphens only":"Component name is required"}),o.push({type:"confirm",name:"isClient",message:"Add 'use client' directive?",initial:!1});let e=await On(o);return{componentName:t||e.componentName,isClient:e.isClient}};W();var fr=t=>{t.command("component [name]").description("Generate a shared component").option("--client","Add 'use client' directive").option("--i18n","Add useTranslations hook").option("--feature <path>","Generate in feature directory (e.g., src/features/auth)").action(async(o,e)=>{try{let r=process.cwd();p(q.cyan(`
548
- \u{1F9E9} Component Generator
549
- `)),g.start("Detecting project setup..."),await _(r),g.succeed("Project setup detected");let n=await ur(o),i=N(n.componentName),s=e.client??n.isClient,c=e.i18n??!1;g.start("Generating component..."),await st({name:n.componentName,projectPath:r,isClient:s||c,hasI18n:c,featurePath:e.feature}),g.succeed("Component generated");let m=e.feature?`${e.feature}/components/${i}.tsx`:`src/components/common/${i}/${i}.tsx`;p(q.green(`
550
- \u2728 Component '${i}' created successfully!
551
- `)),p(q.dim(` \u{1F4C4} ${m}`)),e.feature||(p(q.dim(` \u{1F4C4} src/components/common/${i}/index.ts`)),p(q.dim(" \u{1F4DD} Updated src/components/common/index.ts")),p(q.dim(" \u{1F4DD} Updated src/components/index.ts"))),p(""),p(q.cyan("Usage:")),e.feature?p(q.dim(` import { ${i} } from '${e.feature.replace(/^src\//,"@/")}/components/${i}';`)):p(q.dim(` import { ${i} } from '@/components';`)),p("")}catch(r){g.fail("Component generation failed"),C(`${r}`),process.exit(1)}})};import Y from"picocolors";import kn from"enquirer";var{prompt:_n}=kn,gr=async t=>{let o=[];t||o.push({type:"input",name:"code",message:"Locale code (e.g., es, fr, de):",validate:r=>r?/^[a-z]{2}(-[A-Z]{2})?$/.test(r)?!0:"Use format: xx or xx-XX (e.g., es, pt-BR)":"Locale code is required"}),o.push({type:"input",name:"name",message:"Language name (e.g., Spanish, French):",validate:r=>r?!0:"Language name is required"},{type:"input",name:"country",message:"Country (e.g., Spain, France):",validate:r=>r?!0:"Country is required"},{type:"input",name:"flag",message:"Flag emoji (e.g., \u{1F1EA}\u{1F1F8}, \u{1F1EB}\u{1F1F7}):",validate:r=>r?!0:"Flag emoji is required"},{type:"confirm",name:"copyTranslations",message:"Copy translations from English? (No = empty values)",initial:!1});let e=await _n(o);return{code:t||e.code,name:e.name,country:e.country,flag:e.flag,copyTranslations:e.copyTranslations}};W();P();import jn from"node:path";var hr=t=>{t.command("locale [code]").description("Add a new locale/language").option("--copy-translations","Copy translations from English instead of empty values").action(async(o,e)=>{try{let r=process.cwd();p(Y.cyan(`
552
- \u{1F30D} Locale Generator
553
- `)),g.start("Detecting project setup...");let n=await _(r);g.succeed("Project setup detected"),n.hasI18n||(g.fail("i18n is not set up in this project"),C("Please set up internationalization first"),p(Y.dim(`
554
- Run: npx @teispace/next-maker setup --i18n
555
- `)),process.exit(1));let i=await gr(o),s=jn.join(r,"src","i18n","translations",`${i.code}.json`);l(s)&&(C(`Locale '${i.code}' already exists!`),process.exit(1)),g.start("Adding locale..."),await at({...i,projectPath:r,copyTranslations:e.copyTranslations??i.copyTranslations}),g.succeed("Locale added"),p(Y.green(`
556
- \u2728 Locale '${i.code}' (${i.name}) added successfully!
557
- `)),p(Y.dim("Updated files:")),p(Y.dim(` \u{1F4C4} src/i18n/translations/${i.code}.json`)),p(Y.dim(" \u{1F4DD} src/types/i18n.ts (SupportedLocale type)")),p(Y.dim(" \u{1F4DD} src/lib/config/app-locales.ts")),p(""),p(Y.cyan("Next steps:")),p(Y.dim(` 1. Translate: src/i18n/translations/${i.code}.json`)),p(Y.dim(` 2. Visit: http://localhost:3000/${i.code}`)),p("")}catch(r){g.fail("Locale generation failed"),C(`${r}`),process.exit(1)}})};import ve from"picocolors";import Fn from"enquirer";var{prompt:Dn}=Fn,xr=async t=>t?{hookName:t}:await Dn({type:"input",name:"hookName",message:'Hook name (kebab-case, without "use" prefix):',validate:e=>e?/^[a-z][a-z0-9-]*$/.test(e)?!0:"Use lowercase letters, numbers, and hyphens only":"Hook name is required"});var yr=t=>{t.command("hook [name]").description("Generate a custom React hook").option("--client","Add 'use client' directive (default: true)",!0).option("--feature <path>","Generate in feature directory (e.g., src/features/auth)").action(async(o,e)=>{try{let r=process.cwd();p(ve.cyan(`
558
- \u{1FA9D} Hook Generator
559
- `));let n=await xr(o),s=`use${N(n.hookName)}`;g.start("Generating hook..."),await pt({name:n.hookName,projectPath:r,isClient:e.client??!0,featurePath:e.feature}),g.succeed("Hook generated");let c=e.feature?`${e.feature}/hooks/${s}.ts`:`src/hooks/${s}.ts`;p(ve.green(`
560
- \u2728 Hook '${s}' created successfully!
561
- `)),p(ve.dim(` \u{1F4C4} ${c}`)),p(""),p(ve.cyan("Usage:"));let m=e.feature?`${e.feature.replace(/^src\//,"@/")}/hooks/${s}`:`@/hooks/${s}`;p(ve.dim(` import { ${s} } from '${m}';`)),p("")}catch(r){g.fail("Hook generation failed"),C(`${r}`),process.exit(1)}})};var Pr=t=>{Vt(t),pr(t),Co(t),To(t),Ro(t),dr(t),fr(t),hr(t),yr(t)};var Hn=process.emitWarning;process.emitWarning=function(t,o,e,r){if(!(typeof t=="string"&&t.includes("--localstorage-file")&&t.includes("was provided without a valid path")))return Hn.apply(process,arguments)};async function Gn(){At({logger:o=>Ne(o)});let t=new Ln;t.name("next-maker").description("Teispace Next.js Project Generator").version("1.0.0"),Pr(t),t.parse()}Gn().catch(t=>{let o=t&&typeof t=="object"&&"message"in t?t.message:String(t);Ne(`Unexpected error: ${o}`)});
781
+ `)),r.httpClient||r.darkTheme||r.redux||r.i18n||r.tests||r.reactCompiler||r.bundleAnalyzer){r.httpClient&&await $t(process.cwd()),r.darkTheme&&await Nt(process.cwd()),r.redux&&await Dt(process.cwd()),r.i18n&&await Ot(process.cwd()),r.tests&&await Lt(process.cwd()),r.reactCompiler&&await _t(process.cwd()),r.bundleAnalyzer&&await Rt(process.cwd());return}let n=(await Ss([{type:"select",name:"feature",message:"What would you like to setup?",choices:[{name:"Dark Theme",value:"dark-theme"},{name:"Redux Toolkit",value:"redux"},{name:"HTTP Client (Axios/Fetch)",value:"http-client"},{name:"Internationalization (next-intl)",value:"i18n"},{name:"Testing (Vitest + RTL)",value:"tests"},{name:"React Compiler",value:"react-compiler"},{name:"Bundle Analyzer",value:"bundle-analyzer"},"Cancel"]}])).feature;if(n==="Cancel"){m(Gt.yellow("Setup cancelled."));return}let s={"dark-theme":Nt,redux:Dt,"http-client":$t,i18n:Ot,tests:Lt,"react-compiler":_t,"bundle-analyzer":Rt}[n];s?await s(process.cwd()):m(Gt.yellow(`
782
+ \u26A0\uFE0F ${n} setup is not implemented yet.`))}catch(t){h.fail("Setup failed"),w(`${t}`),process.exit(1)}})};import{existsSync as Cs}from"node:fs";import{mkdir as Es}from"node:fs/promises";import se from"node:path";import F from"picocolors";U();import ws from"enquirer";var{prompt:vs}=ws,Jo=async(e,r,t)=>{let o=[];e||o.push({type:"input",name:"sliceName",message:"What is the slice name?",initial:"my-slice",validate:i=>/^[a-z0-9-]+$/.test(i)?!0:"Slice name must be lowercase and contain only alphanumeric characters and hyphens."}),r===void 0&&t===void 0&&o.push({type:"confirm",name:"persistSlice",message:"Enable persistence for this slice?",initial:!1});let n=o.length>0?await vs(o):{};return{sliceName:e||n.sliceName,persistSlice:r===!0?!0:t===!1?!1:n.persistSlice||!1}};var zo=e=>{e.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").option("--test","Also generate a sibling test file").option("--no-test","Skip test file generation").action(async(r,t)=>{try{let o=process.cwd();t.persist&&t.noPersist===!0&&(w("Cannot use --persist and --no-persist together"),process.exit(1)),m(F.cyan(`
783
+ \u{1F527} Slice Generator
784
+ `)),h.start("Detecting project setup...");let n=await O(o);h.succeed("Project setup detected"),n.hasRedux||(h.fail("Redux is not setup in this project"),w("Please install @reduxjs/toolkit and react-redux first"),m(F.dim(`
785
+ Run: npm install @reduxjs/toolkit react-redux
786
+ `)),process.exit(1)),m(F.dim(` Redux: \u2713
787
+ `));let i=await Jo(r,t.persist,t.noPersist===!0?!1:void 0),{basePath:s,slicePath:c}=Is(o,i.sliceName,t.path),p=se.join(o,s);Cs(p)||await Es(p,{recursive:!0}),await oe(o,i.sliceName,s)&&(w(`Slice '${i.sliceName}' already exists at ${s}!`),process.exit(1)),await me(Ct(),{projectPath:o,spinner:h,sliceName:i.sliceName,basePath:s,slicePath:c,persistSlice:i.persistSlice});let g=null;if(Rs(t,n.hasTests)){let x=se.join(c,`${i.sliceName}.slice.ts`);h.start("Generating test..."),g=await q({projectPath:o,sourceFile:x,kind:"slice",symbolName:$(i.sliceName)}),h.succeed("Test generated")}Ns(i,s,g,o)}catch(o){h.fail("Slice generation failed"),w(`${o}`),process.exit(1)}})},Is=(e,r,t)=>{let o;if(t){let n=t.replace(/^src\//,"");if(n.startsWith("features/")){let i=n.split("/")[1];o=se.join("src","features",i,"store")}else o=se.join("src",n)}else o=se.join("src","features",r,"store");return{basePath:o,slicePath:se.join(e,o,r)}},Rs=(e,r)=>e.noTest?!1:e.test?!0:r,Ns=(e,r,t,o)=>{let n=se.join(r,e.sliceName);m(F.green(`
788
+ \u2728 Slice '${e.sliceName}' created successfully!
789
+ `)),m(F.dim("Generated files:")),m(F.dim(` \u{1F4C2} ${n}/`)),m(F.dim(` \u251C\u2500\u2500 ${e.sliceName}.slice.ts`)),m(F.dim(` \u251C\u2500\u2500 ${e.sliceName}.selectors.ts`)),e.persistSlice&&m(F.dim(" \u251C\u2500\u2500 persist.ts")),m(F.dim(` \u251C\u2500\u2500 ${e.sliceName}.types.ts`)),m(F.dim(` \u2514\u2500\u2500 index.ts
790
+ `)),t&&m(F.dim(` \u{1F9EA} ${se.relative(o,t)}
791
+ `)),m(F.cyan("Next steps:"));let i=r.replace(/^src\//,"@/");m(F.dim(` 1. Import actions: import { setLoading, setError } from '${i}/${e.sliceName}'`)),m(F.dim(" 2. Use in component: dispatch(setLoading(true))")),m("")};import B from"node:path";import Ht from"picocolors";T();U();var Bo=e=>{e.command("test <file>").description(`Generate a sibling test file for an existing component, hook, or slice.
792
+ Infers the kind from filename/content; pass --kind to override.`).option("--kind <kind>","Override inferred kind: component | hook | slice").option("--force","Overwrite an existing test file").action(async(r,t)=>{try{let o=process.cwd(),n=B.isAbsolute(r)?r:B.join(o,r);m(Ht.cyan(`
793
+ \u{1F9EA} Test Generator
794
+ `)),l(n)||(w(`Source file not found: ${r}`),process.exit(1));let i=await O(o);i.hasTests||(w("Testing is not installed in this project. Run `next-maker setup --tests` first."),process.exit(1));let s=await d(n),c=bs(t.kind)??$s(n,s);c||(w(`Could not infer test kind for ${B.basename(n)}. Pass --kind component|hook|slice.`),process.exit(1));let p=As(n,c),f=Os(n,c);l(f)&&!t.force&&(w(`Test file already exists: ${B.relative(o,f)}. Use --force to overwrite.`),process.exit(1)),h.start(`Generating ${c} test...`);let g=await q({projectPath:o,sourceFile:n,kind:c,symbolName:p,hasRedux:i.hasRedux,hasI18n:i.hasI18n,hookUsesStore:c==="hook"&&i.hasRedux&&s.includes("useAppSelector")});h.succeed("Test generated"),m(Ht.green(`
795
+ \u2728 Test '${B.basename(g)}' created.
796
+ `)),m(Ht.dim(` \u{1F9EA} ${B.relative(o,g)}`)),m("")}catch(o){h.fail("Test generation failed"),w(`${o}`),process.exit(1)}})},bs=e=>{if(!e)return null;if(e==="component"||e==="hook"||e==="slice")return e;throw new Error(`Invalid --kind: ${e}. Use component | hook | slice.`)},$s=(e,r)=>{let t=B.basename(e);return/\.slice\.ts$/.test(t)?"slice":/^use[A-Z]/.test(t.replace(/\.tsx?$/,""))?"hook":t.endsWith(".tsx")?"component":/createSlice\s*\(/.test(r)?"slice":/^export\s+(const|function)\s+use[A-Z]/m.test(r)?"hook":null},As=(e,r)=>{let t=B.basename(e).replace(/\.(tsx?|jsx?)$/i,"");return r==="slice"?$(t.replace(/\.slice$/,"")):r==="hook"?/^use[A-Z]/.test(t)?t:`use${R(t.replace(/^use-?/,""))}`:R(t)},Os=(e,r)=>{let t=B.dirname(e),o=B.basename(e).replace(/\.(tsx?|jsx?)$/i,""),n=r==="component"?".tsx":".ts";return B.join(t,`${o}.test${n}`)};var Xo=e=>{yr(e),Mo(e),Vr(e),zo(e),no(e),to(e),Xr(e),Zr(e),Wr(e),Bo(e)};var ks=process.emitWarning;process.emitWarning=function(e,r,t,o){if(!(typeof e=="string"&&e.includes("--localstorage-file")&&e.includes("was provided without a valid path")))return ks.apply(process,arguments)};async function js(){Mt({logger:r=>_e(r)});let e=new _s;e.name("next-maker").description("Teispace Next.js Project Generator").version("1.0.0"),Xo(e),e.parse()}js().catch(e=>{let r=e&&typeof e=="object"&&"message"in e?e.message:String(e);_e(`Unexpected error: ${r}`)});
562
797
  //# sourceMappingURL=index.js.map